mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-11-03 16:16:59 +00:00
fix: keep the vacation reply's plain-text part in step with its HTML after a reload
This commit is contained in:
@@ -78,4 +78,31 @@ describe('HTML auto-reply and its plain-text part', () => {
|
||||
await settle();
|
||||
expect(sends(server)).toBe(1);
|
||||
}, 15_000);
|
||||
|
||||
it('derives the text again after a reload, and keeps it when HTML is switched off', async () => {
|
||||
const server = mockStalwartAccount('b', [], ['vacation'], {
|
||||
vacation: { htmlBody: '<p>Back on 5 May.</p>', textBody: 'Back on 5 May.' },
|
||||
});
|
||||
await openCard(server);
|
||||
expect(body().value).toBe('');
|
||||
fireEvent.change(editor(), { target: { value: '<p>Back on 12 May.</p>' } });
|
||||
await saved(server, 1);
|
||||
expect(lastSent(server)).toMatchObject({ htmlBody: '<p>Back on 12 May.</p>', textBody: 'Back on 12 May.' });
|
||||
|
||||
fireEvent.click(htmlSwitch());
|
||||
expect(body().value).toBe('Back on 12 May.');
|
||||
await saved(server, 2);
|
||||
expect(lastSent(server)).toMatchObject({ htmlBody: null, textBody: 'Back on 12 May.' });
|
||||
}, 15_000);
|
||||
|
||||
it('keeps a plain-text part the user wrote', async () => {
|
||||
const server = mockStalwartAccount('b', [], ['vacation'], {
|
||||
vacation: { htmlBody: '<p>Back on 5 May.</p>', textBody: 'Back soon.' },
|
||||
});
|
||||
await openCard(server);
|
||||
expect(body().value).toBe('Back soon.');
|
||||
fireEvent.change(editor(), { target: { value: '<p>Back on 12 May.</p>' } });
|
||||
await saved(server, 1);
|
||||
expect(lastSent(server)).toMatchObject({ htmlBody: '<p>Back on 12 May.</p>', textBody: 'Back soon.' });
|
||||
}, 15_000);
|
||||
});
|
||||
|
||||
@@ -33,6 +33,11 @@ const STALWART_VACATION_LIMITS = { subject: 511, body: 2047 };
|
||||
const SAVE_AT_ONCE = 0;
|
||||
const SAVE_AFTER_TYPING = 800;
|
||||
|
||||
/** The plain-text part a save derives from the sanitized HTML. */
|
||||
function textFromHtml(sanitizedHtml: string): string {
|
||||
return htmlToPlainText(sanitizedHtml, { paragraphSpacing: true });
|
||||
}
|
||||
|
||||
function byteLength(value: string): number {
|
||||
return new TextEncoder().encode(value).length;
|
||||
}
|
||||
@@ -210,7 +215,11 @@ export function VacationSettings() {
|
||||
setInputZone(timeZone);
|
||||
setHalfFilled({ from: false, to: false });
|
||||
setLocalSubject(stored.subject);
|
||||
setLocalTextBody(stored.textBody);
|
||||
// Text a save derived from the HTML leaves the Body blank, so the next
|
||||
// HTML edit derives it again instead of keeping the old wording.
|
||||
setLocalTextBody(stored.htmlBody && stored.textBody.trim() === textFromHtml(sanitizeEmailHtml(stored.htmlBody)).trim()
|
||||
? ''
|
||||
: stored.textBody);
|
||||
setHtmlEnabled(!!stored.htmlBody);
|
||||
setLocalHtmlBody(stored.htmlBody || '');
|
||||
}
|
||||
@@ -296,10 +305,7 @@ export function VacationSettings() {
|
||||
htmlEnabled && htmlToPlainText(localHtmlBody).trim()
|
||||
? sanitizeEmailHtml(localHtmlBody)
|
||||
: null;
|
||||
const text =
|
||||
localTextBody.trim() || !sanitizedHtml
|
||||
? localTextBody
|
||||
: htmlToPlainText(sanitizedHtml, { paragraphSpacing: true });
|
||||
const text = localTextBody.trim() || !sanitizedHtml ? localTextBody : textFromHtml(sanitizedHtml);
|
||||
return { sanitizedHtml, textBody: text };
|
||||
}, [htmlEnabled, localHtmlBody, localTextBody]);
|
||||
|
||||
@@ -588,7 +594,14 @@ export function VacationSettings() {
|
||||
label={t('message.html_label')}
|
||||
description={t('message.html_description')}
|
||||
>
|
||||
<ToggleSwitch checked={htmlEnabled} onChange={changeNow(setHtmlEnabled)} />
|
||||
<ToggleSwitch
|
||||
checked={htmlEnabled}
|
||||
onChange={changeNow((on: boolean) => {
|
||||
// Switched off, a blank Body keeps the text derived from the HTML.
|
||||
if (!on && !localTextBody.trim()) setLocalTextBody(payload.textBody);
|
||||
setHtmlEnabled(on);
|
||||
})}
|
||||
/>
|
||||
</SettingItem>
|
||||
{htmlEnabled && (
|
||||
<div className="pb-3">
|
||||
|
||||
Reference in New Issue
Block a user