diff --git a/src/screens/Settings/DeerSettings.tsx b/src/screens/Settings/DeerSettings.tsx index 423fb8614..f62494c29 100644 --- a/src/screens/Settings/DeerSettings.tsx +++ b/src/screens/Settings/DeerSettings.tsx @@ -23,6 +23,10 @@ import { useDirectFetchRecords, useSetDirectFetchRecords, } from '#/state/preferences/direct-fetch-records' +import { + useNoAppLabelers, + useSetNoAppLabelers, +} from '#/state/preferences/no-app-labelers' import {TextInput} from '#/view/com/modals/util' import * as SettingsList from '#/screens/Settings/components/SettingsList' import {atoms as a} from '#/alf' @@ -35,6 +39,7 @@ import {Eye_Stroke2_Corner0_Rounded as VisibilityIcon} from '#/components/icons/ import {Earth_Stroke2_Corner2_Rounded as GlobeIcon} from '#/components/icons/Globe' import {Lab_Stroke2_Corner0_Rounded as BeakerIcon} from '#/components/icons/Lab' import {PaintRoller_Stroke2_Corner2_Rounded as PaintRollerIcon} from '#/components/icons/PaintRoller' +import {RaisingHand4Finger_Stroke2_Corner0_Rounded as RaisingHandIcon} from '#/components/icons/RaisingHand' import * as Layout from '#/components/Layout' import {Text} from '#/components/Typography' @@ -117,6 +122,9 @@ export function DeerSettingsScreen({}: Props) { const directFetchRecords = useDirectFetchRecords() const setDirectFetchRecords = useSetDirectFetchRecords() + const noAppLabelers = useNoAppLabelers() + const setNoAppLabelers = useSetNoAppLabelers() + const location = useGeolocation() const setLocationControl = Dialog.useDialogControl() @@ -176,7 +184,8 @@ export function DeerSettingsScreen({}: Props) { style={[a.w_full]}> - Fetch records directly from PDS to see through quote blocks + Fetch records directly from PDS to see contents of blocked and + detatched quotes @@ -214,12 +223,46 @@ export function DeerSettingsScreen({}: Props) { - Geolocation country code informs required regional labelers and - currency behavior. + Geolocation country code informs required regional app labelers + and currency behavior. + + + + Labelers + + setNoAppLabelers(value)} + style={[a.w_full]}> + + Do not declare any default app labelers + + + + + Restart app after changing this setting. + + + + Some appviews will default to using an app labeler if you have + no labelers, so consider subscribing to at least one labeler. + + + + + App labelers are mandatory top-level labelers that can perform + "takedowns". This setting does not influence geolocation based + labelers. + + + + diff --git a/src/state/persisted/schema.ts b/src/state/persisted/schema.ts index 519488e5a..aa7977413 100644 --- a/src/state/persisted/schema.ts +++ b/src/state/persisted/schema.ts @@ -128,7 +128,7 @@ const schema = z.object({ goLinksEnabled: z.boolean().optional(), constellationEnabled: z.boolean().optional(), directFetchRecords: z.boolean().optional(), - unfollowConfirm: z.boolean().optional(), + noAppLabelers: z.boolean().optional(), /** @deprecated */ mutedThreads: z.array(z.string()), @@ -186,7 +186,7 @@ export const defaults: Schema = { goLinksEnabled: true, constellationEnabled: false, directFetchRecords: false, - unfollowConfirm: false, + noAppLabelers: false, } export function tryParse(rawData: string): Schema | undefined { diff --git a/src/state/preferences/index.tsx b/src/state/preferences/index.tsx index 132561dd8..fca56292e 100644 --- a/src/state/preferences/index.tsx +++ b/src/state/preferences/index.tsx @@ -12,6 +12,7 @@ import {Provider as InAppBrowserProvider} from './in-app-browser' import {Provider as KawaiiProvider} from './kawaii' import {Provider as LanguagesProvider} from './languages' import {Provider as LargeAltBadgeProvider} from './large-alt-badge' +import {Provider as NoAppLabelersProvider} from './no-app-labelers' import {Provider as SubtitlesProvider} from './subtitles' import {Provider as TrendingSettingsProvider} from './trending' import {Provider as UsedStarterPacksProvider} from './used-starter-packs' @@ -37,29 +38,31 @@ export function Provider({children}: React.PropsWithChildren<{}>) { - - - - - - - - - - - - {children} - - - - - - - - - - - + + + + + + + + + + + + + {children} + + + + + + + + + + + + diff --git a/src/state/preferences/no-app-labelers.tsx b/src/state/preferences/no-app-labelers.tsx new file mode 100644 index 000000000..c8ca8bd0d --- /dev/null +++ b/src/state/preferences/no-app-labelers.tsx @@ -0,0 +1,51 @@ +import React from 'react' + +import * as persisted from '#/state/persisted' + +type StateContext = persisted.Schema['noAppLabelers'] +type SetContext = (v: persisted.Schema['noAppLabelers']) => void + +const stateContext = React.createContext( + persisted.defaults.noAppLabelers, +) +const setContext = React.createContext( + (_: persisted.Schema['noAppLabelers']) => {}, +) + +export function Provider({children}: React.PropsWithChildren<{}>) { + const [state, setState] = React.useState(persisted.get('noAppLabelers')) + + const setStateWrapped = React.useCallback( + (noAppLabelers: persisted.Schema['noAppLabelers']) => { + setState(noAppLabelers) + persisted.write('noAppLabelers', noAppLabelers) + }, + [setState], + ) + + React.useEffect(() => { + return persisted.onUpdate('noAppLabelers', nextNoAppLabelers => { + setState(nextNoAppLabelers) + }) + }, [setStateWrapped]) + + return ( + + + {children} + + + ) +} + +export function useNoAppLabelers() { + return React.useContext(stateContext) +} + +export function useSetNoAppLabelers() { + return React.useContext(setContext) +} + +export function getNoAppLabelers() { + return persisted.get('noAppLabelers') || persisted.defaults.noAppLabelers! +} diff --git a/src/state/session/moderation.ts b/src/state/session/moderation.ts index 01684fe0b..693281998 100644 --- a/src/state/session/moderation.ts +++ b/src/state/session/moderation.ts @@ -1,9 +1,10 @@ import {BSKY_LABELER_DID, BskyAgent} from '@atproto/api' import {IS_TEST_USER} from '#/lib/constants' +import {getNoAppLabelers} from '../preferences/no-app-labelers' import {configureAdditionalModerationAuthorities} from './additional-moderation-authorities' import {readLabelers} from './agent-config' -import {SessionAccount} from './types' +import {type SessionAccount} from './types' export function configureModerationForGuest() { // This global mutation is *only* OK because this code is only relevant for testing. @@ -38,7 +39,9 @@ export async function configureModerationForAccount( } function switchToBskyAppLabeler() { - BskyAgent.configure({appLabelers: [BSKY_LABELER_DID]}) + BskyAgent.configure({ + appLabelers: getNoAppLabelers() ? [] : [BSKY_LABELER_DID], + }) } async function trySwitchToTestAppLabeler(agent: BskyAgent) {