VulpesOS/gaia/apps/keyboard/js/settings/layout_item_view.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

298 lines
8.7 KiB
JavaScript
Executable file

'use strict';
/* global BaseView */
(function(exports) {
var LayoutItemView = function(list, layoutItem) {
BaseView.apply(this);
this._statusEl = null;
this._progressEl = null;
if (typeof layoutItem !== 'object') {
throw new Error('LayoutItemView: ' +
'LayoutItemView does not create a LayoutItem for itself, ' +
'please pass an approate instance as the model.');
}
this.list = list;
this._model = layoutItem;
};
LayoutItemView.prototype = Object.create(BaseView.prototype);
LayoutItemView.prototype.oninlistchange = null;
LayoutItemView.prototype.inList = undefined;
LayoutItemView.prototype.IN_LIST_INSTALLED = 0;
LayoutItemView.prototype.IN_LIST_INSTALLABLE = 1;
LayoutItemView.prototype.TEMPLATE_ID = 'installable-keyboard-list-item';
LayoutItemView.prototype.start = function() {
this._model.onerror = this._showError.bind(this);
this._model.onprogress = this._updateProgress.bind(this);
this._model.onstatechange = this._updateUI.bind(this);
this._model.oninstall = this._showEnableDialog.bind(this);
var template = document.getElementById(this.TEMPLATE_ID);
var el = this.container =
document.importNode(template.content, true).firstElementChild;
el.querySelector('.label').textContent = this._model.name;
if (this._model.nameL10nId) {
el.querySelector('.label').dataset.l10nId = this._model.nameL10nId;
}
el.addEventListener('click', this);
this._statusEl = el.querySelector('.status');
this._progressEl = el.querySelector('.progress');
this._updateUI();
};
LayoutItemView.prototype._updateProgress = function() {
var loadedSizeData = this._getHumanFileSize(this._model.downloadLoadedSize);
var totalSizeData = this._getHumanFileSize(this._model.downloadTotalSize);
this._progressEl.value = this._model.downloadLoadedSize;
this._progressEl.max = this._model.downloadTotalSize;
this._statusEl.dataset.l10nArgs =
JSON.stringify({
loadedSize: loadedSizeData.size,
loadedSizeUnit: loadedSizeData.localizedUnit,
totalSize: totalSizeData.size,
totalSizeUnit: totalSizeData.localizedUnit
});
};
LayoutItemView.prototype._updateUI = function() {
var fileSizeData;
var loadedSizeData;
var totalSizeData;
var item = this._model;
switch (item.state) {
case item.STATE_PRELOADED:
this.container.dataset.enabledAction = 'none';
this._statusEl.dataset.l10nId = 'preInstalledStatus';
fileSizeData = this._getHumanFileSize(item.fileSize);
this._statusEl.dataset.l10nArgs = JSON.stringify({
size: fileSizeData.size,
sizeUnit: fileSizeData.localizedUnit
});
this._progressEl.classList.add('hide');
this._updateList(this.IN_LIST_INSTALLED);
break;
case item.STATE_INSTALLABLE:
this.container.dataset.enabledAction = 'download';
this._statusEl.dataset.l10nId = 'installableStatus';
fileSizeData = this._getHumanFileSize(item.fileSize);
this._statusEl.dataset.l10nArgs = JSON.stringify({
size: fileSizeData.size,
sizeUnit: fileSizeData.localizedUnit
});
this._progressEl.classList.add('hide');
this._updateList(this.IN_LIST_INSTALLABLE);
break;
case item.STATE_INSTALLING_CANCELLABLE:
this.container.dataset.enabledAction = 'cancel-download';
this._statusEl.dataset.l10nId = 'downloadingStatus';
loadedSizeData = this._getHumanFileSize(item.downloadLoadedSize);
totalSizeData = this._getHumanFileSize(item.downloadTotalSize);
this._statusEl.dataset.l10nArgs =
JSON.stringify({
loadedSize: loadedSizeData.size,
loadedSizeUnit: loadedSizeData.localizedUnit,
totalSize: totalSizeData.size,
totalSizeUnit: totalSizeData.localizedUnit
});
this._progressEl.classList.remove('hide');
this._progressEl.value = item.downloadLoadedSize;
this._progressEl.max = item.downloadTotalSize;
this._updateList(this.IN_LIST_INSTALLABLE);
break;
case item.STATE_INSTALLING:
this.container.dataset.enabledAction = 'none';
this._statusEl.dataset.l10nId = 'downloadingStatus';
fileSizeData = this._getHumanFileSize(item.fileSize);
this._statusEl.dataset.l10nArgs =
JSON.stringify({
loadedSize: fileSizeData.size,
loadedSizeUnit: fileSizeData.localizedUnit,
totalSize: fileSizeData.size,
totalSizeUnit: fileSizeData.localizedUnit
});
this._progressEl.classList.remove('hide');
this._progressEl.value = this._progressEl.max = item.fileSize;
this._updateList(this.IN_LIST_INSTALLABLE);
break;
case item.STATE_INSTALLED:
this.container.dataset.enabledAction = 'remove';
this._statusEl.dataset.l10nId = 'installedStatus';
fileSizeData = this._getHumanFileSize(item.fileSize);
this._statusEl.dataset.l10nArgs = JSON.stringify({
size: fileSizeData.size,
sizeUnit: fileSizeData.localizedUnit
});
this._progressEl.classList.add('hide');
this._updateList(this.IN_LIST_INSTALLED);
break;
case item.STATE_REMOVING:
this.container.dataset.enabledAction = 'none';
this._statusEl.dataset.l10nId = 'removingStatus';
delete this._statusEl.dataset.l10nArgs;
this._progressEl.classList.add('hide');
this._updateList(this.IN_LIST_INSTALLED);
break;
}
};
LayoutItemView.prototype._showEnableDialog = function() {
this.list.confirmEnable(this._model.name).then(function(confirmed) {
if (confirmed) {
return this.list.enableLayout(this._model.id);
}
}.bind(this)).catch(function(e) {
e && console.error(e);
});
};
LayoutItemView.prototype._showError = function(errorInfo) {
switch (errorInfo.error) {
case errorInfo.ERROR_DOWNLOADERROR:
this.list.showDownloadErrorToast();
break;
case errorInfo.ERROR_INSTALLERROR:
console.error('LayoutItemView: layout installation error.');
break;
case errorInfo.ERROR_REMOVEERROR:
console.error('LayoutItemView: layout removal error.');
break;
default:
console.error('LayoutItemView: undefined onerror call,', errorInfo);
break;
}
};
LayoutItemView.prototype.handleEvent = function(evt) {
var el = evt.target;
// This is intentionally kept at minimum. We do not check if the currect state
// is applicable for certain action, nor we keep the returned promise and
// react on it.
// UI updates are all tie to state updates, and state updates only.
// We do, however, wire confirmation dialog here.
var p;
switch (el.dataset.action) {
case 'download':
p = this.list.confirmDownload().then(function(confirmed) {
if (confirmed) {
return this._model.install();
}
}.bind(this));
break;
case 'cancelDownload':
p = this._model.cancelInstall();
break;
case 'remove':
p = this.list.confirmRemoval(this._model.name).then(function(confirmed) {
if (!confirmed) {
return;
}
return this.list.disableLayout(this._model.id)
.then(function() {
return this._model.remove();
}.bind(this));
}.bind(this));
break;
}
if (p) {
p.catch(function(e) {
e && console.error(e);
});
}
};
LayoutItemView.prototype.stop = function() {
this._model.onprogress = null;
this._model.onstatechange = null;
this.container.removeEventListener('click', this);
this.container = null;
};
LayoutItemView.prototype._updateList = function(newListState) {
if (newListState === this.inList) {
return;
}
if (typeof this.inList === 'undefined') {
// First time set, don't trigger.
this.inList = newListState;
return;
}
this.inList = newListState;
if (typeof this.oninlistchange === 'function') {
this.oninlistchange();
}
};
LayoutItemView.prototype._getHumanFileSize = function(sizeInNumber) {
// XXX I actually don't know how not to use get() here.
var _ = navigator.mozL10n.get;
var sizeString = '';
var localizedUnit = '';
if (sizeInNumber > (1 << 30)) {
sizeString = (sizeInNumber / (1 << 30)).toFixed(2);
localizedUnit = _('byteUnit-GB');
} else if (sizeInNumber > (1 << 20)) {
sizeString = (sizeInNumber / (1 << 20)).toFixed(2);
localizedUnit = _('byteUnit-MB');
} else if (sizeInNumber > (1 << 10)) {
sizeString = (sizeInNumber / (1 << 10)).toFixed(2);
localizedUnit = _('byteUnit-KB');
} else {
sizeString = sizeInNumber.toFixed(2);
localizedUnit = _('byteUnit-B');
}
// Remove the zeros after decimal point,
// and the decimal point too if there isn't any thing left on the right side.
sizeString = sizeString.replace(/\.?0*$/, '');
return {
size: sizeString,
localizedUnit: localizedUnit
};
};
exports.LayoutItemView = LayoutItemView;
}(window));