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,
}
}