+
= whenToWarnRemainingCount,
+ })}
+ >
{maxLengthCount - lengthCount}
);
@@ -242,7 +256,7 @@ export const Input = forwardRef<
)}
>
{icon ?
{icon}
: null}
- {expandable ? (
+ {isTextarea || forceTextarea ? (
) : (
diff --git a/ts/components/NotePreviewModal.stories.tsx b/ts/components/NotePreviewModal.stories.tsx
new file mode 100644
index 000000000..1a0ebfe49
--- /dev/null
+++ b/ts/components/NotePreviewModal.stories.tsx
@@ -0,0 +1,32 @@
+// Copyright 2024 Signal Messenger, LLC
+// SPDX-License-Identifier: AGPL-3.0-only
+import { action } from '@storybook/addon-actions';
+import * as React from 'react';
+import enMessages from '../../_locales/en/messages.json';
+import type { ComponentMeta } from '../storybook/types';
+import { getDefaultConversation } from '../test-both/helpers/getDefaultConversation';
+import { setupI18n } from '../util/setupI18n';
+import {
+ NotePreviewModal,
+ type NotePreviewModalProps,
+} from './NotePreviewModal';
+
+const i18n = setupI18n('en', enMessages);
+
+export default {
+ title: 'Components/NotePreviewModal',
+ component: NotePreviewModal,
+ argTypes: {},
+ args: {
+ conversation: getDefaultConversation({
+ note: 'Met at UC Berkeley, mutual friends with Katie Hall.\n\nWebsite: https://example.com/',
+ }),
+ i18n,
+ onClose: action('onClose'),
+ onEdit: action('onEdit'),
+ },
+} satisfies ComponentMeta
;
+
+export function Normal(args: NotePreviewModalProps): JSX.Element {
+ return ;
+}
diff --git a/ts/components/NotePreviewModal.tsx b/ts/components/NotePreviewModal.tsx
new file mode 100644
index 000000000..882690350
--- /dev/null
+++ b/ts/components/NotePreviewModal.tsx
@@ -0,0 +1,47 @@
+// Copyright 2024 Signal Messenger, LLC
+// SPDX-License-Identifier: AGPL-3.0-only
+
+import React from 'react';
+import type { ConversationType } from '../state/ducks/conversations';
+import type { LocalizerType } from '../types/I18N';
+import { Button, ButtonVariant } from './Button';
+import { Modal } from './Modal';
+import { Linkify } from './conversation/Linkify';
+
+export type NotePreviewModalProps = Readonly<{
+ conversation: ConversationType;
+ i18n: LocalizerType;
+ onClose: () => void;
+ onEdit: () => void;
+}>;
+
+export function NotePreviewModal({
+ conversation,
+ i18n,
+ onClose,
+ onEdit,
+}: NotePreviewModalProps): JSX.Element {
+ return (
+
+
+
+ >
+ }
+ >
+
+
+
+
+ );
+}
diff --git a/ts/components/ProfileEditor.tsx b/ts/components/ProfileEditor.tsx
index a6835acdb..ee3cc7116 100644
--- a/ts/components/ProfileEditor.tsx
+++ b/ts/components/ProfileEditor.tsx
@@ -330,7 +330,6 @@ export function ProfileEditor({
i18n={i18n}
maxLengthCount={26}
maxByteCount={128}
- whenToShowRemainingCount={0}
onChange={newFirstName => {
setStagedProfile(profileData => ({
...profileData,
@@ -345,7 +344,6 @@ export function ProfileEditor({
i18n={i18n}
maxLengthCount={26}
maxByteCount={128}
- whenToShowRemainingCount={0}
onChange={newFamilyName => {
setStagedProfile(profileData => ({
...profileData,
diff --git a/ts/components/conversation/AboutContactModal.stories.tsx b/ts/components/conversation/AboutContactModal.stories.tsx
index 30d14e809..3cb6a201c 100644
--- a/ts/components/conversation/AboutContactModal.stories.tsx
+++ b/ts/components/conversation/AboutContactModal.stories.tsx
@@ -59,6 +59,7 @@ export default {
args: {
i18n,
onClose: action('onClose'),
+ onOpenNotePreviewModal: action('onOpenNotePreviewModal'),
toggleSignalConnectionsModal: action('toggleSignalConnections'),
toggleSafetyNumberModal: action('toggleSafetyNumberModal'),
updateSharedGroups: action('updateSharedGroups'),
diff --git a/ts/components/conversation/AboutContactModal.tsx b/ts/components/conversation/AboutContactModal.tsx
index 9496b7d2e..8aa4559ce 100644
--- a/ts/components/conversation/AboutContactModal.tsx
+++ b/ts/components/conversation/AboutContactModal.tsx
@@ -11,10 +11,19 @@ import { Modal } from '../Modal';
import { UserText } from '../UserText';
import { SharedGroupNames } from '../SharedGroupNames';
import { About } from './About';
+import { Intl } from '../Intl';
+import { areNicknamesEnabled } from '../../util/nicknames';
+
+function muted(parts: Array) {
+ return (
+ {parts}
+ );
+}
export type PropsType = Readonly<{
i18n: LocalizerType;
onClose: () => void;
+ onOpenNotePreviewModal: () => void;
conversation: ConversationType;
isSignalConnection: boolean;
toggleSignalConnectionsModal: () => void;
@@ -32,6 +41,7 @@ export function AboutContactModal({
updateSharedGroups,
unblurAvatar,
onClose,
+ onOpenNotePreviewModal,
}: PropsType): JSX.Element {
const { isMe } = conversation;
@@ -135,7 +145,26 @@ export function AboutContactModal({
-
+
+ {areNicknamesEnabled() &&
+ conversation.nicknameGivenName &&
+ conversation.titleNoNickname ? (
+
+ ,
+ titleNoNickname: (
+
+ ),
+ muted,
+ }}
+ />
+
+ ) : (
+
+ )}
{!isMe && conversation.isVerified ? (
@@ -166,7 +195,7 @@ export function AboutContactModal({
)}
+ {areNicknamesEnabled() && conversation.note && (
+