Serve the userscript from the backend; card + loading fixes #8
@@ -852,6 +852,9 @@
|
|||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
||||||
let root, panelOpen = false;
|
let root, panelOpen = false;
|
||||||
|
// True while refresh() is waiting on the backend. Only changes what the list
|
||||||
|
// draws when there is nothing cached to draw instead.
|
||||||
|
let loading = false;
|
||||||
let activeTab = "all"; // "all" | "favorites" | "archived"; resets each page, by design
|
let activeTab = "all"; // "all" | "favorites" | "archived"; resets each page, by design
|
||||||
|
|
||||||
function buildUI() {
|
function buildUI() {
|
||||||
@@ -1071,7 +1074,11 @@
|
|||||||
if (s !== "reading") return false;
|
if (s !== "reading") return false;
|
||||||
return activeTab !== "favorites" || b.favorite;
|
return activeTab !== "favorites" || b.favorite;
|
||||||
});
|
});
|
||||||
if (items.length === 0) {
|
if (items.length === 0 && loading) {
|
||||||
|
// Nothing cached and the fetch is still out — without this the panel
|
||||||
|
// looks frozen on the first open after a cold start.
|
||||||
|
listEl.appendChild(el("div", { class: "empty" }, [el("div", { class: "spinner" })]));
|
||||||
|
} else if (items.length === 0) {
|
||||||
const empty = {
|
const empty = {
|
||||||
favorites: "No favourites yet.",
|
favorites: "No favourites yet.",
|
||||||
archived: "Nothing archived.",
|
archived: "Nothing archived.",
|
||||||
@@ -1154,12 +1161,16 @@
|
|||||||
|
|
||||||
async function refresh() {
|
async function refresh() {
|
||||||
await drain(); // push what we owe before adopting the server's view of it
|
await drain(); // push what we owe before adopting the server's view of it
|
||||||
|
loading = true;
|
||||||
|
render();
|
||||||
try {
|
try {
|
||||||
const list = await apiGet();
|
const list = await apiGet();
|
||||||
setList(overlayPending(list));
|
setList(overlayPending(list));
|
||||||
render();
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
render(); // fall back to cache
|
// Offline or backend down: keep whatever the cache holds.
|
||||||
|
} finally {
|
||||||
|
loading = false;
|
||||||
|
render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1380,6 +1391,12 @@
|
|||||||
.tab.active { color: #eee; border-bottom-color: #6d28d9; }
|
.tab.active { color: #eee; border-bottom-color: #6d28d9; }
|
||||||
#list { overflow-y: auto; flex: 1; padding: 8px 0; }
|
#list { overflow-y: auto; flex: 1; padding: 8px 0; }
|
||||||
.empty { color: #9a9aa5; text-align: center; padding: 30px 16px; font-size: 14px; }
|
.empty { color: #9a9aa5; text-align: center; padding: 30px 16px; font-size: 14px; }
|
||||||
|
.spinner {
|
||||||
|
width: 26px; height: 26px; margin: 0 auto;
|
||||||
|
border: 3px solid #33333d; border-top-color: #6d28d9; border-radius: 50%;
|
||||||
|
animation: spin .8s linear infinite;
|
||||||
|
}
|
||||||
|
@keyframes spin { to { transform: rotate(360deg); } }
|
||||||
.item {
|
.item {
|
||||||
display: flex; flex-direction: row; gap: 10px;
|
display: flex; flex-direction: row; gap: 10px;
|
||||||
padding: 10px 16px; border-bottom: 1px solid #2a2a33;
|
padding: 10px 16px; border-bottom: 1px solid #2a2a33;
|
||||||
|
|||||||
Reference in New Issue
Block a user