fix(tracker): backfill — local-only mark_read'ы досылаются на сервер при загрузке
Старый syncPending-баг (теперь починен в коммите dacc0eb) оставил у
учеников локальное состояние с прочитанными параграфами, но сервер
ничего не знал. После фикса firstTime=false для всех уже-кликнутых
пилюль, и mark_read не уходил на сервер при повторном клике.
Решение: loadServerProgress теперь вычисляет diff между local.read
и server.read; для каждого ключа, которого нет на сервере, дёргает
syncToServer({mark_read: k}). Coalesce в pendingExtra гарантирует,
что все запросы упорядочатся.
Эффект: при следующей загрузке учебника каталог автоматически догоняется.
This commit is contained in:
@@ -53,7 +53,11 @@
|
|||||||
}).catch(() => {});
|
}).catch(() => {});
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── 2. Initial load: merge server data into local state ──────── */
|
/* ── 2. Initial load: merge server data into local state + push back ──
|
||||||
|
Если в локальном кэше есть ключи, которых нет на сервере
|
||||||
|
(последствие старого бага syncPending) — досылаем их через
|
||||||
|
отдельные mark_read POST'ы. Это лечит «вечный 0/N» у пользователей,
|
||||||
|
которые до фикса уже накликали кучу пилюль. */
|
||||||
function loadServerProgress() {
|
function loadServerProgress() {
|
||||||
if (typeof LS === 'undefined' || !LS.getToken || !LS.getToken()) return;
|
if (typeof LS === 'undefined' || !LS.getToken || !LS.getToken()) return;
|
||||||
fetch('/api/textbooks/' + slug, {
|
fetch('/api/textbooks/' + slug, {
|
||||||
@@ -62,11 +66,17 @@
|
|||||||
.then(r => r.ok ? r.json() : null)
|
.then(r => r.ok ? r.json() : null)
|
||||||
.then(d => {
|
.then(d => {
|
||||||
if (!d || !d.progress) return;
|
if (!d || !d.progress) return;
|
||||||
const merged = Array.from(new Set([...(localState.read || []), ...(d.progress.read || [])]));
|
const serverRead = new Set(d.progress.read || []);
|
||||||
|
const localRead = localState.read || [];
|
||||||
|
const missing = localRead.filter(k => !serverRead.has(k));
|
||||||
|
// объединяем для UI
|
||||||
|
const merged = Array.from(new Set([...localRead, ...d.progress.read || []]));
|
||||||
localState.read = merged;
|
localState.read = merged;
|
||||||
if (!localState.last) localState.last = d.progress.last_para;
|
if (!localState.last) localState.last = d.progress.last_para;
|
||||||
localStorage.setItem(lsKey, JSON.stringify(localState));
|
localStorage.setItem(lsKey, JSON.stringify(localState));
|
||||||
refreshAllUI();
|
refreshAllUI();
|
||||||
|
// догоняем сервер последовательно: syncToServer уже коалесцирует
|
||||||
|
missing.forEach(k => syncToServer({ mark_read: k }));
|
||||||
})
|
})
|
||||||
.catch(() => {});
|
.catch(() => {});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user