diff --git a/lib/shared/edit-messages-utils.js b/lib/shared/edit-messages-utils.js --- a/lib/shared/edit-messages-utils.js +++ b/lib/shared/edit-messages-utils.js @@ -55,6 +55,11 @@ threadInfo, threadPermissions.EDIT_MESSAGE, ); + + if (!threadSpecs[threadInfo.type].protocol().supportsMessageEdit) { + return false; + } + if (!currentUserCanEditMessage) { return false; } diff --git a/lib/shared/threads/protocols/dm-thread-protocol.js b/lib/shared/threads/protocols/dm-thread-protocol.js --- a/lib/shared/threads/protocols/dm-thread-protocol.js +++ b/lib/shared/threads/protocols/dm-thread-protocol.js @@ -952,6 +952,7 @@ protocolName: protocolNames.COMM_DM, canReactToRobotext: true, supportsThreadRefreshing: false, + supportsMessageEdit: true, }); function pendingThreadType(numberOfOtherMembers: number) { diff --git a/lib/shared/threads/protocols/farcaster-thread-protocol.js b/lib/shared/threads/protocols/farcaster-thread-protocol.js --- a/lib/shared/threads/protocols/farcaster-thread-protocol.js +++ b/lib/shared/threads/protocols/farcaster-thread-protocol.js @@ -987,6 +987,12 @@ protocolName: protocolNames.FARCASTER_DC, canReactToRobotext: false, supportsThreadRefreshing: true, + temporarilyDisabledFeatures: { + changingThreadAvatar: true, + deletingMessages: true, + pinningMessages: true, + }, + supportsMessageEdit: false, }; function pendingThreadType(numberOfOtherMembers: number) { diff --git a/lib/shared/threads/protocols/keyserver-thread-protocol.js b/lib/shared/threads/protocols/keyserver-thread-protocol.js --- a/lib/shared/threads/protocols/keyserver-thread-protocol.js +++ b/lib/shared/threads/protocols/keyserver-thread-protocol.js @@ -755,6 +755,7 @@ protocolName: protocolNames.KEYSERVER, canReactToRobotext: true, supportsThreadRefreshing: false, + supportsMessageEdit: true, }); function pendingThreadType(numberOfOtherMembers: number) { diff --git a/lib/shared/threads/thread-spec.js b/lib/shared/threads/thread-spec.js --- a/lib/shared/threads/thread-spec.js +++ b/lib/shared/threads/thread-spec.js @@ -544,6 +544,12 @@ +protocolName: ProtocolName, +canReactToRobotext: boolean, +supportsThreadRefreshing: boolean, + +temporarilyDisabledFeatures?: { + +changingThreadAvatar?: boolean, + +deletingMessages?: boolean, + +pinningMessages?: boolean, + }, + +supportsMessageEdit: boolean, }; export type ThreadSpec< diff --git a/lib/utils/delete-message-utils.js b/lib/utils/delete-message-utils.js --- a/lib/utils/delete-message-utils.js +++ b/lib/utils/delete-message-utils.js @@ -64,6 +64,13 @@ threadPermissions.DELETE_ALL_MESSAGES, ); + if ( + threadSpecs[threadInfo.type].protocol().temporarilyDisabledFeatures + ?.deletingMessages + ) { + return false; + } + if ( !targetMessageInfo || !targetMessageInfo.id || diff --git a/lib/utils/message-pinning-utils.js b/lib/utils/message-pinning-utils.js --- a/lib/utils/message-pinning-utils.js +++ b/lib/utils/message-pinning-utils.js @@ -5,6 +5,7 @@ threadHasPermission, useThreadHasPermission, } from '../shared/thread-utils.js'; +import { threadSpecs } from '../shared/threads/thread-specs.js'; import type { MessageInfo, RawMessageInfo } from '../types/message-types.js'; import type { ThreadInfo, @@ -34,6 +35,14 @@ threadInfo, threadPermissions.MANAGE_PINS, ); + + if ( + threadSpecs[threadInfo.type].protocol().temporarilyDisabledFeatures + ?.pinningMessages + ) { + return false; + } + return ( !!messageInfo && hasManagePinsPermission && diff --git a/native/avatars/edit-thread-avatar.react.js b/native/avatars/edit-thread-avatar.react.js --- a/native/avatars/edit-thread-avatar.react.js +++ b/native/avatars/edit-thread-avatar.react.js @@ -7,6 +7,7 @@ import { EditThreadAvatarContext } from 'lib/components/base-edit-thread-avatar-provider.react.js'; import { getCommunity } from 'lib/shared/thread-utils.js'; +import { threadSpecs } from 'lib/shared/threads/thread-specs.js'; import type { CommunityInfo } from 'lib/types/community-types.js'; import type { ThreadInfo, @@ -116,6 +117,10 @@ const showAvatarActionSheet = useShowAvatarActionSheet(actionSheetConfig); + const isChangingAvatarDisabled = + threadSpecs[threadInfo.type].protocol().temporarilyDisabledFeatures + ?.changingThreadAvatar; + let spinner; if (threadAvatarSaveInProgress) { spinner = ( @@ -125,11 +130,13 @@ ); } + const isDisabled = disabled || isChangingAvatarDisabled; + return ( - + {spinner} - {!disabled ? : null} + {!isDisabled ? : null} ); } diff --git a/native/chat/message-list-container.react.js b/native/chat/message-list-container.react.js --- a/native/chat/message-list-container.react.js +++ b/native/chat/message-list-container.react.js @@ -18,7 +18,10 @@ useSearchUsers, } from 'lib/shared/search-utils.js'; import { useExistingThreadInfoFinder } from 'lib/shared/thread-utils.js'; -import { threadTypeIsPersonal } from 'lib/shared/threads/thread-specs.js'; +import { + threadSpecs, + threadTypeIsPersonal, +} from 'lib/shared/threads/thread-specs.js'; import type { ThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js'; import type { AccountUserInfo, UserListItem } from 'lib/types/user-types.js'; import { pinnedMessageCountText } from 'lib/utils/message-pinning-utils.js'; @@ -405,7 +408,11 @@ }, [props.navigation, threadInfo]); const pinnedCountBanner = React.useMemo(() => { - if (!bannerText) { + const isPinningDisabled = + threadSpecs[threadInfo.type].protocol().temporarilyDisabledFeatures + ?.pinningMessages; + + if (isPinningDisabled || !bannerText) { return null; } @@ -430,6 +437,7 @@ styles.pinnedCountBanner, styles.pinnedCountText, colors.panelBackgroundLabel, + threadInfo.type, ]); const isAppForegrounded = useIsAppForegrounded(); diff --git a/web/avatars/edit-thread-avatar.react.js b/web/avatars/edit-thread-avatar.react.js --- a/web/avatars/edit-thread-avatar.react.js +++ b/web/avatars/edit-thread-avatar.react.js @@ -28,14 +28,17 @@ threadInfo, threadPermissions.EDIT_THREAD_AVATAR, ); - const threadSupportAvatarEdit = - threadSpecs[threadInfo.type].protocol().supportedThreadSettings.avatar; + const protocol = threadSpecs[threadInfo.type].protocol(); + const threadSupportAvatarEdit = protocol.supportedThreadSettings.avatar; + const isChangingAvatarDisabled = + protocol.temporarilyDisabledFeatures?.changingThreadAvatar; let editThreadAvatarMenu; if ( canEditThreadAvatar && !threadAvatarSaveInProgress && - threadSupportAvatarEdit + threadSupportAvatarEdit && + !isChangingAvatarDisabled ) { editThreadAvatarMenu = ; } diff --git a/web/chat/pinned-messages-banner.react.js b/web/chat/pinned-messages-banner.react.js --- a/web/chat/pinned-messages-banner.react.js +++ b/web/chat/pinned-messages-banner.react.js @@ -4,6 +4,7 @@ import { ChevronRight } from 'react-feather'; import { useModalContext } from 'lib/components/modal-provider.react.js'; +import { threadSpecs } from 'lib/shared/threads/thread-specs.js'; import type { ThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js'; import { pinnedMessageCountText } from 'lib/utils/message-pinning-utils.js'; @@ -31,6 +32,14 @@ }, [pushModal, inputState, threadInfo]); const pinnedMessagesBanner = React.useMemo(() => { + const isPinningDisabled = + threadSpecs[threadInfo.type].protocol().temporarilyDisabledFeatures + ?.pinningMessages; + + if (isPinningDisabled) { + return null; + } + const bannerText = !!threadInfo.pinnedCount && pinnedMessageCountText(threadInfo.pinnedCount); @@ -47,7 +56,7 @@ ); - }, [pushThreadPinsModal, threadInfo.pinnedCount]); + }, [pushThreadPinsModal, threadInfo.pinnedCount, threadInfo.type]); return pinnedMessagesBanner; }