Commit Graph
883 Commits
Author SHA1 Message Date
jcoffey-dev 20ac83c8df Name Coffey Labs LLC as the copyright holder
ci / node (pull_request) Skipped
ci / version (pull_request) Skipped
github/ci (branch) GitHub Actions
ci / github (pull_request) Successful in 2m5s
ci / docker-build (pull_request) Skipped
ci / publish (pull_request) Skipped
ci / announce (pull_request) Skipped
Coffey Labs is now Coffey Labs LLC, an Arizona limited liability company. Copyright lines and SPDX-FileCopyrightText headers naming Coffey Labs or John Coffey now name Coffey Labs LLC. Upstream copyright notices are unchanged.
2026-10-05 23:33:07 -07:00
jcoffey-dev a58ea326d9 Merge pull request 'Notifications with the app closed, for every signed-in account' (#53) from feat/other-accounts-push-b into main
ci / node (push) Skipped
ci / version (push) Skipped
github/ci (branch) GitHub Actions
ci / github (push) Successful in 2m24s
ci / docker-build (push) Skipped
ci / publish (push) Skipped
ci / announce (push) Skipped
2026-10-06 03:42:31 +00:00
jcoffey-dev 9fcf4812f3 Notifications with the app closed, for every signed-in account
ci / node (pull_request) Skipped
ci / version (pull_request) Skipped
github/ci (branch) GitHub Actions
ci / github (pull_request) Successful in 3m3s
ci / docker-build (pull_request) Skipped
ci / publish (pull_request) Skipped
ci / announce (pull_request) Skipped
Second of three for background push across accounts (multi-account
spec, MA-8 part 2).

Turning on "Notify me even when inbuxa is closed" now registers this
browser in every signed-in account, each through its own session (the
route from the previous change), and renewal keeps them all current.
GET /api/auth/accounts says which mail account each session is, so the
subscription can name it. The remembered endpoint is kept per account,
and survives the clean-up that follows switching accounts.

The service worker is told who the other accounts are. A push for one
of them is titled with that account's address, shown even while a tab
is focused (the tab only shows the front account's mail), and its
Mark read and Archive act through that account's session. Clicking it
brings that account to the front and opens the message. While push is
on, the tab's own polling of other accounts stops notifying, so nothing
arrives twice.

Signing out of one account removes this device's subscription there
only; signing out of all, or turning push off, removes every one.

Also fixes where every background notification opened: the worker
linked to /mail/inbox/<thread>, and the route takes a mailbox id there,
so a click landed on the inbox list with "That folder no longer
exists". The worker now gets each account's inbox id and links to the
message.

Checked end to end in Chrome against a local server with two accounts:
both registered and verified, a message to the account not in front
showed a notification under its address, and clicking it switched
accounts and opened the message. No new strings. typecheck, tests
(web 1547, server 279) and build pass.
2026-10-05 20:38:44 -07:00
jcoffey-dev 13c9b8ef91 Merge pull request 'A narrow route to another signed-in account, for its push subscription' (#52) from feat/other-accounts-push into main
ci / node (push) Skipped
ci / version (push) Skipped
github/ci (branch) GitHub Actions
ci / github (push) Successful in 2m23s
ci / docker-build (push) Skipped
ci / publish (push) Skipped
ci / announce (push) Skipped
2026-10-06 03:27:03 +00:00
jcoffey-dev 6b979c5ac7 A narrow route to another signed-in account, for its push subscription
ci / node (pull_request) Skipped
ci / version (pull_request) Skipped
github/ci (branch) GitHub Actions
ci / github (pull_request) Successful in 2m24s
ci / docker-build (pull_request) Skipped
ci / publish (pull_request) Skipped
ci / announce (pull_request) Skipped
First of three for notifications with the app closed, for every
signed-in account (multi-account spec, MA-8 part 2). No behavior
changes yet.

A JMAP push subscription belongs to whoever signs the request, so an
account that isn't in front can only have one registered, verified and
renewed through its own session. POST /api/auth/accounts/<sessionId>/jmap
forwards to the mail server as that session, when it is one of this
browser's other accounts, and only for PushSubscription/get and /set,
Mailbox/get, and Email/set limited to keywords and mailboxIds updates
(what a notification's Archive and Mark read need). Anything else is
403; the account in front, or a session this browser doesn't hold, is
404. Its OAuth token is renewed first if due. The browser already holds
the session, so nothing new becomes reachable.

On the web app side the push helpers (list, create, extend, destroy,
verify) take a JMAP caller, defaulting to the account in front exactly
as before, and lib/notify/otherAccount gives the caller for another
account through the route.

Tests: the allowlist, the route end to end with two accounts (allowed,
refused, front and unknown sessions), and the caller. The accounts test
file now raises LOGIN_RATE_LIMIT, since it signs in more often from one
address than the default allows. typecheck, tests (web 1543, server
278) and build pass.
2026-10-05 20:24:18 -07:00
jcoffey-dev 8acd30e8a1 Merge pull request 'New mail in the other signed-in accounts: counts, a dot, and a notification' (#51) from feat/other-accounts-unread into main
ci / node (push) Skipped
ci / version (push) Skipped
github/ci (branch) GitHub Actions
ci / github (push) Successful in 3m2s
ci / docker-build (push) Skipped
ci / publish (push) Skipped
ci / announce (push) Skipped
2026-10-06 03:12:56 +00:00
jcoffey-dev 5f27923ce6 New mail in the other signed-in accounts: counts, a dot, and a notification
ci / node (pull_request) Skipped
ci / version (pull_request) Skipped
ci / docker-build (pull_request) Skipped
ci / publish (pull_request) Skipped
github/ci (branch) GitHub Actions
ci / github (pull_request) Successful in 2m24s
ci / announce (pull_request) Skipped
With more than one account signed in (#49), mail arriving in one that
isn't in front went unseen until someone switched to it (multi-account
spec, MA-8).

- GET /api/auth/accounts/unread answers the Inbox unread count of each
  account not in front, asked through that account's own session (its
  OAuth token renewed first if due), kept a minute per account.
- The web app asks every two minutes while another account is signed
  in. The account menu shows each one's count beside its name, and the
  avatar carries a dot when any of them has unread mail.
- When a count rises while the app is open and desktop notifications
  are on, a notification names the account ("New mail for
  [email protected]"); clicking it switches to that account. An
  account seen for the first time doesn't notify: its mail was already
  there.

Not in this change: notifications with the app closed, which need each
added account's own Web Push subscription.

New strings (3, English only in the other ten catalogs): "New mail for
{name}", "Unread in the Inbox: {count}", "Account: new mail in another
account". Tests: the server answers the other account's count and
nothing when alone; the client keeps the counts, notifies only on a
rise and only with notifications on. Checked in Chrome against the
mock. typecheck, tests (web 1541, server 277) and build pass.
2026-10-05 20:10:07 -07:00
jcoffey-dev 68c91a1ad4 Merge pull request 'Ten translations: count Turkish where the repo states the number' (#50) from docs/ten-translations into main
ci / node (push) Skipped
ci / version (push) Skipped
github/ci (branch) GitHub Actions
ci / github (push) Successful in 2m15s
ci / docker-build (push) Skipped
ci / publish (push) Skipped
ci / announce (push) Skipped
2026-10-06 02:33:55 +00:00
jcoffey-dev 9e77fb3f47 Ten translations: count Turkish where the repo states the number
ci / node (pull_request) Skipped
ci / version (pull_request) Skipped
github/ci (branch) GitHub Actions
ci / github (pull_request) Successful in 2m30s
ci / docker-build (pull_request) Skipped
ci / publish (pull_request) Skipped
ci / announce (pull_request) Skipped
Turkish shipped (ihasmail #32/#37), so ten languages ship alongside English, not nine. CONTRIBUTING.md, the PR template and the emlName.ts comment said nine; ROADMAP.md and the i18n-literals.mjs comment describe what shipped on 2026-08-31 and stay as they are. Translations: no user-visible strings added or changed, so no catalog work.
2026-10-05 19:30:40 -07:00
jcoffey-dev 351a5aa01d Merge pull request 'Account switcher: more than one account signed in at once' (#49) from feat/account-switcher into main
ci / node (push) Skipped
ci / version (push) Skipped
github/ci (branch) GitHub Actions
ci / github (push) Successful in 2m25s
ci / docker-build (push) Skipped
ci / publish (push) Skipped
ci / announce (push) Skipped
2026-10-06 01:47:37 +00:00
jcoffey-dev 34baca4365 Account switcher: more than one account signed in at once
ci / node (pull_request) Skipped
ci / version (pull_request) Skipped
github/ci (branch) GitHub Actions
ci / github (pull_request) Successful in 2m26s
ci / docker-build (pull_request) Skipped
ci / publish (pull_request) Skipped
ci / announce (pull_request) Skipped
Someone who looks after several mailboxes of their own can now keep
them all signed in in one browser and move between them from the
account menu, without signing out (multi-account spec, MA-B; forum
topic 75).

How it holds them. The session cookie is unchanged: it is the account
in front, and every request is answered with it, so nothing else in the
server changes. The others ride in a second cookie, <name>_more, as a
list of their own session cookies. Each session stays its own -- sealed
credential, expiry and "this is my device" -- and nothing about one is
read through another. At most 5 in all, all on this mail server.

- Add account (account menu): with sign-in on the mail server's page
  it goes there with prompt=login, so the server asks again rather than
  reuse the first sign-in; with the password form, a small dialog asks.
  Refused, and the front stays, when either account's organization has
  addAccounts off (inbuxa:SharingPolicy), the account is on another
  server, or 5 are open. The same account again just comes to the
  front.
- Switching (POST /api/auth/accounts/<id>/front) swaps it into front;
  the web app clears what it cached for the previous account and
  reloads. A message being written blocks the switch.
- Sign out ends only the account in front, and the next one comes
  forward; Sign out of all accounts ends every one.
- GET /api/auth/accounts lists them, the front first, and says whether
  one more may be added.

Not in this change: unread counts and notifications for the accounts
not in front (MA-8), which the spec puts last.

The mock can sign in a second user (MOCK_SECOND_USER/PASS) and answer
addAccounts false (MOCK_NO_ADD_ACCOUNTS), for the new server tests:
two accounts joining, switching, the same account twice, a switch to a
session it doesn't hold, signing out of one and of all, and an
organization that forbids it; and the OAuth start asking prompt=login.
The client tests cover listing, switching (cache cleared, reload) and
both sign-outs. Checked in Chrome against the mock: add, switch, sign
out of one.

New strings (9, English only in the other ten catalogs): "Add
account", "Sign out of all accounts", "Add an account", "Both accounts
stay signed in here; switch between them from this menu.", "Working…",
"That account couldn't be added.", "You can't add more accounts here.",
and the other-server and organization refusals. typecheck, tests (web
1538, server 276) and build pass.
2026-10-05 18:44:45 -07:00
jcoffey-dev 9f53759462 Merge pull request 'Show an assigned shared mailbox as shared, not as a locked account' (#48) from feat/shared-mailbox-kind into main
ci / version (push) Skipped
ci / github (push) Skipped
github/ci (branch) GitHub Actions
ci / node (push) Successful in 2m45s
ci / publish (push) Skipped
ci / announce (push) Skipped
ci / docker-build (push) Successful in 23s
2026-10-05 22:18:41 +00:00
jcoffey-dev c66a8aadd7 Show an assigned shared mailbox as shared, not as a locked account
ci / version (pull_request) Skipped
ci / github (pull_request) Skipped
ci / node (pull_request) Successful in 1m29s
ci / publish (pull_request) Skipped
ci / announce (pull_request) Skipped
ci / docker-build (pull_request) Successful in 36s
github/ci (branch) GitHub Actions
The server now marks a shared mailbox (support@, legal@) as a
delegation of kind "sharedMailbox" (multi-account spec, MA-S). Without
this, the webmail would show one exactly as it shows a locked account:
a red bar, a padlock in the tab and on the brand, and its calendars and
files in place of the reader's own.

Now such a mailbox is listed with the other shared mailboxes under
"Mail to show", opens with the shared bar, which also gives the
person's access level and whether they can send as it, and changes
mail only. Its access level still applies exactly as a lock's does:
read changes nothing, organize never deletes, no sending without
send-as. Found without asking Mailbox/get, since the server's mark says
it is mail.

A server that sends no kind is treated as before: every delegation is a
lock. No new strings. typecheck and vitest (174 files, 1534 tests)
pass.
2026-10-05 15:15:57 -07:00
jcoffey-dev 7f12a7d8ee Merge pull request 'Open a group's mailbox, or folders someone shared, from the account menu' (#47) from feat/shared-mail into main
ci / version (push) Skipped
ci / github (push) Skipped
github/ci (branch) GitHub Actions
ci / node (push) Successful in 3m1s
ci / publish (push) Skipped
ci / announce (push) Skipped
ci / docker-build (push) Successful in 16s
2026-10-05 21:52:10 +00:00
jcoffey-dev 722a68432c Open a group's mailbox, or folders someone shared, from the account menu
ci / version (pull_request) Skipped
ci / github (pull_request) Skipped
ci / node (pull_request) Successful in 1m29s
ci / publish (pull_request) Skipped
ci / announce (pull_request) Skipped
ci / docker-build (pull_request) Successful in 41s
github/ci (branch) GitHub Actions
A group's members, and anyone a folder was shared with, could reach that
mail over IMAP but not here: Mail read only the reader's own account.
Calendar, Contacts and Files already list other people's shares; Mail
now does too (multi-account spec, MA-A).

Such an account is listed under "Mail to show" in the account menu,
after any locked account handed to the reader, and opens in place of
the reader's own mail through the same switch AL-7 uses. Only accounts
whose Mailbox/get answers with a mailbox are offered: the server
advertises every capability on any shared account, so a colleague who
shared one calendar would otherwise appear with mail.

While one is in view:

- a bar in the palette's accent (not the locked account's red) names
  it, with "Back to my mail"; the tab title names it without a padlock;
- calendars, contacts and files stay the reader's own (viewAccountFor
  follows only a delegation now);
- writing a message uses the viewed account's identities, so a reply in
  support@ goes out as support@ and is saved in its Drafts and Sent.

Losing the account (removed from the group, share withdrawn) takes the
reader back to their own mail with the existing "You no longer have
access" notice.

New string: "Shared mailbox:" (1, English only in the other ten
catalogs). Checked in Chrome against a scratch server with a support@
group and two members. typecheck and vitest (174 files, 1533 tests)
pass.
2026-10-05 14:49:28 -07:00
jcoffey-dev e94508ea89 Merge pull request 'App rail, pill counts, tinted folder icons and raised controls' (#46) from feat/app-rail-layout into main
github/ci (branch) GitHub Actions
github/ci (tag inbuxa-v2026.10.5-ge94508e) GitHub Actions
ci / github (push) Skipped
ci / version (push) Successful in 25s
ci / node (push) Successful in 2m46s
ci / docker-build (push) Skipped
ci / publish (push) Successful in 3m33s
ci / announce (push) Successful in 35s
inbuxa-v2026.10.5-ge94508e
2026-10-05 19:15:50 +00:00
jcoffey-dev 6190d2b4f5 Merge remote-tracking branch 'origin/main' into feat/app-rail-layout
ci / node (pull_request) Skipped
ci / version (pull_request) Skipped
ci / docker-build (pull_request) Skipped
ci / publish (pull_request) Skipped
github/ci (branch) GitHub Actions
ci / github (pull_request) Successful in 2m44s
ci / announce (pull_request) Skipped
2026-10-05 12:12:17 -07:00
jcoffey-dev ed23610e31 Merge pull request 'Turkish: the 88 strings that fell back to English' (#43) from i18n/turkish-inbuxa-strings into main
ci / node (push) Skipped
ci / docker-build (push) Skipped
ci / version (push) Skipped
ci / publish (push) Skipped
github/ci (branch) GitHub Actions
ci / github (push) Successful in 3m4s
ci / announce (push) Skipped
2026-10-05 19:12:03 +00:00
jcoffey-dev 3e044057f6 Merge pull request 'Composer: smarter suggestions, links over selections, big images attached' (#44) from feat/composer-polish into main
ci / node (push) Skipped
ci / version (push) Skipped
ci / docker-build (push) Skipped
ci / publish (push) Skipped
ci / announce (push) Canceled after 0s
ci / github (push) Canceled after 6s
2026-10-05 19:12:00 +00:00
jcoffey-dev 69ccb313e3 Merge pull request 'Save the people you write to as contacts' (#45) from feat/collect-recipients into main
ci / node (push) Skipped
ci / version (push) Skipped
ci / announce (push) Canceled after 0s
ci / github (push) Canceled after 0s
ci / publish (push) Skipped
ci / docker-build (push) Skipped
2026-10-05 19:11:57 +00:00
jcoffey-dev 29795f3988 Merge remote-tracking branch 'origin/main' into feat/collect-recipients
ci / node (pull_request) Skipped
ci / version (pull_request) Skipped
github/ci (branch) GitHub Actions
ci / github (pull_request) Successful in 6m46s
ci / docker-build (pull_request) Skipped
ci / publish (pull_request) Skipped
ci / announce (pull_request) Skipped
# Conflicts:
#	web/src/store/compose.ts
2026-10-05 12:04:39 -07:00
jcoffey-dev 38dcbd9e0c Merge pull request 'Never send a message twice after a lost reply' (#42) from fix/send-no-duplicates into main
ci / node (push) Skipped
ci / version (push) Skipped
github/ci (branch) GitHub Actions
ci / github (push) Successful in 3m4s
ci / docker-build (push) Skipped
ci / publish (push) Skipped
ci / announce (push) Skipped
2026-10-05 19:03:59 +00:00
jcoffey-dev 5fe929c6a4 App rail, pill counts, tinted folder icons and raised controls
ci / node (pull_request) Skipped
ci / version (pull_request) Skipped
github/ci (branch) GitHub Actions
ci / github (pull_request) Successful in 3m4s
ci / docker-build (pull_request) Skipped
ci / publish (pull_request) Skipped
ci / announce (pull_request) Skipped
On a wide screen the switcher moves from the foot of the folder pane to a
rail down the left edge: Mail (with the inbox's unread badge), Calendar,
Contacts and Files, then Settings and the folder-list toggle at the
bottom. The top bar loses the menu button and the Settings gear there,
both now on the rail. Phones are unchanged: no rail, the tab bar, the
menu button for the drawer and the gear.

- Folder counts are pills: filled with the accent when there is unread
  mail, neutral for totals (Drafts, Scheduled).
- Role folders get their own icon tint (Inbox, Drafts, Sent, Archive,
  Junk, Trash, Scheduled); a color the reader picked still wins.
- Buttons, Compose and the current selection have a top-lit, raised look
  with a pressed state; Compose and the selected rail item are filled
  with the accent.
- Collapsing the sidebar keeps Mail's icon strip; Calendar, Contacts,
  Files, Settings and Admin have no icon-only form, so their sidebar
  hides instead of being crushed.
- The collapsed sidebar no longer draws a cut-off "FOLDERS": the rule
  hiding section headings lost to a later one of the same weight (this
  is on main today too).

Contrast: the accent behind small text is darkened in light themes and
lightened a touch in dark ones. Measured in a browser across all 12
palettes x 6 accents x both modes: text on pills, the rail badge and
Compose at least 4.83:1, tinted icons at least 3.14:1 on the sidebar.

New strings: 2 ("Show folder list", "Hide folder list"), in all ten
catalogs (1699 -> 1701).
2026-10-05 12:01:27 -07:00
jcoffey-dev c2502d36bd Save the people you write to as contacts
ci / node (pull_request) Skipped
ci / version (pull_request) Skipped
ci / docker-build (pull_request) Skipped
ci / publish (pull_request) Skipped
github/ci (branch) GitHub Actions
ci / github (pull_request) Successful in 3m5s
ci / announce (pull_request) Skipped
The addresses written to were remembered only in the browser that sent
the message, as a list of recent recipients, so a new device or a cleared
browser suggested nobody. After each confirmed send, the recipients who
are not contacts yet are now saved on the server, in an address book of
their own called Collected, so they are suggested everywhere.

- Only addresses on no card in any address book, own or shared, are
  added, de-duplicated, and never the sender's own identities.
- The book is created on first use and remembered by id in the synced
  settings, so its name can be anything; a deleted one is replaced.
- Names are split as the contact editor does ("Smith, Jane").
- Settings > Calendar & contacts > Contacts has a switch, on by default,
  as mail clients do; the book can be emptied or deleted like any other.

New strings: 3, in all ten catalogs (1699 -> 1702).
2026-10-05 11:55:51 -07:00
jcoffey-dev b11f3997d4 Composer: smarter suggestions, links over selections, big images attached
ci / node (pull_request) Skipped
ci / version (pull_request) Skipped
ci / docker-build (pull_request) Skipped
ci / publish (pull_request) Skipped
github/ci (branch) GitHub Actions
ci / github (pull_request) Successful in 3m5s
ci / announce (pull_request) Skipped
Recipient suggestions:
- the words typed match in any order, each one the start of a word in the
  name, a nickname, the organization or the address: "jane smi" finds
  "Smith, Jane", and "globex" finds the people at Globex;
- someone written to lately ranks a little above an equal match;
- an address already in To, Cc or Bcc is no longer offered in the other
  two fields.

Pasting:
- a single web or mailto address pasted over selected words makes those
  words the link, instead of replacing them with the address;
- a pasted or dropped image over 10 MB goes in as an attachment rather
  than inline, where it would swell every reply.

No new strings.
2026-10-05 11:52:54 -07:00
jcoffey-dev f6320e6614 Turkish: the 88 strings that fell back to English
ci / node (pull_request) Skipped
ci / version (pull_request) Skipped
ci / docker-build (pull_request) Skipped
ci / publish (pull_request) Skipped
github/ci (branch) GitHub Actions
ci / github (pull_request) Successful in 2m24s
ci / announce (pull_request) Skipped
Turkish came from public ihasmail (#41), which has no strings for what
only this webmail has: delegated and locked accounts, sign-in through
the mail server, the suite's About page, legacy protocol switches, the
data loss prevention notices, and held-for-review sends. Those 88 showed
in English.

They are translated now in the terms the Turkish catalog already uses
(Hesap, Yönetim, Kiracı, posta sunucusu, posta uygulaması), and the 22
Turkish entries no key looks up any more (ihasmail's Stalwart wording,
renamed here) are removed. Turkish: 1611/1699 -> 1699/1699, no stale
keys. These 88 are not a native speaker's; the rest of the catalog is.
2026-10-05 11:47:28 -07:00
jcoffey-dev 152311b035 Never send a message twice after a lost reply
ci / node (pull_request) Skipped
ci / version (pull_request) Skipped
ci / docker-build (pull_request) Skipped
ci / publish (pull_request) Skipped
github/ci (branch) GitHub Actions
ci / github (pull_request) Successful in 1m44s
ci / announce (pull_request) Skipped
When a send's request went out and no answer came back, the composer said
"Send failed" and offered the draft back. If the server had in fact
accepted it and only the reply was lost, sending the draft again
delivered the message twice. Nothing identified the first attempt, so
nothing could check.

Each send now carries its own Message-ID (on the sending identity's
domain, RFC 5322 §3.6.4), kept on the draft if it comes back. A failure
that may have happened after the server acted (no answer, a timeout, a
5xx from the proxy) is followed by asking the server what it did:

- a message with that Message-ID was submitted (EmailSubmission/query by
  emailIds, RFC 8621 §7.3): it was sent, and the composer says so;
- one exists with no submission: it was created and never sent; it is
  removed from Sent and the failure stands, so resending is safe;
- none exists: the failure stands;
- the server can't be asked either: the composer says it couldn't confirm
  and to check Sent, instead of a plain "Send failed".

A refusal (4xx) means the server did not run the request, so it is not
checked. Sending a draft again that came back from a failure asks first,
and sends nothing if a message with its Message-ID already exists;
submissions are expunged after the server's hold period, so later on any
surviving copy counts as sent (every failure path removes the copy it
made).

New strings: 3, in all ten catalogs (1699 -> 1702, no new fallbacks).
2026-10-05 11:43:55 -07:00
jcoffey-dev 3434a5ed39 Merge pull request 'Fixes and Turkish from public ihasmail (#29–#36)' (#41) from sync/ihasmail-2026-10-05 into main
github/ci (branch) GitHub Actions
ci / node (push) Skipped
ci / version (push) Skipped
github/ci (tag inbuxa-v2026.10.5-g3434a5e) GitHub Actions
ci / github (push) Successful in 3m44s
ci / docker-build (push) Skipped
ci / publish (push) Skipped
announce / announce (release) Successful in 25s
ci / announce (push) Successful in 28s
inbuxa-v2026.10.5-g3434a5e
2026-10-05 17:43:08 +00:00
jcoffey-dev 64b5db01f3 Keep a narrow list's labels inside the row, on the sender's line (ihasmail #36)
ci / node (pull_request) Skipped
ci / version (pull_request) Skipped
ci / docker-build (pull_request) Skipped
ci / publish (pull_request) Skipped
github/ci (branch) GitHub Actions
ci / github (pull_request) Successful in 2m25s
ci / announce (pull_request) Skipped
On a phone or a narrow list, rows are two lines, and labels went on a third
line of their own. A row is a fixed height at each density, and that third
line fit it only at Comfortable: at Cozy, the default, the labels were cut
off at the bottom, and at Compact they sat outside the row.

They now sit on the sender's line, after the name, which has room to spare,
so the row's height is unchanged at every density. When the line runs short
the name gives way first, then each label truncates; the date stays.

Reported in coffey-labs/ihasmail#35.

(cherry picked from commit 22490d8fe0190d85d8039a977435245b0d7da3cc)
2026-10-05 10:35:26 -07:00
jcoffey-dev af9b3a7f70 Indent the mark-read effect's first two lines again
Lost while resolving the conflict in the #30 pick.
2026-10-05 10:33:48 -07:00
jcoffey-dev 8a670c5e70 Turkish: the three image size strings (ihasmail #34)
(cherry picked from commit 5987f9c815d13df133841c4873b2aa9c394bc433)
2026-10-05 10:33:41 -07:00
jcoffey-dev cfb28ada45 Let mail wider than the pane scroll sideways (ihasmail #31)
(cherry picked from commit 14680d0e1b2cc966aa840a45e73b238322ed5e17)
2026-10-05 10:33:41 -07:00
jcoffey-dev 7b9da44116 Keep an open message unread after Mark as unread (ihasmail #30)
(cherry picked from commit 4a6bf677cbed9ecd23d02c0788c927e0dc9e941a)
2026-10-05 10:33:41 -07:00
jcoffey-dev 300ec1df99 Resize images in the composer (ihasmail #33)
(cherry picked from commit f17bdc9fff1455a734e19fdd8004fcd6b7970825)
2026-10-05 10:33:31 -07:00
jcoffey-dev 3f19f82960 Add Turkish translation (contributed by Hakan Arslan) (ihasmail #32)
(cherry picked from commit 017b1b5eb812ba18c3577ff79c544a25f7f91aaa)
2026-10-05 10:33:27 -07:00
jcoffey-dev 2e7f30c64e Finish the settings load when the tree remounts mid-load (ihasmail #29)
(cherry picked from commit 5ec06f40125cc320fba64edaa4ee1a1fb23d22d2)
2026-10-05 10:33:08 -07:00
jcoffey-dev c558693db5 Merge pull request 'ci: let the announce workflow run by hand for a given tag' (#40) from ci/announce-dispatch into main
ci / node (push) Skipped
ci / version (push) Skipped
ci / docker-build (push) Skipped
ci / publish (push) Skipped
github/ci (branch) GitHub Actions
ci / github (push) Successful in 2m25s
ci / announce (push) Skipped
2026-10-05 03:56:29 +00:00
jcoffey-dev c87a6d1cd6 ci: let the announce workflow run by hand for a given tag
ci / node (pull_request) Skipped
ci / version (pull_request) Skipped
ci / docker-build (pull_request) Skipped
ci / publish (pull_request) Skipped
github/ci (branch) GitHub Actions
ci / github (pull_request) Successful in 2m7s
ci / announce (pull_request) Skipped
A release event runs the workflow as it was at the tag, so re-running a
failed announcement repeats the failure even after main is fixed. A manual
run takes the tag and uses main's workflow; the action already accepts it.
2026-10-04 20:53:46 -07:00
jcoffey-dev 34d3f21b4b Merge pull request 'ci: pin discourse-release at 9282c6f, which maps inbuxa-webmail' (#39) from ci/announce-pin-inbuxa-webmail into main
ci / node (push) Skipped
ci / version (push) Skipped
ci / docker-build (push) Skipped
ci / publish (push) Skipped
github/ci (branch) GitHub Actions
ci / github (push) Successful in 1m55s
ci / announce (push) Skipped
2026-10-05 03:49:11 +00:00
jcoffey-dev 0c5ad7a3b8 ci: pin discourse-release at 9282c6f, which maps inbuxa-webmail
github/ci (branch) GitHub Actions
ci / github (pull_request) Successful in 2m26s
ci / announce (pull_request) Skipped
ci / version (pull_request) Skipped
ci / docker-build (pull_request) Skipped
ci / publish (pull_request) Skipped
ci / node (pull_request) Skipped
The release map knew this repo only by its old name, so announcing
inbuxa-v2026.10.5-g17a8093 failed. The action itself is unchanged.
2026-10-04 20:46:27 -07:00
jcoffey-dev 17a8093c09 Merge pull request 'Rename the repository to inbuxa-webmail' (#38) from chore/rename-to-inbuxa-webmail into main
github/ci (branch) GitHub Actions
github/ci (tag inbuxa-v2026.10.5-g17a8093) GitHub Actions
ci / github (push) Successful in 3m47s
announce / announce (release) Failing after 24s
ci / node (push) Skipped
ci / docker-build (push) Skipped
ci / version (push) Skipped
ci / publish (push) Skipped
ci / announce (push) Failing after 22s
inbuxa-v2026.10.5-g17a8093
2026-10-05 03:31:51 +00:00
jcoffey-dev 5664896f53 Rename the repository to inbuxa-webmail
ci / node (pull_request) Skipped
ci / version (pull_request) Skipped
ci / docker-build (pull_request) Skipped
ci / publish (pull_request) Skipped
github/ci (branch) GitHub Actions
ci / github (pull_request) Successful in 1m30s
ci / announce (pull_request) Skipped
The repository moved from inbuxa/ihasmail-inbuxa to inbuxa/inbuxa-webmail,
matching inbuxa-server and inbuxa-admin. Point the source links, the image
name and the package link at the new name. The OAuth client id stays
ihasmail-inbuxa, since that is what the server registers.
2026-10-04 20:29:09 -07:00
jcoffey-dev 4d7668601e Merge pull request 'ci: copy each release image to GHCR as a replica' (#37) from ci/ghcr-replica into main
ci / node (push) Skipped
ci / version (push) Skipped
ci / docker-build (push) Skipped
ci / publish (push) Skipped
github/ci (branch) GitHub Actions
ci / github (push) Successful in 2m34s
ci / announce (push) Skipped
2026-09-30 16:30:40 +00:00
jcoffey-dev bdee5de814 ci: copy each release image to GHCR as a replica
ci / node (pull_request) Skipped
ci / version (pull_request) Skipped
ci / docker-build (pull_request) Skipped
ci / publish (pull_request) Skipped
github/ci (branch) GitHub Actions
ci / github (pull_request) Successful in 2m23s
ci / announce (pull_request) Skipped
The Gitea registry stays authoritative; GHCR becomes a copy of it, the way
the GitHub repository is a copy of the Gitea one. After the tag build has
pushed the release image to the registry, a new ghcr job copies it to
ghcr.io under the same version tag and :latest with `imagetools create` --
a copy, not a rebuild, so the digest on GHCR is the digest on the registry.

Anything still pulling the old ghcr.io name, including the TrueNAS app
submission, keeps receiving releases. The job uses the run's own token and is
left out of the status reported to Gitea, so a GHCR problem cannot fail a
release.
2026-09-30 09:27:48 -07:00
jcoffey-dev b1436d4d2a Merge pull request 'ci: copy each release to GitHub after the tag build' (#36) from ci/github-release-copy into main
ci / node (push) Skipped
ci / version (push) Skipped
ci / docker-build (push) Skipped
ci / publish (push) Skipped
github/ci (branch) GitHub Actions
ci / github (push) Successful in 2m16s
ci / announce (push) Skipped
2026-09-30 13:54:41 +00:00
jcoffey-dev a7c7d88408 ci: copy each release to GitHub after the tag build
ci / node (pull_request) Skipped
ci / version (pull_request) Skipped
ci / docker-build (pull_request) Skipped
ci / publish (pull_request) Skipped
github/ci (branch) GitHub Actions
ci / github (pull_request) Successful in 2m29s
ci / announce (pull_request) Skipped
The mirror carries tags to GitHub but not releases, so the replica's
Releases page -- and anyone watching the repository there -- stopped at the
last release made on GitHub. After the tag build has published, a new
github-release job copies the tag's Gitea release to a GitHub release: the
same notes, with PR and issue numbers rewritten to Gitea links, the same
files, and a line pointing back to the Gitea release.

It uses the run's own token and is left out of the status reported to
Gitea, so it cannot fail a release. With no Gitea release for the tag it
does nothing.
2026-09-30 06:52:03 -07:00
jcoffey-dev 63ddc23ee2 Merge pull request 'ci: name the tag in GitHub's tag status, and make digests re-runnable' (#35) from ci/tag-path-hardening into main
ci / node (push) Skipped
ci / version (push) Skipped
ci / docker-build (push) Skipped
ci / publish (push) Skipped
github/ci (branch) GitHub Actions
ci / github (push) Successful in 2m24s
ci / announce (push) Skipped
2026-09-30 13:47:42 +00:00
jcoffey-dev ae83d27e4b ci: name the tag in GitHub's tag status, and make digests re-runnable
ci / node (pull_request) Skipped
ci / version (pull_request) Skipped
ci / docker-build (pull_request) Skipped
ci / publish (pull_request) Skipped
github/ci (branch) GitHub Actions
ci / github (pull_request) Successful in 2m29s
ci / announce (pull_request) Skipped
Commit statuses belong to the commit, not the tag. Upstream v* tags and
inbuxa-v* tags can sit on the same commit, so Gitea's github job, waiting
for "github/ci (tag)", could read the other tag's older result and move on
before this tag's build finished. A tag's status is now "github/ci (tag
<name>)" on both sides.

The per-architecture digest artifacts are also overwritable and kept for a
week, so re-running a build, or publish on its own, still works.
2026-09-30 06:44:52 -07:00
jcoffey-dev 043fe4ca54 Merge pull request 'ci: run the github wait job on its own runner label' (#34) from ci/wait-runner into main
ci / node (push) Skipped
ci / version (push) Skipped
ci / docker-build (push) Skipped
ci / publish (push) Skipped
github/ci (branch) GitHub Actions
ci / github (push) Successful in 2m13s
ci / announce (push) Skipped
2026-09-30 07:39:03 +00:00
jcoffey-dev 24dccdb47d ci: run the github wait job on its own runner label
ci / node (pull_request) Skipped
ci / version (pull_request) Skipped
ci / docker-build (pull_request) Skipped
ci / publish (pull_request) Skipped
github/ci (branch) GitHub Actions
ci / github (pull_request) Successful in 2m38s
ci / announce (pull_request) Skipped
The github job only polls Gitea for GitHub's commit status, but it holds a
runner slot for as long as the GitHub build takes -- the better part of an
hour for a cold build. On the shared build runners a handful of those
could take every slot and stall real work, so it now runs on the `wait`
label: a runner of its own, with many slots, no docker socket and a small
CPU and memory cap.
2026-09-30 00:36:13 -07:00