Skip to content

feat: a new message has no header title, and the Attach sheet shows icons #137 - #138

Merged
rathlinus merged 3 commits into
bulwarkmail:mainfrom
wmcparla:feat/compose-attach-menu-icons
Nov 15, 2026
Merged

rathlinus merged 3 commits into
bulwarkmail:mainfrom
wmcparla:feat/compose-attach-menu-icons

Conversation

@wmcparla

Copy link
Copy Markdown
Contributor

Summary

Two finishing touches to the composer from #137. A new message no longer shows "New Message" in its header, because the empty fields below already say what the screen is. The Attach sheet gets an icon on each row, and the two file sources get names that tell them apart: "This device" for the phone's files and "Bulwark Files" for the user's Files on the server. Before, they read "Upload from this device" and "Attach from Files", which looked like the same thing twice.

Changes

  • Header: a new message, including a draft reopened from Drafts, has no visible title. Reply, Reply All and Forward keep theirs, and the draft status line still shows under it.
    • Screen readers still hear the webmail's "New message" (email_composer.new_message, already in every locale), followed by the draft status. The title area stretches to the header's height when it is empty; without that it had no height and TalkBack skipped it.
    • The header has a testID, compose-header, for the Maestro flows.
  • Attach sheet: the composer's SheetOption takes an optional icon node, as ActionSheetItem does. The icons match the attachment action sheet (18 px, textSecondary): image, camera, phone, and the FolderOpen that "Save to Files" uses.
  • Labels:
    • On Android: Gallery, Camera, This device, Bulwark Files. Bulwark Files only shows when the server keeps Files, as before.
    • On iOS the first row keeps "Photos & Videos", since iOS calls its library Photos.
    • Without server Files, the third row still reads "This device", not "Files", so its name no longer depends on the server.
  • Strings: three new keys in locales/rn/*.json for every locale: attach_gallery, attach_this_device, attach_bulwark_files.
    • "This device" is the webmail's settings.notifications.push.device_this, and the "Files" in "Bulwark Files" is its sidebar.files.
    • The word for Gallery and the word order around "Bulwark" are machine-made. In ar, he and fa the brand comes after the noun, so the label runs right to left.
  • Maestro: 03-compose-send, 08-scheduled-send and perf/3-compose waited for "New Message"; they now wait for id: compose-header. The compose flow asserts "This device" instead of "Upload from this device|Files".
  • Test: compose-send-queue-wiring.test.ts cut the send code at const titleKey, which is gone; it now cuts at const headerTitle. Without that change it still passed, but it searched the rest of the file.

Related issues

Closes #137

Type of change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update
  • Refactor / code quality improvement
  • Chore / dependency update / CI change

Checklist

  • I have read the Contributing Guide
  • My code follows the project's code style and conventions
  • I have run npm run typecheck and there are no errors (native has no lint script)
  • The build passes (no npm run build in native; an x86_64 release APK, assembleGithubRelease -PallowDebugSignedRelease=true, builds and runs)
  • I have tested my changes locally
  • I have added or updated documentation if needed (none needed)
  • I have updated translations (locales/) if my changes affect user-facing text (every locale in locales/rn; npm run i18n:check passes)
  • I have included screenshots or a screen recording for UI changes

Tests: npx vitest run: 7103 passed, 163 skipped (the live Stalwart suites), 0 failed.

Tested by hand on the Android 16 emulator (1080x2424, 420 dpi), with an account whose server keeps Files:

  • A new message shows no title, and the view hierarchy has a focusable header node labelled "New message".
  • A reply still shows "Reply".
  • Each row opens its picker:
    • Gallery: the system photo picker
    • Camera: unchanged
    • This device: the system document picker
    • Bulwark Files: the Files sheet
  • An Android copy of the flows' new steps (wait for id: compose-header, open Attach, check the four rows, Cancel, wait again) passes.

Not tested: iOS. The id: compose-header selector is the flows' first on a plain View rather than a button or input; RN sets accessibilityIdentifier from testID, so XCUITest should list it, but one run of 03-compose-send on the simulator would confirm it.

Screenshots / demo

New message Attach
Composer with no title in the header Attach sheet: Gallery, Camera, This device, Bulwark Files, each with an icon

Notes for reviewers

  • The Files picker sheet keeps its title, "Attach from Files". That's the webmail's email_composer.attach_from_files, and in the picker it reads fine.
  • No old key is dropped: attach_photos stays in use on iOS, and the rest live in the vendored webmail catalogs.

🤖 Generated with Claude Code

…cons

The composer header read "New Message" above fields that already say
what the screen is; a new message now leaves it empty. Reply, Reply All
and Forward keep their titles, and the draft status line still shows.

The Attach sheet rows get icons (image, camera, phone, folder) and
names that tell the two file sources apart: "This device" opens the
system file picker, "Bulwark Files" the user's Files on the server.
Before, the pair read "Upload from this device" and "Attach from
Files", which looked like the same thing twice. On Android the photo
library is "Gallery"; iOS keeps "Photos & Videos".

The three new strings are in every locale under locales/rn: "This
device" and "Files" reuse the webmail's own translations, the word for
Gallery is machine-made.
…lwarkmail#137

A new message has no header title any more, so the flows that waited
for "New Message" wait for the header's testID, compose-header, and
the compose flow asserts "This device" instead of the old file label.
The sheet's icon is a ready node, as in ActionSheetItem.
…eads naturally in each language bulwarkmail#137

With no visible title, the header's title area was empty and had no
height, so TalkBack skipped it. It now stretches to the header and reads
the webmail's "New message", with the draft status after it.

The Files row followed the English word order everywhere; each locale
now puts "Bulwark" where its own grammar does (ar, he, fa after the
noun, so the label also runs right to left).

The offline-send wiring test cut the send code at `const titleKey`,
which is gone; it cuts at `const headerTitle` now.
@wmcparla
wmcparla marked this pull request as ready for review November 13, 2026 22:35
@bulwark-warden

Copy link
Copy Markdown

I found no problems in this change, and the test check passed (CI run).

  • Icons: Camera, FolderOpen and Smartphone are all exported from src/components/icons/index.ts. The "Save to Files" action in AttachmentChips.tsx also uses FolderOpen at 18 px in textSecondary.
  • Row layout: scheduleRow already sets flexDirection: 'row' and a gap (ComposeScreen.tsx). OptionsSheet renders opt.icon in that row, right before the label.
  • Maestro: 03-compose-send is written for the iOS simulator. Its comments mention XCTest and boot-sim.sh (03-compose-send.yaml), and on iOS the first row still reads "Photos & Videos" (the Platform.OS === 'ios' branch). On main, the only flows that wait for "New Message" are the three this PR changes.

Bulwark Warden is an AI assistant and can be wrong. It answers from the docs, the code and earlier issues, and links its sources.

@rathlinus
rathlinus merged commit 676bbd6 into bulwarkmail:main Nov 15, 2026
1 check passed
@rathlinus

Copy link
Copy Markdown
Member

Thanks, merged. Main had moved the photo picker steps of 03-compose-send into subflows/pick-photo.yaml since you branched, so I switched that subflow to compose-header as well, and added the three strings for Greek, Nynorsk and Vietnamese, which came to main in the meantime.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: A cleaner composer header, and an Attach sheet with icons and clearer names

2 participants