Serve the userscript from the backend; card + loading fixes #8

Merged
sulthan merged 6 commits from userscript-download-url into main 2026-07-28 18:28:28 +07:00
Showing only changes of commit d2916d4403 - Show all commits
+30 -30
View File
@@ -1094,37 +1094,36 @@
const sub = behind const sub = behind
? "Read: " + (b.last_chapter || "—") + " · Latest: " + b.latest_chapter ? "Read: " + (b.last_chapter || "—") + " · Latest: " + b.latest_chapter
: (b.last_chapter || "—") + " · " + b.site; : (b.last_chapter || "—") + " · " + b.site;
// Cover and text are one link: the card body *is* the continue button, so // Cover and title are the only continue links. The subtitle and the action
// there is no separate one. The action row is a sibling of that link, never // row live in the same text column but are not navigation targets — a thumb
// a child — a thumb that misses ★ must not land on a navigation target, and // that misses ★ must not land on one, and Remove must never be one.
// Remove must never be one.
return el("div", { class: "item" }, [ return el("div", { class: "item" }, [
el("a", { class: "go", href: cont }, [ el("a", { class: "go", href: cont }, [
b.cover b.cover
? el("img", { class: "cover", src: b.cover, loading: "lazy", alt: "" }) ? el("img", { class: "cover", src: b.cover, loading: "lazy", alt: "" })
: el("div", { class: "cover ph" }), : el("div", { class: "cover ph" }),
el("div", { class: "meta" }, [
el("div", { class: "t", text: b.title || b.series_id }),
el("div", { class: "c" + (behind ? " behind" : ""), text: sub }),
]),
]), ]),
el("div", { class: "actions" }, [ el("div", { class: "meta" }, [
el("button", { el("a", { class: "go-t t", href: cont, text: b.title || b.series_id }),
class: "btn small star" + (b.favorite ? " on" : ""), el("div", { class: "c" + (behind ? " behind" : ""), text: sub }),
text: b.favorite ? "★" : "☆", el("div", { class: "actions" }, [
title: b.favorite ? "Remove from favourites" : "Add to favourites", el("button", {
onclick: () => toggleFavorite(b.key), class: "btn small star" + (b.favorite ? " on" : ""),
}), text: b.favorite ? "★" : "☆",
el("button", { title: b.favorite ? "Remove from favourites" : "Add to favourites",
class: "btn small", onclick: () => toggleFavorite(b.key),
text: statusOf(b) === "archived" ? "Unarchive" : "Archive", }),
onclick: () => toggleArchive(b.key), el("button", {
}), class: "btn small",
el("button", { text: statusOf(b) === "archived" ? "Unarchive" : "Archive",
class: "btn small danger", onclick: () => toggleArchive(b.key),
text: "Remove", }),
onclick: () => confirmRemove(b), el("button", {
}), class: "btn small danger",
text: "Remove",
onclick: () => confirmRemove(b),
}),
]),
]), ]),
]); ]);
} }
@@ -1382,16 +1381,17 @@
#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; }
.item { .item {
display: flex; flex-direction: column; gap: 8px; display: flex; flex-direction: row; gap: 10px;
padding: 10px 16px; border-bottom: 1px solid #2a2a33; padding: 10px 16px; border-bottom: 1px solid #2a2a33;
} }
.go { display: flex; gap: 10px; text-decoration: none; color: inherit; } .go { display: block; flex: none; }
.go:active { opacity: .7; } .go:active, .go-t:active { opacity: .7; }
.go-t { display: block; text-decoration: none; color: inherit; }
.cover { width: 46px; height: 62px; object-fit: cover; border-radius: 4px; flex: none; background: #333; } .cover { width: 46px; height: 62px; object-fit: cover; border-radius: 4px; flex: none; background: #333; }
.cover.ph { display: block; } .cover.ph { display: block; }
.meta { min-width: 0; flex: 1; } .meta { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: 6px; }
.t { font-weight: 600; font-size: 14px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .t { font-weight: 600; font-size: 14px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.c { color: #9a9aa5; font-size: 12px; margin: 2px 0 0; } .c { color: #9a9aa5; font-size: 12px; margin: 0; }
.c.behind { color: #c4b5fd; } .c.behind { color: #c4b5fd; }
.actions { display: flex; gap: 6px; flex-wrap: wrap; } .actions { display: flex; gap: 6px; flex-wrap: wrap; }
.btn { .btn {