an appview-less Bluesky client using Constellation and PDS Queries
reddwarf.app
frontend
spa
bluesky
reddwarf
microcosm
1import { atom, createStore, useAtomValue } from "jotai";
2import { atomWithStorage } from "jotai/utils";
3import { useEffect } from "react";
4
5import { type ProfilePostsFilter } from "~/routes/profile.$did";
6
7export const store = createStore();
8
9export const quickAuthAtom = atomWithStorage<string | null>(
10 "quickAuth",
11 null
12);
13
14export const selectedFeedUriAtom = atomWithStorage<string | null>(
15 "selectedFeedUri",
16 null
17);
18
19//export const feedScrollPositionsAtom = atom<Record<string, number>>({});
20
21export const feedScrollPositionsAtom = atomWithStorage<Record<string, number>>(
22 "feedscrollpositions",
23 {}
24);
25
26type TabRouteScrollState = {
27 activeTab: string;
28 scrollPositions: Record<string, number>;
29};
30/**
31 * @deprecated should be safe to remove i think
32 */
33export const notificationsScrollAtom = atom<TabRouteScrollState>({
34 activeTab: "mentions",
35 scrollPositions: {},
36});
37
38export type InteractionFilter = {
39 likes: boolean;
40 reposts: boolean;
41 quotes: boolean;
42 replies: boolean;
43 showAll: boolean;
44};
45const defaultFilters: InteractionFilter = {
46 likes: true,
47 reposts: true,
48 quotes: true,
49 replies: true,
50 showAll: false,
51};
52export const postInteractionsFiltersAtom = atomWithStorage<InteractionFilter>(
53 "postInteractionsFilters",
54 defaultFilters
55);
56
57export const reusableTabRouteScrollAtom = atom<Record<string, TabRouteScrollState | undefined> | undefined>({});
58
59export const likedPostsAtom = atomWithStorage<Record<string, string>>(
60 "likedPosts",
61 {}
62);
63
64export type LikeRecord = {
65 uri: string; // at://did/collection/rkey
66 target: string;
67 cid: string;
68};
69
70export const internalLikedPostsAtom = atomWithStorage<Record<string, LikeRecord | null>>(
71 "internal-liked-posts",
72 {}
73);
74
75export const profileChipsAtom = atom<Record<string, ProfilePostsFilter | null>>({})
76
77export const defaultconstellationURL = "constellation.microcosm.blue";
78export const constellationURLAtom = atomWithStorage<string>(
79 "constellationURL",
80 defaultconstellationURL
81);
82export const defaultslingshotURL = "slingshot.microcosm.blue";
83export const slingshotURLAtom = atomWithStorage<string>(
84 "slingshotURL",
85 defaultslingshotURL
86);
87export const defaultImgCDN = "cdn.bsky.app";
88export const imgCDNAtom = atomWithStorage<string>("imgcdnurl", defaultImgCDN);
89export const defaultVideoCDN = "video.bsky.app";
90export const videoCDNAtom = atomWithStorage<string>(
91 "videocdnurl",
92 defaultVideoCDN
93);
94
95export const defaultLycanURL = "";
96export const lycanURLAtom = atomWithStorage<string>(
97 "lycanURL",
98 defaultLycanURL
99);
100
101export const defaulthue = 28;
102export const hueAtom = atomWithStorage<number>("hue", defaulthue);
103
104export const isAtTopAtom = atom<boolean>(true);
105
106type ComposerState =
107 | { kind: "closed" }
108 | { kind: "root" }
109 | { kind: "reply"; parent: string }
110 | { kind: "quote"; subject: string };
111export const composerAtom = atom<ComposerState>({ kind: "closed" });
112
113//export const agentAtom = atom<Agent | null>(null);
114//export const authedAtom = atom<boolean>(false);
115
116export function useAtomCssVar(atom: typeof hueAtom, cssVar: string) {
117 const value = useAtomValue(atom);
118
119 useEffect(() => {
120 document.documentElement.style.setProperty(cssVar, value.toString());
121 }, [value, cssVar]);
122
123 useEffect(() => {
124 document.documentElement.style.setProperty(cssVar, value.toString());
125 }, []);
126}
127
128hueAtom.onMount = (setAtom) => {
129 const stored = localStorage.getItem("hue");
130 if (stored != null) setAtom(Number(stored));
131};
132// export function initAtomToCssVar(atom: typeof hueAtom, cssVar: string) {
133// const initial = store.get(atom);
134// console.log("atom get ", initial);
135// document.documentElement.style.setProperty(cssVar, initial.toString());
136// }
137
138
139
140// fun stuff
141
142export const enableBitesAtom = atomWithStorage<boolean>(
143 "enableBitesAtom",
144 false
145);
146
147export const enableBridgyTextAtom = atomWithStorage<boolean>(
148 "enableBridgyTextAtom",
149 false
150);
151
152export const enableWafrnTextAtom = atomWithStorage<boolean>(
153 "enableWafrnTextAtom",
154 false
155);