VulpesOS/gaia/apps/operatorvariant/build/build.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

349 lines
11 KiB
JavaScript
Executable file

'use strict';
/* jshint node: true */
var utils = require('utils');
// Resources helper constructor
var Resources = function(gaia, settings, appDomain) {
this.gaia = gaia;
this.settings = settings;
this.fileList = [];
this.json = {};
this.appPrefix = 'app://';
this.appURL = this.appPrefix + appDomain + '/resources/';
};
// Parse and get resources for a given JSON configuration of one operator.
// Also create an output JSON configuration for the processed resources.
Resources.prototype.getResources = function(conf) {
var operatorJSON = {};
operatorJSON.default_contacts = this.addFile(conf.default_contacts);
operatorJSON.support_contacts = this.addFile(conf.support_contacts);
operatorJSON.network_type = this.addFile(conf.network_type);
operatorJSON.known_networks = this.addFile(conf.known_networks);
operatorJSON.sms = this.addFile(conf.sms);
operatorJSON.wallpaper = this.getWallpaperResource(conf.wallpaper);
operatorJSON.ringtone = this.getRingtoneResource(conf.ringtone);
operatorJSON.power = this.getPowerResource(conf.power);
operatorJSON.search = this.getSearchResource(conf.search);
operatorJSON.keyboard_settings = this.getKeyboardResource(conf.keyboard);
operatorJSON.topsites = this.getResourceWithIcon(conf.topsites, 'topSites',
'tilePath', 'tile');
operatorJSON.browser = this.getResourceWithIcon(conf.bookmarks, 'bookmarks',
'iconPath', 'iconUri');
if ('nfc' in conf) {
operatorJSON.nfc = this.getNfcResource(conf.nfc);
}
if ('data_ftu' in conf) {
operatorJSON.data_ftu = conf.data_ftu;
}
if ('data_roaming' in conf) {
operatorJSON.data_roaming = conf.data_roaming;
}
conf['mcc-mnc'].forEach(function(mcc) {
if (Object.keys(operatorJSON).length !== 0) {
this.json[mcc] = operatorJSON;
}
}.bind(this));
};
// Get file object for a given path.
Resources.prototype.getFile = function(path) {
var distDir = this.gaia.distributionDir;
var file = utils.getFile(distDir, path);
if (!file.exists()) {
throw new Error('Invalid single variant configuration: ' +
file.path + ' not found');
}
return file;
};
// Add new resource entry in the output JSON configuration (key / value)
// and add the resource path to the resources list.
Resources.prototype.addEntry = function(resources, name) {
if (resources instanceof Array) {
this.fileList.push.apply(this.fileList, resources);
} else {
this.fileList.push(resources);
}
return '/resources/' + name;
};
// Add file to resources object
Resources.prototype.addFile = function(path, key) {
if (path) {
var file = this.getFile(path);
return this.addEntry(file, file.leafName);
}
};
// Create a new JSON file and add to resources.
Resources.prototype.createJSON = function(name, content) {
var obj = { filename: name,
content: content };
return this.addEntry(obj, obj.filename);
};
// Create new wallpaper JSON from a wallpaper file path.
Resources.prototype.getWallpaperResource = function(wallpaper) {
if (wallpaper) {
var uri;
if (wallpaper.startsWith(this.appPrefix)) {
uri = wallpaper;
} else {
var file = this.getFile(wallpaper);
if (!file) {
return;
}
uri = '/resources/' + file.leafName;
this.addEntry(file, file.leafName);
}
var content = { uri: uri,
default: this.settings['wallpaper.image'] };
var jsonName = 'wallpaper-' + utils.getHash(wallpaper) + '.json';
return this.createJSON(jsonName, content);
}
};
// Create ringtone JSON and add file.
Resources.prototype.getRingtoneResource = function(ringtone) {
if (ringtone) {
var jsonName = 'ringtone-' +
utils.getHash(JSON.stringify(ringtone)) + '.json';
var ringtoneName = ringtone.name;
if (!ringtoneName) {
throw new Error('Missing name for ringtone in single variant conf.');
}
var uri;
if (ringtone.path.startsWith(this.appPrefix)) {
uri = ringtone.path;
} else {
var file = this.getFile(ringtone.path);
if (!file) {
throw new Error('Missing path for ringtone in single variant conf.');
}
uri = '/resources/' + file.leafName;
this.addEntry(file, file.leafName);
}
var content = { uri: uri,
name: ringtoneName,
default: this.settings['dialer.ringtone.id'] };
return this.createJSON(jsonName, content);
}
};
// Create power JSON and add files.
Resources.prototype.getPowerResource = function (power) {
if (power) {
var jsonName = 'power-' + utils.getHash(JSON.stringify(power)) + '.json';
var powerJSON = power;
var poweron = power.poweron;
var poweronFile;
if (poweron) {
var poweronType = poweron.video ? 'video' : null ||
poweron.image ? 'image' : null;
if (!poweronType) {
throw new Error('Invalid poweron type, only video or image are ' +
'valid.');
}
if (poweron[poweronType].startsWith(this.appPrefix)) {
powerJSON.poweron[poweronType] = poweron[poweronType];
} else {
poweronFile = this.getFile(poweron[poweronType]);
this.addEntry(poweronFile, poweronFile.leafName);
powerJSON.poweron[poweronType] = this.appURL + poweronFile.leafName;
}
}
var poweroff = power.poweroff;
var poweroffFile;
if (poweroff) {
var poweroffType = poweroff.video ? 'video' : null ||
poweroff.image ? 'image' : null;
if (!poweroffType) {
throw new Error('Invalid poweroff type, only video or image are ' +
'valid.');
}
if (poweroff[poweroffType].startsWith(this.appPrefix)) {
powerJSON.poweroff[poweroffType] = poweroff[poweroffType];
} else {
poweroffFile = this.getFile(poweroff[poweroffType]);
this.addEntry(poweroffFile, poweroffFile.leafName);
powerJSON.poweroff[poweroffType] = this.appURL + poweroffFile.leafName;
}
}
return this.createJSON(jsonName, powerJSON);
}
};
// Create search JSON and add files.
Resources.prototype.getSearchResource = function (searchPath) {
if (searchPath) {
var file = this.getFile(searchPath);
var searchContent = utils.getJSON(file);
searchContent.forEach(function(engine) {
if (!engine.iconPath.startsWith(this.appPrefix)) {
var searchFile = this.getFile(engine.iconPath);
this.addEntry(searchFile, searchFile.leafName);
engine.iconUrl = this.appURL + searchFile.leafName;
delete engine.iconPath;
}
}.bind(this));
return this.createJSON(file.leafName, searchContent);
}
};
// Create keyboard JSON.
Resources.prototype.getKeyboardResource = function (keyboard) {
if (keyboard) {
var file = utils.getFile(this.gaia.distributionDir, keyboard);
if (!file.exists()) {
throw new Error('Invalid single variant configuration: ' +
file.path + ' not found');
}
var defaults = {
'keyboard.vibration': this.settings['keyboard.vibration'],
'keyboard.autocorrect': this.settings['keyboard.autocorrect'],
'keyboard.clicksound': this.settings['keyboard.clicksound'],
'keyboard.wordsuggestion': this.settings['keyboard.wordsuggestion']
};
var content = { values: utils.getJSON(file),
defaults: defaults };
for (var value in content.values) {
if (!value.startsWith('keyboard.')) {
throw new Error('Invalid keyboard property \'' + value + '\' in file ' +
file.path + ', keyboard properties must start ' +
'with \'keyboard.\'');
}
}
var jsonName = 'keyboard-' + utils.getHash(keyboard) + '.json';
return this.createJSON(jsonName, content);
}
};
Resources.prototype.getResourceWithIcon = function(aFilePath, aRootKey,
aIconPathKey, aIconOutKey) {
if (aFilePath) {
var file = this.getFile(aFilePath);
var json = utils.getJSON(file);
json[aRootKey].forEach(function(elem) {
if (elem[aIconPathKey]) {
var iconFile = this.getFile(elem[aIconPathKey]);
var icon = utils.getFileAsDataURI(iconFile);
elem[aIconOutKey] = icon;
delete elem[aIconPathKey];
}
}.bind(this));
return this.createJSON(file.leafName, json);
}
};
// Create nfc JSON.
Resources.prototype.getNfcResource = function(nfc) {
var content = { isEnabled: nfc,
default: this.settings['nfc.enabled'] };
var jsonName = 'nfc-' + utils.getHash(JSON.stringify(content)) + '.json';
return this.createJSON(jsonName, content);
};
// OperatorAppBuilder constructor object.
var OperatorAppBuilder = function() {
};
// set destination directory, application directory and get settings in order
// to set default values.
OperatorAppBuilder.prototype.setOptions = function(options) {
this.stageDir = utils.getFile(options.STAGE_APP_DIR);
this.gaia = utils.gaia.getInstance(options);
var settingsFile = utils.getFile(options.PROFILE_DIR, 'settings.json');
if (!settingsFile.exists()) {
throw new Error('file not found: ' + settingsFile.path);
}
this.settings = utils.getJSON(settingsFile);
this.appDir = utils.getFile(options.APP_DIR);
this.appDomain = this.appDir.leafName + '.' + options.GAIA_DOMAIN;
};
// Get resources and copy files and configuration JSON to build_stage folder.
OperatorAppBuilder.prototype.generateCustomizeResources = function() {
if (!this.gaia.distributionDir) {
return;
}
var variantFile = utils.getFile(this.gaia.distributionDir, 'variant.json');
if (variantFile.exists()) {
var resources = this.getSingleVariantResources(variantFile);
var resourceDirFile = utils.getFile(this.stageDir.path, 'resources');
utils.ensureFolderExists(resourceDirFile);
var customizationFile = utils.getFile(this.stageDir.path,
'resources', 'customization.json');
utils.writeContent(customizationFile, JSON.stringify(resources.json));
resources.fileList.forEach(function(file) {
if (!file.filename && !file.content) {
utils.copyFileTo(file.path, resourceDirFile.path, file.leafName);
} else {
var resourceFile = utils.getFile(resourceDirFile.path, file.filename);
utils.writeContent(resourceFile, JSON.stringify(file.content));
}
});
} else {
utils.log('operatorvariant',
'Single variant resources will not be added since ' +
variantFile.path + ' not found');
}
};
// Use Resources object to get the resources for each operator.
OperatorAppBuilder.prototype.getSingleVariantResources = function(svConfFile) {
var svConf = utils.getJSON(svConfFile);
var resources = new Resources(this.gaia, this.settings, this.appDomain);
svConf.operators.forEach(function(operator) {
resources.getResources(operator);
});
return resources;
};
OperatorAppBuilder.prototype.execute = function(options) {
utils.copyToStage(options);
this.setOptions(options);
this.generateCustomizeResources(options);
};
exports.execute = function(options) {
(new OperatorAppBuilder()).execute(options);
};