VulpesOS/assets/webapps/system.gaiamobile.org/js/attention_toaster.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

207 lines
6.2 KiB
JavaScript

/* global Service */
'use strict';
(function(exports) {
var toasterEvents = ['init', 'open', 'complete', 'terminate', 'close'];
var toasterStateTable = {
'uninit': ['closed', null, null, null, null],
'closed': [null, 'opening', null, 'uninit', null],
'opening': [null, null, 'opened', 'uninit', null],
'opened': [null, null, null, 'uninit', 'closing'],
'closing': [null, 'opening', 'closed', 'uninit', null]
};
/**
* AttentionToaster is a sub component of AttentionWindow
* to help the attention window instance to play like a notification toaster
* and control the toaster's transition state.
* @param {AppWindow} app The app window installing this sub component.
*/
var AttentionToaster = function(app) {
this.app = app;
};
AttentionToaster.prototype = {
_currentToasterState: 'uninit',
TOASTER_TIMEOUT: 5000,
RESPAWN_TIMEOUT: 45000,
start: function() {
this.app.element.addEventListener('_closed', this);
this.app.element.addEventListener('_requestopen', this);
this.app.element.addEventListener('transitionend', this);
this.app.element.addEventListener('_secure-appclosed', this);
this.app.element.addEventListener('_secure-appopened', this);
this.app.element.addEventListener('_lockscreen-appclosed', this);
this.app.element.addEventListener('_lockscreen-appopened', this);
},
stop: function() {
this.app.element.removeEventListener('_closed', this);
this.app.element.removeEventListener('_requestopen', this);
this.app.element.removeEventListener('transitionend', this);
this.app.element.removeEventListener('_secure-appclosed', this);
this.app.element.removeEventListener('_secure-appopened', this);
this.app.element.removeEventListener('_lockscreen-appclosed', this);
this.app.element.removeEventListener('_lockscreen-appopened', this);
},
shouldProcess: function() {
return this.app && this.app.element && !this.app.isHidden() &&
!this.app.isActive() && !this.app.isDead();
},
handleEvent: function(evt) {
if (!this.shouldProcess()) {
this.app.debug('should not process');
return;
}
switch (evt.type) {
case '_lockscreen-appclosed':
case '_secure-appopened':
this.processStateChange('close', evt.type);
break;
case '_requestopen':
this.processStateChange('terminate', evt.type);
break;
case 'transitionend':
if (evt.target !== this.app.element) {
return;
}
this.processStateChange('complete', evt.type);
break;
case '_closed':
window.requestAnimationFrame(() => {
this.processStateChange('init', evt.type);
});
break;
case '_lockscreen-appopened':
case '_secure-appclosed':
this.processStateChange('open', evt.type);
break;
}
},
processStateChange: function(event, reason) {
if (!this.shouldProcess()) {
this.app.debug('should not process ' + event);
return;
}
var eventIndex = toasterEvents.indexOf(event);
var nextState =
toasterStateTable[this._currentToasterState][eventIndex];
this.app.debug(this._currentToasterState + ' -> ' + nextState);
if (!nextState) {
return;
}
this.app.debug('[toaster] ' +
this._currentToasterState + '->' + nextState +
':' + event + ',' + reason);
this._currentToasterState = nextState;
this.app.element.setAttribute('toaster-transition-state',
this._currentToasterState);
if (typeof(this['_enter_' + nextState]) == 'function') {
this['_enter_' + nextState](event);
}
},
_enter_closing: function() {
if (!this.app || !this.app.element ||
(Service && Service.query('locked') &&
!Service.query('getTopMostWindow').isFullScreen())) {
return;
}
this.app.element.classList.remove('displayed');
},
_enter_closed: function(evt) {
if (!this.app || !this.app.element) {
return;
}
if (evt == 'init') {
this.becomeToaster();
this.app.tryWaitForFullRepaint(function() {
this.processStateChange('open', 'repainted');
}.bind(this));
} else if (evt == 'complete') {
this.app && this.app.setVisible(false);
this.respawnTimer = window.setTimeout(function() {
this.processStateChange('open', 'respawn');
}.bind(this), this.RESPAWN_TIMEOUT);
}
},
_enter_opened: function() {
if (!this.app || !this.app.element) {
return;
}
this.app && this.app.setVisible(true);
this._toasterTimer = window.setTimeout(function() {
if (Service && Service.query('locked') &&
!Service.query('getTopMostWindow').isFullScreen()) {
return;
}
this.processStateChange('close', 'timeout');
}.bind(this), this.TOASTER_TIMEOUT);
},
_enter_opening: function() {
if (!this.app || !this.app.element) {
return;
}
window.clearTimeout(this.respawnTimer);
this.respawnTimer = null;
this.app.setVisible(true);
this.app.element.classList.add('displayed');
},
_enter_uninit: function() {
if (!this.app || !this.app.element) {
return;
}
if (this._toasterTimer) {
window.clearTimeout(this._toasterTimer);
this._toasterTimer = null;
}
this.recoverLayout();
},
recoverLayout: function() {
if (this.app && this.app.resized) {
this.app.element.classList.remove('displayed');
this.app.element.classList.remove('toaster-mode');
this.app.resized = false;
this.app.publish('recovering');
this.app._resize();
}
},
becomeToaster: function() {
if (!this.shouldProcess()) {
return;
}
// Override the resized height anyway
this.app.element.style.height = this.app.closedHeight + 'px';
this.app.element.classList.add('toaster-mode');
this.app.resized = true;
}
};
exports.AttentionToaster = AttentionToaster;
}(window));