an appview-less Bluesky client using Constellation and PDS Queries
reddwarf.app
frontend
spa
bluesky
reddwarf
microcosm
1import type Agent from "@atproto/api";
2import { atom, createStore, useAtomValue } from "jotai";
3import { atomWithStorage } from "jotai/utils";
4import { useEffect } from "react";
5
6export const store = createStore();
7
8export const selectedFeedUriAtom = atomWithStorage<string | null>(
9 "selectedFeedUri",
10 null
11);
12
13//export const feedScrollPositionsAtom = atom<Record<string, number>>({});
14
15export const feedScrollPositionsAtom = atomWithStorage<Record<string, number>>(
16 "feedscrollpositions",
17 {}
18);
19
20export const likedPostsAtom = atomWithStorage<Record<string, string>>(
21 "likedPosts",
22 {}
23);
24
25export const defaultconstellationURL = "constellation.microcosm.blue";
26export const constellationURLAtom = atomWithStorage<string>(
27 "constellationURL",
28 defaultconstellationURL
29);
30export const defaultslingshotURL = "slingshot.microcosm.blue";
31export const slingshotURLAtom = atomWithStorage<string>(
32 "slingshotURL",
33 defaultslingshotURL
34);
35export const defaultaturilistservice = "aturilistservice.reddwarf.app";
36export const aturiListServiceAtom = atomWithStorage<string>(
37 "aturilistservice",
38 defaultaturilistservice
39);
40export const defaultImgCDN = "cdn.bsky.app";
41export const imgCDNAtom = atomWithStorage<string>("imgcdnurl", defaultImgCDN);
42export const defaultVideoCDN = "video.bsky.app";
43export const videoCDNAtom = atomWithStorage<string>(
44 "videocdnurl",
45 defaultVideoCDN
46);
47
48export const defaulthue = 28;
49export const hueAtom = atomWithStorage<number>("hue", defaulthue);
50
51export const isAtTopAtom = atom<boolean>(true);
52
53type ComposerState =
54 | { kind: "closed" }
55 | { kind: "root" }
56 | { kind: "reply"; parent: string }
57 | { kind: "quote"; subject: string };
58export const composerAtom = atom<ComposerState>({ kind: "closed" });
59
60export const agentAtom = atom<Agent | null>(null);
61export const authedAtom = atom<boolean>(false);
62
63export function useAtomCssVar(atom: typeof hueAtom, cssVar: string) {
64 const value = useAtomValue(atom);
65
66 useEffect(() => {
67 document.documentElement.style.setProperty(cssVar, value.toString());
68 }, [value, cssVar]);
69
70 useEffect(() => {
71 document.documentElement.style.setProperty(cssVar, value.toString());
72 }, []);
73}
74
75hueAtom.onMount = (setAtom) => {
76 const stored = localStorage.getItem("hue");
77 if (stored != null) setAtom(Number(stored));
78};
79// export function initAtomToCssVar(atom: typeof hueAtom, cssVar: string) {
80// const initial = store.get(atom);
81// console.log("atom get ", initial);
82// document.documentElement.style.setProperty(cssVar, initial.toString());
83// }