Scrapboard.org client
at labels 51 lines 1.6 kB view raw
1import { create } from "zustand"; 2import { persist } from "zustand/middleware"; 3import { moderatePost, ModerationDecision } from "@atproto/api/dist/moderation"; 4import { type ModerationOpts } from "@atproto/api/dist/moderation/types"; 5import { PostView } from "@atproto/api/dist/client/types/app/bsky/feed/defs"; 6 7export interface ModerationState { 8 // Simple content warning preferences 9 showContentWarnings: boolean; 10 11 // Actions 12 setShowContentWarnings: (show: boolean) => void; 13 14 // Helper to get moderation decision using AT Protocol's built-in moderation 15 getModerationDecision: ( 16 post: PostView, 17 opts: ModerationOpts 18 ) => ModerationDecision; 19 shouldShowWarning: (post: PostView, opts: ModerationOpts) => boolean; 20} 21 22export const useModerationStore = create<ModerationState>()( 23 persist( 24 (set, get) => ({ 25 showContentWarnings: true, 26 27 setShowContentWarnings: (show) => set({ showContentWarnings: show }), 28 29 getModerationDecision: (post: PostView, opts: ModerationOpts) => { 30 return moderatePost(post, opts); 31 }, 32 33 shouldShowWarning: (post: PostView, opts: ModerationOpts) => { 34 const state = get(); 35 if (!state.showContentWarnings) return false; 36 37 const decision = state.getModerationDecision(post, opts); 38 const ui = decision.ui("contentView"); 39 40 // Show warning if content has alerts or informs 41 return ui.alert || ui.inform; 42 }, 43 }), 44 { 45 name: "moderation-store", 46 partialize: (state) => ({ 47 showContentWarnings: state.showContentWarnings, 48 }), 49 } 50 ) 51);