fix: offline-content renamed to downloads
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
|
||||
/**
|
||||
* /offline-content — the reader's device-local offline library.
|
||||
* /downloads — the reader's device-local offline library.
|
||||
*
|
||||
* Lists everything saved via the header's "Save offline" button and lets them
|
||||
* open (offline-capable) or remove each item. Items link with a plain <a> (a
|
||||
@@ -10,7 +10,7 @@
|
||||
* fail. This page also doubles as the SW's offline navigation fallback.
|
||||
*/
|
||||
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { useCallback, useEffect, useState, useSyncExternalStore } from "react";
|
||||
import {
|
||||
BookOpen,
|
||||
FileText,
|
||||
@@ -67,33 +67,45 @@ function formatDate(ms: number): string {
|
||||
}
|
||||
}
|
||||
|
||||
export default function OfflineContentPage() {
|
||||
// External-store readers for the two client-only, non-React values. Using
|
||||
// useSyncExternalStore (instead of setState-in-an-effect) is SSR-safe and
|
||||
// avoids the "setState synchronously within an effect" cascade warning.
|
||||
function subscribeOnline(cb: () => void) {
|
||||
window.addEventListener("online", cb);
|
||||
window.addEventListener("offline", cb);
|
||||
return () => {
|
||||
window.removeEventListener("online", cb);
|
||||
window.removeEventListener("offline", cb);
|
||||
};
|
||||
}
|
||||
const noopSubscribe = () => () => {};
|
||||
|
||||
export default function DownloadsPage() {
|
||||
const [items, setItems] = useState<OfflineItem[] | null>(null);
|
||||
const [usage, setUsage] = useState<number | null>(null);
|
||||
const [online, setOnline] = useState(true);
|
||||
const [supported, setSupported] = useState(true);
|
||||
|
||||
// Client-only reads via external stores (SSR snapshot → server-safe default).
|
||||
const online = useSyncExternalStore(
|
||||
subscribeOnline,
|
||||
() => navigator.onLine,
|
||||
() => true,
|
||||
);
|
||||
const supported = useSyncExternalStore(
|
||||
noopSubscribe,
|
||||
() => offlineSupported(),
|
||||
() => false,
|
||||
);
|
||||
|
||||
const refresh = useCallback(async () => {
|
||||
setItems(await listOffline());
|
||||
setUsage(await usageBytes());
|
||||
}, []);
|
||||
|
||||
// Load the library once mounted. The setState calls happen after an await
|
||||
// (asynchronously), not synchronously in the effect body.
|
||||
useEffect(() => {
|
||||
if (!offlineSupported()) {
|
||||
setSupported(false);
|
||||
setItems([]);
|
||||
return;
|
||||
}
|
||||
setOnline(navigator.onLine);
|
||||
if (!offlineSupported()) return;
|
||||
void refresh();
|
||||
const on = () => setOnline(true);
|
||||
const off = () => setOnline(false);
|
||||
window.addEventListener("online", on);
|
||||
window.addEventListener("offline", off);
|
||||
return () => {
|
||||
window.removeEventListener("online", on);
|
||||
window.removeEventListener("offline", off);
|
||||
};
|
||||
}, [refresh]);
|
||||
|
||||
async function remove(key: string) {
|
||||
@@ -71,7 +71,7 @@ export default function SettingsPage() {
|
||||
description="Pages and lectures you've saved to read or listen to without a connection. Saved on this device — open the library to remove downloads and free up space."
|
||||
>
|
||||
<ul className="divide-y divide-border">
|
||||
<LegalLink href="/offline-content" label="Manage offline library" />
|
||||
<LegalLink href="/downloads" label="Manage offline downloads" />
|
||||
</ul>
|
||||
</Section>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user