aboutsummaryrefslogtreecommitdiffstats
path: root/mail-overview
AgeCommit message (Collapse)AuthorFilesLines
6 hoursrefactor: one Theme.qml in shared/, symlinked from each componentDanilo M.1-66/+1
The four copies had already drifted, which is the argument for doing this now rather than when a palette change has to be made four times and lands in three of them. vm-manager was missing surfaceAlt; volume-osd was missing green, yellow and surfaceAlt. The shared file is the superset, so the two thin ones gain properties they never had and nothing loses one. A symlink rather than a shared import path: a singleton outside the config directory needs a qmldir beside it, the same friction that already keeps the generated palette parsed rather than imported. Quickshell follows the link and resolves the singleton with no qmldir, so no consumer changes and no component stops running standalone under qs -p. All four load clean with Configuration Loaded and no QML resolution error. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TvHeJEXJzdfAaCCYqURAWp
7 hoursdocs(mail-overview): component notesDanilo M.1-0/+167
Records the decisions a later reader would otherwise reverse, each with the measurement behind it: counting by the account tag rather than the path glob qtmaildir itself uses, because notmuch deduplicates by message id and a glob double-counts a message that arrived at two addresses; validating notmuch output as an integer, because a rejected query prints nothing while a misparsed one returns a plausible wrong number; and parsing the config by walking lines, because account folders named like [Gmail]/Bozze end a bracket-delimited section body before its label. Also notes the one property that differs from the other two panels, exclusionMode Normal, with the measured geometry showing the overlay starting exactly where waybar ends. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WWL8JYHu7yhAdtx5pU9PMU
7 hoursfeat(mail-overview): the drawerDanilo M.3-15/+257
Builds the panel body on the house idiom the other two components already use: a fullscreen transparent PanelWindow holding a dim backdrop, with the real content as a Rectangle anchored inside it. The idiom is worth the seemingly oversized window because it hands us two behaviours for free. Click-outside-to-close is just a MouseArea filling the backdrop, and the drawer only needs its own MouseArea to swallow clicks so they do not fall through. Escape works because the window actually covers the screen and can take exclusive keyboard focus. exclusionMode is Normal here, unlike the Ignore the other two components set. Waybar claims an exclusive zone at the top of this screen, and the mail icon lives in it, so respecting that zone positions the drawer immediately below the bar without this file hardcoding, or even knowing, the bar's height. It also means the backdrop begins below waybar, so the bar itself does not dim while its own drawer is open, which reads correctly: the icon you clicked stays lit. Focus sits on an inner Item with focus: true, not on the window. Setting WlrLayershell.keyboardFocus is necessary but not sufficient, because key events in QML are delivered to a focused item and never to a window, so Keys.onEscapePressed on the PanelWindow would never fire. This cost time in the vm-manager panel and the same shape is used here deliberately. Thread rows are deliberately read-only, with no click handler. qtmaildir takes no arguments, so there is no way to ask it to open a particular thread and a clickable row would promise navigation it cannot deliver. The rows are a preview; the button opens the client at its own idea of where to start. show() refreshes before opening rather than relying on a timer. The panel is opened rarely and the shell is autostarted for the whole session, so the counts are almost always stale by the time anyone looks at them, and a refresh on open is both cheaper and fresher than polling. Also removes the temporary console probe from shell.qml, which existed only to verify the account model parsed and counted correctly. The drawer now displays the same data, so the probe has no job left. Dropping it also drops the QtQuick import, which nothing else in that file needed. Button.qml is an unmodified copy of vm-manager's. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WWL8JYHu7yhAdtx5pU9PMU
7 hoursfix(mail-overview): parse account sections by walking linesDanilo M.2-19/+31
Two bugs, both found by actually running the shell rather than reading the code. shell.qml used Connections without importing QtQuick, so the config failed to load outright: "Connections is not a type". That one was loud, and it only affected the temporary verification probe. The parser was the real bug and it was quiet. Section bodies were matched as "everything up to the next [", which is wrong for this file: accounts whose folders are named like [Gmail]/Bozze end their body at that bracket, before the label line is reached. Three of the five accounts therefore fell back to displaying their raw key, and nothing reported a problem because falling back is a legitimate path for an account that genuinely has no label. Replaced with a line walk. It says what it means, its only state is which section is open, and it was checked against the real config before being trusted: all five accounts now resolve both label and colour. An attempted fix with a lazy quantifier and a lookahead made things worse, dropping every label, which is the argument for the boring version. Verified in a running shell: five accounts in config order with their labels, counts summing exactly to the global notmuch count, no unknowns, and the config stays loaded for the full timeout rather than exiting silently. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WWL8JYHu7yhAdtx5pU9PMU
7 hoursfeat(mail-overview): account model singletonDanilo M.2-0/+217
Accounts.qml is the data layer for the mail drawer: it parses accounts from qtmaildir.conf rather than hardcoding them, so adding an account there needs no edit here. The key runs to the closing bracket, not the first dot, because at least one configured key contains a dot of its own; matching only up to the first dot would silently truncate it and drop that account's mail from every count. Counting uses the account-<key> notmuch tag, not a path glob. notmuch deduplicates by message id, so a message delivered to two of the configured addresses is one message with two file paths: a path glob would count it under both accounts and the per-account rows would sum higher than the global total the waybar icon already shows (measured elsewhere as 102 vs 101). The tag is a property of the message, so it is singular and the rows always sum to the header exactly. An unknown count is -1, never 0. notmuch has one failure mode with no distinct exit status: a rejected query fragment can still return 0 exit and empty output, and an empty string must not become a zero, which would render as "no unread mail" instead of "count unavailable". Output is validated as a non-negative integer before being trusted. Includes a temporary console-log probe in shell.qml, added deliberately for runtime verification of this model outside the drawer UI (Task 4). It stays until the user has run and confirmed it against real notmuch output, then gets removed in a follow-up commit. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WWL8JYHu7yhAdtx5pU9PMU
7 hoursfeat(mail-overview): component skeleton with the keepalive windowDanilo M.3-0/+131
Nothing is drawn yet. This commit exists on its own because the thing most likely to be wrong at this stage is invisible: a config whose only window is hidden exits straight after logging Configuration Loaded, reporting no error, and the symptom is a keybind that appears to do nothing. Theme.qml is a verbatim copy of the one in appearance. It is a fallback for before the generated palette is read, not a palette to grow; deduplicating the four copies is a separate change. Not yet run: the user runs the shell themselves, so loading and IPC are verified in their session rather than here. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WWL8JYHu7yhAdtx5pU9PMU
7 hoursdocs: correct the notmuch malformed-query claimDanilo M.1-4/+6
The previous commit, the spec and the plan all said notmuch exits 0 on a malformed query while printing something that is not a count, and that validating the output as an integer therefore catches it. Measured properly, that is wrong in a way worth recording, because the truth is worse. notmuch fails two different ways. A rejected query prints nothing and exits 1: `notmuch count 'tag:unread and ('`. A query Xapian merely misparses returns a plausible wrong number and exits 0: `notmuch count 'tag:unread and (('` gives 41, and `'tag:unread and tag:'` gives 3. The second is undetectable by any check on the output, which is why the original claim was not just imprecise but inverted: the case it described as caught is the case nothing can catch. The integer validation still earns its place, on the first failure mode, where empty output would otherwise render as an empty inbox. The real defence against the second is that QUERY is a fixed string and is never built from anything, which the comment now says. The earlier measurement that produced the wrong claim read 40 as mangled output when it was a successful parse answering a different question. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WWL8JYHu7yhAdtx5pU9PMU
7 hoursfeat(mail-overview): waybar watcher in continuous modeDanilo M.1-0/+66
Prints one JSON line per notmuch commit rather than polling on an interval, so the count drops the moment mail is read in qtmaildir and rises the moment mbsync commits, and waybar owns the watcher process: nothing to supervise on a machine with no systemd. The watch is on the xapian directory, not on a file inside it, because a commit replaces files and a watch held on a filename dies with it. The short sleep coalesces the several writes of one commit into one redraw. notmuch exits 0 even for a malformed query, printing something that is not a count, so the output is validated as an integer rather than trusting the exit status. A failure there renders as an error glyph: a count that silently reads zero would look exactly like an empty inbox. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WWL8JYHu7yhAdtx5pU9PMU