search: Use async functions instead of callbacks
Our search provider API has to be asynchronous to support remote providers. It doesn't have to be based on callbacks though, now that async functions provide a nicer alternative. That is particularly true after gjs's D-Bus wrapper started to generate promise-based method variants. Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2344>
This commit is contained in:
parent
1cce999c30
commit
119581a4cb
@ -1825,7 +1825,7 @@ var AppSearchProvider = class AppSearchProvider {
|
||||
this._parentalControlsManager = ParentalControlsManager.getDefault();
|
||||
}
|
||||
|
||||
getResultMetas(apps, callback) {
|
||||
getResultMetas(apps) {
|
||||
const { scaleFactor } = St.ThemeContext.get_for_stage(global.stage);
|
||||
let metas = [];
|
||||
for (let id of apps) {
|
||||
@ -1852,24 +1852,25 @@ var AppSearchProvider = class AppSearchProvider {
|
||||
}
|
||||
}
|
||||
|
||||
callback(metas);
|
||||
return new Promise(resolve => resolve(metas));
|
||||
}
|
||||
|
||||
filterResults(results, maxNumber) {
|
||||
return results.slice(0, maxNumber);
|
||||
}
|
||||
|
||||
getInitialResultSet(terms, callback, _cancellable) {
|
||||
getInitialResultSet(terms, cancellable) {
|
||||
// Defer until the parental controls manager is initialised, 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 new Promise(resolve => {
|
||||
let initializedId = this._parentalControlsManager.connect('app-filter-changed', async () => {
|
||||
if (this._parentalControlsManager.initialized) {
|
||||
this._parentalControlsManager.disconnect(initializedId);
|
||||
resolve(await this.getInitialResultSet(terms, cancellable));
|
||||
}
|
||||
});
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
let query = terms.join(' ');
|
||||
@ -1887,12 +1888,11 @@ var AppSearchProvider = class AppSearchProvider {
|
||||
});
|
||||
|
||||
results = results.concat(this._systemActions.getMatchingActions(terms));
|
||||
|
||||
callback(results);
|
||||
return new Promise(resolve => resolve(results));
|
||||
}
|
||||
|
||||
getSubsearchResultSet(previousResults, terms, callback, cancellable) {
|
||||
this.getInitialResultSet(terms, callback, cancellable);
|
||||
getSubsearchResultSet(previousResults, terms, cancellable) {
|
||||
return this.getInitialResultSet(terms, cancellable);
|
||||
}
|
||||
|
||||
createResultObject(resultMeta) {
|
||||
|
@ -250,48 +250,43 @@ var RemoteSearchProvider = class {
|
||||
return regularResults.slice(0, maxNumber).concat(specialResults.slice(0, maxNumber));
|
||||
}
|
||||
|
||||
_getResultsFinished(results, error, callback) {
|
||||
if (error) {
|
||||
if (error.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
|
||||
return;
|
||||
|
||||
log(`Received error from D-Bus search provider ${this.id}: ${error}`);
|
||||
callback([]);
|
||||
return;
|
||||
async getInitialResultSet(terms, cancellable) {
|
||||
try {
|
||||
const [results] = await this.proxy.GetInitialResultSetAsync(terms, cancellable);
|
||||
return results;
|
||||
} catch (error) {
|
||||
if (!error.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
|
||||
log(`Received error from D-Bus search provider ${this.id}: ${error}`);
|
||||
return [];
|
||||
}
|
||||
|
||||
callback(results[0]);
|
||||
}
|
||||
|
||||
getInitialResultSet(terms, callback, cancellable) {
|
||||
this.proxy.GetInitialResultSetRemote(terms,
|
||||
(results, error) => {
|
||||
this._getResultsFinished(results, error, callback);
|
||||
},
|
||||
cancellable);
|
||||
async getSubsearchResultSet(previousResults, newTerms, cancellable) {
|
||||
try {
|
||||
const [results] = await this.proxy.GetSubsearchResultSetAsync(previousResults, newTerms, cancellable);
|
||||
return results;
|
||||
} catch (error) {
|
||||
if (!error.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
|
||||
log(`Received error from D-Bus search provider ${this.id}: ${error}`);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
getSubsearchResultSet(previousResults, newTerms, callback, cancellable) {
|
||||
this.proxy.GetSubsearchResultSetRemote(previousResults, newTerms,
|
||||
(results, error) => {
|
||||
this._getResultsFinished(results, error, callback);
|
||||
},
|
||||
cancellable);
|
||||
}
|
||||
|
||||
_getResultMetasFinished(results, error, callback) {
|
||||
if (error) {
|
||||
async getResultMetas(ids, cancellable) {
|
||||
let metas;
|
||||
try {
|
||||
[metas] = await this.proxy.GetResultMetasAsync(ids, cancellable);
|
||||
} catch (error) {
|
||||
if (!error.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
|
||||
log(`Received error from D-Bus search provider ${this.id} during GetResultMetas: ${error}`);
|
||||
callback([]);
|
||||
return;
|
||||
return [];
|
||||
}
|
||||
let metas = results[0];
|
||||
|
||||
let resultMetas = [];
|
||||
for (let i = 0; i < metas.length; i++) {
|
||||
for (let prop in metas[i]) {
|
||||
// we can use the serialized icon variant directly
|
||||
if (prop != 'icon')
|
||||
if (prop !== 'icon')
|
||||
metas[i][prop] = metas[i][prop].deep_unpack();
|
||||
}
|
||||
|
||||
@ -303,15 +298,7 @@ var RemoteSearchProvider = class {
|
||||
clipboardText: metas[i]['clipboardText'],
|
||||
});
|
||||
}
|
||||
callback(resultMetas);
|
||||
}
|
||||
|
||||
getResultMetas(ids, callback, cancellable) {
|
||||
this.proxy.GetResultMetasRemote(ids,
|
||||
(results, error) => {
|
||||
this._getResultMetasFinished(results, error, callback);
|
||||
},
|
||||
cancellable);
|
||||
return resultMetas;
|
||||
}
|
||||
|
||||
activateResult(id) {
|
||||
|
118
js/ui/search.js
118
js/ui/search.js
@ -208,47 +208,40 @@ var SearchResultsBase = GObject.registerClass({
|
||||
_setMoreCount(_count) {
|
||||
}
|
||||
|
||||
_ensureResultActors(results, callback) {
|
||||
async _ensureResultActors(results) {
|
||||
let metasNeeded = results.filter(
|
||||
resultId => this._resultDisplays[resultId] === undefined);
|
||||
|
||||
if (metasNeeded.length === 0) {
|
||||
callback(true);
|
||||
} else {
|
||||
this._cancellable.cancel();
|
||||
this._cancellable.reset();
|
||||
if (metasNeeded.length === 0)
|
||||
return;
|
||||
|
||||
this.provider.getResultMetas(metasNeeded, metas => {
|
||||
if (this._cancellable.is_cancelled()) {
|
||||
if (metas.length > 0)
|
||||
log(`Search provider ${this.provider.id} returned results after the request was canceled`);
|
||||
callback(false);
|
||||
return;
|
||||
}
|
||||
if (metas.length != metasNeeded.length) {
|
||||
log(`Wrong number of result metas returned by search provider ${this.provider.id}: ` +
|
||||
`expected ${metasNeeded.length} but got ${metas.length}`);
|
||||
callback(false);
|
||||
return;
|
||||
}
|
||||
if (metas.some(meta => !meta.name || !meta.id)) {
|
||||
log(`Invalid result meta returned from search provider ${this.provider.id}`);
|
||||
callback(false);
|
||||
return;
|
||||
}
|
||||
this._cancellable.cancel();
|
||||
this._cancellable.reset();
|
||||
|
||||
metasNeeded.forEach((resultId, i) => {
|
||||
let meta = metas[i];
|
||||
let display = this._createResultDisplay(meta);
|
||||
display.connect('key-focus-in', this._keyFocusIn.bind(this));
|
||||
this._resultDisplays[resultId] = display;
|
||||
});
|
||||
callback(true);
|
||||
}, this._cancellable);
|
||||
const metas = await this.provider.getResultMetas(metasNeeded, this._cancellable);
|
||||
|
||||
if (this._cancellable.is_cancelled()) {
|
||||
if (metas.length > 0)
|
||||
throw new Error(`Search provider ${this.provider.id} returned results after the request was canceled`);
|
||||
}
|
||||
|
||||
if (metas.length !== metasNeeded.length) {
|
||||
throw new Error(`Wrong number of result metas returned by search provider ${this.provider.id}: ` +
|
||||
`expected ${metasNeeded.length} but got ${metas.length}`);
|
||||
}
|
||||
|
||||
if (metas.some(meta => !meta.name || !meta.id))
|
||||
throw new Error(`Invalid result meta returned from search provider ${this.provider.id}`);
|
||||
|
||||
metasNeeded.forEach((resultId, i) => {
|
||||
let meta = metas[i];
|
||||
let display = this._createResultDisplay(meta);
|
||||
display.connect('key-focus-in', this._keyFocusIn.bind(this));
|
||||
this._resultDisplays[resultId] = display;
|
||||
});
|
||||
}
|
||||
|
||||
updateSearch(providerResults, terms, callback) {
|
||||
async updateSearch(providerResults, terms, callback) {
|
||||
this._terms = terms;
|
||||
if (providerResults.length == 0) {
|
||||
this._clearResultDisplay();
|
||||
@ -261,25 +254,23 @@ var SearchResultsBase = GObject.registerClass({
|
||||
: providerResults;
|
||||
let moreCount = Math.max(providerResults.length - results.length, 0);
|
||||
|
||||
this._ensureResultActors(results, successful => {
|
||||
if (!successful) {
|
||||
this._clearResultDisplay();
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await this._ensureResultActors(results);
|
||||
|
||||
// To avoid CSS transitions causing flickering when
|
||||
// the first search result stays the same, we hide the
|
||||
// content while filling in the results.
|
||||
this.hide();
|
||||
this._clearResultDisplay();
|
||||
results.forEach(resultId => {
|
||||
this._addItem(this._resultDisplays[resultId]);
|
||||
});
|
||||
results.forEach(
|
||||
resultId => this._addItem(this._resultDisplays[resultId]));
|
||||
this._setMoreCount(this.provider.canLaunchSearch ? moreCount : 0);
|
||||
this.show();
|
||||
callback();
|
||||
});
|
||||
} catch (e) {
|
||||
this._clearResultDisplay();
|
||||
callback();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -638,11 +629,6 @@ var SearchResultsView = GObject.registerClass({
|
||||
provider.display.destroy();
|
||||
}
|
||||
|
||||
_gotResults(results, provider) {
|
||||
this._results[provider.id] = results;
|
||||
this._updateResults(provider, results);
|
||||
}
|
||||
|
||||
_clearSearchTimeout() {
|
||||
if (this._searchTimeoutId > 0) {
|
||||
GLib.source_remove(this._searchTimeoutId);
|
||||
@ -661,6 +647,25 @@ var SearchResultsView = GObject.registerClass({
|
||||
this._updateSearchProgress();
|
||||
}
|
||||
|
||||
async _doProviderSearch(provider, previousResults) {
|
||||
provider.searchInProgress = true;
|
||||
|
||||
let results;
|
||||
if (this._isSubSearch && previousResults) {
|
||||
results = await provider.getSubsearchResultSet(
|
||||
previousResults,
|
||||
this._terms,
|
||||
this._cancellable);
|
||||
} else {
|
||||
results = await provider.getInitialResultSet(
|
||||
this._terms,
|
||||
this._cancellable);
|
||||
}
|
||||
|
||||
this._results[provider.id] = results;
|
||||
this._updateResults(provider, results);
|
||||
}
|
||||
|
||||
_doSearch() {
|
||||
this._startingSearch = false;
|
||||
|
||||
@ -668,23 +673,8 @@ var SearchResultsView = GObject.registerClass({
|
||||
this._results = {};
|
||||
|
||||
this._providers.forEach(provider => {
|
||||
provider.searchInProgress = true;
|
||||
|
||||
let previousProviderResults = previousResults[provider.id];
|
||||
if (this._isSubSearch && previousProviderResults) {
|
||||
provider.getSubsearchResultSet(previousProviderResults,
|
||||
this._terms,
|
||||
results => {
|
||||
this._gotResults(results, provider);
|
||||
},
|
||||
this._cancellable);
|
||||
} else {
|
||||
provider.getInitialResultSet(this._terms,
|
||||
results => {
|
||||
this._gotResults(results, provider);
|
||||
},
|
||||
this._cancellable);
|
||||
}
|
||||
this._doProviderSearch(provider, previousProviderResults);
|
||||
});
|
||||
|
||||
this._updateSearchProgress();
|
||||
|
Loading…
Reference in New Issue
Block a user