first commit
This commit is contained in:
114
src/App.tsx
Normal file
114
src/App.tsx
Normal file
@@ -0,0 +1,114 @@
|
||||
import { useEffect, useMemo, useCallback } from "react";
|
||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
import { RouterProvider } from "@tanstack/react-router";
|
||||
import { ToastContainer } from "react-toastify";
|
||||
|
||||
import {
|
||||
useUserProfileStore,
|
||||
useUserStore,
|
||||
} from "./context/zustand-store/userStore";
|
||||
import { makeRouter } from "./routes/routes";
|
||||
import { useDarkMode } from "./hooks/useDarkMode";
|
||||
import { getUserPermissions } from "./utils/getUserAvalableItems";
|
||||
import { ItemWithSubItems } from "./types/userPermissions";
|
||||
|
||||
import versionNumber from "./version.txt";
|
||||
import "./index.css";
|
||||
import "react-toastify/dist/ReactToastify.css";
|
||||
import { checkIsMobile } from "./utils/checkIsMobile";
|
||||
|
||||
const queryClient = new QueryClient();
|
||||
|
||||
export default function App() {
|
||||
const auth = useUserStore((s) => s.auth);
|
||||
const { profile } = useUserProfileStore();
|
||||
const [isDark] = useDarkMode();
|
||||
|
||||
const menuItems: ItemWithSubItems[] = useMemo(
|
||||
() => getUserPermissions(profile?.permissions ?? []),
|
||||
[profile?.permissions]
|
||||
);
|
||||
|
||||
const router = useMemo(
|
||||
() => makeRouter(auth ?? null, menuItems),
|
||||
[auth, menuItems]
|
||||
);
|
||||
|
||||
const hardRefresh = useCallback(() => {
|
||||
const url = new URL(window.location.href);
|
||||
url.searchParams.set("refresh", Date.now().toString());
|
||||
window.location.href = url.toString();
|
||||
}, []);
|
||||
|
||||
const runWhenIdle = useCallback((fn: () => void) => {
|
||||
const ric = (window as any).requestIdleCallback;
|
||||
if (typeof ric === "function") {
|
||||
ric(fn);
|
||||
} else {
|
||||
setTimeout(fn, 300);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
let aborted = false;
|
||||
const controller = new AbortController();
|
||||
const checkVersion = () => {
|
||||
if (document.visibilityState !== "visible") return;
|
||||
fetch(`${versionNumber}?_=${Date.now()}`, {
|
||||
signal: controller.signal,
|
||||
cache: "no-store",
|
||||
})
|
||||
.then((res) => res.text())
|
||||
.then(async (txt) => {
|
||||
if (aborted) return;
|
||||
const latest = txt.trim();
|
||||
const stored = localStorage.getItem("AppVersion");
|
||||
if (latest && latest !== stored) {
|
||||
localStorage.setItem("AppVersion", latest);
|
||||
const clearAndReload = async () => {
|
||||
if ("caches" in window) {
|
||||
const names = await caches.keys();
|
||||
for (const n of names) {
|
||||
await caches.delete(n).catch(() => undefined);
|
||||
}
|
||||
}
|
||||
setTimeout(hardRefresh, 200);
|
||||
};
|
||||
runWhenIdle(clearAndReload);
|
||||
}
|
||||
})
|
||||
.catch(() => {});
|
||||
};
|
||||
runWhenIdle(checkVersion);
|
||||
return () => {
|
||||
aborted = true;
|
||||
controller.abort();
|
||||
};
|
||||
}, [hardRefresh, runWhenIdle]);
|
||||
|
||||
useEffect(() => {
|
||||
const url = new URL(window.location.href);
|
||||
if (url.searchParams.has("refresh")) {
|
||||
url.searchParams.delete("refresh");
|
||||
window.history.replaceState(
|
||||
{},
|
||||
document.title,
|
||||
url.pathname + url.search
|
||||
);
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={
|
||||
isDark ? "dark:bg-dark-900 dark-scrollbar" : "bg-white light-scrollbar"
|
||||
}
|
||||
>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<RouterProvider router={router} />
|
||||
</QueryClientProvider>
|
||||
<ToastContainer position="bottom-right" />
|
||||
{checkIsMobile() && <div className="h-20"></div>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user