diff --git a/app/scripts/app.js b/app/scripts/app.js index 38e74e2b..6dcaea4e 100644 --- a/app/scripts/app.js +++ b/app/scripts/app.js @@ -33,7 +33,10 @@ ready(() => { .then(loadConfigs) .then(initModules) .then(loadRemoteConfig) - .then(showApp); + .then(showApp) + .catch(e => { + appModel.appLogger.error('Error starting app', e); + }); function loadMixins() { require('./mixins/view'); @@ -68,21 +71,18 @@ ready(() => { } function loadRemoteConfig() { - return new Promise((resolve, reject) => { + return Promise.resolve().then(() => { SettingsManager.setBySettings(appModel.settings); const configParam = getConfigParam(); if (configParam) { - appModel.loadConfig(configParam, err => { + return appModel.loadConfig(configParam).then(() => { SettingsManager.setBySettings(appModel.settings); - if (err && !appModel.settings.get('cacheConfigSettings')) { + }).catch(e => { + if (!appModel.settings.get('cacheConfigSettings')) { showSettingsLoadError(); - reject(err); - } else { - resolve(); + throw e; } }); - } else { - resolve(); } }); } diff --git a/app/scripts/models/app-model.js b/app/scripts/models/app-model.js index fdae77ef..c23c287f 100644 --- a/app/scripts/models/app-model.js +++ b/app/scripts/models/app-model.js @@ -17,6 +17,7 @@ const Format = require('../util/format'); const UrlUtil = require('../util/url-util'); const AutoType = require('../auto-type'); const Launcher = require('../comp/launcher'); +const PluginManager = require('../plugins/plugin-manager'); require('../mixins/protected-value-ex'); @@ -49,39 +50,42 @@ const AppModel = Backbone.Model.extend({ _.forEach(Storage, prv => prv.init()); }, - loadConfig: function(configLocation, callback) { - this.appLogger.debug('Loading config from', configLocation); - const ts = this.appLogger.ts(); - const xhr = new XMLHttpRequest(); - xhr.open('GET', configLocation); - xhr.responseType = 'json'; - xhr.send(); - xhr.addEventListener('load', () => { - let response = xhr.response; - if (!response) { - const errorDesc = xhr.statusText === 'OK' ? 'Malformed JSON' : xhr.statusText; - this.appLogger.error('Error loading app config', errorDesc); - return callback(true); - } - if (typeof response === 'string') { - try { - response = JSON.parse(response); - } catch (e) { - this.appLogger.error('Error parsing response', e, response); - return callback(true); + loadConfig: function(configLocation) { + return new Promise((resolve, reject) => { + this.appLogger.debug('Loading config from', configLocation); + const ts = this.appLogger.ts(); + const xhr = new XMLHttpRequest(); + xhr.open('GET', configLocation); + xhr.responseType = 'json'; + xhr.send(); + xhr.addEventListener('load', () => { + let response = xhr.response; + if (!response) { + const errorDesc = xhr.statusText === 'OK' ? 'Malformed JSON' : xhr.statusText; + this.appLogger.error('Error loading app config', errorDesc); + return reject('Error loading app config'); } - } - if (!response.settings) { - this.appLogger.error('Invalid app config, no settings section', response); - return callback(true); - } - this.appLogger.info('Loaded app config from', configLocation, this.appLogger.ts(ts)); - this.applyUserConfig(response); - callback(); - }); - xhr.addEventListener('error', () => { - this.appLogger.error('Error loading app config', xhr.statusText, xhr.status); - callback(true); + if (typeof response === 'string') { + try { + response = JSON.parse(response); + } catch (e) { + this.appLogger.error('Error parsing response', e, response); + return reject('Error parsing response'); + } + } + if (!response.settings) { + this.appLogger.error('Invalid app config, no settings section', response); + return reject('Invalid app config, no settings section'); + } + this.appLogger.info('Loaded app config from', configLocation, this.appLogger.ts(ts)); + resolve(response); + }); + xhr.addEventListener('error', () => { + this.appLogger.error('Error loading app config', xhr.statusText, xhr.status); + reject('Error loading app config'); + }); + }).then(config => { + return this.applyUserConfig(config); }); }, @@ -104,6 +108,9 @@ const AppModel = Backbone.Model.extend({ .reverse() .forEach(fi => this.fileInfos.unshift(fi)); } + if (config.plugins) { + return Promise.all(config.plugins.map(plugin => PluginManager.installIfNew(plugin.url, plugin.manifest))); + } }, addFile: function(file) { diff --git a/app/scripts/plugins/plugin-manager.js b/app/scripts/plugins/plugin-manager.js index bc7c4676..8786567f 100644 --- a/app/scripts/plugins/plugin-manager.js +++ b/app/scripts/plugins/plugin-manager.js @@ -45,6 +45,11 @@ const PluginManager = Backbone.Model.extend({ }); }, + installIfNew(url, expectedManifest) { + const plugin = this.get('plugins').find({ url }); + return plugin ? Promise.resolve() : this.install(url, expectedManifest); + }, + uninstall(id) { const plugins = this.get('plugins'); const plugin = plugins.get(id); diff --git a/util/config-example.json b/util/config-example.json index b245a143..f471670e 100644 --- a/util/config-example.json +++ b/util/config-example.json @@ -49,5 +49,8 @@ "path": "webdav-url", "options": { "user": "", "password": "" } }], + "plugins": [{ + "url": "" + }], "showOnlyFilesFromConfig": false }