diff --git a/app/ui.js b/app/ui.js index aaabad72..67af7cda 100644 --- a/app/ui.js +++ b/app/ui.js @@ -39,22 +39,20 @@ const UI = { reconnect_callback: null, reconnect_password: null, - prime(callback) { - if (document.readyState === "interactive" || document.readyState === "complete") { - UI.load(callback); - } else { - document.addEventListener('DOMContentLoaded', UI.load.bind(UI, callback)); - } - }, + prime() { + return WebUtil.initSettings().then(() => { + if (document.readyState === "interactive" || document.readyState === "complete") { + return UI.start(); + } - // Setup rfb object, load settings from browser storage, then call - // UI.init to setup the UI/menus - load(callback) { - WebUtil.initSettings(UI.start, callback); + return new Promise((resolve, reject) => { + document.addEventListener('DOMContentLoaded', () => UI.start().then(resolve).catch(reject)); + }); + }); }, // Render default UI and initialize settings menu - start(callback) { + start() { UI.initSettings(); @@ -105,9 +103,7 @@ const UI = { UI.openConnectPanel(); } - if (typeof callback === "function") { - callback(UI.rfb); - } + return Promise.resolve(UI.rfb); }, initFullscreen() { @@ -1646,18 +1642,13 @@ const UI = { // Set up translations const LINGUAS = ["cs", "de", "el", "es", "ko", "nl", "pl", "sv", "tr", "zh_CN", "zh_TW"]; l10n.setup(LINGUAS); -if (l10n.language !== "en" && l10n.dictionary === undefined) { - WebUtil.fetchJSON('app/locale/' + l10n.language + '.json', (translations) => { - l10n.dictionary = translations; - - // wait for translations to load before loading the UI - UI.prime(); - }, (err) => { - Log.Error("Failed to load translations: " + err); - UI.prime(); - }); -} else { +if (l10n.language === "en" || l10n.dictionary !== undefined) { UI.prime(); +} else { + WebUtil.fetchJSON('app/locale/' + l10n.language + '.json') + .then((translations) => { l10n.dictionary = translations; }) + .catch(err => Log.Error("Failed to load translations: " + err)) + .then(UI.prime); } export default UI; diff --git a/app/webutil.js b/app/webutil.js index 922ddc10..98e1d9e6 100644 --- a/app/webutil.js +++ b/app/webutil.js @@ -114,22 +114,14 @@ export function eraseCookie(name) { let settings = {}; -export function initSettings(callback /*, ...callbackArgs */) { - "use strict"; - const callbackArgs = Array.prototype.slice.call(arguments, 1); - if (window.chrome && window.chrome.storage) { - window.chrome.storage.sync.get((cfg) => { - settings = cfg; - if (callback) { - callback.apply(this, callbackArgs); - } - }); - } else { +export function initSettings() { + if (!window.chrome || !window.chrome.storage) { settings = {}; - if (callback) { - callback.apply(this, callbackArgs); - } + return Promise.resolve(); } + + return new Promise(resolve => window.chrome.storage.sync.get(resolve)) + .then((cfg) => { settings = cfg; }); } // Update the settings cache, but do not write to permanent storage @@ -218,28 +210,30 @@ export function injectParamIfMissing(path, param, value) { // IE11 support or polyfill promises and fetch in IE11. // resolve will receive an object on success, while reject // will receive either an event or an error on failure. -export function fetchJSON(path, resolve, reject) { - // NB: IE11 doesn't support JSON as a responseType - const req = new XMLHttpRequest(); - req.open('GET', path); +export function fetchJSON(path) { + return new Promise((resolve, reject) => { + // NB: IE11 doesn't support JSON as a responseType + const req = new XMLHttpRequest(); + req.open('GET', path); - req.onload = () => { - if (req.status === 200) { - let resObj; - try { - resObj = JSON.parse(req.responseText); - } catch (err) { - reject(err); + req.onload = () => { + if (req.status === 200) { + let resObj; + try { + resObj = JSON.parse(req.responseText); + } catch (err) { + reject(err); + } + resolve(resObj); + } else { + reject(new Error("XHR got non-200 status while trying to load '" + path + "': " + req.status)); } - resolve(resObj); - } else { - reject(new Error("XHR got non-200 status while trying to load '" + path + "': " + req.status)); - } - }; + }; - req.onerror = evt => reject(new Error("XHR encountered an error while trying to load '" + path + "': " + evt.message)); + req.onerror = evt => reject(new Error("XHR encountered an error while trying to load '" + path + "': " + evt.message)); - req.ontimeout = evt => reject(new Error("XHR timed out while trying to load '" + path + "'")); + req.ontimeout = evt => reject(new Error("XHR timed out while trying to load '" + path + "'")); - req.send(); + req.send(); + }); } diff --git a/tests/test.webutil.js b/tests/test.webutil.js index 27397041..72e19421 100644 --- a/tests/test.webutil.js +++ b/tests/test.webutil.js @@ -39,7 +39,7 @@ describe('WebUtil', function () { window.localStorage.getItem = sinon.stub(); window.localStorage.removeItem = sinon.stub(); - WebUtil.initSettings(); + return WebUtil.initSettings(); }); afterEach(function () { Object.defineProperty(window, "localStorage", origLocalStorage); @@ -132,7 +132,7 @@ describe('WebUtil', function () { settings = {}; csSandbox.spy(window.chrome.storage.sync, 'set'); csSandbox.spy(window.chrome.storage.sync, 'remove'); - WebUtil.initSettings(); + return WebUtil.initSettings(); }); afterEach(function () { csSandbox.restore();