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 defaulthue = 28;
96export const hueAtom = atomWithStorage<number>("hue", defaulthue);
97
98export const isAtTopAtom = atom<boolean>(true);
99
100type ComposerState =
101 | { kind: "closed" }
102 | { kind: "root" }
103 | { kind: "reply"; parent: string }
104 | { kind: "quote"; subject: string };
105export const composerAtom = atom<ComposerState>({ kind: "closed" });
106
107//export const agentAtom = atom<Agent | null>(null);
108//export const authedAtom = atom<boolean>(false);
109
110export function useAtomCssVar(atom: typeof hueAtom, cssVar: string) {
111 const value = useAtomValue(atom);
112
113 useEffect(() => {
114 document.documentElement.style.setProperty(cssVar, value.toString());
115 }, [value, cssVar]);
116
117 useEffect(() => {
118 document.documentElement.style.setProperty(cssVar, value.toString());
119 }, []);
120}
121
122hueAtom.onMount = (setAtom) => {
123 const stored = localStorage.getItem("hue");
124 if (stored != null) setAtom(Number(stored));
125};
126// export function initAtomToCssVar(atom: typeof hueAtom, cssVar: string) {
127// const initial = store.get(atom);
128// console.log("atom get ", initial);
129// document.documentElement.style.setProperty(cssVar, initial.toString());
130// }
131
132
133
134// fun stuff
135
136export const enableBitesAtom = atomWithStorage<boolean>(
137 "enableBitesAtom",
138 false
139);
140
141export const enableBridgyTextAtom = atomWithStorage<boolean>(
142 "enableBridgyTextAtom",
143 false
144);
145
146export const enableWafrnTextAtom = atomWithStorage<boolean>(
147 "enableWafrnTextAtom",
148 false
149);