mirror of
https://github.com/signalapp/Signal-Desktop.git
synced 2026-02-14 23:18:54 +00:00
GroupMemberLabelEditor: Show dialog on save or permissions error
This commit is contained in:
@@ -6240,6 +6240,18 @@
|
|||||||
"messageformat": "Saving changes...",
|
"messageformat": "Saving changes...",
|
||||||
"description": "Accessibility label for button with spinner as we save the user's member label."
|
"description": "Accessibility label for button with spinner as we save the user's member label."
|
||||||
},
|
},
|
||||||
|
"icu:ConversationDetails--member-label--error-title": {
|
||||||
|
"messageformat": "Can’t save member label",
|
||||||
|
"description": "If save of member label failed, a dialog shows. Title of dialog."
|
||||||
|
},
|
||||||
|
"icu:ConversationDetails--member-label--error-generic": {
|
||||||
|
"messageformat": "Check your connection and try again.",
|
||||||
|
"description": "If save of member label failed, a dialog shows. Description of dialog."
|
||||||
|
},
|
||||||
|
"icu:ConversationDetails--member-label--error-permissions": {
|
||||||
|
"messageformat": "Only admins can set member labels in this group.",
|
||||||
|
"description": "If Desktop discovers that permissions have changed since entering the screen, it will show this in an error dialog and exit the pane."
|
||||||
|
},
|
||||||
"icu:ConversationDetails--disappearing-messages-label": {
|
"icu:ConversationDetails--disappearing-messages-label": {
|
||||||
"messageformat": "Disappearing messages",
|
"messageformat": "Disappearing messages",
|
||||||
"description": "This is the label for the disappearing messages setting panel"
|
"description": "This is the label for the disappearing messages setting panel"
|
||||||
|
|||||||
@@ -9,6 +9,9 @@ import { GroupMemberLabelEditor } from './GroupMemberLabelEditor.dom.js';
|
|||||||
import { getDefaultConversation } from '../../../test-helpers/getDefaultConversation.std.js';
|
import { getDefaultConversation } from '../../../test-helpers/getDefaultConversation.std.js';
|
||||||
import { ThemeType } from '../../../types/Util.std.js';
|
import { ThemeType } from '../../../types/Util.std.js';
|
||||||
import { getFakeBadge } from '../../../test-helpers/getFakeBadge.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;
|
const { i18n } = window.SignalContext;
|
||||||
|
|
||||||
@@ -26,7 +29,14 @@ const createProps = (): PropsType => ({
|
|||||||
ourColor: '160',
|
ourColor: '160',
|
||||||
popPanelForConversation: action('popPanelForConversation'),
|
popPanelForConversation: action('popPanelForConversation'),
|
||||||
theme: ThemeType.light,
|
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 {
|
export function NoExistingLabel(): React.JSX.Element {
|
||||||
@@ -62,3 +72,51 @@ export function WithBadge(): React.JSX.Element {
|
|||||||
|
|
||||||
return <GroupMemberLabelEditor {...props} />;
|
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,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Copyright 2026 Signal Messenger, LLC
|
// Copyright 2026 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// 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 { noop } from 'lodash';
|
||||||
|
|
||||||
import { Input } from '../../Input.dom.js';
|
import { Input } from '../../Input.dom.js';
|
||||||
@@ -26,6 +26,8 @@ import {
|
|||||||
} from '../Message.dom.js';
|
} from '../Message.dom.js';
|
||||||
import { ConversationColors } from '../../../types/Colors.std.js';
|
import { ConversationColors } from '../../../types/Colors.std.js';
|
||||||
import { WidthBreakpoint } from '../../_util.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 { EmojiVariantKey } from '../../fun/data/emojis.std.js';
|
||||||
import type {
|
import type {
|
||||||
@@ -71,6 +73,11 @@ export function GroupMemberLabelEditor({
|
|||||||
theme,
|
theme,
|
||||||
updateGroupMemberLabel,
|
updateGroupMemberLabel,
|
||||||
}: PropsType): React.JSX.Element {
|
}: PropsType): React.JSX.Element {
|
||||||
|
const [isShowingGeneralError, setIsShowingGeneralError] =
|
||||||
|
React.useState(false);
|
||||||
|
const [isShowingPermissionsError, setIsShowingPermissionsError] =
|
||||||
|
React.useState(false);
|
||||||
|
|
||||||
const messageContainer = useRef<HTMLDivElement | null>(null);
|
const messageContainer = useRef<HTMLDivElement | null>(null);
|
||||||
|
|
||||||
const [labelEmoji, setLabelEmoji] = useState(existingLabelEmoji);
|
const [labelEmoji, setLabelEmoji] = useState(existingLabelEmoji);
|
||||||
@@ -94,6 +101,17 @@ export function GroupMemberLabelEditor({
|
|||||||
? { labelEmoji, labelString: labelString.trim() }
|
? { labelEmoji, labelString: labelString.trim() }
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (
|
||||||
|
!group.areWeAdmin &&
|
||||||
|
group.accessControlAttributes ===
|
||||||
|
Proto.AccessControl.AccessRequired.ADMINISTRATOR &&
|
||||||
|
!isShowingPermissionsError
|
||||||
|
) {
|
||||||
|
setIsShowingPermissionsError(true);
|
||||||
|
}
|
||||||
|
}, [group, isShowingPermissionsError, setIsShowingPermissionsError]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={tw('mx-auto flex h-full max-w-[640px] flex-col')}>
|
<div className={tw('mx-auto flex h-full max-w-[640px] flex-col')}>
|
||||||
<div>
|
<div>
|
||||||
@@ -245,7 +263,8 @@ export function GroupMemberLabelEditor({
|
|||||||
popPanelForConversation();
|
popPanelForConversation();
|
||||||
},
|
},
|
||||||
onFailure() {
|
onFailure() {
|
||||||
// TODO: DESKTOP-9710
|
setIsSaving(false);
|
||||||
|
setIsShowingGeneralError(true);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -254,6 +273,68 @@ export function GroupMemberLabelEditor({
|
|||||||
{i18n('icu:save')}
|
{i18n('icu:save')}
|
||||||
</AxoButton.Root>
|
</AxoButton.Root>
|
||||||
</div>
|
</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>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user