update app and index.html

This commit is contained in:
2026-06-01 13:15:12 -07:00
parent 254f488eca
commit e0d0f15731
9 changed files with 754 additions and 38 deletions
+84 -2
View File
@@ -11,6 +11,14 @@
const textLexiconCache = new Map();
const textLexiconOccurrencesCache = new Map();
const textSearchCache = new Map();
const NOW_SNAPSHOT_MIN_INTERVAL_MS = 5 * 60 * 1000;
let nowSnapshotCache = {
geoKey: "",
fetchedAtMs: 0,
value: null,
pendingGeoKey: "",
pendingPromise: null
};
const DATA_ROOT = "data";
const MAGICK_ROOT = DATA_ROOT;
@@ -215,6 +223,26 @@
return url.toString();
}
function normalizeGeoKey(geo) {
const latitude = Number(geo?.latitude);
const longitude = Number(geo?.longitude);
if (!Number.isFinite(latitude) || !Number.isFinite(longitude)) {
return "";
}
return `${latitude.toFixed(6)},${longitude.toFixed(6)}`;
}
function isNowSnapshotPollingEnabled() {
if (typeof document !== "undefined" && document.hidden === true) {
return false;
}
const activeSection = String(window.TarotSectionStateUi?.getActiveSection?.() || "home").trim();
return activeSection === "home";
}
function toApiAssetUrl(assetPath) {
const { apiBaseUrl, apiKey } = resolveConnectionSettings();
const normalizedAssetPath = String(assetPath || "")
@@ -247,6 +275,13 @@
textLexiconCache.clear();
textLexiconOccurrencesCache.clear();
textSearchCache.clear();
nowSnapshotCache = {
geoKey: "",
fetchedAtMs: 0,
value: null,
pendingGeoKey: "",
pendingPromise: null
};
}
function normalizeTarotName(value) {
@@ -370,11 +405,58 @@
}
async function fetchNowSnapshot(geo, timestamp = new Date()) {
return fetchJson(buildApiUrl("/api/v1/now", {
const geoKey = normalizeGeoKey(geo);
const nowMs = Date.now();
if (!isNowSnapshotPollingEnabled()) {
if (geoKey && nowSnapshotCache.pendingPromise && nowSnapshotCache.pendingGeoKey === geoKey) {
return nowSnapshotCache.pendingPromise;
}
if (geoKey && geoKey === nowSnapshotCache.geoKey && nowSnapshotCache.value) {
return nowSnapshotCache.value;
}
return null;
}
if (
geoKey
&& geoKey === nowSnapshotCache.geoKey
&& nowSnapshotCache.value
&& Number.isFinite(nowSnapshotCache.fetchedAtMs)
&& (nowMs - nowSnapshotCache.fetchedAtMs) < NOW_SNAPSHOT_MIN_INTERVAL_MS
) {
return nowSnapshotCache.value;
}
if (geoKey && nowSnapshotCache.pendingPromise && nowSnapshotCache.pendingGeoKey === geoKey) {
return nowSnapshotCache.pendingPromise;
}
const requestPromise = fetchJson(buildApiUrl("/api/v1/now", {
latitude: geo?.latitude,
longitude: geo?.longitude,
date: timestamp instanceof Date ? timestamp.toISOString() : timestamp
}));
}))
.then((snapshot) => {
if (geoKey) {
nowSnapshotCache.geoKey = geoKey;
nowSnapshotCache.fetchedAtMs = Date.now();
nowSnapshotCache.value = snapshot;
}
return snapshot;
})
.finally(() => {
if (nowSnapshotCache.pendingPromise === requestPromise) {
nowSnapshotCache.pendingPromise = null;
nowSnapshotCache.pendingGeoKey = "";
}
});
nowSnapshotCache.pendingPromise = requestPromise;
nowSnapshotCache.pendingGeoKey = geoKey;
return requestPromise;
}
async function loadTarotCards(filters = {}) {