Commit aca1e539 authored by Charles Lindsay's avatar Charles Lindsay

Remove folders locally that were removed on server

Closes: bgo #714357
parent 983c48ea
......@@ -1230,10 +1230,21 @@ public class GearyController : Geary.BaseObject {
if (unavailable != null) {
foreach (Geary.Folder folder in unavailable) {
main_window.folder_list.remove_folder(folder);
if (folder.account == current_account) {
if (main_window.main_toolbar.copy_folder_menu.has_folder(folder))
main_window.main_toolbar.copy_folder_menu.remove_folder(folder);
if (main_window.main_toolbar.move_folder_menu.has_folder(folder))
main_window.main_toolbar.move_folder_menu.remove_folder(folder);
}
if (folder.special_folder_type == Geary.SpecialFolderType.INBOX &&
inboxes.has_key(folder.account)) {
inboxes.unset(folder.account);
new_messages_monitor.remove_folder(folder);
}
folder.special_folder_type_changed.disconnect(on_special_folder_type_changed);
}
}
}
......
......@@ -23,10 +23,13 @@ public class FolderList.AccountBranch : Sidebar.Branch {
account.information.notify["nickname"].connect(on_nicknamed_changed);
graft(get_root(), user_folder_group);
entry_removed.connect(on_entry_removed);
}
~AccountBranch() {
account.information.notify["nickname"].disconnect(on_nicknamed_changed);
entry_removed.disconnect(on_entry_removed);
}
private void on_nicknamed_changed() {
......@@ -123,4 +126,10 @@ public class FolderList.AccountBranch : Sidebar.Branch {
prune(entry);
folder_entries.unset(folder.path);
}
private void on_entry_removed(Sidebar.Entry entry) {
FolderEntry? folder_entry = entry as FolderEntry;
if (folder_entry != null && folder_entries.has_key(folder_entry.folder.path))
folder_entries.unset(folder_entry.folder.path);
}
}
......@@ -213,6 +213,29 @@ private class Geary.ImapDB.Account : BaseObject {
}, cancellable);
}
public async void delete_folder_async(Geary.Folder folder, Cancellable? cancellable)
throws Error {
check_open();
Geary.FolderPath path = folder.path;
yield db.exec_transaction_async(Db.TransactionType.RW, (cx) => {
int64 folder_id;
do_fetch_folder_id(cx, path, false, out folder_id, cancellable);
if (folder_id == Db.INVALID_ROWID)
return Db.TransactionOutcome.ROLLBACK;
if (do_has_children(cx, folder_id, cancellable)) {
debug("Can't delete folder %s because it has children", folder.to_string());
return Db.TransactionOutcome.ROLLBACK;
}
do_delete_folder(cx, folder_id, cancellable);
return Db.TransactionOutcome.COMMIT;
}, cancellable);
}
/**
* Only updates folder's STATUS message count, attributes, recent, and unseen; UIDVALIDITY and UIDNEXT
* updated when the folder is SELECT/EXAMINED (see update_folder_select_examine_async()) unless
......@@ -1245,6 +1268,13 @@ private class Geary.ImapDB.Account : BaseObject {
return do_fetch_folder_id(cx, path.get_parent(), create, out parent_id, cancellable);
}
private bool do_has_children(Db.Connection cx, int64 folder_id, Cancellable? cancellable) throws Error {
Db.Statement stmt = cx.prepare("SELECT 1 FROM FolderTable WHERE parent_id = ?");
stmt.bind_rowid(0, folder_id);
Db.Result result = stmt.exec(cancellable);
return !result.finished;
}
// Turn the collection of folder paths into actual folder ids. As a
// special case, if "folderless" or orphan emails are to be blacklisted,
// set the out bool to true.
......
......@@ -633,12 +633,25 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.AbstractAccount {
Gee.Collection<MinimalFolder> engine_added = new Gee.ArrayList<Geary.Folder>();
engine_added.add_all(build_folders(folders_to_build));
// TODO: Remove local folders no longer available remotely.
foreach (Geary.Folder folder in to_remove)
debug(@"Need to remove folder $folder");
notify_folders_available_unavailable(null, to_remove);
if (engine_added.size > 0)
notify_folders_added_removed(sort_by_path(engine_added), null);
Gee.ArrayList<Geary.Folder> engine_removed = new Gee.ArrayList<Geary.Folder>();
// Sort by path length descending, so we always remove children first.
to_remove.sort((a, b) => b.path.get_path_length() - a.path.get_path_length());
foreach (Geary.Folder folder in to_remove) {
try {
debug("Locally deleting removed folder %s", folder.to_string());
yield local.delete_folder_async(folder, cancellable);
engine_removed.add(folder);
} catch (Error e) {
debug("Unable to locally delete removed folder %s: %s", folder.to_string(), e.message);
}
}
if (engine_added.size > 0 || engine_removed.size > 0)
notify_folders_added_removed(sort_by_path(engine_added), sort_by_path(engine_removed));
// report all altered folders
if (altered_paths.size > 0) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment