an appview-less Bluesky client using Constellation and PDS Queries reddwarf.app
frontend spa bluesky reddwarf microcosm
at main 3.2 kB view raw
1import "~/styles/app.css"; 2 3import { createSyncStoragePersister } from "@tanstack/query-sync-storage-persister"; 4import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; 5import { persistQueryClient } from "@tanstack/react-query-persist-client"; 6import { createRouter, RouterProvider } from "@tanstack/react-router"; 7import { useSetAtom } from "jotai"; 8import { useEffect } from "react"; 9//import { StrictMode } from "react"; 10import ReactDOM from "react-dom/client"; 11 12import reportWebVitals from "./reportWebVitals.ts"; 13// Import the generated route tree 14import { routeTree } from "./routeTree.gen"; 15import { isAtTopAtom } from "./utils/atoms.ts"; 16 17//initAtomToCssVar(hueAtom, "--tw-gray-hue") 18 19const queryClient = new QueryClient({ 20 defaultOptions: { 21 queries: { 22 gcTime: 1000 * 60 * 60 * 24 * 24, // 24 days 23 }, 24 }, 25}); 26const localStoragePersister = createSyncStoragePersister({ 27 storage: window.localStorage, 28}); 29 30persistQueryClient({ 31 queryClient, 32 persister: localStoragePersister, 33}); 34 35// Create a new router instance 36const router = createRouter({ 37 routeTree, 38 context: { queryClient }, 39 defaultPreload: "intent", 40 scrollRestoration: true, 41 defaultStructuralSharing: true, 42 defaultPreloadStaleTime: 0, 43}); 44 45// Register the router instance for type safety 46declare module "@tanstack/react-router" { 47 interface Register { 48 router: typeof router; 49 } 50} 51 52// Render the app 53const rootElement = document.getElementById("app"); 54if (rootElement && !rootElement.innerHTML) { 55 const root = ReactDOM.createRoot(rootElement); 56 root.render( 57 // double queries annoys me 58 // <StrictMode> 59 <QueryClientProvider client={queryClient}> 60 <ScrollTopWatcher /> 61 <RouterProvider router={router} /> 62 </QueryClientProvider> 63 // </StrictMode> 64 ); 65} 66 67// If you want to start measuring performance in your app, pass a function 68// to log results (for example: reportWebVitals(// /*mass comment*/ console.log)) 69// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 70reportWebVitals(); 71 72export default function ScrollTopWatcher() { 73 const setIsAtTop = useSetAtom(isAtTopAtom); 74 useEffect(() => { 75 const meta = document.querySelector('meta[name="theme-color"]'); 76 let lastAtTop = window.scrollY === 0; 77 let timeoutId: number | undefined; 78 79 const setVars = (atTop: boolean) => { 80 const root = document.documentElement; 81 root.style.setProperty("--is-top", atTop ? "1" : "0"); 82 83 const bg = getComputedStyle(root).getPropertyValue("--header-bg").trim(); 84 if (meta && bg) meta.setAttribute("content", bg); 85 setIsAtTop(atTop); 86 }; 87 88 const check = () => { 89 const atTop = window.scrollY === 0; 90 if (atTop !== lastAtTop) { 91 lastAtTop = atTop; 92 setVars(atTop); 93 } 94 }; 95 96 const handleScroll = () => { 97 if (timeoutId) clearTimeout(timeoutId); 98 timeoutId = window.setTimeout(check, 2); 99 }; 100 101 // initialize 102 setVars(lastAtTop); 103 window.addEventListener("scroll", handleScroll, { passive: true }); 104 105 return () => { 106 window.removeEventListener("scroll", handleScroll); 107 if (timeoutId) clearTimeout(timeoutId); 108 }; 109 }, []); 110 111 return null; 112}