···11+import type { Did } from '@atcute/lexicons';
22+13import type { LabelVisibility } from '#/lib/moderation/preferences-types';
2435/** DID of the Bluesky-operated moderation labeler, applied as an app labeler. */
46export const BSKY_LABELER_DID = 'did:plc:ar7c4by46qjdydhdevvrndac';
77+88+/** App-level moderation labeler DIDs. */
99+export const APP_LABELERS: readonly Did[] = [BSKY_LABELER_DID];
510611/** Default visibility for the self-applied adult/graphic labels when the user has no stored preference. */
712export const DEFAULT_LABEL_SETTINGS: Record<string, LabelVisibility> = {
···11import type { LabelPreference } from '@atcute/bluesky-moderation';
22import type { Did } from '@atcute/lexicons';
3344-import { difference } from '@mary/array-fns';
55-64import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
7586import { PROD_DEFAULT_FEED } from '#/lib/constants';
97import { replaceEqualDeep } from '#/lib/functions';
1010-import { getAppLabelers } from '#/lib/moderation/app-labelers';
88+import { APP_LABELERS } from '#/lib/moderation/const';
119import type { AppBskyActorDefs, BskyFeedViewPreference } from '#/lib/moderation/preferences-types';
12101311import { GCTIME, STALE } from '#/state/queries';
···6462 if (!pds || !currentAccount) {
6563 return DEFAULT_LOGGED_OUT_PREFERENCES;
6664 } else {
6767- const res = await getPreferences(pds, getAppLabelers());
6565+ const res = await getPreferences(pds, APP_LABELERS);
68666967 const labelerDids = res.moderationPrefs.labelers.map((l) => l.did);
7068 // save to local storage to ensure there are labels on initial requests
7169 saveLabelers(currentAccount.did, labelerDids);
7270 // keep the appview client's labeler header in sync with the freshly fetched prefs, as
7371 // `agent.getPreferences()` used to do internally
7474- setSubscribedLabelers(difference(labelerDids, getAppLabelers()));
7272+ setSubscribedLabelers(labelerDids);
75737674 const preferences: UsePreferencesQueryResponse = {
7775 ...res,
···11import type { Did } from '@atcute/lexicons';
2233-import { BSKY_LABELER_DID } from '#/lib/moderation/const';
33+import { difference } from '@mary/array-fns';
4455-/**
66- * labelers the AppView and chat clients advertise via the `atproto-accept-labelers` header. kept as mutable
77- * state so subscription changes are reflected on the next request.
88- */
55+import { APP_LABELERS, BSKY_LABELER_DID } from '#/lib/moderation/const';
961010-// App labelers are sent with `;redact`; subscribed labelers are sent plain.
1111-let appLabelers: Did[] = [BSKY_LABELER_DID];
77+import { readLabelers } from './agent-config';
88+import type { SessionAccount } from './types';
99+1210let subscribedLabelers: Did[] = [];
13111412/**
1515- * Sets the app-level labelers, sent with the `;redact` directive.
1313+ * Sets the user's subscribed labelers.
1614 *
1717- * @param dids the app labeler DIDs.
1515+ * @param dids the subscribed labeler DIDs.
1816 */
1919-export function setAppLabelers(dids: Did[]): void {
2020- appLabelers = dids;
1717+export function setSubscribedLabelers(dids: Did[]): void {
1818+ subscribedLabelers = difference(dids, APP_LABELERS);
1919+}
2020+2121+/** Configures moderation labelers for a guest session. */
2222+export function configureModerationForGuest(): void {
2323+ setSubscribedLabelers([]);
2124}
22252326/**
2424- * Sets the user's subscribed labelers, sent without a directive.
2727+ * Configures moderation labelers for an account session.
2528 *
2626- * @param dids the subscribed labeler DIDs.
2929+ * @param account session account info.
2730 */
2828-export function setSubscribedLabelers(dids: Did[]): void {
2929- subscribedLabelers = dids;
3131+export function configureModerationForAccount(account: SessionAccount): void {
3232+ const labelerDids = readLabelers(account.did);
3333+ setSubscribedLabelers(labelerDids ?? []);
3034}
31353232-/**
3333- * Builds the current `atproto-accept-labelers` header value from the configured labelers.
3434- *
3535- * @returns the comma-separated header value.
3636- */
3736export function acceptLabelersHeaderValue(): string {
3838- return [...appLabelers.map((did) => `${did};redact`), ...subscribedLabelers].join(', ');
3737+ if (subscribedLabelers.length === 0) {
3838+ return `${BSKY_LABELER_DID};redact`;
3939+ }
4040+4141+ return `${BSKY_LABELER_DID};redact, ${subscribedLabelers.join(', ')}`;
3942}
-33
src/state/session/moderation.ts
···11-import { configureAppLabelers } from '#/lib/moderation/app-labelers';
22-import { BSKY_LABELER_DID } from '#/lib/moderation/const';
33-44-import { configureAdditionalModerationAuthorities } from './additional-moderation-authorities';
55-import { readLabelers } from './agent-config';
66-import { setAppLabelers, setSubscribedLabelers } from './labelers';
77-import type { SessionAccount } from './types';
88-99-export function configureModerationForGuest() {
1010- switchToBskyAppLabeler();
1111- configureAdditionalModerationAuthorities();
1212-}
1313-1414-export function configureModerationForAccount(account: SessionAccount) {
1515- switchToBskyAppLabeler();
1616-1717- const labelerDids = readLabelers(account.did);
1818- if (labelerDids) {
1919- const subscribed = labelerDids.filter((did) => did !== BSKY_LABELER_DID);
2020- // the @atcute appview client injects this header on every request, reading it fresh from here
2121- setSubscribedLabelers(subscribed);
2222- } else {
2323- // If there are no headers in the storage, we'll not send them on the initial requests.
2424- // If we wanted to fix this, we could block on the preferences query here.
2525- }
2626-2727- configureAdditionalModerationAuthorities();
2828-}
2929-3030-function switchToBskyAppLabeler() {
3131- configureAppLabelers([BSKY_LABELER_DID]);
3232- setAppLabelers([BSKY_LABELER_DID]);
3333-}