UNPKG

cordova-plugin-app-preferences

Version:

Application preferences plugin and preference pane generator

252 lines (199 loc) 7.61 kB
var mappings = require("./mappings"), platformName = "android"; module.exports = function (context) { var req = context ? context.requireCordovaModule : require, Q = req('q'), path = req('path'), ET = req('elementtree'), cordova = req('cordova'), cordova_lib = cordova.cordova_lib, ConfigParser = cordova_lib.configparser, cordova_util = req('cordova-lib/src/cordova/util'), fs = require("./filesystem")(Q, req('fs'), path), platforms = {}; // fs, path, ET, cordova_util, ConfigParser function mapConfig(config) { var element = { attrs: {}, children: [] }; if (!config.type) { throw "no type defined for "+JSON.stringify (config, null, "\t"); } var mapping = mappings[config.type]; if (!mapping) throw "no mapping for "+ config.type; element.tagname = mapping[platformName]; if (mapping.required) { mapping.required.forEach (function (k) { if (!(k in config)) { throw ['attribute', k, 'not found for', config.title, '(' + config.type + ')'].join (" "); } }); } if (mapping.attrs) { for (var attrName in mapping.attrs) { if (!config.hasOwnProperty(attrName)) continue; var attrConfig = mapping.attrs[attrName]; var elementKey = attrConfig[platformName]; var targetCheck = elementKey.split ('@'); var targetAttr; if (targetCheck.length === 2 && targetCheck[0] === '') { targetAttr = targetCheck[1]; if (!element.attrs) element.attrs = {}; element.attrs[targetAttr] = []; } if (attrConfig.value) { if (!attrConfig.value[config[attrName]] || !attrConfig.value[config[attrName]][platformName]) throw "no mapping for type: "+ config.type + ", attr: " + attrName + ", value: " + config[attrName]; if (targetAttr) element.attrs[targetAttr].push (attrConfig.value[config[attrName]][platformName]); else element[elementKey] = attrConfig.value[config[attrName]][platformName] } else { if (targetAttr) element.attrs[targetAttr].push (config[attrName]); else element[elementKey] = config[attrName]; } } } if (mapping.fixup && mapping.fixup[platformName]) { mapping.fixup[platformName] (element, config, mapping); } return element; } function buildNode(parent, config, stringsArrays) { for (var attr in config.attrs) { if (config.attrs[attr] && config.attrs[attr].constructor === Array) config.attrs[attr] = config.attrs[attr].join ('|'); } var newNode = new ET.SubElement(parent, config.tagname); newNode.attrib = config.attrs; if (config.strings) { console.log("will push strings array "+JSON.stringify(config.strings)); stringsArrays.push(config.strings); } if (config.children) { config.children.forEach(function(child){ buildNode(newNode, child, stringsArrays); }); } } // build Android settings XML function buildSettings(configJson) { var screenNode = new ET.Element('PreferenceScreen'), resourcesNode = new ET.Element('resources'), stringsArrays = []; screenNode.set('xmlns:android', 'http://schemas.android.com/apk/res/android'); // Generate base settings file configJson.forEach(function (preference) { var node = mapConfig(preference); if (preference.type === 'group' && preference.items && preference.items.length) { preference.items.forEach(function(childNode) { node.children.push(mapConfig(childNode)); }); } buildNode(screenNode, node, stringsArrays); }); // Generate resource file stringsArrays.forEach(function (stringsArray) { var titlesXml = new ET.SubElement(resourcesNode, 'string-array'), valuesXml = new ET.SubElement(resourcesNode, 'string-array'); titlesXml.set("name", "apppreferences_" + stringsArray.name); valuesXml.set("name", "apppreferences_" + stringsArray.name + 'Values'); for (var i=0, l=stringsArray.titles.length; i<l; i++) { var titleItemXml = new ET.SubElement(titlesXml, "item"), valueItemXml = new ET.SubElement(valuesXml, "item"); titleItemXml.text = stringsArray.titles[i]; valueItemXml.text = stringsArray.values[i]; } }); return { preferencesDocument: new ET.ElementTree(screenNode), preferencesStringDocument: new ET.ElementTree(resourcesNode) }; } function build(config) { var settingsDocuments = buildSettings(config), preferencesDocument = settingsDocuments.preferencesDocument, preferencesStringDocument = settingsDocuments.preferencesStringDocument; return fs.exists('platforms/android') // Write preferences xml file .then(function () { return fs.mkdir('platforms/android/res/xml'); }) .then(function () { return fs.writeFile('platforms/android/res/xml/apppreferences.xml', preferencesDocument.write()); }) // Write localization resource file .then(function () { return fs.mkdir('platforms/android/res/values'); }) .then(function (prefs) { return fs.writeFile('platforms/android/res/values/apppreferences.xml', preferencesStringDocument.write()); }) .then(function () { console.log('android preferences file was successfully generated'); }) .catch(function (err) { if (err.code === 'NEXIST') { console.log("Platform android not found: skipping"); return; } throw err; }); } function afterPluginInstall () { return fs.exists('platforms/android') // Import preferences into native android project .then(function () { return fs.readFile(path.resolve(__dirname, '../../src/android/AppPreferencesActivity.template')); }) .then(function (tmpl) { var projectRoot = cordova_lib.cordova.findProjectRoot(process.cwd()), projectXml = cordova_util.projectConfig(projectRoot), projectConfig = new ConfigParser(projectXml); var packageName = projectConfig.android_packageName() || projectConfig.packageName(); return ( //'package me.apla.cordova;\n\n' + //'import ' + packageName + '.R;\n\n' + tmpl.toString ('utf8').replace (/ANDROID_PACKAGE_NAME/g, packageName) ); }) .then(function (data) { var androidPackagePath = "me.apla.cordova".replace (/\./g, '/'); var activityFileName= path.join ('platforms/android/src', androidPackagePath, 'AppPreferencesActivity.java'); return fs.writeFile(activityFileName, data); }) .catch(function (err) { if (err.code === 'NEXIST') { console.log("Platform android not found: skipping"); return; } throw err; }); } function clean(config) { var androidPackagePath = "me.apla.cordova".replace (/\./g, '/'); var activityFileName = path.join ('platforms/android/src', androidPackagePath, 'AppPreferencesActivity.java'); return fs.exists('platforms/android') // Remove preferences xml file .then(function () { return fs.unlink('platforms/android/res/xml/apppreferences.xml'); }) // Remove localization resource file .then(function (prefs) { return fs.unlink('platforms/android/res/values/apppreferences.xml'); }) // Remove preferences from native android project .then(function (data) { return fs.unlink(activityFileName); }) .then(function () { console.log('android preferences file was successfully cleaned'); }) .catch(function (err) { if (err.code === 'NEXIST') { console.log("Platform android not found: skipping"); return; } else if (err.code === 'ENOENT' && err.path === activityFileName) { // Activity not generated, that's fine return; } throw err; }); } return { mapConfig: mapConfig, buildSettings: buildSettings, build: build, afterPluginInstall: afterPluginInstall, clean: clean }; };