aboutsummaryrefslogtreecommitdiffstats
path: root/CHANGELOG.md
blob: c78cb941f1bce047709b0eeae3bb463c27e90989 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# Changelog

All notable changes to this project are documented here.

The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

While the version is below 1.0.0, the configuration file format and the
keybinding action names may change in a minor release. 1.0.0 will mark the
point at which they are stable.

## [Unreleased]

### Added

- Tags render as coloured chips instead of text in a column. The account tag
  sits in front of the subject in the thread list, and the functional tags fill
  a single row under the message pane, with anything that does not fit
  collapsing into a `+N` chip whose tooltip names the rest.
- `[tagcolors]` config group. Colours resolve by exact tag first, then by
  top-level prefix, so one `shopping` entry covers `shopping/amazon` and
  `shopping/nike` while `shopping/amazon` can still override its own. Built-in
  defaults cover the usual state tags; anything unconfigured gets a stable
  colour derived from its name.
- `color` and `label` keys in an account stanza, setting the account chip's
  fill and its text. `label` shortens a long key for display only and renames
  nothing in notmuch; unset falls back to the key.
- The application icon is now used: window icon, a `.desktop` entry, and
  install rules placing both into `hicolor` and `share/applications`.
- Toolbar and menu actions carry icons from the system theme, falling back to
  text where a theme lacks one.
- Menu bar covering every action: File, Edit, Message, View and Help.
- Toolbar with the frequent subset, Sync, Archive, Delete and Undo.
- **Help > Keyboard shortcuts**, listing the current bindings. Generated from
  the actions themselves, so it shows configured overrides rather than a
  hand-written copy of the defaults.
- **Help > About**.
- Default bindings for `spam` and `load_remote`, which previously had none
  and were unreachable until bound by hand.

### Fixed

- Acting on a thread now visibly changes its row. A thread tagged `deleted`
  or `spam` is filled dark red or orange, in white struck-through text, across
  every column. The tag change was already applied, but `Tags` sat after the
  stretching `Subject` column and was pushed off-screen, so Delete looked like
  it had done nothing.
- Thread list columns are Date, From and Subject, all resizable. The tags
  column is gone: spelling out a dozen tags per row consumed most of the list's
  width. Widening past the viewport scrolls horizontally rather than squeezing
  the other columns.
- Hierarchical tags in `[tagcolors]` were silently ignored. QSettings treats
  `/` in a key as a group separator, so `shopping/amazon` becomes a nested key
  that `childKeys()` never returns, and every tag containing a `/` fell through
  to its prefix.
- Three default bindings never fired. Typing a capital sends `Shift`+the key,
  but `N`, `F` and `G` were stored as the unshifted key, which no keystroke
  produces, leaving `toggle_unread`, `flag` and `sync` dead. A bare capital in
  `[keys]` is now read as `Shift`+that letter. As a side effect `y` and `Y`
  are two distinct keys rather than a collision that silently dropped one.
- Modifier shortcuts such as `Ctrl+Q` now work while the query bar has focus.
  The old event filter suppressed every binding there, not only the plain
  letters that would have interfered with typing.

### Changed

- Default bindings moved to modifier shortcuts (`Ctrl+E` archive, `Ctrl+D`
  delete, and so on). Existing `[keys]` entries are unaffected, and single
  letters are still safe to bind. See "Upgrading from 0.1.0" in the README.
- Actions are `QAction`s dispatched by shortcut rather than a hash of
  callbacks behind an event filter, which is what lets them appear in menus.
  The hand-maintained list of registered action names is now derived from the
  actions, so it can no longer drift from them.

## [0.1.0] - 2026-08-03

First release. Reads and organizes a local notmuch-indexed Maildir; it does
no network protocol work at all, since fetching and sending are left to
external commands.

### Added

- Permanent notmuch query bar with saved-query buttons and per-account
  scoping, over a two-pane thread list and message view.
- Threads streamed from the database in batches of 200, so a query over tens
  of thousands of threads paints its first rows immediately and fills in
  behind. Measured at 21 ms to the first batch against a 36,000-thread
  database.
- Whole-thread rendering: every message in a thread renders into one
  document, oldest first, with messages that did not match the current query
  collapsed to one-line stubs. The last message always renders expanded, so
  a thread is never nothing but stubs.
- HTML mail rendered through QtWebEngine, with a locked-down profile:
  off-the-record, no cookies, no cache, JavaScript disabled, and a
  deny-by-default request interceptor. Remote content is blocked until the
  user asks for it, which defeats tracking pixels and read receipts; the
  grant applies to one render and is never remembered.
- Inline `cid:` images served from an in-memory map scoped to the displayed
  thread. References are namespaced per message, so two newsletters sharing
  a Content-ID do not resolve to each other's images.
- Attachment handling that treats MIME filenames as untrusted: names are
  reduced to a basename and refused if the resolved path escapes the chosen
  directory.
- Tagging (archive, delete, spam, flag, read/unread, custom) over a
  multi-thread selection, applied optimistically and reverted if the write
  fails. Thread ids are resolved to message ids in a single combined query
  rather than one query per thread.
- Undo for tag changes, backed by a `QUndoStack`. Entries store thread ids
  and re-resolve them, so undo stays correct after the selection moves on.
  There is deliberately no dry-run and no destructive-action confirmation:
  undo is the better answer for a human at a GUI.
- Sync by running the user's existing script through `QProcess`, joining the
  `flock` that already serializes it against cron rather than reimplementing
  mbsync orchestration.
- Configurable keybindings via the `[keys]` section, validated against a
  known action list so a typo warns instead of binding silently.
- `--version` and `--help`.

### Known limitations

- Compose and send are not implemented; they are planned for v2 and need a
  companion send script that does not exist yet.
- A thread renders as a flat chronological list. Reply structure is
  available from notmuch but is not drawn as an indented tree.
- MIME parsing happens on the UI thread. Opening a very long thread parses
  every message in it, which could stutter; deferred until measured.
- The sync log pane shows what the sync command writes to stdout and stderr.
  A script that redirects its own output to a file will leave the pane
  empty.