Merge branch 'mjog/special-type-cleanup' into 'mainline'

Special folder type cleanup

See merge request GNOME/geary!482
This commit is contained in:
Michael Gratton 2020-03-31 07:44:27 +00:00
commit 4db87e1215
62 changed files with 604 additions and 566 deletions

View file

@ -128,7 +128,7 @@ src/client/util/util-email.vala
src/client/util/util-files.vala
src/client/util/util-gio.vala
src/client/util/util-gtk.vala
src/client/util/util-international.vala
src/client/util/util-i18n.vala
src/client/util/util-js.vala
src/client/util/util-migrate.vala
src/client/web-process/web-process-extension.vala
@ -173,7 +173,6 @@ src/engine/api/geary-revokable.vala
src/engine/api/geary-search-query.vala
src/engine/api/geary-service-information.vala
src/engine/api/geary-service-provider.vala
src/engine/api/geary-special-folder-type.vala
src/engine/app/app-conversation-monitor.vala
src/engine/app/app-conversation.vala
src/engine/app/app-draft-manager.vala

View file

@ -1022,6 +1022,7 @@ public class Accounts.AccountConfigV1 : AccountConfig, GLib.Object {
private const string FOLDER_ARCHIVE = "archive_folder";
private const string FOLDER_DRAFTS = "drafts_folder";
private const string FOLDER_JUNK = "junk_folder";
private const string FOLDER_SENT = "sent_folder";
private const string FOLDER_SPAM = "spam_folder";
private const string FOLDER_TRASH = "trash_folder";
@ -1110,7 +1111,13 @@ public class Accounts.AccountConfigV1 : AccountConfig, GLib.Object {
account.archive_folder_path = load_folder(folder_config, FOLDER_ARCHIVE);
account.drafts_folder_path = load_folder(folder_config, FOLDER_DRAFTS);
account.sent_folder_path = load_folder(folder_config, FOLDER_SENT);
account.spam_folder_path = load_folder(folder_config, FOLDER_SPAM);
// v3.32-3.36 used spam instead of junk
if (folder_config.has_key(FOLDER_SPAM)) {
account.junk_folder_path = load_folder(folder_config, FOLDER_SPAM);
}
if (folder_config.has_key(FOLDER_JUNK)) {
account.junk_folder_path = load_folder(folder_config, FOLDER_JUNK);
}
account.trash_folder_path = load_folder(folder_config, FOLDER_TRASH);
return account;
@ -1146,7 +1153,7 @@ public class Accounts.AccountConfigV1 : AccountConfig, GLib.Object {
save_folder(folder_config, FOLDER_ARCHIVE, account.archive_folder_path);
save_folder(folder_config, FOLDER_DRAFTS, account.drafts_folder_path);
save_folder(folder_config, FOLDER_SENT, account.sent_folder_path);
save_folder(folder_config, FOLDER_SPAM, account.spam_folder_path);
save_folder(folder_config, FOLDER_JUNK, account.junk_folder_path);
save_folder(folder_config, FOLDER_TRASH, account.trash_folder_path);
}
@ -1273,7 +1280,7 @@ public class Accounts.AccountConfigLegacy : AccountConfig, GLib.Object {
info.sent_folder_path = Geary.AccountInformation.build_folder_path(
config.get_string_list(SENT_MAIL_FOLDER_KEY)
);
info.spam_folder_path = Geary.AccountInformation.build_folder_path(
info.junk_folder_path = Geary.AccountInformation.build_folder_path(
config.get_string_list(SPAM_FOLDER_KEY)
);
info.trash_folder_path = Geary.AccountInformation.build_folder_path(
@ -1330,8 +1337,8 @@ public class Accounts.AccountConfigLegacy : AccountConfig, GLib.Object {
);
config.set_string_list(
SPAM_FOLDER_KEY,
(info.spam_folder_path != null
? new Gee.ArrayList<string>.wrap(info.spam_folder_path.as_array())
(info.junk_folder_path != null
? new Gee.ArrayList<string>.wrap(info.junk_folder_path.as_array())
: empty)
);
config.set_string_list(

View file

@ -384,7 +384,7 @@ public class Application.Client : Gtk.Application {
public override void startup() {
Environment.set_application_name(NAME);
Util.International.init(GETTEXT_PACKAGE, this.binary);
Util.I18n.init(GETTEXT_PACKAGE, this.binary);
Util.Date.init();
Configuration.init(this.is_installed, GSETTINGS_DIR);

View file

@ -234,7 +234,7 @@ public class Application.Configuration : Geary.BaseObject {
).get_maybe();
string[] langs = (value != null)
? value.get_strv()
: Util.International.get_user_preferred_languages();
: Util.I18n.get_user_preferred_languages();
return langs;
}
@ -245,7 +245,7 @@ public class Application.Configuration : Geary.BaseObject {
* client. By default, the set will contain languages based on
* environment variables.
*
* @see Util.International.get_user_preferred_languages
* @see Util.I18n.get_user_preferred_languages
*/
public void set_spell_check_languages(string[] value) {
this.settings.set_value(

View file

@ -23,7 +23,7 @@ internal class Application.Controller : Geary.BaseObject {
public static bool does_folder_support_trash(Geary.Folder? target) {
return (
target != null &&
target.special_folder_type != TRASH &&
target.used_as != TRASH &&
!target.properties.is_local_only &&
(target as Geary.FolderSupport.Move) != null
);
@ -39,9 +39,9 @@ internal class Application.Controller : Geary.BaseObject {
return false;
// if folder contains children, we must ensure that there is at least one of the same type
Geary.SpecialFolderType type = folder.special_folder_type;
Geary.Folder.SpecialUse type = folder.used_as;
foreach (Geary.Folder other in all) {
if (other.special_folder_type == type && other.path.parent == folder.path)
if (other.used_as == type && other.path.parent == folder.path)
return true;
}
@ -597,7 +597,7 @@ internal class Application.Controller : Geary.BaseObject {
"Conversation moved to %s",
"Conversations moved to %s",
conversations.size
).printf(destination.get_display_name()),
).printf(Util.I18n.to_folder_display_name(destination)),
/// Translators: Label for in-app
/// notification. String substitution is the name
/// of the source folder.
@ -605,7 +605,7 @@ internal class Application.Controller : Geary.BaseObject {
"Conversation restored to %s",
"Conversations restored to %s",
conversations.size
).printf(source.get_display_name())
).printf(Util.I18n.to_folder_display_name(source))
),
context.cancellable
);
@ -613,7 +613,7 @@ internal class Application.Controller : Geary.BaseObject {
}
public async void move_conversations_special(Geary.Folder source,
Geary.SpecialFolderType destination,
Geary.Folder.SpecialUse destination,
Gee.Collection<Geary.App.Conversation> conversations)
throws GLib.Error {
AccountContext? context = this.accounts.get(source.account.information);
@ -627,7 +627,7 @@ internal class Application.Controller : Geary.BaseObject {
"Conversation restored to %s",
"Conversations restored to %s",
messages.size
).printf(source.get_display_name());
).printf(Util.I18n.to_folder_display_name(source));
if (destination == ARCHIVE) {
Geary.FolderSupport.Archive? archive_source = (
@ -681,7 +681,7 @@ internal class Application.Controller : Geary.BaseObject {
"Conversation moved to %s",
"Conversations moved to %s",
messages.size
).printf(destination.get_display_name()),
).printf(Util.I18n.to_folder_display_name(dest)),
undone_tooltip
);
}
@ -691,7 +691,7 @@ internal class Application.Controller : Geary.BaseObject {
}
public async void move_messages_special(Geary.Folder source,
Geary.SpecialFolderType destination,
Geary.Folder.SpecialUse destination,
Gee.Collection<Geary.App.Conversation> conversations,
Gee.Collection<Geary.EmailIdentifier> messages)
throws GLib.Error {
@ -704,7 +704,7 @@ internal class Application.Controller : Geary.BaseObject {
"Message restored to %s",
"Messages restored to %s",
messages.size
).printf(source.get_display_name());
).printf(Util.I18n.to_folder_display_name(source));
if (destination == ARCHIVE) {
Geary.FolderSupport.Archive? archive_source = (
@ -760,7 +760,7 @@ internal class Application.Controller : Geary.BaseObject {
"Message moved to %s",
"Messages moved to %s",
messages.size
).printf(destination.get_display_name()),
).printf(Util.I18n.to_folder_display_name(dest)),
undone_tooltip
);
}
@ -788,7 +788,7 @@ internal class Application.Controller : Geary.BaseObject {
"Conversation labelled as %s",
"Conversations labelled as %s",
conversations.size
).printf(destination.get_display_name()),
).printf(Util.I18n.to_folder_display_name(destination)),
/// Translators: Label for in-app
/// notification. String substitution is the name
/// of the destination folder.
@ -796,7 +796,7 @@ internal class Application.Controller : Geary.BaseObject {
"Conversation un-labelled as %s",
"Conversations un-labelled as %s",
conversations.size
).printf(destination.get_display_name())
).printf(Util.I18n.to_folder_display_name(destination))
),
context.cancellable
);
@ -1183,7 +1183,7 @@ internal class Application.Controller : Geary.BaseObject {
private void on_account_email_removed(Geary.Folder folder,
Gee.Collection<Geary.EmailIdentifier> ids) {
if (folder.special_folder_type == OUTBOX) {
if (folder.used_as == OUTBOX) {
foreach (MainWindow window in this.application.get_main_windows()) {
window.status_bar.deactivate_message(StatusBar.Message.OUTBOX_SEND_FAILURE);
window.status_bar.deactivate_message(StatusBar.Message.OUTBOX_SAVE_SENT_MAIL_FAILED);
@ -1254,7 +1254,7 @@ internal class Application.Controller : Geary.BaseObject {
}
GLib.Cancellable cancellable = context.cancellable;
if (folder.special_folder_type == INBOX) {
if (folder.used_as == INBOX) {
if (context.inbox == null) {
context.inbox = folder;
}
@ -1270,7 +1270,7 @@ internal class Application.Controller : Geary.BaseObject {
while (has_prev) {
Geary.Folder folder = unavailable_iterator.get();
if (folder.special_folder_type == INBOX) {
if (folder.used_as == INBOX) {
context.inbox = null;
}
@ -2263,7 +2263,7 @@ private class Application.ArchiveEmailCommand : RevokableCommand {
// affected, so if the dest is the location, just assume
// they are for now.
foreach (var folder in removed) {
if (folder.special_folder_type == ARCHIVE) {
if (folder.used_as == ARCHIVE) {
ret = REMOVE;
break;
}
@ -2281,7 +2281,7 @@ private class Application.ArchiveEmailCommand : RevokableCommand {
// affected, so if the dest is the location, just assume they
// are for now.
return (
location.special_folder_type == ARCHIVE
location.used_as == ARCHIVE
? EmailCommand.StateChangePolicy.REMOVE
: base.email_removed(location, targets)
);

View file

@ -118,8 +118,8 @@ internal class Application.FolderStoreFactory : Geary.BaseObject {
}
private string _display_name;
public Geary.SpecialFolderType folder_type {
get { return this.backing.special_folder_type; }
public Geary.Folder.SpecialUse used_as {
get { return this.backing.used_as; }
}
public Plugin.Account? account {
@ -149,8 +149,8 @@ internal class Application.FolderStoreFactory : Geary.BaseObject {
}
internal void folder_type_changed() {
notify_property("folder-type");
this._display_name = this.backing.get_display_name();
notify_property("used-as");
this._display_name = Util.I18n.to_folder_display_name(this.backing);
notify_property("display-name");
}
@ -235,8 +235,8 @@ internal class Application.FolderStoreFactory : Geary.BaseObject {
account.folders_available_unavailable.connect(
on_folders_available_unavailable
);
account.folders_special_type.connect(
on_folders_type_changed
account.folders_use_changed.connect(
on_folders_use_changed
);
add_folders(account.list_folders());
} catch (GLib.Error err) {
@ -253,8 +253,8 @@ internal class Application.FolderStoreFactory : Geary.BaseObject {
account.folders_available_unavailable.disconnect(
on_folders_available_unavailable
);
account.folders_special_type.disconnect(
on_folders_type_changed
account.folders_use_changed.disconnect(
on_folders_use_changed
);
remove_folders(account.list_folders());
this.accounts.unset(removed);
@ -320,8 +320,8 @@ internal class Application.FolderStoreFactory : Geary.BaseObject {
}
}
private void on_folders_type_changed(Geary.Account account,
Gee.Collection<Geary.Folder> changed) {
private void on_folders_use_changed(Geary.Account account,
Gee.Collection<Geary.Folder> changed) {
var folders = to_plugin_folders(changed);
foreach (FolderImpl folder in folders) {
folder.folder_type_changed();

View file

@ -28,7 +28,7 @@ public class Application.MainWindow :
public const string ACTION_SHOW_COPY_MENU = "show-copy-menu";
public const string ACTION_SHOW_MARK_MENU = "show-mark-menu";
public const string ACTION_SHOW_MOVE_MENU = "show-move-menu";
public const string ACTION_TOGGLE_SPAM = "toggle-conversation-spam";
public const string ACTION_TOGGLE_JUNK = "toggle-conversation-junk";
public const string ACTION_TRASH_CONVERSATION = "trash-conversation";
public const string ACTION_ZOOM = "zoom";
@ -59,7 +59,7 @@ public class Application.MainWindow :
{ ACTION_MARK_AS_UNREAD, on_mark_as_unread },
{ ACTION_MARK_AS_STARRED, on_mark_as_starred },
{ ACTION_MARK_AS_UNSTARRED, on_mark_as_unstarred },
{ ACTION_TOGGLE_SPAM, on_mark_as_spam_toggle },
{ ACTION_TOGGLE_JUNK, on_mark_as_junk_toggle },
// Message viewer
{ ACTION_ZOOM, on_zoom, "s" },
};
@ -406,7 +406,7 @@ public class Application.MainWindow :
/** Keybinding signal for junking the current selection. */
[Signal (action=true)]
public virtual signal void junk_conversations() {
activate_action(get_window_action(ACTION_TOGGLE_SPAM));
activate_action(get_window_action(ACTION_TOGGLE_JUNK));
}
/** Keybinding signal for trashing the current selection. */
@ -593,7 +593,7 @@ public class Application.MainWindow :
/// substitution being the currently selected folder name,
/// the second being the selected account name.
title = _("%s — %s").printf(
this.selected_folder.get_display_name(),
Util.I18n.to_folder_display_name(this.selected_folder),
this.selected_folder.account.information.display_name
);
}
@ -606,7 +606,7 @@ public class Application.MainWindow :
);
this.main_toolbar.folder = (
this.selected_folder != null
? this.selected_folder.get_display_name()
? Util.I18n.to_folder_display_name(this.selected_folder)
: ""
);
}
@ -705,12 +705,12 @@ public class Application.MainWindow :
// Prefer the inboxes branch if it is a thing, but
// only for non-interactive calls
if (is_interactive ||
(to_select.special_folder_type != INBOX ||
(to_select.used_as != INBOX ||
!this.folder_list.select_inbox(to_select.account))) {
this.folder_list.select_folder(to_select);
}
if (to_select.special_folder_type == SEARCH) {
if (to_select.used_as == SEARCH) {
this.previous_non_search_folder = to_select;
}
} else {
@ -963,7 +963,7 @@ public class Application.MainWindow :
this.search_open = new GLib.Cancellable();
if (this.previous_non_search_folder != null &&
this.selected_folder.special_folder_type == SEARCH) {
this.selected_folder.used_as == SEARCH) {
this.select_folder.begin(
this.previous_non_search_folder, is_interactive
);
@ -1036,7 +1036,7 @@ public class Application.MainWindow :
if (this.selected_folder != null &&
this.selected_folder.account == to_remove.account) {
bool is_account_search_active = (
this.selected_folder.special_folder_type == SEARCH
this.selected_folder.used_as == SEARCH
);
yield select_folder(to_select, false);
@ -1076,15 +1076,15 @@ public class Application.MainWindow :
this.main_toolbar.copy_folder_menu.add_folder(to_add);
this.main_toolbar.move_folder_menu.add_folder(to_add);
}
to_add.special_folder_type_changed.connect(
on_special_folder_type_changed
to_add.use_changed.connect(
on_use_changed
);
}
/** Removes a folder from the window. */
private void remove_folder(Geary.Folder to_remove) {
to_remove.special_folder_type_changed.disconnect(
on_special_folder_type_changed
to_remove.use_changed.disconnect(
on_use_changed
);
if (to_remove.account == this.selected_account) {
this.main_toolbar.copy_folder_menu.remove_folder(to_remove);
@ -1283,15 +1283,14 @@ public class Application.MainWindow :
return base.key_release_event(event);
}
internal bool prompt_empty_folder(Geary.SpecialFolderType type) {
internal bool prompt_empty_folder(Geary.Folder.SpecialUse type) {
var folder_name = Util.I18n.to_folder_type_display_name(type);
ConfirmationDialog dialog = new ConfirmationDialog(
this,
_("Empty all email from your %s folder?").printf(
type.get_display_name()
),
_("Empty all email from your %s folder?").printf(folder_name),
_("This removes the email from Geary and your email server.") +
" <b>" + _("This cannot be undone.") + "</b>",
_("Empty %s").printf(type.get_display_name()),
_("Empty %s").printf(folder_name),
"destructive-action"
);
dialog.use_secondary_markup(true);
@ -1617,7 +1616,7 @@ public class Application.MainWindow :
if (!this.has_composer) {
if (this.conversations.size == 0) {
// Let the user know if there's no available conversations
if (this.selected_folder.special_folder_type == SEARCH) {
if (this.selected_folder.used_as == SEARCH) {
this.conversation_viewer.show_empty_search();
} else {
this.conversation_viewer.show_empty_folder();
@ -1682,9 +1681,9 @@ public class Application.MainWindow :
/// Current folder's name followed by its unread count, i.e. "Inbox (42)"
// except for Drafts and Outbox, where we show total count
int count;
switch (this.selected_folder.special_folder_type) {
case Geary.SpecialFolderType.DRAFTS:
case Geary.SpecialFolderType.OUTBOX:
switch (this.selected_folder.used_as) {
case DRAFTS:
case OUTBOX:
count = this.selected_folder.properties.email_total;
break;
@ -1693,10 +1692,12 @@ public class Application.MainWindow :
break;
}
if (count > 0)
this.main_toolbar.folder = _("%s (%d)").printf(this.selected_folder.get_display_name(), count);
else
this.main_toolbar.folder = this.selected_folder.get_display_name();
var folder_name = Util.I18n.to_folder_display_name(this.selected_folder);
this.main_toolbar.folder = (
count > 0
? _("%s (%d)").printf(folder_name, count)
: folder_name
);
}
private void update_conversation_actions(ConversationCount count) {
@ -1711,7 +1712,7 @@ public class Application.MainWindow :
sensitive &&
!multiple &&
this.selected_folder != null &&
this.selected_folder.special_folder_type != DRAFTS
this.selected_folder.used_as != DRAFTS
);
get_window_action(ACTION_REPLY_CONVERSATION).set_enabled(reply_sensitive);
get_window_action(ACTION_REPLY_ALL_CONVERSATION).set_enabled(reply_sensitive);
@ -1990,9 +1991,9 @@ public class Application.MainWindow :
}
}
private void on_special_folder_type_changed(Geary.Folder folder,
Geary.SpecialFolderType old_type,
Geary.SpecialFolderType new_type) {
private void on_use_changed(Geary.Folder folder,
Geary.Folder.SpecialUse old_type,
Geary.Folder.SpecialUse new_type) {
// Update the main window
this.folder_list.remove_folder(folder);
this.folder_list.add_folder(folder);
@ -2117,7 +2118,7 @@ public class Application.MainWindow :
private void on_conversation_activated(Geary.App.Conversation activated) {
if (this.selected_folder != null) {
if (this.selected_folder.special_folder_type != DRAFTS) {
if (this.selected_folder.used_as != DRAFTS) {
this.application.new_window.begin(
this.selected_folder,
this.conversation_list_view.copy_selected()
@ -2235,11 +2236,13 @@ public class Application.MainWindow :
get_window_action(ACTION_MARK_AS_STARRED).set_enabled(unstarred_selected);
get_window_action(ACTION_MARK_AS_UNSTARRED).set_enabled(starred_selected);
// If we're in Drafts/Outbox, we also shouldn't set a message as SPAM.
bool in_spam_folder = selected_folder.special_folder_type == Geary.SpecialFolderType.SPAM;
get_window_action(ACTION_TOGGLE_SPAM).set_enabled(!in_spam_folder &&
selected_folder.special_folder_type != Geary.SpecialFolderType.DRAFTS &&
selected_folder.special_folder_type != Geary.SpecialFolderType.OUTBOX);
// If we're in Drafts/Outbox, we also shouldn't set a message as junk
bool in_junk_folder = (selected_folder.used_as == JUNK);
get_window_action(ACTION_TOGGLE_JUNK).set_enabled(
!in_junk_folder &&
selected_folder.used_as != DRAFTS &&
selected_folder.used_as != OUTBOX
);
}
private void on_mark_conversations(Gee.Collection<Geary.App.Conversation> conversations,
@ -2338,13 +2341,13 @@ public class Application.MainWindow :
}
}
private void on_mark_as_spam_toggle() {
private void on_mark_as_junk_toggle() {
Geary.Folder? source = this.selected_folder;
if (source != null) {
Geary.SpecialFolderType destination =
(source.special_folder_type != SPAM)
? Geary.SpecialFolderType.SPAM
: Geary.SpecialFolderType.INBOX;
Geary.Folder.SpecialUse destination =
(source.used_as != JUNK)
? Geary.Folder.SpecialUse.JUNK
: Geary.Folder.SpecialUse.INBOX;
this.controller.move_conversations_special.begin(
source,
destination,
@ -2423,7 +2426,7 @@ public class Application.MainWindow :
if (source != null) {
this.controller.move_conversations_special.begin(
source,
Geary.SpecialFolderType.TRASH,
TRASH,
this.conversation_list_view.copy_selected(),
(obj, res) => {
try {
@ -2456,8 +2459,6 @@ public class Application.MainWindow :
}
}
// Individual conversation email view action callbacks
private void on_email_loaded(ConversationListBox view,
Geary.Email loaded) {
this.controller.email_loaded(

View file

@ -101,7 +101,7 @@ public class Application.PluginManager : GLib.Object {
Geary.Folder? target = this.folders.get_engine_folder(folder);
if (target != null) {
if (!main.prompt_empty_folder(target.special_folder_type)) {
if (!main.prompt_empty_folder(target.used_as)) {
throw new Plugin.Error.PERMISSION_DENIED(
"Permission not granted"
);

View file

@ -2596,8 +2596,7 @@ public class Composer.Widget : Gtk.EventBox, Geary.BaseInterface {
// <https://gitlab.gnome.org/GNOME/gspell/issues/5>) and
// we don't support spell checker language priority, use
// the first matching most preferred language, if any.
foreach (string pref in
Util.International.get_user_preferred_languages()) {
foreach (string pref in Util.I18n.get_user_preferred_languages()) {
if (pref in langs) {
lang = Gspell.Language.lookup(pref);
if (lang != null) {

View file

@ -63,8 +63,8 @@ public class SpellCheckPopover {
box.margin = 6;
box.margin_start = 12;
lang_name = Util.International.language_name_from_locale(lang_code);
country_name = Util.International.country_name_from_locale(lang_code);
lang_name = Util.I18n.language_name_from_locale(lang_code);
country_name = Util.I18n.country_name_from_locale(lang_code);
string label_text = lang_name;
Gtk.Label label = new Gtk.Label(label_text);
@ -216,7 +216,7 @@ public class SpellCheckPopover {
private void setup_popover() {
// We populate the popover with the list of languages that the user wants to see
string[] languages = Util.International.get_available_dictionaries();
string[] languages = Util.I18n.get_available_dictionaries();
string[] enabled_langs = this.config.get_spell_check_languages();
string[] visible_langs = this.config.get_spell_check_visible_languages();

View file

@ -121,7 +121,7 @@ public class FormattedConversationData : Geary.BaseObject {
this.config = config;
this.conversation = conversation;
this.account_owner_emails = account_owner_emails;
use_to = (folder != null) && folder.special_folder_type.is_outgoing();
use_to = (folder != null) && folder.used_as.is_outgoing();
// Load preview-related data.
update_date_string();

View file

@ -1278,12 +1278,11 @@ public class ConversationListBox : Gtk.ListBox, Geary.BaseInterface {
// XXX should be able to edit draft emails from any
// conversation. This test should be more like "is in drafts
// folder"
Geary.SpecialFolderType type =
this.conversation.base_folder.special_folder_type;
Geary.Folder.SpecialUse use = this.conversation.base_folder.used_as;
bool is_in_folder = this.conversation.is_in_base_folder(email.id);
return (
is_in_folder && type == Geary.SpecialFolderType.DRAFTS // ||
is_in_folder && use == DRAFTS // ||
//email.flags.is_draft()
);
}

View file

@ -56,16 +56,10 @@ public class FolderList.AccountBranch : Sidebar.Branch {
if (a is Sidebar.Grouping || b is Sidebar.Grouping)
return special_grouping_comparator(a, b);
assert(a is FolderEntry);
assert(b is FolderEntry);
FolderEntry entry_a = (FolderEntry) a;
FolderEntry entry_b = (FolderEntry) b;
Geary.SpecialFolderType type_a = entry_a.folder.special_folder_type;
Geary.SpecialFolderType type_b = entry_b.folder.special_folder_type;
assert(type_a != Geary.SpecialFolderType.NONE);
assert(type_b != Geary.SpecialFolderType.NONE);
Geary.Folder.SpecialUse type_a = entry_a.folder.used_as;
Geary.Folder.SpecialUse type_b = entry_b.folder.used_as;
// Special folders are ordered by their enum value.
return (int) type_a - (int) type_b;
@ -83,9 +77,9 @@ public class FolderList.AccountBranch : Sidebar.Branch {
public void add_folder(Geary.Folder folder) {
Sidebar.Entry? graft_point = null;
FolderEntry folder_entry = new FolderEntry(folder);
Geary.SpecialFolderType special_folder_type = folder.special_folder_type;
if (special_folder_type != Geary.SpecialFolderType.NONE) {
if (special_folder_type == Geary.SpecialFolderType.SEARCH)
Geary.Folder.SpecialUse used_as = folder.used_as;
if (used_as != NONE) {
if (used_as == SEARCH)
return; // Don't show search folder under the account.
// Special folders go in the root of the account.
@ -120,7 +114,7 @@ public class FolderList.AccountBranch : Sidebar.Branch {
folder_entries.set(folder.path, folder_entry);
} else {
debug("Could not add folder %s of type %s to folder list", folder.to_string(),
special_folder_type.to_string());
used_as.to_string());
}
}

View file

@ -14,17 +14,15 @@ public class FolderList.FolderEntry : FolderList.AbstractFolderEntry, Sidebar.In
has_new = false;
folder.properties.notify[Geary.FolderProperties.PROP_NAME_EMAIL_TOTAL].connect(on_counts_changed);
folder.properties.notify[Geary.FolderProperties.PROP_NAME_EMAIL_UNREAD].connect(on_counts_changed);
folder.display_name_changed.connect(on_display_name_changed);
}
~FolderEntry() {
folder.properties.notify[Geary.FolderProperties.PROP_NAME_EMAIL_TOTAL].disconnect(on_counts_changed);
folder.properties.notify[Geary.FolderProperties.PROP_NAME_EMAIL_UNREAD].disconnect(on_counts_changed);
folder.display_name_changed.disconnect(on_display_name_changed);
}
public override string get_sidebar_name() {
return folder.get_display_name();
return Util.I18n.to_folder_display_name(this.folder);
}
public override string? get_sidebar_tooltip() {
@ -46,36 +44,36 @@ public class FolderList.FolderEntry : FolderList.AbstractFolderEntry, Sidebar.In
}
public override string? get_sidebar_icon() {
switch (folder.special_folder_type) {
case Geary.SpecialFolderType.NONE:
switch (folder.used_as) {
case NONE:
return "tag-symbolic";
case Geary.SpecialFolderType.INBOX:
case INBOX:
return "mail-inbox-symbolic";
case Geary.SpecialFolderType.DRAFTS:
case DRAFTS:
return "mail-drafts-symbolic";
case Geary.SpecialFolderType.SENT:
case SENT:
return "mail-sent-symbolic";
case Geary.SpecialFolderType.FLAGGED:
case FLAGGED:
return "starred-symbolic";
case Geary.SpecialFolderType.IMPORTANT:
case IMPORTANT:
return "task-due-symbolic";
case Geary.SpecialFolderType.ALL_MAIL:
case Geary.SpecialFolderType.ARCHIVE:
case ALL_MAIL:
case ARCHIVE:
return "mail-archive-symbolic";
case Geary.SpecialFolderType.SPAM:
case JUNK:
return "dialog-warning-symbolic";
case Geary.SpecialFolderType.TRASH:
case TRASH:
return "user-trash-symbolic";
case Geary.SpecialFolderType.OUTBOX:
case OUTBOX:
return "mail-outbox-symbolic";
default:
@ -120,21 +118,17 @@ public class FolderList.FolderEntry : FolderList.AbstractFolderEntry, Sidebar.In
sidebar_tooltip_changed(get_sidebar_tooltip());
}
private void on_display_name_changed() {
sidebar_name_changed(folder.get_display_name());
}
public override int get_count() {
switch (folder.special_folder_type) {
switch (folder.used_as) {
// for Drafts and Outbox, interested in showing total count, not unread count
case Geary.SpecialFolderType.DRAFTS:
case Geary.SpecialFolderType.OUTBOX:
case DRAFTS:
case OUTBOX:
return folder.properties.email_total;
// only show counts for Inbox, Spam, and user folders
case Geary.SpecialFolderType.INBOX:
case Geary.SpecialFolderType.SPAM:
case Geary.SpecialFolderType.NONE:
// only show counts for Inbox, Junk, and user folders
case INBOX:
case JUNK:
case NONE:
return folder.properties.email_unread;
// otherwise, to avoid clutter, no counts displayed (but are available in tooltip)

View file

@ -30,8 +30,6 @@ public class FolderList.InboxesBranch : Sidebar.Branch {
}
public void add_inbox(Geary.Folder inbox) {
assert(inbox.special_folder_type == Geary.SpecialFolderType.INBOX);
InboxFolderEntry folder_entry = new InboxFolderEntry(inbox);
graft(get_root(), folder_entry);

View file

@ -51,7 +51,7 @@ public class FolderList.Tree : Sidebar.Tree, Geary.BaseInterface {
entry.set_has_new(has_new);
}
if (folder.special_folder_type == INBOX &&
if (folder.used_as == INBOX &&
has_branch(inboxes_branch)) {
entry = inboxes_branch.get_entry_for_account(folder.account);
if (entry != null) {
@ -105,7 +105,7 @@ public class FolderList.Tree : Sidebar.Tree, Geary.BaseInterface {
if (account_branches.size > 1 && !has_branch(inboxes_branch))
graft(inboxes_branch, INBOX_ORDINAL); // The Inboxes branch comes first.
if (folder.special_folder_type == Geary.SpecialFolderType.INBOX)
if (folder.used_as == INBOX)
inboxes_branch.add_inbox(folder);
account_branch.add_folder(folder);
@ -132,7 +132,7 @@ public class FolderList.Tree : Sidebar.Tree, Geary.BaseInterface {
}
// if Inbox, remove from inboxes branch, selected or not
if (folder.special_folder_type == Geary.SpecialFolderType.INBOX)
if (folder.used_as == INBOX)
inboxes_branch.remove_inbox(folder.account);
account_branch.remove_folder(folder);
@ -163,7 +163,7 @@ public class FolderList.Tree : Sidebar.Tree, Geary.BaseInterface {
public void select_folder(Geary.Folder to_select) {
if (this.selected != to_select) {
bool selected = false;
if (to_select.special_folder_type == INBOX) {
if (to_select.used_as == INBOX) {
selected = select_inbox(to_select.account);
}

View file

@ -137,7 +137,7 @@ geary_client_vala_sources = files(
'util/util-files.vala',
'util/util-gio.vala',
'util/util-gtk.vala',
'util/util-international.vala',
'util/util-i18n.vala',
'util/util-js.vala',
'util/util-migrate.vala',
)

View file

@ -26,7 +26,7 @@ public class Plugin.DesktopNotifications :
TrustedExtension {
private const Geary.SpecialFolderType[] MONITORED_TYPES = {
private const Geary.Folder.SpecialUse[] MONITORED_TYPES = {
INBOX, NONE
};
@ -269,7 +269,7 @@ public class Plugin.DesktopNotifications :
private void check_folders(Gee.Collection<Folder> folders) {
foreach (Folder folder in folders) {
if (folder.folder_type in MONITORED_TYPES) {
if (folder.used_as in MONITORED_TYPES) {
this.notifications.start_monitoring_folder(folder);
} else {
this.notifications.stop_monitoring_folder(folder);

View file

@ -22,7 +22,7 @@ public class Plugin.FolderHighlight :
PluginBase, NotificationExtension, FolderExtension, TrustedExtension {
private const Geary.SpecialFolderType[] MONITORED_TYPES = {
private const Geary.Folder.SpecialUse[] MONITORED_TYPES = {
INBOX, NONE
};
@ -66,7 +66,7 @@ public class Plugin.FolderHighlight :
private void check_folders(Gee.Collection<Folder> folders) {
foreach (Folder folder in folders) {
if (folder.folder_type in MONITORED_TYPES) {
if (folder.used_as in MONITORED_TYPES) {
this.notifications.start_monitoring_folder(folder);
} else {
this.notifications.stop_monitoring_folder(folder);

View file

@ -113,7 +113,7 @@ public class Plugin.MessagingMenu :
private void check_folders(Gee.Collection<Folder> folders) {
foreach (Folder folder in folders) {
if (folder.folder_type == INBOX) {
if (folder.used_as == INBOX) {
this.notifications.start_monitoring_folder(folder);
} else if (this.notifications.is_monitoring_folder(folder)) {
this.notifications.stop_monitoring_folder(folder);

View file

@ -20,7 +20,7 @@ public class Plugin.NotificationBadge :
PluginBase, NotificationExtension, FolderExtension, TrustedExtension {
private const Geary.SpecialFolderType[] MONITORED_TYPES = {
private const Geary.Folder.SpecialUse[] MONITORED_TYPES = {
INBOX, NONE
};
@ -82,7 +82,7 @@ public class Plugin.NotificationBadge :
private void check_folders(Gee.Collection<Folder> folders) {
foreach (Folder folder in folders) {
if (folder.folder_type in MONITORED_TYPES) {
if (folder.used_as in MONITORED_TYPES) {
this.notifications.start_monitoring_folder(folder);
} else {
this.notifications.stop_monitoring_folder(folder);

View file

@ -24,7 +24,7 @@ public interface Plugin.Folder : Geary.BaseObject {
public abstract string display_name { get; }
/** Returns the type of this folder. */
public abstract Geary.SpecialFolderType folder_type { get; }
public abstract Geary.Folder.SpecialUse used_as { get; }
/** Returns the account the folder belongs to, if any. */
public abstract Account? account { get; }

View file

@ -78,14 +78,14 @@ public class Plugin.SpecialFolders :
}
private void update_folder(Folder target) {
switch (target.folder_type) {
switch (target.used_as) {
case TRASH:
this.folders.add_folder_info_bar(
target, get_folder_info_bar(target), PRIORITY
);
break;
case SPAM:
case JUNK:
this.folders.add_folder_info_bar(
target, get_folder_info_bar(target), PRIORITY
);
@ -104,7 +104,7 @@ public class Plugin.SpecialFolders :
target.identifier, this.cancellable
);
foreach (var folder in folders) {
if (folder.folder_type == DRAFTS) {
if (folder.used_as == DRAFTS) {
is_draft = true;
break;
}
@ -133,7 +133,7 @@ public class Plugin.SpecialFolders :
private InfoBar get_folder_info_bar(Folder target) {
var bar = this.info_bars.get(target);
if (bar == null) {
bar = new InfoBar(target.folder_type.get_display_name());
bar = new InfoBar(target.display_name);
bar.primary_button = new Button(
// Translators: Info bar button label for emptying
// trash/spam folders

View file

@ -1,14 +1,19 @@
/* Copyright 2016 Software Freedom Conservancy Inc.
/*
* Copyright © 2016 Software Freedom Conservancy Inc.
* Copyright © 2020 Michael Gratton <mike@vee.net>
*
* This software is licensed under the GNU Lesser General Public License
* (version 2.1 or later). See the COPYING file in this distribution.
* (version 2.1 or later). See the COPYING file in this distribution.
*/
extern const string _LANGUAGE_SUPPORT_DIRECTORY;
extern const string _ISO_CODE_639_XML;
extern const string _ISO_CODE_3166_XML;
namespace Util.International {
/**
* Internationalisation support functions.
*/
namespace Util.I18n {
private GLib.HashTable<string, string> language_names = null;
private GLib.HashTable<string, string> country_names = null;
@ -242,4 +247,63 @@ namespace Util.International {
return country_name;
}
/**
* Returns the localised display name name for specific folder.
*
* If the folder has a special type, the result of {@link
* to_folder_type_display_name} is returned, otherwise the last
* folder path step is returned.
*/
public string? to_folder_display_name(Geary.Folder folder) {
var name = to_folder_type_display_name(folder.used_as);
if (Geary.String.is_empty_or_whitespace(name)) {
name = folder.path.name;
}
return name;
}
/**
* Returns the localised name for a specific folder type, if any.
*/
public unowned string? to_folder_type_display_name(Geary.Folder.SpecialUse use) {
switch (use) {
case INBOX:
return _("Inbox");
case DRAFTS:
return _("Drafts");
case SENT:
return _("Sent");
case FLAGGED:
return _("Starred");
case IMPORTANT:
return _("Important");
case ALL_MAIL:
return _("All Mail");
case JUNK:
return _("Junk");
case TRASH:
return _("Trash");
case OUTBOX:
return _("Outbox");
case SEARCH:
return _("Search");
case ARCHIVE:
return _("Archive");
case NONE:
default:
return null;
}
}
}

View file

@ -180,8 +180,8 @@ public class Geary.AccountInformation : BaseObject {
/** Sent special folder path. */
public Geary.FolderPath? sent_folder_path { get; set; default = null; }
/** Spam special folder path. */
public Geary.FolderPath? spam_folder_path { get; set; default = null; }
/** Junk special folder path. */
public Geary.FolderPath? junk_folder_path { get; set; default = null; }
/** Trash special folder path. */
public Geary.FolderPath? trash_folder_path { get; set; default = null; }
@ -289,7 +289,7 @@ public class Geary.AccountInformation : BaseObject {
this.drafts_folder_path = other.drafts_folder_path;
this.sent_folder_path = other.sent_folder_path;
this.spam_folder_path = other.spam_folder_path;
this.junk_folder_path = other.junk_folder_path;
this.trash_folder_path = other.trash_folder_path;
this.archive_folder_path = other.archive_folder_path;
@ -369,31 +369,31 @@ public class Geary.AccountInformation : BaseObject {
}
/**
* Returns the configured path for a special folder type.
* Returns the configured path for a special folder use.
*
* This is used when Geary has found or created a special folder
* for this account. The path will be null if Geary has always
* been told about the special folders by the server, and hasn't
* had to go looking for them. Only the ARCHIVE, DRAFTS, SENT,
* SPAM, and TRASH special folder types are valid to pass to this
* JUNK, and TRASH special folder types are valid to pass to this
* function.
*/
public Geary.FolderPath? get_special_folder_path(Geary.SpecialFolderType special) {
public Geary.FolderPath? get_special_folder_path(Folder.SpecialUse special) {
switch (special) {
case Geary.SpecialFolderType.DRAFTS:
return this.drafts_folder_path;
case DRAFTS:
return this.drafts_folder_path;
case Geary.SpecialFolderType.SENT:
return this.sent_folder_path;
case SENT:
return this.sent_folder_path;
case Geary.SpecialFolderType.SPAM:
return this.spam_folder_path;
case JUNK:
return this.junk_folder_path;
case Geary.SpecialFolderType.TRASH:
return this.trash_folder_path;
case TRASH:
return this.trash_folder_path;
case Geary.SpecialFolderType.ARCHIVE:
return this.archive_folder_path;
case ARCHIVE:
return this.archive_folder_path;
}
return null;
@ -403,37 +403,37 @@ public class Geary.AccountInformation : BaseObject {
* Sets the configured path for a special folder type.
*
* This is only obeyed if the server doesn't tell Geary which
* folders are special. Only the DRAFTS, SENT, SPAM, TRASH and
* folders are special. Only the DRAFTS, SENT, JUNK, TRASH and
* ARCHIVE special folder types are valid to pass to this
* function.
*/
public void set_special_folder_path(Geary.SpecialFolderType special,
Geary.FolderPath? new_path) {
public void set_special_folder_path(Folder.SpecialUse special,
FolderPath? new_path) {
Geary.FolderPath? old_path = null;
switch (special) {
case Geary.SpecialFolderType.DRAFTS:
old_path = this.drafts_folder_path;
this.drafts_folder_path = new_path;
case DRAFTS:
old_path = this.drafts_folder_path;
this.drafts_folder_path = new_path;
break;
case Geary.SpecialFolderType.SENT:
old_path = this.sent_folder_path;
this.sent_folder_path = new_path;
case SENT:
old_path = this.sent_folder_path;
this.sent_folder_path = new_path;
break;
case Geary.SpecialFolderType.SPAM:
old_path = this.spam_folder_path;
this.spam_folder_path = new_path;
case JUNK:
old_path = this.junk_folder_path;
this.junk_folder_path = new_path;
break;
case Geary.SpecialFolderType.TRASH:
old_path = this.trash_folder_path;
this.trash_folder_path = new_path;
case TRASH:
old_path = this.trash_folder_path;
this.trash_folder_path = new_path;
break;
case Geary.SpecialFolderType.ARCHIVE:
old_path = this.archive_folder_path;
this.archive_folder_path = new_path;
case ARCHIVE:
old_path = this.archive_folder_path;
this.archive_folder_path = new_path;
break;
}
@ -541,7 +541,7 @@ public class Geary.AccountInformation : BaseObject {
this.outgoing.equal_to(other.outgoing) &&
this.drafts_folder_path == other.drafts_folder_path &&
this.sent_folder_path == other.sent_folder_path &&
this.spam_folder_path == other.spam_folder_path &&
this.junk_folder_path == other.junk_folder_path &&
this.trash_folder_path == other.trash_folder_path &&
this.archive_folder_path == other.archive_folder_path &&
this.config_dir == other.config_dir &&

View file

@ -215,9 +215,9 @@ public abstract class Geary.Account : BaseObject, Logging.Source {
public signal void folders_contents_altered(Gee.Collection<Geary.Folder> altered);
/**
* Fired when a Folder's type is detected having changed.
* Fired when a Folder's special use is detected having changed.
*/
public signal void folders_special_type(Gee.Collection<Geary.Folder> altered);
public signal void folders_use_changed(Gee.Collection<Geary.Folder> altered);
/**
* Fired when emails are appended to a folder in this account.
@ -395,19 +395,21 @@ public abstract class Geary.Account : BaseObject, Logging.Source {
/**
* Returns a folder for the given special folder type, it is exists.
*/
public virtual Geary.Folder? get_special_folder(Geary.SpecialFolderType type){
public virtual Geary.Folder? get_special_folder(Folder.SpecialUse use) {
return traverse<Folder>(list_folders())
.first_matching(f => f.special_folder_type == type);
.first_matching(f => f.used_as == use);
}
/**
* Returns the Folder object with the given special folder type. The folder will be
* created on the server if it doesn't already exist. An error will be thrown if the
* folder doesn't exist and can't be created. The only valid special folder types that
* can be required are: DRAFTS, SENT, SPAM, and TRASH.
* can be required are: DRAFTS, SENT, JUNK, and TRASH.
*/
public abstract async Geary.Folder get_required_special_folder_async(Geary.SpecialFolderType special,
Cancellable? cancellable = null) throws Error;
public abstract async Geary.Folder get_required_special_folder_async(
Folder.SpecialUse special,
GLib.Cancellable? cancellable = null
) throws GLib.Error;
/**
* Search the local account for emails referencing a Message-ID value

View file

@ -63,6 +63,62 @@
*/
public abstract class Geary.Folder : BaseObject, Logging.Source {
/**
* Specifies the use of a specific folder.
*
* These are populated from a number of sources, including mailbox
* names, protocol hints, and special folder implementations.
*/
public enum SpecialUse {
/** No special type, likely user-created. */
NONE,
// Well-known concrete folders
/** Denotes the inbox for the account. */
INBOX,
/** Stores email to be kept. */
ARCHIVE,
/** Stores email that has not yet been sent. */
DRAFTS,
/** Stores spam, malware and other kinds of unwanted email. */
JUNK,
/** Stores email that is waiting to be sent. */
OUTBOX,
/** Stores email that has been sent. */
SENT,
/** Stores email that is to be deleted. */
TRASH,
// Virtual folders
/** A view of all email in an account. */
ALL_MAIL,
/** A view of all flagged/starred email in an account. */
FLAGGED,
/** A view of email the server thinks is important. */
IMPORTANT,
/** A view of email matching some kind of search criteria. */
SEARCH;
public bool is_outgoing() {
return this == SENT || this == OUTBOX;
}
}
/**
* Indicates if a folder has been opened, and if so in which way.
*/
@ -232,8 +288,8 @@ public abstract class Geary.Folder : BaseObject, Logging.Source {
/** The folder path represented by this object. */
public abstract Geary.FolderPath path { get; }
/** Determines the type of this folder. */
public abstract Geary.SpecialFolderType special_folder_type { get; }
/** Determines the special use of this folder. */
public abstract SpecialUse used_as { get; }
/** Monitor for notifying of progress when opening the folder. */
public abstract Geary.ProgressMonitor opening_monitor { get; }
@ -385,23 +441,13 @@ public abstract class Geary.Folder : BaseObject, Logging.Source {
public signal void email_locally_complete(Gee.Collection<Geary.EmailIdentifier> ids);
/**
* Fired when the {@link SpecialFolderType} has changed.
* Fired when the folder's special use has changed.
*
* This will usually happen when the local object has been updated with data discovered from the
* remote account.
* This will usually happen when the local object has been updated
* with data discovered from the remote account.
*/
public signal void special_folder_type_changed(Geary.SpecialFolderType old_type,
Geary.SpecialFolderType new_type);
public signal void use_changed(SpecialUse old_use, SpecialUse new_use);
/**
* Fired when the Folder's display name has changed.
*
* @see get_display_name
*/
public signal void display_name_changed();
protected Folder() {
}
protected virtual void notify_opened(Geary.Folder.OpenState state, int count) {
opened(state, count);
@ -448,32 +494,9 @@ public abstract class Geary.Folder : BaseObject, Logging.Source {
email_locally_complete(ids);
}
/**
* In its default implementation, this will also call {@link notify_display_name_changed} since
* that's often the case; if not, subclasses should override.
*/
protected virtual void notify_special_folder_type_changed(Geary.SpecialFolderType old_type,
Geary.SpecialFolderType new_type) {
special_folder_type_changed(old_type, new_type);
// in default implementation, this may also mean the display name changed; subclasses may
// override this behavior, but no way to detect this, so notify
notify_display_name_changed();
}
protected virtual void notify_display_name_changed() {
display_name_changed();
}
/**
* Returns a name suitable for displaying to the user.
*
* Default is to display the name of the Folder's path, unless it's a special folder,
* in which case {@link SpecialFolderType.get_display_name} is returned.
*/
public virtual string get_display_name() {
return (special_folder_type == Geary.SpecialFolderType.NONE)
? path.name : special_folder_type.get_display_name();
protected virtual void notify_use_changed(SpecialUse old_use,
SpecialUse new_use) {
use_changed(old_use, new_use);
}
/** Determines if a folder has been opened, and if so in which way. */

View file

@ -5,6 +5,7 @@
*/
public enum Geary.SpecialFolderType {
NONE,
INBOX,
SEARCH,
@ -13,54 +14,13 @@ public enum Geary.SpecialFolderType {
FLAGGED,
IMPORTANT,
ALL_MAIL,
SPAM,
JUNK,
TRASH,
OUTBOX,
ARCHIVE;
public unowned string get_display_name() {
switch (this) {
case INBOX:
return _("Inbox");
case DRAFTS:
return _("Drafts");
case SENT:
return _("Sent Mail");
case FLAGGED:
return _("Starred");
case IMPORTANT:
return _("Important");
case ALL_MAIL:
return _("All Mail");
case SPAM:
return _("Spam");
case TRASH:
return _("Trash");
case OUTBOX:
return _("Outbox");
case SEARCH:
return _("Search");
case ARCHIVE:
return _("Archive");
case NONE:
default:
return _("None");
}
}
public bool is_outgoing() {
return this == SENT || this == OUTBOX;
}
}
}

View file

@ -423,14 +423,14 @@ public class Geary.App.ConversationMonitor : BaseObject {
* Returns the list of folders that disqualify emails from conversations.
*/
internal Gee.Collection<Geary.FolderPath> get_search_folder_blacklist() {
Geary.SpecialFolderType[] blacklisted_folder_types = {
Geary.SpecialFolderType.SPAM,
Geary.SpecialFolderType.TRASH,
Geary.SpecialFolderType.DRAFTS,
Folder.SpecialUse[] blacklisted_folder_types = {
JUNK,
TRASH,
DRAFTS,
};
Gee.ArrayList<Geary.FolderPath?> blacklist = new Gee.ArrayList<Geary.FolderPath?>();
foreach (Geary.SpecialFolderType type in blacklisted_folder_types) {
var blacklist = new Gee.ArrayList<Geary.FolderPath?>();
foreach (var type in blacklisted_folder_types) {
Geary.Folder? blacklist_folder = this.base_folder.account.get_special_folder(type);
if (blacklist_folder != null) {
blacklist.add(blacklist_folder.path);

View file

@ -205,7 +205,7 @@ public class Geary.App.DraftManager : BaseObject {
if (current_draft_id != null)
draft_state = DraftState.STORED;
drafts_folder = account.get_special_folder(SpecialFolderType.DRAFTS);
drafts_folder = account.get_special_folder(DRAFTS);
if (drafts_folder == null)
throw new EngineError.NOT_FOUND("%s: No drafts folder found", to_string());

View file

@ -23,11 +23,11 @@ public class Geary.App.SearchFolder :
/** The canonical name of the search folder. */
public const string MAGIC_BASENAME = "$GearyAccountSearchFolder$";
private const SpecialFolderType[] EXCLUDE_TYPES = {
SpecialFolderType.SPAM,
SpecialFolderType.TRASH,
SpecialFolderType.DRAFTS,
// Orphan emails (without a folder) are also excluded; see ct or.
private const Folder.SpecialUse[] EXCLUDE_TYPES = {
DRAFTS,
JUNK,
TRASH,
// Orphan emails (without a folder) are also excluded; see ctor.
};
@ -98,8 +98,8 @@ public class Geary.App.SearchFolder :
*
* Always returns {@link SpecialFolderType.SEARCH}.
*/
public override SpecialFolderType special_folder_type {
get { return SpecialFolderType.SEARCH; }
public override Folder.SpecialUse used_as {
get { return SEARCH; }
}
/** The query being evaluated by this folder, if any. */
@ -126,7 +126,7 @@ public class Geary.App.SearchFolder :
this._path = root.get_child(MAGIC_BASENAME, Trillian.TRUE);
account.folders_available_unavailable.connect(on_folders_available_unavailable);
account.folders_special_type.connect(on_folders_special_type);
account.folders_use_changed.connect(on_folders_use_changed);
account.email_locally_complete.connect(on_email_locally_complete);
account.email_removed.connect(on_account_email_removed);
@ -139,7 +139,7 @@ public class Geary.App.SearchFolder :
~SearchFolder() {
account.folders_available_unavailable.disconnect(on_folders_available_unavailable);
account.folders_special_type.disconnect(on_folders_special_type);
account.folders_use_changed.disconnect(on_folders_use_changed);
account.email_locally_complete.disconnect(on_email_locally_complete);
account.email_removed.disconnect(on_account_email_removed);
}
@ -573,15 +573,15 @@ public class Geary.App.SearchFolder :
) {
if (available != null) {
// Exclude it from searching if it's got the right special type.
foreach(Folder folder in traverse<Folder>(available)
.filter(f => f.special_folder_type in EXCLUDE_TYPES))
foreach(var folder in traverse<Folder>(available)
.filter(f => f.used_as in EXCLUDE_TYPES))
exclude_folder(folder);
}
}
private void on_folders_special_type(Gee.Collection<Folder> folders) {
private void on_folders_use_changed(Gee.Collection<Folder> folders) {
foreach (Folder folder in folders) {
if (folder.special_folder_type in EXCLUDE_TYPES) {
if (folder.used_as in EXCLUDE_TYPES) {
exclude_folder(folder);
} else {
include_folder(folder);

View file

@ -20,7 +20,7 @@ internal class Geary.ContactHarvesterImpl : BaseObject, ContactHarvester {
private const Email.Field REQUIRED_FIELDS = ORIGINATORS | RECEIVERS;
private const SpecialFolderType[] FOLDER_WHITELIST = {
private const Folder.SpecialUse[] FOLDER_WHITELIST = {
INBOX,
ARCHIVE,
SENT,
@ -30,11 +30,12 @@ internal class Geary.ContactHarvesterImpl : BaseObject, ContactHarvester {
private ContactStore store;
private Gee.Collection<RFC822.MailboxAddress> owner_mailboxes;
private SpecialFolderType location;
private Folder.SpecialUse location;
private bool is_whitelisted;
public ContactHarvesterImpl(ContactStore store,
SpecialFolderType location,
Folder.SpecialUse location,
Gee.Collection<RFC822.MailboxAddress> owners) {
this.store = store;
this.owner_mailboxes = owners;

View file

@ -9,11 +9,11 @@
private class Geary.ImapEngine.GmailAccount : Geary.ImapEngine.GenericAccount {
// Archive is handled specially, so don't require it
private const Geary.SpecialFolderType[] SUPPORTED_SPECIAL_FOLDERS = {
Geary.SpecialFolderType.DRAFTS,
Geary.SpecialFolderType.SENT,
Geary.SpecialFolderType.SPAM,
Geary.SpecialFolderType.TRASH,
private const Folder.SpecialUse[] SUPPORTED_SPECIAL_FOLDERS = {
DRAFTS,
SENT,
JUNK,
TRASH,
};
@ -45,36 +45,36 @@ private class Geary.ImapEngine.GmailAccount : Geary.ImapEngine.GenericAccount {
base(config, local, incoming_remote, outgoing_remote);
}
protected override Geary.SpecialFolderType[] get_supported_special_folders() {
protected override Folder.SpecialUse[] get_supported_special_folders() {
return SUPPORTED_SPECIAL_FOLDERS;
}
protected override MinimalFolder new_folder(ImapDB.Folder local_folder) {
FolderPath path = local_folder.get_path();
SpecialFolderType type;
Folder.SpecialUse use = NONE;
if (Imap.MailboxSpecifier.folder_path_is_inbox(path)) {
type = SpecialFolderType.INBOX;
use = INBOX;
} else {
type = local_folder.get_properties().attrs.get_special_folder_type();
use = local_folder.get_properties().attrs.get_special_use();
// There can be only one Inbox
if (type == SpecialFolderType.INBOX) {
type = SpecialFolderType.NONE;
if (use == INBOX) {
use = NONE;
}
}
switch (type) {
case SpecialFolderType.ALL_MAIL:
return new GmailAllMailFolder(this, local_folder, type);
switch (use) {
case ALL_MAIL:
return new GmailAllMailFolder(this, local_folder);
case SpecialFolderType.DRAFTS:
return new GmailDraftsFolder(this, local_folder, type);
case DRAFTS:
return new GmailDraftsFolder(this, local_folder);
case SpecialFolderType.SPAM:
case SpecialFolderType.TRASH:
return new GmailSpamTrashFolder(this, local_folder, type);
case JUNK:
case TRASH:
return new GmailSpamTrashFolder(this, local_folder, use);
default:
return new GmailFolder(this, local_folder, type);
return new GmailFolder(this, local_folder, use);
}
}

View file

@ -10,9 +10,8 @@
private class Geary.ImapEngine.GmailAllMailFolder : MinimalFolder, FolderSupport.Remove {
public GmailAllMailFolder(GmailAccount account,
ImapDB.Folder local_folder,
SpecialFolderType special_folder_type) {
base(account, local_folder, special_folder_type);
ImapDB.Folder local_folder) {
base(account, local_folder, ALL_MAIL);
}
public async void

View file

@ -15,9 +15,8 @@ private class Geary.ImapEngine.GmailDraftsFolder :
MinimalFolder, FolderSupport.Create, FolderSupport.Remove {
public GmailDraftsFolder(GmailAccount account,
ImapDB.Folder local_folder,
SpecialFolderType special_folder_type) {
base(account, local_folder, special_folder_type);
ImapDB.Folder local_folder) {
base(account, local_folder, DRAFTS);
}
public new async EmailIdentifier?

View file

@ -9,8 +9,8 @@ private class Geary.ImapEngine.GmailFolder : MinimalFolder, FolderSupport.Archiv
FolderSupport.Create, FolderSupport.Remove {
public GmailFolder(GmailAccount account,
ImapDB.Folder local_folder,
SpecialFolderType special_folder_type) {
base (account, local_folder, special_folder_type);
Folder.SpecialUse use) {
base (account, local_folder, use);
}
public new async EmailIdentifier?
@ -31,7 +31,7 @@ private class Geary.ImapEngine.GmailFolder : MinimalFolder, FolderSupport.Archiv
// Use move_email_async("All Mail") here; Gmail will do the right thing and report
// it was copied with the pre-existing All Mail UID (in other words, no actual copy is
// performed). This allows for undoing an archive with the same code path as a move.
Geary.Folder? all_mail = account.get_special_folder(Geary.SpecialFolderType.ALL_MAIL);
Geary.Folder? all_mail = account.get_special_folder(ALL_MAIL);
if (all_mail != null)
return yield move_email_async(email_ids, all_mail.path, cancellable);
@ -65,7 +65,7 @@ private class Geary.ImapEngine.GmailFolder : MinimalFolder, FolderSupport.Archiv
GLib.Cancellable? cancellable)
throws GLib.Error {
// Get path to Trash folder
Geary.Folder? trash = folder.account.get_special_folder(SpecialFolderType.TRASH);
Geary.Folder? trash = folder.account.get_special_folder(TRASH);
if (trash == null)
throw new EngineError.NOT_FOUND("%s: Trash folder not found for removal", folder.to_string());

View file

@ -16,8 +16,8 @@ private class Geary.ImapEngine.GmailSpamTrashFolder :
public GmailSpamTrashFolder(GmailAccount account,
ImapDB.Folder local_folder,
SpecialFolderType special_folder_type) {
base(account, local_folder, special_folder_type);
Folder.SpecialUse use) {
base(account, local_folder, use);
}
public async void

View file

@ -17,12 +17,12 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.Account {
// we don't need to double check.
private const int REFRESH_FOLDER_LIST_SEC = 15 * 60;
private const Geary.SpecialFolderType[] SUPPORTED_SPECIAL_FOLDERS = {
Geary.SpecialFolderType.DRAFTS,
Geary.SpecialFolderType.SENT,
Geary.SpecialFolderType.SPAM,
Geary.SpecialFolderType.TRASH,
Geary.SpecialFolderType.ARCHIVE,
private const Folder.SpecialUse[] SUPPORTED_SPECIAL_FOLDERS = {
DRAFTS,
SENT,
JUNK,
TRASH,
ARCHIVE,
};
private static GLib.VariantType email_id_type = new GLib.VariantType(
@ -50,8 +50,8 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.Account {
private AccountSynchronizer sync;
private TimeoutManager refresh_folder_timer;
private Gee.Map<Geary.SpecialFolderType, Gee.List<string>> special_search_names =
new Gee.HashMap<Geary.SpecialFolderType, Gee.List<string>>();
private Gee.Map<Folder.SpecialUse,Gee.List<string>> special_search_names =
new Gee.HashMap<Folder.SpecialUse,Gee.List<string>>();
protected GenericAccount(AccountInformation config,
@ -426,8 +426,10 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.Account {
.to_array_list();
}
public override async Geary.Folder get_required_special_folder_async(Geary.SpecialFolderType special,
Cancellable? cancellable) throws Error {
public override async Geary.Folder get_required_special_folder_async(
Folder.SpecialUse special,
GLib.Cancellable? cancellable
) throws GLib.Error {
if (!(special in get_supported_special_folders())) {
throw new EngineError.BAD_PARAMETERS(
"Invalid special folder type %s passed to get_required_special_folder_async",
@ -587,27 +589,27 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.Account {
/**
* Marks a folder as a specific special folder type.
*/
internal void promote_folders(Gee.Map<Geary.SpecialFolderType,Geary.Folder> specials) {
Gee.Set<Geary.Folder> changed = new Gee.HashSet<Geary.Folder>();
foreach (Geary.SpecialFolderType special in specials.keys) {
internal void promote_folders(Gee.Map<Folder.SpecialUse,Folder> specials) {
var changed = new Gee.HashSet<Geary.Folder>();
foreach (var special in specials.keys) {
MinimalFolder? minimal = specials.get(special) as MinimalFolder;
if (minimal.special_folder_type != special) {
if (minimal.used_as != special) {
debug("Promoting %s to %s",
minimal.to_string(), special.to_string());
minimal.set_special_folder_type(special);
minimal.set_use(special);
changed.add(minimal);
MinimalFolder? existing =
get_special_folder(special) as MinimalFolder;
if (existing != null && existing != minimal) {
existing.set_special_folder_type(SpecialFolderType.NONE);
existing.set_use(NONE);
changed.add(existing);
}
}
}
if (!changed.is_empty) {
folders_special_type(changed);
folders_use_changed(changed);
}
}
@ -647,18 +649,18 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.Account {
*/
internal async Folder
ensure_special_folder_async(Imap.AccountSession remote,
SpecialFolderType type,
Folder.SpecialUse use,
GLib.Cancellable? cancellable)
throws GLib.Error {
Folder? special = get_special_folder(type);
Folder? special = get_special_folder(use);
if (special == null) {
FolderPath? path = information.get_special_folder_path(type);
FolderPath? path = information.get_special_folder_path(use);
if (path != null) {
if (!remote.is_folder_path_valid(path)) {
warning(
"Ignoring bad special folder path '%s' for type %s",
path.to_string(),
type.to_string()
use.to_string()
);
path = null;
} else {
@ -669,7 +671,7 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.Account {
if (path == null) {
FolderPath root =
yield remote.get_default_personal_namespace(cancellable);
Gee.List<string> search_names = special_search_names.get(type);
Gee.List<string> search_names = special_search_names.get(use);
foreach (string search_name in search_names) {
FolderPath search_path = root.get_child(search_name);
foreach (FolderPath test_path in folder_map.keys) {
@ -687,18 +689,18 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.Account {
}
debug("Guessed folder \'%s\' for special_path %s",
path.to_string(), type.to_string()
path.to_string(), use.to_string()
);
information.set_special_folder_path(type, path);
information.set_special_folder_path(use, path);
}
if (!this.folder_map.has_key(path)) {
debug("Creating \"%s\" to use as special folder %s",
path.to_string(), type.to_string());
path.to_string(), use.to_string());
GLib.Error? created_err = null;
try {
yield remote.create_folder_async(path, type, cancellable);
yield remote.create_folder_async(path, use, cancellable);
} catch (GLib.Error err) {
// Hang on to the error since the folder might exist
// on the remote, so try fetching it anyway.
@ -732,8 +734,8 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.Account {
special= this.folder_map.get(path);
promote_folders(
Collection.single_map<SpecialFolderType,Folder>(
type, special
Collection.single_map<Folder.SpecialUse,Folder>(
use, special
)
);
}
@ -834,7 +836,7 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.Account {
}
}
protected virtual Geary.SpecialFolderType[] get_supported_special_folders() {
protected virtual Folder.SpecialUse[] get_supported_special_folders() {
return SUPPORTED_SPECIAL_FOLDERS;
}
@ -849,7 +851,7 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.Account {
* session's language. Also checks for lower-case versions of
* each.
*/
foreach (Geary.SpecialFolderType type in get_supported_special_folders()) {
foreach (Folder.SpecialUse type in get_supported_special_folders()) {
Gee.List<string> compiled = new Gee.ArrayList<string>();
foreach (string names in get_special_search_names(type)) {
foreach (string name in names.split("|")) {
@ -870,11 +872,11 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.Account {
}
}
private Gee.List<string> get_special_search_names(Geary.SpecialFolderType type) {
private Gee.List<string> get_special_search_names(Folder.SpecialUse type) {
Gee.List<string> loc_names = new Gee.ArrayList<string>();
Gee.List<string> unloc_names = new Gee.ArrayList<string>();
switch (type) {
case Geary.SpecialFolderType.DRAFTS:
case DRAFTS:
// List of general possible folder names to match for the
// Draft mailbox. Separate names using a vertical bar and
// put the most common localized name to the front for the
@ -883,7 +885,7 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.Account {
unloc_names.add("Drafts | Draft");
break;
case Geary.SpecialFolderType.SENT:
case SENT:
// List of general possible folder names to match for the
// Sent mailbox. Separate names using a vertical bar and
// put the most common localized name to the front for the
@ -898,17 +900,17 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.Account {
break;
case Geary.SpecialFolderType.SPAM:
case JUNK:
// List of general possible folder names to match for the
// Spam mailbox. Separate names using a vertical bar and
// put the most common localized name to the front for the
// default. English names do not need to be included.
// Junk/Spam mailbox. Separate names using a vertical bar
// and put the most common localized name to the front for
// the default. English names do not need to be included.
loc_names.add(_("Junk | Spam | Junk Mail | Junk Email | Junk E-Mail | Bulk Mail | Bulk Email | Bulk E-Mail"));
unloc_names.add("Junk | Spam | Junk Mail | Junk Email | Junk E-Mail | Bulk Mail | Bulk Email | Bulk E-Mail");
break;
case Geary.SpecialFolderType.TRASH:
case TRASH:
// List of general possible folder names to match for the
// Trash mailbox. Separate names using a vertical bar and
// put the most common localized name to the front for the
@ -923,7 +925,7 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.Account {
break;
case Geary.SpecialFolderType.ARCHIVE:
case ARCHIVE:
// List of general possible folder names to match for the
// Archive mailbox. Separate names using a vertical bar
// and put the most common localized name to the front for
@ -969,12 +971,12 @@ internal class Geary.ImapEngine.LoadFolders : AccountOperation {
private weak ImapDB.Account local;
private Geary.SpecialFolderType[] specials;
private Folder.SpecialUse[] specials;
internal LoadFolders(GenericAccount account,
ImapDB.Account local,
Geary.SpecialFolderType[] specials) {
Folder.SpecialUse[] specials) {
base(account);
this.local = local;
this.specials = specials;
@ -1032,9 +1034,8 @@ internal class Geary.ImapEngine.LoadFolders : AccountOperation {
// that will attempt to create the folders if missing, which
// is bad if offline.
GenericAccount generic = (GenericAccount) this.account;
Gee.Map<Geary.SpecialFolderType,Geary.Folder> added_specials =
new Gee.HashMap<Geary.SpecialFolderType,Geary.Folder>();
foreach (Geary.SpecialFolderType type in this.specials) {
var added_specials = new Gee.HashMap<Folder.SpecialUse,Folder>();
foreach (var type in this.specials) {
if (generic.get_special_folder(type) == null) {
Geary.FolderPath? path =
generic.information.get_special_folder_path(type);
@ -1105,11 +1106,11 @@ internal class Geary.ImapEngine.UpdateRemoteFolders : AccountOperation {
private weak GenericAccount generic_account;
private Geary.SpecialFolderType[] specials;
private Folder.SpecialUse[] specials;
internal UpdateRemoteFolders(GenericAccount account,
Geary.SpecialFolderType[] specials) {
Folder.SpecialUse[] specials) {
base(account);
this.generic_account = account;
this.specials = specials;
@ -1227,8 +1228,11 @@ internal class Geary.ImapEngine.UpdateRemoteFolders : AccountOperation {
// its properties relies on the optional SPECIAL-USE or
// XLIST extensions) use this iteration to add discovered
// properties to map
if (minimal_folder.special_folder_type == SpecialFolderType.NONE)
minimal_folder.set_special_folder_type(remote_folder.properties.attrs.get_special_folder_type());
if (minimal_folder.used_as == NONE) {
minimal_folder.set_use(
remote_folder.properties.attrs.get_special_use()
);
}
}
// If path in remote but not local, need to add it
@ -1302,13 +1306,16 @@ internal class Geary.ImapEngine.UpdateRemoteFolders : AccountOperation {
}
// Ensure each of the important special folders we need already exist
foreach (Geary.SpecialFolderType special in this.specials) {
foreach (var use in this.specials) {
try {
yield this.generic_account.ensure_special_folder_async(
remote, special, cancellable
remote, use, cancellable
);
} catch (Error e) {
warning("Unable to ensure special folder %s: %s", special.to_string(), e.message);
warning(
"Unable to ensure special folder %s: %s",
use.to_string(), e.message
);
}
}
}

View file

@ -13,8 +13,8 @@ private class Geary.ImapEngine.GenericFolder : MinimalFolder,
public GenericFolder(GenericAccount account,
ImapDB.Folder local_folder,
SpecialFolderType special_folder_type) {
base (account, local_folder, special_folder_type);
Folder.SpecialUse use) {
base (account, local_folder, use);
}
public async Geary.Revokable?
@ -23,7 +23,9 @@ private class Geary.ImapEngine.GenericFolder : MinimalFolder,
throws GLib.Error {
Geary.Folder? archive_folder = null;
try {
archive_folder = yield account.get_required_special_folder_async(Geary.SpecialFolderType.ARCHIVE, cancellable);
archive_folder = yield account.get_required_special_folder_async(
Folder.SpecialUse.ARCHIVE, cancellable
);
} catch (Error e) {
debug("Error looking up archive folder in %s: %s", account.to_string(), e.message);
}

View file

@ -46,12 +46,12 @@ private class Geary.ImapEngine.MinimalFolder : Geary.Folder, Geary.FolderSupport
}
}
private SpecialFolderType _special_folder_type;
public override SpecialFolderType special_folder_type {
public override Folder.SpecialUse used_as {
get {
return _special_folder_type;
return this._used_as;
}
}
private Folder.SpecialUse _used_as;
private ProgressMonitor _opening_monitor =
new Geary.ReentrantProgressMonitor(Geary.ProgressType.ACTIVITY);
@ -117,12 +117,12 @@ private class Geary.ImapEngine.MinimalFolder : Geary.Folder, Geary.FolderSupport
public MinimalFolder(GenericAccount account,
ImapDB.Folder local_folder,
SpecialFolderType special_folder_type) {
Folder.SpecialUse use) {
this._account = account;
this.local_folder = local_folder;
this.local_folder.email_complete.connect(on_email_complete);
this._special_folder_type = special_folder_type;
this._used_as = use;
this._properties.add(local_folder.get_properties());
this.email_prefetcher = new EmailPrefetcher(this);
update_harvester();
@ -178,11 +178,11 @@ private class Geary.ImapEngine.MinimalFolder : Geary.Folder, Geary.FolderSupport
notify_email_flags_changed(flag_map);
}
public void set_special_folder_type(SpecialFolderType new_type) {
SpecialFolderType old_type = _special_folder_type;
_special_folder_type = new_type;
if (old_type != new_type)
notify_special_folder_type_changed(old_type, new_type);
public void set_use(Folder.SpecialUse new_use) {
var old_use = this._used_as;
this._used_as = new_use;
if (old_use != new_use)
notify_use_changed(old_use, new_use);
update_harvester();
}
@ -1579,7 +1579,7 @@ private class Geary.ImapEngine.MinimalFolder : Geary.Folder, Geary.FolderSupport
private void update_harvester() {
this.harvester = new ContactHarvesterImpl(
this.account.contact_store,
this.special_folder_type,
this._used_as,
this.account.information.sender_mailboxes
);
}

View file

@ -17,18 +17,18 @@ private class Geary.ImapEngine.OtherAccount : Geary.ImapEngine.GenericAccount {
protected override MinimalFolder new_folder(ImapDB.Folder local_folder) {
FolderPath path = local_folder.get_path();
SpecialFolderType type;
Folder.SpecialUse use = NONE;
if (Imap.MailboxSpecifier.folder_path_is_inbox(path)) {
type = SpecialFolderType.INBOX;
use = INBOX;
} else {
type = local_folder.get_properties().attrs.get_special_folder_type();
use = local_folder.get_properties().attrs.get_special_use();
// There can be only one Inbox
if (type == SpecialFolderType.INBOX) {
type = SpecialFolderType.NONE;
if (use == INBOX) {
use = NONE;
}
}
return new OtherFolder(this, local_folder, type);
return new OtherFolder(this, local_folder, use);
}
}

View file

@ -5,10 +5,11 @@
*/
private class Geary.ImapEngine.OtherFolder : GenericFolder {
public OtherFolder(OtherAccount account,
ImapDB.Folder local_folder,
SpecialFolderType special_folder_type) {
base (account, local_folder, special_folder_type);
Folder.SpecialUse use) {
base(account, local_folder, use);
}
}

View file

@ -39,21 +39,21 @@ private class Geary.ImapEngine.OutlookAccount : Geary.ImapEngine.GenericAccount
protected override MinimalFolder new_folder(ImapDB.Folder local_folder) {
FolderPath path = local_folder.get_path();
SpecialFolderType type;
Folder.SpecialUse use = NONE;
if (Imap.MailboxSpecifier.folder_path_is_inbox(path)) {
type = SpecialFolderType.INBOX;
use = INBOX;
} else {
type = local_folder.get_properties().attrs.get_special_folder_type();
use = local_folder.get_properties().attrs.get_special_use();
// There can be only one Inbox
if (type == SpecialFolderType.INBOX) {
type = SpecialFolderType.NONE;
if (use == INBOX) {
use = NONE;
}
}
if (type == Geary.SpecialFolderType.DRAFTS)
return new OutlookDraftsFolder(this, local_folder, type);
if (use == DRAFTS)
return new OutlookDraftsFolder(this, local_folder);
return new OutlookFolder(this, local_folder, type);
return new OutlookFolder(this, local_folder, use);
}
}

View file

@ -13,8 +13,7 @@
*/
private class Geary.ImapEngine.OutlookDraftsFolder : MinimalFolder {
public OutlookDraftsFolder(OutlookAccount account,
ImapDB.Folder local_folder,
SpecialFolderType special_folder_type) {
base(account, local_folder, special_folder_type);
ImapDB.Folder local_folder) {
base(account, local_folder, DRAFTS);
}
}

View file

@ -7,7 +7,7 @@
private class Geary.ImapEngine.OutlookFolder : GenericFolder {
public OutlookFolder(OutlookAccount account,
ImapDB.Folder local_folder,
SpecialFolderType special_folder_type) {
base(account, local_folder, special_folder_type);
Folder.SpecialUse use) {
base(account, local_folder, use);
}
}

View file

@ -39,22 +39,22 @@ private class Geary.ImapEngine.YahooAccount : Geary.ImapEngine.GenericAccount {
protected override MinimalFolder new_folder(ImapDB.Folder local_folder) {
FolderPath path = local_folder.get_path();
SpecialFolderType type;
Folder.SpecialUse use = NONE;
if (Imap.MailboxSpecifier.folder_path_is_inbox(path)) {
type = SpecialFolderType.INBOX;
use = INBOX;
} else {
// Despite Yahoo not advertising that it supports
// SPECIAL-USE via its CAPABILITIES, it lists the
// appropriate attributes in LIST results anyway, so we
// can just consult that. :|
type = local_folder.get_properties().attrs.get_special_folder_type();
use = local_folder.get_properties().attrs.get_special_use();
// There can be only one Inbox
if (type == SpecialFolderType.INBOX) {
type = SpecialFolderType.NONE;
if (use == INBOX) {
use = NONE;
}
}
return new YahooFolder(this, local_folder, type);
return new YahooFolder(this, local_folder, use);
}
}

View file

@ -7,7 +7,7 @@
private class Geary.ImapEngine.YahooFolder : GenericFolder {
public YahooFolder(YahooAccount account,
ImapDB.Folder local_folder,
SpecialFolderType special_folder_type) {
base (account, local_folder, special_folder_type);
Folder.SpecialUse use) {
base (account, local_folder, use);
}
}

View file

@ -91,14 +91,14 @@ internal class Geary.Imap.AccountSession : Geary.Imap.SessionObject {
* used to specify the type of the new folder.
*/
public async void create_folder_async(FolderPath path,
Geary.SpecialFolderType? type,
Geary.Folder.SpecialUse? use,
Cancellable? cancellable)
throws Error {
ClientSession session = claim_session();
MailboxSpecifier mailbox = session.get_mailbox_for_path(path);
bool can_create_special = session.capabilities.has_capability(Capabilities.CREATE_SPECIAL_USE);
CreateCommand cmd = (type != null && can_create_special)
? new CreateCommand.special_use(mailbox, type)
CreateCommand cmd = (use != null && can_create_special)
? new CreateCommand.special_use(mailbox, use)
: new CreateCommand(mailbox);
StatusResponse response = yield send_command_async(

View file

@ -22,33 +22,33 @@ public class Geary.Imap.CreateCommand : Command {
public MailboxSpecifier mailbox { get; private set; }
public Geary.SpecialFolderType use {
get; private set; default = Geary.SpecialFolderType.NONE;
public Geary.Folder.SpecialUse use {
get; private set; default = NONE;
}
private static MailboxAttribute? get_special_folder_type(Geary.SpecialFolderType type) {
switch (type) {
case Geary.SpecialFolderType.TRASH:
return MailboxAttribute.SPECIAL_FOLDER_TRASH;
private static MailboxAttribute? get_special_folder_type(Geary.Folder.SpecialUse use) {
switch (use) {
case ALL_MAIL:
return MailboxAttribute.SPECIAL_FOLDER_ALL;
case Geary.SpecialFolderType.DRAFTS:
return MailboxAttribute.SPECIAL_FOLDER_DRAFTS;
case Geary.SpecialFolderType.SENT:
return MailboxAttribute.SPECIAL_FOLDER_SENT;
case Geary.SpecialFolderType.ARCHIVE:
case ARCHIVE:
return MailboxAttribute.SPECIAL_FOLDER_ARCHIVE;
case Geary.SpecialFolderType.SPAM:
case DRAFTS:
return MailboxAttribute.SPECIAL_FOLDER_DRAFTS;
case FLAGGED:
return MailboxAttribute.SPECIAL_FOLDER_FLAGGED;
case JUNK:
return MailboxAttribute.SPECIAL_FOLDER_JUNK;
case Geary.SpecialFolderType.FLAGGED:
return MailboxAttribute.SPECIAL_FOLDER_STARRED;
case SENT:
return MailboxAttribute.SPECIAL_FOLDER_SENT;
case Geary.SpecialFolderType.ALL_MAIL:
return MailboxAttribute.SPECIAL_FOLDER_ALL;
case TRASH:
return MailboxAttribute.SPECIAL_FOLDER_TRASH;
default:
return null;
@ -62,7 +62,7 @@ public class Geary.Imap.CreateCommand : Command {
}
public CreateCommand.special_use(MailboxSpecifier mailbox,
Geary.SpecialFolderType use) {
Geary.Folder.SpecialUse use) {
this(mailbox);
this.use = use;

View file

@ -75,70 +75,6 @@ public class Geary.Imap.MailboxAttribute : Geary.Imap.Flag {
return _allows_new;
} }
private static MailboxAttribute? _xlist_inbox = null;
public static MailboxAttribute SPECIAL_FOLDER_INBOX { get {
if (_xlist_inbox == null)
_xlist_inbox = new MailboxAttribute("\\Inbox");
return _xlist_inbox;
} }
private static MailboxAttribute? _xlist_all_mail = null;
public static MailboxAttribute SPECIAL_FOLDER_ALL_MAIL { get {
if (_xlist_all_mail == null)
_xlist_all_mail = new MailboxAttribute("\\AllMail");
return _xlist_all_mail;
} }
private static MailboxAttribute? _xlist_trash = null;
public static MailboxAttribute SPECIAL_FOLDER_TRASH { get {
if (_xlist_trash == null)
_xlist_trash = new MailboxAttribute("\\Trash");
return _xlist_trash;
} }
private static MailboxAttribute? _xlist_drafts = null;
public static MailboxAttribute SPECIAL_FOLDER_DRAFTS { get {
if (_xlist_drafts == null)
_xlist_drafts = new MailboxAttribute("\\Drafts");
return _xlist_drafts;
} }
private static MailboxAttribute? _xlist_sent = null;
public static MailboxAttribute SPECIAL_FOLDER_SENT { get {
if (_xlist_sent == null)
_xlist_sent = new MailboxAttribute("\\Sent");
return _xlist_sent;
} }
private static MailboxAttribute? _xlist_spam = null;
public static MailboxAttribute SPECIAL_FOLDER_SPAM { get {
if (_xlist_spam == null)
_xlist_spam = new MailboxAttribute("\\Spam");
return _xlist_spam;
} }
private static MailboxAttribute? _xlist_starred = null;
public static MailboxAttribute SPECIAL_FOLDER_STARRED { get {
if (_xlist_starred == null)
_xlist_starred = new MailboxAttribute("\\Starred");
return _xlist_starred;
} }
private static MailboxAttribute? _xlist_important = null;
public static MailboxAttribute SPECIAL_FOLDER_IMPORTANT { get {
if (_xlist_important == null)
_xlist_important = new MailboxAttribute("\\Important");
return _xlist_important;
} }
private static MailboxAttribute? _special_use_all = null;
public static MailboxAttribute SPECIAL_FOLDER_ALL { get {
return (_special_use_all != null) ? _special_use_all
@ -151,18 +87,75 @@ public class Geary.Imap.MailboxAttribute : Geary.Imap.Flag {
: _special_use_archive = new MailboxAttribute("\\Archive");
} }
private static MailboxAttribute? _special_use_drafts = null;
public static MailboxAttribute SPECIAL_FOLDER_DRAFTS { get {
return (_special_use_drafts != null) ? _special_use_drafts
: _special_use_drafts = new MailboxAttribute("\\Drafts");
} }
private static MailboxAttribute? _special_use_flagged = null;
public static MailboxAttribute SPECIAL_FOLDER_FLAGGED { get {
return (_special_use_flagged != null) ? _special_use_flagged
: _special_use_flagged = new MailboxAttribute("\\Flagged");
} }
private static MailboxAttribute? _special_use_important = null;
public static MailboxAttribute SPECIAL_FOLDER_IMPORTANT { get {
return (_special_use_important != null) ? _special_use_important
: _special_use_important = new MailboxAttribute("\\Important");
} }
private static MailboxAttribute? _special_use_junk = null;
public static MailboxAttribute SPECIAL_FOLDER_JUNK { get {
return (_special_use_junk != null) ? _special_use_junk
: _special_use_junk = new MailboxAttribute("\\Junk");
} }
private static MailboxAttribute? _special_use_sent = null;
public static MailboxAttribute SPECIAL_FOLDER_SENT { get {
return (_special_use_sent != null) ? _special_use_sent
: _special_use_sent = new MailboxAttribute("\\Sent");
} }
private static MailboxAttribute? _special_use_trash = null;
public static MailboxAttribute SPECIAL_FOLDER_TRASH { get {
return (_special_use_trash != null) ? _special_use_trash
: _special_use_trash = new MailboxAttribute("\\Trash");
} }
private static MailboxAttribute? _xlist_inbox = null;
public static MailboxAttribute XLIST_INBOX { get {
if (_xlist_inbox == null)
_xlist_inbox = new MailboxAttribute("\\Inbox");
return _xlist_inbox;
} }
private static MailboxAttribute? _xlist_all_mail = null;
public static MailboxAttribute XLIST_ALL_MAIL { get {
if (_xlist_all_mail == null)
_xlist_all_mail = new MailboxAttribute("\\AllMail");
return _xlist_all_mail;
} }
private static MailboxAttribute? _xlist_spam = null;
public static MailboxAttribute XLIST_SPAM { get {
if (_xlist_spam == null)
_xlist_spam = new MailboxAttribute("\\Spam");
return _xlist_spam;
} }
private static MailboxAttribute? _xlist_starred = null;
public static MailboxAttribute XLIST_STARRED { get {
if (_xlist_starred == null)
_xlist_starred = new MailboxAttribute("\\Starred");
return _xlist_starred;
} }
public MailboxAttribute(string value) {
base (value);
}
@ -177,18 +170,18 @@ public class Geary.Imap.MailboxAttribute : Geary.Imap.Flag {
to_init = HAS_NO_CHILDREN;
to_init = HAS_CHILDREN;
to_init = ALLOWS_NEW;
to_init = SPECIAL_FOLDER_ALL_MAIL;
to_init = SPECIAL_FOLDER_DRAFTS;
to_init = SPECIAL_FOLDER_IMPORTANT;
to_init = SPECIAL_FOLDER_INBOX;
to_init = SPECIAL_FOLDER_SENT;
to_init = SPECIAL_FOLDER_SPAM;
to_init = SPECIAL_FOLDER_STARRED;
to_init = SPECIAL_FOLDER_TRASH;
to_init = SPECIAL_FOLDER_ALL;
to_init = SPECIAL_FOLDER_ARCHIVE;
to_init = SPECIAL_FOLDER_DRAFTS;
to_init = SPECIAL_FOLDER_FLAGGED;
to_init = SPECIAL_FOLDER_IMPORTANT;
to_init = SPECIAL_FOLDER_JUNK;
to_init = SPECIAL_FOLDER_SENT;
to_init = SPECIAL_FOLDER_TRASH;
to_init = XLIST_ALL_MAIL;
to_init = XLIST_INBOX;
to_init = XLIST_SPAM;
to_init = XLIST_STARRED;
}
}
}

View file

@ -58,41 +58,41 @@ public class Geary.Imap.MailboxAttributes : Geary.Imap.Flags {
* Search the {@link MailboxAttributes} looking for an XLIST-style
* {@link Geary.SpecialFolderType}.
*/
public Geary.SpecialFolderType get_special_folder_type() {
if (contains(MailboxAttribute.SPECIAL_FOLDER_INBOX))
return Geary.SpecialFolderType.INBOX;
public Geary.Folder.SpecialUse get_special_use() {
if (contains(MailboxAttribute.XLIST_INBOX))
return INBOX;
if (contains(MailboxAttribute.SPECIAL_FOLDER_ALL_MAIL))
return Geary.SpecialFolderType.ALL_MAIL;
if (contains(MailboxAttribute.XLIST_ALL_MAIL))
return ALL_MAIL;
if (contains(MailboxAttribute.SPECIAL_FOLDER_TRASH))
return Geary.SpecialFolderType.TRASH;
return TRASH;
if (contains(MailboxAttribute.SPECIAL_FOLDER_DRAFTS))
return Geary.SpecialFolderType.DRAFTS;
return DRAFTS;
if (contains(MailboxAttribute.SPECIAL_FOLDER_SENT))
return Geary.SpecialFolderType.SENT;
return SENT;
if (contains(MailboxAttribute.SPECIAL_FOLDER_JUNK))
return Geary.SpecialFolderType.SPAM;
return JUNK;
if (contains(MailboxAttribute.SPECIAL_FOLDER_SPAM))
return Geary.SpecialFolderType.SPAM;
if (contains(MailboxAttribute.XLIST_SPAM))
return JUNK;
if (contains(MailboxAttribute.SPECIAL_FOLDER_STARRED))
return Geary.SpecialFolderType.FLAGGED;
if (contains(MailboxAttribute.XLIST_STARRED))
return FLAGGED;
if (contains(MailboxAttribute.SPECIAL_FOLDER_IMPORTANT))
return Geary.SpecialFolderType.IMPORTANT;
return IMPORTANT;
if (contains(MailboxAttribute.SPECIAL_FOLDER_ARCHIVE))
return Geary.SpecialFolderType.ARCHIVE;
return ARCHIVE;
if (contains(MailboxAttribute.SPECIAL_FOLDER_FLAGGED))
return Geary.SpecialFolderType.FLAGGED;
return FLAGGED;
return Geary.SpecialFolderType.NONE;
return NONE;
}
}

View file

@ -77,7 +77,7 @@ public class Geary.Imap.MailboxInformation : BaseObject {
// Inbox name, otherwise decode it
MailboxSpecifier? specifier =
(canonical_inbox &&
Geary.Imap.MailboxAttribute.SPECIAL_FOLDER_INBOX in attributes)
Geary.Imap.MailboxAttribute.XLIST_INBOX in attributes)
? MailboxSpecifier.inbox
: new MailboxSpecifier.from_parameter(mailbox);

View file

@ -40,7 +40,6 @@ geary_engine_vala_sources = files(
'api/geary-search-query.vala',
'api/geary-service-information.vala',
'api/geary-service-provider.vala',
'api/geary-special-folder-type.vala',
'app/app-conversation.vala',
'app/app-conversation-monitor.vala',

View file

@ -68,9 +68,9 @@ public class Geary.Outbox.Folder :
*
* This is always {@link Geary.SpecialFolderType.OUTBOX}
*/
public override SpecialFolderType special_folder_type {
public override Geary.Folder.SpecialUse used_as {
get {
return Geary.SpecialFolderType.OUTBOX;
return OUTBOX;
}
}

View file

@ -148,7 +148,7 @@ public class Geary.MockAccount : Account, MockObject {
} catch (EngineError.NOT_FOUND err) {
throw err;
} catch (GLib.Error err) {
return new MockFolder(null, null, null, SpecialFolderType.NONE, null);
return new MockFolder(null, null, null, NONE, null);
}
}
@ -162,7 +162,7 @@ public class Geary.MockAccount : Account, MockObject {
}
}
public override Folder? get_special_folder(SpecialFolderType special) {
public override Folder? get_special_folder(Folder.SpecialUse special) {
try {
return object_call<Folder?>(
"get_special_folder", {box_arg(special)}, null
@ -172,7 +172,7 @@ public class Geary.MockAccount : Account, MockObject {
}
}
public override async Folder get_required_special_folder_async(SpecialFolderType special,
public override async Folder get_required_special_folder_async(Folder.SpecialUse special,
Cancellable? cancellable = null)
throws Error {
return object_or_throw_call<Folder>(

View file

@ -20,8 +20,8 @@ public class Geary.MockFolder : Folder, MockObject {
get { return this._path; }
}
public override SpecialFolderType special_folder_type {
get { return this._type; }
public override Folder.SpecialUse used_as {
get { return this._used_as; }
}
public override ProgressMonitor opening_monitor {
@ -36,19 +36,19 @@ public class Geary.MockFolder : Folder, MockObject {
private Account _account;
private FolderProperties _properties;
private FolderPath _path;
private SpecialFolderType _type;
private Folder.SpecialUse _used_as;
private ProgressMonitor _opening_monitor;
public MockFolder(Account? account,
FolderProperties? properties,
FolderPath? path,
SpecialFolderType type,
Folder.SpecialUse used_as,
ProgressMonitor? monitor) {
this._account = account;
this._properties = properties ?? new MockFolderPoperties();
this._path = path;
this._type = type;
this._used_as = used_as;
this._opening_monitor = monitor;
}

View file

@ -42,14 +42,14 @@ class Geary.App.ConversationMonitorTest : TestCase {
this.account,
null,
this.folder_root.get_child("base"),
SpecialFolderType.NONE,
NONE,
null
);
this.other_folder = new MockFolder(
this.account,
null,
this.folder_root.get_child("other"),
SpecialFolderType.NONE,
NONE,
null
);
}

View file

@ -33,7 +33,7 @@ class Geary.App.ConversationSetTest : TestCase {
null,
null,
this.folder_root.get_child("test"),
SpecialFolderType.NONE,
NONE,
null
);
this.test = new ConversationSet(this.base_folder);

View file

@ -33,7 +33,7 @@ class Geary.App.ConversationTest : TestCase {
null,
null,
this.folder_root.get_child("test"),
SpecialFolderType.NONE,
NONE,
null
);
this.test = new Conversation(this.base_folder);

View file

@ -54,7 +54,7 @@ class Geary.ContactHarvesterImplTest : TestCase {
public void whitelisted_folder_type() throws GLib.Error {
ContactHarvesterImpl whitelisted = new ContactHarvesterImpl(
this.store,
SpecialFolderType.INBOX,
INBOX,
this.senders
);
this.store.expect_call("get_by_rfc822");
@ -84,7 +84,7 @@ class Geary.ContactHarvesterImplTest : TestCase {
public void blacklisted_folder_type() throws GLib.Error {
ContactHarvesterImpl whitelisted = new ContactHarvesterImpl(
this.store,
SpecialFolderType.SPAM,
JUNK,
this.senders
);
this.email.set_receivers(
@ -103,7 +103,7 @@ class Geary.ContactHarvesterImplTest : TestCase {
public void seen_priority() throws GLib.Error {
ContactHarvesterImpl whitelisted = new ContactHarvesterImpl(
this.store,
SpecialFolderType.INBOX,
INBOX,
this.senders
);
this.store.expect_call("get_by_rfc822");
@ -132,7 +132,7 @@ class Geary.ContactHarvesterImplTest : TestCase {
public void sent_priority() throws GLib.Error {
ContactHarvesterImpl whitelisted = new ContactHarvesterImpl(
this.store,
SpecialFolderType.SENT,
SENT,
this.senders
);
this.store.expect_call("get_by_rfc822");
@ -161,7 +161,7 @@ class Geary.ContactHarvesterImplTest : TestCase {
public void received_priority() throws GLib.Error {
ContactHarvesterImpl whitelisted = new ContactHarvesterImpl(
this.store,
SpecialFolderType.SENT,
SENT,
this.senders
);
this.store.expect_call("get_by_rfc822");

View file

@ -26,7 +26,7 @@ class Geary.Imap.CreateCommandTest : TestCase {
"---- create Everything (use (\\All))",
new CreateCommand.special_use(
new MailboxSpecifier("Everything"),
SpecialFolderType.ALL_MAIL
ALL_MAIL
).to_string()
);
}

View file

@ -18,8 +18,8 @@
<attribute name="action">win.mark-conversation-unstarred</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Toggle as S_pam</attribute>
<attribute name="action">win.toggle-conversation-spam</attribute>
<attribute name="label" translatable="yes">Toggle as _Junk</attribute>
<attribute name="action">win.toggle-conversation-junk</attribute>
</item>
</menu>
<menu id="main_menu">
@ -48,7 +48,5 @@
<attribute name="action">app.about</attribute>
</item>
</section>
</menu>
</interface>