/* This file is part of Caffeine (gnome-shell-extension-caffeine). Caffeine 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. Caffeine 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 Caffeine. If not, see . Copyright 2022 Pakaoraki // From https://gitlab.com/skrewball/openweather/-/blob/master/src/prefs.js */ /* exported AppsPage */ 'use strict'; import Adw from 'gi://Adw'; import Gtk from 'gi://Gtk'; import GObject from 'gi://GObject'; import Gio from 'gi://Gio'; import { gettext as _ } from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; export var AppsPage = GObject.registerClass( class CaffeineAppsPage extends Adw.PreferencesPage { _init(settings, settingsKey) { super._init({ title: _('Apps'), icon_name: 'applications-symbolic', name: 'AppsPage' }); this._settingsKey = settingsKey; this._settings = settings; this._listApps = []; // Apps behavior group // -------------- let appsBehaviorGroup = new Adw.PreferencesGroup({ title: _('Trigger mode') }); // Apps behavior select mode let appsTriggerMode = new Gtk.StringList(); appsTriggerMode.append(_('Running')); appsTriggerMode.append(_('Focus')); appsTriggerMode.append(_('Active workspace')); let appsTriggerModeRow = new Adw.ComboRow({ title: _('Apps trigger Caffeine mode'), subtitle: _('Choose the way apps will trigger Caffeine'), model: appsTriggerMode, selected: this._settings.get_enum(this._settingsKey.TRIGGER_APPS_MODE) }); // Add elements appsBehaviorGroup.add(appsTriggerModeRow); this.add(appsBehaviorGroup); // Apps list group // -------------- let addAppsButton = new Gtk.Button({ child: new Adw.ButtonContent({ icon_name: 'list-add-symbolic', label: _('Add') }) }); this.appsGroup = new Adw.PreferencesGroup({ title: _('Apps that trigger Caffeine'), header_suffix: addAppsButton }); this._refreshApps(); // Add elements this.add(this.appsGroup); // Bind signals addAppsButton.connect('clicked', this._onAddApp.bind(this)); appsTriggerModeRow.connect('notify::selected', (widget) => { this._settings.set_enum(this._settingsKey.TRIGGER_APPS_MODE, widget.selected); }); } _refreshApps() { const _apps = this._settings.get_strv(this._settingsKey.INHIBIT_APPS); // Clear the Apps list this._listApps.length = 0; // Update the list & Check if app still exist _apps.forEach((id) => { const appInfo = Gio.DesktopAppInfo.new(id); if (appInfo) { this._listApps.push(id); } }); // Check if the apps list UI needs updating if (this._appsListUi !== this._listApps) { // Remove the old list if (this._count) { for (let i = 0; i < this._count; i++) { this.appsGroup.remove(this.apps[i].Row); } this._count = null; } if (this._listApps.length > 0) { this.apps = {}; // Build new apps UI list for (let i in this._listApps) { this.apps[i] = {}; this.apps[i].ButtonBox = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL, halign: Gtk.Align.CENTER, spacing: 5, hexpand: false, vexpand: false }); this.apps[i].DeleteButton = new Gtk.Button({ icon_name: 'edit-delete-symbolic', valign: Gtk.Align.CENTER, css_classes: ['error'], hexpand: false, vexpand: false }); // App info let appInfo = Gio.DesktopAppInfo.new(this._listApps[i]); const appIcon = new Gtk.Image({ gicon: appInfo.get_icon(), pixel_size: 32 }); appIcon.get_style_context().add_class('icon-dropshadow'); this.apps[i].Row = new Adw.ActionRow({ title: appInfo.get_display_name(), subtitle: this._listApps[i].replace('.desktop', ''), activatable: true }); // Add elements this.apps[i].Row.add_prefix(appIcon); this.apps[i].ButtonBox.append(this.apps[i].DeleteButton); this.apps[i].Row.add_suffix(this.apps[i].ButtonBox); this.appsGroup.add(this.apps[i].Row); } // Bind signals for (let i in this.apps) { this.apps[i].DeleteButton.connect('clicked', () => { this._onRemoveApp(this._listApps[i]); }); } this._count = this._listApps.length; } this._appsListUi = [...this._listApps]; } return 0; } _onAddApp() { const dialog = new NewAppDialog(this.get_root(), this._settings, this._settingsKey); dialog.connect('response', (dlg, id) => { const appInfo = id === Gtk.ResponseType.OK ? dialog.get_widget().get_app_info() : null; const apps = this._settings.get_strv(this._settingsKey.INHIBIT_APPS); if (appInfo && !apps.some((a) => a === appInfo.get_id())) { this._settings.set_strv(this._settingsKey.INHIBIT_APPS, [ ...apps, appInfo.get_id() ]); this._refreshApps(); } dialog.destroy(); }); dialog.show(); } _onRemoveApp(appId) { this._settings.set_strv(this._settingsKey.INHIBIT_APPS, this._settings.get_strv(this._settingsKey.INHIBIT_APPS).filter((id) => { return id !== appId; }) ); this._refreshApps(); } }); const NewAppDialog = GObject.registerClass( class NewAppDialog extends Gtk.AppChooserDialog { _init(parent, settings, settingsKey) { super._init({ transient_for: parent, modal: true }); this._settings = settings; this._settingsKey = settingsKey; this.get_widget().set({ show_all: true, show_other: true // hide more button }); this.get_widget().connect('application-selected', this._updateSensitivity.bind(this)); this._updateSensitivity(); } _updateSensitivity() { const apps = this._settings.get_strv(this._settingsKey.INHIBIT_APPS); const appInfo = this.get_widget().get_app_info(); this.set_response_sensitive(Gtk.ResponseType.OK, appInfo && !apps.some((i) => i.startsWith(appInfo.get_id()))); } });