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

312 lines
10 KiB
JavaScript

/* globals Service, BaseModule,
DialerAgent */
'use strict';
(function(exports) {
var AttentionWindowManager = function() {};
AttentionWindowManager.prototype = {
DEBUG: false,
TRACE: false,
name: 'AttentionWindowManager',
_openedInstances: null,
EVENT_PREFIX: 'attentionwindowmanager',
publish: function vm_publish(eventName, detail) {
this.debug('publishing: ', eventName);
var evt = new CustomEvent(this.EVENT_PREFIX + eventName,
{ detail: detail });
window.dispatchEvent(evt);
},
debug: function aw_debug() {
if (this.DEBUG) {
console.log('[' + this.name + ']' +
'[' + Service.currentTime() + '] ' +
Array.slice(arguments).concat());
if (this.TRACE) {
console.trace();
}
}
},
isActive: function() {
return this.hasActiveWindow();
},
hasActiveWindow: function attwm_hasActiveWindow() {
return (this._openedInstances.size !== 0);
},
getActiveWindow: function() {
return this.getTopMostWindow();
},
getTopMostWindow: function attwm_hasActiveWindow() {
return this._topMostWindow;
},
respondToHierarchyEvent: function(evt) {
if (this['_handle_' + evt.type]) {
return this['_handle_' + evt.type](evt);
} else {
return true;
}
},
_handle_home: function(evt) {
if (!this.hasActiveWindow()) {
return true;
}
this._topMostWindow = null;
var nextApp = Service.query('getHomescreen');
if (Service.query('locked')) {
this.closeAllAttentionWindows();
} else if (nextApp && !nextApp.isDead()) {
nextApp.ready(this.closeAllAttentionWindows.bind(this));
} else {
this.closeAllAttentionWindows();
}
return true;
},
'_handle_system-resize': function(evt) {
if (this._topMostWindow) {
var p = this._topMostWindow.resize();
if (typeof evt.detail.waitUntil === 'function') {
evt.detail.waitUntil(p);
}
return false;
}
return true;
},
_handle_holdhome: function() {
if (this.isActive()) {
this._topMostWindow = null;
this.closeAllAttentionWindows();
}
return true;
},
/**
* Return current alive attention window instances in a map.
* @return {Map} The attention window map
*/
getInstances: function() {
return this._instances;
},
screen: document.getElementById('screen'),
start: function attwm_start() {
this._instances = [];
this._openedInstances = new Map();
window.addEventListener('attentioncreated', this);
window.addEventListener('attentionterminated', this);
window.addEventListener('attentionshown', this);
window.addEventListener('attentionopening', this);
window.addEventListener('attentionopened', this);
window.addEventListener('attentionclosed', this);
window.addEventListener('attentionclosing', this);
window.addEventListener('attentionrequestopen', this);
window.addEventListener('attentionrequestclose', this);
window.addEventListener('emergencyalert', this);
window.addEventListener('launchapp', this);
window.addEventListener('lockscreen-appclosed', this);
window.addEventListener('lockscreen-appopened', this);
window.addEventListener('secure-appclosed', this);
window.addEventListener('secure-appopened', this);
window.addEventListener('rocketbar-overlayopened', this);
window.addEventListener('languagechange', this);
window.addEventListener('updatepromptshown', this);
Service.request('registerHierarchy', this);
if (navigator.mozTelephony) {
BaseModule.lazyLoad(['DialerAgent']).then(() => {
// DialerAgent will create callscreen window
// so it is 'CallscreenWindowLauncher' exactly.
this.dialerAgent = new DialerAgent();
this.dialerAgent.start();
});
}
},
stop: function attwm_stop() {
this._instances = null;
this._openedInstances = null;
window.removeEventListener('attentioncreated', this);
window.removeEventListener('attentionterminated', this);
window.removeEventListener('attentionshow', this);
window.removeEventListener('attentionopening', this);
window.removeEventListener('attentionopened', this);
window.removeEventListener('attentionclosed', this);
window.removeEventListener('attentionclosing', this);
window.removeEventListener('attentionrequestopen', this);
window.removeEventListener('attentionrequestclose', this);
window.removeEventListener('emergencyalert', this);
window.removeEventListener('launchapp', this);
window.removeEventListener('lockscreen-appclosed', this);
window.removeEventListener('lockscreen-appopened', this);
window.removeEventListener('secure-appclosed', this);
window.removeEventListener('secure-appopened', this);
window.removeEventListener('rocketbar-overlayopened', this);
window.removeEventListener('languagechange', this);
window.removeEventListener('updatepromptshown', this);
Service.request('unregisterHierarchy', this);
},
handleEvent: function attwm_handleEvent(evt) {
this.debug('handling ' + evt.type);
var attention = evt.detail;
switch (evt.type) {
case 'attentioncreated':
this._instances.push(attention);
break;
case 'attentionopening':
case 'attentionopened':
this._openedInstances.set(attention, attention);
this.updateAttentionIndicator();
this.publish('-activated');
this.updateClassState();
break;
case 'attentionrequestclose':
this._openedInstances.delete(attention);
if (this._topMostWindow !== attention) {
attention.close();
break;
}
var candidate = null;
if (this._openedInstances.size === 0) {
this._topMostWindow = null;
candidate = Service.query('AppWindowManager.getActiveWindow');
} else {
this._openedInstances.forEach(function(instance) {
candidate = instance;
});
this._topMostWindow = candidate;
}
if (!candidate) {
attention.close();
break;
}
candidate.ready(function() {
attention.close();
});
break;
case 'attentionclosed':
this._openedInstances.delete(attention);
if (this._topMostWindow) {
this._topMostWindow.promote();
this._topMostWindow.setVisible(true);
}
attention.demote();
if (this._openedInstances.size === 0) {
this.publish('-deactivated');
}
this.updateAttentionIndicator();
this.updateClassState();
break;
case 'attentionrequestopen':
this._topMostWindow = attention;
attention.ready(function() {
if (document.mozFullScreen) {
document.mozCancelFullScreen();
}
this._openedInstances.forEach(function(opened) {
if (opened !== attention) {
opened.demote();
opened.setVisible(false);
}
});
attention.promote();
attention.setVisible(true);
attention.open();
}.bind(this));
break;
// For callscreen window.
case 'attentionshown':
if (this._instances.indexOf(attention) < 0) {
this._instances.push(attention);
}
break;
case 'attentionterminated':
var index = this._instances.indexOf(attention);
if (index >= 0) {
this._instances.splice(index, 1);
}
this._openedInstances.delete(attention);
this.updateAttentionIndicator();
// In case of a kill/crash we might not get the attentionclosed
// event, so updating the attention class if that's the case.
if (attention.isCrashed) {
this.updateClassState();
}
break;
case 'launchapp':
if (evt.detail && evt.detail.stayBackground) {
break;
} // jshint ignore:line
case 'emergencyalert':
case 'rocketbar-overlayopened':
case 'updatepromptshown':
this._topMostWindow = null;
this.closeAllAttentionWindows();
break;
case 'lockscreen-appclosed':
case 'lockscreen-appopened':
case 'secure-appopened':
case 'secure-appclosed':
case 'languagechange':
this._instances.forEach(function(instance) {
instance.broadcast(evt.type);
});
break;
}
},
/**
* Traverse the instances list to get the count of displayed window.
* @return {Number} The count of displayed window
*/
getShownWindowCount: function() {
var count = this._instances.length;
this._instances.forEach(function(attention) {
if (attention.isHidden()) {
count--;
}
});
return count;
},
updateAttentionIndicator: function() {
if (this._openedInstances.size == this.getShownWindowCount()) {
Service.request('makeAmbientIndicatorInactive');
} else {
Service.request('makeAmbientIndicatorActive');
}
},
updateClassState: function() {
// XXX We set a class to screen to allow overriding the screen.lock class.
// When we get rid of screen.lock in the future, this can go away safely.
if (this._openedInstances.size !== 0) {
this.screen.classList.add('attention');
} else {
this.screen.classList.remove('attention');
}
},
closeAllAttentionWindows: function() {
this._openedInstances.forEach(function(value) {
value.close();
});
}
};
exports.AttentionWindowManager = AttentionWindowManager;
}(window));