diff --git a/src/Core/Package.vala b/src/Core/Package.vala index 441ab92c1..91f494540 100644 --- a/src/Core/Package.vala +++ b/src/Core/Package.vala @@ -83,6 +83,7 @@ public class AppCenterCore.Package : Object { } public const string OS_UPDATES_ID = "xxx-os-updates"; + public const string RUNTIME_UPDATES_ID = "xxx-runtime-updates"; public const string LOCAL_ID_SUFFIX = ".appcenter-local"; public const string DEFAULT_PRICE_DOLLARS = "1"; @@ -102,7 +103,7 @@ public class AppCenterCore.Package : Object { private bool _installed = false; public bool installed { get { - if (component.get_id () == OS_UPDATES_ID) { + if (is_os_updates || is_runtime_updates) { return true; } @@ -188,6 +189,12 @@ public class AppCenterCore.Package : Object { } } + public bool is_runtime_updates { + get { + return component.id == RUNTIME_UPDATES_ID; + } + } + public AppStream.ComponentKind kind { get { return component.get_kind (); @@ -202,7 +209,7 @@ public class AppCenterCore.Package : Object { public bool is_shareable { get { - return is_native && component.get_kind () != AppStream.ComponentKind.DRIVER && !is_os_updates; + return is_native && component.get_kind () != AppStream.ComponentKind.DRIVER && !is_os_updates && !is_runtime_updates; } } @@ -827,7 +834,7 @@ public class AppCenterCore.Package : Object { } private string convert_version (string version) { - if (is_os_updates) { + if (is_os_updates || is_runtime_updates) { return version; } @@ -914,7 +921,7 @@ public class AppCenterCore.Package : Object { } private void populate_backend_details_sync () { - if (component.id == OS_UPDATES_ID || is_local) { + if (is_os_updates || is_runtime_updates || is_local) { backend_details = new PackageDetails (); return; } diff --git a/src/Core/UpdateManager.vala b/src/Core/UpdateManager.vala index 12f7038c1..3e04687e4 100644 --- a/src/Core/UpdateManager.vala +++ b/src/Core/UpdateManager.vala @@ -20,6 +20,7 @@ public class AppCenterCore.UpdateManager : Object { public bool restart_required { public get; private set; default = false; } public Package os_updates { public get; private set; } + public Package runtime_updates { public get; private set; } public int unpaid_apps_number { get; private set; default = 0; } public uint64 updates_size { get; private set; default = 0ULL; } public bool has_flatpak_updates { get; private set; default = false; } @@ -31,17 +32,29 @@ public class AppCenterCore.UpdateManager : Object { construct { restart_file = File.new_for_path (RESTART_REQUIRED_FILE); - var icon = new AppStream.Icon (); - icon.set_name ("distributor-logo"); - icon.set_kind (AppStream.IconKind.STOCK); + var os_icon = new AppStream.Icon (); + os_icon.set_name ("distributor-logo"); + os_icon.set_kind (AppStream.IconKind.STOCK); var os_updates_component = new AppStream.Component (); os_updates_component.id = AppCenterCore.Package.OS_UPDATES_ID; os_updates_component.name = _("Operating System Updates"); os_updates_component.summary = _("Updates to system components"); - os_updates_component.add_icon (icon); + os_updates_component.add_icon (os_icon); os_updates = new AppCenterCore.Package (BackendAggregator.get_default (), os_updates_component); + + var runtime_icon = new AppStream.Icon (); + runtime_icon.set_name ("application-vnd.flatpak"); + runtime_icon.set_kind (AppStream.IconKind.STOCK); + + var runtime_updates_component = new AppStream.Component (); + runtime_updates_component.id = AppCenterCore.Package.RUNTIME_UPDATES_ID; + runtime_updates_component.name = _("Runtime Updates"); + runtime_updates_component.summary = _("Updates to app runtimes"); + runtime_updates_component.add_icon (runtime_icon); + + runtime_updates = new AppCenterCore.Package (FlatpakBackend.get_default (), runtime_updates_component); } public async uint get_updates (Cancellable? cancellable = null) { @@ -99,6 +112,9 @@ public class AppCenterCore.UpdateManager : Object { os_updates.component.set_pkgnames ({}); os_updates.change_information.clear_update_info (); + uint runtime_count = 0; + string runtime_desc = ""; + unowned FlatpakBackend fp_client = FlatpakBackend.get_default (); var flatpak_updates = yield fp_client.get_updates (); debug ("Flatpak backend reports %d updates", flatpak_updates.size); @@ -129,7 +145,7 @@ public class AppCenterCore.UpdateManager : Object { warning ("Unable to get flatpak download size: %s", e.message); } } else { - debug ("Added %s to OS updates", flatpak_update); + debug ("Added %s to runtime updates", flatpak_update); string bundle_id; if (!FlatpakBackend.get_package_list_key_parts (flatpak_update, null, null, out bundle_id)) { continue; @@ -144,13 +160,13 @@ public class AppCenterCore.UpdateManager : Object { } if (!AppCenter.App.settings.get_boolean ("automatic-updates")) { - os_count++; + runtime_count++; } - os_desc += Markup.printf_escaped ( + runtime_desc += Markup.printf_escaped ( " • %s\n\t%s\n", @ref.get_name (), - _("Flatpak runtime") + _("Version: %s").printf (@ref.get_branch ()) ); uint64 dl_size = 0; @@ -161,8 +177,8 @@ public class AppCenterCore.UpdateManager : Object { } updates_size += dl_size; - os_updates.change_information.size += dl_size; - os_updates.change_information.updatable_packages.@set (fp_client, flatpak_update); + runtime_updates.change_information.size += dl_size; + runtime_updates.change_information.updatable_packages.@set (fp_client, flatpak_update); } } @@ -178,11 +194,27 @@ public class AppCenterCore.UpdateManager : Object { os_updates.description = "%s\n%s\n".printf (GLib.Markup.printf_escaped (_("%s:"), latest_version), os_desc); } + if (runtime_count == 0) { + debug ("No runtime updates found"); + var latest_version = _("No runtimes with updates"); + runtime_updates.latest_version = latest_version; + runtime_updates.description = GLib.Markup.printf_escaped ("%s\n", latest_version); + } else { + debug ("%u runtime updates found", runtime_count); + var latest_version = ngettext ("%u runtimes with updates", "%u runtimes with updates", runtime_count).printf (runtime_count); + runtime_updates.latest_version = latest_version; + runtime_updates.description = "%s\n%s\n".printf (GLib.Markup.printf_escaped (_("%s:"), latest_version), runtime_desc); + } + debug ("%u app updates found", count); if (os_count > 0) { count += 1; } + if (runtime_count > 0) { + count += 1; + } + pk_updates.get_details_array ().foreach ((pk_detail) => { var pk_package = new Pk.Package (); try { @@ -207,6 +239,7 @@ public class AppCenterCore.UpdateManager : Object { }); os_updates.update_state (); + runtime_updates.update_state (); return count; } diff --git a/src/Views/AppInfoView.vala b/src/Views/AppInfoView.vala index 2402fd38f..abac8c714 100644 --- a/src/Views/AppInfoView.vala +++ b/src/Views/AppInfoView.vala @@ -170,7 +170,7 @@ namespace AppCenter.Views { content_warning_clamp.add (oars_flowbox_revealer); #if CURATED - if (!package.is_native && !package.is_os_updates) { + if (!package.is_native && !package.is_os_updates && !package.is_runtime_updates) { var uncurated = new ContentType ( _("Non-Curated"), _("Not reviewed by elementary for security, privacy, or system integration"), @@ -489,7 +489,7 @@ namespace AppCenter.Views { } else { app_icon.gicon = package.get_icon (app_icon.pixel_size, scale_factor); - if (package.is_os_updates) { + if (package.is_os_updates || package.is_runtime_updates) { badge_image.icon_name = "system-software-update"; app_icon_overlay.add_overlay (badge_image); } @@ -816,10 +816,10 @@ namespace AppCenter.Views { uninstall_button_revealer.reveal_child = false; break; case AppCenterCore.Package.State.INSTALLED: - uninstall_button_revealer.reveal_child = !package.is_os_updates && !package.is_compulsory; + uninstall_button_revealer.reveal_child = !package.is_os_updates && !package.is_runtime_updates && !package.is_compulsory; break; case AppCenterCore.Package.State.UPDATE_AVAILABLE: - uninstall_button_revealer.reveal_child = !package.is_os_updates && !package.is_compulsory; + uninstall_button_revealer.reveal_child = !package.is_os_updates && !package.is_runtime_updates && !package.is_compulsory; break; default: break; @@ -922,7 +922,7 @@ namespace AppCenter.Views { new Thread ("content-loading", () => { var description = package.get_description (); Idle.add (() => { - if (package.is_os_updates) { + if (package.is_os_updates || package.is_runtime_updates) { author_label.label = package.get_version (); } else { author_label.label = package.author_title; diff --git a/src/Views/AppListUpdateView.vala b/src/Views/AppListUpdateView.vala index db3c889e9..98c06d51f 100644 --- a/src/Views/AppListUpdateView.vala +++ b/src/Views/AppListUpdateView.vala @@ -176,6 +176,8 @@ namespace AppCenter.Views { var os_updates = AppCenterCore.UpdateManager.get_default ().os_updates; add_package (os_updates); + var runtime_updates = AppCenterCore.UpdateManager.get_default ().runtime_updates; + add_package (runtime_updates); add_packages (installed_apps); } @@ -216,12 +218,14 @@ namespace AppCenter.Views { bool a_has_updates = false; bool a_is_driver = false; bool a_is_os = false; + bool a_is_runtime = false; bool a_is_updating = false; string a_package_name = ""; if (row1_package != null) { a_has_updates = row1_package.update_available; a_is_driver = row1_package.kind == AppStream.ComponentKind.DRIVER; a_is_os = row1_package.is_os_updates; + a_is_runtime = row1_package.is_runtime_updates; a_is_updating = row1_package.is_updating; a_package_name = row1_package.get_name (); } @@ -229,12 +233,14 @@ namespace AppCenter.Views { bool b_has_updates = false; bool b_is_driver = false; bool b_is_os = false; + bool b_is_runtime = false; bool b_is_updating = false; string b_package_name = ""; if (row2_package != null) { b_has_updates = row2_package.update_available; b_is_driver = row2_package.kind == AppStream.ComponentKind.DRIVER; b_is_os = row2_package.is_os_updates; + b_is_runtime = row2_package.is_runtime_updates; b_is_updating = row2_package.is_updating; b_package_name = row2_package.get_name (); } @@ -272,6 +278,11 @@ namespace AppCenter.Views { return a_is_os ? -1 : 1; } + // Ensures runtime updates are sorted to the top amongst up-to-date packages but below OS updates + if (a_is_runtime || b_is_runtime) { + return a_is_runtime ? -1 : 1; + } + return a_package_name.collate (b_package_name); /* Else sort in name order */ } diff --git a/src/Widgets/AppContainers/AbstractAppContainer.vala b/src/Widgets/AppContainers/AbstractAppContainer.vala index c4f38041a..83059d478 100644 --- a/src/Widgets/AppContainers/AbstractAppContainer.vala +++ b/src/Widgets/AppContainers/AbstractAppContainer.vala @@ -162,7 +162,7 @@ namespace AppCenter { } protected void update_action () { - if (package == null || package.component == null || !package.is_native || package.is_os_updates) { + if (package == null || package.component == null || !package.is_native || package.is_os_updates || package.is_runtime_updates) { action_button.can_purchase = false; } else { var can_purchase = package.get_payments_key () != null; @@ -190,7 +190,7 @@ namespace AppCenter { action_button.amount = 0; } - action_button_revealer.reveal_child = !package.is_os_updates; + action_button_revealer.reveal_child = !(package.is_os_updates || package.is_runtime_updates); open_button_revealer.reveal_child = false; break; diff --git a/src/Widgets/AppContainers/AbstractPackageRowGrid.vala b/src/Widgets/AppContainers/AbstractPackageRowGrid.vala index 02702e7f0..fc8eb633e 100644 --- a/src/Widgets/AppContainers/AbstractPackageRowGrid.vala +++ b/src/Widgets/AppContainers/AbstractPackageRowGrid.vala @@ -53,7 +53,7 @@ public abstract class AppCenter.Widgets.AbstractPackageRowGrid : AbstractAppCont } else { app_icon.gicon = package.get_icon (app_icon.pixel_size, scale_factor); - if (package.is_os_updates) { + if (package.is_os_updates || package.is_runtime_updates) { badge_image.icon_name = "system-software-update"; app_icon_overlay.add_overlay (badge_image); }