status/network: Add ItemSorter option to track MRU

We always display items sorted by name, but there are cases where a
second order by recency is interesting. Add an option to ItemSorter
to keep such a list and allow accessing it with another generator
function.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2407>
This commit is contained in:
Florian Müllner 2022-08-03 08:12:28 +02:00 committed by Marge Bot
parent a3dbb3e71f
commit 911762ea54

View File

@ -93,28 +93,58 @@ class ItemSorter {
* Maintains a list of sorted items. By default, items are * Maintains a list of sorted items. By default, items are
* assumed to be objects with a name property. * assumed to be objects with a name property.
* *
* Optionally items can have a secondary sort order by
* recency. If used, items must by objects with a timestamp
* property that can be used in substraction, and "bigger"
* must mean "more recent". Number and Date both qualify.
*
* @param {object=} options - property object with options * @param {object=} options - property object with options
* @param {Function} options.sortFunc - a custom sort function * @param {Function} options.sortFunc - a custom sort function
* @param {bool} options.trackMru - whether to track MRU order as well
**/ **/
constructor(options = {}) { constructor(options = {}) {
const {sortFunc} = { const {sortFunc, trackMru} = {
sortFunc: this._sortByName.bind(this), sortFunc: this._sortByName.bind(this),
trackMru: false,
...options, ...options,
}; };
this._trackMru = trackMru;
this._sortFunc = sortFunc; this._sortFunc = sortFunc;
this._sortFuncMru = this._sortByMru.bind(this);
this._itemsOrder = []; this._itemsOrder = [];
this._itemsMruOrder = [];
} }
*items() { *items() {
yield* this._itemsOrder; yield* this._itemsOrder;
} }
*itemsByMru() {
console.assert(this._trackMru, 'itemsByMru: MRU tracking is disabled');
yield* this._itemsMruOrder;
}
_sortByName(one, two) { _sortByName(one, two) {
return GLib.utf8_collate(one.name, two.name); return GLib.utf8_collate(one.name, two.name);
} }
_sortByMru(one, two) {
return two.timestamp - one.timestamp;
}
_upsert(array, item, sortFunc) {
this._delete(array, item);
return Util.insertSorted(array, item, sortFunc);
}
_delete(array, item) {
const pos = array.indexOf(item);
if (pos >= 0)
array.splice(pos, 1);
}
/** /**
* Insert or update item. * Insert or update item.
* *
@ -122,17 +152,19 @@ class ItemSorter {
* @returns {number} - the sorted position of item * @returns {number} - the sorted position of item
*/ */
upsert(item) { upsert(item) {
this.delete(item); if (this._trackMru)
return Util.insertSorted(this._itemsOrder, item, this._sortFunc); this._upsert(this._itemsMruOrder, item, this._sortFuncMru);
return this._upsert(this._itemsOrder, item, this._sortFunc);
} }
/** /**
* @param {any} item - item to remove * @param {any} item - item to remove
*/ */
delete(item) { delete(item) {
const pos = this._itemsOrder.indexOf(item); if (this._trackMru)
if (pos >= 0) this._delete(this._itemsMruOrder, item);
this._itemsOrder.splice(pos, 1); this._delete(this._itemsOrder, item);
} }
} }