Skip to content

Commit 64048b1

Browse files
authored
Refactor changeAppFavourite function for animations
Refactor changeAppFavourite to include optional refresh parameter and update favorite count handling.
1 parent 5436722 commit 64048b1

File tree

1 file changed

+77
-29
lines changed

1 file changed

+77
-29
lines changed

js/index.js

Lines changed: 77 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
//FAV WITH PILL AND ANIM
12
let appJSON = []; // List of apps and info from apps.json
23
let appSortInfo = {}; // list of data to sort by, from appdates.csv { created, modified }
34
let appCounts = {};
@@ -501,7 +502,7 @@ function handleAppInterface(app) {
501502
});
502503
}
503504

504-
function changeAppFavourite(favourite, app) {
505+
function changeAppFavourite(favourite, app,refresh=true) {
505506
if (favourite) {
506507
SETTINGS.appsFavoritedThisSession.push({"id":app.id,"favs":appSortInfo[app.id]&&appSortInfo[app.id].favourites?appSortInfo[app.id].favourites:0});
507508
SETTINGS.favourites = SETTINGS.favourites.concat([app.id]);
@@ -510,10 +511,11 @@ function changeAppFavourite(favourite, app) {
510511
SETTINGS.favourites = SETTINGS.favourites.filter(e => e != app.id);
511512
}
512513
saveSettings();
513-
refreshLibrary();
514-
refreshMyApps();
514+
if(refresh) {
515+
refreshLibrary();
516+
refreshMyApps();
517+
}
515518
}
516-
517519
// =========================================== Top Navigation
518520
function showTab(tabname) {
519521
htmlToArray(document.querySelectorAll("#tab-navigate .tab-item")).forEach(tab => {
@@ -543,6 +545,29 @@ librarySearchInput.addEventListener('input', evt => {
543545

544546
// =========================================== App Info
545547

548+
549+
550+
551+
function getAppFavorites(app){
552+
let info = appSortInfo[app.id];
553+
let appFavourites = 0;
554+
if (info.favourites) {
555+
let favsThisSession = SETTINGS.appsFavoritedThisSession.find(obj => obj.id === app.id);
556+
appFavourites = info.favourites;
557+
if(favsThisSession){
558+
if(info.favourites!=favsThisSession.favs){
559+
//database has been updated, remove app from favsThisSession
560+
SETTINGS.appsFavoritedThisSession = SETTINGS.appsFavoritedThisSession.filter(obj => obj.id !== app.id);
561+
}
562+
else{
563+
appFavourites += 1; //add one to give the illusion of immediate database changes
564+
}
565+
}
566+
}
567+
return appFavourites;
568+
}
569+
570+
546571
function getAppHTML(app, appInstalled, forInterface) {
547572
let version = getVersionInfo(app, appInstalled);
548573
let versionInfo = version.text;
@@ -559,21 +584,11 @@ function getAppHTML(app, appInstalled, forInterface) {
559584
infoTxt.push(`${info.installs} reported installs (${percentText})`);
560585
}
561586
if (info.favourites) {
562-
let favsThisSession = SETTINGS.appsFavoritedThisSession.find(obj => obj.id === app.id);
563-
let percent=(info.favourites / info.installs * 100).toFixed(0);
587+
appFavourites = getAppFavorites(app);
588+
let percent=(appFavourites / info.installs * 100).toFixed(0);
564589
let percentText=percent>100?"More than 100% of installs":percent+"% of installs";
565-
if(!info.installs||info.installs<1) {infoTxt.push(`${info.favourites} users favourited`)}
566-
else {infoTxt.push(`${info.favourites} users favourited (${percentText})`)}
567-
appFavourites = info.favourites;
568-
if(favsThisSession){
569-
if(info.favourites!=favsThisSession.favs){
570-
//database has been updated, remove app from favsThisSession
571-
SETTINGS.appsFavoritedThisSession = SETTINGS.appsFavoritedThisSession.filter(obj => obj.id !== app.id);
572-
}
573-
else{
574-
appFavourites += 1; //add one to give the illusion of immediate database changes
575-
}
576-
}
590+
if(!info.installs||info.installs<1) {infoTxt.push(`${appFavourites} users favourited`)}
591+
else {infoTxt.push(`${appFavourites} users favourited (${percentText})`)}
577592
}
578593
if (infoTxt.length)
579594
versionTitle = `title="${infoTxt.join("\n")}"`;
@@ -585,9 +600,10 @@ function getAppHTML(app, appInstalled, forInterface) {
585600
let githubLink = Const.APP_SOURCECODE_URL ?
586601
`<a href="${Const.APP_SOURCECODE_URL}/${app.id}" target="_blank" class="link-github"><img src="core/img/github-icon-sml.png" alt="See the code on GitHub"/></a>` : "";
587602
let getAppFavouritesHTML = cnt => {
588-
if (!cnt) return "";
589-
let txt = (cnt > 999) ? Math.round(cnt/1000)+"k" : cnt;
590-
return `<span>${txt}</span>`;
603+
// Always show a count (0 if none) and format large numbers with 'k'
604+
let n = (cnt && typeof cnt === 'number') ? cnt : 0;
605+
let txt = (n > 999) ? Math.round(n/1000)+"k" : n;
606+
return `<span class="fav-count">${txt}</span>`;
591607
};
592608

593609
let html = `<div class="tile column col-6 col-sm-12 col-xs-12 app-tile">
@@ -601,20 +617,21 @@ function getAppHTML(app, appInstalled, forInterface) {
601617
<a href="${appurl}" class="link-copy-url" appid="${app.id}" title="Copy link to app" style="position:absolute;top: 56px;left: -24px;"><img src="core/img/copy-icon.png" alt="Copy link to app"/></a>
602618
</div>
603619
<div class="tile-action">`;
620+
html += `<div class="pill-container">`;
604621
if (forInterface=="library") html += `
605-
<button class="btn btn-link btn-action btn-lg btn-favourite" appid="${app.id}" title="Favourite"><i class="icon icon-favourite${favourite?" icon-favourite-active":""}">${getAppFavouritesHTML(appFavourites)}</i></button>
622+
<button class="btn btn-link btn-action btn-lg btn-favourite" appid="${app.id}" title="Favourite">${getAppFavouritesHTML(appFavourites)}<i class="icon icon-favourite${favourite?" icon-favourite-active":""}"></i></button>
606623
<button class="btn btn-link btn-action btn-lg ${(appInstalled&&app.interface)?"":"d-hide"}" appid="${app.id}" title="Download data from app"><i class="icon icon-interface"></i></button>
607624
<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-emulator"></i></button>
608625
<button class="btn btn-link btn-action btn-lg ${(SETTINGS.alwaysAllowUpdate && appInstalled) || version.canUpdate?"":"d-hide"}" appid="${app.id}" title="Update App"><i class="icon icon-refresh"></i></button>
609626
<button class="btn btn-link btn-action btn-lg ${(!appInstalled && !app.custom)?"":"d-hide"}" appid="${app.id}" title="Upload App"><i class="icon icon-upload"></i></button>
610627
<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>
611628
<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>`;
612629
if (forInterface=="myapps") html += `
613-
<button class="btn btn-link btn-action btn-lg btn-favourite" appid="${app.id}" title="Favourite"><i class="icon icon-favourite${favourite?" icon-favourite-active":""}">${getAppFavouritesHTML(appFavourites)}</i></button>
630+
<button class="btn btn-link btn-action btn-lg btn-favourite" appid="${app.id}" title="Favourite">${getAppFavouritesHTML(appFavourites)}<i class="icon icon-favourite${favourite?" icon-favourite-active":""}"></i></button>
614631
<button class="btn btn-link btn-action btn-lg ${(appInstalled&&app.interface)?"":"d-hide"}" appid="${app.id}" title="Download data from app"><i class="icon icon-interface"></i></button>
615632
<button class="btn btn-link btn-action btn-lg ${(SETTINGS.alwaysAllowUpdate && appInstalled) || version.canUpdate?'':'d-hide'}" appid="${app.id}" title="Update App"><i class="icon icon-refresh"></i></button>
616633
<button class="btn btn-link btn-action btn-lg" appid="${app.id}" title="Remove App"><i class="icon icon-delete"></i></button>`;
617-
html += "</div>";
634+
html += "</div></div>";
618635
if (forInterface=="library") {
619636
let screenshots = (app.screenshots || []).filter(s=>s.url);
620637
if (screenshots.length)
@@ -789,7 +806,6 @@ function refreshLibrary(options) {
789806
visibleApps = visibleApps.slice(0, Const.MAX_APPS_SHOWN-1);
790807
}
791808

792-
793809
panelbody.innerHTML = visibleApps.map((app,idx) => {
794810
let appInstalled = device.appsInstalled.find(a=>a.id==app.id);
795811
return getAppHTML(app, appInstalled, "library");
@@ -801,7 +817,7 @@ function refreshLibrary(options) {
801817
htmlToArray(panelbody.getElementsByTagName("button")).forEach(button => {
802818
button.addEventListener("click",event => {
803819
let button = event.currentTarget;
804-
let icon = button.firstChild;
820+
let icon = (button.querySelector && (button.querySelector('i.icon'))) || button.firstElementChild || button.firstChild;
805821
let appid = button.getAttribute("appid");
806822
let app = appNameToApp(appid);
807823
if (!app) throw new Error("App "+appid+" not found");
@@ -842,8 +858,21 @@ function refreshLibrary(options) {
842858
if (err != "") showToast("Failed, "+err, "error");
843859
});
844860
} else if ( button.classList.contains("btn-favourite")) {
861+
// clicked: animate and toggle favourite state immediately for instant feedback
845862
let favourite = SETTINGS.favourites.find(e => e == app.id);
846-
changeAppFavourite(!favourite, app);
863+
changeAppFavourite(!favourite, app,false);
864+
if (icon) icon.classList.toggle("icon-favourite-active", !favourite);
865+
if (icon) icon.classList.add("favoriteAnim");
866+
// update visible count optimistically
867+
let cnt = getAppFavorites(app);
868+
if (!cnt) return "";
869+
let txt = (cnt > 999) ? Math.round(cnt/1000)+"k" : cnt;
870+
let countEl = button.querySelector('.fav-count');
871+
countEl.textContent = String(txt);
872+
const ANIM_MS = 500;
873+
setTimeout(() => {
874+
try { if (icon) icon.classList.remove("favoriteAnim"); } catch (e) {}
875+
}, ANIM_MS);
847876
}
848877
});
849878
});
@@ -1109,7 +1138,7 @@ function refreshMyApps() {
11091138
htmlToArray(panelbody.getElementsByTagName("button")).forEach(button => {
11101139
button.addEventListener("click",event => {
11111140
let button = event.currentTarget;
1112-
let icon = button.firstChild;
1141+
let icon = (button.querySelector && (button.querySelector('i.icon'))) || button.firstElementChild || button.firstChild;
11131142
let appid = button.getAttribute("appid");
11141143
let app = appNameToApp(appid);
11151144
if (!app) throw new Error("App "+appid+" not found");
@@ -1122,7 +1151,26 @@ function refreshMyApps() {
11221151
});
11231152
if (icon.classList.contains("icon-favourite")) {
11241153
let favourite = SETTINGS.favourites.find(e => e == app.id);
1125-
changeAppFavourite(!favourite, app);
1154+
try {
1155+
if (icon) icon.classList.toggle("icon-favourite-active", !favourite);
1156+
if (icon) icon.classList.add("favoriteAnim");
1157+
} catch (e) {}
1158+
// update visible count optimistically
1159+
try {
1160+
let countEl = button.querySelector('.fav-count');
1161+
if (countEl) {
1162+
let txt = countEl.textContent.trim();
1163+
let val = 0;
1164+
if (txt.endsWith('k')) val = Math.round(parseFloat(txt) * 1000);
1165+
else val = parseInt(txt) || 0;
1166+
val = (!favourite) ? val + 1 : Math.max(0, val - 1);
1167+
countEl.textContent = (val > 999) ? Math.round(val/1000) + 'k' : String(val);
1168+
}
1169+
} catch (e) {}
1170+
const ANIM_MS = 500;
1171+
setTimeout(() => {
1172+
try { if (icon) icon.classList.remove("favoriteAnim"); } catch (e) {}
1173+
}, ANIM_MS);
11261174
}
11271175
});
11281176
});

0 commit comments

Comments
 (0)