mirror of
https://github.com/karatektus/pl_mail.git
synced 2026-10-25 10:04:18 +00:00
Four reported items, and the feature that turned out to be the fix for two of
them.
**Selecting past the page.** "Select all" meant the fifty rows on screen, which
is the only thing a checkbox over a paginated list can mean on its own — and not
what anybody wants in a bin holding a hundred and ninety-five. When the page is
fully selected and the view holds more, the toolbar now offers the rest, and the
same gesture covers "every starred mail".
The view arrives as a named scope, not as the URL the user is on. Posting the
URL would make every mail list route an input to a bulk WRITE, so a route added
later for reading becomes a way of deleting without anyone deciding that. The
scope names are the ones the list templates already use for themselves
(`{% block list_scope %}`), so there is nothing new to learn and the two cannot
drift. Unread-only travels with it: a "select all" that ignored the filter would
act on mail the person cannot see.
**One request, not one per conversation.** The toolbar posted per thread, in
parallel — fine for fifty rows, impossible for a folder. That also could not
answer for the LIST: each response redrew its own row and knew nothing else, so
an emptied list still said "1–5 of 5" (Schreibtest 10). The bulk response
carries the rows AND the pane re-reads the list, because the pager and the empty
state are properties of the list that no row-shaped stream can carry.
Two single-thread assumptions had to go with it, and both were correct until
now. `finish()` resynced only `$messages[0]->thread`, so a bulk archive answered
200, reported 71, and changed nothing on screen — the threads kept the Inbox
label their messages no longer had. `markRead()` wrote the whole selection's
unread count onto the first thread, so four conversations were marked read and
three rows went on rendering as unread. Both now work per thread, and the bulk
controller groups by ACCOUNT because ThreadStatusUpdater resolves the
destination folder from the first message's account.
**The 404 was English and in the wrong theme** (Befunde 2). Not an oversight in
the template: a 404 is thrown by the router at priority 32 of kernel.request,
before the firewall at 8 and before UserLocaleSubscriber at 6 — nothing has
authenticated when the exception is handled, so there is no user, no locale and
no theme. The error template must not look one up, and its own docblock explains
why at length. So both hints ride in a cookie written on ordinary responses.
**Sie/du** (Befunde 8). Seven strings addressed the reader formally, and the
report found them in Aliases because that is where the reader happened to look.
Guarded by a test that uses the one rule that can be checked: German capitalises
both the polite second person and the first word of a sentence, so a capitalised
form MID-sentence can only be formal address. A naive search flags a dozen good
sentences, gets an exception list, and the exception list then swallows the next
real one.
**A revert, recorded rather than hidden.** The label menu's escape to the
browser's top layer is gone. The bug is real — the panes' `backdrop-filter`
makes each a stacking context and the containing block for `position: fixed`, so
nothing inside one can rise above the chrome — but the fix broke clicking:
`elementFromPoint` at an option's own coordinates answers null and the click
never lands. It did the same to the snooze menu. Three specs caught it. A menu
that is visible and does nothing is worse than one that is clipped, and I could
not find the cause without seeing the real layout, so the spec is marked fixme
with the whole story in it.
Also: a shared `rowAction()` for the specs. A row's actions are
`visibility: hidden` until hovered, which makes them easy to lose under four
parallel workers and — because a hidden element is not in the accessibility tree
— makes `getByRole` report a missing action for one that is merely unhovered.
That was three of my own specs failing on a different run each time.
4027 unit tests, PHPStan clean, 550 browser tests.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
29 lines
879 B
Twig
29 lines
879 B
Twig
{% extends '_layout/_mailbox.html.twig' %}
|
|
|
|
{% block list_scope %}starred{% endblock %}
|
|
|
|
{% block title %}
|
|
{% set _unread = sidebarCounts.forStarred() %}
|
|
{{ _unread > 0 ? '('~_unread~')' }} {{ 'sidebar.nav.starred'|trans }} — {{ 'app.name'|trans }}
|
|
{% endblock %}
|
|
|
|
{% block title_count_key %}starred{% endblock %}
|
|
|
|
{% block inbox_tabs %}
|
|
<div class="px-4 py-2.5 border-b border-line">
|
|
<h2 class="text-sm font-semibold text-ink-soft">{{ 'starred.heading'|trans }}</h2>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block message_list %}
|
|
{% if threads is empty %}
|
|
<li class="px-4 py-8 text-center text-sm text-ink-faint">
|
|
{{ 'starred.empty'|trans }}
|
|
</li>
|
|
{% else %}
|
|
{% for thread in threads %}
|
|
{% include '_partials/_thread_row.html.twig' with { thread: thread } %}
|
|
{% endfor %}
|
|
{% endif %}
|
|
{% endblock %}
|