diff --git a/browser/devtools/webide/content/webide.js b/browser/devtools/webide/content/webide.js index 04ebb37c950..4b996fdd21e 100644 --- a/browser/devtools/webide/content/webide.js +++ b/browser/devtools/webide/content/webide.js @@ -138,6 +138,8 @@ let UI = { this.updateProjectButton(); this.updateProjectEditorHeader(); break; + case "install-progress": + this.updateProgress(Math.round(100 * details.bytesSent / details.totalBytes)); }; }, @@ -169,34 +171,71 @@ let UI = { } }, + /********** BUSY UI **********/ + + _busyTimeout: null, + _busyOperationDescription: null, + _busyPromise: null, + + updateProgress: function(percent) { + let progress = document.querySelector("#action-busy-determined"); + progress.mode = "determined"; + progress.value = percent; + this.setupBusyTimeout(); + }, + busy: function() { this.hidePanels(); - document.querySelector("window").classList.add("busy") + let win = document.querySelector("window"); + win.classList.add("busy") + win.classList.add("busy-undetermined"); this.updateCommands(); }, unbusy: function() { - document.querySelector("window").classList.remove("busy") + let win = document.querySelector("window"); + win.classList.remove("busy") + win.classList.remove("busy-determined"); + win.classList.remove("busy-undetermined"); this.updateCommands(); this._busyPromise = null; }, + setupBusyTimeout: function() { + this.cancelBusyTimeout(); + this._busyTimeout = setTimeout(() => { + this.unbusy(); + UI.reportError("error_operationTimeout", this._busyOperationDescription); + this._busyPromise.reject("promise timeout: " + this._busyOperationDescription); + }, 30000); + }, + + cancelBusyTimeout: function() { + clearTimeout(this._busyTimeout); + }, + + busyWithProgressUntil: function(promise, operationDescription) { + this.busyUntil(promise, operationDescription); + let win = document.querySelector("window"); + let progress = document.querySelector("#action-busy-determined"); + progress.mode = "undetermined"; + win.classList.add("busy-determined"); + win.classList.remove("busy-undetermined"); + }, + busyUntil: function(promise, operationDescription) { // Freeze the UI until the promise is resolved. A 30s timeout // will unfreeze the UI, just in case the promise never gets // resolved. this._busyPromise = promise; - let timeout = setTimeout(() => { - this.unbusy(); - UI.reportError("error_operationTimeout", operationDescription); - promise.reject("promise timeout: " + operationDescription); - }, 30000); + this._busyOperationDescription = operationDescription; + this.setupBusyTimeout(); this.busy(); promise.then(() => { - clearTimeout(timeout); + this.cancelBusyTimeout(); this.unbusy(); }, (e) => { - clearTimeout(timeout); + this.cancelBusyTimeout(); UI.reportError("error_operationFail", operationDescription); console.error(e); this.unbusy(); @@ -396,6 +435,12 @@ let UI = { return; } + // Save last project location + + if (project.location) { + Services.prefs.setCharPref("devtools.webide.lastprojectlocation", project.location); + } + // Make sure the directory exist before we show Project Editor let forceDetailsOnly = false; @@ -420,10 +465,6 @@ let UI = { this.getProjectEditor().then(() => { this.updateProjectEditorHeader(); }, console.error); - - if (project.location) { - Services.prefs.setCharPref("devtools.webide.lastprojectlocation", project.location); - } }, /********** DECK **********/ @@ -823,12 +864,11 @@ let Cmds = { play: function() { switch(AppManager.selectedProject.type) { case "packaged": + return UI.busyWithProgressUntil(AppManager.installAndRunProject(), "installing and running app"); case "hosted": return UI.busyUntil(AppManager.installAndRunProject(), "installing and running app"); - break; case "runtimeApp": return UI.busyUntil(AppManager.runRuntimeApp(), "running app"); - break; } return promise.reject(); }, diff --git a/browser/devtools/webide/content/webide.xul b/browser/devtools/webide/content/webide.xul index 16cac8db20f..ec31544858b 100644 --- a/browser/devtools/webide/content/webide.xul +++ b/browser/devtools/webide/content/webide.xul @@ -102,7 +102,10 @@ - + + + + diff --git a/browser/devtools/webide/modules/app-manager.js b/browser/devtools/webide/modules/app-manager.js index a82a1d2fc53..a62b8668a69 100644 --- a/browser/devtools/webide/modules/app-manager.js +++ b/browser/devtools/webide/modules/app-manager.js @@ -59,11 +59,15 @@ exports.AppManager = AppManager = { this.trackWiFiRuntimes(); this.trackSimulatorRuntimes(); + this.onInstallProgress = this.onInstallProgress.bind(this); + AppActorFront.on("install-progress", this.onInstallProgress); + this.observe = this.observe.bind(this); Services.prefs.addObserver(WIFI_SCANNING_PREF, this, false); }, uninit: function() { + AppActorFront.off("install-progress", this.onInstallProgress); this._unlistenToApps(); this.selectedProject = null; this.selectedRuntime = null; @@ -134,6 +138,10 @@ exports.AppManager = AppManager = { this.update("connection"); }, + onInstallProgress: function(event, details) { + this.update("install-progress", details); + }, + onWebAppsStoreready: function() { this.update("runtime-apps-found"); }, diff --git a/browser/devtools/webide/themes/webide.css b/browser/devtools/webide/themes/webide.css index ef876951957..fe16b3a8849 100644 --- a/browser/devtools/webide/themes/webide.css +++ b/browser/devtools/webide/themes/webide.css @@ -21,13 +21,15 @@ pointer-events: auto; } -#action-busy { +#action-busy-undetermined { height: 24px; width: 24px; } window.busy .action-button, -window:not(.busy) #action-busy { +window:not(.busy) #action-busy, +window.busy-undetermined #action-busy-determined, +window.busy-determined #action-busy-undetermined { display: none; }