2023-05-10 22:26:03 +00:00
|
|
|
(() => {
|
2023-05-03 06:50:43 +00:00
|
|
|
type Timestamp = number;
|
2023-05-07 22:51:38 +00:00
|
|
|
type Cache = {
|
2023-05-03 06:50:43 +00:00
|
|
|
[key: string]: {
|
|
|
|
sortorder: number,
|
|
|
|
pop: number, // amount of launches
|
|
|
|
last: Timestamp,
|
|
|
|
}
|
|
|
|
};
|
2023-04-24 21:29:17 +00:00
|
|
|
|
2023-05-07 22:51:38 +00:00
|
|
|
const oldRead = require("Storage").readJSON;
|
|
|
|
const oneMonth = 1000 * 86400 * 28;
|
|
|
|
const monthAgo = Date.now() - oneMonth;
|
|
|
|
let cache: undefined | Cache;
|
|
|
|
|
2023-05-03 06:50:43 +00:00
|
|
|
const ensureCache = (): NonNull<typeof cache> => {
|
2023-04-24 21:29:17 +00:00
|
|
|
if(!cache){
|
2023-05-21 21:38:42 +00:00
|
|
|
cache = oldRead("popcon.cache.json", true) as Cache | undefined;
|
2023-04-24 21:29:17 +00:00
|
|
|
if(!cache)
|
|
|
|
cache = {};
|
|
|
|
}
|
2023-05-03 06:50:43 +00:00
|
|
|
return cache;
|
2023-04-24 21:29:17 +00:00
|
|
|
};
|
|
|
|
|
2023-05-07 22:51:38 +00:00
|
|
|
const trimCache = (cache: Cache) => {
|
|
|
|
const threeMonthsBack = Date.now() - oneMonth * 3;
|
|
|
|
const del = [];
|
|
|
|
for(const k in cache)
|
|
|
|
if(cache[k]!.last < threeMonthsBack)
|
|
|
|
del.push(k);
|
|
|
|
|
|
|
|
for(const k of del)
|
|
|
|
delete cache[k];
|
|
|
|
};
|
|
|
|
|
|
|
|
const saveCache = (cache: Cache, orderChanged: boolean) => {
|
|
|
|
trimCache(cache);
|
2023-04-24 21:29:17 +00:00
|
|
|
require("Storage").writeJSON("popcon.cache.json", cache);
|
2023-05-03 21:14:54 +00:00
|
|
|
if(orderChanged){
|
|
|
|
// ensure launchers reload their caches:
|
2023-06-13 22:22:14 +00:00
|
|
|
const info = (oldRead("popconlaunch.info", true) as undefined | AppInfo & { cacheBuster?: boolean }) || {cacheBuster:true};
|
2023-05-03 21:14:54 +00:00
|
|
|
info.cacheBuster = !info.cacheBuster;
|
2023-05-24 07:27:29 +00:00
|
|
|
require("Storage").writeJSON("popconlaunch.info", info);
|
2023-05-03 06:50:43 +00:00
|
|
|
}
|
2023-04-24 21:29:17 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
const sortCache = () => {
|
2023-05-03 06:50:43 +00:00
|
|
|
const ents = Object.values(cache);
|
|
|
|
|
|
|
|
ents.sort((a, b) => {
|
|
|
|
// group the most recently launched apps in the last month,
|
|
|
|
// then sort by launch count
|
|
|
|
// then by name
|
|
|
|
let n;
|
|
|
|
|
|
|
|
const am = (a.last > monthAgo) as unknown as number;
|
|
|
|
const bm = (b.last > monthAgo) as unknown as number;
|
|
|
|
n = bm - am;
|
|
|
|
if(n) return n;
|
|
|
|
|
|
|
|
n = b.pop - a.pop;
|
|
|
|
if(n) return n;
|
|
|
|
|
|
|
|
// pops are the same, sort by most recent
|
|
|
|
n = b.last - a.last;
|
|
|
|
if(n) return n;
|
|
|
|
|
|
|
|
if(a.name<b.name) return -1;
|
|
|
|
if(a.name>b.name) return 1;
|
|
|
|
return 0;
|
|
|
|
});
|
|
|
|
|
|
|
|
let i = 0;
|
2023-05-03 21:14:41 +00:00
|
|
|
let orderChanged = false;
|
2023-05-03 06:50:43 +00:00
|
|
|
for(const ent of ents){
|
2023-05-03 21:14:41 +00:00
|
|
|
if(ent.sortorder !== i) orderChanged = true;
|
2023-05-03 06:50:43 +00:00
|
|
|
ent.sortorder = i++;
|
|
|
|
}
|
2023-05-03 21:14:41 +00:00
|
|
|
return orderChanged;
|
2023-04-24 21:29:17 +00:00
|
|
|
};
|
|
|
|
|
2023-05-03 06:50:43 +00:00
|
|
|
require("Storage").readJSON = ((fname, skipExceptions) => {
|
2023-05-21 21:38:42 +00:00
|
|
|
const j = oldRead(fname, skipExceptions) as AppInfo | undefined;
|
|
|
|
// technically only AppInfo if we're "*.info" ^
|
2023-04-24 21:29:17 +00:00
|
|
|
|
2023-05-21 21:38:42 +00:00
|
|
|
if(j && /\.info$/.test(fname)){
|
2023-05-03 06:50:43 +00:00
|
|
|
const cache = ensureCache();
|
|
|
|
let so;
|
2023-04-24 21:29:17 +00:00
|
|
|
|
2023-05-03 06:50:43 +00:00
|
|
|
if(j.src && (so = cache[j.src]?.sortorder) != null)
|
2023-05-02 22:08:04 +00:00
|
|
|
j.sortorder = so;
|
2023-05-03 06:50:43 +00:00
|
|
|
else
|
2023-05-02 22:08:04 +00:00
|
|
|
j.sortorder = 99;
|
2023-04-24 21:29:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return j;
|
2023-05-03 06:50:43 +00:00
|
|
|
}) satisfies typeof oldRead;
|
2023-04-24 21:29:17 +00:00
|
|
|
|
|
|
|
const oldLoad = load;
|
2023-05-03 06:50:43 +00:00
|
|
|
global.load = (src: string) => {
|
|
|
|
if(src){
|
|
|
|
const cache = ensureCache();
|
2023-05-02 22:08:04 +00:00
|
|
|
const ent = cache[src] ||= {
|
2023-05-03 06:50:43 +00:00
|
|
|
pop: 0,
|
|
|
|
last: 0,
|
|
|
|
sortorder: -10,
|
2023-05-02 22:08:04 +00:00
|
|
|
};
|
2023-05-03 06:50:43 +00:00
|
|
|
ent.pop++;
|
|
|
|
ent.last = Date.now();
|
2023-05-03 21:14:41 +00:00
|
|
|
const orderChanged = sortCache();
|
2023-05-07 22:51:38 +00:00
|
|
|
saveCache(cache, orderChanged);
|
2023-05-03 06:50:43 +00:00
|
|
|
}
|
2023-04-24 21:29:17 +00:00
|
|
|
|
|
|
|
return oldLoad(src);
|
|
|
|
};
|
2023-05-10 22:26:03 +00:00
|
|
|
})()
|