If app is installed but older, offer 'update' button (fix #79).
Fix occasional 'null' error from clicking button rather than icon Tidy up button handling in 'Library'master
parent
d8e5af43be
commit
575954aaaf
85
index.js
85
index.js
|
|
@ -149,19 +149,10 @@ function refreshLibrary() {
|
||||||
}
|
}
|
||||||
|
|
||||||
panelbody.innerHTML = visibleApps.map((app,idx) => {
|
panelbody.innerHTML = visibleApps.map((app,idx) => {
|
||||||
var icon = "icon-upload";
|
var appInstalled = appsInstalled.find(a=>a.id==app.id);
|
||||||
var versionInfo = app.version || "";
|
var version = getVersionInfo(app, appInstalled);
|
||||||
if (app.custom)
|
var versionInfo = version.text;
|
||||||
icon = "icon-menu";
|
|
||||||
if (appsInstalled.find(a=>a.id==app.id)) {
|
|
||||||
icon = "icon-delete";
|
|
||||||
versionInfo+=" installed";
|
|
||||||
}
|
|
||||||
var buttons = "";
|
|
||||||
if (versionInfo) versionInfo = " <small>("+versionInfo+")</small>";
|
if (versionInfo) versionInfo = " <small>("+versionInfo+")</small>";
|
||||||
if (app.allow_emulator)
|
|
||||||
buttons += `<button class="btn btn-link btn-action btn-lg" title="Try in Emulator"><i class="icon icon-share" appid="${app.id}"></i></button>`;
|
|
||||||
buttons += `<button class="btn btn-link btn-action btn-lg"><i class="icon ${icon}" appid="${app.id}"></i></button>`;
|
|
||||||
return `<div class="tile column col-6 col-sm-12 col-xs-12">
|
return `<div class="tile column col-6 col-sm-12 col-xs-12">
|
||||||
<div class="tile-icon">
|
<div class="tile-icon">
|
||||||
<figure class="avatar"><img src="apps/${app.icon?`${app.id}/${app.icon}`:"unknown.png"}" alt="${escapeHtml(app.name)}"></figure>
|
<figure class="avatar"><img src="apps/${app.icon?`${app.id}/${app.icon}`:"unknown.png"}" alt="${escapeHtml(app.name)}"></figure>
|
||||||
|
|
@ -171,7 +162,11 @@ function refreshLibrary() {
|
||||||
<p class="tile-subtitle">${escapeHtml(app.description)}</p>
|
<p class="tile-subtitle">${escapeHtml(app.description)}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="tile-action">
|
<div class="tile-action">
|
||||||
${buttons}
|
<button class="btn btn-link btn-action btn-lg ${app.allow_emulator?"":"d-hide"}" appid="${app.id}" title="Try in Emulator"><i class="icon icon-share"></i></button>
|
||||||
|
<button class="btn btn-link btn-action btn-lg ${version.canUpdate?"":"d-hide"}" appid="${app.id}" title="Update App"><i class="icon icon-refresh"></i></button>
|
||||||
|
<button class="btn btn-link btn-action btn-lg ${!appInstalled?"":"d-hide"}" appid="${app.id}" title="Upload App"><i class="icon icon-upload"></i></button>
|
||||||
|
<button class="btn btn-link btn-action btn-lg ${appInstalled?"":"d-hide"}" appid="${app.id}" title="Remove App"><i class="icon icon-delete"></i></button>
|
||||||
|
<button class="btn btn-link btn-action btn-lg ${app.custom?"":"d-hide"}" appid="${app.id}" title="Customise and Upload App"><i class="icon icon-menu"></i></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;}).join("");
|
`;}).join("");
|
||||||
|
|
@ -181,10 +176,12 @@ function refreshLibrary() {
|
||||||
tab.setAttribute("data-badge", appJSON.length);
|
tab.setAttribute("data-badge", appJSON.length);
|
||||||
htmlToArray(panelbody.getElementsByTagName("button")).forEach(button => {
|
htmlToArray(panelbody.getElementsByTagName("button")).forEach(button => {
|
||||||
button.addEventListener("click",event => {
|
button.addEventListener("click",event => {
|
||||||
var icon = event.target;
|
var button = event.currentTarget;
|
||||||
var appid = icon.getAttribute("appid");
|
var icon = button.firstChild;
|
||||||
var app = appJSON.find(app=>app.id==appid);
|
var appid = button.getAttribute("appid");
|
||||||
if (!app) return;
|
var app = appNameToApp(appid);
|
||||||
|
if (!app) throw new Error("App "+appid+" not found");
|
||||||
|
// check icon to figure out what we should do
|
||||||
if (icon.classList.contains("icon-share")) {
|
if (icon.classList.contains("icon-share")) {
|
||||||
// emulator
|
// emulator
|
||||||
var file = app.storage.find(f=>f.name[0]=='-');
|
var file = app.storage.find(f=>f.name[0]=='-');
|
||||||
|
|
@ -196,6 +193,7 @@ function refreshLibrary() {
|
||||||
var url = baseurl+"apps/"+app.id+"/"+file.url;
|
var url = baseurl+"apps/"+app.id+"/"+file.url;
|
||||||
window.open(`https://espruino.com/ide/emulator.html?codeurl=${url}&upload`);
|
window.open(`https://espruino.com/ide/emulator.html?codeurl=${url}&upload`);
|
||||||
} else if (icon.classList.contains("icon-upload")) {
|
} else if (icon.classList.contains("icon-upload")) {
|
||||||
|
// upload
|
||||||
icon.classList.remove("icon-upload");
|
icon.classList.remove("icon-upload");
|
||||||
icon.classList.add("loading");
|
icon.classList.add("loading");
|
||||||
Comms.uploadApp(app).then((appJSON) => {
|
Comms.uploadApp(app).then((appJSON) => {
|
||||||
|
|
@ -204,12 +202,14 @@ function refreshLibrary() {
|
||||||
icon.classList.remove("loading");
|
icon.classList.remove("loading");
|
||||||
icon.classList.add("icon-delete");
|
icon.classList.add("icon-delete");
|
||||||
refreshMyApps();
|
refreshMyApps();
|
||||||
|
refreshLibrary();
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
showToast("Upload failed, "+err, "error");
|
showToast("Upload failed, "+err, "error");
|
||||||
icon.classList.remove("loading");
|
icon.classList.remove("loading");
|
||||||
icon.classList.add("icon-upload");
|
icon.classList.add("icon-upload");
|
||||||
});
|
});
|
||||||
} else if (icon.classList.contains("icon-menu")) {
|
} else if (icon.classList.contains("icon-menu")) {
|
||||||
|
// custom HTML update
|
||||||
if (app.custom) {
|
if (app.custom) {
|
||||||
icon.classList.remove("icon-menu");
|
icon.classList.remove("icon-menu");
|
||||||
icon.classList.add("loading");
|
icon.classList.add("loading");
|
||||||
|
|
@ -219,16 +219,23 @@ function refreshLibrary() {
|
||||||
icon.classList.remove("loading");
|
icon.classList.remove("loading");
|
||||||
icon.classList.add("icon-delete");
|
icon.classList.add("icon-delete");
|
||||||
refreshMyApps();
|
refreshMyApps();
|
||||||
|
refreshLibrary();
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
showToast("Customise failed, "+err, "error");
|
showToast("Customise failed, "+err, "error");
|
||||||
icon.classList.remove("loading");
|
icon.classList.remove("loading");
|
||||||
icon.classList.add("icon-menu");
|
icon.classList.add("icon-menu");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else if (icon.classList.contains("icon-delete")) {
|
||||||
|
// Remove app
|
||||||
icon.classList.remove("icon-delete");
|
icon.classList.remove("icon-delete");
|
||||||
icon.classList.add("loading");
|
icon.classList.add("loading");
|
||||||
removeApp(app);
|
removeApp(app);
|
||||||
|
} else if (icon.classList.contains("icon-refresh")) {
|
||||||
|
// Update app
|
||||||
|
icon.classList.remove("icon-refresh");
|
||||||
|
icon.classList.add("loading");
|
||||||
|
updateApp(app);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -239,7 +246,8 @@ refreshLibrary();
|
||||||
|
|
||||||
function removeApp(app) {
|
function removeApp(app) {
|
||||||
return showPrompt("Delete","Really remove '"+app.name+"'?").then(() => {
|
return showPrompt("Delete","Really remove '"+app.name+"'?").then(() => {
|
||||||
Comms.removeApp(app).then(()=>{
|
return Comms.removeApp(app);
|
||||||
|
}).then(()=>{
|
||||||
appsInstalled = appsInstalled.filter(a=>a.id!=app.id);
|
appsInstalled = appsInstalled.filter(a=>a.id!=app.id);
|
||||||
showToast(app.name+" removed successfully","success");
|
showToast(app.name+" removed successfully","success");
|
||||||
refreshMyApps();
|
refreshMyApps();
|
||||||
|
|
@ -247,6 +255,20 @@ function removeApp(app) {
|
||||||
}, err=>{
|
}, err=>{
|
||||||
showToast(app.name+" removal failed, "+err,"error");
|
showToast(app.name+" removal failed, "+err,"error");
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateApp(app) {
|
||||||
|
Comms.removeApp(app).then(()=>{
|
||||||
|
showToast(app.name+" removed successfully. Updating...",);
|
||||||
|
appsInstalled = appsInstalled.filter(a=>a.id!=app.id);
|
||||||
|
return Comms.uploadApp(app);
|
||||||
|
}).then((appJSON) => {
|
||||||
|
if (appJSON) appsInstalled.push(appJSON);
|
||||||
|
showToast(app.name+" Updated!", "success");
|
||||||
|
refreshMyApps();
|
||||||
|
refreshLibrary();
|
||||||
|
}, err=>{
|
||||||
|
showToast(app.name+" update failed, "+err,"error");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -281,34 +303,31 @@ function refreshMyApps() {
|
||||||
tab.setAttribute("data-badge", appsInstalled.length);
|
tab.setAttribute("data-badge", appsInstalled.length);
|
||||||
panelbody.innerHTML = appsInstalled.map(appJSON => {
|
panelbody.innerHTML = appsInstalled.map(appJSON => {
|
||||||
var app = appNameToApp(appJSON.id);
|
var app = appNameToApp(appJSON.id);
|
||||||
var version = "";
|
var version = getVersionInfo(app, appJSON);
|
||||||
if (!appJSON.version) {
|
|
||||||
version = "Unknown version";
|
|
||||||
if (app.version) version += ", latest "+app.version;
|
|
||||||
} else {
|
|
||||||
version = appJSON.version;
|
|
||||||
if (app.version == appJSON.version) version += ", up to date";
|
|
||||||
else if (app.version) version += ", latest "+app.version;
|
|
||||||
}
|
|
||||||
return `<div class="tile column col-6 col-sm-12 col-xs-12">
|
return `<div class="tile column col-6 col-sm-12 col-xs-12">
|
||||||
<div class="tile-icon">
|
<div class="tile-icon">
|
||||||
<figure class="avatar"><img src="apps/${app.icon?`${app.id}/${app.icon}`:"unknown.png"}" alt="${escapeHtml(app.name)}"></figure>
|
<figure class="avatar"><img src="apps/${app.icon?`${app.id}/${app.icon}`:"unknown.png"}" alt="${escapeHtml(app.name)}"></figure>
|
||||||
</div>
|
</div>
|
||||||
<div class="tile-content">
|
<div class="tile-content">
|
||||||
<p class="tile-title text-bold">${escapeHtml(app.name)} <small>(${version})</small></p>
|
<p class="tile-title text-bold">${escapeHtml(app.name)} <small>(${version.text})</small></p>
|
||||||
<p class="tile-subtitle">${escapeHtml(app.description)}</p>
|
<p class="tile-subtitle">${escapeHtml(app.description)}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="tile-action">
|
<div class="tile-action">
|
||||||
<button class="btn btn-link btn-action btn-lg"><i class="icon icon-delete" appid="${app.id}"></i></button>
|
<button class="btn btn-link btn-action btn-lg ${version.canUpdate?'':'d-hide'}" appid="${app.id}" title="Update App"><i class="icon icon-refresh"></i></button>
|
||||||
|
<button class="btn btn-link btn-action btn-lg" appid="${app.id}" title="Remove App"><i class="icon icon-delete"></i></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`}).join("");
|
`}).join("");
|
||||||
htmlToArray(panelbody.getElementsByTagName("button")).forEach(button => {
|
htmlToArray(panelbody.getElementsByTagName("button")).forEach(button => {
|
||||||
button.addEventListener("click",event => {
|
button.addEventListener("click",event => {
|
||||||
var icon = event.target;
|
var button = event.currentTarget;
|
||||||
var appid = icon.getAttribute("appid");
|
var icon = button.firstChild;
|
||||||
|
var appid = button.getAttribute("appid");
|
||||||
var app = appNameToApp(appid);
|
var app = appNameToApp(appid);
|
||||||
removeApp(app);
|
if (!app) throw new Error("App "+appid+" not found");
|
||||||
|
// check icon to figure out what we should do
|
||||||
|
if (icon.classList.contains("icon-delete")) removeApp(app);
|
||||||
|
if (icon.classList.contains("icon-refresh")) updateApp(app);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
21
utils.js
21
utils.js
|
|
@ -42,3 +42,24 @@ function appSorter(a,b) {
|
||||||
if (sa>sb) return 1;
|
if (sa>sb) return 1;
|
||||||
return (a.name==b.name) ? 0 : ((a.name<b.name) ? -1 : 1);
|
return (a.name==b.name) ? 0 : ((a.name<b.name) ? -1 : 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Given 2 JSON structures (1st from apps.json, 2nd from an installed app)
|
||||||
|
work out what to display re: versions and if we can update */
|
||||||
|
function getVersionInfo(appListing, appInstalled) {
|
||||||
|
var versionText = "";
|
||||||
|
var canUpdate = false;
|
||||||
|
if (!appInstalled) {
|
||||||
|
if (appListing.version)
|
||||||
|
versionText = "v"+appListing.version;
|
||||||
|
} else {
|
||||||
|
versionText = (appInstalled.version ? ("v"+appInstalled.version) : "Unknown version");
|
||||||
|
if (appListing.version != appInstalled.version) {
|
||||||
|
if (appListing.version) versionText += ", latest "+appListing.version;
|
||||||
|
canUpdate = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
text : versionText,
|
||||||
|
canUpdate : canUpdate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue