Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Handle flatpak+https scheme #170

Merged
merged 4 commits into from
Jul 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion data/sideload.desktop.in
Original file line number Diff line number Diff line change
Expand Up @@ -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
53 changes: 4 additions & 49 deletions src/Application.vala
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +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[] SUPPORTED_CONTENT_TYPES = {
BUNDLE_CONTENT_TYPE,
REF_CONTENT_TYPE
};

public Application () {
GLib.Intl.setlocale (LocaleCategory.ALL, "");
GLib.Intl.bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
Expand Down Expand Up @@ -54,56 +47,18 @@ public class Sideload.Application : Gtk.Application {
}

private async void open_file (File 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);
}
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);

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 ();
});
});
Expand Down
127 changes: 106 additions & 21 deletions src/MainWindow.vala
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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",
Expand Down Expand Up @@ -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);
}
}
});
Expand All @@ -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;
Expand All @@ -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);
}
}
Expand Down Expand Up @@ -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);
}
}
Expand All @@ -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);
}

Expand Down
2 changes: 1 addition & 1 deletion src/Views/SuccessView.vala
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down