From 8fc6004b87e95b12af8bd9293988131c4cf06b60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Tue, 26 Mar 2024 14:20:48 -0700 Subject: [PATCH 01/14] AppSettingsView: show switch for background permission --- src/Permissions/Widgets/AppSettingsView.vala | 87 ++++++++++++++++---- src/meson.build | 1 + 2 files changed, 70 insertions(+), 18 deletions(-) diff --git a/src/Permissions/Widgets/AppSettingsView.vala b/src/Permissions/Widgets/AppSettingsView.vala index 0c4692ab..b66a178e 100644 --- a/src/Permissions/Widgets/AppSettingsView.vala +++ b/src/Permissions/Widgets/AppSettingsView.vala @@ -22,12 +22,54 @@ public class Permissions.Widgets.AppSettingsView : Switchboard.SettingsPage { public Backend.App? selected_app { get; set; default = null; } - private Gtk.ListBox list_box; + private const string BACKGROUND_TABLE = "background"; + private const string BACKGROUND_ID = "background"; + + private Gtk.ListBox sandbox_box; private Gtk.Button reset_button; + private Gtk.Switch background_switch; + + private static PermissionStore permission_store; + + static construct { + Bus.get_proxy.begin (BusType.SESSION, "org.freedesktop.impl.portal.PermissionStore", "/org/freedesktop/impl/portal/PermissionStore", 0, null, (obj, res) => { + try { + permission_store = Bus.get_proxy.end (res); + } catch (Error e) { + critical (e.message); + } + }); + } construct { notify["selected-app"].connect (update_view); + var background_image = new Gtk.Image.from_icon_name ("image-missing") { + icon_size = LARGE + }; + + var background_label = new Gtk.Label (_("Run in background")) { + hexpand = true, + xalign = 0 + }; + + background_switch = new Gtk.Switch () { + valign = CENTER + }; + + var background_box = new Gtk.Box (HORIZONTAL, 6); + background_box.append (background_image); + background_box.append (background_label); + background_box.append (background_switch); + + var permission_box = new Gtk.ListBox () { + hexpand = true, + selection_mode = NONE + }; + permission_box.add_css_class ("boxed-list"); + permission_box.add_css_class (Granite.STYLE_CLASS_RICH_LIST); + permission_box.append (background_box); + var homefolder_widget = new PermissionSettingsWidget ( Plug.permission_names["filesystems=home"], _("Access your entire Home folder, including any hidden folders."), @@ -84,23 +126,27 @@ public class Permissions.Widgets.AppSettingsView : Switchboard.SettingsPage { new Backend.PermissionSettings ("devices=dri") ); - list_box = new Gtk.ListBox () { + sandbox_box = new Gtk.ListBox () { hexpand = true, vexpand = true, selection_mode = NONE }; - list_box.add_css_class ("boxed-list"); - list_box.add_css_class (Granite.STYLE_CLASS_RICH_LIST); - list_box.append (homefolder_widget); - list_box.append (sysfolders_widget); - list_box.append (devices_widget); - list_box.append (network_widget); - list_box.append (bluetooth_widget); - list_box.append (printing_widget); - list_box.append (ssh_widget); - list_box.append (gpu_widget); - - child = list_box; + sandbox_box.add_css_class ("boxed-list"); + sandbox_box.add_css_class (Granite.STYLE_CLASS_RICH_LIST); + sandbox_box.append (homefolder_widget); + sandbox_box.append (sysfolders_widget); + sandbox_box.append (devices_widget); + sandbox_box.append (network_widget); + sandbox_box.append (bluetooth_widget); + sandbox_box.append (printing_widget); + sandbox_box.append (ssh_widget); + sandbox_box.append (gpu_widget); + + var box = new Gtk.Box (VERTICAL, 24); + box.append (permission_box); + box.append (sandbox_box); + + child = box; reset_button = add_button (_("Reset to Defaults")); @@ -124,7 +170,7 @@ public class Permissions.Widgets.AppSettingsView : Switchboard.SettingsPage { } private void initialize_settings_view () { - var children = list_box.observe_children (); + var children = sandbox_box.observe_children (); for (var iter = 0; iter < children.get_n_items (); iter++) { if (children.get_item (iter) is PermissionSettingsWidget) { var widget = (PermissionSettingsWidget) children.get_item (iter); @@ -140,14 +186,14 @@ public class Permissions.Widgets.AppSettingsView : Switchboard.SettingsPage { initialize_settings_view (); if (selected_app == null) { - list_box.sensitive = false; + sandbox_box.sensitive = false; reset_button.sensitive = false; return; } var should_enable_reset = false; selected_app.settings.foreach ((settings) => { - var children = list_box.observe_children (); + var children = sandbox_box.observe_children (); for (var iter = 0; iter < children.get_n_items (); iter++) { if (children.get_item (iter) is PermissionSettingsWidget) { var widget = (PermissionSettingsWidget) children.get_item (iter); @@ -164,10 +210,15 @@ public class Permissions.Widgets.AppSettingsView : Switchboard.SettingsPage { } } - list_box.sensitive = true; + sandbox_box.sensitive = true; reset_button.sensitive = should_enable_reset; }); + if (permission_store != null) { + var string_array = permission_store.get_permission (BACKGROUND_TABLE, BACKGROUND_ID, selected_app.id); + background_switch.active = string_array[0] == "yes"; + } + update_property (Gtk.AccessibleProperty.LABEL, _("%s permissions").printf (selected_app.name), -1); title = selected_app.name; icon = selected_app.icon; diff --git a/src/meson.build b/src/meson.build index 2a5f6e5e..729ac1b5 100644 --- a/src/meson.build +++ b/src/meson.build @@ -16,6 +16,7 @@ plug_files = files( 'Permissions/Backend/AppManager.vala', 'Permissions/Backend/FlatpakManager.vala', 'Permissions/Backend/PermissionSettings.vala', + 'Permissions/Backend/PermissionStore.vala', 'Permissions/Widgets/AppSettingsView.vala', 'Permissions/Widgets/PermissionSettingsWidget.vala', 'Permissions/Widgets/SidebarRow.vala', From b2fe8eb383200993a37629d2372041a33bf66047 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Tue, 26 Mar 2024 14:23:14 -0700 Subject: [PATCH 02/14] Add missing dbus file --- src/Permissions/Backend/PermissionStore.vala | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 src/Permissions/Backend/PermissionStore.vala diff --git a/src/Permissions/Backend/PermissionStore.vala b/src/Permissions/Backend/PermissionStore.vala new file mode 100644 index 00000000..d2fa6a90 --- /dev/null +++ b/src/Permissions/Backend/PermissionStore.vala @@ -0,0 +1,18 @@ +/* + * SPDX-License-Identifier: LGPL-3.0-or-later + * SPDX-FileCopyrightText: 2023 elementary, Inc. (https://elementary.io) + */ + +[DBus (name = "org.freedesktop.impl.portal.PermissionStore", timeout = 120000)] +public interface Permissions.PermissionStore : GLib.Object { + public signal void changed (string table, string id, bool deleted, GLib.Variant data, [DBus (signature = "a{sas}")] GLib.Variant permissions); + public abstract uint version { get; } + public abstract void lookup (string table, string id, [DBus (signature = "a{sas}")] out GLib.Variant permissions, out GLib.Variant data) throws DBusError, IOError; + public abstract void set (string table, bool create, string id, [DBus (signature = "a{sas}")] GLib.Variant app_permissions, GLib.Variant data) throws DBusError, IOError; + public abstract void delete (string table, string id) throws DBusError, IOError; + public abstract void set_value (string table, bool create, string id, GLib.Variant data) throws DBusError, IOError; + public abstract void set_permission (string table, bool create, string id, string app, string[] permissions) throws DBusError, IOError; + public abstract void delete_permission (string table, string id, string app) throws DBusError, IOError; + public abstract string[] get_permission (string table, string id, string app) throws DBusError, IOError; + public abstract string[] list (string table) throws DBusError, IOError; +} From fff9557ddc52b7b221c41e78bc742d7d3bea840e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Tue, 26 Mar 2024 17:21:58 -0700 Subject: [PATCH 03/14] set --- src/Permissions/Widgets/AppSettingsView.vala | 25 ++++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/Permissions/Widgets/AppSettingsView.vala b/src/Permissions/Widgets/AppSettingsView.vala index b66a178e..7c1ab11d 100644 --- a/src/Permissions/Widgets/AppSettingsView.vala +++ b/src/Permissions/Widgets/AppSettingsView.vala @@ -1,5 +1,5 @@ /* -* Copyright 2020 elementary, Inc. (https://elementary.io) +* Copyright 2020-2024 elementary, Inc. (https://elementary.io) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public @@ -32,7 +32,12 @@ public class Permissions.Widgets.AppSettingsView : Switchboard.SettingsPage { private static PermissionStore permission_store; static construct { - Bus.get_proxy.begin (BusType.SESSION, "org.freedesktop.impl.portal.PermissionStore", "/org/freedesktop/impl/portal/PermissionStore", 0, null, (obj, res) => { + Bus.get_proxy.begin ( + BusType.SESSION, + "org.freedesktop.impl.portal.PermissionStore", + "/org/freedesktop/impl/portal/PermissionStore", + 0, null, + (obj, res) => { try { permission_store = Bus.get_proxy.end (res); } catch (Error e) { @@ -161,6 +166,17 @@ public class Permissions.Widgets.AppSettingsView : Switchboard.SettingsPage { ssh_widget.changed_permission_settings.connect (change_permission_settings); gpu_widget.changed_permission_settings.connect (change_permission_settings); + background_switch.notify["active"].connect (() => { + string[] permissions; + if (background_switch.active) { + permissions += "yes"; + } else { + permissions += "no"; + } + + permission_store.set_permission (BACKGROUND_TABLE, true, BACKGROUND_ID, selected_app.id, permissions); + }); + reset_button.clicked.connect (() => { if (selected_app != null) { selected_app.reset_settings_to_standard (); @@ -186,8 +202,7 @@ public class Permissions.Widgets.AppSettingsView : Switchboard.SettingsPage { initialize_settings_view (); if (selected_app == null) { - sandbox_box.sensitive = false; - reset_button.sensitive = false; + sensitive = false; return; } @@ -210,7 +225,7 @@ public class Permissions.Widgets.AppSettingsView : Switchboard.SettingsPage { } } - sandbox_box.sensitive = true; + sensitive = true; reset_button.sensitive = should_enable_reset; }); From 51eb36351cf12618c9c55f89c4c627a80b8cb4a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Tue, 26 Mar 2024 18:24:58 -0700 Subject: [PATCH 04/14] icon --- data/applications.gresource.xml | 6 + data/background.svg | 176 +++++++++++++++++++ data/meson.build | 7 + src/Permissions/Widgets/AppSettingsView.vala | 30 +++- src/meson.build | 1 + 5 files changed, 214 insertions(+), 6 deletions(-) create mode 100644 data/applications.gresource.xml create mode 100644 data/background.svg diff --git a/data/applications.gresource.xml b/data/applications.gresource.xml new file mode 100644 index 00000000..067e48d6 --- /dev/null +++ b/data/applications.gresource.xml @@ -0,0 +1,6 @@ + + + + background.svg + + diff --git a/data/background.svg b/data/background.svg new file mode 100644 index 00000000..3c2b63b9 --- /dev/null +++ b/data/background.svg @@ -0,0 +1,176 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/data/meson.build b/data/meson.build index be9909aa..980b974b 100644 --- a/data/meson.build +++ b/data/meson.build @@ -1,3 +1,10 @@ +gresource = gnome.compile_resources( + 'applications-resources', + 'applications.gresource.xml', + source_dir: meson.current_source_dir() +) + + i18n.merge_file( input: 'applications.metainfo.xml.in', output: 'io.elementary.settings.applications.metainfo.xml', diff --git a/src/Permissions/Widgets/AppSettingsView.vala b/src/Permissions/Widgets/AppSettingsView.vala index 7c1ab11d..16150772 100644 --- a/src/Permissions/Widgets/AppSettingsView.vala +++ b/src/Permissions/Widgets/AppSettingsView.vala @@ -26,10 +26,11 @@ public class Permissions.Widgets.AppSettingsView : Switchboard.SettingsPage { private const string BACKGROUND_ID = "background"; private Gtk.ListBox sandbox_box; + private Gtk.ListBox permission_box; private Gtk.Button reset_button; private Gtk.Switch background_switch; - private static PermissionStore permission_store; + private static PermissionStore? permission_store = null; static construct { Bus.get_proxy.begin ( @@ -49,7 +50,7 @@ public class Permissions.Widgets.AppSettingsView : Switchboard.SettingsPage { construct { notify["selected-app"].connect (update_view); - var background_image = new Gtk.Image.from_icon_name ("image-missing") { + var background_image = new Gtk.Image.from_icon_name ("permissions-background") { icon_size = LARGE }; @@ -67,7 +68,7 @@ public class Permissions.Widgets.AppSettingsView : Switchboard.SettingsPage { background_box.append (background_label); background_box.append (background_switch); - var permission_box = new Gtk.ListBox () { + permission_box = new Gtk.ListBox () { hexpand = true, selection_mode = NONE }; @@ -229,9 +230,16 @@ public class Permissions.Widgets.AppSettingsView : Switchboard.SettingsPage { reset_button.sensitive = should_enable_reset; }); - if (permission_store != null) { - var string_array = permission_store.get_permission (BACKGROUND_TABLE, BACKGROUND_ID, selected_app.id); - background_switch.active = string_array[0] == "yes"; + if (permission_store == null) { + // permission_box.sensitive = false; + + // this.notify["permission-store"].connect (() => { + // critical ("notified"); + // update_permissions (); + // permission_box.sensitive = true; + // }); + } else { + update_permissions (); } update_property (Gtk.AccessibleProperty.LABEL, _("%s permissions").printf (selected_app.name), -1); @@ -239,6 +247,16 @@ public class Permissions.Widgets.AppSettingsView : Switchboard.SettingsPage { icon = selected_app.icon; } + private void update_permissions () { + var background_permission = permission_store.get_permission ( + BACKGROUND_TABLE, BACKGROUND_ID, selected_app.id + ); + + // A lack of explicit permission is considered permission + // to allow pre-emptive opt-out + background_switch.active = background_permission[0] != "no"; + } + private void change_permission_settings (Backend.PermissionSettings settings) { if (selected_app == null) { return; diff --git a/src/meson.build b/src/meson.build index 729ac1b5..5a7cedef 100644 --- a/src/meson.build +++ b/src/meson.build @@ -28,6 +28,7 @@ switchboard_plugsdir = switchboard_dep.get_pkgconfig_variable('plugsdir', define shared_module( meson.project_name(), + gresource, plug_files, conf_file, dependencies: [ From df188dfda11977580d7a03e34df7052924f9c3eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Wed, 27 Mar 2024 11:48:58 -0700 Subject: [PATCH 05/14] Vastly improve dbus handling --- src/Permissions/Backend/PermissionStore.vala | 46 +++++++++++++++++++- src/Permissions/Widgets/AppSettingsView.vala | 42 +++++------------- 2 files changed, 57 insertions(+), 31 deletions(-) diff --git a/src/Permissions/Backend/PermissionStore.vala b/src/Permissions/Backend/PermissionStore.vala index d2fa6a90..8ba5be02 100644 --- a/src/Permissions/Backend/PermissionStore.vala +++ b/src/Permissions/Backend/PermissionStore.vala @@ -4,7 +4,7 @@ */ [DBus (name = "org.freedesktop.impl.portal.PermissionStore", timeout = 120000)] -public interface Permissions.PermissionStore : GLib.Object { +public interface PermissionStoreDBus : GLib.Object { public signal void changed (string table, string id, bool deleted, GLib.Variant data, [DBus (signature = "a{sas}")] GLib.Variant permissions); public abstract uint version { get; } public abstract void lookup (string table, string id, [DBus (signature = "a{sas}")] out GLib.Variant permissions, out GLib.Variant data) throws DBusError, IOError; @@ -16,3 +16,47 @@ public interface Permissions.PermissionStore : GLib.Object { public abstract string[] get_permission (string table, string id, string app) throws DBusError, IOError; public abstract string[] list (string table) throws DBusError, IOError; } + +public class Permissions.PermissionStore : GLib.Object { + private const string DBUS_NAME = "org.freedesktop.impl.portal.PermissionStore"; + private const string DBUS_PATH = "/org/freedesktop/impl/portal/PermissionStore"; + private const uint RECONNECT_TIMEOUT = 5000U; + + private static PermissionStore? instance; + public static unowned PermissionStore get_default () { + if (instance == null) { + instance = new PermissionStore (); + } + + return instance; + } + + public PermissionStoreDBus dbus { get; private set; default = null; } + + construct { + Bus.watch_name ( + BusType.SESSION, DBUS_NAME, AUTO_START, + () => try_connect (), name_vanished_callback + ); + } + + private PermissionStore () { } + + private void try_connect () { + Bus.get_proxy.begin (SESSION, DBUS_NAME, DBUS_PATH, 0, null, (obj, res) => { + try { + dbus = Bus.get_proxy.end (res); + } catch (Error e) { + critical (e.message); + Timeout.add (RECONNECT_TIMEOUT, () => { + try_connect (); + return GLib.Source.REMOVE; + }); + } + }); + } + + private void name_vanished_callback (DBusConnection connection, string name) { + dbus = null; + } +} diff --git a/src/Permissions/Widgets/AppSettingsView.vala b/src/Permissions/Widgets/AppSettingsView.vala index 16150772..42807694 100644 --- a/src/Permissions/Widgets/AppSettingsView.vala +++ b/src/Permissions/Widgets/AppSettingsView.vala @@ -30,23 +30,6 @@ public class Permissions.Widgets.AppSettingsView : Switchboard.SettingsPage { private Gtk.Button reset_button; private Gtk.Switch background_switch; - private static PermissionStore? permission_store = null; - - static construct { - Bus.get_proxy.begin ( - BusType.SESSION, - "org.freedesktop.impl.portal.PermissionStore", - "/org/freedesktop/impl/portal/PermissionStore", - 0, null, - (obj, res) => { - try { - permission_store = Bus.get_proxy.end (res); - } catch (Error e) { - critical (e.message); - } - }); - } - construct { notify["selected-app"].connect (update_view); @@ -175,7 +158,7 @@ public class Permissions.Widgets.AppSettingsView : Switchboard.SettingsPage { permissions += "no"; } - permission_store.set_permission (BACKGROUND_TABLE, true, BACKGROUND_ID, selected_app.id, permissions); + PermissionStore.get_default ().dbus.set_permission (BACKGROUND_TABLE, true, BACKGROUND_ID, selected_app.id, permissions); }); reset_button.clicked.connect (() => { @@ -230,17 +213,8 @@ public class Permissions.Widgets.AppSettingsView : Switchboard.SettingsPage { reset_button.sensitive = should_enable_reset; }); - if (permission_store == null) { - // permission_box.sensitive = false; - - // this.notify["permission-store"].connect (() => { - // critical ("notified"); - // update_permissions (); - // permission_box.sensitive = true; - // }); - } else { - update_permissions (); - } + update_permissions (); + PermissionStore.get_default ().notify["dbus"].connect (update_permissions); update_property (Gtk.AccessibleProperty.LABEL, _("%s permissions").printf (selected_app.name), -1); title = selected_app.name; @@ -248,7 +222,15 @@ public class Permissions.Widgets.AppSettingsView : Switchboard.SettingsPage { } private void update_permissions () { - var background_permission = permission_store.get_permission ( + var permission_store = PermissionStore.get_default (); + if (permission_store.dbus == null) { + permission_box.sensitive = false; + return; + } + + permission_box.sensitive = true; + + var background_permission = permission_store.dbus.get_permission ( BACKGROUND_TABLE, BACKGROUND_ID, selected_app.id ); From a0c441a95bf7b699cb9579f3265ef16c92ba3a7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Wed, 27 Mar 2024 11:59:12 -0700 Subject: [PATCH 06/14] Update when dbus changes --- src/Permissions/Backend/PermissionStore.vala | 10 +++------- src/Permissions/Widgets/AppSettingsView.vala | 4 +++- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/Permissions/Backend/PermissionStore.vala b/src/Permissions/Backend/PermissionStore.vala index 8ba5be02..de3ba7c5 100644 --- a/src/Permissions/Backend/PermissionStore.vala +++ b/src/Permissions/Backend/PermissionStore.vala @@ -6,18 +6,13 @@ [DBus (name = "org.freedesktop.impl.portal.PermissionStore", timeout = 120000)] public interface PermissionStoreDBus : GLib.Object { public signal void changed (string table, string id, bool deleted, GLib.Variant data, [DBus (signature = "a{sas}")] GLib.Variant permissions); - public abstract uint version { get; } - public abstract void lookup (string table, string id, [DBus (signature = "a{sas}")] out GLib.Variant permissions, out GLib.Variant data) throws DBusError, IOError; - public abstract void set (string table, bool create, string id, [DBus (signature = "a{sas}")] GLib.Variant app_permissions, GLib.Variant data) throws DBusError, IOError; - public abstract void delete (string table, string id) throws DBusError, IOError; - public abstract void set_value (string table, bool create, string id, GLib.Variant data) throws DBusError, IOError; public abstract void set_permission (string table, bool create, string id, string app, string[] permissions) throws DBusError, IOError; - public abstract void delete_permission (string table, string id, string app) throws DBusError, IOError; public abstract string[] get_permission (string table, string id, string app) throws DBusError, IOError; - public abstract string[] list (string table) throws DBusError, IOError; } public class Permissions.PermissionStore : GLib.Object { + public signal void changed (); + private const string DBUS_NAME = "org.freedesktop.impl.portal.PermissionStore"; private const string DBUS_PATH = "/org/freedesktop/impl/portal/PermissionStore"; private const uint RECONNECT_TIMEOUT = 5000U; @@ -46,6 +41,7 @@ public class Permissions.PermissionStore : GLib.Object { Bus.get_proxy.begin (SESSION, DBUS_NAME, DBUS_PATH, 0, null, (obj, res) => { try { dbus = Bus.get_proxy.end (res); + dbus.changed.connect (() => changed ()); } catch (Error e) { critical (e.message); Timeout.add (RECONNECT_TIMEOUT, () => { diff --git a/src/Permissions/Widgets/AppSettingsView.vala b/src/Permissions/Widgets/AppSettingsView.vala index 42807694..62a095f9 100644 --- a/src/Permissions/Widgets/AppSettingsView.vala +++ b/src/Permissions/Widgets/AppSettingsView.vala @@ -214,7 +214,9 @@ public class Permissions.Widgets.AppSettingsView : Switchboard.SettingsPage { }); update_permissions (); - PermissionStore.get_default ().notify["dbus"].connect (update_permissions); + var permission_store = PermissionStore.get_default (); + permission_store.notify["dbus"].connect (update_permissions); + permission_store.changed.connect (update_permissions); update_property (Gtk.AccessibleProperty.LABEL, _("%s permissions").printf (selected_app.name), -1); title = selected_app.name; From 6b8343fe76cab2278a46daaa1f884b1242aff2c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Wed, 27 Mar 2024 12:04:35 -0700 Subject: [PATCH 07/14] Description --- src/Permissions/Widgets/AppSettingsView.vala | 22 ++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/Permissions/Widgets/AppSettingsView.vala b/src/Permissions/Widgets/AppSettingsView.vala index 62a095f9..9fea820d 100644 --- a/src/Permissions/Widgets/AppSettingsView.vala +++ b/src/Permissions/Widgets/AppSettingsView.vala @@ -37,19 +37,29 @@ public class Permissions.Widgets.AppSettingsView : Switchboard.SettingsPage { icon_size = LARGE }; - var background_label = new Gtk.Label (_("Run in background")) { + var background_label = new Gtk.Label (_("Background Activity")) { hexpand = true, xalign = 0 }; + var background_description = new Gtk.Label (_("Perform tasks and use system resources while its window is closed.")) { + xalign = 0, + wrap = true + }; + background_description.add_css_class (Granite.STYLE_CLASS_DIM_LABEL); + background_description.add_css_class (Granite.STYLE_CLASS_SMALL_LABEL); + background_switch = new Gtk.Switch () { valign = CENTER }; - var background_box = new Gtk.Box (HORIZONTAL, 6); - background_box.append (background_image); - background_box.append (background_label); - background_box.append (background_switch); + var background_grid = new Gtk.Grid () { + column_spacing = 6 + }; + background_grid.attach (background_image, 0, 0, 1, 2); + background_grid.attach (background_label, 1, 0); + background_grid.attach (background_description, 1, 1); + background_grid.attach (background_switch, 2, 0, 1, 2); permission_box = new Gtk.ListBox () { hexpand = true, @@ -57,7 +67,7 @@ public class Permissions.Widgets.AppSettingsView : Switchboard.SettingsPage { }; permission_box.add_css_class ("boxed-list"); permission_box.add_css_class (Granite.STYLE_CLASS_RICH_LIST); - permission_box.append (background_box); + permission_box.append (background_grid); var homefolder_widget = new PermissionSettingsWidget ( Plug.permission_names["filesystems=home"], From ae8efaaafe657871528bd45098908d6742216765 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Wed, 27 Mar 2024 13:49:32 -0700 Subject: [PATCH 08/14] Make methods async, handle errors --- src/Permissions/Backend/PermissionStore.vala | 4 +- src/Permissions/Widgets/AppSettingsView.vala | 46 ++++++++++++++++---- 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/src/Permissions/Backend/PermissionStore.vala b/src/Permissions/Backend/PermissionStore.vala index de3ba7c5..d32b24b4 100644 --- a/src/Permissions/Backend/PermissionStore.vala +++ b/src/Permissions/Backend/PermissionStore.vala @@ -6,8 +6,8 @@ [DBus (name = "org.freedesktop.impl.portal.PermissionStore", timeout = 120000)] public interface PermissionStoreDBus : GLib.Object { public signal void changed (string table, string id, bool deleted, GLib.Variant data, [DBus (signature = "a{sas}")] GLib.Variant permissions); - public abstract void set_permission (string table, bool create, string id, string app, string[] permissions) throws DBusError, IOError; - public abstract string[] get_permission (string table, string id, string app) throws DBusError, IOError; + public abstract async void set_permission (string table, bool create, string id, string app, string[] permissions) throws DBusError, IOError; + public abstract async string[] get_permission (string table, string id, string app) throws DBusError, IOError; } public class Permissions.PermissionStore : GLib.Object { diff --git a/src/Permissions/Widgets/AppSettingsView.vala b/src/Permissions/Widgets/AppSettingsView.vala index 9fea820d..1d46a36a 100644 --- a/src/Permissions/Widgets/AppSettingsView.vala +++ b/src/Permissions/Widgets/AppSettingsView.vala @@ -168,7 +168,22 @@ public class Permissions.Widgets.AppSettingsView : Switchboard.SettingsPage { permissions += "no"; } - PermissionStore.get_default ().dbus.set_permission (BACKGROUND_TABLE, true, BACKGROUND_ID, selected_app.id, permissions); + try { + PermissionStore.get_default ().dbus.set_permission.begin (BACKGROUND_TABLE, true, BACKGROUND_ID, selected_app.id, permissions); + } catch (Error e) { + critical (e.message); + var dialog = new Granite.MessageDialog ( + _("Couldn't set background activity permission"), + e.message, + new ThemedIcon ("preferences-system") + ) { + badge_icon = new ThemedIcon ("dialog-error"), + modal = true, + transient_for = (Gtk.Window) get_root () + }; + dialog.present (); + dialog.response.connect (dialog.destroy); + } }); reset_button.clicked.connect (() => { @@ -242,13 +257,28 @@ public class Permissions.Widgets.AppSettingsView : Switchboard.SettingsPage { permission_box.sensitive = true; - var background_permission = permission_store.dbus.get_permission ( - BACKGROUND_TABLE, BACKGROUND_ID, selected_app.id - ); - - // A lack of explicit permission is considered permission - // to allow pre-emptive opt-out - background_switch.active = background_permission[0] != "no"; + permission_store.dbus.get_permission.begin (BACKGROUND_TABLE, BACKGROUND_ID, selected_app.id, (obj, res) => { + try { + var background_permission = permission_store.dbus.get_permission.end (res); + + // A lack of explicit permission is considered permission + // to allow pre-emptive opt-out + background_switch.active = background_permission[0] != "no"; + } catch (Error e) { + critical (e.message); + var dialog = new Granite.MessageDialog ( + _("Couldn't get background activity permission"), + e.message, + new ThemedIcon ("preferences-system") + ) { + badge_icon = new ThemedIcon ("dialog-error"), + modal = true, + transient_for = (Gtk.Window) get_root () + }; + dialog.present (); + dialog.response.connect (dialog.destroy); + } + }); } private void change_permission_settings (Backend.PermissionSettings settings) { From b8ecdab900f62727674ba0d9aa7b489d5b829c24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Thu, 28 Mar 2024 21:03:23 -0700 Subject: [PATCH 09/14] use PermissionSettingsWidget --- src/Permissions/Widgets/AppSettingsView.vala | 42 +++++--------------- 1 file changed, 10 insertions(+), 32 deletions(-) diff --git a/src/Permissions/Widgets/AppSettingsView.vala b/src/Permissions/Widgets/AppSettingsView.vala index a9b6c8bf..9939f7a7 100644 --- a/src/Permissions/Widgets/AppSettingsView.vala +++ b/src/Permissions/Widgets/AppSettingsView.vala @@ -28,38 +28,16 @@ public class Permissions.Widgets.AppSettingsView : Switchboard.SettingsPage { private Gtk.ListBox sandbox_box; private Gtk.ListBox permission_box; private Gtk.Button reset_button; - private Gtk.Switch background_switch; + private PermissionSettingsWidget background_row; construct { notify["selected-app"].connect (update_view); - var background_image = new Gtk.Image.from_icon_name ("permissions-background") { - icon_size = LARGE - }; - - var background_label = new Gtk.Label (_("Background Activity")) { - hexpand = true, - xalign = 0 - }; - - var background_description = new Gtk.Label (_("Perform tasks and use system resources while its window is closed.")) { - xalign = 0, - wrap = true - }; - background_description.add_css_class (Granite.STYLE_CLASS_DIM_LABEL); - background_description.add_css_class (Granite.STYLE_CLASS_SMALL_LABEL); - - background_switch = new Gtk.Switch () { - valign = CENTER - }; - - var background_grid = new Gtk.Grid () { - column_spacing = 6 - }; - background_grid.attach (background_image, 0, 0, 1, 2); - background_grid.attach (background_label, 1, 0); - background_grid.attach (background_description, 1, 1); - background_grid.attach (background_switch, 2, 0, 1, 2); + background_row = new PermissionSettingsWidget ( + _("Background Activity"), + _("Perform tasks and use system resources while its window is closed."), + "permissions-background" + ); permission_box = new Gtk.ListBox () { hexpand = true, @@ -67,7 +45,7 @@ public class Permissions.Widgets.AppSettingsView : Switchboard.SettingsPage { }; permission_box.add_css_class ("boxed-list"); permission_box.add_css_class (Granite.STYLE_CLASS_RICH_LIST); - permission_box.append (background_grid); + permission_box.append (background_row); sandbox_box = new Gtk.ListBox () { hexpand = true, @@ -86,9 +64,9 @@ public class Permissions.Widgets.AppSettingsView : Switchboard.SettingsPage { update_view (); - background_switch.notify["active"].connect (() => { + background_row.notify["active"].connect (() => { string[] permissions; - if (background_switch.active) { + if (background_row.active) { permissions += "yes"; } else { permissions += "no"; @@ -214,7 +192,7 @@ public class Permissions.Widgets.AppSettingsView : Switchboard.SettingsPage { // A lack of explicit permission is considered permission // to allow pre-emptive opt-out - background_switch.active = background_permission[0] != "no"; + background_row.active = background_permission[0] != "no"; } catch (Error e) { critical (e.message); var dialog = new Granite.MessageDialog ( From b8d56b92ddea334d21e08be6b54c3ed6a5a41d42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Thu, 28 Mar 2024 21:24:40 -0700 Subject: [PATCH 10/14] Only show bg activity option when relevant --- src/Permissions/Widgets/AppSettingsView.vala | 122 ++++++++++--------- 1 file changed, 65 insertions(+), 57 deletions(-) diff --git a/src/Permissions/Widgets/AppSettingsView.vala b/src/Permissions/Widgets/AppSettingsView.vala index 9939f7a7..ce90c3dd 100644 --- a/src/Permissions/Widgets/AppSettingsView.vala +++ b/src/Permissions/Widgets/AppSettingsView.vala @@ -33,19 +33,12 @@ public class Permissions.Widgets.AppSettingsView : Switchboard.SettingsPage { construct { notify["selected-app"].connect (update_view); - background_row = new PermissionSettingsWidget ( - _("Background Activity"), - _("Perform tasks and use system resources while its window is closed."), - "permissions-background" - ); - permission_box = new Gtk.ListBox () { hexpand = true, selection_mode = NONE }; permission_box.add_css_class ("boxed-list"); permission_box.add_css_class (Granite.STYLE_CLASS_RICH_LIST); - permission_box.append (background_row); sandbox_box = new Gtk.ListBox () { hexpand = true, @@ -64,32 +57,6 @@ public class Permissions.Widgets.AppSettingsView : Switchboard.SettingsPage { update_view (); - background_row.notify["active"].connect (() => { - string[] permissions; - if (background_row.active) { - permissions += "yes"; - } else { - permissions += "no"; - } - - try { - PermissionStore.get_default ().dbus.set_permission.begin (BACKGROUND_TABLE, true, BACKGROUND_ID, selected_app.id, permissions); - } catch (Error e) { - critical (e.message); - var dialog = new Granite.MessageDialog ( - _("Couldn't set background activity permission"), - e.message, - new ThemedIcon ("preferences-system") - ) { - badge_icon = new ThemedIcon ("dialog-error"), - modal = true, - transient_for = (Gtk.Window) get_root () - }; - dialog.present (); - dialog.response.connect (dialog.destroy); - } - }); - reset_button.clicked.connect (() => { if (selected_app != null) { selected_app.reset_settings_to_standard (); @@ -99,6 +66,7 @@ public class Permissions.Widgets.AppSettingsView : Switchboard.SettingsPage { } private void update_view () { + permission_box.remove_all (); sandbox_box.remove_all (); if (selected_app == null) { @@ -164,9 +132,46 @@ public class Permissions.Widgets.AppSettingsView : Switchboard.SettingsPage { sandbox_box.append (override_row); }); - update_permissions (); var permission_store = PermissionStore.get_default (); - permission_store.notify["dbus"].connect (update_permissions); + + background_row = new PermissionSettingsWidget ( + _("Background Activity"), + _("Perform tasks and use system resources while its window is closed."), + "permissions-background" + ); + + background_row.notify["active"].connect (() => { + string[] permissions = { }; + if (background_row.active) { + permissions += "yes"; + } else { + permissions += "no"; + } + + permission_store.dbus.set_permission.begin (BACKGROUND_TABLE, true, BACKGROUND_ID, selected_app.id, permissions, (obj, res) => { + try { + permission_store.dbus.set_permission.end (res); + } catch (Error e) { + critical (e.message); + var dialog = new Granite.MessageDialog ( + _("Couldn't set background activity permission"), + e.message, + new ThemedIcon ("preferences-system") + ) { + badge_icon = new ThemedIcon ("dialog-error"), + modal = true, + transient_for = (Gtk.Window) get_root () + }; + dialog.present (); + dialog.response.connect (dialog.destroy); + } + }); + }); + + update_permissions.begin (); + permission_store.notify["dbus"].connect (() => { + update_permissions.begin (); + }); permission_store.changed.connect (update_permissions); sensitive = true; @@ -177,7 +182,7 @@ public class Permissions.Widgets.AppSettingsView : Switchboard.SettingsPage { icon = selected_app.icon; } - private void update_permissions () { + private async void update_permissions () { var permission_store = PermissionStore.get_default (); if (permission_store.dbus == null) { permission_box.sensitive = false; @@ -186,28 +191,31 @@ public class Permissions.Widgets.AppSettingsView : Switchboard.SettingsPage { permission_box.sensitive = true; - permission_store.dbus.get_permission.begin (BACKGROUND_TABLE, BACKGROUND_ID, selected_app.id, (obj, res) => { - try { - var background_permission = permission_store.dbus.get_permission.end (res); - - // A lack of explicit permission is considered permission - // to allow pre-emptive opt-out - background_row.active = background_permission[0] != "no"; - } catch (Error e) { - critical (e.message); - var dialog = new Granite.MessageDialog ( - _("Couldn't get background activity permission"), - e.message, - new ThemedIcon ("preferences-system") - ) { - badge_icon = new ThemedIcon ("dialog-error"), - modal = true, - transient_for = (Gtk.Window) get_root () - }; - dialog.present (); - dialog.response.connect (dialog.destroy); + try { + var background_permission = yield permission_store.dbus.get_permission (BACKGROUND_TABLE, BACKGROUND_ID, selected_app.id); + if (background_permission[0] != null) { + background_row.active = background_permission[0] == "yes"; + + if (background_row.parent == null) { + permission_box.append (background_row); + } } - }); + } catch (Error e) { + critical (e.message); + var dialog = new Granite.MessageDialog ( + _("Couldn't get background activity permission"), + e.message, + new ThemedIcon ("preferences-system") + ) { + badge_icon = new ThemedIcon ("dialog-error"), + modal = true, + transient_for = (Gtk.Window) get_root () + }; + dialog.present (); + dialog.response.connect (dialog.destroy); + } + + permission_box.visible = permission_box.get_row_at_index (0) != null; } private void change_permission_settings (Backend.PermissionSettings settings) { From 7614eeaf08d21319060b36717c7a21d5ac364edb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Thu, 28 Mar 2024 21:34:37 -0700 Subject: [PATCH 11/14] Move error handling to backend --- src/Permissions/Backend/PermissionStore.vala | 41 ++++++++++++++++++ src/Permissions/Widgets/AppSettingsView.vala | 44 +++----------------- 2 files changed, 47 insertions(+), 38 deletions(-) diff --git a/src/Permissions/Backend/PermissionStore.vala b/src/Permissions/Backend/PermissionStore.vala index d32b24b4..700ddcf6 100644 --- a/src/Permissions/Backend/PermissionStore.vala +++ b/src/Permissions/Backend/PermissionStore.vala @@ -55,4 +55,45 @@ public class Permissions.PermissionStore : GLib.Object { private void name_vanished_callback (DBusConnection connection, string name) { dbus = null; } + + public void set_permission (string table, string id, string app, string[] permissions) { + dbus.set_permission.begin (table, false, id, app, permissions, (obj, res) => { + try { + dbus.set_permission.end (res); + } catch (Error e) { + critical (e.message); + var dialog = new Granite.MessageDialog ( + _("Couldn't set permission"), + e.message, + new ThemedIcon ("preferences-system") + ) { + badge_icon = new ThemedIcon ("dialog-error"), + modal = true, + transient_for = ((Gtk.Application) GLib.Application.get_default ()).active_window + }; + dialog.present (); + dialog.response.connect (dialog.destroy); + } + }); + } + + public async string[] get_permission (string table, string id, string app) { + try { + return yield dbus.get_permission (table, id, app); + } catch (Error e) { + var dialog = new Granite.MessageDialog ( + _("Couldn't get permission"), + e.message, + new ThemedIcon ("preferences-system") + ) { + badge_icon = new ThemedIcon ("dialog-error"), + modal = true, + transient_for = ((Gtk.Application) GLib.Application.get_default ()).active_window + }; + dialog.present (); + dialog.response.connect (dialog.destroy); + } + + return { null }; + } } diff --git a/src/Permissions/Widgets/AppSettingsView.vala b/src/Permissions/Widgets/AppSettingsView.vala index ce90c3dd..ec740fa0 100644 --- a/src/Permissions/Widgets/AppSettingsView.vala +++ b/src/Permissions/Widgets/AppSettingsView.vala @@ -148,24 +148,7 @@ public class Permissions.Widgets.AppSettingsView : Switchboard.SettingsPage { permissions += "no"; } - permission_store.dbus.set_permission.begin (BACKGROUND_TABLE, true, BACKGROUND_ID, selected_app.id, permissions, (obj, res) => { - try { - permission_store.dbus.set_permission.end (res); - } catch (Error e) { - critical (e.message); - var dialog = new Granite.MessageDialog ( - _("Couldn't set background activity permission"), - e.message, - new ThemedIcon ("preferences-system") - ) { - badge_icon = new ThemedIcon ("dialog-error"), - modal = true, - transient_for = (Gtk.Window) get_root () - }; - dialog.present (); - dialog.response.connect (dialog.destroy); - } - }); + permission_store.set_permission (BACKGROUND_TABLE, BACKGROUND_ID, selected_app.id, permissions); }); update_permissions.begin (); @@ -191,28 +174,13 @@ public class Permissions.Widgets.AppSettingsView : Switchboard.SettingsPage { permission_box.sensitive = true; - try { - var background_permission = yield permission_store.dbus.get_permission (BACKGROUND_TABLE, BACKGROUND_ID, selected_app.id); - if (background_permission[0] != null) { - background_row.active = background_permission[0] == "yes"; + var background_permission = yield permission_store.get_permission (BACKGROUND_TABLE, BACKGROUND_ID, selected_app.id); + if (background_permission[0] != null) { + background_row.active = background_permission[0] == "yes"; - if (background_row.parent == null) { - permission_box.append (background_row); - } + if (background_row.parent == null) { + permission_box.append (background_row); } - } catch (Error e) { - critical (e.message); - var dialog = new Granite.MessageDialog ( - _("Couldn't get background activity permission"), - e.message, - new ThemedIcon ("preferences-system") - ) { - badge_icon = new ThemedIcon ("dialog-error"), - modal = true, - transient_for = (Gtk.Window) get_root () - }; - dialog.present (); - dialog.response.connect (dialog.destroy); } permission_box.visible = permission_box.get_row_at_index (0) != null; From 4fca060313d0fa44cf993708638ac402c0e5db29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Thu, 28 Mar 2024 21:41:44 -0700 Subject: [PATCH 12/14] more compact --- src/Permissions/Widgets/AppSettingsView.vala | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Permissions/Widgets/AppSettingsView.vala b/src/Permissions/Widgets/AppSettingsView.vala index ec740fa0..b0ae65ee 100644 --- a/src/Permissions/Widgets/AppSettingsView.vala +++ b/src/Permissions/Widgets/AppSettingsView.vala @@ -152,9 +152,7 @@ public class Permissions.Widgets.AppSettingsView : Switchboard.SettingsPage { }); update_permissions.begin (); - permission_store.notify["dbus"].connect (() => { - update_permissions.begin (); - }); + permission_store.notify["dbus"].connect (update_permissions); permission_store.changed.connect (update_permissions); sensitive = true; From e737de183e8e9267f1e2e292deb51eb0e4ee9947 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Thu, 28 Mar 2024 21:43:45 -0700 Subject: [PATCH 13/14] Extra whitespace --- data/meson.build | 1 - 1 file changed, 1 deletion(-) diff --git a/data/meson.build b/data/meson.build index 980b974b..d2c22809 100644 --- a/data/meson.build +++ b/data/meson.build @@ -4,7 +4,6 @@ gresource = gnome.compile_resources( source_dir: meson.current_source_dir() ) - i18n.merge_file( input: 'applications.metainfo.xml.in', output: 'io.elementary.settings.applications.metainfo.xml', From 7aee4bbb6c3013b9549321d5d8b7bfd3d221e8b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Fri, 29 Mar 2024 08:06:37 -0700 Subject: [PATCH 14/14] ternary operator and single item array --- src/Permissions/Widgets/AppSettingsView.vala | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/Permissions/Widgets/AppSettingsView.vala b/src/Permissions/Widgets/AppSettingsView.vala index b0ae65ee..f72b2a54 100644 --- a/src/Permissions/Widgets/AppSettingsView.vala +++ b/src/Permissions/Widgets/AppSettingsView.vala @@ -141,13 +141,7 @@ public class Permissions.Widgets.AppSettingsView : Switchboard.SettingsPage { ); background_row.notify["active"].connect (() => { - string[] permissions = { }; - if (background_row.active) { - permissions += "yes"; - } else { - permissions += "no"; - } - + string[] permissions = { background_row.active ? "yes" : "no" }; permission_store.set_permission (BACKGROUND_TABLE, BACKGROUND_ID, selected_app.id, permissions); });