VulpesOS/gaia/apps/system/js/device_storage_watcher.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

184 lines
6 KiB
JavaScript
Executable file

/* global MozActivity, LazyLoader, Service, SystemBanner */
/**
* DeviceStorageWatcher listens for nsIDOMDeviceStorage.onchange events
* notifying about low device storage situations (see Bug 861921). When a
* 'onchange' event containing a 'low-disk-space' reason is received, we show a
* banner for a few seconds and pin a notification in the notifications center.
* When the reason of the 'onchange' event is 'available-disk-space', we remove
* the pinned notification, if one exists.
*/
'use strict';
(function(exports) {
var DeviceStorageWatcher = {
LOW_DISK_NOTIF_ID: 'low-disk-space',
start: function dsw_init() {
this._lowDeviceStorage = false;
this._freeSpace = null;
this._ = navigator.mozL10n.get;
this._appStorage = navigator.getDeviceStorage('apps');
this._appStorage.addEventListener('change', this);
this._container = document.getElementById('storage-watcher-container');
this._container.onclick = this.containerClicked;
this._message = this._container.querySelector('.title-container');
this._availableSpace = this._container.querySelector('.detail');
window.addEventListener('appopening', this);
},
containerClicked: function dsw_containerClicked() {
// We redirect the user to the app permissions section of the settings app
// so she can uninstall 3rd party apps trying to recover from the low
// storage situation. This is not the best solution, but the only one that
// we have so far. In the future, we must expose how much storage each app
// consumes, so the user has a better idea of which apps are consuming
// more (see Bug 862408).
/* jshint nonew: false */
new MozActivity({
name: 'configure',
data: {
section: 'appPermissions'
}
});
},
hideNotification: function dsw_hideNotification() {
this._lowDeviceStorage = false;
if (this._container.classList.contains('displayed')) {
this._container.classList.remove('displayed');
Service.request('NotificationScreen:removeUnreadNotification',
this.LOW_DISK_NOTIF_ID);
}
},
displayNotification: function dsw_displayNotification() {
this._lowDeviceStorage = true;
if (!this._container.classList.contains('displayed')) {
this._container.classList.add('displayed');
Service.request('NotificationScreen:addUnreadNotification',
this.LOW_DISK_NOTIF_ID);
}
},
displayBanner: function dsw_displayBanner(space) {
var notification = ['low-device-storage'];
if (space && typeof space.size !== 'undefined' && space.unit) {
notification.push({
id: 'free-space',
args: {
value: space.size,
unit: space.unit
}
});
} else {
notification.push('unknown-free-space');
}
LazyLoader.load(['js/system_banner.js']).then(() => {
var systemBanner = new SystemBanner();
systemBanner.show(notification);
}).catch((err) => {
console.error(err);
});
},
lowDiskSpaceNotification: function dsw_lowDiskSpaceNotification(space) {
this.displayBanner(space);
this._message.setAttribute('data-l10n-id', 'low-device-storage');
this.updateAvailableSpace(space);
this.displayNotification();
},
updateAvailableSpace: function dsw_updateAvailableSpace(space) {
if (space && typeof space.size !== 'undefined' && space.unit) {
navigator.mozL10n.setAttributes(
this._availableSpace,
'free-space',
{
value: space.size,
unit: space.unit
}
);
} else {
this._availableSpace.setAttribute('data-l10n-id', 'unknown-free-space');
}
},
/**
* Helper function to format the value returned by the
* nsIDOMDeviceStorage.freeSpace call in a more readable way.
*/
formatSize: function dsw_formatSize(size) {
if (size === undefined || isNaN(size)) {
return;
}
var units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
var i = 0;
while (size >= 1024 && i < (units.length) - 1) {
size /= 1024;
++i;
}
var sizeDecimal = i < 2 ? Math.round(size) : Math.round(size * 10) / 10;
return {
size: sizeDecimal,
unit: this._('byteUnit-' + units[i])
};
},
handleEvent: function dsw_handleEvent(evt) {
// Display low storage banner every time an app opens with low storage.
if (evt.type === 'appopening') {
if (this._lowDeviceStorage) {
this.displayBanner(this._freeSpace);
}
return;
}
// Otherwise if event is not a storage change event we ignore it.
if (evt.type !== 'change') {
return;
}
switch (evt.reason) {
// We get 'onchange' events with a 'low-disk-space' reason when a
// modification of a file is identified while the device is in a low
// storage situation. When we get the first notification, we have to
// show a system banner and pin a notification in the notifications
// center, containing the remaining free space. Consecutive events with
// a 'low-disk-space' reason will only update the remaining free space.
case 'low-disk-space':
var req = this._appStorage.freeSpace();
req.onsuccess = () => {
if (typeof req.result !== 'undefined') {
this._freeSpace = this.formatSize(req.result);
}
if (this._lowDeviceStorage) {
this.updateAvailableSpace(this._freeSpace);
return;
}
this.lowDiskSpaceNotification(this._freeSpace);
};
req.onerror = () => {
this.lowDiskSpaceNotification();
};
break;
case 'available-disk-space':
this.hideNotification();
break;
}
}
};
exports.DeviceStorageWatcher = DeviceStorageWatcher;
}(window));