an independent Bluesky client using Constellation, PDS Queries, and other services reddwarf.app
frontend spa bluesky reddwarf microcosm client app
92
fork

Configure Feed

Select the types of activity you want to include in your feed.

better live update status of indexing

rimar1337 f922e15e 1414d177

+86 -21
+48 -20
src/routes/search.tsx
··· 2 2 import { useQueryClient } from "@tanstack/react-query"; 3 3 import { createFileRoute, useSearch } from "@tanstack/react-router"; 4 4 import { useAtom } from "jotai"; 5 - import { useMemo } from "react"; 5 + import { useEffect,useMemo } from "react"; 6 6 7 7 import { Header } from "~/components/Header"; 8 8 import { Import } from "~/components/Import"; ··· 21 21 } from "~/utils/useQuery"; 22 22 23 23 import { renderSnack } from "./__root"; 24 + import { SliderPrimitive } from "./settings"; 24 25 25 26 export const Route = createFileRoute("/search")({ 26 27 component: Search, ··· 32 33 const { data: identity } = useQueryIdentity(agent?.did); 33 34 const [lycandomain] = useAtom(lycanURLAtom); 34 35 const lycanExists = lycandomain !== ""; 35 - const { data: lycanstatusdata } = useQueryLycanStatus(); 36 + const { data: lycanstatusdata, refetch } = useQueryLycanStatus(); 36 37 const lycanIndexed = lycanstatusdata?.status === "finished" || false; 38 + const lycanIndexing = lycanstatusdata?.status === "in_progress" || false; 39 + const lycanIndexingProgress = lycanIndexing 40 + ? lycanstatusdata?.progress 41 + : undefined; 42 + 37 43 const authed = status === "signedIn"; 38 44 39 45 const lycanReady = lycanExists && lycanIndexed && authed; 40 46 41 47 const { q }: { q: string } = useSearch({ from: "/search" }); 42 48 43 - //const lycanIndexed = useQuery(); 49 + // auto-refetch Lycan status until ready 50 + useEffect(() => { 51 + if (!lycanExists || !authed) return; 52 + if (lycanReady) return; 53 + 54 + const interval = setInterval(() => { 55 + refetch(); 56 + }, 3000); 57 + 58 + return () => clearInterval(interval); 59 + }, [lycanExists, authed, lycanReady, refetch]); 44 60 45 61 const maintext = !lycanExists 46 62 ? "Sorry we dont have search. But instead, you can load some of these types of content into Red Dwarf:" ··· 64 80 constructLycanRequestIndexQuery(opts) 65 81 ); 66 82 if ( 67 - response?.message !== "Import has already started" || 68 - response?.message !== "Import has already started" 83 + response?.message !== "Import has already started" && 84 + response?.message !== "Import has been scheduled" 69 85 ) { 70 86 renderSnack({ 71 87 title: "Registration failed!", ··· 76 92 title: "Succesfully sent registration request!", 77 93 description: "Please wait for the server to index your account", 78 94 }); 95 + refetch(); 79 96 } 80 97 } catch { 81 98 renderSnack({ ··· 127 144 </p> 128 145 129 146 {lycanExists && authed && !lycanReady ? ( 130 - <div className="mt-4 mx-auto"> 131 - <button 132 - onClick={() => 133 - index({ 134 - agent: agent || undefined, 135 - isAuthed: status === "signedIn", 136 - pdsUrl: identity?.pds, 137 - feedServiceDid: "did:web:" + lycandomain, 138 - }) 139 - } 140 - className="px-6 py-2 h-12 rounded-full bg-gray-100 dark:bg-gray-800 147 + !lycanIndexing ? ( 148 + <div className="mt-4 mx-auto"> 149 + <button 150 + onClick={() => 151 + index({ 152 + agent: agent || undefined, 153 + isAuthed: status === "signedIn", 154 + pdsUrl: identity?.pds, 155 + feedServiceDid: "did:web:" + lycandomain, 156 + }) 157 + } 158 + className="px-6 py-2 h-12 rounded-full bg-gray-100 dark:bg-gray-800 141 159 text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-700 transition" 142 - > 143 - Index my Account 144 - </button> 145 - </div> 160 + > 161 + Index my Account 162 + </button> 163 + </div> 164 + ) : ( 165 + <div className="mt-4 gap-2 flex flex-col"> 166 + <span>indexing...</span> 167 + <SliderPrimitive 168 + value={lycanIndexingProgress || 0} 169 + min={0} 170 + max={1} 171 + /> 172 + </div> 173 + ) 146 174 ) : ( 147 175 <></> 148 176 )}
+33
src/routes/settings.tsx
··· 325 325 </Slider.Root> 326 326 ); 327 327 }; 328 + 329 + 330 + interface SliderPProps { 331 + value: number; 332 + min?: number; 333 + max?: number; 334 + step?: number; 335 + } 336 + 337 + 338 + export const SliderPrimitive: React.FC<SliderPProps> = ({ 339 + value, 340 + min = 0, 341 + max = 100, 342 + step = 1, 343 + }) => { 344 + 345 + return ( 346 + <Slider.Root 347 + className="relative flex items-center w-full h-4" 348 + value={[value]} 349 + min={min} 350 + max={max} 351 + step={step} 352 + onValueChange={(v: number[]) => {}} 353 + > 354 + <Slider.Track className="relative flex-grow h-4 bg-gray-300 dark:bg-gray-700 rounded-full"> 355 + <Slider.Range className="absolute h-full bg-gray-500 dark:bg-gray-400 rounded-l-full rounded-r-none" /> 356 + </Slider.Track> 357 + <Slider.Thumb className=" hidden shadow-[0_0_0_8px_var(--color-white)] dark:shadow-[0_0_0_8px_var(--color-gray-950)] block w-[3px] h-12 bg-gray-500 dark:bg-gray-400 rounded-md focus:outline-none" /> 358 + </Slider.Root> 359 + ); 360 + };
+5 -1
src/utils/useQuery.ts
··· 806 806 [key: string]: unknown; 807 807 error?: "MethodNotImplemented"; 808 808 message?: "Method Not Implemented"; 809 - status?: "finished"; 809 + status?: "finished" | "in_progress"; 810 + position?: string, 811 + progress?: number, 812 + 810 813 }; 811 814 815 + //{"status":"in_progress","position":"2025-08-30T06:53:18Z","progress":0.0878319661441268} 812 816 type importtype = { 813 817 message?: "Import has already started" | "Import has been scheduled" 814 818 }