1 import type { ChangeEvent } from 'react';
2 import { useEffect, useRef, useState } from 'react';
4 import { c } from 'ttag';
6 import { Button, Input } from '@proton/atoms';
7 import Editor from '@proton/components/components/editor/Editor';
8 import { useToolbar } from '@proton/components/components/editor/hooks/useToolbar';
9 import type { EditorActions } from '@proton/components/components/editor/interface';
10 import Info from '@proton/components/components/link/Info';
11 import useActiveBreakpoint from '@proton/components/hooks/useActiveBreakpoint';
12 import useApi from '@proton/components/hooks/useApi';
13 import useEventManager from '@proton/components/hooks/useEventManager';
14 import useNotifications from '@proton/components/hooks/useNotifications';
15 import { useLoading } from '@proton/hooks';
16 import { useMailSettings } from '@proton/mail/mailSettings/hooks';
17 import { updateAddress } from '@proton/shared/lib/api/addresses';
18 import { getKnowledgeBaseUrl } from '@proton/shared/lib/helpers/url';
19 import type { Address } from '@proton/shared/lib/interfaces';
20 import { DEFAULT_MAILSETTINGS } from '@proton/shared/lib/mail/mailSettings';
22 import { useHotkeys } from '../../hooks/useHotkeys';
23 import SettingsLayout from '../account/SettingsLayout';
24 import SettingsLayoutLeft from '../account/SettingsLayoutLeft';
25 import SettingsLayoutRight from '../account/SettingsLayoutRight';
27 const EMPTY_VALUES = [/^(<div><br><\/div>)+$/, /^(<div>\s*<\/div>)+$/];
29 const formatSignature = (value: string) => (EMPTY_VALUES.some((regex) => regex.test(value)) ? '' : value);
35 const EditAddressesSection = ({ address }: Props) => {
36 const [mailSettings = DEFAULT_MAILSETTINGS] = useMailSettings();
38 const { call } = useEventManager();
39 const [loading, withLoading] = useLoading();
40 const [editorReady, setEditorReady] = useState(false);
41 const [displayName, setDisplayName] = useState(address.DisplayName);
42 const [signatureUpdated, setSignatureUpdated] = useState(false);
43 const { createNotification } = useNotifications();
44 const { viewportWidth } = useActiveBreakpoint();
46 const editorWrapperRef = useRef<HTMLDivElement>(null);
47 const editorRef = useRef<EditorActions>();
49 const handleReady = (actions: EditorActions) => {
50 actions.setContent(address.Signature);
51 editorRef.current = actions;
55 const handleDisplayName = ({ target }: ChangeEvent<HTMLInputElement>) => {
56 setDisplayName(target.value);
59 const handleSubmit = async () => {
60 const signature = signatureUpdated ? (editorRef.current?.getContent() as string) : address.Signature;
63 updateAddress(address.ID, {
64 DisplayName: displayName,
65 Signature: formatSignature(signature),
69 createNotification({ text: c('Success').t`Address updated` });
72 useHotkeys(editorWrapperRef, [
76 if (mailSettings.Shortcuts) {
77 void withLoading(handleSubmit());
85 setDisplayName(address.DisplayName);
87 if (editorRef?.current && editorReady) {
88 setSignatureUpdated(false);
89 editorRef.current.setContent(address.Signature);
94 const { openEmojiPickerRef, toolbarConfig, setToolbarConfig, modalLink, modalImage, modalDefaultFont } = useToolbar(
100 onSubmit={async (e) => {
102 await withLoading(handleSubmit());
107 <label htmlFor="displayName" className="text-semibold">
108 {c('Label').t`Display name`}
110 </SettingsLayoutLeft>
111 <SettingsLayoutRight>
115 placeholder={c('Placeholder').t`Choose display name`}
116 onChange={handleDisplayName}
117 data-testid="settings:identity-section:display-name"
119 </SettingsLayoutRight>
122 <SettingsLayout stackEarlier className="max-w-custom" style={{ '--max-w-custom': '49em' }}>
124 {/* eslint-disable-next-line */}
125 <label htmlFor="editor" className="text-semibold" onClick={() => editorRef.current?.focus()}>
126 <span className="mr-2">{c('Label').t`Signature`}</span>
128 url={getKnowledgeBaseUrl('/display-name-email-signature')}
129 title={c('Tooltip').t`Click here to learn how to create a customized signature with HTML.`}
132 </SettingsLayoutLeft>
133 <SettingsLayoutRight>
134 <div ref={editorWrapperRef} tabIndex={-1}>
136 onReady={handleReady}
138 setSignatureUpdated(true);
141 openEmojiPickerRef={openEmojiPickerRef}
142 toolbarConfig={toolbarConfig}
143 setToolbarConfig={setToolbarConfig}
144 modalLink={modalLink}
145 modalImage={modalImage}
146 modalDefaultFont={modalDefaultFont}
147 isSmallViewportForToolbar={viewportWidth['<=medium']}
148 mailSettings={mailSettings}
158 data-testid="settings:identity-section:update"
160 {c('Action').t`Update`}
162 </SettingsLayoutRight>
168 export default EditAddressesSection;