ソースを参照

Optimized Musicify cache logic

Toby Chui 2 週間 前
コミット
2f2bef15f7

+ 31 - 0
src/web/Musicify/backend/getArtistsCache.js

@@ -0,0 +1,31 @@
+/*
+    Musicify - Artists Cache Reader
+    Returns the previously-saved artists list from server storage.
+    Does NO file-system scanning — responds in milliseconds.
+
+    Written by listArtists.js after every full scan, so it is always as fresh
+    as the last completed scan (even if the browser tab was closed during it).
+
+    Returns JSON: { ts: <unix-ms>, items: [...artists] }
+    or            { error: "no_cache" }
+*/
+
+includes("common.js");
+requirelib("filelib");
+
+var CACHE_FILE = "user:/Document/Appdata/Musicify/artists_cache.json";
+
+function main() {
+    if (!filelib.fileExists(CACHE_FILE)) {
+        sendJSONResp(JSON.stringify({ error: "no_cache" }));
+        return;
+    }
+    var content = filelib.readFile(CACHE_FILE);
+    if (!content || content === false || content.length < 10) {
+        sendJSONResp(JSON.stringify({ error: "no_cache" }));
+        return;
+    }
+    sendJSONResp(content);  // { ts, items } — already valid JSON
+}
+
+main();

+ 13 - 0
src/web/Musicify/backend/listArtists.js

@@ -63,6 +63,19 @@ function main() {
         return a.name.toLowerCase().localeCompare(b.name.toLowerCase());
     });
 
+    // Persist to server-side cache so any device (or next session) can load instantly.
+    // Written BEFORE sendJSONResp so the file is guaranteed on disk even if the
+    // client closes the tab before the HTTP response arrives.
+    try {
+        if (!filelib.fileExists("user:/Document/"))                    { filelib.mkdir("user:/Document/"); }
+        if (!filelib.fileExists("user:/Document/Appdata/"))            { filelib.mkdir("user:/Document/Appdata/"); }
+        if (!filelib.fileExists("user:/Document/Appdata/Musicify/"))   { filelib.mkdir("user:/Document/Appdata/Musicify/"); }
+        filelib.writeFile(
+            "user:/Document/Appdata/Musicify/artists_cache.json",
+            JSON.stringify({ ts: new Date().getTime(), items: artists })
+        );
+    } catch (e) {}  // never let a cache-write failure break the response
+
     sendJSONResp(JSON.stringify(artists));
 }
 

+ 32 - 32
src/web/Musicify/musicify.js

@@ -291,20 +291,12 @@ function musicifyApp() {
         _loadArtists(opts) {
             opts = opts || {};
             var forceNetwork = !!opts.forceNetwork;
-            var cache = null;
+            var self = this;
 
             // Artists refresh should never block the entire content panel.
             this.loading = false;
 
-            if (!forceNetwork) {
-                cache = this._readArtistsCache();
-                if (cache && Array.isArray(cache.items)) {
-                    this.artists = cache.items;
-                    this.artistsFromCache = true;
-                    this.artistsCacheUpdatedAt = cache.updatedAt || 0;
-                }
-            }
-
+            // ── Start the network scan immediately — never wait for cache ─────
             if (this._artistsFetchInFlight) return;
 
             this._artistsFetchInFlight = true;
@@ -317,9 +309,20 @@ function musicifyApp() {
             // Use worker first to keep fetch + JSON parsing off the UI thread.
             var startedInWorker = this._dispatchArtistsFetchToWorker(reqId);
             if (!startedInWorker) {
-                // Fallback for environments where Worker is unavailable.
                 this._dispatchArtistsFetchFallback(reqId);
             }
+
+            // ── In parallel: read server-side cache to pre-populate the UI ────
+            // Only applies the cache if the network scan has not yet returned.
+            if (!forceNetwork) {
+                this._readArtistsCache(function(cache) {
+                    if (self.artistsRefreshing && cache && Array.isArray(cache.items)) {
+                        self.artists = cache.items;
+                        self.artistsFromCache = true;
+                        self.artistsCacheUpdatedAt = cache.ts || 0;
+                    }
+                });
+            }
         },
 
         _dispatchArtistsFetchToWorker(reqId) {
@@ -430,29 +433,26 @@ function musicifyApp() {
             this._artistsFetchInFlight = false;
         },
 
-        _readArtistsCache() {
-            try {
-                var raw = localStorage.getItem('musicify_artists_cache');
-                if (!raw) return null;
-                var payload = JSON.parse(raw);
-                if (!payload || !Array.isArray(payload.items)) return null;
-                return {
-                    updatedAt: payload.updatedAt || 0,
-                    items: payload.items
-                };
-            } catch (e) {
-                return null;
-            }
+        // Reads the server-side artists cache (user:/Document/Appdata/Musicify/).
+        // Async — calls callback(cache) where cache is { ts, items } or null.
+        _readArtistsCache(callback) {
+            fetch(ao_root + 'system/ajgi/interface?script=Musicify/backend/getArtistsCache.js', {
+                method: 'POST', cache: 'no-cache',
+                headers: { 'Content-Type': 'application/json' },
+                body: JSON.stringify({})
+            }).then(function(r) { return r.json(); })
+              .then(function(data) {
+                if (data && !data.error && Array.isArray(data.items)) {
+                    callback({ ts: data.ts || 0, items: data.items });
+                } else {
+                    callback(null);
+                }
+              }).catch(function() { callback(null); });
         },
 
-        _writeArtistsCache(items, updatedAt) {
-            try {
-                localStorage.setItem('musicify_artists_cache', JSON.stringify({
-                    updatedAt: updatedAt || Date.now(),
-                    items: Array.isArray(items) ? items : []
-                }));
-            } catch (e) {}
-        },
+        // Cache is now written server-side by listArtists.js before it sends its
+        // response — no client-side write needed.
+        _writeArtistsCache(items, updatedAt) {},
 
         _flashArtistsUpdated() {
             this._artistsUpdateFlash = true;