For now, the undo stack is 1-deep with no redo facility, which mimics
Gmail's facility. We can consider later offering a more involved
undo stack, but would like to try this out for now and work out the
kinks before becoming more aggressive.
Although this doesn't solve the problems described in the bug, there
was some perceived improvement in reducing the occurrence. These
changes also clean up the code, being verbose about distinguishing
between sorting by sent date (i.e. the Date: header field) and
received date (i.e. in EmailProperties, i.e. IMAP's INTERNALDATE).
There was one comparator that did not have a proper stabilizer; that's
fixed here as well.
This allows us to avoid messing with the state of the conversation
viewer when we're composing a new message. Instead, we hide it
completely and show only the ComposerBox.
The styling of paned composer is changed to resemble that of the inline
composers. Because of restrictions on what styles are available for
various widgets, the ComposerBox becomes a Gtk.Frame, and its border
simulates the margin while some padding and an inset shadow simulate the
border. I haven't figured out how to do an outset box-shadow.
https://bugzilla.gnome.org/show_bug.cgi?id=743670
We search for HTML-like tags in signatures, and don't do much as much
escaping if we find one. For .signature files detected to be HTML, we
insert them without any change. User-entered signatures get their
whitespace protected, even when HTML is detected. The existing code for
preserving whitespace doesn't work when there's already HTML code in the
text (it converts "<a b>" to "<a b>"), so instead we preserve the
whitespace with CSS.
A preview of the signature is added to the the UI. There's a TextView
and a WebView in a Stack, and we swap between them with a StackSwitcher.
Some of the packing details are changed so that these views are the
thing that expands when the dialog size changes.
https://bugzilla.gnome.org/show_bug.cgi?id=738895
When messages have been appended and removed from a folder, Geary has
no choice but to do a full UID scan of the server to figure out
exactly what's changed. Prior code use a FETCH command, but SEARCH is
a better choice because there's less overhead in a SEARCH result: only
the UIDs are returned and they may be returned in a single line or in
batches. Also, there's no reason to return those results in a sorted
set, which was driving up transaction time, so an unsorted set is
returned.
On my account, a full normalization of All Mail went from 8s to 1s
with this change.
Selection change processing is now done in idle handler by
ConversationListView to allow for back-to-back selection changes to be
processed one time only, as well as to allow for ConversationMonitor
signals to be handled in any order (by ConversationListStore and
others).
When certain punctuation marks are found in a search term (i.e. an
extended name, or with an email address), treat the search as an
exact-term search to remove spurious search results.
The App.ConversationMonitor would blacklist the current folder when
searching for email related to a conversation. Earlier searching for
related emails returned SearchEmailIdentifiers and there was a
question about determining equivalence with ImapDB.EmailIdentifiers.
However, that's no longer the case (Message-ID searching returnes
ImapDB.EmailIdentifiers), so searching within the current folder is
not a problem.
This means that constructing conversations where very old messages are
in the current folder -- for example, All Mail -- will be loaded
without expanding the window to load all email in the span.
This is only allowed when quoting the entire message, no keystrokes have
been made, and the cursor has not been moved. To ensure this last, we
watch editor.selection_changed, but only after we've set the body up.
A note is added to the label in the composer toolbar when this is
active. This was previously called the draft_save_text, but we rename
it here to reflect the current usage.
The quote is deleted by clearing the message entirely, and then
recreating the initial state. This caused critical errors in
update_actions(), so we now check for the selection being null before
proceeding.
https://bugzilla.gnome.org/show_bug.cgi?id=741609
If a command fails due to a hard error (connection dropped, network
loss, etc.), the command is preserved in the in-memory Folder queue
and retried when the connection is reestablished. This makes Geary
more robust and resistant to simple errors due to connection loss,
i.e. archiving a message and having it return later because the
archive command was dropped and, when the connection reestablished,
the message "reappears" because it's still on the server.
Note that this is *not* offline mode or a replacement for it, merely
a way to make Geary more robust when a user's connection is flaky.
ClientConnection state machine had a timing hole where two DONEs could
be issued in near-succession when closing a single IDLE command.
The hole is issuing the DONE *before* the server acknowledged it
was idling. When the idling continuation response was received,
the state machine would go to IDLE. Then, when the next command
was submitted, a second DONE would be issued. The second DONE
would be treated by the server as a tag with no command, causing
a CLIENTBUG response.
This tracks outstanding DONE commands when deidling and prevents
switching to the IDLE state when an idline continuation response
is received while waiting for the DONE to complete.
This patch drastically improves network connection handling and
reestablishment. In particular, the ImapEngine.Folder's open_count
wasn't always properly maintained (in the engine and the client)
causing connection reestablishment issues. Also, prior code attempted
to deduce when to reestablish a connection based on the type of Error
encountered. Now, as long as the Folder's open_count is greater than
zero, reestablishment will be attempted (with a back-off algorithm and
special cases in the ClientSessionManager preventing continual login,
i.e. when credentials are bad).
ClientSessionManager also has a back-off algorithm when it's adjusting
its session pool and uses the NetworkMonitor to detect when the host
is simply unavailable due to the network being unavailable (to prevent
continuous retries).
In addition to the above bug, this patch solves the following tickets:
Bug #714595
Bug #725959
Bug #712960
Clearing the ConversationListStore caused multiple selection-changed
notifications to the ConversationListView, whose signals in turn
caused I/O in the GearyController. This stops that process in its
tracks.
The composer can hide itself while the draft manager is in the process
of closing up. If we try to close that composer again, it should
automatically return PENDING_CLOSE instead of asking the user what to
do.
We do this heuristically, by noting which messages it is in reply to and
seeing if it matches the unmodified reply or reply all states. This
isn't perfect; notably forwarded messages are picked up.
We hide the existing draft in the conversation viewer as soon as we open
the composer. We also ensure that future versions of this draft will
also be hidden. The list of emails to be hidden is cleared when the
conversation viewer is, so we query all open composers at this point to
see which email ids should be hidden.
https://bugzilla.gnome.org/show_bug.cgi?id=743067
When the user replies with a quote to a second message, the composer
moves into a paned below the conversation viewer. This makes it easy to
scroll through the conversation and select text for replies.
The Gtk.Paned acutally holds a Box, which in turn can hold many
ComposerBoxes. Only one is shown at a time, but the model used
elsewhere is that each ComposerWidget has a ComposerContainer until it
is destroyed. When a composer is closed, it hides while finishing up
asynchronous work. This allows us to hold hidden paned composers as
they finish up their work.
The logic for focus handling at detachment is moved into the
ComposerWidget from ComposerEmbed, since it may also be detached from
the paned state. ComposerContainers gain a remove_composer() method
that does the container's clean up, as well as returning the focused
widget. The ComposerWindow's remove_composer() method should never be
called.
https://bugzilla.gnome.org/show_bug.cgi?id=738188
When replying to a message, we use the existing inline composer if it
already references the message we're replying to, or if we're replying
with a quote. Replies without quotes get made into new composers.
When adding a new message as a reply in a composer, we add the relevant
addresses to the to and cc lines, based on the current reply type. We
remove duplicates, and don't include any to addresses as cc. We also
keep track of a total to and total cc list, which gets swapped in if a
reply action is to change the reply type.
We keep track of all the replied-to message ids and include all of them
in the In-Reply-To header. However, the References header only includes
message ids from the first message replied to. This is because RFC 2822
requires this header to represent a single lineage, which we cannot
guarantee if we're replying to different branches of the conversation.
With the Empty button now attached to Archive/Trash/Delete, it's now
less lopsided for only Archive to have a label. This removes the
label from Trash/Delete (which also makes it more innocuous when the
user presses Shift a lot, i.e. while editing in the inline composer),
which in turns simplifies building the main toolbar.
At two seconds, the background AccountSynchronizer kicks in too
quickly and can interfere with foreground operations, especially when
the Inbox is being normalized at startup.
do_save_attachments() is called by schema update 22, which is prior
to when DeleteAttachmentFileTable was introduced (in update 24).
Ignore error if cannot remove from that table, i.e. it doesn't exist
yet.
Trash and Spam folders may now be emptied by Geary. A user warning is
presented, as the operation cannot be undone and deletes mail on the
server, not just locally.
Issue introduced with recent move to DraftManager. When Geary is
closed with an open composer, the window would hide but the app
itself would hang. This was due to telling the GearyController that
a close was pending when it was not. Now, when PENDING is returned,
the draft is saved or discarded (based on user input) and the
DraftManager fully closed, ensuring the I/O operation is flushed and
completed.
Introduces a DraftManager class which handles saving and deleting
drafts for the composer and error situations. Not perfect yet w/o
better support in the Engine for dealing with network disconnects
and offline mode, but much better than before for ensuring that drafts
are not orphaned in the Drafts folder.
Since the dawn of time, Folder and Account were interfaces. It's
become obvious over time nothing was gained by making them interfaces,
only a duplication of effort when changing their API to update the
interface and then the abstract base class all other classes derive
from.
This makes both abstract classes, cleaning up the code a bit and
reducing complexity.
Geary now offers "true" deletion of messages in Gmail. It does this
by moving the offending email to the Trash folder and then expunging
them from the Trash.
Fortunately, this works with the composer without changes, meaning
discarded drafts won't sit in the Trash for 30 days.
Email address such as ["<S dude@example. com>" <s.dude@example.com>]
was not being escaped for HTML, so the S tag would strike-out the
remaining text in the address line. This patch corrects that.
While working on this, I noticed as well that the mailto: link was not
being properly formed due to lack of quoting. By using
MailboxAddress.to_rfc822_string(), problem solved.