summaryrefslogtreecommitdiffstats
path: root/extensions/vertical-workspaces/lib/search.js
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/vertical-workspaces/lib/search.js')
-rw-r--r--extensions/vertical-workspaces/lib/search.js206
1 files changed, 206 insertions, 0 deletions
diff --git a/extensions/vertical-workspaces/lib/search.js b/extensions/vertical-workspaces/lib/search.js
new file mode 100644
index 0000000..8540626
--- /dev/null
+++ b/extensions/vertical-workspaces/lib/search.js
@@ -0,0 +1,206 @@
+/**
+ * V-Shell (Vertical Workspaces)
+ * search.js
+ *
+ * @author GdH <G-dH@github.com>
+ * @copyright 2022 - 2023
+ * @license GPL-3.0
+ *
+ */
+
+'use strict';
+const { Shell, Gio, St, Clutter } = imports.gi;
+const Main = imports.ui.main;
+
+const AppDisplay = imports.ui.appDisplay;
+const Search = imports.ui.search;
+
+const Me = imports.misc.extensionUtils.getCurrentExtension();
+const _Util = Me.imports.lib.util;
+
+const _ = Me.imports.lib.settings._;
+const shellVersion = _Util.shellVersion;
+
+let opt;
+let _overrides;
+let _firstRun = true;
+
+let SEARCH_MAX_WIDTH;
+
+function update(reset = false) {
+ opt = Me.imports.lib.settings.opt;
+ const moduleEnabled = opt.get('searchModule', true);
+ reset = reset || !moduleEnabled;
+
+ // don't even touch this module if disabled
+ if (_firstRun && reset)
+ return;
+
+ _firstRun = false;
+
+ if (_overrides)
+ _overrides.removeAll();
+
+ _updateSearchViewWidth(reset);
+
+ if (reset) {
+ Main.overview._overview._controls.layoutManager._searchController.y_align = Clutter.ActorAlign.FILL;
+ opt = null;
+ _overrides = null;
+ return;
+ }
+
+ _overrides = new _Util.Overrides();
+
+ _overrides.addOverride('AppSearchProvider', AppDisplay.AppSearchProvider.prototype, AppSearchProvider);
+ _overrides.addOverride('SearchResult', Search.SearchResult.prototype, SearchResult);
+ _overrides.addOverride('SearchResultsView', Search.SearchResultsView.prototype, SearchResultsView);
+
+ // Don't expand the search view vertically and align it to the top
+ // this is important in the static workspace mode when the search view bg is not transparent
+ // also the "Searching..." and "No Results" notifications will be closer to the search entry, with the distance given by margin-top in the stylesheet
+ Main.overview._overview._controls.layoutManager._searchController.y_align = Clutter.ActorAlign.START;
+}
+
+function _updateSearchViewWidth(reset = false) {
+ const searchContent = Main.overview._overview._controls.layoutManager._searchController._searchResults._content;
+ if (!SEARCH_MAX_WIDTH) { // just store original value;
+ const themeNode = searchContent.get_theme_node();
+ const width = themeNode.get_max_width();
+ SEARCH_MAX_WIDTH = width;
+ }
+
+ if (reset) {
+ searchContent.set_style('');
+ } else {
+ let width = Math.round(SEARCH_MAX_WIDTH * opt.SEARCH_VIEW_SCALE);
+ searchContent.set_style(`max-width: ${width}px;`);
+ }
+}
+
+// AppDisplay.AppSearchProvider
+const AppSearchProvider = {
+ getInitialResultSet(terms, callback, _cancellable) {
+ // Defer until the parental controls manager is initialized, so the
+ // results can be filtered correctly.
+ if (!this._parentalControlsManager.initialized) {
+ let initializedId = this._parentalControlsManager.connect('app-filter-changed', () => {
+ if (this._parentalControlsManager.initialized) {
+ this._parentalControlsManager.disconnect(initializedId);
+ this.getInitialResultSet(terms, callback, _cancellable);
+ }
+ });
+ return;
+ }
+
+
+ const pattern = terms.join(' ');
+ let appInfoList = Shell.AppSystem.get_default().get_installed();
+
+ let weightList = {};
+ appInfoList = appInfoList.filter(appInfo => {
+ try {
+ appInfo.get_id(); // catch invalid file encodings
+ } catch (e) {
+ return false;
+ }
+
+ let string = '';
+ let name;
+ let shouldShow = false;
+ if (appInfo.get_display_name) {
+ // show only launchers that should be visible in this DE
+ shouldShow = appInfo.should_show() && this._parentalControlsManager.shouldShowApp(appInfo);
+
+ if (shouldShow) {
+ let dispName = appInfo.get_display_name() || '';
+ let gName = appInfo.get_generic_name() || '';
+ let description = appInfo.get_description() || '';
+ let categories = appInfo.get_string('Categories') || '';
+ let keywords = appInfo.get_string('Keywords') || '';
+ name = dispName;
+ string = `${dispName} ${gName} ${description} ${categories} ${keywords}`;
+ }
+ }
+
+ let m = -1;
+ if (shouldShow && opt.SEARCH_FUZZY) {
+ m = _Util.fuzzyMatch(pattern, name);
+ m = (m + _Util.strictMatch(pattern, string)) / 2;
+ } else if (shouldShow) {
+ m = _Util.strictMatch(pattern, string);
+ }
+
+ if (m !== -1)
+ weightList[appInfo.get_id()] = m;
+
+ return shouldShow && (m !== -1);
+ });
+
+ appInfoList.sort((a, b) => weightList[a.get_id()] > weightList[b.get_id()]);
+
+ const usage = Shell.AppUsage.get_default();
+ // sort apps by usage list
+ appInfoList.sort((a, b) => usage.compare(a.get_id(), b.get_id()));
+ // prefer apps where any word in their name starts with the pattern
+ appInfoList.sort((a, b) => _Util.isMoreRelevant(a.get_display_name(), b.get_display_name(), pattern));
+
+ let results = appInfoList.map(app => app.get_id());
+
+ results = results.concat(this._systemActions.getMatchingActions(terms));
+
+ if (shellVersion < 43)
+ callback(results);
+ else
+ return new Promise(resolve => resolve(results));
+ },
+
+ // App search result size
+ createResultObject(resultMeta) {
+ if (resultMeta.id.endsWith('.desktop')) {
+ const icon = new AppDisplay.AppIcon(this._appSys.lookup_app(resultMeta['id']), {
+ expandTitleOnHover: false,
+ });
+ icon.icon.setIconSize(opt.SEARCH_ICON_SIZE);
+ return icon;
+ } else {
+ const icon = new AppDisplay.SystemActionIcon(this, resultMeta);
+ icon.icon._setSizeManually = true;
+ icon.icon.setIconSize(opt.SEARCH_ICON_SIZE);
+ return icon;
+ }
+ },
+};
+
+const SearchResult = {
+ activate() {
+ this.provider.activateResult(this.metaInfo.id, this._resultsView.terms);
+
+ if (this.metaInfo.clipboardText) {
+ St.Clipboard.get_default().set_text(
+ St.ClipboardType.CLIPBOARD, this.metaInfo.clipboardText);
+ }
+ // don't close overview if Shift key is pressed - Shift moves windows to the workspace
+ if (!_Util.isShiftPressed())
+ Main.overview.toggle();
+ },
+};
+
+const SearchResultsView = {
+ _updateSearchProgress() {
+ let haveResults = this._providers.some(provider => {
+ let display = provider.display;
+ return display.getFirstResult() !== null;
+ });
+
+ this._scrollView.visible = haveResults;
+ this._statusBin.visible = !haveResults;
+
+ if (!haveResults) {
+ if (this.searchInProgress)
+ this._statusText.set_text(_('Searching…'));
+ else
+ this._statusText.set_text(_('No results.'));
+ }
+ },
+};