GroupMemberLabelEditor: Show dialog on save or permissions error

This commit is contained in:
Scott Nonnenberg
2026-02-10 04:33:26 +10:00
committed by GitHub
parent 74e0e245c4
commit a45eabc7aa
3 changed files with 154 additions and 3 deletions

View File

@@ -9,6 +9,9 @@ import { GroupMemberLabelEditor } from './GroupMemberLabelEditor.dom.js';
import { getDefaultConversation } from '../../../test-helpers/getDefaultConversation.std.js';
import { ThemeType } from '../../../types/Util.std.js';
import { getFakeBadge } from '../../../test-helpers/getFakeBadge.std.js';
import { SECOND } from '../../../util/durations/constants.std.js';
import { sleep } from '../../../util/sleep.std.js';
import { SignalService as Proto } from '../../../protobuf/index.std.js';
const { i18n } = window.SignalContext;
@@ -26,7 +29,14 @@ const createProps = (): PropsType => ({
ourColor: '160',
popPanelForConversation: action('popPanelForConversation'),
theme: ThemeType.light,
updateGroupMemberLabel: action('changeHasGroupLink'),
updateGroupMemberLabel: async (
options,
callbacks?: { onSuccess?: () => unknown }
) => {
action('updateGroupMemberLabel')(options);
await sleep(SECOND);
callbacks?.onSuccess?.();
},
});
export function NoExistingLabel(): React.JSX.Element {
@@ -62,3 +72,51 @@ export function WithBadge(): React.JSX.Element {
return <GroupMemberLabelEditor {...props} />;
}
export function ThrowsErrorOnSave(): React.JSX.Element {
const props: PropsType = {
...createProps(),
updateGroupMemberLabel: async (
options,
callbacks?: { onFailure?: () => unknown }
) => {
action('updateGroupMemberLabel')(options);
await sleep(SECOND);
callbacks?.onFailure?.();
},
};
return <GroupMemberLabelEditor {...props} />;
}
export function PermissionsError(): React.JSX.Element {
const props: PropsType = createProps();
return (
<GroupMemberLabelEditor
{...props}
group={{
...props.group,
areWeAdmin: false,
accessControlAttributes:
Proto.AccessControl.AccessRequired.ADMINISTRATOR,
}}
/>
);
}
export function PermissionsRestrictedButAdmin(): React.JSX.Element {
const props: PropsType = createProps();
return (
<GroupMemberLabelEditor
{...props}
group={{
...props.group,
areWeAdmin: true,
accessControlAttributes:
Proto.AccessControl.AccessRequired.ADMINISTRATOR,
}}
/>
);
}

View File

@@ -1,7 +1,7 @@
// Copyright 2026 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import React, { useRef, useState } from 'react';
import React, { useEffect, useRef, useState } from 'react';
import { noop } from 'lodash';
import { Input } from '../../Input.dom.js';
@@ -26,6 +26,8 @@ import {
} from '../Message.dom.js';
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 type { EmojiVariantKey } from '../../fun/data/emojis.std.js';
import type {
@@ -71,6 +73,11 @@ export function GroupMemberLabelEditor({
theme,
updateGroupMemberLabel,
}: PropsType): React.JSX.Element {
const [isShowingGeneralError, setIsShowingGeneralError] =
React.useState(false);
const [isShowingPermissionsError, setIsShowingPermissionsError] =
React.useState(false);
const messageContainer = useRef<HTMLDivElement | null>(null);
const [labelEmoji, setLabelEmoji] = useState(existingLabelEmoji);
@@ -94,6 +101,17 @@ export function GroupMemberLabelEditor({
? { labelEmoji, labelString: labelString.trim() }
: undefined;
useEffect(() => {
if (
!group.areWeAdmin &&
group.accessControlAttributes ===
Proto.AccessControl.AccessRequired.ADMINISTRATOR &&
!isShowingPermissionsError
) {
setIsShowingPermissionsError(true);
}
}, [group, isShowingPermissionsError, setIsShowingPermissionsError]);
return (
<div className={tw('mx-auto flex h-full max-w-[640px] flex-col')}>
<div>
@@ -245,7 +263,8 @@ export function GroupMemberLabelEditor({
popPanelForConversation();
},
onFailure() {
// TODO: DESKTOP-9710
setIsSaving(false);
setIsShowingGeneralError(true);
},
}
);
@@ -254,6 +273,68 @@ export function GroupMemberLabelEditor({
{i18n('icu:save')}
</AxoButton.Root>
</div>
<AxoAlertDialog.Root
open={isShowingGeneralError}
onOpenChange={value => {
if (!value) {
setIsShowingGeneralError(false);
}
}}
>
<AxoAlertDialog.Content escape="cancel-is-noop">
<AxoAlertDialog.Body>
<AxoAlertDialog.Title>
{i18n('icu:ConversationDetails--member-label--error-title')}
</AxoAlertDialog.Title>
<AxoAlertDialog.Description>
{i18n('icu:ConversationDetails--member-label--error-generic')}
</AxoAlertDialog.Description>
</AxoAlertDialog.Body>
<AxoAlertDialog.Footer>
<AxoAlertDialog.Action
variant="primary"
arrow={false}
onClick={() => {
setIsShowingGeneralError(false);
}}
>
{i18n('icu:ok')}
</AxoAlertDialog.Action>
</AxoAlertDialog.Footer>
</AxoAlertDialog.Content>
</AxoAlertDialog.Root>
<AxoAlertDialog.Root
open={isShowingPermissionsError}
onOpenChange={value => {
if (!value) {
setIsShowingPermissionsError(false);
popPanelForConversation();
}
}}
>
<AxoAlertDialog.Content escape="cancel-is-noop">
<AxoAlertDialog.Body>
<AxoAlertDialog.Title>
{i18n('icu:ConversationDetails--member-label--error-title')}
</AxoAlertDialog.Title>
<AxoAlertDialog.Description>
{i18n('icu:ConversationDetails--member-label--error-permissions')}
</AxoAlertDialog.Description>
</AxoAlertDialog.Body>
<AxoAlertDialog.Footer>
<AxoAlertDialog.Action
variant="primary"
arrow={false}
onClick={() => {
popPanelForConversation();
setIsShowingPermissionsError(false);
}}
>
{i18n('icu:ok')}
</AxoAlertDialog.Action>
</AxoAlertDialog.Footer>
</AxoAlertDialog.Content>
</AxoAlertDialog.Root>
</div>
);
}