From 9aa6b49daf05549f6d8d35652afa55854194d4f1 Mon Sep 17 00:00:00 2001 From: Samuel Newman Date: Tue, 4 Aug 2026 02:35:38 +0300 Subject: [PATCH] swap the moderation core to the sdk moderation module Point the moderation primitives - the label definitions, the cause/UI/decision types and the label-info hooks - at `@bsky.app/sdk/moderation` instead of `@atproto/api`. The two implementations are mutually unassignable: the sdk's subject types are the generated `#/lexicons` views, so their `did`/`uri`/`cid` fields are branded (`DidString`, `AtUriString`) where the `@atproto/api` views type the same fields as plain `string`. That rules out a partial swap - a decision made by one implementation cannot be read by the other - so the whole moderation layer moves together. `lib/moderation/subjects.ts` is the transitional seam for the brand mismatch. Every `moderate*` entry point is re-exported through a wrapper that widens its subject parameter to accept a view from either world, because many read paths still emit `@atproto/api` views while the moderation runtime only ever reads `.did`, `.labels` and `.viewer` - none of which the brand affects. It is deleted in the `@atproto/api` removal pass. --- src/ageAssurance/util.ts | 2 +- src/components/LabelingServiceCard/index.tsx | 6 +- src/components/Pills.tsx | 3 +- src/components/moderation/ContentHider.tsx | 2 +- src/components/moderation/Hider.tsx | 2 +- src/components/moderation/LabelPreference.tsx | 2 +- .../moderation/ModerationDetailsDialog.tsx | 2 +- src/components/moderation/PostAlerts.tsx | 8 +- src/components/moderation/PostHider.tsx | 7 +- .../moderation/ProfileHeaderAlerts.tsx | 2 +- .../moderation/ReportDialog/action.ts | 2 +- .../moderation/ReportDialog/index.tsx | 7 +- .../moderation/ReportDialog/state.test.ts | 10 +- .../moderation/ReportDialog/state.ts | 10 +- src/components/moderation/ScreenHider.tsx | 2 +- src/lib/moderation.ts | 15 +- .../create-sanitized-display-name.ts | 2 +- src/lib/moderation/subjects.ts | 133 ++++++++++++++++++ .../moderation/useLabelBehaviorDescription.ts | 2 +- src/lib/moderation/useLabelInfo.ts | 8 +- .../useModerationCauseDescription.ts | 9 +- src/lib/strings/display-names.ts | 2 +- 22 files changed, 179 insertions(+), 59 deletions(-) create mode 100644 src/lib/moderation/subjects.ts diff --git a/src/ageAssurance/util.ts b/src/ageAssurance/util.ts index 2bceab4d16..fcda8056f1 100644 --- a/src/ageAssurance/util.ts +++ b/src/ageAssurance/util.ts @@ -4,8 +4,8 @@ import { AppBskyAgeassuranceDefs, computeAgeAssuranceRegionAccess, getAgeAssuranceRegionConfig, - type ModerationPrefs, } from '@atproto/api' +import {type ModerationPrefs} from '@bsky.app/sdk/moderation' import {getAge} from '#/lib/strings/time' import {regionName} from '#/locale/helpers' diff --git a/src/components/LabelingServiceCard/index.tsx b/src/components/LabelingServiceCard/index.tsx index 10d8c97333..dc40181735 100644 --- a/src/components/LabelingServiceCard/index.tsx +++ b/src/components/LabelingServiceCard/index.tsx @@ -1,5 +1,4 @@ import {View} from 'react-native' -import {type AppBskyLabelerDefs} from '@atproto/api' import {msg} from '@lingui/core/macro' import {useLingui} from '@lingui/react' import {Plural, Trans} from '@lingui/react/macro' @@ -13,10 +12,11 @@ import {Flag_Stroke2_Corner0_Rounded as Flag} from '#/components/icons/Flag' import {Link as InternalLink, type LinkProps} from '#/components/Link' import {RichText} from '#/components/RichText' import {Text} from '#/components/Typography' +import {type app} from '#/lexicons' import {ChevronRight_Stroke2_Corner0_Rounded as ChevronRight} from '../icons/Chevron' type LabelingServiceProps = { - labeler: AppBskyLabelerDefs.LabelerViewDetailed + labeler: app.bsky.labeler.defs.LabelerViewDetailed } export function Outer({ @@ -187,7 +187,7 @@ export function Loader({ loading?: React.ComponentType<{}> error?: React.ComponentType<{error: string}> component: React.ComponentType<{ - labeler: AppBskyLabelerDefs.LabelerViewDetailed + labeler: app.bsky.labeler.defs.LabelerViewDetailed }> }) { const {isLoading, data, error} = useLabelerInfoQuery({did}) diff --git a/src/components/Pills.tsx b/src/components/Pills.tsx index e38afb6c87..8fae63e7bd 100644 --- a/src/components/Pills.tsx +++ b/src/components/Pills.tsx @@ -1,7 +1,8 @@ import {useMemo} from 'react' import {View} from 'react-native' -import {BSKY_LABELER_DID, type ModerationCause} from '@atproto/api' import {Trans, useLingui} from '@lingui/react/macro' +import {BSKY_LABELER_DID} from '@atproto/api' +import {type ModerationCause} from '@bsky.app/sdk/moderation' import {useModerationCauseDescription} from '#/lib/moderation/useModerationCauseDescription' import {UserAvatar} from '#/view/com/util/UserAvatar' diff --git a/src/components/moderation/ContentHider.tsx b/src/components/moderation/ContentHider.tsx index cfdc6c7e12..b0f8dddf01 100644 --- a/src/components/moderation/ContentHider.tsx +++ b/src/components/moderation/ContentHider.tsx @@ -5,7 +5,7 @@ import { View, type ViewStyle, } from 'react-native' -import {type ModerationUI} from '@atproto/api' +import {type ModerationUI} from '@bsky.app/sdk/moderation' import {Trans, useLingui} from '@lingui/react/macro' import { diff --git a/src/components/moderation/Hider.tsx b/src/components/moderation/Hider.tsx index 74cc9bd1c8..85d063f088 100644 --- a/src/components/moderation/Hider.tsx +++ b/src/components/moderation/Hider.tsx @@ -1,5 +1,5 @@ import {createContext, useContext, useState} from 'react' -import {type ModerationUI} from '@atproto/api' +import {type ModerationUI} from '@bsky.app/sdk/moderation' import { type ModerationCauseDescription, diff --git a/src/components/moderation/LabelPreference.tsx b/src/components/moderation/LabelPreference.tsx index a654b46e24..80a83c5e6c 100644 --- a/src/components/moderation/LabelPreference.tsx +++ b/src/components/moderation/LabelPreference.tsx @@ -2,7 +2,7 @@ import {View} from 'react-native' import { type InterpretedLabelValueDefinition, type LabelPreference, -} from '@atproto/api' +} from '@bsky.app/sdk/moderation' import {msg} from '@lingui/core/macro' import {useLingui} from '@lingui/react' import {Trans} from '@lingui/react/macro' diff --git a/src/components/moderation/ModerationDetailsDialog.tsx b/src/components/moderation/ModerationDetailsDialog.tsx index bf19dc0363..1b2351432e 100644 --- a/src/components/moderation/ModerationDetailsDialog.tsx +++ b/src/components/moderation/ModerationDetailsDialog.tsx @@ -1,6 +1,6 @@ import {useState} from 'react' import {View} from 'react-native' -import {type ModerationCause} from '@atproto/api' +import {type ModerationCause} from '@bsky.app/sdk/moderation' import {msg} from '@lingui/core/macro' import {useLingui} from '@lingui/react' import {Trans} from '@lingui/react/macro' diff --git a/src/components/moderation/PostAlerts.tsx b/src/components/moderation/PostAlerts.tsx index af8329bec5..4aa3c92a6c 100644 --- a/src/components/moderation/PostAlerts.tsx +++ b/src/components/moderation/PostAlerts.tsx @@ -1,10 +1,6 @@ import {type StyleProp, View, type ViewStyle} from 'react-native' -import { - type AppBskyFeedDefs, - type ComAtprotoLabelDefs, - type ModerationCause, - type ModerationUI, -} from '@atproto/api' +import {type AppBskyFeedDefs, type ComAtprotoLabelDefs} from '@atproto/api' +import {type ModerationCause, type ModerationUI} from '@bsky.app/sdk/moderation' import {plural} from '@lingui/core/macro' import {useLingui} from '@lingui/react/macro' diff --git a/src/components/moderation/PostHider.tsx b/src/components/moderation/PostHider.tsx index 5019b7c3e3..54d4acf945 100644 --- a/src/components/moderation/PostHider.tsx +++ b/src/components/moderation/PostHider.tsx @@ -7,11 +7,8 @@ import { View, type ViewStyle, } from 'react-native' -import { - type AppBskyActorDefs, - type ModerationCause, - type ModerationUI, -} from '@atproto/api' +import {type AppBskyActorDefs} from '@atproto/api' +import {type ModerationCause, type ModerationUI} from '@bsky.app/sdk/moderation' import {msg} from '@lingui/core/macro' import {useLingui} from '@lingui/react' import {Trans} from '@lingui/react/macro' diff --git a/src/components/moderation/ProfileHeaderAlerts.tsx b/src/components/moderation/ProfileHeaderAlerts.tsx index e6a13e2944..ee8d472b79 100644 --- a/src/components/moderation/ProfileHeaderAlerts.tsx +++ b/src/components/moderation/ProfileHeaderAlerts.tsx @@ -1,5 +1,5 @@ import {type StyleProp, type ViewStyle} from 'react-native' -import {type ModerationDecision} from '@atproto/api' +import {type ModerationDecision} from '@bsky.app/sdk/moderation' import {getModerationCauseKey, unique} from '#/lib/moderation' import * as Pills from '#/components/Pills' diff --git a/src/components/moderation/ReportDialog/action.ts b/src/components/moderation/ReportDialog/action.ts index 12b483fcab..6113a280cb 100644 --- a/src/components/moderation/ReportDialog/action.ts +++ b/src/components/moderation/ReportDialog/action.ts @@ -145,7 +145,7 @@ export function useSubmitReportMutation() { * the proxy target is built per call from that labeler's creator did. */ await client.call(com.atproto.moderation.createReport, report, { - service: `${labeler.creator.did as DidString}#atproto_labeler`, + service: `${labeler.creator.did}#atproto_labeler`, }) } }, diff --git a/src/components/moderation/ReportDialog/index.tsx b/src/components/moderation/ReportDialog/index.tsx index 7c63d04a47..79ac0be690 100644 --- a/src/components/moderation/ReportDialog/index.tsx +++ b/src/components/moderation/ReportDialog/index.tsx @@ -7,7 +7,7 @@ import { useState, } from 'react' import {Pressable, type ScrollView, View} from 'react-native' -import {type AppBskyLabelerDefs, BSKY_LABELER_DID} from '@atproto/api' +import {BSKY_LABELER_DID} from '@atproto/api' import {Trans, useLingui} from '@lingui/react/macro' import {wait} from '#/lib/async/wait' @@ -38,6 +38,7 @@ import {Loader} from '#/components/Loader' import {Text} from '#/components/Typography' import {useAnalytics} from '#/analytics' import {IS_NATIVE} from '#/env' +import {type app} from '#/lexicons' import {useSubmitReportMutation} from './action' import { BSKY_LABELER_ONLY_REPORT_REASONS, @@ -1045,8 +1046,8 @@ function LabelerCard({ labeler, onSelect, }: { - labeler: AppBskyLabelerDefs.LabelerViewDetailed - onSelect?: (option: AppBskyLabelerDefs.LabelerViewDetailed) => void + labeler: app.bsky.labeler.defs.LabelerViewDetailed + onSelect?: (option: app.bsky.labeler.defs.LabelerViewDetailed) => void }) { const t = useTheme() const {t: l} = useLingui() diff --git a/src/components/moderation/ReportDialog/state.test.ts b/src/components/moderation/ReportDialog/state.test.ts index e6f399ddf1..1bc9d54d4d 100644 --- a/src/components/moderation/ReportDialog/state.test.ts +++ b/src/components/moderation/ReportDialog/state.test.ts @@ -1,8 +1,6 @@ -import { - type AppBskyLabelerDefs, - ToolsOzoneReportDefs as OzoneReportDefs, -} from '@atproto/api' +import {ToolsOzoneReportDefs as OzoneReportDefs} from '@atproto/api' +import {type app} from '#/lexicons' import { getNciiQualificationOutcome, initialState, @@ -83,7 +81,7 @@ describe('reducer NCII qualification', () => { let state = selectNciiOption() state = reducer(state, { type: 'selectLabeler', - labeler: {} as AppBskyLabelerDefs.LabelerViewDetailed, + labeler: {} as app.bsky.labeler.defs.LabelerViewDetailed, }) expect(state.activeStepIndex1).toBe(2) }) @@ -92,7 +90,7 @@ describe('reducer NCII qualification', () => { let state = selectNciiOption() state = reducer(state, { type: 'selectLabeler', - labeler: {} as AppBskyLabelerDefs.LabelerViewDetailed, + labeler: {} as app.bsky.labeler.defs.LabelerViewDetailed, }) state = reducer(state, { type: 'answerNciiQuestion', diff --git a/src/components/moderation/ReportDialog/state.ts b/src/components/moderation/ReportDialog/state.ts index 921074952d..2dc55a6638 100644 --- a/src/components/moderation/ReportDialog/state.ts +++ b/src/components/moderation/ReportDialog/state.ts @@ -1,13 +1,11 @@ -import { - type AppBskyLabelerDefs, - ToolsOzoneReportDefs as OzoneReportDefs, -} from '@atproto/api' +import {ToolsOzoneReportDefs as OzoneReportDefs} from '@atproto/api' import {OTHER_REPORT_REASONS} from '#/components/moderation/ReportDialog/const' import { type ReportCategoryConfig, type ReportOption, } from '#/components/moderation/ReportDialog/utils/useReportOptions' +import {type app} from '#/lexicons' export type NciiQualification = { isDepicted?: boolean @@ -16,7 +14,7 @@ export type NciiQualification = { export type ReportState = { selectedCategory?: ReportCategoryConfig selectedOption?: ReportOption - selectedLabeler?: AppBskyLabelerDefs.LabelerViewDetailed + selectedLabeler?: app.bsky.labeler.defs.LabelerViewDetailed details?: string detailsOpen: boolean activeStepIndex1: number @@ -71,7 +69,7 @@ export type ReportAction = } | { type: 'selectLabeler' - labeler: AppBskyLabelerDefs.LabelerViewDetailed + labeler: app.bsky.labeler.defs.LabelerViewDetailed } | { type: 'clearLabeler' diff --git a/src/components/moderation/ScreenHider.tsx b/src/components/moderation/ScreenHider.tsx index 3c0d4584b8..9557121a05 100644 --- a/src/components/moderation/ScreenHider.tsx +++ b/src/components/moderation/ScreenHider.tsx @@ -5,7 +5,7 @@ import { View, type ViewStyle, } from 'react-native' -import {type ModerationUI} from '@atproto/api' +import {type ModerationUI} from '@bsky.app/sdk/moderation' import {Trans, useLingui} from '@lingui/react/macro' import {useNavigation} from '@react-navigation/native' diff --git a/src/lib/moderation.ts b/src/lib/moderation.ts index 0d2e3c4dbd..68b424347b 100644 --- a/src/lib/moderation.ts +++ b/src/lib/moderation.ts @@ -1,18 +1,17 @@ import {useMemo} from 'react' +import {AtpAgent, type ComAtprotoLabelDefs} from '@atproto/api' import { - type AppBskyLabelerDefs, - AtpAgent, - type ComAtprotoLabelDefs, type InterpretedLabelValueDefinition, LABELS, type ModerationCause, type ModerationOpts, type ModerationUI, -} from '@atproto/api' +} from '@bsky.app/sdk/moderation' import {sanitizeDisplayName} from '#/lib/strings/display-names' import {sanitizeHandle} from '#/lib/strings/handles' import {type AppModerationCause} from '#/components/Pills' +import {type app} from '#/lexicons' export const ADULT_CONTENT_LABELS = ['sexual', 'nudity', 'porn'] as const export const OTHER_SELF_LABELS = ['graphic-media'] as const @@ -102,8 +101,8 @@ export function lookupLabelValueDefinition( export function isAppLabeler( labeler: | string - | AppBskyLabelerDefs.LabelerView - | AppBskyLabelerDefs.LabelerViewDetailed, + | app.bsky.labeler.defs.LabelerView + | app.bsky.labeler.defs.LabelerViewDetailed, ): boolean { if (typeof labeler === 'string') { return AtpAgent.appLabelers.includes(labeler) @@ -114,8 +113,8 @@ export function isAppLabeler( export function isLabelerSubscribed( labeler: | string - | AppBskyLabelerDefs.LabelerView - | AppBskyLabelerDefs.LabelerViewDetailed, + | app.bsky.labeler.defs.LabelerView + | app.bsky.labeler.defs.LabelerViewDetailed, modOpts: ModerationOpts, ) { labeler = typeof labeler === 'string' ? labeler : labeler.creator.did diff --git a/src/lib/moderation/create-sanitized-display-name.ts b/src/lib/moderation/create-sanitized-display-name.ts index d15564d385..1298afd7ef 100644 --- a/src/lib/moderation/create-sanitized-display-name.ts +++ b/src/lib/moderation/create-sanitized-display-name.ts @@ -1,4 +1,4 @@ -import {type ModerationUI} from '@atproto/api' +import {type ModerationUI} from '@bsky.app/sdk/moderation' import {sanitizeDisplayName} from '#/lib/strings/display-names' import {sanitizeHandle} from '#/lib/strings/handles' diff --git a/src/lib/moderation/subjects.ts b/src/lib/moderation/subjects.ts new file mode 100644 index 0000000000..c1621b300c --- /dev/null +++ b/src/lib/moderation/subjects.ts @@ -0,0 +1,133 @@ +import { + type AppBskyActorDefs, + type AppBskyFeedDefs, + type AppBskyGraphDefs, + type AppBskyNotificationListNotifications, + type AppBskyRichtextFacet, + type ChatBskyActorDefs, +} from '@atproto/api' +import { + hasMutedWord as sdkHasMutedWord, + moderateFeedGenerator as sdkModerateFeedGenerator, + moderateNotification as sdkModerateNotification, + moderatePost as sdkModeratePost, + moderateProfile as sdkModerateProfile, + moderateStatus as sdkModerateStatus, + moderateUserList as sdkModerateUserList, + type ModerationDecision, + type ModerationOpts, +} from '@bsky.app/sdk/moderation' + +import {type app, type chat} from '#/lexicons' + +/* + * TRANSITIONAL. The moderation implementation now comes from + * `@bsky.app/sdk/moderation`, whose subject types are the generated + * `#/lexicons` views - so their `did`/`uri`/`cid` fields are branded + * (`DidString`, `AtUriString`). Many read paths still emit the identically + * shaped `@atproto/api` views, whose same fields are plain `string`. + * + * A plain `string` is not assignable to a branded template-literal type, so + * every `moderate*` call taking an unmigrated view fails to typecheck even + * though the value is byte-identical - the runtime only ever reads `.did`, + * `.labels` and `.viewer`, none of which the brand affects. + * + * These wrappers widen each subject parameter to accept a view from either + * world and drop the brand on the way in. Delete this module once every + * producer emits `#/lexicons` views (the `@atproto/api` removal pass) and point + * callers back at `@bsky.app/sdk/moderation` directly. + */ + +type AnyProfileSubject = + | app.bsky.actor.defs.ProfileViewBasic + | app.bsky.actor.defs.ProfileView + | app.bsky.actor.defs.ProfileViewDetailed + | chat.bsky.actor.defs.ProfileViewBasic + | AppBskyActorDefs.ProfileViewBasic + | AppBskyActorDefs.ProfileView + | AppBskyActorDefs.ProfileViewDetailed + | ChatBskyActorDefs.ProfileViewBasic + +type AnyPostSubject = app.bsky.feed.defs.PostView | AppBskyFeedDefs.PostView + +type AnyUserListSubject = + | app.bsky.graph.defs.ListViewBasic + | app.bsky.graph.defs.ListView + | AppBskyGraphDefs.ListViewBasic + | AppBskyGraphDefs.ListView + +type AnyFeedGeneratorSubject = + | app.bsky.feed.defs.GeneratorView + | AppBskyFeedDefs.GeneratorView + +type AnyNotificationSubject = + | app.bsky.notification.listNotifications.Notification + | AppBskyNotificationListNotifications.Notification + +export function moderateProfile( + subject: AnyProfileSubject, + opts: ModerationOpts, +): ModerationDecision { + return sdkModerateProfile(subject as app.bsky.actor.defs.ProfileView, opts) +} + +export function moderateStatus( + subject: AnyProfileSubject, + opts: ModerationOpts, +): ModerationDecision { + return sdkModerateStatus(subject as app.bsky.actor.defs.ProfileView, opts) +} + +export function moderatePost( + subject: AnyPostSubject, + opts: ModerationOpts, +): ModerationDecision { + return sdkModeratePost(subject as app.bsky.feed.defs.PostView, opts) +} + +export function moderateUserList( + subject: AnyUserListSubject, + opts: ModerationOpts, +): ModerationDecision { + return sdkModerateUserList(subject as app.bsky.graph.defs.ListView, opts) +} + +export function moderateFeedGenerator( + subject: AnyFeedGeneratorSubject, + opts: ModerationOpts, +): ModerationDecision { + return sdkModerateFeedGenerator( + subject as app.bsky.feed.defs.GeneratorView, + opts, + ) +} + +export function moderateNotification( + subject: AnyNotificationSubject, + opts: ModerationOpts, +): ModerationDecision { + return sdkModerateNotification( + subject as app.bsky.notification.listNotifications.Notification, + opts, + ) +} + +/** + * Widens `facets`/`actor` for the same reason the `moderate*` wrappers widen + * their subjects: mute-word matching reads only `text`/`features`/`langs`, none + * of which the brand affects. + */ +export function hasMutedWord(params: { + mutedWords: app.bsky.actor.defs.MutedWord[] + text: string + facets?: app.bsky.richtext.facet.Main[] | AppBskyRichtextFacet.Main[] + outlineTags?: string[] + languages?: string[] + actor?: AnyProfileSubject +}): boolean { + return sdkHasMutedWord({ + ...params, + facets: params.facets as app.bsky.richtext.facet.Main[] | undefined, + actor: params.actor as app.bsky.actor.defs.ProfileView | undefined, + }) +} diff --git a/src/lib/moderation/useLabelBehaviorDescription.ts b/src/lib/moderation/useLabelBehaviorDescription.ts index cdded25924..e97ecef33c 100644 --- a/src/lib/moderation/useLabelBehaviorDescription.ts +++ b/src/lib/moderation/useLabelBehaviorDescription.ts @@ -1,7 +1,7 @@ import { type InterpretedLabelValueDefinition, type LabelPreference, -} from '@atproto/api' +} from '@bsky.app/sdk/moderation' import {msg} from '@lingui/core/macro' import {useLingui} from '@lingui/react' diff --git a/src/lib/moderation/useLabelInfo.ts b/src/lib/moderation/useLabelInfo.ts index f398406078..fc565c3d45 100644 --- a/src/lib/moderation/useLabelInfo.ts +++ b/src/lib/moderation/useLabelInfo.ts @@ -1,10 +1,9 @@ +import {type ComAtprotoLabelDefs} from '@atproto/api' import { - type AppBskyLabelerDefs, - type ComAtprotoLabelDefs, type InterpretedLabelValueDefinition, interpretLabelValueDefinition, LABELS, -} from '@atproto/api' +} from '@bsky.app/sdk/moderation' import {useLingui} from '@lingui/react' import * as bcp47Match from 'bcp-47-match' @@ -13,12 +12,13 @@ import { useGlobalLabelStrings, } from '#/lib/moderation/useGlobalLabelStrings' import {useLabelDefinitions} from '#/state/preferences' +import {type app} from '#/lexicons' export interface LabelInfo { label: ComAtprotoLabelDefs.Label def: InterpretedLabelValueDefinition strings: ComAtprotoLabelDefs.LabelValueDefinitionStrings - labeler: AppBskyLabelerDefs.LabelerViewDetailed | undefined + labeler: app.bsky.labeler.defs.LabelerViewDetailed | undefined } export function useLabelInfo(label: ComAtprotoLabelDefs.Label): LabelInfo { diff --git a/src/lib/moderation/useModerationCauseDescription.ts b/src/lib/moderation/useModerationCauseDescription.ts index d11d16dca3..3cdbb30961 100644 --- a/src/lib/moderation/useModerationCauseDescription.ts +++ b/src/lib/moderation/useModerationCauseDescription.ts @@ -1,9 +1,6 @@ import {useMemo} from 'react' -import { - BSKY_LABELER_DID, - type ModerationCause, - type ModerationCauseSource, -} from '@atproto/api' +import {BSKY_LABELER_DID} from '@atproto/api' +import {type ModerationCause} from '@bsky.app/sdk/moderation' import {msg} from '@lingui/core/macro' import {useLingui} from '@lingui/react' @@ -25,7 +22,7 @@ export interface ModerationCauseDescription { description: string source?: string sourceDisplayName?: string - sourceType?: ModerationCauseSource['type'] + sourceType?: ModerationCause['source']['type'] sourceAvi?: string sourceDid?: string isSubjectAccount?: boolean diff --git a/src/lib/strings/display-names.ts b/src/lib/strings/display-names.ts index 612a317eaf..8ba2e1d215 100644 --- a/src/lib/strings/display-names.ts +++ b/src/lib/strings/display-names.ts @@ -1,4 +1,4 @@ -import {type ModerationUI} from '@atproto/api' +import {type ModerationUI} from '@bsky.app/sdk/moderation' // \u2705 = ✅ // \u2713 = ✓