extensions-app: Use new 'enabled' property

The switch for enabling/disabling extensions currently bases its
state on the extension's ACTIVE state.

This is problematic in the enabled-but-inactive case, because
activating the switch tries to change the state from off to on,
which leads to enabling an already enabled extension (an obvious
no-op).

The new `enabled` property allows us to do better, and use delayed
state changes where the switch position represents the `enabled`
state, and the trough color whether the extension is ACTIVE.

https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/7004

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/3073>
This commit is contained in:
Florian Müllner 2023-09-12 14:25:03 +02:00 committed by Marge Bot
parent f9e81284f8
commit fec523f83f
3 changed files with 39 additions and 32 deletions

View File

@ -86,7 +86,16 @@
<child type="suffix"> <child type="suffix">
<object class="GtkSwitch" id="switch"> <object class="GtkSwitch" id="switch">
<property name="valign">center</property> <property name="valign">center</property>
<property name="action-name">row.enabled</property> <binding name="active">
<lookup name="enabled" type="Extension">
<lookup name="extension" type="ExtensionRow"/>
</lookup>
</binding>
<binding name="sensitive">
<lookup name="can-change" type="Extension">
<lookup name="extension" type="ExtensionRow"/>
</lookup>
</binding>
</object> </object>
</child> </child>
<child type="suffix"> <child type="suffix">

View File

@ -44,6 +44,10 @@ const Extension = GObject.registerClass({
'state', null, null, 'state', null, null,
GObject.ParamFlags.READABLE, GObject.ParamFlags.READABLE,
1, 99, ExtensionState.INITIALIZED), 1, 99, ExtensionState.INITIALIZED),
'enabled': GObject.ParamSpec.boolean(
'enabled', null, null,
GObject.ParamFlags.READABLE,
false),
'creator': GObject.ParamSpec.string( 'creator': GObject.ParamSpec.string(
'creator', null, null, 'creator', null, null,
GObject.ParamFlags.READABLE, GObject.ParamFlags.READABLE,
@ -95,7 +99,7 @@ const Extension = GObject.registerClass({
const deserialized = deserializeExtension(variant); const deserialized = deserializeExtension(variant);
const { const {
uuid, type, state, error, hasPrefs, hasUpdate, canChange, metadata, uuid, type, state, enabled, error, hasPrefs, hasUpdate, canChange, metadata,
} = deserialized; } = deserialized;
if (!this._uuid) if (!this._uuid)
@ -128,6 +132,11 @@ const Extension = GObject.registerClass({
this.notify('error'); this.notify('error');
} }
if (this._enabled !== enabled) {
this._enabled = enabled;
this.notify('enabled');
}
if (this._state !== state) { if (this._state !== state) {
const hadError = this.hasError; const hadError = this.hasError;
this._state = state; this._state = state;
@ -193,6 +202,10 @@ const Extension = GObject.registerClass({
return this._state; return this._state;
} }
get enabled() {
return this._enabled;
}
get creator() { get creator() {
return this._creator; return this._creator;
} }

View File

@ -1,5 +1,4 @@
import Adw from 'gi://Adw?version=1'; import Adw from 'gi://Adw?version=1';
import GLib from 'gi://GLib';
import Gio from 'gi://Gio'; import Gio from 'gi://Gio';
import GObject from 'gi://GObject'; import GObject from 'gi://GObject';
@ -54,35 +53,31 @@ export const ExtensionRow = GObject.registerClass({
this.get_root().uninstall(extension); this.get_root().uninstall(extension);
}, },
enabledProp: 'is-user', enabledProp: 'is-user',
}, {
name: 'enabled',
state: 'false',
activate: action => {
const state = action.get_state();
action.change_state(new GLib.Variant('b', !state.get_boolean()));
},
change_state: (a, state) => {
const {uuid} = this._extension;
if (state.get_boolean())
this._app.extensionManager.enableExtension(uuid);
else
this._app.extensionManager.disableExtension(uuid);
},
enabledProp: 'can-change',
}, },
]; ];
this._actionGroup.add_action_entries(actionEntries); this._actionGroup.add_action_entries(actionEntries);
this._bindActionEnabled(actionEntries); this._bindActionEnabled(actionEntries);
this._switch.connect('state-set', (sw, state) => {
const {uuid} = this._extension;
if (state)
this._app.extensionManager.enableExtension(uuid);
else
this._app.extensionManager.disableExtension(uuid);
return true;
});
this._extension.bind_property_full('state',
this._switch, 'state',
GObject.BindingFlags.SYNC_CREATE,
(bind, source) => [true, source === ExtensionState.ACTIVE],
null);
this._extension.bind_property_full('version', this._extension.bind_property_full('version',
this._versionLabel, 'label', this._versionLabel, 'label',
GObject.BindingFlags.SYNC_CREATE, GObject.BindingFlags.SYNC_CREATE,
(bind, source) => [true, _('Version %s').format(source)], (bind, source) => [true, _('Version %s').format(source)],
null); null);
this._extension.connect('notify::state',
() => this._updateState());
this._updateState();
} }
get extension() { get extension() {
@ -113,14 +108,4 @@ export const ExtensionRow = GObject.registerClass({
} }
} }
} }
_updateState() {
const state = this._extension.state === ExtensionState.ACTIVE;
const action = this._actionGroup.lookup_action('enabled');
action.set_state(new GLib.Variant('b', state));
if (!action.enabled)
this._switch.active = state;
}
}); });