From 64048b12f1ce55dd9e4287ac12853750827801eb Mon Sep 17 00:00:00 2001 From: RKBoss6 Date: Mon, 1 Dec 2025 20:36:43 -0500 Subject: [PATCH 01/12] Refactor changeAppFavourite function for animations Refactor changeAppFavourite to include optional refresh parameter and update favorite count handling. --- js/index.js | 106 ++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 77 insertions(+), 29 deletions(-) diff --git a/js/index.js b/js/index.js index 259ee0d..df45abb 100644 --- a/js/index.js +++ b/js/index.js @@ -1,3 +1,4 @@ +//FAV WITH PILL AND ANIM let appJSON = []; // List of apps and info from apps.json let appSortInfo = {}; // list of data to sort by, from appdates.csv { created, modified } let appCounts = {}; @@ -501,7 +502,7 @@ function handleAppInterface(app) { }); } -function changeAppFavourite(favourite, app) { +function changeAppFavourite(favourite, app,refresh=true) { if (favourite) { SETTINGS.appsFavoritedThisSession.push({"id":app.id,"favs":appSortInfo[app.id]&&appSortInfo[app.id].favourites?appSortInfo[app.id].favourites:0}); SETTINGS.favourites = SETTINGS.favourites.concat([app.id]); @@ -510,10 +511,11 @@ function changeAppFavourite(favourite, app) { SETTINGS.favourites = SETTINGS.favourites.filter(e => e != app.id); } saveSettings(); - refreshLibrary(); - refreshMyApps(); + if(refresh) { + refreshLibrary(); + refreshMyApps(); + } } - // =========================================== Top Navigation function showTab(tabname) { htmlToArray(document.querySelectorAll("#tab-navigate .tab-item")).forEach(tab => { @@ -543,6 +545,29 @@ librarySearchInput.addEventListener('input', evt => { // =========================================== App Info + + + +function getAppFavorites(app){ + let info = appSortInfo[app.id]; + let appFavourites = 0; + if (info.favourites) { + let favsThisSession = SETTINGS.appsFavoritedThisSession.find(obj => obj.id === app.id); + appFavourites = info.favourites; + if(favsThisSession){ + if(info.favourites!=favsThisSession.favs){ + //database has been updated, remove app from favsThisSession + SETTINGS.appsFavoritedThisSession = SETTINGS.appsFavoritedThisSession.filter(obj => obj.id !== app.id); + } + else{ + appFavourites += 1; //add one to give the illusion of immediate database changes + } + } + } + return appFavourites; +} + + function getAppHTML(app, appInstalled, forInterface) { let version = getVersionInfo(app, appInstalled); let versionInfo = version.text; @@ -559,21 +584,11 @@ function getAppHTML(app, appInstalled, forInterface) { infoTxt.push(`${info.installs} reported installs (${percentText})`); } if (info.favourites) { - let favsThisSession = SETTINGS.appsFavoritedThisSession.find(obj => obj.id === app.id); - let percent=(info.favourites / info.installs * 100).toFixed(0); + appFavourites = getAppFavorites(app); + let percent=(appFavourites / info.installs * 100).toFixed(0); let percentText=percent>100?"More than 100% of installs":percent+"% of installs"; - if(!info.installs||info.installs<1) {infoTxt.push(`${info.favourites} users favourited`)} - else {infoTxt.push(`${info.favourites} users favourited (${percentText})`)} - appFavourites = info.favourites; - if(favsThisSession){ - if(info.favourites!=favsThisSession.favs){ - //database has been updated, remove app from favsThisSession - SETTINGS.appsFavoritedThisSession = SETTINGS.appsFavoritedThisSession.filter(obj => obj.id !== app.id); - } - else{ - appFavourites += 1; //add one to give the illusion of immediate database changes - } - } + if(!info.installs||info.installs<1) {infoTxt.push(`${appFavourites} users favourited`)} + else {infoTxt.push(`${appFavourites} users favourited (${percentText})`)} } if (infoTxt.length) versionTitle = `title="${infoTxt.join("\n")}"`; @@ -585,9 +600,10 @@ function getAppHTML(app, appInstalled, forInterface) { let githubLink = Const.APP_SOURCECODE_URL ? `See the code on GitHub` : ""; let getAppFavouritesHTML = cnt => { - if (!cnt) return ""; - let txt = (cnt > 999) ? Math.round(cnt/1000)+"k" : cnt; - return `${txt}`; + // Always show a count (0 if none) and format large numbers with 'k' + let n = (cnt && typeof cnt === 'number') ? cnt : 0; + let txt = (n > 999) ? Math.round(n/1000)+"k" : n; + return `${txt}`; }; let html = `
@@ -601,8 +617,9 @@ function getAppHTML(app, appInstalled, forInterface) { Copy link to app
`; + html += `
`; if (forInterface=="library") html += ` - + @@ -610,11 +627,11 @@ function getAppHTML(app, appInstalled, forInterface) { `; if (forInterface=="myapps") html += ` - + `; - html += "
"; + html += "
"; if (forInterface=="library") { let screenshots = (app.screenshots || []).filter(s=>s.url); if (screenshots.length) @@ -789,7 +806,6 @@ function refreshLibrary(options) { visibleApps = visibleApps.slice(0, Const.MAX_APPS_SHOWN-1); } - panelbody.innerHTML = visibleApps.map((app,idx) => { let appInstalled = device.appsInstalled.find(a=>a.id==app.id); return getAppHTML(app, appInstalled, "library"); @@ -801,7 +817,7 @@ function refreshLibrary(options) { htmlToArray(panelbody.getElementsByTagName("button")).forEach(button => { button.addEventListener("click",event => { let button = event.currentTarget; - let icon = button.firstChild; + let icon = (button.querySelector && (button.querySelector('i.icon'))) || button.firstElementChild || button.firstChild; let appid = button.getAttribute("appid"); let app = appNameToApp(appid); if (!app) throw new Error("App "+appid+" not found"); @@ -842,8 +858,21 @@ function refreshLibrary(options) { if (err != "") showToast("Failed, "+err, "error"); }); } else if ( button.classList.contains("btn-favourite")) { + // clicked: animate and toggle favourite state immediately for instant feedback let favourite = SETTINGS.favourites.find(e => e == app.id); - changeAppFavourite(!favourite, app); + changeAppFavourite(!favourite, app,false); + if (icon) icon.classList.toggle("icon-favourite-active", !favourite); + if (icon) icon.classList.add("favoriteAnim"); + // update visible count optimistically + let cnt = getAppFavorites(app); + if (!cnt) return ""; + let txt = (cnt > 999) ? Math.round(cnt/1000)+"k" : cnt; + let countEl = button.querySelector('.fav-count'); + countEl.textContent = String(txt); + const ANIM_MS = 500; + setTimeout(() => { + try { if (icon) icon.classList.remove("favoriteAnim"); } catch (e) {} + }, ANIM_MS); } }); }); @@ -1109,7 +1138,7 @@ function refreshMyApps() { htmlToArray(panelbody.getElementsByTagName("button")).forEach(button => { button.addEventListener("click",event => { let button = event.currentTarget; - let icon = button.firstChild; + let icon = (button.querySelector && (button.querySelector('i.icon'))) || button.firstElementChild || button.firstChild; let appid = button.getAttribute("appid"); let app = appNameToApp(appid); if (!app) throw new Error("App "+appid+" not found"); @@ -1122,7 +1151,26 @@ function refreshMyApps() { }); if (icon.classList.contains("icon-favourite")) { let favourite = SETTINGS.favourites.find(e => e == app.id); - changeAppFavourite(!favourite, app); + try { + if (icon) icon.classList.toggle("icon-favourite-active", !favourite); + if (icon) icon.classList.add("favoriteAnim"); + } catch (e) {} + // update visible count optimistically + try { + let countEl = button.querySelector('.fav-count'); + if (countEl) { + let txt = countEl.textContent.trim(); + let val = 0; + if (txt.endsWith('k')) val = Math.round(parseFloat(txt) * 1000); + else val = parseInt(txt) || 0; + val = (!favourite) ? val + 1 : Math.max(0, val - 1); + countEl.textContent = (val > 999) ? Math.round(val/1000) + 'k' : String(val); + } + } catch (e) {} + const ANIM_MS = 500; + setTimeout(() => { + try { if (icon) icon.classList.remove("favoriteAnim"); } catch (e) {} + }, ANIM_MS); } }); }); From c15cfda678f24751fa7f4042ea956cc110591576 Mon Sep 17 00:00:00 2001 From: RKBoss6 Date: Mon, 1 Dec 2025 20:45:17 -0500 Subject: [PATCH 02/12] Remove unnecessary icon check --- js/index.js | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/js/index.js b/js/index.js index df45abb..8ac3c94 100644 --- a/js/index.js +++ b/js/index.js @@ -1,4 +1,3 @@ -//FAV WITH PILL AND ANIM let appJSON = []; // List of apps and info from apps.json let appSortInfo = {}; // list of data to sort by, from appdates.csv { created, modified } let appCounts = {}; @@ -1149,29 +1148,6 @@ function refreshMyApps() { handleAppInterface(app).catch( err => { if (err != "") showToast("Failed, "+err, "error"); }); - if (icon.classList.contains("icon-favourite")) { - let favourite = SETTINGS.favourites.find(e => e == app.id); - try { - if (icon) icon.classList.toggle("icon-favourite-active", !favourite); - if (icon) icon.classList.add("favoriteAnim"); - } catch (e) {} - // update visible count optimistically - try { - let countEl = button.querySelector('.fav-count'); - if (countEl) { - let txt = countEl.textContent.trim(); - let val = 0; - if (txt.endsWith('k')) val = Math.round(parseFloat(txt) * 1000); - else val = parseInt(txt) || 0; - val = (!favourite) ? val + 1 : Math.max(0, val - 1); - countEl.textContent = (val > 999) ? Math.round(val/1000) + 'k' : String(val); - } - } catch (e) {} - const ANIM_MS = 500; - setTimeout(() => { - try { if (icon) icon.classList.remove("favoriteAnim"); } catch (e) {} - }, ANIM_MS); - } }); }); let nonCustomAppsToUpdate = getAppsToUpdate({excludeCustomApps:true}); From b10e2e5f018db9e51424db2e4a569ab2f1389f9c Mon Sep 17 00:00:00 2001 From: RKBoss6 Date: Mon, 1 Dec 2025 20:54:58 -0500 Subject: [PATCH 03/12] Fix bug with favoriting app with 0 favorites not registering --- js/index.js | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/js/index.js b/js/index.js index 8ac3c94..00f2b66 100644 --- a/js/index.js +++ b/js/index.js @@ -1,3 +1,4 @@ +//FAV WITH PILL AND ANIM let appJSON = []; // List of apps and info from apps.json let appSortInfo = {}; // list of data to sort by, from appdates.csv { created, modified } let appCounts = {}; @@ -548,19 +549,19 @@ librarySearchInput.addEventListener('input', evt => { function getAppFavorites(app){ - let info = appSortInfo[app.id]; - let appFavourites = 0; - if (info.favourites) { - let favsThisSession = SETTINGS.appsFavoritedThisSession.find(obj => obj.id === app.id); - appFavourites = info.favourites; - if(favsThisSession){ - if(info.favourites!=favsThisSession.favs){ - //database has been updated, remove app from favsThisSession - SETTINGS.appsFavoritedThisSession = SETTINGS.appsFavoritedThisSession.filter(obj => obj.id !== app.id); - } - else{ - appFavourites += 1; //add one to give the illusion of immediate database changes - } + let info = appSortInfo[app.id] || {}; + // start with whatever number we have in the database (may be undefined -> treat as 0) + let appFavourites = (typeof info.favourites === 'number') ? info.favourites : 0; + let favsThisSession = SETTINGS.appsFavoritedThisSession.find(obj => obj.id === app.id); + if (favsThisSession) { + // If the database count changed since we recorded the session-favourite, it means + // the server/db has been updated and our optimistic session entry is stale. + if (typeof info.favourites === 'number' && info.favourites !== favsThisSession.favs) { + // remove stale session entry + SETTINGS.appsFavoritedThisSession = SETTINGS.appsFavoritedThisSession.filter(obj => obj.id !== app.id); + } else { + // otherwise include our optimistic +1 so the UI updates immediately + appFavourites += 1; } } return appFavourites; @@ -862,13 +863,13 @@ function refreshLibrary(options) { changeAppFavourite(!favourite, app,false); if (icon) icon.classList.toggle("icon-favourite-active", !favourite); if (icon) icon.classList.add("favoriteAnim"); - // update visible count optimistically + // update visible count optimistically (always update, even if 0) let cnt = getAppFavorites(app); - if (!cnt) return ""; - let txt = (cnt > 999) ? Math.round(cnt/1000)+"k" : cnt; + let txt = (cnt > 999) ? Math.round(cnt/1000)+"k" : cnt; let countEl = button.querySelector('.fav-count'); - countEl.textContent = String(txt); + if (countEl) countEl.textContent = String(txt); const ANIM_MS = 500; + // ensure animation class is removed after the duration so it can be re-triggered setTimeout(() => { try { if (icon) icon.classList.remove("favoriteAnim"); } catch (e) {} }, ANIM_MS); From d81eca219b7840f6c84af99b8626b0d3306db9ac Mon Sep 17 00:00:00 2001 From: RKBoss6 Date: Thu, 4 Dec 2025 16:17:34 -0500 Subject: [PATCH 04/12] Update index.js --- js/index.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/js/index.js b/js/index.js index 00f2b66..acda28d 100644 --- a/js/index.js +++ b/js/index.js @@ -1,4 +1,3 @@ -//FAV WITH PILL AND ANIM let appJSON = []; // List of apps and info from apps.json let appSortInfo = {}; // list of data to sort by, from appdates.csv { created, modified } let appCounts = {}; @@ -503,6 +502,8 @@ function handleAppInterface(app) { } function changeAppFavourite(favourite, app,refresh=true) { + let inDatabase=SETTINGS.appsFavoritedThisSession.find(obj => obj.id === app.id); + if (favourite) { SETTINGS.appsFavoritedThisSession.push({"id":app.id,"favs":appSortInfo[app.id]&&appSortInfo[app.id].favourites?appSortInfo[app.id].favourites:0}); SETTINGS.favourites = SETTINGS.favourites.concat([app.id]); @@ -510,6 +511,7 @@ function changeAppFavourite(favourite, app,refresh=true) { SETTINGS.appsFavoritedThisSession = SETTINGS.appsFavoritedThisSession.filter(obj => obj.id !== app.id); SETTINGS.favourites = SETTINGS.favourites.filter(e => e != app.id); } + saveSettings(); if(refresh) { refreshLibrary(); @@ -603,7 +605,7 @@ function getAppHTML(app, appInstalled, forInterface) { // Always show a count (0 if none) and format large numbers with 'k' let n = (cnt && typeof cnt === 'number') ? cnt : 0; let txt = (n > 999) ? Math.round(n/1000)+"k" : n; - return `${txt}`; + return `${txt}`; }; let html = `
@@ -612,7 +614,7 @@ function getAppHTML(app, appInstalled, forInterface) {

${escapeHtml(app.name)} ${versionInfo}

-

${getAppDescription(app)}${app.readme?`
${readme}`:""}

+

${getAppDescription(app)}${app.readme?`
${readme}`:""}

${githubLink} Copy link to app
From 55d985b1f2407489cffce40afa93a9fd03de5cf0 Mon Sep 17 00:00:00 2001 From: RKBoss6 Date: Fri, 5 Dec 2025 06:50:53 -0500 Subject: [PATCH 05/12] Update index.js Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- js/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/index.js b/js/index.js index acda28d..d9ef619 100644 --- a/js/index.js +++ b/js/index.js @@ -502,7 +502,7 @@ function handleAppInterface(app) { } function changeAppFavourite(favourite, app,refresh=true) { - let inDatabase=SETTINGS.appsFavoritedThisSession.find(obj => obj.id === app.id); + if (favourite) { SETTINGS.appsFavoritedThisSession.push({"id":app.id,"favs":appSortInfo[app.id]&&appSortInfo[app.id].favourites?appSortInfo[app.id].favourites:0}); From e357a342901c65b3cd2c289cec239ca5aecd7b7a Mon Sep 17 00:00:00 2001 From: RKBoss6 Date: Fri, 5 Dec 2025 06:53:10 -0500 Subject: [PATCH 06/12] Update index.js Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- js/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/index.js b/js/index.js index d9ef619..d806e4f 100644 --- a/js/index.js +++ b/js/index.js @@ -873,7 +873,7 @@ function refreshLibrary(options) { const ANIM_MS = 500; // ensure animation class is removed after the duration so it can be re-triggered setTimeout(() => { - try { if (icon) icon.classList.remove("favoriteAnim"); } catch (e) {} + try { if (icon) icon.classList.remove("favoriteAnim"); } catch (e) { console.error(e); } }, ANIM_MS); } }); From 78448fc40ad1feb3d2f3889dfc39a5a81fc34cd1 Mon Sep 17 00:00:00 2001 From: RKBoss6 Date: Fri, 5 Dec 2025 06:53:28 -0500 Subject: [PATCH 07/12] Update index.js Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- js/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/index.js b/js/index.js index d806e4f..6a5d12b 100644 --- a/js/index.js +++ b/js/index.js @@ -589,7 +589,7 @@ function getAppHTML(app, appInstalled, forInterface) { appFavourites = getAppFavorites(app); let percent=(appFavourites / info.installs * 100).toFixed(0); let percentText=percent>100?"More than 100% of installs":percent+"% of installs"; - if(!info.installs||info.installs<1) {infoTxt.push(`${appFavourites} users favourited`)} + if(!info.installs||info.installs<1) {infoTxt.push(`${appFavourites} users favourited`);} else {infoTxt.push(`${appFavourites} users favourited (${percentText})`)} } if (infoTxt.length) From 4e01766ceb5b2eb24f54647d461c3710a248f7dd Mon Sep 17 00:00:00 2001 From: RKBoss6 Date: Fri, 5 Dec 2025 06:53:41 -0500 Subject: [PATCH 08/12] Update index.js Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- js/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/index.js b/js/index.js index 6a5d12b..e37caa6 100644 --- a/js/index.js +++ b/js/index.js @@ -590,7 +590,7 @@ function getAppHTML(app, appInstalled, forInterface) { let percent=(appFavourites / info.installs * 100).toFixed(0); let percentText=percent>100?"More than 100% of installs":percent+"% of installs"; if(!info.installs||info.installs<1) {infoTxt.push(`${appFavourites} users favourited`);} - else {infoTxt.push(`${appFavourites} users favourited (${percentText})`)} + else {infoTxt.push(`${appFavourites} users favourited (${percentText})`);} } if (infoTxt.length) versionTitle = `title="${infoTxt.join("\n")}"`; From a55bf86eb3130bf582e951571188e8fb53589ac9 Mon Sep 17 00:00:00 2001 From: RKBoss6 Date: Fri, 5 Dec 2025 10:04:30 -0500 Subject: [PATCH 09/12] Add updated apps with highlighted tile, fix favorites unresponsive in my apps Refactor favorite handling and improve display logic. --- js/index.js | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/js/index.js b/js/index.js index e37caa6..924d563 100644 --- a/js/index.js +++ b/js/index.js @@ -1,3 +1,4 @@ +//FAV WITH PILL AND ANIM let appJSON = []; // List of apps and info from apps.json let appSortInfo = {}; // list of data to sort by, from appdates.csv { created, modified } let appCounts = {}; @@ -502,7 +503,7 @@ function handleAppInterface(app) { } function changeAppFavourite(favourite, app,refresh=true) { - + let inDatabase=SETTINGS.appsFavoritedThisSession.find(obj => obj.id === app.id); if (favourite) { SETTINGS.appsFavoritedThisSession.push({"id":app.id,"favs":appSortInfo[app.id]&&appSortInfo[app.id].favourites?appSortInfo[app.id].favourites:0}); @@ -589,8 +590,8 @@ function getAppHTML(app, appInstalled, forInterface) { appFavourites = getAppFavorites(app); let percent=(appFavourites / info.installs * 100).toFixed(0); let percentText=percent>100?"More than 100% of installs":percent+"% of installs"; - if(!info.installs||info.installs<1) {infoTxt.push(`${appFavourites} users favourited`);} - else {infoTxt.push(`${appFavourites} users favourited (${percentText})`);} + if(!info.installs||info.installs<1) {infoTxt.push(`${appFavourites} users favourited`)} + else {infoTxt.push(`${appFavourites} users favourited (${percentText})`)} } if (infoTxt.length) versionTitle = `title="${infoTxt.join("\n")}"`; @@ -604,11 +605,11 @@ function getAppHTML(app, appInstalled, forInterface) { let getAppFavouritesHTML = cnt => { // Always show a count (0 if none) and format large numbers with 'k' let n = (cnt && typeof cnt === 'number') ? cnt : 0; - let txt = (n > 999) ? Math.round(n/1000)+"k" : n; + let txt = (n > 999) ? Math.round(n/100)/10+"k" : n; return `${txt}`; }; - let html = `
+ let html = `
${escapeHtml(app.name)}
@@ -867,13 +868,13 @@ function refreshLibrary(options) { if (icon) icon.classList.add("favoriteAnim"); // update visible count optimistically (always update, even if 0) let cnt = getAppFavorites(app); - let txt = (cnt > 999) ? Math.round(cnt/1000)+"k" : cnt; + let txt = (cnt > 999) ? Math.round(cnt/100)/10+"k" : cnt; let countEl = button.querySelector('.fav-count'); if (countEl) countEl.textContent = String(txt); const ANIM_MS = 500; // ensure animation class is removed after the duration so it can be re-triggered setTimeout(() => { - try { if (icon) icon.classList.remove("favoriteAnim"); } catch (e) { console.error(e); } + try { if (icon) icon.classList.remove("favoriteAnim"); } catch (e) {} }, ANIM_MS); } }); @@ -1151,13 +1152,30 @@ function refreshMyApps() { handleAppInterface(app).catch( err => { if (err != "") showToast("Failed, "+err, "error"); }); + // handle favourites on My Apps page (button has class btn-favourite) + if (button.classList && button.classList.contains("btn-favourite")) { + let favourite = SETTINGS.favourites.find(e => e == app.id); + changeAppFavourite(!favourite, app, false); + if (icon) icon.classList.toggle("icon-favourite-active", !favourite); + if (icon) icon.classList.add("favoriteAnim"); + // update visible count optimistically (always update, even if 0) + let cnt = getAppFavorites(app); + let txt = (cnt > 999) ? Math.round(cnt/100)/10+"k" : cnt; + let countEl = button.querySelector('.fav-count'); + if (countEl) countEl.textContent = String(txt); + const ANIM_MS = 500; + setTimeout(() => { + try { if (icon) icon.classList.remove("favoriteAnim"); } catch (e) {} + }, ANIM_MS); + } }); }); let nonCustomAppsToUpdate = getAppsToUpdate({excludeCustomApps:true}); let tab = document.querySelector("#tab-myappscontainer a"); let updateApps = document.querySelector("#myappscontainer .updateapps"); if (nonCustomAppsToUpdate.length) { - updateApps.innerHTML = `Update ${nonCustomAppsToUpdate.length} apps`; + + updateApps.innerHTML = `Update ${nonCustomAppsToUpdate.length} ${nonCustomAppsToUpdate.length>1?"apps":"app"}`; updateApps.classList.remove("hidden"); updateApps.classList.remove("disabled"); tab.setAttribute("data-badge", `${device.appsInstalled.length} ⬆${nonCustomAppsToUpdate.length}`); @@ -1543,4 +1561,4 @@ if (btn) btn.addEventListener("click",event=>{ document.querySelector(".editor__canvas").style.display = "inherit"; Comms.on("data",x=>Espruino.Core.Terminal.outputDataHandler(x)) Espruino.Core.Terminal.setInputDataHandler(function(d) { Comms.write(d); }) -}); +}) From c8549436a439ba67ee87fafda2832778d8a8ef9f Mon Sep 17 00:00:00 2001 From: RKBoss6 Date: Fri, 5 Dec 2025 10:08:10 -0500 Subject: [PATCH 10/12] Merge old changes with new ones --- js/index.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/js/index.js b/js/index.js index 924d563..07f43d3 100644 --- a/js/index.js +++ b/js/index.js @@ -1,4 +1,4 @@ -//FAV WITH PILL AND ANIM + let appJSON = []; // List of apps and info from apps.json let appSortInfo = {}; // list of data to sort by, from appdates.csv { created, modified } let appCounts = {}; @@ -503,7 +503,7 @@ function handleAppInterface(app) { } function changeAppFavourite(favourite, app,refresh=true) { - let inDatabase=SETTINGS.appsFavoritedThisSession.find(obj => obj.id === app.id); + if (favourite) { SETTINGS.appsFavoritedThisSession.push({"id":app.id,"favs":appSortInfo[app.id]&&appSortInfo[app.id].favourites?appSortInfo[app.id].favourites:0}); @@ -590,8 +590,8 @@ function getAppHTML(app, appInstalled, forInterface) { appFavourites = getAppFavorites(app); let percent=(appFavourites / info.installs * 100).toFixed(0); let percentText=percent>100?"More than 100% of installs":percent+"% of installs"; - if(!info.installs||info.installs<1) {infoTxt.push(`${appFavourites} users favourited`)} - else {infoTxt.push(`${appFavourites} users favourited (${percentText})`)} + if(!info.installs||info.installs<1) {infoTxt.push(`${appFavourites} users favourited`);} + else {infoTxt.push(`${appFavourites} users favourited (${percentText})`);} } if (infoTxt.length) versionTitle = `title="${infoTxt.join("\n")}"`; @@ -874,7 +874,7 @@ function refreshLibrary(options) { const ANIM_MS = 500; // ensure animation class is removed after the duration so it can be re-triggered setTimeout(() => { - try { if (icon) icon.classList.remove("favoriteAnim"); } catch (e) {} + try { if (icon) icon.classList.remove("favoriteAnim"); } catch (e) { console.error(e); } }, ANIM_MS); } }); @@ -1561,4 +1561,4 @@ if (btn) btn.addEventListener("click",event=>{ document.querySelector(".editor__canvas").style.display = "inherit"; Comms.on("data",x=>Espruino.Core.Terminal.outputDataHandler(x)) Espruino.Core.Terminal.setInputDataHandler(function(d) { Comms.write(d); }) -}) +}); From 3bac7f55e3b74b52dbf9bf973b50dfd9f9a5fcba Mon Sep 17 00:00:00 2001 From: RKBoss6 Date: Fri, 5 Dec 2025 10:09:14 -0500 Subject: [PATCH 11/12] Update js/index.js Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- js/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/index.js b/js/index.js index 07f43d3..5e96b6a 100644 --- a/js/index.js +++ b/js/index.js @@ -615,7 +615,7 @@ function getAppHTML(app, appInstalled, forInterface) {

${escapeHtml(app.name)} ${versionInfo}

-

${getAppDescription(app)}${app.readme?`
${readme}`:""}

+

${getAppDescription(app)}${app.readme?`
${readme}`:""}

${githubLink} Copy link to app
From e19af6053d9ce0fb69fdbd196182a43250b454a2 Mon Sep 17 00:00:00 2001 From: RKBoss6 Date: Fri, 5 Dec 2025 10:11:41 -0500 Subject: [PATCH 12/12] abstract animation length to one global variable --- js/index.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/js/index.js b/js/index.js index 5e96b6a..c5681b5 100644 --- a/js/index.js +++ b/js/index.js @@ -1,4 +1,3 @@ - let appJSON = []; // List of apps and info from apps.json let appSortInfo = {}; // list of data to sort by, from appdates.csv { created, modified } let appCounts = {}; @@ -42,6 +41,7 @@ let device = { } };*/ let LANGUAGE = undefined; +const favAnimMS = 500; /** Ensure we run transfers one after the other rather that potentially having them overlap if the user clicks around https://github.com/espruino/EspruinoAppLoaderCore/issues/67 */ @@ -871,11 +871,10 @@ function refreshLibrary(options) { let txt = (cnt > 999) ? Math.round(cnt/100)/10+"k" : cnt; let countEl = button.querySelector('.fav-count'); if (countEl) countEl.textContent = String(txt); - const ANIM_MS = 500; // ensure animation class is removed after the duration so it can be re-triggered setTimeout(() => { try { if (icon) icon.classList.remove("favoriteAnim"); } catch (e) { console.error(e); } - }, ANIM_MS); + }, favAnimMS); } }); }); @@ -1163,10 +1162,9 @@ function refreshMyApps() { let txt = (cnt > 999) ? Math.round(cnt/100)/10+"k" : cnt; let countEl = button.querySelector('.fav-count'); if (countEl) countEl.textContent = String(txt); - const ANIM_MS = 500; setTimeout(() => { try { if (icon) icon.classList.remove("favoriteAnim"); } catch (e) {} - }, ANIM_MS); + }, favAnimMS); } }); });