Write on the margins of the internet. Powered by the AT Protocol.
margin.at
extension
web
atproto
comments
1import { atom } from "nanostores";
2import { getPreferences, updatePreferences } from "../api/client";
3import type {
4 LabelerSubscription,
5 LabelPreference,
6 LabelVisibility,
7} from "../types";
8
9export interface Preferences {
10 externalLinkSkippedHostnames: string[];
11 subscribedLabelers: LabelerSubscription[];
12 labelPreferences: LabelPreference[];
13 disableExternalLinkWarning: boolean;
14}
15
16export const $preferences = atom<Preferences>({
17 externalLinkSkippedHostnames: [],
18 subscribedLabelers: [],
19 labelPreferences: [],
20 disableExternalLinkWarning: false,
21});
22
23export async function loadPreferences() {
24 const prefs = await getPreferences();
25 $preferences.set({
26 externalLinkSkippedHostnames: prefs.externalLinkSkippedHostnames || [],
27 subscribedLabelers: prefs.subscribedLabelers || [],
28 labelPreferences: prefs.labelPreferences || [],
29 disableExternalLinkWarning: !!prefs.disableExternalLinkWarning,
30 });
31}
32
33export async function addSkippedHostname(hostname: string) {
34 const current = $preferences.get();
35 if (current.externalLinkSkippedHostnames.includes(hostname)) return;
36
37 const updated = {
38 ...current,
39 externalLinkSkippedHostnames: [
40 ...current.externalLinkSkippedHostnames,
41 hostname,
42 ],
43 };
44 $preferences.set(updated);
45 await updatePreferences(updated);
46}
47
48export async function addLabeler(did: string) {
49 const current = $preferences.get();
50 if (current.subscribedLabelers.some((l) => l.did === did)) return;
51
52 const updated = {
53 ...current,
54 subscribedLabelers: [...current.subscribedLabelers, { did }],
55 };
56 $preferences.set(updated);
57 await updatePreferences(updated);
58}
59
60export async function removeLabeler(did: string) {
61 const current = $preferences.get();
62 const updated = {
63 ...current,
64 subscribedLabelers: current.subscribedLabelers.filter((l) => l.did !== did),
65 };
66 $preferences.set(updated);
67 await updatePreferences(updated);
68}
69
70export async function setLabelVisibility(
71 labelerDid: string,
72 label: string,
73 visibility: LabelVisibility,
74) {
75 const current = $preferences.get();
76 const filtered = current.labelPreferences.filter(
77 (p) => !(p.labelerDid === labelerDid && p.label === label),
78 );
79 const newPrefs =
80 visibility === "warn"
81 ? filtered
82 : [...filtered, { labelerDid, label, visibility }];
83 const updated = { ...current, labelPreferences: newPrefs };
84 $preferences.set(updated);
85 await updatePreferences(updated);
86}
87
88export function getLabelVisibility(
89 labelerDid: string,
90 label: string,
91): LabelVisibility {
92 const prefs = $preferences.get();
93 const pref = prefs.labelPreferences.find(
94 (p) => p.labelerDid === labelerDid && p.label === label,
95 );
96 return pref?.visibility || "warn";
97}
98
99export async function setDisableExternalLinkWarning(disabled: boolean) {
100 const current = $preferences.get();
101 if (current.disableExternalLinkWarning === disabled) return;
102
103 const updated = {
104 ...current,
105 disableExternalLinkWarning: disabled,
106 };
107 $preferences.set(updated);
108 await updatePreferences(updated);
109}