diff --git a/package.json b/package.json index 84324a70de..2096871cca 100644 --- a/package.json +++ b/package.json @@ -93,7 +93,7 @@ "prettier": "prettier --check ." }, "dependencies": { - "@atproto/api": "0.20.11", + "@atproto/api": "0.20.12", "@atproto/syntax": "0.6.1", "@bitdrift/react-native": "^0.6.8", "@braintree/sanitize-url": "^6.0.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9d21e055cd..d2808a2e9d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -242,8 +242,8 @@ importers: .: dependencies: '@atproto/api': - specifier: 0.20.11 - version: 0.20.11 + specifier: 0.20.12 + version: 0.20.12 '@atproto/syntax': specifier: 0.6.1 version: 0.6.1 @@ -877,8 +877,8 @@ packages: graphql: optional: true - '@atproto/api@0.20.11': - resolution: {integrity: sha512-1NoVJpBDAdotxo1iMZdMd75JstpdKWgBYOnxfVD4m+52bRjgU4cFg3EOGNUognZntFgL/bIHyEgyN7SJWVf6Ig==} + '@atproto/api@0.20.12': + resolution: {integrity: sha512-pNCrl/BSmkjlrVu0W5A9zkOVRIWdWAdajuHX/EyhDZFxu8HExsiQi6j46H5kv85GrNRXS/QtULE+ocSuMtEJfw==} engines: {node: '>=22'} '@atproto/common-web@0.5.0': @@ -9493,7 +9493,7 @@ snapshots: '@0no-co/graphql.web@1.2.0': {} - '@atproto/api@0.20.11': + '@atproto/api@0.20.12': dependencies: '@atproto/common-web': 0.5.0 '@atproto/lexicon': 0.7.1 diff --git a/src/screens/Messages/ConversationSettings/index.tsx b/src/screens/Messages/ConversationSettings/index.tsx index 661c197d8c..32430cfc0c 100644 --- a/src/screens/Messages/ConversationSettings/index.tsx +++ b/src/screens/Messages/ConversationSettings/index.tsx @@ -3,6 +3,7 @@ import {Pressable, View} from 'react-native' import { ChatBskyActorDefs, ChatBskyConvoDefs, + ChatBskyConvoUnlockConvo, type ModerationOpts, } from '@atproto/api' import {Trans, useLingui} from '@lingui/react/macro' @@ -417,6 +418,12 @@ function SettingsHeader({ if (lock) { logger.error('Failed to lock group chat', {message: e}) Toast.show(l`Failed to lock group chat`, {type: 'error'}) + } else if ( + e instanceof ChatBskyConvoUnlockConvo.ConvoLockedByModerationError + ) { + Toast.show(l`This chat is locked by a moderation action`, { + type: 'error', + }) } else { logger.error('Failed to unlock group chat', {message: e}) Toast.show(l`Failed to unlock group chat`, {type: 'error'}) @@ -447,7 +454,11 @@ function SettingsHeader({ const createdAt = new Date(convo.details.createdAt) - const canLockGroupChat = isOwner && lockStatus !== 'locked-permanently' + // A lock forced by a moderation action cannot be undone by the owner. + const canLockGroupChat = + isOwner && + lockStatus !== 'locked-permanently' && + !convo.details.lockStatusModerationOverride const groupNameComponent = ( - + {subheading ? ( { Toast.show(l({message: 'Group chat unlocked', context: 'toast'})) }, onError: e => { + if (e instanceof ChatBskyConvoUnlockConvo.ConvoLockedByModerationError) { + Toast.show(l`This chat is locked by a moderation action`, { + type: 'error', + }) + return + } logger.error('Failed to unlock group chat', {message: e}) Toast.show(l`Failed to unlock group chat`, {type: 'error'}) }, @@ -59,10 +68,14 @@ export function ChatLocked({ return ( {isOwner ? ( - <> + isModerationLock ? null : ( Unlock chat - + ) ) : ( <> { if (ChatBskyConvoDefs.isGroupConvo(convo.kind)) { return { ...convo, - kind: {...convo.kind, lockStatus: 'unlocked'}, + kind: { + ...convo.kind, + lockStatus: 'unlocked', + // An unlocked convo cannot be moderation-locked. + lockStatusModerationOverride: false, + }, rev: log.rev, } }