Make GearyApplication::show_uri handle mailto: URIs

This lets us simplify several code paths where these were handled,
and remove a signal and handler from ConversationMessage.
This commit is contained in:
Michael Gratton 2019-10-27 21:15:40 +11:00 committed by Michael James Gratton
parent 50749d9823
commit bcce3a3a83
5 changed files with 43 additions and 73 deletions

View file

@ -158,6 +158,7 @@ public class GearyApplication : Gtk.Application {
{ null }
};
private const string MAILTO_URI_SCHEME_PREFIX = "mailto:";
private const int64 USEC_PER_SEC = 1000000;
private const int64 FORCE_SHUTDOWN_USEC = 5 * USEC_PER_SEC;
@ -478,10 +479,11 @@ public class GearyApplication : Gtk.Application {
string mailto = target.get_uri();
// Due to GNOME/glib#1886, the email address may be
// prefixed by a '///'. If so, remove it.
if (mailto.has_prefix("mailto:///")) {
const string B0RKED_GLIB_MAILTO_PREFIX = "mailto:///";
if (mailto.has_prefix(B0RKED_GLIB_MAILTO_PREFIX)) {
mailto = (
Geary.ComposedEmail.MAILTO_SCHEME +
mailto.substring("mailto:///".length)
MAILTO_URI_SCHEME_PREFIX +
mailto.substring(B0RKED_GLIB_MAILTO_PREFIX.length)
);
}
this.new_composer.begin(mailto);
@ -635,19 +637,25 @@ public class GearyApplication : Gtk.Application {
}
/** Displays a URI on the current active window, if any. */
public void show_uri(string uri) throws Error {
string uri_ = uri;
public async void show_uri(string uri) {
yield create_controller();
// Support web URLs that omit the protocol.
if (!uri.contains(":")) {
uri_ = "http://" + uri;
}
if (uri.down().has_prefix(MAILTO_URI_SCHEME_PREFIX)) {
yield this.new_composer(uri);
} else {
string uri_ = uri;
// Support web URLs that omit the protocol.
if (!uri.contains(":")) {
uri_ = "http://" + uri;
}
bool success = Gtk.show_uri_on_window(
get_active_window(), uri, Gdk.CURRENT_TIME
);
if (!success) {
throw new IOError.FAILED("gtk_show_uri() returned false");
try {
Gtk.show_uri_on_window(
get_active_window(), uri_, Gdk.CURRENT_TIME
);
} catch (GLib.Error err) {
this.controller.report_problem(new Geary.ProblemReport(err));
}
}
}
@ -864,10 +872,10 @@ public class GearyApplication : Gtk.Application {
).get_strv();
foreach (string arg in args) {
// the only acceptable arguments are mailto:'s
if (arg == Geary.ComposedEmail.MAILTO_SCHEME) {
if (arg == MAILTO_URI_SCHEME_PREFIX) {
activate_action(GearyApplication.ACTION_COMPOSE, null);
activated = true;
} else if (arg.has_prefix(Geary.ComposedEmail.MAILTO_SCHEME)) {
} else if (arg.down().has_prefix(MAILTO_URI_SCHEME_PREFIX)) {
activate_action(
GearyApplication.ACTION_MAILTO,
new GLib.Variant.string(arg)
@ -1000,7 +1008,7 @@ public class GearyApplication : Gtk.Application {
private void on_activate_help() {
try {
if (this.is_installed) {
show_uri("help:geary");
this.show_uri.begin("help:geary");
} else {
Pid pid;
File exec_dir = this.exec_dir;

View file

@ -1416,7 +1416,6 @@ public class MainWindow : Gtk.ApplicationWindow, Geary.BaseInterface {
this.on_shift_key.connect(view.shift_key_changed);
foreach (ConversationMessage msg_view in view) {
msg_view.link_activated.connect(on_link_activated);
msg_view.save_image.connect((url, alt_text, buf) => {
on_save_image_extended(view, url, alt_text, buf);
});
@ -1870,12 +1869,7 @@ public class MainWindow : Gtk.ApplicationWindow, Geary.BaseInterface {
}
foreach (Geary.Attachment attachment in attachments) {
string uri = attachment.file.get_uri();
try {
this.application.show_uri(uri);
} catch (Error err) {
message("Unable to open attachment \"%s\": %s", uri, err.message);
}
this.application.show_uri.begin(attachment.file.get_uri());
}
}
@ -1911,7 +1905,7 @@ public class MainWindow : Gtk.ApplicationWindow, Geary.BaseInterface {
FileUtils.chmod(temporary_filename, (int) (Posix.S_IRUSR | Posix.S_IWUSR));
string temporary_uri = Filename.to_uri(temporary_filename, null);
this.application.show_uri(temporary_uri);
this.application.show_uri.begin(temporary_uri);
} catch (Error error) {
ErrorDialog dialog = new ErrorDialog(
this,
@ -1969,19 +1963,4 @@ public class MainWindow : Gtk.ApplicationWindow, Geary.BaseInterface {
}
}
private void on_link_activated(string uri) {
try {
if (uri.down().has_prefix(Geary.ComposedEmail.MAILTO_SCHEME)) {
this.application.controller.compose(uri);
} else {
this.application.show_uri(uri);
}
} catch (GLib.Error err) {
handle_error(
this.selected_account != null ? this.selected_account.information : null,
err
);
}
}
}

View file

@ -164,6 +164,8 @@ public class ComposerWidget : Gtk.EventBox, Geary.BaseInterface {
private const string URI_LIST_MIME_TYPE = "text/uri-list";
private const string FILE_URI_PREFIX = "file://";
private const string MAILTO_URI_PREFIX = "mailto:";
// Keep these in sync with the next const below.
private const string ATTACHMENT_KEYWORDS =
"attach|attaching|attaches|attachment|attachments|attached|enclose|enclosed|enclosing|encloses|enclosure|enclosures";
@ -566,9 +568,9 @@ public class ComposerWidget : Gtk.EventBox, Geary.BaseInterface {
this(application, initial_account, null, ComposeType.NEW_MESSAGE);
Gee.HashMultiMap<string, string> headers = new Gee.HashMultiMap<string, string>();
if (mailto.length > Geary.ComposedEmail.MAILTO_SCHEME.length) {
if (mailto.has_prefix(MAILTO_URI_PREFIX)) {
// Parse the mailto link.
string[] parts = mailto.substring(Geary.ComposedEmail.MAILTO_SCHEME.length).split("?", 2);
string[] parts = mailto.substring(MAILTO_URI_PREFIX.length).split("?", 2);
string email = Uri.unescape_string(parts[0]);
string[] params = parts.length == 2 ? parts[1].split("&") : new string[0];
foreach (string param in params) {
@ -2337,11 +2339,7 @@ public class ComposerWidget : Gtk.EventBox, Geary.BaseInterface {
this.editor.delete_link(selection_id);
});
popover.link_open.connect(() => {
try {
this.application.show_uri(popover.link_uri);
} catch (GLib.Error err) {
debug("Failed to open URI: %s", err.message);
}
this.application.show_uri.begin(popover.link_uri);
});
return popover;
}

View file

@ -25,6 +25,9 @@ public class ConversationMessage : Gtk.Grid, Geary.BaseInterface {
private const string REPLACED_CID_TEMPLATE = "replaced_%02u@geary";
private const string REPLACED_IMAGE_CLASS = "geary_replaced_inline_image";
private const string MAILTO_URI_PREFIX = "mailto:";
private const int MAX_PREVIEW_BYTES = Geary.Email.MAX_PREVIEW_BYTES;
private const int SHOW_PROGRESS_TIMEOUT_MSEC = 1000;
@ -332,9 +335,6 @@ public class ConversationMessage : Gtk.Grid, Geary.BaseInterface {
private Geary.TimeoutManager progress_pulse;
/** Fired when the user clicks a link in the email. */
public signal void link_activated(string link);
/** Fired when the user clicks a internal link in the email. */
public signal void internal_link_activated(int y);
@ -400,7 +400,7 @@ public class ConversationMessage : Gtk.Grid, Geary.BaseInterface {
// Actions
add_action(ACTION_CONVERSATION_NEW, true, VariantType.STRING)
.activate.connect(on_new_conversation);
.activate.connect(on_link_activated);
add_action(ACTION_COPY_EMAIL, true, VariantType.STRING)
.activate.connect(on_copy_email_address);
add_action(ACTION_COPY_LINK, true, VariantType.STRING)
@ -1104,7 +1104,7 @@ public class ConversationMessage : Gtk.Grid, Geary.BaseInterface {
if (hit_test.context_is_link()) {
string link_url = hit_test.get_link_uri();
MenuModel link_menu =
link_url.has_prefix(Geary.ComposedEmail.MAILTO_SCHEME)
link_url.has_prefix(MAILTO_URI_PREFIX)
? context_menu_email
: context_menu_link;
model.append_section(
@ -1221,26 +1221,10 @@ public class ConversationMessage : Gtk.Grid, Geary.BaseInterface {
clipboard.store();
}
private void on_new_conversation(Variant? param) {
string value = param.get_string();
if (value.has_prefix(Geary.ComposedEmail.MAILTO_SCHEME)) {
value = value.substring(Geary.ComposedEmail.MAILTO_SCHEME.length, -1);
}
MainWindow? main = this.get_toplevel() as MainWindow;
if (main != null &&
Geary.RFC822.MailboxAddress.is_valid_address(value)) {
Geary.RFC822.MailboxAddress mailbox = new Geary.RFC822.MailboxAddress(
null, value
);
main.open_composer_for_mailbox(mailbox);
}
}
private void on_copy_email_address(Variant? param) {
string value = param.get_string();
if (value.has_prefix(Geary.ComposedEmail.MAILTO_SCHEME)) {
value = value.substring(Geary.ComposedEmail.MAILTO_SCHEME.length, -1);
if (value.has_prefix(MAILTO_URI_PREFIX)) {
value = value.substring(MAILTO_URI_PREFIX.length, -1);
}
Gtk.Clipboard clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD);
clipboard.set_text(value, -1);
@ -1291,7 +1275,10 @@ public class ConversationMessage : Gtk.Grid, Geary.BaseInterface {
}
});
} else {
link_activated(link);
MainWindow? main = this.get_toplevel() as MainWindow;
if (main != null) {
main.application.show_uri.begin(link);
}
}
}

View file

@ -9,8 +9,6 @@
*/
public class Geary.ComposedEmail : BaseObject {
public const string MAILTO_SCHEME = "mailto:";
private const string IMG_SRC_TEMPLATE = "src=\"%s\"";
public const Geary.Email.Field REQUIRED_REPLY_FIELDS =