Don't save draft when UIDPLUS is not present: Closes bgo#713983
Without UIDPLUS Geary currently cannot determine the UID of the drafts it saves to the server, and so it cannot delete them when the draft is saved again or the message is sent. This patch simply checks if UIDPLUS is supported, and if not, does not save the draft to the server. Although a string is included in this patch, it's a duplicate of an existing string and so technically does not break string freeze.
This commit is contained in:
parent
173ed7dcbe
commit
730b33d806
7 changed files with 49 additions and 15 deletions
|
|
@ -667,28 +667,39 @@ public class ComposerWindow : Gtk.Window {
|
|||
update_from_field();
|
||||
}
|
||||
|
||||
private bool can_save() {
|
||||
return (drafts_folder != null && drafts_folder.get_open_state() == Geary.Folder.OpenState.BOTH
|
||||
&& !drafts_folder.properties.create_never_returns_id && editor.can_undo());
|
||||
}
|
||||
|
||||
public bool should_close() {
|
||||
if (!editor.can_undo())
|
||||
return true;
|
||||
bool try_to_save = can_save();
|
||||
|
||||
present();
|
||||
AlertDialog dialog;
|
||||
|
||||
if (drafts_folder == null) {
|
||||
if (drafts_folder == null && try_to_save) {
|
||||
dialog = new ConfirmationDialog(this,
|
||||
_("Do you want to discard the unsaved message?"), null, Stock._DISCARD);
|
||||
} else {
|
||||
} else if (try_to_save) {
|
||||
dialog = new TernaryConfirmationDialog(this,
|
||||
_("Do you want to discard this message?"), null, Stock._KEEP, Stock._DISCARD,
|
||||
Gtk.ResponseType.CLOSE);
|
||||
} else {
|
||||
dialog = new ConfirmationDialog(this,
|
||||
_("Do you want to discard this message?"), null, Stock._DISCARD);
|
||||
}
|
||||
|
||||
Gtk.ResponseType response = dialog.run();
|
||||
if (response == Gtk.ResponseType.CANCEL || response == Gtk.ResponseType.DELETE_EVENT) {
|
||||
return false; // Cancel
|
||||
} else if (response == Gtk.ResponseType.OK) {
|
||||
save_and_exit.begin(); // Save
|
||||
return false;
|
||||
if (try_to_save) {
|
||||
save_and_exit.begin(); // Save
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
delete_and_exit.begin(); // Discard
|
||||
return false;
|
||||
|
|
@ -798,6 +809,11 @@ public class ComposerWindow : Gtk.Window {
|
|||
destroy(); // Only close window after draft is deleted; this closes the drafts folder.
|
||||
}
|
||||
|
||||
private void on_drafts_opened(Geary.Folder.OpenState open_state, int count) {
|
||||
if (open_state == Geary.Folder.OpenState.BOTH)
|
||||
reset_draft_timer();
|
||||
}
|
||||
|
||||
// Returns the drafts folder for the current From account.
|
||||
private async void open_drafts_folder_async(Cancellable cancellable) throws Error {
|
||||
yield close_drafts_folder_async(cancellable);
|
||||
|
|
@ -808,9 +824,11 @@ public class ComposerWindow : Gtk.Window {
|
|||
if (folder == null)
|
||||
return; // No drafts folder.
|
||||
|
||||
yield folder.open_async(Geary.Folder.OpenFlags.FAST_OPEN, cancellable);
|
||||
yield folder.open_async(Geary.Folder.OpenFlags.FAST_OPEN | Geary.Folder.OpenFlags.NO_DELAY,
|
||||
cancellable);
|
||||
|
||||
drafts_folder = folder;
|
||||
drafts_folder.opened.connect(on_drafts_opened);
|
||||
}
|
||||
|
||||
private async void close_drafts_folder_async(Cancellable? cancellable = null) throws Error {
|
||||
|
|
@ -818,6 +836,7 @@ public class ComposerWindow : Gtk.Window {
|
|||
return;
|
||||
|
||||
// Close existing folder.
|
||||
drafts_folder.opened.disconnect(on_drafts_opened);
|
||||
yield drafts_folder.close_async(cancellable);
|
||||
drafts_folder = null;
|
||||
}
|
||||
|
|
@ -835,7 +854,7 @@ public class ComposerWindow : Gtk.Window {
|
|||
}
|
||||
|
||||
private async void save_async(Cancellable? cancellable) {
|
||||
if (drafts_folder == null)
|
||||
if (drafts_folder == null || !can_save())
|
||||
return;
|
||||
|
||||
draft_save_label.label = DRAFT_SAVING_TEXT;
|
||||
|
|
@ -1555,7 +1574,7 @@ public class ComposerWindow : Gtk.Window {
|
|||
|
||||
// Resets the draft save timeout.
|
||||
private void reset_draft_timer() {
|
||||
if (!editor.can_undo())
|
||||
if (!can_save())
|
||||
return;
|
||||
|
||||
draft_save_label.label = "";
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ private class Geary.AggregatedFolderProperties : Geary.FolderProperties {
|
|||
*/
|
||||
public AggregatedFolderProperties(bool is_local_only, bool is_virtual) {
|
||||
// Set defaults.
|
||||
base(0, 0, Trillian.UNKNOWN, Trillian.UNKNOWN, Trillian.UNKNOWN, is_local_only, is_virtual);
|
||||
base(0, 0, Trillian.UNKNOWN, Trillian.UNKNOWN, Trillian.UNKNOWN, is_local_only, is_virtual, false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -59,8 +59,16 @@ public abstract class Geary.FolderProperties : BaseObject {
|
|||
*/
|
||||
public bool is_virtual { get; private set; }
|
||||
|
||||
/**
|
||||
* True if APPEND on the folder will never return the created UID. This is
|
||||
* for servers that don't support UIDPLUS. Most servers support UIDPLUS,
|
||||
* so this will usually be false.
|
||||
*/
|
||||
public bool create_never_returns_id { get; protected set; }
|
||||
|
||||
protected FolderProperties(int email_total, int email_unread, Trillian has_children,
|
||||
Trillian supports_children, Trillian is_openable, bool is_local_only, bool is_virtual) {
|
||||
Trillian supports_children, Trillian is_openable, bool is_local_only, bool is_virtual,
|
||||
bool create_never_returns_id) {
|
||||
this.email_total = email_total;
|
||||
this.email_unread = email_unread;
|
||||
this.has_children = has_children;
|
||||
|
|
@ -68,6 +76,7 @@ public abstract class Geary.FolderProperties : BaseObject {
|
|||
this.is_openable = is_openable;
|
||||
this.is_local_only = is_local_only;
|
||||
this.is_virtual = is_virtual;
|
||||
this.create_never_returns_id = create_never_returns_id;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ public class Geary.SearchFolderRoot : Geary.FolderRoot {
|
|||
|
||||
public class Geary.SearchFolderProperties : Geary.FolderProperties {
|
||||
public SearchFolderProperties(int total, int unread) {
|
||||
base(total, unread, Trillian.FALSE, Trillian.FALSE, Trillian.TRUE, true, true);
|
||||
base(total, unread, Trillian.FALSE, Trillian.FALSE, Trillian.TRUE, true, true, false);
|
||||
}
|
||||
|
||||
public void set_total(int total) {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
private class Geary.SmtpOutboxFolderProperties : Geary.FolderProperties {
|
||||
public SmtpOutboxFolderProperties(int total, int unread) {
|
||||
base (total, unread, Trillian.FALSE, Trillian.FALSE, Trillian.TRUE, true, false);
|
||||
base (total, unread, Trillian.FALSE, Trillian.FALSE, Trillian.TRUE, true, false, false);
|
||||
}
|
||||
|
||||
public void set_total(int total) {
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ public class Geary.Imap.FolderProperties : Geary.FolderProperties {
|
|||
// give the base class a zero email_unread, as the notion of "unknown" doesn't exist in
|
||||
// its contract
|
||||
base (messages, email_unread, Trillian.UNKNOWN, Trillian.UNKNOWN, Trillian.UNKNOWN, false,
|
||||
false);
|
||||
false, false);
|
||||
|
||||
select_examine_messages = messages;
|
||||
status_messages = -1;
|
||||
|
|
@ -82,7 +82,7 @@ public class Geary.Imap.FolderProperties : Geary.FolderProperties {
|
|||
|
||||
public FolderProperties.status(StatusData status, MailboxAttributes attrs) {
|
||||
base (status.messages, status.unseen, Trillian.UNKNOWN, Trillian.UNKNOWN, Trillian.UNKNOWN,
|
||||
false, false);
|
||||
false, false, false);
|
||||
|
||||
select_examine_messages = -1;
|
||||
status_messages = status.messages;
|
||||
|
|
@ -213,5 +213,9 @@ public class Geary.Imap.FolderProperties : Geary.FolderProperties {
|
|||
// update base class value (which clients see)
|
||||
email_unread = count;
|
||||
}
|
||||
|
||||
public void set_from_session_capabilities(Capabilities capabilities) {
|
||||
create_never_returns_id = !capabilities.supports_uidplus();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -95,6 +95,8 @@ private class Geary.Imap.Folder : BaseObject {
|
|||
session.status_response_received.connect(on_status_response);
|
||||
session.disconnected.connect(on_disconnected);
|
||||
|
||||
properties.set_from_session_capabilities(session.capabilities);
|
||||
|
||||
StatusResponse response = yield session.select_async(
|
||||
new MailboxSpecifier.from_folder_path(path, info.delim), cancellable);
|
||||
if (response.status != Status.OK) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue