[geary/gnumdk/stable: 13/21] client: accounts: Add support for Thunderbird autoconfig
- From: Cédric Bellegarde <cbellegarde src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary/gnumdk/stable: 13/21] client: accounts: Add support for Thunderbird autoconfig
- Date: Mon, 1 Aug 2022 12:45:47 +0000 (UTC)
commit 44cc57308e8c8bb01fe9cefa6e7d880f2c158a64
Author: Cédric Bellegarde <cedric bellegarde adishatz org>
Date: Tue Jul 12 14:42:49 2022 +0200
client: accounts: Add support for Thunderbird autoconfig
- Auto detect server settings
- Rework accounts editor add panel
- Remove Yahoo service provider
Fix #1390
Fix #1350
meson.build | 1 +
src/client/accounts/accounts-autoconfig.vala | 163 ++++++++++
src/client/accounts/accounts-editor-add-pane.vala | 336 ++++++++++++++-------
src/client/accounts/accounts-editor-list-pane.vala | 107 +------
src/client/accounts/accounts-editor-row.vala | 4 -
.../accounts/accounts-editor-servers-pane.vala | 1 -
src/client/meson.build | 1 +
src/engine/api/geary-engine.vala | 11 +-
src/engine/api/geary-service-provider.vala | 7 -
.../yahoo/imap-engine-yahoo-account.vala | 60 ----
.../yahoo/imap-engine-yahoo-folder.vala | 13 -
src/engine/meson.build | 2 -
.../engine/api/geary-account-information-test.vala | 8 -
ui/accounts_editor_add_pane.ui | 179 ++++++-----
ui/accounts_editor_list_pane.ui | 58 +---
15 files changed, 490 insertions(+), 461 deletions(-)
---
diff --git a/meson.build b/meson.build
index d0af9eef8..9deaa6c10 100644
--- a/meson.build
+++ b/meson.build
@@ -94,6 +94,7 @@ libmath = cc.find_library('m')
libpeas = dependency('libpeas-1.0', version: '>= 1.24.0')
libpeas_gtk = dependency('libpeas-gtk-1.0', version: '>= 1.24.0')
libsecret = dependency('libsecret-1', version: '>= 0.11')
+libsoup = dependency('libsoup-3.0')
libstemmer_dep = cc.find_library('stemmer')
libsoup = dependency('libsoup-2.4', version: '>= 2.48')
libunwind_dep = dependency(
diff --git a/src/client/accounts/accounts-autoconfig.vala b/src/client/accounts/accounts-autoconfig.vala
new file mode 100644
index 000000000..3ce9c3a32
--- /dev/null
+++ b/src/client/accounts/accounts-autoconfig.vala
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2022 Cédric Bellegarde <cedric bellegarde adishatz org>
+ *
+ * This software is licensed under the GNU Lesser General Public License
+ * (version 2.1 or later). See the COPYING file in this distribution.
+ */
+
+/**
+ * An account autoconfiguration helper
+ */
+
+internal errordomain Accounts.AutoConfigError {
+ ERROR
+}
+
+internal class Accounts.AutoConfigValues {
+ public string id { get; set; default = ""; }
+
+ public string imap_server { get; set; default = ""; }
+ public string imap_port { get; set; default = ""; }
+ public Geary.TlsNegotiationMethod imap_tls_method {
+ get; set; default = Geary.TlsNegotiationMethod.TRANSPORT;
+ }
+
+ public string smtp_server{ get; set; default = ""; }
+ public string smtp_port { get; set; default = ""; }
+ public Geary.TlsNegotiationMethod smtp_tls_method {
+ get; set; default = Geary.TlsNegotiationMethod.TRANSPORT;
+ }
+
+}
+
+internal class Accounts.AutoConfig {
+
+ private static string AUTOCONFIG_BASE_URI = "https://autoconfig.thunderbird.net/v1.1/";
+ private static string AUTOCONFIG_PATH = "/mail/config-v1.1.xml";
+ private static size_t SOUP_BUF_SIZE = 1024;
+
+ private unowned GLib.Cancellable cancellable;
+
+ internal AutoConfig(GLib.Cancellable auto_config_cancellable) {
+ cancellable = auto_config_cancellable;
+ }
+
+ public async AutoConfigValues get_config(string hostname)
+ throws AutoConfigError {
+ AutoConfigValues auto_config_values;
+
+ // First try to get config from mail domain, then from thunderbird
+ try {
+ auto_config_values = yield get_config_for_uri(
+ "http://autoconfig." + hostname + AUTOCONFIG_PATH
+ );
+ } catch (AutoConfigError err) {
+ auto_config_values = yield get_config_for_uri(
+ AUTOCONFIG_BASE_URI + hostname
+ );
+ }
+ return auto_config_values;
+ }
+
+ private async AutoConfigValues get_config_for_uri(string uri)
+ throws AutoConfigError {
+ Soup.Session session = new Soup.Session();
+ Soup.Message msg = new Soup.Message("GET", uri);
+ string str = "";
+
+ try {
+ var stream = yield session.send_async(
+ msg, Priority.DEFAULT, this.cancellable
+ );
+ uint8[] buf = new uint8[SOUP_BUF_SIZE];
+ size_t read = SOUP_BUF_SIZE;
+ try {
+ while (read == SOUP_BUF_SIZE) {
+ yield stream.read_all_async(
+ buf, Priority.DEFAULT, this.cancellable, out read
+ );
+ buf[read] = '\0';
+ str += (string) buf;
+ }
+ } finally {
+ try {
+ yield stream.close_async();
+ } catch (GLib.Error err) {
+ // Oh well
+ }
+ }
+ } catch (GLib.Error err) {
+ throw new AutoConfigError.ERROR(err.message);
+ }
+ return get_config_for_xml(str);
+ }
+
+ private AutoConfigValues get_config_for_xml(string xml_data)
+ throws AutoConfigError {
+ unowned Xml.Doc doc = Xml.Parser.parse_memory(xml_data, xml_data.length);
+ if (doc == null) {
+ throw new AutoConfigError.ERROR("Invalid XML");
+ }
+
+ unowned Xml.Node root = doc.get_root_element();
+ unowned Xml.Node email_provider = get_node(root, "emailProvider");
+ unowned Xml.Node incoming_server = get_node(email_provider, "incomingServer");
+ unowned Xml.Node outgoing_server = get_node(email_provider, "outgoingServer");
+
+ if (incoming_server == null || outgoing_server == null) {
+ throw new AutoConfigError.ERROR("Invalid XML");
+ }
+
+ if (incoming_server.get_prop("type") != "imap" ||
+ outgoing_server.get_prop("type") != "smtp") {
+ throw new AutoConfigError.ERROR("Unsupported protocol");
+ }
+
+ var auto_config_values = new AutoConfigValues();
+
+ auto_config_values.id = email_provider.get_prop("id");
+
+ auto_config_values.imap_server = get_node_value(incoming_server, "hostname");
+ auto_config_values.imap_port = get_node_value(incoming_server, "port");
+ auto_config_values.imap_tls_method = get_tls_method(
+ get_node_value(incoming_server, "socketType")
+ );
+
+ auto_config_values.smtp_server = get_node_value(outgoing_server, "hostname");
+ auto_config_values.smtp_port = get_node_value(outgoing_server, "port");
+ auto_config_values.smtp_tls_method = get_tls_method(
+ get_node_value(outgoing_server, "socketType")
+ );
+
+ return auto_config_values;
+ }
+
+ private unowned Xml.Node? get_node(Xml.Node root, string name) {
+ for (unowned Xml.Node entry = root.children; entry != null; entry = entry.next) {
+ if (entry.type == Xml.ElementType.ELEMENT_NODE && entry.name == name) {
+ return entry;
+ }
+ }
+ return null;
+ }
+
+ private string get_node_value(Xml.Node root, string name) {
+ for (unowned Xml.Node entry = root.children; entry != null; entry = entry.next) {
+ if (entry.type == Xml.ElementType.ELEMENT_NODE && entry.name == name) {
+ return entry.get_content();
+ }
+ }
+ return "";
+ }
+
+ private Geary.TlsNegotiationMethod get_tls_method(string method) {
+ switch (method) {
+ case "SSL":
+ return Geary.TlsNegotiationMethod.TRANSPORT;
+ case "TLS":
+ return Geary.TlsNegotiationMethod.START_TLS;
+ default:
+ return Geary.TlsNegotiationMethod.NONE;
+ }
+ }
+}
diff --git a/src/client/accounts/accounts-editor-add-pane.vala
b/src/client/accounts/accounts-editor-add-pane.vala
index 647711f47..1eb4eda3a 100644
--- a/src/client/accounts/accounts-editor-add-pane.vala
+++ b/src/client/accounts/accounts-editor-add-pane.vala
@@ -37,31 +37,29 @@ internal class Accounts.EditorAddPane : Gtk.Grid, EditorPane {
[GtkChild] private unowned Gtk.HeaderBar header;
- [GtkChild] private unowned Gtk.Grid pane_content;
+ [GtkChild] private unowned Gtk.Stack stack;
[GtkChild] private unowned Gtk.Adjustment pane_adjustment;
[GtkChild] private unowned Gtk.ListBox details_list;
- [GtkChild] private unowned Gtk.Grid receiving_panel;
-
[GtkChild] private unowned Gtk.ListBox receiving_list;
- [GtkChild] private unowned Gtk.Grid sending_panel;
-
[GtkChild] private unowned Gtk.ListBox sending_list;
- [GtkChild] private unowned Gtk.Button create_button;
+ [GtkChild] private unowned Gtk.Button action_button;
[GtkChild] private unowned Gtk.Button back_button;
- [GtkChild] private unowned Gtk.Spinner create_spinner;
+ [GtkChild] private unowned Gtk.Spinner action_spinner;
private NameRow real_name;
private EmailRow email = new EmailRow();
private string last_valid_email = "";
private string last_valid_hostname = "";
+ private GLib.Cancellable auto_config_cancellable = new GLib.Cancellable();
+
private HostnameRow imap_hostname = new HostnameRow(Geary.Protocol.IMAP);
private TransportSecurityRow imap_tls = new TransportSecurityRow();
private LoginRow imap_login = new LoginRow();
@@ -76,32 +74,19 @@ internal class Accounts.EditorAddPane : Gtk.Grid, EditorPane {
private bool controls_valid = false;
- internal EditorAddPane(Editor editor, Geary.ServiceProvider provider) {
+ internal EditorAddPane(Editor editor) {
this.editor = editor;
- this.provider = provider;
+ this.provider = Geary.ServiceProvider.OTHER;
this.accounts = editor.application.controller.account_manager;
this.engine = editor.application.engine;
- this.pane_content.set_focus_vadjustment(this.pane_adjustment);
+ this.stack.set_focus_vadjustment(this.pane_adjustment);
this.details_list.set_header_func(Editor.seperator_headers);
this.receiving_list.set_header_func(Editor.seperator_headers);
this.sending_list.set_header_func(Editor.seperator_headers);
- if (provider != Geary.ServiceProvider.OTHER) {
- this.details_list.add(
- new ServiceProviderRow<EditorAddPane>(
- provider,
- // Translators: Label for adding an email account
- // account for a generic IMAP service provider.
- _("All others")
- )
- );
- this.receiving_panel.hide();
- this.sending_panel.hide();
- }
-
this.real_name = new NameRow(this.accounts.get_account_name());
this.details_list.add(this.real_name);
@@ -130,18 +115,14 @@ internal class Accounts.EditorAddPane : Gtk.Grid, EditorPane {
this.smtp_password.validator.state_changed.connect(on_validated);
this.smtp_password.value.activate.connect(on_activated);
- if (provider == Geary.ServiceProvider.OTHER) {
- this.receiving_list.add(this.imap_hostname);
- this.receiving_list.add(this.imap_tls);
- this.receiving_list.add(this.imap_login);
- this.receiving_list.add(this.imap_password);
+ this.receiving_list.add(this.imap_hostname);
+ this.receiving_list.add(this.imap_tls);
+ this.receiving_list.add(this.imap_login);
+ this.receiving_list.add(this.imap_password);
- this.sending_list.add(this.smtp_hostname);
- this.sending_list.add(this.smtp_tls);
- this.sending_list.add(this.smtp_auth);
- } else {
- this.details_list.add(this.imap_password);
- }
+ this.sending_list.add(this.smtp_hostname);
+ this.sending_list.add(this.smtp_tls);
+ this.sending_list.add(this.smtp_auth);
}
internal Gtk.HeaderBar get_header() {
@@ -169,7 +150,8 @@ internal class Accounts.EditorAddPane : Gtk.Grid, EditorPane {
account.outgoing = new_smtp_service();
account.untrusted_host.connect(on_untrusted_host);
- if (this.provider == Geary.ServiceProvider.OTHER) {
+ if (this.provider == Geary.ServiceProvider.OTHER &&
+ this.imap_hostname.get_visible()) {
bool imap_valid = false;
bool smtp_valid = false;
@@ -302,30 +284,22 @@ internal class Accounts.EditorAddPane : Gtk.Grid, EditorPane {
Geary.Protocol.IMAP, this.provider
);
- if (this.provider == Geary.ServiceProvider.OTHER) {
- service.credentials = new Geary.Credentials(
- Geary.Credentials.Method.PASSWORD,
- this.imap_login.value.get_text().strip(),
- this.imap_password.value.get_text().strip()
- );
+ service.credentials = new Geary.Credentials(
+ Geary.Credentials.Method.PASSWORD,
+ this.imap_login.value.get_text().strip(),
+ this.imap_password.value.get_text().strip()
+ );
- Components.NetworkAddressValidator host =
- (Components.NetworkAddressValidator)
- this.imap_hostname.validator;
- GLib.NetworkAddress address = host.validated_address;
- service.host = address.hostname;
- service.port = (uint16) address.port;
- service.transport_security = this.imap_tls.value.method;
+ Components.NetworkAddressValidator host =
+ (Components.NetworkAddressValidator)
+ this.imap_hostname.validator;
+ GLib.NetworkAddress address = host.validated_address;
+ service.host = address.hostname;
+ service.port = (uint16) address.port;
+ service.transport_security = this.imap_tls.value.method;
- if (service.port == 0) {
- service.port = service.get_default_port();
- }
- } else {
- service.credentials = new Geary.Credentials(
- Geary.Credentials.Method.PASSWORD,
- this.email.value.get_text().strip(),
- this.imap_password.value.get_text().strip()
- );
+ if (service.port == 0) {
+ service.port = service.get_default_port();
}
return service;
@@ -336,90 +310,204 @@ internal class Accounts.EditorAddPane : Gtk.Grid, EditorPane {
Geary.Protocol.SMTP, this.provider
);
- if (this.provider == Geary.ServiceProvider.OTHER) {
- service.credentials_requirement = this.smtp_auth.value.source;
- if (service.credentials_requirement ==
- Geary.Credentials.Requirement.CUSTOM) {
- service.credentials = new Geary.Credentials(
- Geary.Credentials.Method.PASSWORD,
- this.smtp_login.value.get_text().strip(),
- this.smtp_password.value.get_text().strip()
- );
- }
+ service.credentials_requirement = this.smtp_auth.value.source;
+ if (service.credentials_requirement ==
+ Geary.Credentials.Requirement.CUSTOM) {
+ service.credentials = new Geary.Credentials(
+ Geary.Credentials.Method.PASSWORD,
+ this.smtp_login.value.get_text().strip(),
+ this.smtp_password.value.get_text().strip()
+ );
+ }
- Components.NetworkAddressValidator host =
- (Components.NetworkAddressValidator)
- this.smtp_hostname.validator;
- GLib.NetworkAddress address = host.validated_address;
+ Components.NetworkAddressValidator host =
+ (Components.NetworkAddressValidator)
+ this.smtp_hostname.validator;
+ GLib.NetworkAddress address = host.validated_address;
- service.host = address.hostname;
- service.port = (uint16) address.port;
- service.transport_security = this.smtp_tls.value.method;
+ service.host = address.hostname;
+ service.port = (uint16) address.port;
+ service.transport_security = this.smtp_tls.value.method;
- if (service.port == 0) {
- service.port = service.get_default_port();
- }
+ if (service.port == 0) {
+ service.port = service.get_default_port();
}
return service;
}
private void check_validation() {
+ bool server_settings_visible = this.stack.get_visible_child_name() == "server_settings";
bool controls_valid = true;
- foreach (Gtk.ListBox list in new Gtk.ListBox[] {
+ Gtk.ListBox[] list_boxes;
+ if (server_settings_visible) {
+ list_boxes = new Gtk.ListBox[] {
this.details_list, this.receiving_list, this.sending_list
- }) {
- list.foreach((child) => {
+ };
+ } else {
+ list_boxes = new Gtk.ListBox[] { this.details_list };
+ }
+ foreach (Gtk.ListBox list_box in list_boxes) {
+ list_box.foreach((child) => {
AddPaneRow? validatable = child as AddPaneRow;
if (validatable != null && !validatable.validator.is_valid) {
controls_valid = false;
}
});
}
- this.create_button.set_sensitive(controls_valid);
+ this.action_button.set_sensitive(controls_valid);
this.controls_valid = controls_valid;
}
private void update_operation_ui(bool is_running) {
- this.create_spinner.visible = is_running;
- this.create_spinner.active = is_running;
- this.create_button.sensitive = !is_running;
+ this.action_spinner.visible = is_running;
+ this.action_spinner.active = is_running;
+ this.action_button.sensitive = !is_running;
this.back_button.sensitive = !is_running;
this.sensitive = !is_running;
}
+ private void switch_to_user_settings() {
+ this.stack.set_visible_child_name("user_settings");
+ this.action_button.set_label(_("_Next"));
+ this.action_button.set_sensitive(true);
+ this.action_button.get_style_context().remove_class("suggested-action");
+ }
+
+ private void switch_to_server_settings() {
+ this.stack.set_visible_child_name("server_settings");
+ this.action_button.set_label(_("_Create"));
+ this.action_button.set_sensitive(false);
+ this.action_button.get_style_context().add_class("suggested-action");
+ }
+
+ private void set_server_settings_from_autoconfig(AutoConfig auto_config,
+ GLib.AsyncResult res)
+ throws Accounts.AutoConfigError {
+ AutoConfigValues auto_config_values = auto_config.get_config.end(res);
+ Gtk.Entry imap_hostname_entry = this.imap_hostname.value;
+ Gtk.Entry smtp_hostname_entry = this.smtp_hostname.value;
+ TlsComboBox imap_tls_combo_box = this.imap_tls.value;
+ TlsComboBox smtp_tls_combo_box = this.smtp_tls.value;
+
+ imap_hostname_entry.text = auto_config_values.imap_server +
+ ":" + auto_config_values.imap_port;
+ smtp_hostname_entry.text = auto_config_values.smtp_server +
+ ":" + auto_config_values.smtp_port;
+ imap_tls_combo_box.method = auto_config_values.imap_tls_method;
+ smtp_tls_combo_box.method = auto_config_values.smtp_tls_method;
+
+ this.imap_hostname.hide();
+ this.smtp_hostname.hide();
+ this.imap_tls.hide();
+ this.smtp_tls.hide();
+
+ switch (auto_config_values.id) {
+ case "googlemail.com":
+ this.provider = Geary.ServiceProvider.GMAIL;
+ break;
+ case "hotmail.com":
+ this.provider = Geary.ServiceProvider.OUTLOOK;
+ break;
+ default:
+ this.provider = Geary.ServiceProvider.OTHER;
+ break;
+ }
+ }
+
+ private void set_server_settings_from_hostname(string hostname) {
+ Gtk.Entry imap_hostname_entry = this.imap_hostname.value;
+ Gtk.Entry smtp_hostname_entry = this.smtp_hostname.value;
+ string smtp_hostname = "smtp." + hostname;
+ string imap_hostname = "imap." + hostname;
+ string last_imap_hostname = "";
+ string last_smtp_hostname = "";
+
+ this.imap_hostname.show();
+ this.smtp_hostname.show();
+
+ if (this.last_valid_hostname != "") {
+ last_imap_hostname = "imap." + this.last_valid_hostname;
+ last_smtp_hostname = "smtp." + this.last_valid_hostname;
+ }
+ if (imap_hostname_entry.text == last_imap_hostname) {
+ imap_hostname_entry.text = imap_hostname;
+ }
+ if (smtp_hostname_entry.text == last_smtp_hostname) {
+ smtp_hostname_entry.text = smtp_hostname;
+ }
+ this.last_valid_hostname = hostname;
+ }
+
+ private void add_goa_account() {
+ this.accounts.add_goa_account.begin(
+ this.provider, this.op_cancellable,
+ (obj, res) => {
+ bool add_local = false;
+ try {
+ this.accounts.add_goa_account.end(res);
+ } catch (GLib.IOError.NOT_SUPPORTED err) {
+ // Not a supported type, so don't bother logging the error
+ add_local = true;
+ } catch (GLib.Error err) {
+ debug("Failed to add %s via GOA: %s",
+ this.provider.to_string(), err.message);
+ add_local = true;
+ }
+ // Google Mail does not support "Less secure apps" anymore
+ if (add_local) {
+ switch (this.provider) {
+ case Geary.ServiceProvider.GMAIL:
+ this.editor.add_notification(
+ new Components.InAppNotification(
+ // Translators: In-app notification label, when
+ // GNOME Online Accounts are missing
+ _("Online accounts are missing")
+ )
+ );
+ add_local = false;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (add_local) {
+ switch_to_server_settings();
+ } else {
+ this.editor.pop();
+ }
+ }
+ );
+ }
+
private void on_validated(Components.Validator.Trigger reason) {
check_validation();
if (this.controls_valid && reason == Components.Validator.Trigger.ACTIVATED) {
- this.create_button.clicked();
+ this.action_button.clicked();
}
}
private void on_activated() {
if (this.controls_valid) {
- this.create_button.clicked();
+ this.action_button.clicked();
}
}
private void on_email_changed() {
Gtk.Entry imap_login_entry = this.imap_login.value;
Gtk.Entry smtp_login_entry = this.smtp_login.value;
- Gtk.Entry imap_hostname_entry = this.imap_hostname.value;
- Gtk.Entry smtp_hostname_entry = this.smtp_hostname.value;
- string email = "";
- string hostname = "";
- string imap_hostname = "";
- string smtp_hostname = "";
- string last_imap_hostname = "";
- string last_smtp_hostname = "";
- if (this.email.validator.state == Components.Validator.Validity.VALID) {
- email = this.email.value.text;
- hostname = email.split("@")[1];
- smtp_hostname = "smtp." + hostname;
- imap_hostname = "imap." + hostname;
+ this.auto_config_cancellable.cancel();
+
+ if (this.email.validator.state != Components.Validator.Validity.VALID) {
+ return;
}
+ string email = this.email.value.text;
+ string hostname = email.split("@")[1];
+
+ // Do not update entries if changed by user
if (imap_login_entry.text == this.last_valid_email) {
imap_login_entry.text = email;
}
@@ -427,19 +515,23 @@ internal class Accounts.EditorAddPane : Gtk.Grid, EditorPane {
smtp_login_entry.text = email;
}
- if (this.last_valid_hostname != "") {
- last_imap_hostname = "imap." + this.last_valid_hostname;
- last_smtp_hostname = "smtp." + this.last_valid_hostname;
- }
- if (imap_hostname_entry.text == last_imap_hostname) {
- imap_hostname_entry.text = imap_hostname;
- }
- if (smtp_hostname_entry.text == last_smtp_hostname) {
- smtp_hostname_entry.text = smtp_hostname;
- }
-
this.last_valid_email = email;
- this.last_valid_hostname = hostname;
+
+ // Try to get configuration from Thunderbird autoconfig service
+ this.action_spinner.visible = true;
+ this.action_spinner.active = true;
+ this.auto_config_cancellable = new GLib.Cancellable();
+ var auto_config = new AutoConfig(this.auto_config_cancellable);
+ auto_config.get_config.begin(hostname, (obj, res) => {
+ try {
+ set_server_settings_from_autoconfig(auto_config, res);
+ } catch (Accounts.AutoConfigError err) {
+ debug("Error getting auto configuration: %s", err.message);
+ set_server_settings_from_hostname(hostname);
+ }
+ this.action_spinner.visible = false;
+ this.action_spinner.active = false;
+ });
}
private void on_smtp_auth_changed() {
@@ -474,13 +566,29 @@ internal class Accounts.EditorAddPane : Gtk.Grid, EditorPane {
}
[GtkCallback]
- private void on_create_button_clicked() {
- this.validate_account.begin(this.op_cancellable);
+ private void on_action_button_clicked() {
+ if (this.stack.get_visible_child_name() == "user_settings") {
+ switch (this.provider) {
+ case Geary.ServiceProvider.GMAIL:
+ case Geary.ServiceProvider.OUTLOOK:
+ add_goa_account();
+ break;
+ case Geary.ServiceProvider.OTHER:
+ switch_to_server_settings();
+ break;
+ }
+ } else {
+ this.validate_account.begin(this.op_cancellable);
+ }
}
[GtkCallback]
private void on_back_button_clicked() {
- this.editor.pop();
+ if (this.stack.get_visible_child_name() == "user_settings") {
+ this.editor.pop();
+ } else {
+ switch_to_user_settings();
+ }
}
[GtkCallback]
diff --git a/src/client/accounts/accounts-editor-list-pane.vala
b/src/client/accounts/accounts-editor-list-pane.vala
index c156eeaff..e7d718430 100644
--- a/src/client/accounts/accounts-editor-list-pane.vala
+++ b/src/client/accounts/accounts-editor-list-pane.vala
@@ -31,7 +31,7 @@ internal class Accounts.EditorListPane : Gtk.Grid, EditorPane, CommandPane {
/** {@inheritDoc} */
internal Gtk.Widget initial_widget {
get {
- return this.show_welcome ? this.service_list : this.accounts_list;
+ return this.accounts_list;
}
}
@@ -73,10 +73,6 @@ internal class Accounts.EditorListPane : Gtk.Grid, EditorPane, CommandPane {
[GtkChild] private unowned Gtk.Frame accounts_list_frame;
- [GtkChild] private unowned Gtk.Label add_service_label;
-
- [GtkChild] private unowned Gtk.ListBox service_list;
-
private Gee.Map<Geary.AccountInformation,EditorEditPane> edit_pane_cache =
new Gee.HashMap<Geary.AccountInformation,EditorEditPane>();
@@ -97,12 +93,6 @@ internal class Accounts.EditorListPane : Gtk.Grid, EditorPane, CommandPane {
add_account(account, this.accounts.get_status(account));
}
- this.service_list.set_header_func(Editor.seperator_headers);
- this.service_list.add(new AddServiceProviderRow(Geary.ServiceProvider.GMAIL));
- this.service_list.add(new AddServiceProviderRow(Geary.ServiceProvider.OUTLOOK));
- this.service_list.add(new AddServiceProviderRow(Geary.ServiceProvider.YAHOO));
- this.service_list.add(new AddServiceProviderRow(Geary.ServiceProvider.OTHER));
-
this.accounts.account_added.connect(on_account_added);
this.accounts.account_status_changed.connect(on_account_status_changed);
this.accounts.account_removed.connect(on_account_removed);
@@ -128,8 +118,8 @@ internal class Accounts.EditorListPane : Gtk.Grid, EditorPane, CommandPane {
base.destroy();
}
- internal void show_new_account(Geary.ServiceProvider provider) {
- this.editor.push(new EditorAddPane(this.editor, provider));
+ internal void show_new_account() {
+ this.editor.push(new EditorAddPane(this.editor));
}
internal void show_existing_account(Geary.AccountInformation account) {
@@ -171,13 +161,11 @@ internal class Accounts.EditorListPane : Gtk.Grid, EditorPane, CommandPane {
// pane and service list.
this.welcome_panel.show();
this.accounts_list_frame.hide();
- this.add_service_label.hide();
} else {
// There are some accounts available, so show them and
// the full add service UI.
this.welcome_panel.hide();
this.accounts_list_frame.show();
- this.add_service_label.show();
}
}
@@ -266,21 +254,9 @@ internal class Accounts.EditorListPane : Gtk.Grid, EditorPane, CommandPane {
}
[GtkCallback]
- private bool on_list_keynav_failed(Gtk.Widget widget,
- Gtk.DirectionType direction) {
- bool ret = Gdk.EVENT_PROPAGATE;
- if (direction == Gtk.DirectionType.DOWN &&
- widget == this.accounts_list) {
- this.service_list.child_focus(direction);
- ret = Gdk.EVENT_STOP;
- } else if (direction == Gtk.DirectionType.UP &&
- widget == this.service_list) {
- this.accounts_list.child_focus(direction);
- ret = Gdk.EVENT_STOP;
- }
- return ret;
+ private void on_add_button_clicked() {
+ show_new_account();
}
-
}
@@ -353,10 +329,6 @@ private class Accounts.AccountListRow : AccountRow<EditorListPane,Gtk.Grid> {
details = _("Outlook.com");
break;
- case Geary.ServiceProvider.YAHOO:
- details = _("Yahoo");
- break;
-
case Geary.ServiceProvider.OTHER:
// no-op: Use the generated label
break;
@@ -424,75 +396,6 @@ private class Accounts.AccountListRow : AccountRow<EditorListPane,Gtk.Grid> {
}
-private class Accounts.AddServiceProviderRow : EditorRow<EditorListPane> {
-
-
- internal Geary.ServiceProvider provider;
-
- private Gtk.Label service_name = new Gtk.Label("");
- private Gtk.Image next_icon = new Gtk.Image.from_icon_name(
- "go-next-symbolic", Gtk.IconSize.SMALL_TOOLBAR
- );
-
-
- public AddServiceProviderRow(Geary.ServiceProvider provider) {
- this.provider = provider;
-
- // Translators: Label for adding a generic email account
- string? name = null;
- switch (provider) {
- case Geary.ServiceProvider.GMAIL:
- name = _("Gmail");
- break;
-
- case Geary.ServiceProvider.OUTLOOK:
- name = _("Outlook.com");
- break;
-
- case Geary.ServiceProvider.YAHOO:
- name = _("Yahoo");
- break;
-
- case Geary.ServiceProvider.OTHER:
- name = _("Other email providers");
- break;
- }
- this.service_name.set_text(name);
- this.service_name.set_hexpand(true);
- this.service_name.halign = Gtk.Align.START;
- this.service_name.show();
-
- this.next_icon.show();
-
- this.layout.add(this.service_name);
- this.layout.add(this.next_icon);
- }
-
- public override void activated(EditorListPane pane) {
- pane.accounts.add_goa_account.begin(
- this.provider, pane.op_cancellable,
- (obj, res) => {
- bool add_local = false;
- try {
- pane.accounts.add_goa_account.end(res);
- } catch (GLib.IOError.NOT_SUPPORTED err) {
- // Not a supported type, so don't bother logging the error
- add_local = true;
- } catch (GLib.Error err) {
- debug("Failed to add %s via GOA: %s",
- this.provider.to_string(), err.message);
- add_local = true;
- }
-
- if (add_local) {
- pane.show_new_account(this.provider);
- }
- });
- }
-
-}
-
-
internal class Accounts.ReorderAccountCommand : Application.Command {
diff --git a/src/client/accounts/accounts-editor-row.vala b/src/client/accounts/accounts-editor-row.vala
index cca825acc..2f8084667 100644
--- a/src/client/accounts/accounts-editor-row.vala
+++ b/src/client/accounts/accounts-editor-row.vala
@@ -283,10 +283,6 @@ internal class Accounts.ServiceProviderRow<PaneType> :
label = _("Outlook.com");
break;
- case Geary.ServiceProvider.YAHOO:
- label = _("Yahoo");
- break;
-
case Geary.ServiceProvider.OTHER:
label = other_type_label;
break;
diff --git a/src/client/accounts/accounts-editor-servers-pane.vala
b/src/client/accounts/accounts-editor-servers-pane.vala
index 558bc9bcc..8bd9bde1f 100644
--- a/src/client/accounts/accounts-editor-servers-pane.vala
+++ b/src/client/accounts/accounts-editor-servers-pane.vala
@@ -115,7 +115,6 @@ internal class Accounts.EditorServersPane :
this.account, this.commands, this.op_cancellable
);
switch (account.service_provider) {
- case YAHOO:
case OTHER:
add_row(this.details_list, this.save_sent);
break;
diff --git a/src/client/meson.build b/src/client/meson.build
index bb485ac84..ab68ee5f1 100644
--- a/src/client/meson.build
+++ b/src/client/meson.build
@@ -34,6 +34,7 @@ client_vala_sources = files(
'application/goa-mediator.vala',
'application/secret-mediator.vala',
+ 'accounts/accounts-autoconfig.vala',
'accounts/accounts-editor.vala',
'accounts/accounts-editor-add-pane.vala',
'accounts/accounts-editor-edit-pane.vala',
diff --git a/src/engine/api/geary-engine.vala b/src/engine/api/geary-engine.vala
index 69089c08a..ab8b40d71 100644
--- a/src/engine/api/geary-engine.vala
+++ b/src/engine/api/geary-engine.vala
@@ -218,26 +218,17 @@ public class Geary.Engine : BaseObject {
);
break;
- case ServiceProvider.YAHOO:
- account = new ImapEngine.YahooAccount(
- config, local, incoming_remote, outgoing_remote
- );
- break;
-
case ServiceProvider.OUTLOOK:
account = new ImapEngine.OutlookAccount(
config, local, incoming_remote, outgoing_remote
);
break;
- case ServiceProvider.OTHER:
+ default:
account = new ImapEngine.OtherAccount(
config, local, incoming_remote, outgoing_remote
);
break;
-
- default:
- assert_not_reached();
}
config.notify["ordinal"].connect(on_account_ordinal_changed);
diff --git a/src/engine/api/geary-service-provider.vala b/src/engine/api/geary-service-provider.vala
index 517bc3a4b..c61cba421 100644
--- a/src/engine/api/geary-service-provider.vala
+++ b/src/engine/api/geary-service-provider.vala
@@ -12,7 +12,6 @@
public enum Geary.ServiceProvider {
GMAIL,
- YAHOO,
OUTLOOK,
OTHER;
@@ -34,9 +33,6 @@ public enum Geary.ServiceProvider {
case GMAIL:
ImapEngine.GmailAccount.setup_account(service);
break;
- case YAHOO:
- ImapEngine.YahooAccount.setup_account(service);
- break;
case OUTLOOK:
ImapEngine.OutlookAccount.setup_account(service);
break;
@@ -51,9 +47,6 @@ public enum Geary.ServiceProvider {
case GMAIL:
ImapEngine.GmailAccount.setup_service(service);
break;
- case YAHOO:
- ImapEngine.YahooAccount.setup_service(service);
- break;
case OUTLOOK:
ImapEngine.OutlookAccount.setup_service(service);
break;
diff --git a/src/engine/meson.build b/src/engine/meson.build
index a29daf0b0..c2e22d622 100644
--- a/src/engine/meson.build
+++ b/src/engine/meson.build
@@ -223,8 +223,6 @@ engine_vala_sources = files(
'imap-engine/replay-ops/imap-engine-replay-update.vala',
'imap-engine/replay-ops/imap-engine-server-search-email.vala',
'imap-engine/replay-ops/imap-engine-user-close.vala',
- 'imap-engine/yahoo/imap-engine-yahoo-account.vala',
- 'imap-engine/yahoo/imap-engine-yahoo-folder.vala',
'memory/memory-buffer.vala',
'memory/memory-byte-buffer.vala',
diff --git a/test/engine/api/geary-account-information-test.vala
b/test/engine/api/geary-account-information-test.vala
index 447902738..aec0a6a71 100644
--- a/test/engine/api/geary-account-information-test.vala
+++ b/test/engine/api/geary-account-information-test.vala
@@ -41,14 +41,6 @@ class Geary.AccountInformationTest : TestCase {
new RFC822.MailboxAddress(null, "test1 example com")
).save_sent
);
- assert_true(
- new AccountInformation(
- "test",
- ServiceProvider.YAHOO,
- new Mock.CredentialsMediator(),
- new RFC822.MailboxAddress(null, "test1 example com")
- ).save_sent
- );
}
public void test_sender_mailboxes() throws GLib.Error {
diff --git a/ui/accounts_editor_add_pane.ui b/ui/accounts_editor_add_pane.ui
index cfe259021..8a38f67a9 100644
--- a/ui/accounts_editor_add_pane.ui
+++ b/ui/accounts_editor_add_pane.ui
@@ -7,34 +7,29 @@
<property name="title" translatable="yes">Add an account</property>
<property name="has_subtitle">False</property>
<child>
- <object class="GtkGrid">
+ <object class="GtkButton" id="back_button">
<property name="visible">True</property>
+ <property name="receives_default">True</property>
+ <signal name="clicked" handler="on_back_button_clicked" swapped="no"/>
<child>
- <object class="GtkButton" id="back_button">
+ <object class="GtkImage">
<property name="visible">True</property>
- <property name="receives_default">True</property>
- <signal name="clicked" handler="on_back_button_clicked" swapped="no"/>
- <child>
- <object class="GtkImage">
- <property name="visible">True</property>
- <property name="no_show_all">True</property>
- <property name="icon_name">go-previous-symbolic</property>
- </object>
- </child>
+ <property name="no_show_all">True</property>
+ <property name="icon_name">go-previous-symbolic</property>
</object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">0</property>
- </packing>
</child>
</object>
+ <packing>
+ <property name="pack_type">start</property>
+ <property name="position">1</property>
+ </packing>
</child>
<child>
<object class="GtkGrid">
<property name="visible">True</property>
<property name="column_spacing">12</property>
<child>
- <object class="GtkSpinner" id="create_spinner">
+ <object class="GtkSpinner" id="action_spinner">
<property name="visible">True</property>
</object>
<packing>
@@ -43,16 +38,13 @@
</packing>
</child>
<child>
- <object class="GtkButton" id="create_button">
- <property name="label" translatable="yes">_Create</property>
+ <object class="GtkButton" id="action_button">
+ <property name="label" translatable="yes">_Next</property>
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="receives_default">True</property>
<property name="use_underline">True</property>
- <signal name="clicked" handler="on_create_button_clicked" swapped="no"/>
- <style>
- <class name="suggested-action"/>
- </style>
+ <signal name="clicked" handler="on_action_button_clicked" swapped="no"/>
</object>
<packing>
<property name="left_attach">1</property>
@@ -89,13 +81,14 @@
<property name="visible">True</property>
<property name="margin">24</property>
<child>
- <object class="GtkGrid" id="pane_content">
+ <object class="GtkStack" id="stack">
<property name="visible">True</property>
<child>
<object class="GtkFrame">
<property name="visible">True</property>
<property name="label_xalign">0</property>
<property name="shadow_type">in</property>
+ <property name="valign">start</property>
<child>
<object class="GtkListBox" id="details_list">
<property name="visible">True</property>
@@ -105,102 +98,98 @@
</child>
</object>
<packing>
- <property name="left_attach">0</property>
- <property name="top_attach">0</property>
+ <property name="name">user_settings</property>
</packing>
</child>
<child>
- <object class="GtkGrid" id="receiving_panel">
+ <object class="GtkBox">
<property name="visible">True</property>
+ <property name="orientation">vertical</property>
<child>
- <object class="GtkLabel">
+ <object class="GtkGrid" id="receiving_panel">
<property name="visible">True</property>
- <property name="halign">start</property>
- <property name="label" translatable="yes">Receiving</property>
- <attributes>
- <attribute name="weight" value="bold"/>
- </attributes>
- <style>
- <class name="geary-settings-heading"/>
- </style>
- </object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkFrame">
- <property name="visible">True</property>
- <property name="label_xalign">0</property>
- <property name="shadow_type">in</property>
<child>
- <object class="GtkListBox" id="receiving_list">
+ <object class="GtkLabel">
<property name="visible">True</property>
- <property name="selection_mode">none</property>
- <signal name="keynav-failed" handler="on_list_keynav_failed" swapped="no"/>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes">Receiving</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ <style>
+ <class name="geary-settings-heading"/>
+ </style>
</object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkListBox" id="receiving_list">
+ <property name="visible">True</property>
+ <property name="selection_mode">none</property>
+ <signal name="keynav-failed" handler="on_list_keynav_failed"
swapped="no"/>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
</child>
</object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkGrid" id="sending_panel">
- <property name="visible">True</property>
- <child>
- <object class="GtkLabel">
- <property name="visible">True</property>
- <property name="halign">start</property>
- <property name="label" translatable="yes">Sending</property>
- <attributes>
- <attribute name="weight" value="bold"/>
- </attributes>
- <style>
- <class name="geary-settings-heading"/>
- </style>
- </object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">0</property>
- </packing>
</child>
<child>
- <object class="GtkFrame">
+ <object class="GtkGrid" id="sending_panel">
<property name="visible">True</property>
- <property name="label_xalign">0</property>
- <property name="shadow_type">in</property>
<child>
- <object class="GtkListBox" id="sending_list">
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes">Sending</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ <style>
+ <class name="geary-settings-heading"/>
+ </style>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame">
<property name="visible">True</property>
- <property name="selection_mode">none</property>
- <signal name="keynav-failed" handler="on_list_keynav_failed" swapped="no"/>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkListBox" id="sending_list">
+ <property name="visible">True</property>
+ <property name="selection_mode">none</property>
+ <signal name="keynav-failed" handler="on_list_keynav_failed"
swapped="no"/>
+ </object>
+ </child>
</object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
</child>
</object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">1</property>
- </packing>
</child>
</object>
<packing>
- <property name="left_attach">0</property>
- <property name="top_attach">2</property>
+ <property name="name">server_settings</property>
</packing>
</child>
- <style>
- <class name="geary-accounts-editor-pane-content"/>
- </style>
-
</object>
</child>
</object>
diff --git a/ui/accounts_editor_list_pane.ui b/ui/accounts_editor_list_pane.ui
index 2f5e6af27..f92084417 100644
--- a/ui/accounts_editor_list_pane.ui
+++ b/ui/accounts_editor_list_pane.ui
@@ -7,6 +7,19 @@
<property name="title" translatable="yes">Accounts</property>
<property name="has_subtitle">False</property>
<property name="show_close_button">True</property>
+ <child>
+ <object class="GtkButton" id="add_button">
+ <property name="label" translatable="yes">_Add</property>
+ <property name="tooltip_text" translatable="yes">Add an account</property>
+ <property name="visible">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ <signal name="clicked" handler="on_add_button_clicked" swapped="no"/>
+ <style>
+ <class name="suggested-action"/>
+ </style>
+ </object>
+ </child>
</object>
<object class="GtkAdjustment" id="pane_adjustment">
<property name="upper">100</property>
@@ -103,7 +116,6 @@
<object class="GtkListBox" id="accounts_list">
<property name="visible">True</property>
<property name="selection_mode">none</property>
- <signal name="keynav-failed" handler="on_list_keynav_failed" swapped="no"/>
<signal name="row-activated" handler="on_row_activated" swapped="no"/>
</object>
</child>
@@ -115,53 +127,9 @@
<property name="top_attach">1</property>
</packing>
</child>
- <child>
- <object class="GtkLabel" id="add_service_label">
- <property name="visible">True</property>
- <property name="halign">start</property>
- <property name="label" translatable="yes">Add an account</property>
- <attributes>
- <attribute name="weight" value="bold"/>
- </attributes>
- <style>
- <class name="geary-settings-heading"/>
- </style>
- </object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">2</property>
- </packing>
- </child>
- <child>
- <object class="GtkFrame">
- <property name="visible">True</property>
- <property name="valign">start</property>
- <property name="hexpand">True</property>
- <property name="vexpand">True</property>
- <property name="label_xalign">0</property>
- <property name="shadow_type">in</property>
- <child>
- <object class="GtkListBox" id="service_list">
- <property name="width_request">0</property>
- <property name="visible">True</property>
- <property name="valign">start</property>
- <property name="selection_mode">none</property>
- <signal name="keynav-failed" handler="on_list_keynav_failed" swapped="no"/>
- <signal name="row-activated" handler="on_row_activated" swapped="no"/>
- </object>
- </child>
- <child type="label_item">
- </child>
- </object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">3</property>
- </packing>
- </child>
<style>
<class name="geary-accounts-editor-pane-content"/>
</style>
-
</object>
</child>
</object>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]