'use strict'; /* global Event */ /* global Service */ /* global SettingsListener */ (function(exports) { /** * SleepMenu controls functionality found in the menu after long-pressing on * the power button. Controls include: airplane mode, silence incoming calls, * restart, and power off. This file also currently contains a * developerOptions object which is not currently in use. * @class SleepMenu * @requires InitLogoHandler * @requires LogoLoader * @requires Service * @requires SettingsListener */ function SleepMenu() {} SleepMenu.prototype = { /** * Indicate setting status of ril.radio.disabled * @memberof SleepMenu.prototype * @type {Boolean} */ isFlightModeEnabled: false, /** * Indicate setting status of developer.menu.enabled * @memberof SleepMenu.prototype * @type {Boolean} */ isDeveloperMenuEnabled: false, /** * Additional options to show in the menu if developer menu is enabled. * @memberof SleepMenu.prototype * @type {Object} */ developerOptions: { }, /** * Indicate setting status of volume * @memberof SleepMenu.prototype * @type {Boolean} */ isSilentModeEnabled: false, /** * Additional developer option to view source code of apps. * @memberof @SleepMenu.prototype * @type {Boolean} */ isViewSourceEnabled: false, /** * References to elements in the menu. * @memberof SleepMenu.prototype * @type {Object} */ elements: {}, /** * Whether or not the sleep menu is visibile. * @memberof SleepMenu.prototype * @return {Boolean} */ get visible() { return this.elements.overlay.classList.contains('visible'); }, /** * Populates this.elements with references to elements. * @memberof SleepMenu.prototype */ getAllElements: function sm_getAllElements() { this.elements.overlay = document.getElementById('sleep-menu'); this.elements.container = document.querySelector('#sleep-menu-container ul'); this.elements.cancel = document.querySelector('#sleep-menu button'); }, /** * Start listening for events and settings changes. * @memberof SleepMenu.prototype */ start: function sm_init() { this.getAllElements(); window.addEventListener('holdsleep', this.show.bind(this)); window.addEventListener('click', this, true); window.addEventListener('screenchange', this, true); window.addEventListener('home', this); window.addEventListener('batteryshutdown', this); window.addEventListener('cardviewbeforeshow', this); window.addEventListener('attentionopened', this); this.elements.cancel.addEventListener('click', this); var self = this; SettingsListener.observe('ril.radio.disabled', false, function(value) { self.isFlightModeEnabled = value; }); SettingsListener.observe('developer.menu.enabled', false, function(value) { self.isDeveloperMenuEnabled = value; }); for (var option in this.developerOptions) { /* jshint loopfunc: true */ (function attachListenerToDeveloperOption(opt) { SettingsListener.observe(opt.setting, opt.value, function(value) { opt.value = value; }); })(this.developerOptions[option]); } SettingsListener.observe('audio.volume.notification', 7, function(value) { self.isSilentModeEnabled = (value === 0); }); SettingsListener.observe('dev.gaia.view_source', false, function(value) { self.isViewSourceEnabled = value; }); }, /** * Generates menu items. * @memberof SleepMenu.prototype */ generateItems: function sm_generateItems() { var items = []; var _ = navigator.mozL10n.get; var options = { airplane: { label: _('airplane'), value: 'airplane' }, airplaneOff: { label: _('airplaneOff'), value: 'airplane' }, silent: { label: _('silent'), value: 'silent' }, silentOff: { label: _('normal'), value: 'silentOff' }, restart: { label: _('restart'), value: 'restart' }, power: { label: _('power'), value: 'power' }, viewSource: { label: _('viewSource'), value: 'viewSource' } }; if (this.isFlightModeEnabled) { items.push(options.airplaneOff); } else { items.push(options.airplane); } if (navigator.mozTelephony) { if (!this.isSilentModeEnabled) { items.push(options.silent); } else { items.push(options.silentOff); } } items.push(options.restart); items.push(options.power); // Add the developer options at the end. if (this.isDeveloperMenuEnabled) { for (var option in this.developerOptions) { if (this.developerOptions[option].value) { items.push(options[option]); } else { items.push(options[option + 'Off']); } } } if (this.isDeveloperMenuEnabled && this.isViewSourceEnabled) { items.push(options.viewSource); } return items; }, /** * Shows the sleep menu. * @memberof SleepMenu.prototype */ show: function sm_show() { this.elements.container.innerHTML = ''; this.buildMenu(this.generateItems()); this.elements.overlay.classList.add('visible'); // Lock to default orientation screen.mozLockOrientation(Service.query('defaultOrientation')); }, /** * Builds markup for all menu items. * @memberof SleepMenu.prototype * @param {Array} items A list of items. */ buildMenu: function sm_buildMenu(items) { items.forEach(function traveseItems(item) { var item_li = document.createElement('li'); item_li.dataset.value = item.value; item_li.textContent = item.label; item_li.setAttribute('role', 'menuitem'); this.elements.container.appendChild(item_li); }, this); }, /** * Hides the sleep menu. * @memberof SleepMenu.prototype */ hide: function lm_hide() { if (!this.elements.overlay.classList.contains('visible')) { return; } this.elements.overlay.classList.remove('visible'); window.dispatchEvent(new Event('sleepmenuhide')); }, /** * General event handler. * @memberof SleepMenu.prototype * @param {Event} evt The event to handle. */ handleEvent: function sm_handleEvent(evt) { switch (evt.type) { case 'cardviewbeforeshow': this.hide(); break; case 'batteryshutdown': window.dispatchEvent( new CustomEvent('requestshutdown', {detail: this})); break; case 'screenchange': if (!evt.detail.screenEnabled) { this.hide(); } break; case 'click': if (!this.visible) { return; } if (evt.currentTarget === this.elements.cancel) { this.hide(); return; } var action = evt.target.dataset.value; if (!action) { return; } this.clickHandler(action); break; case 'home': case 'attentionopened': if (this.visible) { this.hide(); } break; default: break; } }, publish: function(evtName) { window.dispatchEvent(new CustomEvent(evtName)); }, /** * Handles click events on menu items. * @memberof SleepMenu.prototype * @param {String} action The action of the clicked menu item. */ clickHandler: function sm_clickHandler(action) { switch (action) { case 'airplane': this.hide(); // Airplane mode should turn off // // Radio ('ril.radio.disabled'`) // Data ('ril.data.enabled'`) // Wifi // Bluetooth // Geolocation // // It should also save the status of the latter 4 items so when // leaving the airplane mode we could know which one to turn on. this.publish(this.isFlightModeEnabled ? 'request-airplane-mode-disable' : 'request-airplane-mode-enable'); break; // About silent and silentOff // * Turn on silent mode will cause: // send a custom event 'mute' to sound manager // * Turn off silent mode will cause: // send a custom event 'unmute' to sound manager case 'silent': this.hide(); window.dispatchEvent(new Event('mute')); this.isSilentModeEnabled = true; break; case 'silentOff': this.hide(); window.dispatchEvent(new Event('unmute')); this.isSilentModeEnabled = false; break; case 'restart': this.startPowerOff(true); break; case 'power': this.startPowerOff(false); break; case 'viewSource': this.hide(); this.viewSource(); break; default: break; } }, /** * Begins the power off of the device. Also reboots the device if * requested. * @memberof SleepMenu.prototype * @param {Boolean} reboot Whether or not to reboot the phone. */ startPowerOff: function sm_startPowerOff(reboot) { Service.request('poweroff', reboot); }, /** * Dispatches 'viewsource' event to display source of the current active * app. * @memberof SleepMenu.prototype */ viewSource: function sm_viewSource() { Service.request('viewsource'); } }; exports.SleepMenu = SleepMenu; }(window));