From 05df758d0a6593cdacb843527fd9ed13047331e2 Mon Sep 17 00:00:00 2001 From: jcoffey <51408202+jcoffey-dev@users.noreply.github.com> Date: Sat, 19 Sep 2026 14:06:18 -0700 Subject: [PATCH] Open the composer full screen, as a setting (#401) (#404) Settings > General > Composing has a new switch, "Open the composer full screen". With it on, every new composer, whether a new message, reply, forward or reopened draft, starts maximized. Restore still shrinks it to a window. A draft put back after an undone or failed send keeps the size it had. It's off by default, and on a phone, where the composer already fills the screen, it changes nothing. One new string, translated in all nine catalogs. The count falling back to English stays at 16 in every language. Fixes #401 --- FEATURES.md | 4 +- web/src/locales/de.ts | 1 + web/src/locales/es.ts | 1 + web/src/locales/fr.ts | 1 + web/src/locales/ja.ts | 1 + web/src/locales/nl.ts | 1 + web/src/locales/pt-BR.ts | 1 + web/src/locales/ru.ts | 1 + web/src/locales/uk.ts | 1 + web/src/locales/zh-Hans.ts | 1 + .../__tests__/compose-start-maximized.test.ts | 41 +++++++++++++++++++ web/src/store/compose.ts | 2 +- web/src/store/settings.ts | 6 +++ web/src/views/settings/GeneralSettings.tsx | 1 + 14 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 web/src/store/__tests__/compose-start-maximized.test.ts diff --git a/FEATURES.md b/FEATURES.md index bf67894..3f1c2a1 100644 --- a/FEATURES.md +++ b/FEATURES.md @@ -482,6 +482,8 @@ minimizable and maximizable; full-screen on mobile. uploaded, which it was not being. - **Attachment reminder** when the text mentions an attachment and none is there. - **Spell check** toggle. +- **Open the composer full screen**, as a setting, for anyone whose first + move is always Maximize. Off by default; on a phone it changes nothing. - **Drafts** save as you type and on close, with the save state shown. - **Quoting** on reply, with the signature placed above or below it, and reply-all as an optional default. @@ -921,7 +923,7 @@ not reach another that already has ihasmail open until it signs in again. | Section | Holds | | --- | --- | -| **General** | Reading pane, mark-as-read delay, auto-advance, conversation view, snippets, avatars; compose format, quoting, signature placement, spell check; time zone, week start, language & region, date format, time format; `mailto:` handler; export / import / reset | +| **General** | Reading pane, mark-as-read delay, auto-advance, conversation view, snippets, avatars; compose format, quoting, signature placement, spell check, full-screen composer; time zone, week start, language & region, date format, time format; `mailto:` handler; export / import / reset | | **Privacy & safety** | Remote images and the senders trusted with them, read receipts asked for and answered; the three warnings and the domains they measure against; undo-send window, attachment reminder, confirm-before-delete | | **Appearance** | Theme, accent color, density, font size, sidebar, swipe actions, interface language | | **Identities & signatures** | Addresses, names, Reply-To, HTML signatures, the default, and which to hide from the picker | diff --git a/web/src/locales/de.ts b/web/src/locales/de.ts index 7137239..242ce90 100644 --- a/web/src/locales/de.ts +++ b/web/src/locales/de.ts @@ -754,6 +754,7 @@ export const catalog: Catalog = { "Attachment reminder": "Anhang-Erinnerung", "Warn when the message mentions an attachment but none is attached.": "Warnen, wenn die Nachricht einen Anhang erwähnt, aber keiner angehängt ist.", "Spell check while typing": "Rechtschreibprüfung während der Eingabe", + "Open the composer full screen": "Nachrichten im Vollbild verfassen", "Confirm before deleting": "Vor dem Löschen bestätigen", "Show message snippets": "Nachrichtenvorschau anzeigen", "Preview the first line of each message in the list.": "Die erste Zeile jeder Nachricht in der Liste anzeigen.", diff --git a/web/src/locales/es.ts b/web/src/locales/es.ts index 344377f..ca5d12d 100644 --- a/web/src/locales/es.ts +++ b/web/src/locales/es.ts @@ -749,6 +749,7 @@ export const catalog: Catalog = { "Attachment reminder": "Aviso de adjunto", "Warn when the message mentions an attachment but none is attached.": "Avisar cuando el mensaje menciona un adjunto pero no hay ninguno.", "Spell check while typing": "Corrección ortográfica al escribir", + "Open the composer full screen": "Redactar mensajes a pantalla completa", "Confirm before deleting": "Confirmar antes de eliminar", "Show message snippets": "Mostrar un fragmento de los mensajes", "Preview the first line of each message in the list.": "Mostrar la primera línea de cada mensaje en la lista.", diff --git a/web/src/locales/fr.ts b/web/src/locales/fr.ts index 5af24b0..873f263 100644 --- a/web/src/locales/fr.ts +++ b/web/src/locales/fr.ts @@ -755,6 +755,7 @@ export const catalog: Catalog = { "Attachment reminder": "Rappel de pièce jointe", "Warn when the message mentions an attachment but none is attached.": "Avertir lorsque le message mentionne une pièce jointe alors qu'aucune n'est jointe.", "Spell check while typing": "Vérification orthographique pendant la saisie", + "Open the composer full screen": "Rédiger les messages en plein écran", "Confirm before deleting": "Confirmer avant de supprimer", "Show message snippets": "Afficher un aperçu des messages", "Preview the first line of each message in the list.": "Afficher la première ligne de chaque message dans la liste.", diff --git a/web/src/locales/ja.ts b/web/src/locales/ja.ts index 193d3a2..6756140 100644 --- a/web/src/locales/ja.ts +++ b/web/src/locales/ja.ts @@ -749,6 +749,7 @@ export const catalog: Catalog = { "Attachment reminder": "添付忘れの確認", "Warn when the message mentions an attachment but none is attached.": "本文で添付に触れているのにファイルが添付されていないとき警告します。", "Spell check while typing": "入力中にスペルチェックする", + "Open the composer full screen": "メールを全画面で作成", "Confirm before deleting": "削除前に確認する", "Show message snippets": "本文の抜粋を表示する", "Preview the first line of each message in the list.": "一覧に各メールの 1 行目を表示します。", diff --git a/web/src/locales/nl.ts b/web/src/locales/nl.ts index d6bb8eb..d2e9ecd 100644 --- a/web/src/locales/nl.ts +++ b/web/src/locales/nl.ts @@ -747,6 +747,7 @@ export const catalog: Catalog = { "Attachment reminder": "Bijlageherinnering", "Warn when the message mentions an attachment but none is attached.": "Waarschuwen wanneer het bericht een bijlage noemt maar er geen is bijgevoegd.", "Spell check while typing": "Spellingcontrole tijdens het typen", + "Open the composer full screen": "Berichten opstellen op volledig scherm", "Confirm before deleting": "Bevestigen voor verwijderen", "Show message snippets": "Berichtfragmenten tonen", "Preview the first line of each message in the list.": "De eerste regel van elk bericht in de lijst tonen.", diff --git a/web/src/locales/pt-BR.ts b/web/src/locales/pt-BR.ts index 28786b5..c9fe6b3 100644 --- a/web/src/locales/pt-BR.ts +++ b/web/src/locales/pt-BR.ts @@ -752,6 +752,7 @@ export const catalog: Catalog = { "Attachment reminder": "Aviso de anexo", "Warn when the message mentions an attachment but none is attached.": "Avisar quando a mensagem mencionar um anexo mas nenhum estiver anexado.", "Spell check while typing": "Verificação ortográfica ao digitar", + "Open the composer full screen": "Escrever mensagens em tela cheia", "Confirm before deleting": "Confirmar antes de excluir", "Show message snippets": "Mostrar um trecho das mensagens", "Preview the first line of each message in the list.": "Mostrar a primeira linha de cada mensagem na lista.", diff --git a/web/src/locales/ru.ts b/web/src/locales/ru.ts index 386f5d6..19931af 100644 --- a/web/src/locales/ru.ts +++ b/web/src/locales/ru.ts @@ -752,6 +752,7 @@ export const catalog: Catalog = { "Attachment reminder": "Напоминание о вложении", "Warn when the message mentions an attachment but none is attached.": "Предупреждать, если письмо упоминает вложение, но его нет.", "Spell check while typing": "Проверять орфографию при вводе", + "Open the composer full screen": "Писать письма во весь экран", "Confirm before deleting": "Спрашивать перед удалением", "Show message snippets": "Показывать начало письма", "Preview the first line of each message in the list.": "Показывать первую строку каждого письма в списке.", diff --git a/web/src/locales/uk.ts b/web/src/locales/uk.ts index 2d202ce..e4600f5 100644 --- a/web/src/locales/uk.ts +++ b/web/src/locales/uk.ts @@ -746,6 +746,7 @@ export const catalog: Catalog = { "Attachment reminder": "Нагадування про вкладення", "Warn when the message mentions an attachment but none is attached.": "Попереджати, якщо лист згадує вкладення, але його немає.", "Spell check while typing": "Перевіряти орфографію під час введення", + "Open the composer full screen": "Писати листи на весь екран", "Confirm before deleting": "Питати перед видаленням", "Show message snippets": "Показувати початок листа", "Preview the first line of each message in the list.": "Показувати перший рядок кожного листа у списку.", diff --git a/web/src/locales/zh-Hans.ts b/web/src/locales/zh-Hans.ts index 425eac0..192b8c5 100644 --- a/web/src/locales/zh-Hans.ts +++ b/web/src/locales/zh-Hans.ts @@ -748,6 +748,7 @@ export const catalog: Catalog = { "Attachment reminder": "附件提醒", "Warn when the message mentions an attachment but none is attached.": "邮件提到附件但未添加时提醒。", "Spell check while typing": "输入时检查拼写", + "Open the composer full screen": "全屏写邮件", "Confirm before deleting": "删除前确认", "Show message snippets": "显示邮件摘要", "Preview the first line of each message in the list.": "在列表中显示每封邮件的首行。", diff --git a/web/src/store/__tests__/compose-start-maximized.test.ts b/web/src/store/__tests__/compose-start-maximized.test.ts new file mode 100644 index 0000000..345db45 --- /dev/null +++ b/web/src/store/__tests__/compose-start-maximized.test.ts @@ -0,0 +1,41 @@ +import { beforeEach, describe, expect, it } from "vitest"; +import { useCompose } from "@/store/compose"; +import { useMail } from "@/store/mail"; +import { DEFAULT_SETTINGS, useSettings } from "@/store/settings"; + +/** + * "Open the composer full screen" (#401): the size a new composer starts at. + * + * Only new composers follow it. A draft put back after an undone or failed + * send keeps the size it had, since that is the window somebody was already + * looking at. + */ + +beforeEach(() => { + useCompose.setState({ drafts: [], activeKey: null, pendingSends: {} }); + useMail.setState({ accountId: "a1", identities: [] as never }); + useSettings.setState({ settings: { ...DEFAULT_SETTINGS } }); +}); + +const opened = () => { + const key = useCompose.getState().open(); + return useCompose.getState().drafts.find((d) => d.key === key)!; +}; + +describe("the size a new composer opens at", () => { + it("is the usual window by default", () => { + expect(opened().maximized).toBe(false); + }); + + it("is full screen with the setting on", () => { + useSettings.setState((s) => ({ settings: { ...s.settings, composeMaximized: true } })); + expect(opened().maximized).toBe(true); + }); + + it("can still be restored to a window once open", () => { + useSettings.setState((s) => ({ settings: { ...s.settings, composeMaximized: true } })); + const d = opened(); + useCompose.getState().update(d.key, { maximized: false }); + expect(useCompose.getState().drafts.find((x) => x.key === d.key)!.maximized).toBe(false); + }); +}); diff --git a/web/src/store/compose.ts b/web/src/store/compose.ts index 6944a9b..b224642 100644 --- a/web/src/store/compose.ts +++ b/web/src/store/compose.ts @@ -137,7 +137,7 @@ function blankDraft(init: Partial = {}): Draft { showBcc: false, showReplyTo: false, minimized: false, - maximized: false, + maximized: s.composeMaximized, dirty: false, savedAt: null, saving: false, diff --git a/web/src/store/settings.ts b/web/src/store/settings.ts index 952c93e..f9b359f 100644 --- a/web/src/store/settings.ts +++ b/web/src/store/settings.ts @@ -251,6 +251,11 @@ export interface Settings { archiveOnReply: boolean; autoAdvance: "newer" | "older" | "list"; spellcheck: boolean; + /** + * Open every new composer full screen (#401). Desktop only: on a phone the + * composer fills the screen already and has no size to choose. + */ + composeMaximized: boolean; sendAndArchive: boolean; /** Width (px) of the message list when the reading pane is on the right. */ listPaneWidth: number; @@ -376,6 +381,7 @@ export const DEFAULT_SETTINGS: Settings = { archiveOnReply: false, autoAdvance: "list", spellcheck: true, + composeMaximized: false, sendAndArchive: false, listPaneWidth: 520, listPaneHeight: 340, diff --git a/web/src/views/settings/GeneralSettings.tsx b/web/src/views/settings/GeneralSettings.tsx index 67d4cfb..69c758b 100644 --- a/web/src/views/settings/GeneralSettings.tsx +++ b/web/src/views/settings/GeneralSettings.tsx @@ -183,6 +183,7 @@ export function GeneralSettings() { update({ includeQuote: v })} label={t("Quote original message in replies")} /> update({ signatureAboveQuote: v })} label={t("Place signature above quoted text")} /> update({ spellcheck: v })} label={t("Spell check while typing")} /> + update({ composeMaximized: v })} label={t("Open the composer full screen")} />

{t("Locale")}