From daf336b444fe5f1b79dfa91f836c6400aafc8b98 Mon Sep 17 00:00:00 2001 From: Marius Meisenzahl Date: Mon, 29 Jul 2024 12:28:56 +0200 Subject: [PATCH 1/4] Application: Handle flatpak+https scheme --- src/Application.vala | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/Application.vala b/src/Application.vala index 6fd59418..2c9081bc 100644 --- a/src/Application.vala +++ b/src/Application.vala @@ -21,9 +21,11 @@ public class Sideload.Application : Gtk.Application { private const string BUNDLE_CONTENT_TYPE = "application/vnd.flatpak"; private const string REF_CONTENT_TYPE = "application/vnd.flatpak.ref"; + private const string FLATPAK_HTTPS_CONTENT_TYPE = "x-scheme-handler/flatpak+https"; private const string[] SUPPORTED_CONTENT_TYPES = { BUNDLE_CONTENT_TYPE, - REF_CONTENT_TYPE + REF_CONTENT_TYPE, + FLATPAK_HTTPS_CONTENT_TYPE }; public Application () { @@ -54,6 +56,30 @@ public class Sideload.Application : Gtk.Application { } private async void open_file (File file) { + if (file.get_uri ().has_prefix ("flatpak+https://")) { + var uri = file.get_uri ().replace ("flatpak+https://", "https://"); + var path = Path.build_filename ( + Environment.get_user_special_dir (UserDirectory.DOWNLOAD), + Path.get_basename (uri) + ); + + var remote_file = File.new_for_uri (uri); + File local_file = File.new_for_path(path); + try { + if (!remote_file.copy(local_file, FileCopyFlags.OVERWRITE)) { + warning ("Failed to download file from %s", uri); + release (); + return; + } + } catch (Error e) { + critical ("Failed to download file from %s: %s", uri, e.message); + release (); + return; + } + + file = local_file; + } + FileInfo? file_info = null; try { file_info = yield file.query_info_async ( @@ -92,6 +118,8 @@ public class Sideload.Application : Gtk.Application { flatpak_file = new FlatpakRefFile (file); } else if (content_type == BUNDLE_CONTENT_TYPE) { flatpak_file = new FlatpakBundleFile (file); + } else if (content_type == FLATPAK_HTTPS_CONTENT_TYPE) { + flatpak_file = new FlatpakRefFile (file); } main_window = new MainWindow (this, flatpak_file); From 28e17bd34c344ac2826d2b4a2827a791be966e06 Mon Sep 17 00:00:00 2001 From: Marius Meisenzahl Date: Mon, 29 Jul 2024 12:29:19 +0200 Subject: [PATCH 2/4] Desktop: Handle flatpak+https scheme --- data/sideload.desktop.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/sideload.desktop.in b/data/sideload.desktop.in index e73c9297..d8dd9a09 100644 --- a/data/sideload.desktop.in +++ b/data/sideload.desktop.in @@ -10,5 +10,5 @@ Type=Application StartupNotify=true Categories=PackageManager; NoDisplay=true -MimeType=application/vnd.flatpak.ref;application/vnd.flatpak; +MimeType=application/vnd.flatpak.ref;application/vnd.flatpak;x-scheme-handler/flatpak+https; X-GNOME-UsesNotifications=true From f845696c5381e91a6d731f6170f8f32e4afdf1af Mon Sep 17 00:00:00 2001 From: Marius Meisenzahl Date: Mon, 29 Jul 2024 12:33:49 +0200 Subject: [PATCH 3/4] Application: Satisfy linter --- src/Application.vala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Application.vala b/src/Application.vala index 2c9081bc..70462f29 100644 --- a/src/Application.vala +++ b/src/Application.vala @@ -64,9 +64,9 @@ public class Sideload.Application : Gtk.Application { ); var remote_file = File.new_for_uri (uri); - File local_file = File.new_for_path(path); + File local_file = File.new_for_path (path); try { - if (!remote_file.copy(local_file, FileCopyFlags.OVERWRITE)) { + if (!remote_file.copy (local_file, FileCopyFlags.OVERWRITE)) { warning ("Failed to download file from %s", uri); release (); return; From fe4c87cbb2c38454d1198e4c4214b44f5d926678 Mon Sep 17 00:00:00 2001 From: Marius Meisenzahl Date: Tue, 30 Jul 2024 12:55:56 +0200 Subject: [PATCH 4/4] Show user error in window --- src/Application.vala | 81 ++--------------------- src/MainWindow.vala | 127 +++++++++++++++++++++++++++++++------ src/Views/SuccessView.vala | 2 +- 3 files changed, 111 insertions(+), 99 deletions(-) diff --git a/src/Application.vala b/src/Application.vala index 70462f29..9985992f 100644 --- a/src/Application.vala +++ b/src/Application.vala @@ -19,15 +19,6 @@ */ public class Sideload.Application : Gtk.Application { - private const string BUNDLE_CONTENT_TYPE = "application/vnd.flatpak"; - private const string REF_CONTENT_TYPE = "application/vnd.flatpak.ref"; - private const string FLATPAK_HTTPS_CONTENT_TYPE = "x-scheme-handler/flatpak+https"; - private const string[] SUPPORTED_CONTENT_TYPES = { - BUNDLE_CONTENT_TYPE, - REF_CONTENT_TYPE, - FLATPAK_HTTPS_CONTENT_TYPE - }; - public Application () { GLib.Intl.setlocale (LocaleCategory.ALL, ""); GLib.Intl.bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); @@ -56,73 +47,9 @@ public class Sideload.Application : Gtk.Application { } private async void open_file (File file) { - if (file.get_uri ().has_prefix ("flatpak+https://")) { - var uri = file.get_uri ().replace ("flatpak+https://", "https://"); - var path = Path.build_filename ( - Environment.get_user_special_dir (UserDirectory.DOWNLOAD), - Path.get_basename (uri) - ); - - var remote_file = File.new_for_uri (uri); - File local_file = File.new_for_path (path); - try { - if (!remote_file.copy (local_file, FileCopyFlags.OVERWRITE)) { - warning ("Failed to download file from %s", uri); - release (); - return; - } - } catch (Error e) { - critical ("Failed to download file from %s: %s", uri, e.message); - release (); - return; - } - - file = local_file; - } - - FileInfo? file_info = null; - try { - file_info = yield file.query_info_async ( - FileAttribute.STANDARD_CONTENT_TYPE, - FileQueryInfoFlags.NONE - ); - } catch (Error e) { - critical ("Unable to query content type of provided file: %s", e.message); - release (); - return; - } - - if (file_info == null) { - warning ("Unable to query content type of provided file"); - release (); - return; - } - - var content_type = file_info.get_attribute_as_string (FileAttribute.STANDARD_CONTENT_TYPE); - if (content_type == null) { - warning ("Unable to query content type of provided file"); - release (); - return; - } - - if (!(content_type in SUPPORTED_CONTENT_TYPES)) { - warning ("This does not appear to be a valid flatpak/flatpakref file"); - release (); - return; - } - - Gtk.ApplicationWindow main_window = null; - FlatpakFile flatpak_file = null; - - if (content_type == REF_CONTENT_TYPE) { - flatpak_file = new FlatpakRefFile (file); - } else if (content_type == BUNDLE_CONTENT_TYPE) { - flatpak_file = new FlatpakBundleFile (file); - } else if (content_type == FLATPAK_HTTPS_CONTENT_TYPE) { - flatpak_file = new FlatpakRefFile (file); - } + Sideload.MainWindow main_window = null; - main_window = new MainWindow (this, flatpak_file); + main_window = new MainWindow (this, file); main_window.present (); var launch_action = new SimpleAction ("launch", null); @@ -130,8 +57,8 @@ public class Sideload.Application : Gtk.Application { add_action (launch_action); launch_action.activate.connect (() => { - flatpak_file.launch.begin ((obj, res) => { - flatpak_file.launch.end (res); + main_window.flatpak_file.launch.begin ((obj, res) => { + main_window.flatpak_file.launch.end (res); main_window.close (); }); }); diff --git a/src/MainWindow.vala b/src/MainWindow.vala index 2948d5db..37379469 100644 --- a/src/MainWindow.vala +++ b/src/MainWindow.vala @@ -19,7 +19,17 @@ */ public class Sideload.MainWindow : Gtk.ApplicationWindow { - public FlatpakFile file { get; construct; } + private const string BUNDLE_CONTENT_TYPE = "application/vnd.flatpak"; + private const string REF_CONTENT_TYPE = "application/vnd.flatpak.ref"; + private const string FLATPAK_HTTPS_CONTENT_TYPE = "x-scheme-handler/flatpak+https"; + private const string[] SUPPORTED_CONTENT_TYPES = { + BUNDLE_CONTENT_TYPE, + REF_CONTENT_TYPE, + FLATPAK_HTTPS_CONTENT_TYPE + }; + + public File file { get; construct; } + public FlatpakFile flatpak_file { get; construct; } private Cancellable? current_cancellable = null; private Gtk.Stack stack; @@ -29,7 +39,7 @@ public class Sideload.MainWindow : Gtk.ApplicationWindow { private string? app_name = null; private string? app_id = null; - public MainWindow (Gtk.Application application, FlatpakFile file) { + public MainWindow (Gtk.Application application, File file) { Object ( application: application, icon_name: "io.elementary.sideload", @@ -75,35 +85,110 @@ public class Sideload.MainWindow : Gtk.ApplicationWindow { } }); - if (file.size == "0") { - var error_view = new ErrorView (file.error_code, file.error_message); + if (file.get_uri ().has_prefix ("flatpak+https://")) { + var uri = file.get_uri ().replace ("flatpak+https://", "https://"); + var path = Path.build_filename ( + Environment.get_user_special_dir (UserDirectory.DOWNLOAD), + Path.get_basename (uri) + ); + + var remote_file = File.new_for_uri (uri); + var local_file = File.new_for_path (path); + try { + if (!remote_file.copy (local_file, FileCopyFlags.OVERWRITE)) { + var message = (_("Failed to download file from %s")).printf (uri); + var error_view = new ErrorView (-1, message); + stack.add_child (error_view); + stack.visible_child = error_view; + return; + } + } catch (Error e) { + var message = (_("Failed to download file from %s: %s")).printf (uri, e.message); + var error_view = new ErrorView (-1, message); + stack.add_child (error_view); + stack.visible_child = error_view; + return; + } + + file = local_file; + } + + FileInfo? file_info = null; + try { + file_info = file.query_info ( + FileAttribute.STANDARD_CONTENT_TYPE, + FileQueryInfoFlags.NONE + ); + } catch (Error e) { + var message = (_("Unable to query content type of provided file: %s")).printf (e.message); + var error_view = new ErrorView (-1, message); + stack.add_child (error_view); + stack.visible_child = error_view; + return; + } + + if (file_info == null) { + var message = _("Unable to query content type of provided file"); + var error_view = new ErrorView (-1, message); + stack.add_child (error_view); + stack.visible_child = error_view; + return; + } + + var content_type = file_info.get_attribute_as_string (FileAttribute.STANDARD_CONTENT_TYPE); + if (content_type == null) { + var message = _("Unable to query content type of provided file"); + var error_view = new ErrorView (-1, message); + stack.add_child (error_view); + stack.visible_child = error_view; + return; + } + + if (!(content_type in SUPPORTED_CONTENT_TYPES)) { + var message = _("This does not appear to be a valid flatpak/flatpakref file"); + var error_view = new ErrorView (-1, message); + stack.add_child (error_view); + stack.visible_child = error_view; + return; + } + + if (content_type == REF_CONTENT_TYPE) { + flatpak_file = new FlatpakRefFile (file); + } else if (content_type == BUNDLE_CONTENT_TYPE) { + flatpak_file = new FlatpakBundleFile (file); + } else if (content_type == FLATPAK_HTTPS_CONTENT_TYPE) { + flatpak_file = new FlatpakRefFile (file); + } + + if (flatpak_file.size == "0") { + var error_view = new ErrorView (flatpak_file.error_code, flatpak_file.error_message); stack.add_child (error_view); stack.visible_child = error_view; return; - } else if (file is FlatpakRefFile) { + } else if (flatpak_file is FlatpakRefFile) { progress_view = new ProgressView (ProgressView.ProgressType.REF_INSTALL); } else { progress_view = new ProgressView (ProgressView.ProgressType.BUNDLE_INSTALL); - progress_view.status = (_("Installing %s. Unable to estimate time remaining.")).printf (file.size); + progress_view.status = (_("Installing %s. Unable to estimate time remaining.")).printf (flatpak_file.size); } stack.add_child (progress_view); main_view.install_request.connect (on_install_button_clicked); - file.progress_changed.connect (on_progress_changed); - file.installation_failed.connect (on_install_failed); - file.installation_succeeded.connect (on_install_succeeded); - file.details_ready.connect (() => { - if (file.already_installed) { + flatpak_file.progress_changed.connect (on_progress_changed); + flatpak_file.installation_failed.connect (on_install_failed); + flatpak_file.installation_succeeded.connect (on_install_succeeded); + flatpak_file.details_ready.connect (() => { + if (flatpak_file.already_installed) { var success_view = new SuccessView (app_name, SuccessView.SuccessType.ALREADY_INSTALLED); stack.add_child (success_view); stack.visible_child = success_view; } else { - if (file is FlatpakRefFile) { - main_view.display_ref_details (file.size, file.extra_remotes_needed, file.permissions_flags); + if (flatpak_file is FlatpakRefFile) { + main_view.display_ref_details (flatpak_file.size, flatpak_file.extra_remotes_needed, flatpak_file.permissions_flags); } else { - main_view.display_bundle_details (file.size, ((FlatpakBundleFile) file).has_remote, file.extra_remotes_needed); + main_view.display_bundle_details (flatpak_file.size, ((FlatpakBundleFile) file).has_remote, flatpak_file.extra_remotes_needed); } } }); @@ -112,9 +197,9 @@ public class Sideload.MainWindow : Gtk.ApplicationWindow { } private async void get_details () { - yield file.get_details (); - app_name = yield file.get_name (); - app_id = yield file.get_id (); + yield flatpak_file.get_details (); + app_name = yield flatpak_file.get_name (); + app_id = yield flatpak_file.get_id (); if (app_name != null) { progress_view.app_name = app_name; @@ -124,10 +209,10 @@ public class Sideload.MainWindow : Gtk.ApplicationWindow { private void on_install_button_clicked () { current_cancellable = new Cancellable (); - file.install.begin (current_cancellable); + flatpak_file.install.begin (current_cancellable); stack.visible_child = progress_view; - if (file is FlatpakRefFile) { + if (flatpak_file is FlatpakRefFile) { Granite.Services.Application.set_progress_visible.begin (true); } } @@ -158,7 +243,7 @@ public class Sideload.MainWindow : Gtk.ApplicationWindow { break; } - if (file is FlatpakRefFile) { + if (flatpak_file is FlatpakRefFile) { Granite.Services.Application.set_progress_visible.begin (false); } } @@ -169,7 +254,7 @@ public class Sideload.MainWindow : Gtk.ApplicationWindow { stack.add_child (success_view); stack.visible_child = success_view; - if (file is FlatpakRefFile) { + if (flatpak_file is FlatpakRefFile) { Granite.Services.Application.set_progress_visible.begin (false); } diff --git a/src/Views/SuccessView.vala b/src/Views/SuccessView.vala index ff87e92a..89a0c25f 100644 --- a/src/Views/SuccessView.vala +++ b/src/Views/SuccessView.vala @@ -36,7 +36,7 @@ public class Sideload.SuccessView : AbstractView { var app = (Sideload.Application) GLib.Application.get_default (); var appstore_name = app.get_appstore_name (); - var file = ((Sideload.MainWindow) app.active_window).file; + var file = ((Sideload.MainWindow) app.active_window).flatpak_file; string? secondary_label_string; if (view_type == SuccessType.INSTALLED) {