Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
349 lines
11 KiB
JavaScript
349 lines
11 KiB
JavaScript
/**
|
|
Copyright 2012, Mozilla Foundation
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
/*global Service, UtilityTray, LazyLoader */
|
|
|
|
'use strict';
|
|
|
|
(function(exports) {
|
|
const AVG_ICON_SIZE = 22;
|
|
|
|
var Statusbar = {
|
|
name: 'Statusbar',
|
|
|
|
// The indices indicate icons priority (lower index = highest priority)
|
|
PRIORITIES: [
|
|
'time',
|
|
'emergency-callback',
|
|
'battery',
|
|
'recording',
|
|
'airplane-mode',
|
|
'wifi',
|
|
'mobile-connection',
|
|
'debugging',
|
|
'download',
|
|
'geolocation',
|
|
'network-activity',
|
|
'tethering',
|
|
'bluetooth-transfer',
|
|
'bluetooth',
|
|
'nfc',
|
|
'usb',
|
|
'alarm',
|
|
'bluetooth-headphone',
|
|
'mute',
|
|
'call-forwardings',
|
|
'playing',
|
|
'headphone',
|
|
'operator'
|
|
],
|
|
|
|
/* Whether or not status bar is actively updating or not */
|
|
active: true,
|
|
|
|
_numMinimizedIcons: 9,
|
|
_currentIcons: {},
|
|
get _iconsCount() {
|
|
return Object.keys(this._currentIcons).length;
|
|
},
|
|
|
|
/* For other modules to acquire */
|
|
get height() {
|
|
if (document.mozFullScreen ||
|
|
(Service.query('getTopMostWindow') &&
|
|
Service.query('getTopMostWindow').isFullScreen())) {
|
|
return 0;
|
|
} else {
|
|
return this._cacheHeight ||
|
|
(this._cacheHeight =
|
|
this.element.getBoundingClientRect().height);
|
|
}
|
|
},
|
|
|
|
start: function() {
|
|
this.getAllElements();
|
|
|
|
// cache height.
|
|
this._cacheHeight = this.element.getBoundingClientRect().height;
|
|
|
|
window.addEventListener('apptitlestatechanged', this);
|
|
window.addEventListener('activitytitlestatechanged', this);
|
|
window.addEventListener('homescreentitlestatechanged', this);
|
|
window.addEventListener('appchromecollapsed', this);
|
|
window.addEventListener('appchromeexpanded', this);
|
|
window.addEventListener('iconshown', this);
|
|
window.addEventListener('iconhidden', this);
|
|
window.addEventListener('iconrendered', this);
|
|
|
|
if (Service.query('FtuLauncher.isFinished')) {
|
|
this.finishInit();
|
|
} else {
|
|
window.addEventListener('ftuskip', this);
|
|
window.addEventListener('ftudone', this);
|
|
}
|
|
Service.registerState('height', this);
|
|
Service.register('iconContainer', this);
|
|
},
|
|
|
|
calculateMinimized: function sb_calculateMinimized() {
|
|
var minimizedWidth = this.element.clientWidth / 2;
|
|
var count = minimizedWidth / AVG_ICON_SIZE;
|
|
this._numMinimizedIcons = Math.floor(count);
|
|
},
|
|
|
|
iconContainer: function sb_iconContainer(icon) {
|
|
if (icon.dashPureName === 'operator') {
|
|
return this.statusbarTray;
|
|
}
|
|
return this.statusbarIcons;
|
|
},
|
|
|
|
/**
|
|
* Finish all initializing statusbar event handlers
|
|
*/
|
|
finishInit: function() {
|
|
window.addEventListener(
|
|
'appstatusbar-fullscreen-statusbar-set-appearance', this);
|
|
window.addEventListener('appstatusbar-fullscreen-statusbar-show', this);
|
|
window.addEventListener('appstatusbar-fullscreen-statusbar-hide', this);
|
|
window.addEventListener('sheets-gesture-begin', this);
|
|
window.addEventListener('sheets-gesture-end', this);
|
|
window.addEventListener('utilitytraywillshow', this);
|
|
window.addEventListener('utilitytraywillhide', this);
|
|
window.addEventListener('utility-tray-overlayopened', this);
|
|
window.addEventListener('utility-tray-overlayclosed', this);
|
|
window.addEventListener('utility-tray-abortopen', this);
|
|
window.addEventListener('utility-tray-abortclose', this);
|
|
window.addEventListener('cardviewshown', this);
|
|
window.addEventListener('cardviewclosed', this);
|
|
|
|
window.addEventListener('attentionopened', this);
|
|
window.addEventListener('appwillopen', this);
|
|
window.addEventListener('appwillclose', this);
|
|
window.addEventListener('appopened', this);
|
|
window.addEventListener('appclosed', this);
|
|
window.addEventListener('hierarchytopmostwindowchanged', this);
|
|
window.addEventListener('activityopened', this);
|
|
window.addEventListener('homescreenopened', this);
|
|
window.addEventListener('stackchanged', this);
|
|
window.addEventListener('lockscreen-request-unlock', this);
|
|
|
|
// Listen to updates dialog
|
|
window.addEventListener('updatepromptshown', this);
|
|
window.addEventListener('updateprompthidden', this);
|
|
|
|
// We need to preventDefault on mouse events until
|
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=1005815 lands
|
|
var events = ['touchstart', 'touchmove', 'touchend',
|
|
'mousedown', 'mousemove', 'mouseup'];
|
|
events.forEach(function bindEvents(name) {
|
|
this.topPanel.addEventListener(name, this.panelHandler.bind(this));
|
|
}, this);
|
|
|
|
LazyLoader.load([
|
|
'js/utility_tray_motion.js',
|
|
'js/utility_tray.js'
|
|
]).then(function() {
|
|
this.utilityTray = UtilityTray;
|
|
UtilityTray.init();
|
|
}.bind(this)).catch((err) => {
|
|
console.error('UtilityTray load or init error', err);
|
|
});
|
|
|
|
this.calculateMinimized();
|
|
},
|
|
|
|
handleEvent: function sb_handleEvent(evt) {
|
|
var icon;
|
|
switch (evt.type) {
|
|
case 'iconshown':
|
|
this._currentIcons[evt.detail.dashPureName] = true;
|
|
this.toggleMaximized();
|
|
break;
|
|
case 'iconhidden':
|
|
delete this._currentIcons[evt.detail.dashPureName];
|
|
break;
|
|
case 'ftudone':
|
|
case 'ftuskip':
|
|
this.finishInit();
|
|
break;
|
|
case 'iconrendered':
|
|
icon = evt.detail;
|
|
var order = this.PRIORITIES.indexOf(icon.dashPureName);
|
|
icon.setOrder(order);
|
|
break;
|
|
|
|
case 'attentionopened':
|
|
this.element.classList.add('maximized');
|
|
this.element.classList.remove('light');
|
|
break;
|
|
|
|
case 'sheets-gesture-begin':
|
|
case 'appwillopen':
|
|
case 'appwillclose':
|
|
case 'cardviewshown':
|
|
this.element.classList.add('hidden');
|
|
break;
|
|
|
|
case 'sheets-gesture-end':
|
|
case 'stackchanged':
|
|
case 'cardviewclosed':
|
|
this.element.classList.remove('hidden');
|
|
break;
|
|
|
|
case 'appstatusbar-fullscreen-statusbar-show':
|
|
this.topPanel.style.pointerEvents = 'none';
|
|
break;
|
|
case 'appstatusbar-fullscreen-statusbar-hide':
|
|
this.topPanel.style.pointerEvents = '';
|
|
break;
|
|
|
|
case 'utilitytraywillshow':
|
|
case 'utilitytraywillhide':
|
|
case 'appstatusbar-fullscreen-statusbar-set-appearance':
|
|
case 'utility-tray-overlayopened':
|
|
case 'utility-tray-overlayclosed':
|
|
case 'utility-tray-abortopen':
|
|
case 'utility-tray-abortclose':
|
|
case 'appchromecollapsed':
|
|
case 'updateprompthidden':
|
|
this.setAppearance();
|
|
break;
|
|
|
|
case 'appopened':
|
|
var app = evt.detail;
|
|
if (!app.isFullScreen() && !app.isFullScreenLayout()) {
|
|
this.element.setAttribute('aria-owns',
|
|
evt.detail.appChrome.element.id);
|
|
} else {
|
|
this.element.removeAttribute('aria-owns');
|
|
}
|
|
/* falls through */
|
|
case 'appclosed':
|
|
case 'hierarchytopmostwindowchanged':
|
|
case 'lockscreen-request-unlock':
|
|
case 'appchromeexpanded':
|
|
this.element.classList.remove('hidden');
|
|
this.setAppearance();
|
|
break;
|
|
|
|
case 'activityopened':
|
|
case 'apptitlestatechanged':
|
|
case 'activitytitlestatechanged':
|
|
case 'homescreentitlestatechanged':
|
|
this.setAppearance();
|
|
this.element.classList.remove('hidden');
|
|
break;
|
|
case 'homescreenopened':
|
|
// In some cases, if the user has been switching apps so fast and
|
|
// quickly he press the home button, we might miss the
|
|
// |sheets-gesture-end| event so we must resume the statusbar
|
|
// if needed
|
|
this.setAppearance();
|
|
this.element.classList.remove('hidden');
|
|
this.element.classList.remove('fullscreen');
|
|
this.element.classList.remove('fullscreen-layout');
|
|
this.element.removeAttribute('aria-owns');
|
|
break;
|
|
case 'updatepromptshown':
|
|
this.element.classList.remove('light');
|
|
break;
|
|
}
|
|
},
|
|
|
|
setAppearance: function() {
|
|
var app = Service.query('getTopMostWindow');
|
|
if (!app) {
|
|
return;
|
|
}
|
|
|
|
var isFullScreen = app.isFullScreen() || document.mozFullScreen;
|
|
|
|
this.element.classList.toggle('light',
|
|
!!(app.appChrome && app.appChrome.useLightTheming()) && !isFullScreen
|
|
);
|
|
|
|
this.element.classList.toggle('fullscreen', isFullScreen);
|
|
|
|
this.element.classList.toggle('fullscreen-layout',
|
|
app.isFullScreenLayout()
|
|
);
|
|
|
|
this.toggleMaximized();
|
|
},
|
|
|
|
toggleMaximized: function() {
|
|
var app = Service.query('getTopMostWindow');
|
|
|
|
if (!app) {
|
|
return;
|
|
}
|
|
|
|
var appsWithoutRocketbar = [
|
|
'isHomescreen',
|
|
'isAttentionWindow',
|
|
'isLockscreen'
|
|
];
|
|
|
|
var noRocketbar = appsWithoutRocketbar.some(function(name) {
|
|
return !!(app[name]);
|
|
});
|
|
var chromeMaximized = !!(app.appChrome && app.appChrome.isMaximized());
|
|
var trayActive = !!(this.utilityTray && this.utilityTray.shown);
|
|
var shouldMaximize = noRocketbar || chromeMaximized || trayActive;
|
|
var fewIcons = (this._iconsCount < this._numMinimizedIcons);
|
|
|
|
// Important: we need a boolean to make the toggle method
|
|
// take the right decision
|
|
var elem = this.element;
|
|
elem.classList.toggle('maximized', !!(shouldMaximize && !fewIcons));
|
|
},
|
|
|
|
panelHandler: function sb_panelHandler(evt) {
|
|
// Do not forward events if FTU is running
|
|
if (Service.query('isFtuRunning')) {
|
|
return;
|
|
}
|
|
|
|
// Do not forward events if the utility tray is shown.
|
|
if (this.utilityTray && this.utilityTray.shown) {
|
|
return;
|
|
}
|
|
|
|
var app = Service.query('getTopMostWindow');
|
|
app && app.handleStatusbarTouch(evt, this._cacheHeight);
|
|
},
|
|
|
|
getAllElements: function sb_getAllElements() {
|
|
this.element = document.getElementById('statusbar');
|
|
this.statusbarIcons = document.getElementById('statusbar-icons');
|
|
this.statusbarIconsMax = document.getElementById('statusbar-maximized');
|
|
this.screen = document.getElementById('screen');
|
|
this.topPanel = document.getElementById('top-panel');
|
|
this.statusbarTray = document.getElementById('statusbar-tray');
|
|
|
|
// Dummy element used at initialization.
|
|
this.statusbarIconsMin = document.createElement('div');
|
|
this.statusbarIcons.appendChild(this.statusbarIconsMin);
|
|
},
|
|
|
|
// To reduce the duplicated code
|
|
isLocked: function() {
|
|
return Service.query('locked');
|
|
}
|
|
};
|
|
exports.Statusbar = Statusbar;
|
|
}(window));
|