diff --git a/page/src/App.tsx b/page/src/App.tsx
index 2a12e2fd..82a7561b 100644
--- a/page/src/App.tsx
+++ b/page/src/App.tsx
@@ -3,12 +3,13 @@ import { TooltipProvider } from "@/components/ui/tooltip";
import { HashRouter, Route, Routes, Navigate } from "react-router-dom";
import { Playground, storeEmulateData } from "./playground";
import { LandingPage } from "./landing-page";
-
+import { useEffect, useState } from "react";
import { useParams } from "react-router-dom";
import "@fontsource/inter/latin.css";
import "./App.css";
+import "./animation.css";
function EmulateFile() {
const { encodedData } = useParams();
@@ -16,6 +17,38 @@ function EmulateFile() {
return ;
}
+function isWindowLoading() {
+ return !!(window as any).loading;
+}
+
+function useLoader() {
+ const [isLoading, setIsLoading] = useState(isWindowLoading());
+
+ useEffect(() => {
+ const id = setInterval(() => {
+ setIsLoading(isWindowLoading());
+ }, 60);
+
+ return () => {
+ clearInterval(id);
+ };
+ });
+
+ return isLoading;
+}
+
+function Loader() {
+ const loading = useLoader();
+
+ if (!loading) {
+ return <>>;
+ }
+
+ return (
+
+ );
+}
+
function App() {
return (
@@ -28,6 +61,7 @@ function App() {
} />
+
);
diff --git a/page/src/animation.css b/page/src/animation.css
new file mode 100644
index 00000000..204d33b0
--- /dev/null
+++ b/page/src/animation.css
@@ -0,0 +1,311 @@
+:root {
+ --ring-full-color: #ffffff00;
+ --ring-half-color: #ffffff75;
+}
+
+/**
+ * Ring of dots
+ *
+ * @author jh3y
+*/
+@-webkit-keyframes ring-of-dots {
+ 0% {
+ -webkit-box-shadow:
+ 20px 0px 0 0 white,
+ 12.4698px 15.63663px 0 0 white,
+ -4.45042px 19.49856px 0 0 white,
+ -18.01938px 8.67767px 0 0 white,
+ -18.01938px -8.67767px 0 0 white,
+ -4.45042px -19.49856px 0 0 var(--ring-half-color),
+ 12.4698px -15.63663px 0 0 var(--ring-full-color);
+ box-shadow:
+ 20px 0px 0 0 white,
+ 12.4698px 15.63663px 0 0 white,
+ -4.45042px 19.49856px 0 0 white,
+ -18.01938px 8.67767px 0 0 white,
+ -18.01938px -8.67767px 0 0 white,
+ -4.45042px -19.49856px 0 0 var(--ring-half-color),
+ 12.4698px -15.63663px 0 0 var(--ring-full-color);
+ }
+ 14.28571% {
+ -webkit-box-shadow:
+ 20px 0px 0 0 white,
+ 12.4698px 15.63663px 0 0 white,
+ -4.45042px 19.49856px 0 0 white,
+ -18.01938px 8.67767px 0 0 white,
+ -18.01938px -8.67767px 0 0 var(--ring-half-color),
+ -4.45042px -19.49856px 0 0 var(--ring-full-color),
+ 12.4698px -15.63663px 0 0 white;
+ box-shadow:
+ 20px 0px 0 0 white,
+ 12.4698px 15.63663px 0 0 white,
+ -4.45042px 19.49856px 0 0 white,
+ -18.01938px 8.67767px 0 0 white,
+ -18.01938px -8.67767px 0 0 var(--ring-half-color),
+ -4.45042px -19.49856px 0 0 var(--ring-full-color),
+ 12.4698px -15.63663px 0 0 white;
+ }
+ 28.57143% {
+ -webkit-box-shadow:
+ 20px 0px 0 0 white,
+ 12.4698px 15.63663px 0 0 white,
+ -4.45042px 19.49856px 0 0 white,
+ -18.01938px 8.67767px 0 0 var(--ring-half-color),
+ -18.01938px -8.67767px 0 0 var(--ring-full-color),
+ -4.45042px -19.49856px 0 0 white,
+ 12.4698px -15.63663px 0 0 white;
+ box-shadow:
+ 20px 0px 0 0 white,
+ 12.4698px 15.63663px 0 0 white,
+ -4.45042px 19.49856px 0 0 white,
+ -18.01938px 8.67767px 0 0 var(--ring-half-color),
+ -18.01938px -8.67767px 0 0 var(--ring-full-color),
+ -4.45042px -19.49856px 0 0 white,
+ 12.4698px -15.63663px 0 0 white;
+ }
+ 42.85714% {
+ -webkit-box-shadow:
+ 20px 0px 0 0 white,
+ 12.4698px 15.63663px 0 0 white,
+ -4.45042px 19.49856px 0 0 var(--ring-half-color),
+ -18.01938px 8.67767px 0 0 var(--ring-full-color),
+ -18.01938px -8.67767px 0 0 white,
+ -4.45042px -19.49856px 0 0 white,
+ 12.4698px -15.63663px 0 0 white;
+ box-shadow:
+ 20px 0px 0 0 white,
+ 12.4698px 15.63663px 0 0 white,
+ -4.45042px 19.49856px 0 0 var(--ring-half-color),
+ -18.01938px 8.67767px 0 0 var(--ring-full-color),
+ -18.01938px -8.67767px 0 0 white,
+ -4.45042px -19.49856px 0 0 white,
+ 12.4698px -15.63663px 0 0 white;
+ }
+ 57.14286% {
+ -webkit-box-shadow:
+ 20px 0px 0 0 white,
+ 12.4698px 15.63663px 0 0 var(--ring-half-color),
+ -4.45042px 19.49856px 0 0 var(--ring-full-color),
+ -18.01938px 8.67767px 0 0 white,
+ -18.01938px -8.67767px 0 0 white,
+ -4.45042px -19.49856px 0 0 white,
+ 12.4698px -15.63663px 0 0 white;
+ box-shadow:
+ 20px 0px 0 0 white,
+ 12.4698px 15.63663px 0 0 var(--ring-half-color),
+ -4.45042px 19.49856px 0 0 var(--ring-full-color),
+ -18.01938px 8.67767px 0 0 white,
+ -18.01938px -8.67767px 0 0 white,
+ -4.45042px -19.49856px 0 0 white,
+ 12.4698px -15.63663px 0 0 white;
+ }
+ 71.42857% {
+ -webkit-box-shadow:
+ 20px 0px 0 0 var(--ring-half-color),
+ 12.4698px 15.63663px 0 0 var(--ring-full-color),
+ -4.45042px 19.49856px 0 0 white,
+ -18.01938px 8.67767px 0 0 white,
+ -18.01938px -8.67767px 0 0 white,
+ -4.45042px -19.49856px 0 0 white,
+ 12.4698px -15.63663px 0 0 white;
+ box-shadow:
+ 20px 0px 0 0 var(--ring-half-color),
+ 12.4698px 15.63663px 0 0 var(--ring-full-color),
+ -4.45042px 19.49856px 0 0 white,
+ -18.01938px 8.67767px 0 0 white,
+ -18.01938px -8.67767px 0 0 white,
+ -4.45042px -19.49856px 0 0 white,
+ 12.4698px -15.63663px 0 0 white;
+ }
+ 85.71429% {
+ -webkit-box-shadow:
+ 20px 0px 0 0 var(--ring-full-color),
+ 12.4698px 15.63663px 0 0 white,
+ -4.45042px 19.49856px 0 0 white,
+ -18.01938px 8.67767px 0 0 white,
+ -18.01938px -8.67767px 0 0 white,
+ -4.45042px -19.49856px 0 0 white,
+ 12.4698px -15.63663px 0 0 var(--ring-half-color);
+ box-shadow:
+ 20px 0px 0 0 var(--ring-full-color),
+ 12.4698px 15.63663px 0 0 white,
+ -4.45042px 19.49856px 0 0 white,
+ -18.01938px 8.67767px 0 0 white,
+ -18.01938px -8.67767px 0 0 white,
+ -4.45042px -19.49856px 0 0 white,
+ 12.4698px -15.63663px 0 0 var(--ring-half-color);
+ }
+ 100% {
+ -webkit-box-shadow:
+ 20px 0px 0 0 white,
+ 12.4698px 15.63663px 0 0 white,
+ -4.45042px 19.49856px 0 0 white,
+ -18.01938px 8.67767px 0 0 white,
+ -18.01938px -8.67767px 0 0 white,
+ -4.45042px -19.49856px 0 0 var(--ring-half-color),
+ 12.4698px -15.63663px 0 0 var(--ring-full-color);
+ box-shadow:
+ 20px 0px 0 0 white,
+ 12.4698px 15.63663px 0 0 white,
+ -4.45042px 19.49856px 0 0 white,
+ -18.01938px 8.67767px 0 0 white,
+ -18.01938px -8.67767px 0 0 white,
+ -4.45042px -19.49856px 0 0 var(--ring-half-color),
+ 12.4698px -15.63663px 0 0 var(--ring-full-color);
+ }
+}
+@keyframes ring-of-dots {
+ 0% {
+ -webkit-box-shadow:
+ 20px 0px 0 0 white,
+ 12.4698px 15.63663px 0 0 white,
+ -4.45042px 19.49856px 0 0 white,
+ -18.01938px 8.67767px 0 0 white,
+ -18.01938px -8.67767px 0 0 white,
+ -4.45042px -19.49856px 0 0 var(--ring-half-color),
+ 12.4698px -15.63663px 0 0 var(--ring-full-color);
+ box-shadow:
+ 20px 0px 0 0 white,
+ 12.4698px 15.63663px 0 0 white,
+ -4.45042px 19.49856px 0 0 white,
+ -18.01938px 8.67767px 0 0 white,
+ -18.01938px -8.67767px 0 0 white,
+ -4.45042px -19.49856px 0 0 var(--ring-half-color),
+ 12.4698px -15.63663px 0 0 var(--ring-full-color);
+ }
+ 14.28571% {
+ -webkit-box-shadow:
+ 20px 0px 0 0 white,
+ 12.4698px 15.63663px 0 0 white,
+ -4.45042px 19.49856px 0 0 white,
+ -18.01938px 8.67767px 0 0 white,
+ -18.01938px -8.67767px 0 0 var(--ring-half-color),
+ -4.45042px -19.49856px 0 0 var(--ring-full-color),
+ 12.4698px -15.63663px 0 0 white;
+ box-shadow:
+ 20px 0px 0 0 white,
+ 12.4698px 15.63663px 0 0 white,
+ -4.45042px 19.49856px 0 0 white,
+ -18.01938px 8.67767px 0 0 white,
+ -18.01938px -8.67767px 0 0 var(--ring-half-color),
+ -4.45042px -19.49856px 0 0 var(--ring-full-color),
+ 12.4698px -15.63663px 0 0 white;
+ }
+ 28.57143% {
+ -webkit-box-shadow:
+ 20px 0px 0 0 white,
+ 12.4698px 15.63663px 0 0 white,
+ -4.45042px 19.49856px 0 0 white,
+ -18.01938px 8.67767px 0 0 var(--ring-half-color),
+ -18.01938px -8.67767px 0 0 var(--ring-full-color),
+ -4.45042px -19.49856px 0 0 white,
+ 12.4698px -15.63663px 0 0 white;
+ box-shadow:
+ 20px 0px 0 0 white,
+ 12.4698px 15.63663px 0 0 white,
+ -4.45042px 19.49856px 0 0 white,
+ -18.01938px 8.67767px 0 0 var(--ring-half-color),
+ -18.01938px -8.67767px 0 0 var(--ring-full-color),
+ -4.45042px -19.49856px 0 0 white,
+ 12.4698px -15.63663px 0 0 white;
+ }
+ 42.85714% {
+ -webkit-box-shadow:
+ 20px 0px 0 0 white,
+ 12.4698px 15.63663px 0 0 white,
+ -4.45042px 19.49856px 0 0 var(--ring-half-color),
+ -18.01938px 8.67767px 0 0 var(--ring-full-color),
+ -18.01938px -8.67767px 0 0 white,
+ -4.45042px -19.49856px 0 0 white,
+ 12.4698px -15.63663px 0 0 white;
+ box-shadow:
+ 20px 0px 0 0 white,
+ 12.4698px 15.63663px 0 0 white,
+ -4.45042px 19.49856px 0 0 var(--ring-half-color),
+ -18.01938px 8.67767px 0 0 var(--ring-full-color),
+ -18.01938px -8.67767px 0 0 white,
+ -4.45042px -19.49856px 0 0 white,
+ 12.4698px -15.63663px 0 0 white;
+ }
+ 57.14286% {
+ -webkit-box-shadow:
+ 20px 0px 0 0 white,
+ 12.4698px 15.63663px 0 0 var(--ring-half-color),
+ -4.45042px 19.49856px 0 0 var(--ring-full-color),
+ -18.01938px 8.67767px 0 0 white,
+ -18.01938px -8.67767px 0 0 white,
+ -4.45042px -19.49856px 0 0 white,
+ 12.4698px -15.63663px 0 0 white;
+ box-shadow:
+ 20px 0px 0 0 white,
+ 12.4698px 15.63663px 0 0 var(--ring-half-color),
+ -4.45042px 19.49856px 0 0 var(--ring-full-color),
+ -18.01938px 8.67767px 0 0 white,
+ -18.01938px -8.67767px 0 0 white,
+ -4.45042px -19.49856px 0 0 white,
+ 12.4698px -15.63663px 0 0 white;
+ }
+ 71.42857% {
+ -webkit-box-shadow:
+ 20px 0px 0 0 var(--ring-half-color),
+ 12.4698px 15.63663px 0 0 var(--ring-full-color),
+ -4.45042px 19.49856px 0 0 white,
+ -18.01938px 8.67767px 0 0 white,
+ -18.01938px -8.67767px 0 0 white,
+ -4.45042px -19.49856px 0 0 white,
+ 12.4698px -15.63663px 0 0 white;
+ box-shadow:
+ 20px 0px 0 0 var(--ring-half-color),
+ 12.4698px 15.63663px 0 0 var(--ring-full-color),
+ -4.45042px 19.49856px 0 0 white,
+ -18.01938px 8.67767px 0 0 white,
+ -18.01938px -8.67767px 0 0 white,
+ -4.45042px -19.49856px 0 0 white,
+ 12.4698px -15.63663px 0 0 white;
+ }
+ 85.71429% {
+ -webkit-box-shadow:
+ 20px 0px 0 0 var(--ring-full-color),
+ 12.4698px 15.63663px 0 0 white,
+ -4.45042px 19.49856px 0 0 white,
+ -18.01938px 8.67767px 0 0 white,
+ -18.01938px -8.67767px 0 0 white,
+ -4.45042px -19.49856px 0 0 white,
+ 12.4698px -15.63663px 0 0 var(--ring-half-color);
+ box-shadow:
+ 20px 0px 0 0 var(--ring-full-color),
+ 12.4698px 15.63663px 0 0 white,
+ -4.45042px 19.49856px 0 0 white,
+ -18.01938px 8.67767px 0 0 white,
+ -18.01938px -8.67767px 0 0 white,
+ -4.45042px -19.49856px 0 0 white,
+ 12.4698px -15.63663px 0 0 var(--ring-half-color);
+ }
+ 100% {
+ -webkit-box-shadow:
+ 20px 0px 0 0 white,
+ 12.4698px 15.63663px 0 0 white,
+ -4.45042px 19.49856px 0 0 white,
+ -18.01938px 8.67767px 0 0 white,
+ -18.01938px -8.67767px 0 0 white,
+ -4.45042px -19.49856px 0 0 var(--ring-half-color),
+ 12.4698px -15.63663px 0 0 var(--ring-full-color);
+ box-shadow:
+ 20px 0px 0 0 white,
+ 12.4698px 15.63663px 0 0 white,
+ -4.45042px 19.49856px 0 0 white,
+ -18.01938px 8.67767px 0 0 white,
+ -18.01938px -8.67767px 0 0 white,
+ -4.45042px -19.49856px 0 0 var(--ring-half-color),
+ 12.4698px -15.63663px 0 0 var(--ring-full-color);
+ }
+}
+
+.ring-of-dots:before {
+ animation: ring-of-dots 1s infinite linear reverse;
+ border-radius: 10px;
+ content: "";
+ display: block;
+ height: 10px;
+ width: 10px;
+}
diff --git a/page/src/main.tsx b/page/src/main.tsx
index 794b4af8..e4c11801 100644
--- a/page/src/main.tsx
+++ b/page/src/main.tsx
@@ -4,15 +4,24 @@ import "./index.css";
import App from "./App.tsx";
import { registerSW } from "virtual:pwa-register";
+(window as any).loading = false;
+
+registerSW({
+ onNeedRefresh() {
+ setTimeout(() => {
+ window.location.reload();
+ }, 5000);
+ },
+ onOfflineReady() {},
+ onRegisteredSW(_, registration) {
+ registration?.addEventListener("updatefound", () => {
+ (window as any).loading = true;
+ });
+ },
+});
+
createRoot(document.getElementById("root")!).render(
,
);
-
-registerSW({
- onNeedRefresh() {
- window.location.reload();
- },
- onOfflineReady() {},
-});