| Age | Commit message (Collapse) | Author | Files | Lines |
|
Hand-testing item 169 found four defects, three of them visible on every
card.
The initials were taken from whatever the card's first line held, which is
the raw From header on a reply row and notmuch's comma-joined author
summary on a thread row. A naive space split therefore gave `T<` for
`tsujan <notifications@github.com>` and one letter each from two different
people for `Standreas, tsujan`, and a separator counted as a word, so
`INE - Expert IT Training` drew `I-`. Avatar::initialsFor() now normalises
first: the angle-addr and any quoting go, a comma takes the first entry
unless the name is quoted, a bare address is not a name, and a word has to
carry a letter or a digit. Avatar::fillFor() uses the same normalisation,
so an address in the name's place no longer reads as a person.
The two-tone fill built its gradient axis as a radius from the centre, so
the 0.5 colour stop landed on the squircle's edge and one hue filled almost
the whole face. The axis spans the diameter now.
The fade ran left to right, which put its hard stop at 60% of the card and
read as a slab rather than a wash. It runs right to left: opaque at the
card's right edge, where the only hard stop is the card's own boundary, and
gone before it reaches the accent bar that already states the account.
And the flat views hashed the user's own address on every row, so every
Sent and Drafts card shared one pattern. ThreadSummary::firstMessageRecipient
rides the recipient fold, which already parses the To header, and
SenderAddressRole prefers it, falling back to the sender when there is no
usable To.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P88Q3MCSCSQxKDy7pmXh9F
|
|
|
|
|
|
A thread's card has rendered one message since item 66, but every tag
action still acted on the entire conversation. Delete, Archive,
Important, Mark spam and Toggle unread now act on the message the card
shows; the whole-thread versions move to a "Whole thread" submenu in the
Message menu and the thread list's context menu, on Ctrl+Alt+<key>.
Closes items 87, 88, 105, 106, 107, 108, 109, 110 and 111.
The defects fixed along the way, several found by reading rather than by
report:
- threadAt(current.row()) answered about the wrong thread for a reply
row, because a tree numbers rows per parent. The audit found four live
sites, not the one reported: Delete and Toggle unread each chose their
DIRECTION from an unrelated thread, and the tag dialog counted the
wrong thread's tags. threadFor(index) replaces them.
- A message-scoped write made no optimistic model update and no reply
row carried a doomed cue, so acting on a reply moved the pending-edit
count and changed nothing on screen.
- Both toggles read the state of a reply's THREAD, which a
message-scoped write never changes, so they were one-way: the second
press re-sent a tag the message already had.
- flushHeldEdits() re-sent only thread-scoped edits, so a tag change
made on one message during a sync was applied to the row, counted as
unsynced, and then dropped without ever being written.
- applyTagChange() updated a thread's summary but not its loaded
replies, leaving an expanded thread's rows describing a state the
database no longer held.
- A thread's first message is not among its children, so both
message-scoped lookups missed it: acting on a root card repainted
nothing and emptied the message pane's chip row.
- ThreadSummary::tags is notmuch's union over the thread, so a card
standing for one message drew tags belonging to its siblings. The
worker now reads that message's own tags in the walk that already
finds its id, so the split is known before a row is ever opened.
The card shows both tiers: its own message's tags at full size, the rest
of the conversation's smaller and muted, so nothing appears to vanish
when a row is selected.
Auto mark-read is message-scoped as a result, and now arms for a reply,
which it never did. With maildir.synchronize_flags on, the old
thread-wide write reached the server for mail that had never been
displayed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
|
The five real account colours are all mid-tone, because they were chosen as
CHIP fills with legible text on top, and three pixels of a mid-tone colour
barely registers beside a card's own background. The bar now lifts saturation
and lightness to a floor.
A floor, not a repaint: a colour already past it is returned untouched, so a
deliberately vivid choice is preserved and only the muted ones move. Hue is
never altered, because hue is the entire information the bar carries and a
shifted one would stop matching the account's chip and its dropdown swatch.
0.65 and 0.50 were chosen by rendering all five accounts as 3px bars against
both a dark and a light card background and looking at them. Higher pushed the
weakest of them, a green at S 0.33, toward a neon that no longer matched its own
chip; lower left it where it started.
accentLineColour had no test at all until now, which is how two earlier versions
of it shipped wrong: one blended toward Base until it WAS the background, the
other passed a chip colour through unchanged. test_carddelegate covers the lift,
the floor's idempotence, hue preservation across all five accounts, and the
fallback for a thread with no account tag.
|