[gnome-shell] extensions-app: Add extension filtering
- From: Georges Basile Stavracas Neto <gbsneto src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell] extensions-app: Add extension filtering
- Date: Thu, 12 Nov 2020 22:11:57 +0000 (UTC)
commit 9ef59b3b4fd3a12c22091cec7f8020c0d5792138
Author: Florian Müllner <fmuellner gnome org>
Date: Wed Nov 11 02:37:20 2020 +0100
extensions-app: Add extension filtering
It's possible for the list of installed extension to get long
enough to make searching more convenient than scrolling.
Support that by implementing the standard search pattern[0]
with a hidden search bar and a toggle in the headerbar.
[0] https://developer.gnome.org/hig/stable/search.html.en
https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/3382
.../extensions-app/data/ui/extensions-window.ui | 31 ++++++++++++++
subprojects/extensions-app/js/main.js | 48 ++++++++++++++++++++++
2 files changed, 79 insertions(+)
---
diff --git a/subprojects/extensions-app/data/ui/extensions-window.ui
b/subprojects/extensions-app/data/ui/extensions-window.ui
index dd36924484..1ae5bfc991 100644
--- a/subprojects/extensions-app/data/ui/extensions-window.ui
+++ b/subprojects/extensions-app/data/ui/extensions-window.ui
@@ -89,6 +89,22 @@
<property name="pack_type">end</property>
</packing>
</child>
+ <child>
+ <object class="GtkToggleButton" id="searchButton">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <child>
+ <object class="GtkImage">
+ <property name="visible">True</property>
+ <property name="icon_name">edit-find-symbolic</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="pack_type">end</property>
+ </packing>
+ </child>
<child>
<object class="GtkSwitch">
<property name="visible">True</property>
@@ -105,6 +121,21 @@
<object class="GtkBox">
<property name="visible">True</property>
<property name="orientation">vertical</property>
+ <child>
+ <object class="GtkSearchBar" id="searchBar">
+ <property name="visible">True</property>
+ <property name="search-mode-enabled"
+ bind-source="searchButton"
+ bind-property="active"
+ bind-flags="bidirectional"/>
+ <child>
+ <object class="GtkSearchEntry" id="searchEntry">
+ <property name="visible">True</property>
+ <property name="max-width-chars">35</property>
+ </object>
+ </child>
+ </object>
+ </child>
<child>
<object class="GtkStack" id="mainStack">
<property name="visible">True</property>
diff --git a/subprojects/extensions-app/js/main.js b/subprojects/extensions-app/js/main.js
index 2e8b01804b..31a717df7f 100644
--- a/subprojects/extensions-app/js/main.js
+++ b/subprojects/extensions-app/js/main.js
@@ -89,6 +89,9 @@ var ExtensionsWindow = GObject.registerClass({
'mainBox',
'mainStack',
'scrolledWindow',
+ 'searchBar',
+ 'searchButton',
+ 'searchEntry',
'updatesBar',
'updatesLabel',
],
@@ -122,11 +125,45 @@ var ExtensionsWindow = GObject.registerClass({
});
this.add_action(action);
+ const accelGroup = new Gtk.AccelGroup();
+ this._searchButton.add_accelerator('clicked',
+ accelGroup, Gdk.KEY_f, Gdk.ModifierType.CONTROL_MASK, 0);
+ this._searchButton.add_accelerator('clicked',
+ accelGroup, Gdk.KEY_s, Gdk.ModifierType.CONTROL_MASK, 0);
+ this.add_accel_group(accelGroup);
+
+ this.connect('key-press-event',
+ (w, event) => this._searchBar.handle_event(event));
+
+ this._searchTerms = [];
+ this._searchEntry.connect('search-changed', () => {
+ const { text } = this._searchEntry;
+ if (text === '')
+ this._searchTerms = [];
+ else
+ [this._searchTerms] = GLib.str_tokenize_and_fold(text, null);
+
+ this._userList.invalidate_filter();
+ this._systemList.invalidate_filter();
+ });
+
this._userList.set_sort_func(this._sortList.bind(this));
this._userList.set_header_func(this._updateHeader.bind(this));
+ this._userList.set_filter_func(this._filterList.bind(this));
+ this._userList.set_placeholder(new Gtk.Label({
+ label: _('No Matches'),
+ margin: 12,
+ visible: true,
+ }));
this._systemList.set_sort_func(this._sortList.bind(this));
this._systemList.set_header_func(this._updateHeader.bind(this));
+ this._systemList.set_filter_func(this._filterList.bind(this));
+ this._systemList.set_placeholder(new Gtk.Label({
+ label: _('No Matches'),
+ margin: 12,
+ visible: true,
+ }));
this._shellProxy.connectSignal('ExtensionStateChanged',
this._onExtensionStateChanged.bind(this));
@@ -215,6 +252,11 @@ var ExtensionsWindow = GObject.registerClass({
return row1.name.localeCompare(row2.name);
}
+ _filterList(row) {
+ return this._searchTerms.every(
+ t => row.keywords.some(k => k.startsWith(t)));
+ }
+
_updateHeader(row, before) {
if (!before || row.get_header())
return;
@@ -352,6 +394,8 @@ var ExtensionRow = GObject.registerClass({
this._extension = extension;
this._prefsModule = null;
+ [this._keywords] = GLib.str_tokenize_and_fold(this.name, null);
+
this._actionGroup = new Gio.SimpleActionGroup();
this.insert_action_group('row', this._actionGroup);
@@ -470,6 +514,10 @@ var ExtensionRow = GObject.registerClass({
? this._extension.error : _('The extension had an error');
}
+ get keywords() {
+ return this._keywords;
+ }
+
_updateState() {
let state = this._extension.state === ExtensionState.ENABLED;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]