From 051a8a0eef625bee7118170751dedef1b0f0edfe Mon Sep 17 00:00:00 2001 From: Scott Nonnenberg Date: Sat, 28 Feb 2026 05:34:14 +1000 Subject: [PATCH] Allow all group members to have labels, no permission required --- .../GroupMemberLabelEditor.dom.tsx | 46 --------------- .../GroupV2Permissions.dom.tsx | 57 ------------------- ts/groups.preload.ts | 56 ------------------ ts/types/GroupMemberLabels.std.ts | 9 +-- 4 files changed, 1 insertion(+), 167 deletions(-) diff --git a/ts/components/conversation/conversation-details/GroupMemberLabelEditor.dom.tsx b/ts/components/conversation/conversation-details/GroupMemberLabelEditor.dom.tsx index 7ceab345c2..1129811caa 100644 --- a/ts/components/conversation/conversation-details/GroupMemberLabelEditor.dom.tsx +++ b/ts/components/conversation/conversation-details/GroupMemberLabelEditor.dom.tsx @@ -26,7 +26,6 @@ import { import { ConversationColors } from '../../../types/Colors.std.js'; import { WidthBreakpoint } from '../../_util.std.js'; import { AxoAlertDialog } from '../../../axo/AxoAlertDialog.dom.js'; -import { SignalService as Proto } from '../../../protobuf/index.std.js'; import { Avatar, AvatarSize } from '../../Avatar.dom.js'; import { UserText } from '../../UserText.dom.js'; import { GroupMemberLabel } from '../ContactName.dom.js'; @@ -105,8 +104,6 @@ export function GroupMemberLabelEditor({ }: PropsType): React.JSX.Element { const [isShowingGeneralError, setIsShowingGeneralError] = React.useState(false); - const [isShowingPermissionsError, setIsShowingPermissionsError] = - React.useState(false); const messageContainer = useRef(null); @@ -134,17 +131,6 @@ export function GroupMemberLabelEditor({ ? { labelEmoji, labelString: labelStringForSave } : undefined; - useEffect(() => { - if ( - !group.areWeAdmin && - group.accessControlAttributes === - Proto.AccessControl.AccessRequired.ADMINISTRATOR && - !isShowingPermissionsError - ) { - setIsShowingPermissionsError(true); - } - }, [group, isShowingPermissionsError, setIsShowingPermissionsError]); - const tryClose = React.useRef<() => void | undefined>(); const [confirmDiscardModal, confirmDiscardIf] = useConfirmDiscard({ i18n, @@ -438,38 +424,6 @@ export function GroupMemberLabelEditor({ - { - if (!value) { - setIsShowingPermissionsError(false); - popPanelForConversation(); - } - }} - > - - - - {i18n('icu:ConversationDetails--member-label--error-title')} - - - {i18n('icu:ConversationDetails--member-label--error-permissions')} - - - - { - popPanelForConversation(); - setIsShowingPermissionsError(false); - }} - > - {i18n('icu:ok')} - - - - ); } diff --git a/ts/components/conversation/conversation-details/GroupV2Permissions.dom.tsx b/ts/components/conversation/conversation-details/GroupV2Permissions.dom.tsx index 0990756a40..b4507ef150 100644 --- a/ts/components/conversation/conversation-details/GroupV2Permissions.dom.tsx +++ b/ts/components/conversation/conversation-details/GroupV2Permissions.dom.tsx @@ -8,7 +8,6 @@ import { SignalService as Proto } from '../../../protobuf/index.std.js'; import { PanelRow } from './PanelRow.dom.js'; import { PanelSection } from './PanelSection.dom.js'; import { Select } from '../../Select.dom.js'; -import { AxoAlertDialog } from '../../../axo/AxoAlertDialog.dom.js'; export type PropsDataType = { conversation?: ConversationType; @@ -32,8 +31,6 @@ export function GroupV2Permissions({ }: PropsType): React.JSX.Element { const AccessControlEnum = Proto.AccessControl.AccessRequired; - const [isWarningAboutClearingLabels, setIsWarningAboutClearingLabels] = - React.useState(false); const addMembersSelectId = useId(); const groupInfoSelectId = useId(); const announcementSelectId = useId(); @@ -41,17 +38,8 @@ export function GroupV2Permissions({ if (conversation === undefined) { throw new Error('GroupV2Permissions rendered without a conversation'); } - const nonAdminsHaveLabels = conversation.memberships?.some( - membership => !membership.isAdmin && membership.labelString - ); const updateAccessControlAttributes = (value: string) => { - const newValue = Number(value); - if (newValue === AccessControlEnum.ADMINISTRATOR && nonAdminsHaveLabels) { - setIsWarningAboutClearingLabels(true); - return; - } - setAccessControlAttributesSetting(conversation.id, Number(value)); }; const updateAccessControlMembers = (value: string) => { @@ -126,51 +114,6 @@ export function GroupV2Permissions({ } /> )} - { - if (!value) { - setIsWarningAboutClearingLabels(false); - } - }} - > - - - - {i18n('icu:ConversationDetails--label-clear-warning--title')} - - - {i18n( - 'icu:ConversationDetails--label-clear-warning--description' - )} - - - - { - setIsWarningAboutClearingLabels(false); - }} - > - {i18n('icu:cancel')} - - { - setAccessControlAttributesSetting( - conversation.id, - AccessControlEnum.ADMINISTRATOR - ); - setIsWarningAboutClearingLabels(false); - }} - > - {i18n('icu:ConversationDetails--label-clear-warning--continue')} - - - - ); } diff --git a/ts/groups.preload.ts b/ts/groups.preload.ts index 2b3971399d..6f78157b89 100644 --- a/ts/groups.preload.ts +++ b/ts/groups.preload.ts @@ -857,9 +857,6 @@ export function buildAccessControlAttributesChange( group: ConversationAttributesType, newValue: AccessRequiredEnum ): Proto.GroupChange.Actions { - const ACCESS_ENUM = Proto.AccessControl.AccessRequired; - const ROLE_ENUM = Proto.Member.Role; - const accessControlAction = new Proto.GroupChange.Actions.ModifyAttributesAccessControlAction(); accessControlAction.attributesAccess = newValue; @@ -874,40 +871,6 @@ export function buildAccessControlAttributesChange( actions.version = (group.revision || 0) + 1; actions.modifyAttributesAccess = accessControlAction; - // Clear out all non-admin labels - const previousValue = group.accessControl?.attributes; - if ( - previousValue !== ACCESS_ENUM.ADMINISTRATOR && - newValue === ACCESS_ENUM.ADMINISTRATOR - ) { - const clientZkGroupCipher = getClientZkGroupCipher(group.secretParams); - - const modifyLabelActions = (group.membersV2 || []) - .map(member => { - if (member.role === ROLE_ENUM.ADMINISTRATOR) { - return undefined; - } - - if (!member.labelString && !member.labelEmoji) { - return undefined; - } - - const modifyLabel = - new Proto.GroupChange.Actions.ModifyMemberLabelAction(); - modifyLabel.userId = encryptServiceId(clientZkGroupCipher, member.aci); - - return modifyLabel; - }) - .filter(isNotNil); - - if (modifyLabelActions.length) { - log.info( - `buildAccessControlAttributesChange: Found ${modifyLabelActions.length} non-admins with labels. Clearing.` - ); - actions.modifyMemberLabels = modifyLabelActions; - } - } - return actions; } @@ -1271,25 +1234,6 @@ export function buildModifyMemberRoleChange({ actions.version = (group.revision || 0) + 1; actions.modifyMemberRoles = [toggleAdmin]; - const membership = group.membersV2?.find(member => member.aci === serviceId); - const onlyAdminsCanChangeAttributes = - group.accessControl?.attributes === - Proto.AccessControl.AccessRequired.ADMINISTRATOR; - const wasPreviouslyAnAdmin = - membership?.role === Proto.Member.Role.ADMINISTRATOR; - const nowNotAnAdmin = role !== Proto.Member.Role.ADMINISTRATOR; - - if ( - membership?.labelString && - onlyAdminsCanChangeAttributes && - wasPreviouslyAnAdmin && - nowNotAnAdmin - ) { - const modifyLabel = new Proto.GroupChange.Actions.ModifyMemberLabelAction(); - modifyLabel.userId = userIdCipherText; - actions.modifyMemberLabels = [modifyLabel]; - } - return actions; } diff --git a/ts/types/GroupMemberLabels.std.ts b/ts/types/GroupMemberLabels.std.ts index 10dbc6fd33..da942273f8 100644 --- a/ts/types/GroupMemberLabels.std.ts +++ b/ts/types/GroupMemberLabels.std.ts @@ -5,7 +5,6 @@ import type { ConversationType, MembershipType, } from '../state/ducks/conversations.preload.js'; -import { SignalService as Proto } from '../protobuf/index.std.js'; export const missingEmojiPlaceholder = '⍰'; @@ -26,11 +25,5 @@ export function getCanAddLabel( conversation: ConversationType, membership: MembershipType | undefined ): boolean { - return Boolean( - membership && - conversation.type === 'group' && - (membership.isAdmin || - conversation.accessControlAttributes === - Proto.AccessControl.AccessRequired.MEMBER) - ); + return Boolean(membership && conversation.type === 'group'); }