diff --git a/po/POTFILES b/po/POTFILES index 76a6c39f0..c34d18dcf 100644 --- a/po/POTFILES +++ b/po/POTFILES @@ -4,7 +4,6 @@ src/MainWindow.vala src/SuspendControl.vala src/Utils.vala src/Core/ChangeInformation.vala -src/Core/Client.vala src/Core/FlatpakBackend.vala src/Core/Job.vala src/Core/Package.vala diff --git a/src/Application.vala b/src/Application.vala index 67cc4787c..d49e8c6cf 100644 --- a/src/Application.vala +++ b/src/Application.vala @@ -130,16 +130,16 @@ public class AppCenter.App : Gtk.Application { activate (); }); - var client = AppCenterCore.Client.get_default (); - client.operation_finished.connect (on_operation_finished); - client.cache_update_failed.connect (on_cache_update_failed); - var flatpak_backend = AppCenterCore.FlatpakBackend.get_default (); + flatpak_backend.operation_finished.connect (on_operation_finished); + + var update_manager = AppCenterCore.UpdateManager.get_default (); + update_manager.cache_update_failed.connect (on_cache_update_failed); refresh_action = new SimpleAction ("refresh", null); refresh_action.set_enabled (!Utils.is_running_in_guest_session ()); refresh_action.activate.connect (() => { - client.update_cache.begin (true); + update_manager.update_cache.begin (true); }); repair_action = new SimpleAction ("repair", null); @@ -181,7 +181,7 @@ public class AppCenter.App : Gtk.Application { } public override void activate () { - var client = AppCenterCore.Client.get_default (); + unowned var update_manager = AppCenterCore.UpdateManager.get_default (); if (first_activation) { first_activation = false; @@ -196,14 +196,14 @@ public class AppCenter.App : Gtk.Application { }); // Don't force a cache refresh for the silent daemon, it'll run if it was >24 hours since the last one - client.update_cache.begin (false); + update_manager.update_cache.begin (false); silent = false; return; } if (active_window == null) { // Force a Flatpak cache refresh when the window is created, so we get new apps - client.update_cache.begin (true); + update_manager.update_cache.begin (true); var main_window = new MainWindow (this); add_window (main_window); @@ -295,7 +295,7 @@ public class AppCenter.App : Gtk.Application { private uint cache_update_timeout_id = 0; private void schedule_cache_update (bool cancel = false) { - var client = AppCenterCore.Client.get_default (); + unowned var update_manager = AppCenterCore.UpdateManager.get_default (); if (cache_update_timeout_id > 0) { Source.remove (cache_update_timeout_id); @@ -303,11 +303,11 @@ public class AppCenter.App : Gtk.Application { } if (cancel) { - client.cancel_updates (true); // Also stops timeouts. + update_manager.cancel_updates (true); // Also stops timeouts. return; } else { cache_update_timeout_id = Timeout.add_seconds (SECONDS_AFTER_NETWORK_UP, () => { - client.update_cache.begin (); + update_manager.update_cache.begin (); cache_update_timeout_id = 0; return false; }); diff --git a/src/Core/Client.vala b/src/Core/Client.vala deleted file mode 100644 index f5619d289..000000000 --- a/src/Core/Client.vala +++ /dev/null @@ -1,153 +0,0 @@ -/* Copyright 2015 Marvin Beckers -* -* This program is free software: you can redistribute it -* and/or modify it under the terms of the GNU General Public License as -* published by the Free Software Foundation, either version 3 of the -* License, or (at your option) any later version. -* -* This program is distributed in the hope that it will be -* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -* Public License for more details. -* -* You should have received a copy of the GNU General Public License along -* with this program. If not, see http://www.gnu.org/licenses/. -*/ - -public class AppCenterCore.Client : Object { - public signal void operation_finished (Package package, Package.State operation, Error? error); - public signal void cache_update_failed (Error error); - /** - * This signal is likely to be fired from a non-main thread. Ensure any UI - * logic driven from this runs on the GTK thread - */ - public signal void installed_apps_changed (); - - public AppCenterCore.ScreenshotCache? screenshot_cache { get; private set; default = new ScreenshotCache (); } - - private GLib.Cancellable cancellable; - - private GLib.DateTime last_cache_update = null; - - private uint update_cache_timeout_id = 0; - private bool refresh_in_progress = false; - - private const int SECONDS_BETWEEN_REFRESHES = 60 * 60 * 24; - - private Client () { } - - construct { - cancellable = new GLib.Cancellable (); - - last_cache_update = new DateTime.from_unix_utc (AppCenter.App.settings.get_int64 ("last-refresh-time")); - } - - public async void refresh_updates () { - yield UpdateManager.get_default ().get_updates (null); - installed_apps_changed (); - } - - public void cancel_updates (bool cancel_timeout) { - cancellable.cancel (); - - if (update_cache_timeout_id > 0 && cancel_timeout) { - Source.remove (update_cache_timeout_id); - update_cache_timeout_id = 0; - } - } - - public async void update_cache (bool force = false) { - cancellable.reset (); - - if (Utils.is_running_in_demo_mode () || Utils.is_running_in_guest_session ()) { - return; - } - - debug ("update cache called %s", force.to_string ()); - bool success = false; - - /* Make sure only one update cache can run at a time */ - if (refresh_in_progress) { - debug ("Update cache already in progress - returning"); - return; - } - - if (update_cache_timeout_id > 0) { - if (force) { - debug ("Forced update_cache called when there is an on-going timeout - cancelling timeout"); - Source.remove (update_cache_timeout_id); - update_cache_timeout_id = 0; - } else { - debug ("Refresh timeout running and not forced - returning"); - return; - } - } - - var nm = NetworkMonitor.get_default (); - - /* One cache update a day, keeps the doctor away! */ - var seconds_since_last_refresh = new DateTime.now_utc ().difference (last_cache_update) / GLib.TimeSpan.SECOND; - bool last_cache_update_is_old = seconds_since_last_refresh >= SECONDS_BETWEEN_REFRESHES; - if (force || last_cache_update_is_old) { - if (nm.get_network_available ()) { - debug ("New refresh task"); - - refresh_in_progress = true; - try { - success = yield FlatpakBackend.get_default ().refresh_cache (cancellable); - - if (success) { - last_cache_update = new DateTime.now_utc (); - AppCenter.App.settings.set_int64 ("last-refresh-time", last_cache_update.to_unix ()); - } - - seconds_since_last_refresh = 0; - } catch (Error e) { - if (!(e is GLib.IOError.CANCELLED)) { - critical ("Update_cache: Refesh cache async failed - %s", e.message); - cache_update_failed (e); - } - } finally { - refresh_in_progress = false; - } - } - } else { - debug ("Too soon to refresh and not forced"); - } - - - var next_refresh = SECONDS_BETWEEN_REFRESHES - (uint)seconds_since_last_refresh; - debug ("Setting a timeout for a refresh in %f minutes", next_refresh / 60.0f); - update_cache_timeout_id = GLib.Timeout.add_seconds (next_refresh, () => { - update_cache_timeout_id = 0; - update_cache.begin (true); - - return GLib.Source.REMOVE; - }); - - if (nm.get_network_available ()) { - if ((force || last_cache_update_is_old) && AppCenter.App.settings.get_boolean ("automatic-updates")) { - yield refresh_updates (); - debug ("Update Flatpaks"); - var installed_apps = yield FlatpakBackend.get_default ().get_installed_applications (cancellable); - foreach (var app in installed_apps) { - if (app.update_available && !app.should_pay) { - debug ("Update: %s", app.get_name ()); - try { - yield app.update (false); - } catch (Error e) { - warning ("Updating %s failed: %s", app.get_name (), e.message); - } - } - } - } - - refresh_updates.begin (); - } - } - - private static GLib.Once instance; - public static unowned Client get_default () { - return instance.once (() => { return new Client (); }); - } -} diff --git a/src/Core/FlatpakBackend.vala b/src/Core/FlatpakBackend.vala index 34f9e38ee..222a0b9bc 100644 --- a/src/Core/FlatpakBackend.vala +++ b/src/Core/FlatpakBackend.vala @@ -49,6 +49,7 @@ public class AppCenterCore.FlatpakPackage : Package { } public class AppCenterCore.FlatpakBackend : Object { + public signal void operation_finished (Package package, Package.State operation, Error? error); public signal void cache_flush_needed (); // Based on https://github.com/flatpak/flatpak/blob/417e3949c0ecc314e69311e3ee8248320d3e3d52/common/flatpak-run-private.h @@ -251,7 +252,7 @@ public class AppCenterCore.FlatpakBackend : Object { warning ("Unable to refresh cache after external change: %s", e.message); } - yield Client.get_default ().refresh_updates (); + yield UpdateManager.get_default ().get_updates (); } static construct { diff --git a/src/Core/Package.vala b/src/Core/Package.vala index e3fc33674..afe8318ea 100644 --- a/src/Core/Package.vala +++ b/src/Core/Package.vala @@ -459,8 +459,7 @@ public class AppCenterCore.Package : Object { var success = yield perform_operation (State.UPDATING, State.INSTALLED, State.UPDATE_AVAILABLE); if (success && refresh_updates_after) { - unowned Client client = Client.get_default (); - yield client.refresh_updates (); + yield UpdateManager.get_default ().get_updates (); } return success; @@ -471,17 +470,17 @@ public class AppCenterCore.Package : Object { return false; } + unowned var flatpak_backend = AppCenterCore.FlatpakBackend.get_default (); + try { bool success = yield perform_operation (State.INSTALLING, State.INSTALLED, State.NOT_INSTALLED); if (success) { - var client = AppCenterCore.Client.get_default (); - client.operation_finished (this, State.INSTALLING, null); + flatpak_backend.operation_finished (this, State.INSTALLING, null); } return success; } catch (Error e) { - var client = AppCenterCore.Client.get_default (); - client.operation_finished (this, State.INSTALLING, e); + flatpak_backend.operation_finished (this, State.INSTALLING, e); return false; } } @@ -539,8 +538,8 @@ public class AppCenterCore.Package : Object { } private async bool perform_package_operation () throws GLib.Error { - var backend = AppCenterCore.FlatpakBackend.get_default (); - var client = AppCenterCore.Client.get_default (); + unowned var backend = AppCenterCore.FlatpakBackend.get_default (); + unowned var update_manager = AppCenterCore.UpdateManager.get_default (); switch (state) { case State.UPDATING: @@ -560,7 +559,7 @@ public class AppCenterCore.Package : Object { var success = yield backend.remove_package (this, change_information, action_cancellable); _installed = !success; update_state (); - yield client.refresh_updates (); + yield update_manager.get_updates (); return success; default: return false; diff --git a/src/Core/UpdateManager.vala b/src/Core/UpdateManager.vala index 187aae5c0..69fb5850b 100644 --- a/src/Core/UpdateManager.vala +++ b/src/Core/UpdateManager.vala @@ -18,11 +18,25 @@ */ public class AppCenterCore.UpdateManager : Object { + /** + * This signal is likely to be fired from a non-main thread. Ensure any UI + * logic driven from this runs on the GTK thread + */ + public signal void installed_apps_changed (); + public signal void cache_update_failed (Error error); + public Package runtime_updates { public get; private set; } public int unpaid_apps_number { get; private set; default = 0; } public uint updates_number { get; private set; default = 0U; } public uint64 updates_size { get; private set; default = 0ULL; } + private const int SECONDS_BETWEEN_REFRESHES = 60 * 60 * 24; + + private GLib.Cancellable cancellable; + private GLib.DateTime last_cache_update = null; + private uint update_cache_timeout_id = 0; + private bool refresh_in_progress = false; + construct { var runtime_icon = new AppStream.Icon (); runtime_icon.set_name ("application-vnd.flatpak"); @@ -35,6 +49,10 @@ public class AppCenterCore.UpdateManager : Object { runtime_updates_component.add_icon (runtime_icon); runtime_updates = new AppCenterCore.Package (runtime_updates_component); + + cancellable = new GLib.Cancellable (); + + last_cache_update = new DateTime.from_unix_utc (AppCenter.App.settings.get_int64 ("last-refresh-time")); } public async uint get_updates (Cancellable? cancellable = null) { @@ -160,9 +178,111 @@ public class AppCenterCore.UpdateManager : Object { } runtime_updates.update_state (); + + installed_apps_changed (); + return updates_number; } + public void cancel_updates (bool cancel_timeout) { + cancellable.cancel (); + + if (update_cache_timeout_id > 0 && cancel_timeout) { + Source.remove (update_cache_timeout_id); + update_cache_timeout_id = 0; + } + } + + public async void update_cache (bool force = false) { + cancellable.reset (); + + if (Utils.is_running_in_demo_mode () || Utils.is_running_in_guest_session ()) { + return; + } + + debug ("update cache called %s", force.to_string ()); + bool success = false; + + /* Make sure only one update cache can run at a time */ + if (refresh_in_progress) { + debug ("Update cache already in progress - returning"); + return; + } + + if (update_cache_timeout_id > 0) { + if (force) { + debug ("Forced update_cache called when there is an on-going timeout - cancelling timeout"); + Source.remove (update_cache_timeout_id); + update_cache_timeout_id = 0; + } else { + debug ("Refresh timeout running and not forced - returning"); + return; + } + } + + var nm = NetworkMonitor.get_default (); + + /* One cache update a day, keeps the doctor away! */ + var seconds_since_last_refresh = new DateTime.now_utc ().difference (last_cache_update) / GLib.TimeSpan.SECOND; + bool last_cache_update_is_old = seconds_since_last_refresh >= SECONDS_BETWEEN_REFRESHES; + if (force || last_cache_update_is_old) { + if (nm.get_network_available ()) { + debug ("New refresh task"); + + refresh_in_progress = true; + try { + success = yield FlatpakBackend.get_default ().refresh_cache (cancellable); + + if (success) { + last_cache_update = new DateTime.now_utc (); + AppCenter.App.settings.set_int64 ("last-refresh-time", last_cache_update.to_unix ()); + } + + seconds_since_last_refresh = 0; + } catch (Error e) { + if (!(e is GLib.IOError.CANCELLED)) { + critical ("Update_cache: Refesh cache async failed - %s", e.message); + cache_update_failed (e); + } + } finally { + refresh_in_progress = false; + } + } + } else { + debug ("Too soon to refresh and not forced"); + } + + + var next_refresh = SECONDS_BETWEEN_REFRESHES - (uint)seconds_since_last_refresh; + debug ("Setting a timeout for a refresh in %f minutes", next_refresh / 60.0f); + update_cache_timeout_id = GLib.Timeout.add_seconds (next_refresh, () => { + update_cache_timeout_id = 0; + update_cache.begin (true); + + return GLib.Source.REMOVE; + }); + + if (nm.get_network_available ()) { + if ((force || last_cache_update_is_old) && AppCenter.App.settings.get_boolean ("automatic-updates")) { + yield get_updates (); + debug ("Update Flatpaks"); + var installed_apps = yield FlatpakBackend.get_default ().get_installed_applications (cancellable); + foreach (var app in installed_apps) { + if (app.update_available && !app.should_pay) { + debug ("Update: %s", app.get_name ()); + try { + yield app.update (false); + } catch (Error e) { + warning ("Updating %s failed: %s", app.get_name (), e.message); + } + } + } + } + + get_updates.begin (); + } + } + private static GLib.Once instance; public static unowned UpdateManager get_default () { return instance.once (() => { return new UpdateManager (); }); diff --git a/src/Dialogs/UpdateFailDialog.vala b/src/Dialogs/UpdateFailDialog.vala index a14cc87cc..6739560df 100644 --- a/src/Dialogs/UpdateFailDialog.vala +++ b/src/Dialogs/UpdateFailDialog.vala @@ -37,7 +37,7 @@ public class UpdateFailDialog : Granite.MessageDialog { response.connect ((response_id) => { if (response_id == TRY_AGAIN_RESPONSE_ID) { - AppCenterCore.Client.get_default ().update_cache.begin (true); + AppCenterCore.UpdateManager.get_default ().update_cache.begin (true); } destroy (); }); diff --git a/src/MainWindow.vala b/src/MainWindow.vala index da517b011..d6ce84642 100644 --- a/src/MainWindow.vala +++ b/src/MainWindow.vala @@ -254,16 +254,15 @@ public class AppCenter.MainWindow : Gtk.ApplicationWindow { SettingsBindFlags.DEFAULT ); - var client = AppCenterCore.Client.get_default (); + unowned var update_manager = AppCenterCore.UpdateManager.get_default (); automatic_updates_button.notify["active"].connect (() => { if (automatic_updates_button.active) { - client.update_cache.begin (true); + update_manager.update_cache.begin (true); } else { - client.cancel_updates (true); + update_manager.cancel_updates (true); } }); - unowned var update_manager = AppCenterCore.UpdateManager.get_default (); update_manager.notify["updates-number"].connect (() => { show_update_badge (update_manager.updates_number); }); @@ -320,7 +319,7 @@ public class AppCenter.MainWindow : Gtk.ApplicationWindow { } }); - AppCenterCore.Client.get_default ().cancel_updates (false); //Timeouts keep running + AppCenterCore.UpdateManager.get_default ().cancel_updates (false); //Timeouts keep running return true; } diff --git a/src/Views/AppInfoView.vala b/src/Views/AppInfoView.vala index 045c8b886..02f7fc877 100644 --- a/src/Views/AppInfoView.vala +++ b/src/Views/AppInfoView.vala @@ -52,6 +52,8 @@ public class AppCenter.Views.AppInfoView : Adw.NavigationPage { public bool to_recycle { public get; private set; default = false; } + private static AppCenterCore.ScreenshotCache? screenshot_cache; + public AppInfoView (AppCenterCore.Package package) { Object (package: package); } @@ -60,6 +62,10 @@ public class AppCenter.Views.AppInfoView : Adw.NavigationPage { set_css_name ("appinfoview"); } + static construct { + screenshot_cache = new AppCenterCore.ScreenshotCache (); + } + construct { AppCenterCore.FlatpakBackend.get_default ().cache_flush_needed.connect (() => { to_recycle = true; @@ -926,8 +932,6 @@ public class AppCenter.Views.AppInfoView : Adw.NavigationPage { } private void load_more_content () { - var cache = AppCenterCore.Client.get_default ().screenshot_cache; - uint count = 0; foreach (var origin_package in package.origin_packages) { origin_liststore.append (origin_package); @@ -1033,8 +1037,8 @@ public class AppCenter.Views.AppInfoView : Adw.NavigationPage { string? file = null; int index = i; - cache.fetch.begin (url, (obj, res) => { - results[index] = cache.fetch.end (res, out file); + screenshot_cache.fetch.begin (url, (obj, res) => { + results[index] = screenshot_cache.fetch.end (res, out file); screenshot_files[index] = file; completed++; }); diff --git a/src/Views/AppListUpdateView.vala b/src/Views/AppListUpdateView.vala index 456e801d6..086161201 100644 --- a/src/Views/AppListUpdateView.vala +++ b/src/Views/AppListUpdateView.vala @@ -144,8 +144,7 @@ namespace AppCenter.Views { stack.visible_child = main_box; }); - unowned var client = AppCenterCore.Client.get_default (); - client.installed_apps_changed.connect (() => { + AppCenterCore.UpdateManager.get_default ().installed_apps_changed.connect (() => { Idle.add (() => { get_apps.begin (); return GLib.Source.REMOVE; @@ -342,8 +341,7 @@ namespace AppCenter.Views { } } - unowned AppCenterCore.Client client = AppCenterCore.Client.get_default (); - yield client.refresh_updates (); + yield AppCenterCore.UpdateManager.get_default ().get_updates (); updating_all_apps = false; } diff --git a/src/Views/CategoryView.vala b/src/Views/CategoryView.vala index eb516d7b8..d17a8ebf9 100644 --- a/src/Views/CategoryView.vala +++ b/src/Views/CategoryView.vala @@ -77,7 +77,7 @@ public class AppCenter.CategoryView : Adw.NavigationPage { show_app (package); }); - AppCenterCore.Client.get_default ().installed_apps_changed.connect (() => { + AppCenterCore.UpdateManager.get_default ().installed_apps_changed.connect (() => { populate (); }); } diff --git a/src/Views/Homepage.vala b/src/Views/Homepage.vala index 0b411a008..ec6346f30 100644 --- a/src/Views/Homepage.vala +++ b/src/Views/Homepage.vala @@ -387,7 +387,7 @@ public class AppCenter.Homepage : Adw.NavigationPage { child = content_area; - AppCenterCore.Client.get_default ().installed_apps_changed.connect (() => { + AppCenterCore.UpdateManager.get_default ().installed_apps_changed.connect (() => { Idle.add (() => { // Clear the cached categories when the AppStream pool is updated if (visible) { diff --git a/src/meson.build b/src/meson.build index 150ba5a0a..987eed55d 100644 --- a/src/meson.build +++ b/src/meson.build @@ -6,7 +6,6 @@ appcenter_files = files( 'Utils.vala', 'Core/CardUtils.vala', 'Core/ChangeInformation.vala', - 'Core/Client.vala', 'Core/FlatpakBackend.vala', 'Core/HttpClient.vala', 'Core/Job.vala',