| Age | Commit message (Collapse) | Author | Files | Lines |
|
Zoom was Chromium's, not the application's: the web view handled the
keys natively and never told anyone, so there was no value to save.
qtmaildir now owns it. Zoom in, out and reset are real actions, in the
View menu and rebindable through [keys], and the factor is persisted to
the UI state file. Ctrl+wheel over the body zooms and Ctrl+middle-click
resets, both filtered by ancestry from an application-level filter: the
events are delivered to an internal QQuickWidget the web view creates
lazily, so a filter on the view itself never sees them.
The factor is clamped to 0.5 - 3.0, and NaN, infinity, zero and negative
values fall back to 1.0, since a corrupt state file must not be able to
leave the pane unreadable with no visible way back.
Both risks the plan flagged turned out not to exist, verified by probe
rather than assumed. The application QAction wins over the web view's
native zoom key, so the tracked factor cannot diverge from what is on
screen. And the factor survives setHtml(), so the web view is the single
source of truth and needs no reapply per render.
A third finding is worth recording because it produced a wrong fix
first. A probe using QTest::keyClick() reported Ctrl++ as a dead
binding, and a test was written asserting that. Both were wrong: Ctrl++
is exactly what the '+' key emits on an Italian layout, confirmed
against the real keyboard, and it is the shipped default. Whether a
symbol needs Shift is a property of the layout, not of Qt, and
keyClick() reproduces neither. The test now only checks that every
default parses, and the comment in defaultBindings() says not to
re-derive this from synthetic input.
Ctrl+= is a second binding for reset, skipped when [keys] gives it to
something else.
Also fixes a pre-existing bug the new config key exposed. [general]
entries were read as "general/<key>", which matches nothing: QSettings'
INI backend treats a section literally named [general] as its own
fallback section and strips the prefix. notmuch_config had therefore
never worked. Both keys are now read without it; the file format is
unchanged.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
|
Spelled out per row, tags ran to 500 pixels of largely repeated text and
took most of the thread list's width. The column is gone; tags render as
coloured chips split by what they actually mean.
An account tag says which mailbox a thread arrived in, and draws as a
chip in front of the subject. A functional tag says what state a thread
is in, and those fill one row under the message pane. One row keeps the
message area from shifting between threads with different tag counts, so
whatever does not fit collapses into a +N chip that names the rest in its
tooltip.
TagColors resolves a colour by exact tag first, then by top-level prefix,
so a single "shopping" entry covers shopping/amazon and shopping/nike
while shopping/amazon can still override its own. That matters at 96
tags. Built-in defaults cover the usual state tags, and anything left
unconfigured falls back to a hash of the name, stable so a chip does not
change colour as the list scrolls.
|
|
Confirmed with the maintainer as v2-only rather than v2-or-later. LICENSE is
the official text from gnu.org. Every file under src/ and tests/ carries the
matching notice.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
|
Off-the-record profile, JavaScript off, deny-by-default interceptor, and a
page subclass that hands link clicks to the system browser so a message can
never navigate the pane.
Honours the obligation task 5 recorded: the interceptor trusts exactly one
qtmaildir: URL and fails closed otherwise, so setHtml() and setDocumentUrl()
must agree or the pane renders nothing. Rather than pairing those calls at
each site, every load goes through one setDocument() and the URL comes from
a single documentUrl() accessor. Verified against the real interceptor that
this URL is allowed while siblings, subpaths, remote and file: are not.
Three fixes against the drafted version:
- showError() called setHtml() with a base URL but never setDocumentUrl(),
so an error card would have rendered blank. Now impossible to repeat.
- clear() and showError() left the previous thread's inline parts in the
scheme handler and its cids in the interceptor. Both now empty the policy,
so no thread's parts outlive it.
- MessagePage trusted the whole qtmaildir: scheme for typed navigations,
which is the same blanket-trust mistake task 5 removed from the
interceptor. It now matches the exact document URL.
The parts-flattening is extracted into buildThreadCidMap() so it can be
tested without a live profile, and a cidPrefix containing '!' is sanitized
rather than trusted, since Q_ASSERT is compiled out in release and this map
decides which bytes a message can name. The sanitizer escapes '_' before
replacing '!', because a plain replace would map "m0!x" and "m0_x" onto one
key and merge two messages, which is the very collision the namespacing
exists to prevent. Mutation-verified: the naive replace fails the
distinctness test, and dropping the sanitizer trips the assert.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|