Update styles for verified icon
This commit is contained in:
parent
03ed42188e
commit
6c38823b50
7 changed files with 111 additions and 8 deletions
|
@ -5911,6 +5911,14 @@
|
||||||
"messageformat": "Your profile could not be updated. Please try again.",
|
"messageformat": "Your profile could not be updated. Please try again.",
|
||||||
"description": "Error message when something goes wrong updating your profile."
|
"description": "Error message when something goes wrong updating your profile."
|
||||||
},
|
},
|
||||||
|
"icu:ProfileEditor__invalid-about__title": {
|
||||||
|
"messageformat": "Invalid characters",
|
||||||
|
"description": "Title of the confirmation model for profile editor when about text contains invalid characters"
|
||||||
|
},
|
||||||
|
"icu:ProfileEditor__invalid-about__body": {
|
||||||
|
"messageformat": "One or more characters you’ve entered can’t be used. Try again.",
|
||||||
|
"description": "Body of the confirmation model for profile editor when about text contains invalid characters"
|
||||||
|
},
|
||||||
"icu:AnnouncementsOnlyGroupBanner--modal": {
|
"icu:AnnouncementsOnlyGroupBanner--modal": {
|
||||||
"messageformat": "Message an admin",
|
"messageformat": "Message an admin",
|
||||||
"description": "Modal title for the list of admins in a group"
|
"description": "Modal title for the list of admins in a group"
|
||||||
|
|
|
@ -55,7 +55,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&--verified {
|
&--verified {
|
||||||
@include about-modal-icon('../images/icons/v3/check/check.svg');
|
@include about-modal-icon(
|
||||||
|
'../images/icons/v3/safety_number/safety_number.svg'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
&--blocked {
|
&--blocked {
|
||||||
|
|
|
@ -136,7 +136,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&__verified {
|
&__verified {
|
||||||
@include icon-element('../images/icons/v3/check/check-compact.svg');
|
@include icon-element(
|
||||||
|
'../images/icons/v3/safety_number/safety_number-compact.svg'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -198,7 +198,7 @@
|
||||||
|
|
||||||
&--icon-verified::before {
|
&--icon-verified::before {
|
||||||
@include system-message-icon(
|
@include system-message-icon(
|
||||||
'../images/icons/v3/check/check-compact.svg'
|
'../images/icons/v3/safety_number/safety_number-compact.svg'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@ import type { ShowToastAction } from '../state/ducks/toast';
|
||||||
import { getEmojiData, unifiedToEmoji } from './emoji/lib';
|
import { getEmojiData, unifiedToEmoji } from './emoji/lib';
|
||||||
import { assertDev } from '../util/assert';
|
import { assertDev } from '../util/assert';
|
||||||
import { missingCaseError } from '../util/missingCaseError';
|
import { missingCaseError } from '../util/missingCaseError';
|
||||||
|
import { sanitizeAboutText } from '../util/getAboutText';
|
||||||
import { ConfirmationDialog } from './ConfirmationDialog';
|
import { ConfirmationDialog } from './ConfirmationDialog';
|
||||||
import { ContextMenu } from './ContextMenu';
|
import { ContextMenu } from './ContextMenu';
|
||||||
import { UsernameLinkModalBody } from './UsernameLinkModalBody';
|
import { UsernameLinkModalBody } from './UsernameLinkModalBody';
|
||||||
|
@ -209,6 +210,7 @@ export function ProfileEditor({
|
||||||
});
|
});
|
||||||
const [isResettingUsername, setIsResettingUsername] = useState(false);
|
const [isResettingUsername, setIsResettingUsername] = useState(false);
|
||||||
const [isResettingUsernameLink, setIsResettingUsernameLink] = useState(false);
|
const [isResettingUsernameLink, setIsResettingUsernameLink] = useState(false);
|
||||||
|
const [isInvalidAboutText, setIsInvalidAboutText] = useState(false);
|
||||||
|
|
||||||
// Reset username edit state when leaving
|
// Reset username edit state when leaving
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -495,6 +497,14 @@ export function ProfileEditor({
|
||||||
<Button
|
<Button
|
||||||
disabled={shouldDisableSave}
|
disabled={shouldDisableSave}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
if (
|
||||||
|
sanitizeAboutText(stagedProfile.aboutText) !==
|
||||||
|
stagedProfile.aboutText
|
||||||
|
) {
|
||||||
|
setIsInvalidAboutText(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
setFullBio({
|
setFullBio({
|
||||||
aboutEmoji: stagedProfile.aboutEmoji,
|
aboutEmoji: stagedProfile.aboutEmoji,
|
||||||
aboutText: stagedProfile.aboutText,
|
aboutText: stagedProfile.aboutText,
|
||||||
|
@ -768,6 +778,25 @@ export function ProfileEditor({
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{isInvalidAboutText && (
|
||||||
|
<ConfirmationDialog
|
||||||
|
dialogName="ProfileEditorModal.invalidAboutText"
|
||||||
|
title={i18n('icu:ProfileEditor__invalid-about__title')}
|
||||||
|
cancelButtonVariant={ButtonVariant.Primary}
|
||||||
|
cancelText={i18n('icu:Confirmation--confirm')}
|
||||||
|
i18n={i18n}
|
||||||
|
onClose={() => {
|
||||||
|
setStagedProfile(profileData => ({
|
||||||
|
...profileData,
|
||||||
|
aboutText: sanitizeAboutText(profileData?.aboutText),
|
||||||
|
}));
|
||||||
|
setIsInvalidAboutText(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{i18n('icu:ProfileEditor__invalid-about__body')}
|
||||||
|
</ConfirmationDialog>
|
||||||
|
)}
|
||||||
|
|
||||||
{isResettingUsernameLink && (
|
{isResettingUsernameLink && (
|
||||||
<ConfirmationDialog
|
<ConfirmationDialog
|
||||||
i18n={i18n}
|
i18n={i18n}
|
||||||
|
|
53
ts/test-node/util/getAboutText_test.ts
Normal file
53
ts/test-node/util/getAboutText_test.ts
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
// Copyright 2024 Signal Messenger, LLC
|
||||||
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
import { assert } from 'chai';
|
||||||
|
|
||||||
|
import enMessages from '../../../_locales/en/messages.json';
|
||||||
|
import { getAboutText } from '../../util/getAboutText';
|
||||||
|
import { setupI18n } from '../../util/setupI18n';
|
||||||
|
|
||||||
|
const i18n = setupI18n('en', enMessages);
|
||||||
|
|
||||||
|
describe('getAboutText', () => {
|
||||||
|
it('returns undefined when there is no text', () => {
|
||||||
|
assert.isUndefined(getAboutText({}, i18n));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns text when there is text, but not emoji', () => {
|
||||||
|
assert.strictEqual(
|
||||||
|
getAboutText(
|
||||||
|
{
|
||||||
|
about: 'hello',
|
||||||
|
},
|
||||||
|
i18n
|
||||||
|
),
|
||||||
|
'hello'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns text and emoji', () => {
|
||||||
|
assert.strictEqual(
|
||||||
|
getAboutText(
|
||||||
|
{
|
||||||
|
about: 'hello',
|
||||||
|
aboutEmoji: '😁',
|
||||||
|
},
|
||||||
|
i18n
|
||||||
|
),
|
||||||
|
'😁 hello'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('simplifies text', () => {
|
||||||
|
assert.strictEqual(
|
||||||
|
getAboutText(
|
||||||
|
{
|
||||||
|
about: '✓✔☑√⛉⛊⛛hello',
|
||||||
|
},
|
||||||
|
i18n
|
||||||
|
),
|
||||||
|
'hello'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,23 +1,32 @@
|
||||||
// Copyright 2023 Signal Messenger, LLC
|
// Copyright 2023 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
import type { LocalizerType } from '../types/Util';
|
||||||
import type { ConversationAttributesType } from '../model-types';
|
import type { ConversationAttributesType } from '../model-types';
|
||||||
|
|
||||||
export function getAboutText(
|
export function sanitizeAboutText(
|
||||||
attributes: ConversationAttributesType
|
text: string | undefined
|
||||||
): string | undefined {
|
): string | undefined {
|
||||||
if (!attributes.about) {
|
return text?.replace(/[✓✔☑√⛉⛊⛛]/g, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getAboutText(
|
||||||
|
attributes: Pick<ConversationAttributesType, 'about' | 'aboutEmoji'>,
|
||||||
|
i18n: LocalizerType = window.i18n
|
||||||
|
): string | undefined {
|
||||||
|
const text = sanitizeAboutText(attributes.about);
|
||||||
|
|
||||||
|
if (!text) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const emoji = attributes.aboutEmoji;
|
const emoji = attributes.aboutEmoji;
|
||||||
const text = attributes.about;
|
|
||||||
|
|
||||||
if (!emoji) {
|
if (!emoji) {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
return window.i18n('icu:message--getNotificationText--text-with-emoji', {
|
return i18n('icu:message--getNotificationText--text-with-emoji', {
|
||||||
text,
|
text,
|
||||||
emoji,
|
emoji,
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue