import * as ATPAPI from "@atproto/api"; import { isAdultContentPref, isBskyAppStatePref, isContentLabelPref, isFeedViewPref, isLabelersPref, isMutedWordsPref, isSavedFeedsPref, } from "@atproto/api/dist/client/types/app/bsky/actor/defs"; import { createFileRoute } from "@tanstack/react-router"; import { useAtom } from "jotai"; import { Switch } from "radix-ui"; import { Header } from "~/components/Header"; import { useAuth } from "~/providers/UnifiedAuthProvider"; import { quickAuthAtom } from "~/utils/atoms"; import { useQueryIdentity, useQueryPreferences } from "~/utils/useQuery"; import { renderSnack } from "./__root"; import { NotificationItem } from "./notifications"; import { SettingHeading } from "./settings"; export const Route = createFileRoute("/moderation")({ component: RouteComponent, }); function RouteComponent() { const { agent } = useAuth(); const [quickAuth, setQuickAuth] = useAtom(quickAuthAtom); const isAuthRestoring = quickAuth ? status === "loading" : false; const identityresultmaybe = useQueryIdentity( !isAuthRestoring ? agent?.did : undefined ); const identity = identityresultmaybe?.data; const prefsresultmaybe = useQueryPreferences({ agent: !isAuthRestoring ? (agent ?? undefined) : undefined, pdsUrl: !isAuthRestoring ? identity?.pds : undefined, }); const rawprefs = prefsresultmaybe?.data?.preferences as | ATPAPI.AppBskyActorGetPreferences.OutputSchema["preferences"] | undefined; //console.log(JSON.stringify(prefs, null, 2)) const parsedPref = parsePreferences(rawprefs); return (
{ if (window.history.length > 1) { window.history.back(); } else { window.location.assign("/"); } }} bottomBorderDisabled={true} /> {/*

todo: add all these:
- Interaction settings
- Muted words & tags
- Moderation lists
- Muted accounts
- Blocked accounts
- Verification settings

*/}
{ renderSnack({ title: "Sorry... Modifying preferences is not implemented yet", description: "You can use another app to change preferences", //button: { label: 'Try Again', onClick: () => console.log('whatever') }, }); }} className="m3switch root" >
{Object.entries(parsedPref?.contentLabelPrefs ?? {}).map( ([label, visibility]) => (
{/* {visibility} */}
) )}
{parsedPref?.labelers.map((labeler) => { return ( ); })}
); } export function TripleToggle({ value, onChange, }: { value: "ignore" | "warn" | "hide"; onChange?: (newValue: "ignore" | "warn" | "hide") => void; }) { const options: Array<"ignore" | "warn" | "hide"> = ["ignore", "warn", "hide"]; return (
{options.map((opt) => { const isActive = opt === value; return ( ); })}
); } type PrefItem = ATPAPI.AppBskyActorGetPreferences.OutputSchema["preferences"][number]; export interface NormalizedPreferences { contentLabelPrefs: Record; mutedWords: string[]; feedViewPrefs: Record; labelers: string[]; adultContentEnabled: boolean; savedFeeds: { pinned: string[]; saved: string[]; }; nuxs: string[]; } export function parsePreferences( prefs?: PrefItem[] ): NormalizedPreferences | undefined { if (!prefs) return undefined; const normalized: NormalizedPreferences = { contentLabelPrefs: {}, mutedWords: [], feedViewPrefs: {}, labelers: [], adultContentEnabled: false, savedFeeds: { pinned: [], saved: [] }, nuxs: [], }; for (const pref of prefs) { switch (pref.$type) { case "app.bsky.actor.defs#contentLabelPref": if (!isContentLabelPref(pref)) break; normalized.contentLabelPrefs[pref.label] = pref.visibility; break; case "app.bsky.actor.defs#mutedWordsPref": if (!isMutedWordsPref(pref)) break; for (const item of pref.items ?? []) { normalized.mutedWords.push(item.value); } break; case "app.bsky.actor.defs#feedViewPref": if (!isFeedViewPref(pref)) break; normalized.feedViewPrefs[pref.feed] = pref; break; case "app.bsky.actor.defs#labelersPref": if (!isLabelersPref(pref)) break; normalized.labelers.push(...(pref.labelers?.map((l) => l.did) ?? [])); break; case "app.bsky.actor.defs#adultContentPref": if (!isAdultContentPref(pref)) break; normalized.adultContentEnabled = !!pref.enabled; break; case "app.bsky.actor.defs#savedFeedsPref": if (!isSavedFeedsPref(pref)) break; normalized.savedFeeds.pinned.push(...(pref.pinned ?? [])); normalized.savedFeeds.saved.push(...(pref.saved ?? [])); break; case "app.bsky.actor.defs#bskyAppStatePref": if (!isBskyAppStatePref(pref)) break; normalized.nuxs.push(...(pref.nuxs?.map((n) => n.id) ?? [])); break; default: // unknown pref type — just ignore for now break; } } return normalized; }