+48
-20
src/routes/search.tsx
+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
+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
+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
}