+1
-1
src/components/Login.tsx
+1
-1
src/components/Login.tsx
···
161
161
onClick={onClick}
162
162
className={`px-4 py-2 text-sm font-medium transition-colors rounded-full flex-1 ${
163
163
active
164
-
? "text-gray-950 dark:text-gray-200 border-gray-500 bg-gray-400 dark:bg-gray-500"
164
+
? "text-gray-50 dark:text-gray-200 border-gray-500 bg-gray-400 dark:bg-gray-500"
165
165
: "text-gray-600 dark:text-gray-300 hover:text-gray-700 dark:hover:text-gray-200"
166
166
}`}
167
167
>
+7
-3
src/routes/notifications.tsx
+7
-3
src/routes/notifications.tsx
···
1
1
import { createFileRoute } from "@tanstack/react-router";
2
+
import { useAtom } from "jotai";
2
3
import React, { useEffect, useRef,useState } from "react";
3
4
4
5
import { useAuth } from "~/providers/UnifiedAuthProvider";
6
+
import { constellationURLAtom } from "~/utils/atoms";
5
7
6
8
const HANDLE_DID_CACHE_TIMEOUT = 60 * 60 * 1000; // 1 hour
7
9
···
70
72
}
71
73
}
72
74
75
+
const [constellationURL] = useAtom(constellationURLAtom)
76
+
73
77
useEffect(() => {
74
78
if (!did) return;
75
79
setLoading(true);
76
80
setError(null);
77
81
const urls = [
78
-
`https://constellation.microcosm.blue/links?target=${encodeURIComponent(did)}&collection=app.bsky.feed.post&path=.facets[app.bsky.richtext.facet].features[app.bsky.richtext.facet%23mention].did`,
79
-
`https://constellation.microcosm.blue/links?target=${encodeURIComponent(did)}&collection=app.bsky.feed.post&path=.facets[].features[app.bsky.richtext.facet%23mention].did`,
80
-
`https://constellation.microcosm.blue/links?target=${encodeURIComponent(did)}&collection=app.bsky.graph.follow&path=.subject`,
82
+
`https://${constellationURL}/links?target=${encodeURIComponent(did)}&collection=app.bsky.feed.post&path=.facets[app.bsky.richtext.facet].features[app.bsky.richtext.facet%23mention].did`,
83
+
`https://${constellationURL}/links?target=${encodeURIComponent(did)}&collection=app.bsky.feed.post&path=.facets[].features[app.bsky.richtext.facet%23mention].did`,
84
+
`https://${constellationURL}/links?target=${encodeURIComponent(did)}&collection=app.bsky.graph.follow&path=.subject`,
81
85
];
82
86
let ignore = false;
83
87
Promise.all(
+70
src/routes/settings.tsx
+70
src/routes/settings.tsx
···
1
1
import { createFileRoute } from "@tanstack/react-router";
2
+
import { useAtom } from "jotai";
2
3
3
4
import { Header } from "~/components/Header";
4
5
import Login from "~/components/Login";
6
+
import {
7
+
constellationURLAtom,
8
+
defaultconstellationURL,
9
+
defaultslingshotURL,
10
+
slingshotURLAtom,
11
+
} from "~/utils/atoms";
5
12
6
13
export const Route = createFileRoute("/settings")({
7
14
component: Settings,
···
21
28
}}
22
29
/>
23
30
<Login />
31
+
<TextInputSetting
32
+
atom={constellationURLAtom}
33
+
title={"Constellation URL"}
34
+
description={
35
+
"customize the Constellation instance to be used by Red Dwarf"
36
+
}
37
+
init={defaultconstellationURL}
38
+
/>
39
+
<TextInputSetting
40
+
atom={slingshotURLAtom}
41
+
title={"Slingshot URL"}
42
+
description={"customize the Slingshot instance to be used by Red Dwarf"}
43
+
init={defaultslingshotURL}
44
+
/>
24
45
</>
25
46
);
26
47
}
48
+
49
+
export function TextInputSetting({
50
+
atom,
51
+
title,
52
+
description,
53
+
init,
54
+
}: {
55
+
atom: typeof constellationURLAtom;
56
+
title?: string;
57
+
description?: string;
58
+
init?: string;
59
+
}) {
60
+
const [value, setValue] = useAtom(atom);
61
+
return (
62
+
<div className="flex flex-col gap-2 p-4 rounded-2xl border border-gray-200 dark:border-gray-800 ">
63
+
<div>
64
+
{title && (
65
+
<h3 className="text-sm font-medium text-gray-900 dark:text-gray-100">
66
+
{title}
67
+
</h3>
68
+
)}
69
+
{description && (
70
+
<p className="text-sm text-gray-500 dark:text-gray-400">
71
+
{description}
72
+
</p>
73
+
)}
74
+
</div>
75
+
76
+
<div className="flex flex-row gap-2 items-center">
77
+
<input
78
+
type="text"
79
+
value={value}
80
+
onChange={(e) => setValue(e.target.value)}
81
+
className="flex-1 px-3 py-2 rounded-lg bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-700
82
+
text-gray-900 dark:text-gray-100 placeholder:text-gray-500 dark:placeholder:text-gray-400
83
+
focus:outline-none focus:ring-2 focus:ring-gray-400 dark:focus:ring-gray-600"
84
+
placeholder="Enter value..."
85
+
/>
86
+
<button
87
+
onClick={() => setValue(init ?? "")}
88
+
className="px-3 py-2 rounded-lg border border-gray-300 dark:border-gray-700 bg-gray-100 dark:bg-gray-800
89
+
text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-700 transition"
90
+
>
91
+
Reset
92
+
</button>
93
+
</div>
94
+
</div>
95
+
);
96
+
}
+11
src/utils/atoms.ts
+11
src/utils/atoms.ts
···
21
21
{}
22
22
);
23
23
24
+
export const defaultconstellationURL = 'constellation.microcosm.blue'
25
+
export const constellationURLAtom = atomWithStorage<string>(
26
+
'constellationURL',
27
+
defaultconstellationURL
28
+
)
29
+
export const defaultslingshotURL = 'slingshot.microcosm.blue'
30
+
export const slingshotURLAtom = atomWithStorage<string>(
31
+
'slingshotURL',
32
+
defaultslingshotURL
33
+
)
34
+
24
35
export const isAtTopAtom = atom<boolean>(true);
25
36
26
37
type ComposerState =
+13
-6
src/utils/useQuery.ts
+13
-6
src/utils/useQuery.ts
···
7
7
useQuery,
8
8
type UseQueryResult} from "@tanstack/react-query";
9
9
10
+
import { constellationURLAtom, slingshotURLAtom, store } from "./atoms";
11
+
10
12
export function constructIdentityQuery(didorhandle?: string) {
11
13
return queryOptions({
12
14
queryKey: ["identity", didorhandle],
13
15
queryFn: async () => {
14
16
if (!didorhandle) return undefined as undefined
17
+
const slingshoturl = store.get(slingshotURLAtom)
15
18
const res = await fetch(
16
-
`https://slingshot.microcosm.blue/xrpc/com.bad-example.identity.resolveMiniDoc?identifier=${encodeURIComponent(didorhandle)}`
19
+
`https://${slingshoturl}/xrpc/com.bad-example.identity.resolveMiniDoc?identifier=${encodeURIComponent(didorhandle)}`
17
20
);
18
21
if (!res.ok) throw new Error("Failed to fetch post");
19
22
try {
···
63
66
queryKey: ["post", uri],
64
67
queryFn: async () => {
65
68
if (!uri) return undefined as undefined
69
+
const slingshoturl = store.get(slingshotURLAtom)
66
70
const res = await fetch(
67
-
`https://slingshot.microcosm.blue/xrpc/com.bad-example.repo.getUriRecord?at_uri=${encodeURIComponent(uri)}`
71
+
`https://${slingshoturl}/xrpc/com.bad-example.repo.getUriRecord?at_uri=${encodeURIComponent(uri)}`
68
72
);
69
73
let data: any;
70
74
try {
···
126
130
queryKey: ["profile", uri],
127
131
queryFn: async () => {
128
132
if (!uri) return undefined as undefined
133
+
const slingshoturl = store.get(slingshotURLAtom)
129
134
const res = await fetch(
130
-
`https://slingshot.microcosm.blue/xrpc/com.bad-example.repo.getUriRecord?at_uri=${encodeURIComponent(uri)}`
135
+
`https://${slingshoturl}/xrpc/com.bad-example.repo.getUriRecord?at_uri=${encodeURIComponent(uri)}`
131
136
);
132
137
let data: any;
133
138
try {
···
249
254
const path = query?.path
250
255
const cursor = query.cursor
251
256
const dids = query?.dids
257
+
const constellation = store.get(constellationURLAtom);
252
258
const res = await fetch(
253
-
`https://constellation.microcosm.blue${method}?target=${encodeURIComponent(target)}${collection ? `&collection=${encodeURIComponent(collection)}` : ""}${path ? `&path=${encodeURIComponent(path)}` : ""}${cursor ? `&cursor=${encodeURIComponent(cursor)}` : ""}${dids ? dids.map((did) => `&did=${encodeURIComponent(did)}`).join("") : ""}`
259
+
`https://${constellation}${method}?target=${encodeURIComponent(target)}${collection ? `&collection=${encodeURIComponent(collection)}` : ""}${path ? `&path=${encodeURIComponent(path)}` : ""}${cursor ? `&cursor=${encodeURIComponent(cursor)}` : ""}${dids ? dids.map((did) => `&did=${encodeURIComponent(did)}`).join("") : ""}`
254
260
);
255
261
if (!res.ok) throw new Error("Failed to fetch post");
256
262
try {
···
450
456
queryKey: ["arbitrary", uri],
451
457
queryFn: async () => {
452
458
if (!uri) return undefined as undefined
459
+
const slingshoturl = store.get(slingshotURLAtom)
453
460
const res = await fetch(
454
-
`https://slingshot.microcosm.blue/xrpc/com.bad-example.repo.getUriRecord?at_uri=${encodeURIComponent(uri)}`
461
+
`https://${slingshoturl}/xrpc/com.bad-example.repo.getUriRecord?at_uri=${encodeURIComponent(uri)}`
455
462
);
456
463
let data: any;
457
464
try {
···
624
631
collection: string
625
632
path: string
626
633
}) {
627
-
const constellationHost = 'constellation.microcosm.blue'
634
+
const constellationHost = store.get(constellationURLAtom)
628
635
console.log(
629
636
'yknowIReallyHateThisButWhateverGuardedConstructConstellationInfiniteQueryLinks',
630
637
query,