VulpesOS/gaia/apps/email/js/ext/slice_bridge_proxy.js
OverSu b38dea0597 Publish Vulpes Preview 15 sources for desktop, Android and Tundra
Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
2026-09-30 23:13:03 +02:00

158 lines
4.6 KiB
JavaScript
Executable file

/*global define */
define(
[
'exports'
],
function(
exports
) {
/**
* The abstraction for back-end slices to talk to front-end slices.
*
* Consolidates communication which allows us to provide transparent batching
* to our multiple varieties of slices as well as allowing for us to be hacked
* up to not actually send anything anywhere.
*
* The types of slices we support are:
* - The main `MailSlice` implementation in mailslice.js
* - The filtering `SearchSlice` implementation in searchfilter.js
* - The cronsync.js use-case that uses us to be able to hook up a normal
* `MailSlice` without there actually being anything to listen to what it
* says. It gives us a minimal/fake MailBridge that has a no-op
* __sendMessage.
*
* If you change this class, you want to make sure you've considered those
* slices and their tests too.
*/
function SliceBridgeProxy(bridge, ns, handle) {
this._bridge = bridge;
this._ns = ns;
this._handle = handle;
this.__listener = null;
this.status = 'synced';
this.progress = 0.0;
this.atTop = false;
this.atBottom = false;
this.headerCount = 0;
/**
* Can we potentially grow the slice in the negative direction if explicitly
* desired by the user or UI desires to be up-to-date? For example,
* triggering an IMAP sync.
*
* This is only really meaningful when `atTop` is true; if we are not at the
* top then this value will be false.
*
* For messages, the implication is that we are not synchronized through 'now'
* if this value is true (and atTop is true).
*/
this.userCanGrowUpwards = false;
this.userCanGrowDownwards = false;
/**
* We batch both slices and updates into the same queue. The MailAPI checks
* to differentiate between the two.
*/
this.pendingUpdates = [];
this.scheduledUpdate = false;
}
exports.SliceBridgeProxy = SliceBridgeProxy;
SliceBridgeProxy.prototype = {
/**
* Issue a splice to add and remove items.
* @param {number} newEmailCount Number of new emails synced during this
* slice request.
*/
sendSplice: function sbp_sendSplice(index, howMany, addItems, requested,
moreExpected, newEmailCount) {
var updateSplice = {
index: index,
howMany: howMany,
addItems: addItems,
requested: requested,
moreExpected: moreExpected,
newEmailCount: newEmailCount,
// send header count here instead of batchSlice,
// since need an accurate count for each splice
// call: there could be two splices for the 0
// index in a row, and setting count on the
// batchSlice will not give an accurate picture
// that the slice actions are growing the slice.
headerCount: this.headerCount,
type: 'slice'
};
this.addUpdate(updateSplice);
},
/**
* Issue an update for existing items.
*
* @param {Array[]} indexUpdatesRun
* Flattened pairs of index and the updated object wire representation.
*/
sendUpdate: function sbp_sendUpdate(indexUpdatesRun) {
var update = {
updates: indexUpdatesRun,
type: 'update',
};
this.addUpdate(update);
},
/**
* @param {number} newEmailCount Number of new emails synced during this
* slice request.
*/
sendStatus: function sbp_sendStatus(status, requested, moreExpected,
progress, newEmailCount) {
this.status = status;
if (progress != null) {
this.progress = progress;
}
this.sendSplice(0, 0, [], requested, moreExpected, newEmailCount);
},
sendSyncProgress: function(progress) {
this.progress = progress;
this.sendSplice(0, 0, [], true, true);
},
addUpdate: function sbp_addUpdate(update) {
this.pendingUpdates.push(update);
// If we batched a lot, flush now. Otherwise
// we sometimes get into a position where nothing happens
// and then a bunch of updates occur, causing jank
if (this.pendingUpdates.length > 5) {
this.flushUpdates();
} else if (!this.scheduledUpdate) {
window.setZeroTimeout(this.flushUpdates.bind(this));
this.scheduledUpdate = true;
}
},
flushUpdates: function sbp_flushUpdates() {
this._bridge.__sendMessage({
type: 'batchSlice',
handle: this._handle,
status: this.status,
progress: this.progress,
atTop: this.atTop,
atBottom: this.atBottom,
userCanGrowUpwards: this.userCanGrowUpwards,
userCanGrowDownwards: this.userCanGrowDownwards,
sliceUpdates: this.pendingUpdates
});
this.pendingUpdates = [];
this.scheduledUpdate = false;
},
die: function sbp_die() {
if (this.__listener)
this.__listener.die();
},
};
});