Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Live update unread mail badge for INBOX #722

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 57 additions & 1 deletion src/FoldersView/AccountSourceItem.vala
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public class Mail.AccountSourceItem : Granite.Widgets.SourceList.ExpandableItem

private GLib.Cancellable connect_cancellable;
private Gee.HashMap<string, FolderSourceItem> folder_items;
private Gee.HashMap<string, Camel.Folder> folders;
private AccountSavedState saved_state;
private unowned Camel.OfflineStore offlinestore;

Expand All @@ -38,6 +39,7 @@ public class Mail.AccountSourceItem : Granite.Widgets.SourceList.ExpandableItem
visible = true;
connect_cancellable = new GLib.Cancellable ();
folder_items = new Gee.HashMap<string, FolderSourceItem> ();
folders = new Gee.HashMap<string, Camel.Folder> ();
saved_state = new AccountSavedState (account);
saved_state.bind_with_expandable_item (this);

Expand All @@ -61,7 +63,7 @@ public class Mail.AccountSourceItem : Granite.Widgets.SourceList.ExpandableItem
try {
var folderinfo = yield offlinestore.get_folder_info (null, Camel.StoreGetFolderInfoFlags.RECURSIVE, GLib.Priority.DEFAULT, connect_cancellable);
if (folderinfo != null) {
show_info (folderinfo, this);
folder_created (folderinfo);
}
} catch (Error e) {
critical (e.message);
Expand Down Expand Up @@ -89,19 +91,36 @@ public class Mail.AccountSourceItem : Granite.Widgets.SourceList.ExpandableItem
private void folder_renamed (string old_name, Camel.FolderInfo folder_info) {
var item = folder_items[old_name];
item.update_infos (folder_info);

lock (folders) {
if (folders.has_key (old_name)) {
Camel.Folder folder;
if (folders.unset (old_name, out folder)) {
folders.set (folder_info.full_name, folder);

folder.refresh_info.begin (GLib.Priority.DEFAULT, null);
}
}
}
}

private void folder_deleted (Camel.FolderInfo folder_info) {
Mail.FolderSourceItem? item = folder_items[folder_info.full_name];
if (item != null) {
item.parent.remove (item);
folder_items.unset (folder_info.full_name);

lock (folders) {
folders.unset (folder_info.full_name);
}
}
}

private void folder_created (Camel.FolderInfo folder_info) {
if (folder_info.parent == null) {
show_info (folder_info, this);
connect_folder_changed (folder_info);

} else {
unowned Camel.FolderInfo parent_info = (Camel.FolderInfo) folder_info.parent;
var parent_item = folder_items[parent_info.full_name];
Expand All @@ -111,10 +130,47 @@ public class Mail.AccountSourceItem : Granite.Widgets.SourceList.ExpandableItem
folder_created (folder_info);
} else {
show_info (folder_info, parent_item);
connect_folder_changed (folder_info);
}
}
}

private void connect_folder_changed (Camel.FolderInfo folder_info) {
offlinestore.get_folder.begin (folder_info.full_name, Camel.StoreGetFolderFlags.NONE, GLib.Priority.DEFAULT, null, (obj, res) => {
try {
var folder = offlinestore.get_folder.end (res);
folder.changed.connect ((changes) => {
folder_changed (folder, changes);
});

lock (folders) {
folders.set (folder_info.full_name, folder);
}

} catch (Error e) {
warning ("Error retrieving folder '%s' from store: %s", folder_info.full_name, e.message);
}
});
}

private void folder_changed (Camel.Folder folder, Camel.FolderChangeInfo changes) {
Mail.FolderSourceItem? item = folder_items[folder.full_name];

if (item != null && account.service is Camel.Store) {
var store = (Camel.Store) account.service;

store.get_folder_info.begin (folder.full_name, Camel.StoreGetFolderInfoFlags.REFRESH, GLib.Priority.DEFAULT, null, (obj, res) => {
try {
var folder_info = store.get_folder_info.end (res);
item.update_infos (folder_info);

} catch (Error e) {
warning ("Error refreshing folder info for '%s': %s", folder.full_name, e.message);
}
});
}
}

private async void reload_folders () {
var offlinestore = (Camel.OfflineStore) account.service;
foreach (var folder_item in folder_items.values) {
Expand Down
7 changes: 5 additions & 2 deletions src/FoldersView/FolderSourceItem.vala
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ public class Mail.FolderSourceItem : Granite.Widgets.SourceList.ExpandableItem {
public void update_infos (Camel.FolderInfo folderinfo) {
name = folderinfo.display_name;
full_name = folderinfo.full_name;

badge = "";
if (folderinfo.unread > 0) {
badge = "%d".printf (folderinfo.unread);
}
Expand All @@ -63,7 +65,7 @@ public class Mail.FolderSourceItem : Granite.Widgets.SourceList.ExpandableItem {
case Camel.FolderInfoFlags.TYPE_TRASH:
icon = new ThemedIcon (folderinfo.total == 0 ? "user-trash" : "user-trash-full");
can_modify = false;
badge = null;
badge = "";
break;
case Camel.FolderInfoFlags.TYPE_JUNK:
icon = new ThemedIcon ("edit-flag");
Expand All @@ -72,11 +74,12 @@ public class Mail.FolderSourceItem : Granite.Widgets.SourceList.ExpandableItem {
case Camel.FolderInfoFlags.TYPE_SENT:
icon = new ThemedIcon ("mail-sent");
can_modify = false;
badge = "";
break;
case Camel.FolderInfoFlags.TYPE_ARCHIVE:
icon = new ThemedIcon ("mail-archive");
can_modify = false;
badge = null;
badge = "";
break;
case Camel.FolderInfoFlags.TYPE_DRAFTS:
icon = new ThemedIcon ("mail-drafts");
Expand Down
62 changes: 52 additions & 10 deletions src/FoldersView/GroupedFolderSourceItem.vala
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public class Mail.GroupedFolderSourceItem : Granite.Widgets.SourceList.Item {

private GLib.Cancellable connect_cancellable;
private Gee.HashMap<Backend.Account, Camel.FolderInfo?> account_folderinfo;
private Gee.HashMap<Backend.Account, Camel.Folder?> account_folders;

public GroupedFolderSourceItem (Mail.Backend.Session session, Camel.FolderInfoFlags folder_type) {
Object (session: session, folder_type: folder_type);
Expand All @@ -32,6 +33,7 @@ public class Mail.GroupedFolderSourceItem : Granite.Widgets.SourceList.Item {
visible = true;
connect_cancellable = new GLib.Cancellable ();
account_folderinfo = new Gee.HashMap<Backend.Account, Camel.FolderInfo?> ();
account_folders = new Gee.HashMap<Backend.Account, Camel.Folder?> ();

switch (folder_type & Camel.FOLDER_TYPE_MASK) {
case Camel.FolderInfoFlags.TYPE_INBOX:
Expand Down Expand Up @@ -91,7 +93,9 @@ public class Mail.GroupedFolderSourceItem : Granite.Widgets.SourceList.Item {
private async void load_folder_info (Mail.Backend.Account account) {
var offlinestore = (Camel.OfflineStore) account.service;
var full_name = build_folder_full_name (account);

Camel.FolderInfo? folderinfo = null;
Camel.Folder? folder = null;

if (full_name != null) {
try {
Expand All @@ -102,11 +106,26 @@ public class Mail.GroupedFolderSourceItem : Granite.Widgets.SourceList.Item {
warning ("Unable to fetch %s of account '%s': %s", full_name, account.service.display_name, e.message);
}
}

try {
folder = yield offlinestore.get_folder (full_name, Camel.StoreGetFolderFlags.NONE, GLib.Priority.DEFAULT, connect_cancellable);

folder.changed.connect ((changes) => {
account_folder_changed (account, folder, changes);
});

} catch (Error e) {
warning ("Error retrieving folder '%s' from store: %s", full_name, e.message);
}
}

lock (account_folderinfo) {
account_folderinfo.set (account, folderinfo);
}

lock (account_folders) {
account_folders.set (account, folder);
}
update_infos ();
}

Expand All @@ -116,20 +135,43 @@ public class Mail.GroupedFolderSourceItem : Granite.Widgets.SourceList.Item {
}
}

private void account_folder_changed (Mail.Backend.Account account, Camel.Folder folder, Camel.FolderChangeInfo changes) {
if (account.service is Camel.Store) {
var store = (Camel.Store) account.service;

store.get_folder_info.begin (folder.full_name, Camel.StoreGetFolderInfoFlags.REFRESH, GLib.Priority.DEFAULT, null, (obj, res) => {
try {
var folder_info = store.get_folder_info.end (res);
lock (account_folderinfo) {
account_folderinfo.set (account, folder_info);
}

update_infos ();

} catch (Error e) {
warning ("Error refreshing folder info for '%s': %s", folder.full_name, e.message);
}
});
}
}

private void update_infos () {
badge = null;
var total_unread = 0;
lock (account_folderinfo) {
foreach (var entry in account_folderinfo) {
if (entry.value == null) {
continue;
badge = "";

if (Camel.FolderInfoFlags.TYPE_INBOX == (folder_type & Camel.FOLDER_TYPE_MASK)) {
var total_unread = 0;
lock (account_folderinfo) {
foreach (var entry in account_folderinfo) {
if (entry.value == null) {
continue;
}
total_unread += entry.value.unread;
}
total_unread += entry.value.unread;
}
}

if (total_unread > 0) {
badge = "%d".printf (total_unread);
if (total_unread > 0) {
badge = "%d".printf (total_unread);
}
}
}

Expand Down