diff --git a/comms.js b/comms.js
index f59a45962..74c150c6c 100644
--- a/comms.js
+++ b/comms.js
@@ -2,7 +2,15 @@ Puck.debug=3;
// FIXME: use UART lib so that we handle errors properly
var Comms = {
-uploadApp : app => {
+reset : () => {
+ return new Promise((resolve,reject) => {
+ Puck.write("\x03reset();\n", (result) => {
+ if (result===null) return reject("");
+ setTimeout(resolve,500);
+ });
+ });
+},
+uploadApp : (app,skipReset) => {
return AppInfo.getFiles(app, httpGet).then(fileContents => {
return new Promise((resolve,reject) => {
var appJSONFile = fileContents.find(f=>f.name=="+"+app.id);
@@ -16,16 +24,18 @@ uploadApp : app => {
}
fileContents = fileContents.map(storageFile=>storageFile.cmd).join("\n")+"\n";
console.log("uploadApp",fileContents);
- // reset to ensure we have enough memory to upload what we need to
- Puck.write("\x03reset();\n", (result) => {
- if (result===null) return reject("");
- setTimeout(() => { // wait for reset
- Puck.write("\x10E.showMessage('Uploading...')\n"+fileContents+"\x10E.showMessage('Hold BTN3\\nto reload')\n",(result) => {
- if (result===null) return reject("");
- resolve(appJSON);
- });
- },500);
- });
+ function doUpload() {
+ Puck.write(`\x10E.showMessage('Uploading\\n${app.id}...')\n${fileContents}\x10E.showMessage('Hold BTN3\\nto reload')\n`,(result) => {
+ if (result===null) return reject("");
+ resolve(appJSON);
+ });
+ }
+ if (skipReset) {
+ doUpload();
+ } else {
+ // reset to ensure we have enough memory to upload what we need to
+ Comms.reset().then(doUpload)
+ }
});
});
},
@@ -46,24 +56,21 @@ removeApp : app => { // expects an app structure
return `\x10require("Storage").erase(${toJS(file.name)});\n`;
}).join("");
console.log("removeApp", cmds);
- return new Promise((resolve,reject) => {
- Puck.write("\x03"+cmds+"\x10E.showMessage('Hold BTN3\\nto reload')\n",(result) => {
+ return Comms.reset().then(new Promise((resolve,reject) => {
+ Puck.write(`\x03\x10E.showMessage('Erasing\\n${app.id}...')${cmds}\x10E.showMessage('Hold BTN3\\nto reload')\n`,(result) => {
if (result===null) return reject("");
resolve();
});
- });
+ }));
},
removeAllApps : () => {
- return new Promise((resolve,reject) => {
- // Use eval here so we wait for it to finish
- Puck.eval('require("Storage").eraseAll()||true', (result,err) => {
+ return Comms.reset().then(new Promise((resolve,reject) => {
+ // Use write with newline here so we wait for it to finish
+ Puck.write('\x10E.showMessage("Erasing...");require("Storage").eraseAll();Bluetooth.println("OK")\n', (result,err) => {
if (result===null) return reject(err || "");
- Puck.write('\x03\x10reset()\n',(result) => {
- if (result===null) return reject("");
- resolve();
- });
- });
- });
+ resolve();
+ }, true /* wait for newline */);
+ }));
},
setTime : () => {
return new Promise((resolve,reject) => {
diff --git a/index.js b/index.js
index 12391ee6a..572009920 100644
--- a/index.js
+++ b/index.js
@@ -29,17 +29,31 @@ function showToast(message, type) {
msgDiv.remove();
}, 5000);
}
-var progressToast;
-Puck.writeProgress = function(charsSent, charsTotal) {
- if (charsSent===undefined) {
- if (progressToast) progressToast.remove();
- progressToast = undefined;
- return;
- }
- var percent = Math.round(charsSent*100/charsTotal);
+var progressToast; // the DOM element
+var progressSticky; // showProgress(,,"sticky") don't remove until hideProgress("sticky")
+var progressInterval; // the interval used if showProgress(..., "animate")
+var progressPercent; // the current progress percentage
+function showProgress(text, percent, sticky) {
+ if (sticky=="sticky")
+ progressSticky = true;
if (!progressToast) {
+ if (progressInterval) {
+ clearInterval(progressInterval);
+ progressInterval = undefined;
+ }
+ if (percent == "animate") {
+ progressInterval = setInterval(function() {
+ progressPercent += 2;
+ if (progressPercent>100) progressPercent=0;
+ showProgress(undefined, progressPercent);
+ }, 100);
+ percent = 0;
+ }
+ progressPercent = percent;
+
var toastcontainer = document.getElementById("toastcontainer");
progressToast = htmlElement(`
+ ${text ? `
${text}
`:``}
@@ -51,6 +65,26 @@ Puck.writeProgress = function(charsSent, charsTotal) {
pt.style.width = percent+"%";
}
}
+function hideProgress(sticky) {
+ if (progressSticky && sticky!="sticky")
+ return;
+ progressSticky = false;
+ if (progressInterval) {
+ clearInterval(progressInterval);
+ progressInterval = undefined;
+ }
+ if (progressToast) progressToast.remove();
+ progressToast = undefined;
+}
+
+Puck.writeProgress = function(charsSent, charsTotal) {
+ if (charsSent===undefined) {
+ hideProgress();
+ return;
+ }
+ var percent = Math.round(charsSent*100/charsTotal);
+ showProgress(undefined, percent);
+}
function showPrompt(title, text, buttons) {
if (!buttons) buttons={yes:1,no:1};
return new Promise((resolve,reject) => {
@@ -78,7 +112,7 @@ function showPrompt(title, text, buttons) {
document.body.append(modal);
modal.querySelector("a[href='#close']").addEventListener("click",event => {
event.preventDefault();
- reject();
+ reject("User cancelled");
modal.remove();
});
htmlToArray(modal.getElementsByTagName("button")).forEach(button => {
@@ -86,7 +120,7 @@ function showPrompt(title, text, buttons) {
event.preventDefault();
var isYes = event.target.getAttribute("isyes")=="1";
if (isYes) resolve();
- else reject();
+ else reject("User cancelled");
modal.remove();
});
});
@@ -132,7 +166,14 @@ function handleCustomApp(app) {
var app = event.data;
console.log("Received custom app", app);
modal.remove();
- Comms.uploadApp(app).then(resolve,reject);
+ showProgress(`Uploading ${app.name}`,undefined,"sticky");
+ Comms.uploadApp(app).then(()=>{
+ hideProgress("sticky");
+ resolve();
+ }).catch(e => {
+ hideProgress("sticky");
+ reject(e);
+ });
}, false);
});
}
@@ -270,7 +311,9 @@ function refreshLibrary() {
// upload
icon.classList.remove("icon-upload");
icon.classList.add("loading");
+ showProgress(`Uploading ${app.name}`,undefined,"sticky");
Comms.uploadApp(app).then((appJSON) => {
+ hideProgress("sticky");
if (appJSON) appsInstalled.push(appJSON);
showToast(app.name+" Uploaded!", "success");
icon.classList.remove("loading");
@@ -278,6 +321,7 @@ function refreshLibrary() {
refreshMyApps();
refreshLibrary();
}).catch(err => {
+ hideProgress("sticky");
showToast("Upload failed, "+err, "error");
icon.classList.remove("loading");
icon.classList.add("icon-upload");
@@ -334,16 +378,19 @@ function removeApp(app) {
}
function updateApp(app) {
+ showProgress(`Upgrading ${app.name}`,undefined,"sticky");
Comms.removeApp(app).then(()=>{
showToast(app.name+" removed successfully. Updating...",);
appsInstalled = appsInstalled.filter(a=>a.id!=app.id);
return Comms.uploadApp(app);
}).then((appJSON) => {
+ hideProgress("sticky");
if (appJSON) appsInstalled.push(appJSON);
showToast(app.name+" Updated!", "success");
refreshMyApps();
refreshLibrary();
}, err=>{
+ hideProgress("sticky");
showToast(app.name+" update failed, "+err,"error");
});
}
@@ -413,14 +460,20 @@ return `
function getInstalledApps() {
showLoadingIndicator("myappscontainer");
+ showProgress(`Getting app list...`,undefined,"sticky");
// Get apps and files
return Comms.getInstalledApps()
.then(appJSON => {
+ hideProgress("sticky");
appsInstalled = appJSON;
refreshMyApps();
refreshLibrary();
})
- .then(() => handleConnectionChange(true));
+ .then(() => handleConnectionChange(true))
+ .catch(err=>{
+ hideProgress("sticky");
+ return Promise.reject();
+ });
}
var connectMyDeviceBtn = document.getElementById("connectmydevice");
@@ -475,12 +528,15 @@ document.getElementById("settime").addEventListener("click",event=>{
});
document.getElementById("removeall").addEventListener("click",event=>{
showPrompt("Remove All","Really remove all apps?").then(() => {
+ showProgress("Removing all apps","animate", "sticky");
return Comms.removeAllApps();
}).then(()=>{
+ hideProgress("sticky");
appsInstalled = [];
showToast("All apps removed","success");
return getInstalledApps();
}).catch(err=>{
+ hideProgress("sticky");
showToast("App removal failed, "+err,"error");
});
});
@@ -495,18 +551,25 @@ document.getElementById("installdefault").addEventListener("click",event=>{
appCount = defaultApps.length;
return showPrompt("Install Defaults","Remove everything and install default apps?");
}).then(() => {
+ showProgress("Removing all apps","animate", "sticky");
return Comms.removeAllApps();
}).then(()=>{
+ hideProgress("sticky");
appsInstalled = [];
showToast(`Existing apps removed. Installing ${appCount} apps...`);
- return new Promise(resolve => {
+ return new Promise((resolve,reject) => {
function upload() {
var app = defaultApps.shift();
if (app===undefined) return resolve();
+ showProgress(`${app.name} (${appCount-defaultApps.length}/${appCount})`,undefined,"sticky");
Comms.uploadApp(app).then((appJSON) => {
+ hideProgress("sticky");
if (appJSON) appsInstalled.push(appJSON);
showToast(`(${appCount-defaultApps.length}/${appCount}) ${app.name} Uploaded`);
upload();
+ }).catch(function() {
+ hideProgress("sticky");
+ reject()
});
}
upload();