From 7163dccee1fd8968ed2a00370e299df046025c82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Mon, 18 Mar 2024 12:25:07 -0700 Subject: [PATCH 01/13] PermissionsPlug: use Switchboard.SettingsPage --- src/Permissions/Backend/App.vala | 8 +++++++ src/Permissions/PermissionsPlug.vala | 12 +++++------ src/Permissions/Widgets/AppSettingsView.vala | 22 ++++++-------------- src/Permissions/Widgets/SidebarRow.vala | 12 +++-------- 4 files changed, 22 insertions(+), 32 deletions(-) diff --git a/src/Permissions/Backend/App.vala b/src/Permissions/Backend/App.vala index 51bd1cf8..38e7b683 100644 --- a/src/Permissions/Backend/App.vala +++ b/src/Permissions/Backend/App.vala @@ -25,6 +25,7 @@ public class Permissions.Backend.App : GLib.Object { public Flatpak.InstalledRef installed_ref { get; construct; } public string id { get; private set; } public string name { get; private set; } + public Icon icon { get; private set; } public GenericArray settings; private const string GROUP = "Context"; @@ -37,6 +38,13 @@ public class Permissions.Backend.App : GLib.Object { id = installed_ref.get_name (); name = installed_ref.get_appdata_name () ?? id; + var appinfo = new GLib.DesktopAppInfo (id + ".desktop"); + if (appinfo != null && appinfo.get_icon () != null) { + icon = appinfo.get_icon (); + } else { + icon = new ThemedIcon ("application-default-icon"); + } + settings = new GenericArray (); var permissions = new GenericArray (); diff --git a/src/Permissions/PermissionsPlug.vala b/src/Permissions/PermissionsPlug.vala index d89abc39..c7eafad3 100644 --- a/src/Permissions/PermissionsPlug.vala +++ b/src/Permissions/PermissionsPlug.vala @@ -73,7 +73,10 @@ public class Permissions.Plug : Gtk.Box { child = scrolled_window }; - var sidebar = new Gtk.Box (VERTICAL, 12); + var sidebar = new Gtk.Box (VERTICAL, 12) { + margin_bottom = 12, + margin_start = 12 + }; sidebar.append (search_entry); sidebar.append (frame); @@ -94,12 +97,7 @@ public class Permissions.Plug : Gtk.Box { show_row (row); } - var grid = new Gtk.Grid () { - margin_end = 12, - margin_bottom = 12, - margin_start = 12, - column_spacing = 12 - }; + var grid = new Gtk.Grid (); grid.attach (sidebar, 0, 0, 1, 1); grid.attach (app_settings_view, 1, 0, 2, 1); diff --git a/src/Permissions/Widgets/AppSettingsView.vala b/src/Permissions/Widgets/AppSettingsView.vala index 0e8fdc16..96d2aa7b 100644 --- a/src/Permissions/Widgets/AppSettingsView.vala +++ b/src/Permissions/Widgets/AppSettingsView.vala @@ -19,7 +19,7 @@ * Authored by: Marius Meisenzahl */ -public class Permissions.Widgets.AppSettingsView : Gtk.Grid { +public class Permissions.Widgets.AppSettingsView : Switchboard.SettingsPage { public Backend.App? selected_app { get; set; default = null; } private Gtk.ListBox list_box; @@ -97,23 +97,11 @@ public class Permissions.Widgets.AppSettingsView : Gtk.Grid { list_box.append (printing_widget); list_box.append (ssh_widget); list_box.append (gpu_widget); + list_box.add_css_class (Granite.STYLE_CLASS_BACKGROUND); - var scrolled_window = new Gtk.ScrolledWindow () { - child = list_box - }; - - var frame = new Gtk.Frame (null) { - child = scrolled_window - }; - frame.add_css_class (Granite.STYLE_CLASS_VIEW); - - reset_button = new Gtk.Button.with_label (_("Reset to Defaults")) { - halign = Gtk.Align.END - }; + child = list_box; - row_spacing = 24; - attach (frame, 0, 0); - attach (reset_button, 0, 1); + reset_button = add_button (_("Reset to Defaults")); update_view (); @@ -180,6 +168,8 @@ public class Permissions.Widgets.AppSettingsView : Gtk.Grid { }); update_property (Gtk.AccessibleProperty.LABEL, _("%s permissions").printf (selected_app.name), -1); + title = selected_app.name; + icon = selected_app.icon; } private void change_permission_settings (Backend.PermissionSettings settings) { diff --git a/src/Permissions/Widgets/SidebarRow.vala b/src/Permissions/Widgets/SidebarRow.vala index 134f4c3a..5aa183d2 100644 --- a/src/Permissions/Widgets/SidebarRow.vala +++ b/src/Permissions/Widgets/SidebarRow.vala @@ -30,16 +30,10 @@ public class Permissions.SidebarRow : Gtk.ListBoxRow { construct { hexpand = true; - var appinfo = new GLib.DesktopAppInfo (app.id + ".desktop"); - Gtk.Image image; - if (appinfo != null && appinfo.get_icon () != null) { - image = new Gtk.Image.from_gicon (appinfo.get_icon ()); - } else { - image = new Gtk.Image.from_icon_name ("application-default-icon"); - } - - image.pixel_size = 32; + var image = new Gtk.Image.from_gicon (app.icon) { + pixel_size = 32 + }; var title_label = new Gtk.Label (app.name) { ellipsize = Pango.EllipsizeMode.END, From f71d0aedeb95fd9e45474cfc1c932d6d83bf89be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Tue, 26 Mar 2024 13:06:26 -0700 Subject: [PATCH 02/13] Style stuff, fix wrong app name --- src/Permissions/Backend/App.vala | 7 ++++--- src/Permissions/Widgets/AppSettingsView.vala | 2 +- src/Permissions/Widgets/PermissionSettingsWidget.vala | 5 +++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/Permissions/Backend/App.vala b/src/Permissions/Backend/App.vala index 38e7b683..85d0f31b 100644 --- a/src/Permissions/Backend/App.vala +++ b/src/Permissions/Backend/App.vala @@ -36,13 +36,14 @@ public class Permissions.Backend.App : GLib.Object { construct { id = installed_ref.get_name (); - name = installed_ref.get_appdata_name () ?? id; var appinfo = new GLib.DesktopAppInfo (id + ".desktop"); - if (appinfo != null && appinfo.get_icon () != null) { - icon = appinfo.get_icon (); + if (appinfo != null) { + name = appinfo.get_name (); + icon = appinfo.get_icon () ?? new ThemedIcon ("application-default-icon"); } else { icon = new ThemedIcon ("application-default-icon"); + name = id; } settings = new GenericArray (); diff --git a/src/Permissions/Widgets/AppSettingsView.vala b/src/Permissions/Widgets/AppSettingsView.vala index 96d2aa7b..06483a1f 100644 --- a/src/Permissions/Widgets/AppSettingsView.vala +++ b/src/Permissions/Widgets/AppSettingsView.vala @@ -88,6 +88,7 @@ public class Permissions.Widgets.AppSettingsView : Switchboard.SettingsPage { hexpand = true, vexpand = true }; + 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); @@ -97,7 +98,6 @@ public class Permissions.Widgets.AppSettingsView : Switchboard.SettingsPage { list_box.append (printing_widget); list_box.append (ssh_widget); list_box.append (gpu_widget); - list_box.add_css_class (Granite.STYLE_CLASS_BACKGROUND); child = list_box; diff --git a/src/Permissions/Widgets/PermissionSettingsWidget.vala b/src/Permissions/Widgets/PermissionSettingsWidget.vala index 63e58d22..62196d1e 100644 --- a/src/Permissions/Widgets/PermissionSettingsWidget.vala +++ b/src/Permissions/Widgets/PermissionSettingsWidget.vala @@ -40,7 +40,7 @@ public class Permissions.Widgets.PermissionSettingsWidget : Gtk.ListBoxRow { construct { var icon = new Gtk.Image.from_icon_name (icon_name) { - pixel_size = 32, + icon_size = LARGE, tooltip_text = settings.context }; @@ -48,12 +48,13 @@ public class Permissions.Widgets.PermissionSettingsWidget : Gtk.ListBoxRow { halign = Gtk.Align.START, hexpand = true }; - name_label.add_css_class (Granite.STYLE_CLASS_H3_LABEL); var description_label = new Gtk.Label (description) { wrap = true, xalign = 0 }; + description_label.add_css_class (Granite.STYLE_CLASS_DIM_LABEL); + description_label.add_css_class (Granite.STYLE_CLASS_SMALL_LABEL); var allow_switch = new Gtk.Switch () { valign = Gtk.Align.CENTER From 41a723ee06ef906f013a14b3b8d7f89b311b54e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Tue, 26 Mar 2024 13:11:05 -0700 Subject: [PATCH 03/13] Fix column_spacing --- src/Permissions/Widgets/PermissionSettingsWidget.vala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Permissions/Widgets/PermissionSettingsWidget.vala b/src/Permissions/Widgets/PermissionSettingsWidget.vala index 62196d1e..b31b0071 100644 --- a/src/Permissions/Widgets/PermissionSettingsWidget.vala +++ b/src/Permissions/Widgets/PermissionSettingsWidget.vala @@ -61,7 +61,7 @@ public class Permissions.Widgets.PermissionSettingsWidget : Gtk.ListBoxRow { }; var grid = new Gtk.Grid () { - column_spacing = 12 + column_spacing = 6 }; grid.attach (icon, 0, 0, 1, 2); grid.attach (name_label, 1, 0); From 05d8a681922916b81362e63d238dfc973f88259a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Tue, 26 Mar 2024 13:18:38 -0700 Subject: [PATCH 04/13] Fix selection mode --- src/Permissions/Widgets/AppSettingsView.vala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Permissions/Widgets/AppSettingsView.vala b/src/Permissions/Widgets/AppSettingsView.vala index 06483a1f..0c4692ab 100644 --- a/src/Permissions/Widgets/AppSettingsView.vala +++ b/src/Permissions/Widgets/AppSettingsView.vala @@ -86,7 +86,8 @@ public class Permissions.Widgets.AppSettingsView : Switchboard.SettingsPage { list_box = new Gtk.ListBox () { hexpand = true, - vexpand = true + vexpand = true, + selection_mode = NONE }; list_box.add_css_class ("boxed-list"); list_box.add_css_class (Granite.STYLE_CLASS_RICH_LIST); From 31e11b33f7741c48e44ce39b53e718492e190784 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 05/13] 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 2c50c28a0651040a0860a6715103d398ae2d6ac5 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 06/13] 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 8bb88d648d6075aa209a3d1c7505bdf70dd78a22 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 07/13] 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 16bc928e9a624032401d1c6995bb2f03ea660410 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 08/13] 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 62bd06fcc5b39b31b76caee20e8deaf146fb0f23 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 09/13] 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 528ce5a44fa0ab61f8e6338cff1f435b262c7fe5 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 10/13] 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 83b2a35cb5632c73e49ce711058fd7b37c072eca 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 11/13] 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 52ca2c3686304d24624c0acc339035d1e8885fc1 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 12/13] 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 7a4c469e4024f124ef5cd547744fc7f7c482c8eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Thu, 28 Mar 2024 20:07:23 -0700 Subject: [PATCH 13/13] AppSettingsView: add notification permission link --- src/Permissions/Widgets/AppSettingsView.vala | 22 ++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/Permissions/Widgets/AppSettingsView.vala b/src/Permissions/Widgets/AppSettingsView.vala index 1d46a36a..f77bedf6 100644 --- a/src/Permissions/Widgets/AppSettingsView.vala +++ b/src/Permissions/Widgets/AppSettingsView.vala @@ -29,6 +29,7 @@ public class Permissions.Widgets.AppSettingsView : Switchboard.SettingsPage { private Gtk.ListBox permission_box; private Gtk.Button reset_button; private Gtk.Switch background_switch; + private Gtk.LinkButton notification_button; construct { notify["selected-app"].connect (update_view); @@ -61,6 +62,24 @@ public class Permissions.Widgets.AppSettingsView : Switchboard.SettingsPage { background_grid.attach (background_description, 1, 1); background_grid.attach (background_switch, 2, 0, 1, 2); + var notification_icon = new Gtk.Image.from_icon_name ("preferences-system-notifications") { + icon_size = LARGE + }; + + var notification_label = new Gtk.Label (_("Notifications")) { + hexpand = true, + xalign = 0 + }; + + notification_button = new Gtk.LinkButton ("settings://notifications") { + icon_name = "view-more-horizontal-symbolic" + }; + + var notification_box = new Gtk.Box (HORIZONTAL, 6); + notification_box.append (notification_icon); + notification_box.append (notification_label); + notification_box.append (notification_button); + permission_box = new Gtk.ListBox () { hexpand = true, selection_mode = NONE @@ -68,6 +87,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 (notification_box); var homefolder_widget = new PermissionSettingsWidget ( Plug.permission_names["filesystems=home"], @@ -243,6 +263,8 @@ public class Permissions.Widgets.AppSettingsView : Switchboard.SettingsPage { permission_store.notify["dbus"].connect (update_permissions); permission_store.changed.connect (update_permissions); + notification_button.uri = "settings://notifications/%s".printf (selected_app.id); + update_property (Gtk.AccessibleProperty.LABEL, _("%s permissions").printf (selected_app.name), -1); title = selected_app.name; icon = selected_app.icon;