implement message threading on the message store level using the
jwz algorithm. Build threads on-the-fly when new message headers arrive.
Use the references header to create the threads and the in-reply-to
header as a fall-back option in case no references header is present.
Does not run when the worker provides its own threading (e.g. imap
server threads).
Include only those message headers that have been fetched and are
stored in the message store.
References: https://www.jwz.org/doc/threading.html
Signed-off-by: Koni Marti <koni.marti@gmail.com>
Tested-by: Inwit <inwit@sindominio.net>
Tested-by: akspecs <akspecs@gmail.com>
Acked-by: Robin Jarry <robin@jarry.cc>
fetches missing headers when in visual selection mode. This prevents
large archive operations from panicking due to a nil pointer
dereference.
The archive command will return an error to the ui when a nil message is
encountered to signal that the message store is not ready yet.
Signed-off-by: Koni Marti <koni.marti@gmail.com>
Display threads in the message list. For now, only supported by the
notmuch backend and on IMAP when the server supports the THREAD
extension.
Setting threading-enable=true is global and will cause the message list
to be empty with maildir:// accounts.
Co-authored-by: Kevin Kuehler <keur@xcf.berkeley.edu>
Co-authored-by: Reto Brunner <reto@labrat.space>
Signed-off-by: Robin Jarry <robin@jarry.cc>
More mail flags can now be set, unset, and toggled, not just the
read/seen flag.
This functionality is implemented with a new `:flag` and `:unflag`
command, which are extensions to the matching `:read` and `:unread`
commands, adding support for different flags. In fact, the
`read`/`unread` commands are now recognized aliases to `flag`/`unflag`.
The new commands are also well documented in aerc(1).
The change mostly extends the previous read/unread setting functionality
by adding a selection for the flag to change.
This changes the ui to show the spinner while we are sorting. It only
shows one line of the spinner since there are an unknown number of
messages at this time.
Apparently sending an event for every incoming messageInfo slows down
the application significantly.
Therefore this slows down the emmision rate, on the cost of being out of date
in some cases.
This reverts commit bd4df53009.
I did not properly untangle the opening / dirlist update of each other.
This interferes with the imap worker, hence the revert
Actions such as read / unread or the addition of new messages do change
the read/unread/recent count. Hence we request an update from the workers.
Workers going over the network should probably cache the information and invalidate
it only if necessary
Previously, sending a DirectoryInfo assumed that a directory change
happened. However we don't want that if we only want to update the
unread message count.
Previously the workers returned a mixture of decoded / encoded parts.
This lead to a whole bunch of issues.
This commit changes the msgviewer and the commands to assume parts to already
be decoded
A panic could happen when multiple delete messages are sent one after
another without waiting until there are no messages left to be deleted:
panic: runtime error: makeslice: len out of range
goroutine 1 [running]:
git.sr.ht/~sircmpwn/aerc/lib.(*MessageStore).Update(0xc000592e00, 0xa8fe60, 0xc0003340f0)
/go/src/git.sr.ht/~sircmpwn/aerc/lib/msgstore.go:222 +0x5b8
git.sr.ht/~sircmpwn/aerc/widgets.(*AccountView).onMessage(0xc0000a0460, 0xa8fe60, 0xc0003340f0)
/go/src/git.sr.ht/~sircmpwn/aerc/widgets/account.go:251 +0x307
git.sr.ht/~sircmpwn/aerc/widgets.(*AccountView).Tick(0xc0000a0460, 0xc0001496b0)
/go/src/git.sr.ht/~sircmpwn/aerc/widgets/account.go:90 +0xa1
git.sr.ht/~sircmpwn/aerc/widgets.(*Aerc).Tick(0xc0000a9f40, 0xc000020501)
/go/src/git.sr.ht/~sircmpwn/aerc/widgets/aerc.go:123 +0x91
main.main()
/go/src/git.sr.ht/~sircmpwn/aerc/aerc.go:182 +0x5bf
The make that blows up is:
uids := make([]uint32, len(store.uids)-len(msg.Uids))
This change simply checks whether the make is going to be valid before
starting to work on the actual delete. If there are more messages queued
to be deleted than what's left in the store, then we're obviously in an
inconsistent state, ask for an update and break.
This addresses occasional crashes when a `MessageInfo` event reached the message
store before `DirectoryContents`, particularly on slower (imap) accounts.
There is a command and config option. The criteria are a list of the
sort criterion and each can be individually reversed.
This only includes support for sorting in the maildir backend currently.
The other backends are not supported in this patch.
Add an onUpdateDirs handler. This is used to invalidate the dirlist and
redraw with the correct number of recent/unread/total messages is shown.
A config option and formatting options are provided.
Sometimes I observe out-of-order messages when using a maildir inbox. It
appears that the UIDs for these messages are returned out of order by
the MessageStore. In order for a maildir MessageStore to return messages
in most recently received order, it must have already opened all
messages and parsed the date to use as a sort key. Rather than implement
that, simply sort messages by time as we display. This fix shows my
emails in order.
Add a "new-message-bell" option to the UI section of aerc.conf. A new
hook into the message store allows the msglist widget to detect new
messages being added to the displayed list. When new messages are
delivered, and the new-message-bell option is enabled (as it is by
default), the terminal will beep.
When filter is active we want to use store.results instead of
store.uids, since we are dealing with a subset of the uids. Otherwise
any methods involving len will have undefined behavior.
Signed-off-by: Kevin Kuehler <keur@ocf.berkeley.edu>
This patch sets up the trigger config section of aerc.conf.
Each trigger has its own function which is called from the place where
it is triggered. Currently only the new-email trigger is implemented.
The triggers make use of format strings. For instance, in the new-email
trigger this allows the user to select the trigger command and also the
information extracted from the command and placed into their command.
To actually execute the trigger commands the keypresses are simulated.
Further triggers can be implemented in the future.
Formatting of the command is moved to a new package.
A sequence-set is an IMAP-specific implementation detail. Throughout the
UI, aerc simply operates using lists of opaque identifiers. In order to
loosen the coupling between the UI and IMAP in particular, replace most
usages of imap.SeqSet with []uint32, leaving the translation to a SeqSet
to the IMAP backend as needed.
Before, the information needed to display different parts of the UI was
tightly coupled to the specific messages being sent back and forth to
the backend worker. Separating out a models package allows us to be more
specific about exactly what a backend is able to and required to
provide for the UI.
Adds an archive command that moves the current message into the folder
specified in the account config entry.
Supports three layouts at this point:
- flat: puts all messages next to each other
- year: creates a folder per year
- month: same as above, plus folders per month
This also adds a "-p" argument to "cp" and "mv" that works like
"--parents" on mkdir(1). We use this to auto-create the directories
for the archive layout.
This commit introduces a new Aerc.Tick function that should be called to
refresh the internal state. This in turn makes each AccountView process worker
events.
The UI goroutine repeatedly refreshes the internal state before drawing a new
frame. The reason for this is that many worker messages may need to be
processed for a single frame, and drawing the UI is far slower than refreshing
the internal state. This has been confirmed in my testing (calling Aerc.Tick
only once per frame results in a slower display).
Many synchronization code has been removed. We can now write widgets without
having to care so much about races. The remaining sync users are:
- widgets/spinner: the spinner value is updated from inside an internal
goroutine
- lib/ui/invalidatable: Invalidate may be called from any goroutine
- lib/ui/grid: same
- lib/ui/ui: an internal goroutine needs read access to UI.exit
- worker/types/worker: Worker.callbacks is used for both worker and UI
callbacks
The exact goroutine requirements for Drawable have been documented.
MessageStore has a lot of exported fields that can be read from the outside.
Each read must be protected, because a call from Update could happen at any
time.