Emojify note and add non-nickname tooltip

This commit is contained in:
Jamie Kyle 2024-04-03 15:41:13 -07:00 committed by GitHub
parent 4d794eaf14
commit b6afa47126
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 47 additions and 10 deletions

View file

@ -1370,6 +1370,10 @@
"messageformat": "{nickname} <muted>({titleNoNickname})</muted>", "messageformat": "{nickname} <muted>({titleNoNickname})</muted>",
"description": "Title of conversation when there is a nickname, example: 'Jim (James Smith)'" "description": "Title of conversation when there is a nickname, example: 'Jim (James Smith)'"
}, },
"icu:AboutContactModal__TitleWithoutNickname__Tooltip": {
"messageformat": "“{title}” is the profile name this person set for themselves in Signal.",
"description": "Tooltip for the non-nickname title of a conversation."
},
"icu:AboutContactModal__verified": { "icu:AboutContactModal__verified": {
"messageformat": "Verified", "messageformat": "Verified",
"description": "Text of a button on About modal leading to a safety number modal" "description": "Text of a button on About modal leading to a safety number modal"

View file

@ -141,3 +141,7 @@
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
} }
.AboutContactModal__TitleWithoutNickname__Tooltip {
max-width: 300px;
}

View file

@ -19,7 +19,7 @@ import { strictAssert } from '../util/assert';
const formSchema = z.object({ const formSchema = z.object({
nickname: z nickname: z
.object({ .object({
givenName: z.string(), givenName: z.string().nullable(),
familyName: z.string().nullable(), familyName: z.string().nullable(),
}) })
.nullable(), .nullable(),

View file

@ -7,6 +7,8 @@ import type { LocalizerType } from '../types/I18N';
import { Button, ButtonVariant } from './Button'; import { Button, ButtonVariant } from './Button';
import { Modal } from './Modal'; import { Modal } from './Modal';
import { Linkify } from './conversation/Linkify'; import { Linkify } from './conversation/Linkify';
import type { RenderTextCallbackType } from '../types/Util';
import { Emojify } from './conversation/Emojify';
export type NotePreviewModalProps = Readonly<{ export type NotePreviewModalProps = Readonly<{
conversation: ConversationType; conversation: ConversationType;
@ -15,6 +17,10 @@ export type NotePreviewModalProps = Readonly<{
onEdit: () => void; onEdit: () => void;
}>; }>;
const renderNonLink: RenderTextCallbackType = ({ key, text }) => {
return <Emojify key={key} text={text} />;
};
export function NotePreviewModal({ export function NotePreviewModal({
conversation, conversation,
i18n, i18n,
@ -40,7 +46,7 @@ export function NotePreviewModal({
} }
> >
<div dir="auto"> <div dir="auto">
<Linkify text={conversation.note ?? ''} /> <Linkify text={conversation.note ?? ''} renderNonLink={renderNonLink} />
</div> </div>
</Modal> </Modal>
); );

View file

@ -1,12 +1,16 @@
// 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 React from 'react'; import React, { useMemo } from 'react';
import { Emojify } from './conversation/Emojify'; import { Emojify } from './conversation/Emojify';
import { bidiIsolate } from '../util/unicodeBidi';
export function UserText({ text }: { text: string }): JSX.Element { export function UserText({ text }: { text: string }): JSX.Element {
const normalizedText = useMemo(() => {
return bidiIsolate(text);
}, [text]);
return ( return (
<span dir="auto"> <span dir="auto">
<Emojify text={text} /> <Emojify text={normalizedText} />
</span> </span>
); );
} }

View file

@ -16,6 +16,7 @@ import {
areNicknamesEnabled, areNicknamesEnabled,
canHaveNicknameAndNote, canHaveNicknameAndNote,
} from '../../util/nicknames'; } from '../../util/nicknames';
import { Tooltip, TooltipPlacement } from '../Tooltip';
function muted(parts: Array<string | JSX.Element>) { function muted(parts: Array<string | JSX.Element>) {
return ( return (
@ -150,7 +151,7 @@ export function AboutContactModal({
<i className="AboutContactModal__row__icon AboutContactModal__row__icon--profile" /> <i className="AboutContactModal__row__icon AboutContactModal__row__icon--profile" />
{canHaveNicknameAndNote(conversation) && {canHaveNicknameAndNote(conversation) &&
conversation.nicknameGivenName && (conversation.nicknameGivenName || conversation.nicknameFamilyName) &&
conversation.titleNoNickname ? ( conversation.titleNoNickname ? (
<span> <span>
<Intl <Intl
@ -159,7 +160,24 @@ export function AboutContactModal({
components={{ components={{
nickname: <UserText text={conversation.title} />, nickname: <UserText text={conversation.title} />,
titleNoNickname: ( titleNoNickname: (
<UserText text={conversation.titleNoNickname} /> <Tooltip
className="AboutContactModal__TitleWithoutNickname__Tooltip"
direction={TooltipPlacement.Top}
content={
<Intl
i18n={i18n}
id="icu:AboutContactModal__TitleWithoutNickname__Tooltip"
components={{
title: (
<UserText text={conversation.titleNoNickname} />
),
}}
/>
}
delay={0}
>
<UserText text={conversation.titleNoNickname} />
</Tooltip>
), ),
muted, muted,
}} }}

View file

@ -38,7 +38,8 @@ export function ProfileChangeNotification({
contents={<Emojify text={message} />} contents={<Emojify text={message} />}
button={ button={
areNicknamesEnabled() && areNicknamesEnabled() &&
changedContact.nicknameGivenName != null && ( (changedContact.nicknameGivenName != null ||
changedContact.nicknameFamilyName != null) && (
<Button <Button
onClick={handleOpenEditNicknameAndNoteModal} onClick={handleOpenEditNicknameAndNoteModal}
size={ButtonSize.Small} size={ButtonSize.Small}

View file

@ -203,8 +203,8 @@ export async function toContactRecord(
contactRecord.familyName = profileFamilyName; contactRecord.familyName = profileFamilyName;
} }
const nicknameGivenName = conversation.get('nicknameGivenName'); const nicknameGivenName = conversation.get('nicknameGivenName');
if (nicknameGivenName) { const nicknameFamilyName = conversation.get('nicknameFamilyName');
const nicknameFamilyName = conversation.get('nicknameFamilyName'); if (nicknameGivenName || nicknameFamilyName) {
contactRecord.nickname = { contactRecord.nickname = {
given: nicknameGivenName, given: nicknameGivenName,
family: nicknameFamilyName, family: nicknameFamilyName,

View file

@ -4680,7 +4680,7 @@ export function updateLastMessage(
export type NicknameAndNote = ReadonlyDeep<{ export type NicknameAndNote = ReadonlyDeep<{
nickname: { nickname: {
givenName: string; givenName: string | null;
familyName: string | null; familyName: string | null;
} | null; } | null;
note: string | null; note: string | null;