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
? "Read: " + (b.last_chapter || "—") + " · Latest: " + b.latest_chapter
: (b.last_chapter || "—") + " · " + b.site;
// Cover and text are one link: the card body *is* the continue button, so
// there is no separate one. The action row is a sibling of that link, never
// a child — a thumb that misses ★ must not land on a navigation target, and
// Remove must never be one.
// Cover and title are the only continue links. The subtitle and the action
// row live in the same text column but are not navigation targets — a thumb
// that misses ★ must not land on one, and Remove must never be one.
return el("div", { class: "item" }, [
el("a", { class: "go", href: cont }, [
b.cover
? el("img", { class: "cover", src: b.cover, loading: "lazy", alt: "" })
: 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("button", {
class: "btn small star" + (b.favorite ? " on" : ""),
text: b.favorite ? "★" : "☆",
title: b.favorite ? "Remove from favourites" : "Add to favourites",
onclick: () => toggleFavorite(b.key),
}),
el("button", {
class: "btn small",
text: statusOf(b) === "archived" ? "Unarchive" : "Archive",
onclick: () => toggleArchive(b.key),
}),
el("button", {
class: "btn small danger",
text: "Remove",
onclick: () => confirmRemove(b),
}),
el("div", { class: "meta" }, [
el("a", { class: "go-t t", href: cont, text: b.title || b.series_id }),
el("div", { class: "c" + (behind ? " behind" : ""), text: sub }),
el("div", { class: "actions" }, [
el("button", {
class: "btn small star" + (b.favorite ? " on" : ""),
text: b.favorite ? "★" : "☆",
title: b.favorite ? "Remove from favourites" : "Add to favourites",
onclick: () => toggleFavorite(b.key),
}),
el("button", {
class: "btn small",
text: statusOf(b) === "archived" ? "Unarchive" : "Archive",
onclick: () => toggleArchive(b.key),
}),
el("button", {
class: "btn small danger",
text: "Remove",
onclick: () => confirmRemove(b),
}),
]),
]),
]);
}
@@ -1382,16 +1381,17 @@
#list { overflow-y: auto; flex: 1; padding: 8px 0; }
.empty { color: #9a9aa5; text-align: center; padding: 30px 16px; font-size: 14px; }
.item {
display: flex; flex-direction: column; gap: 8px;
display: flex; flex-direction: row; gap: 10px;
padding: 10px 16px; border-bottom: 1px solid #2a2a33;
}
.go { display: flex; gap: 10px; text-decoration: none; color: inherit; }
.go:active { opacity: .7; }
.go { display: block; flex: none; }
.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.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; }
.c { color: #9a9aa5; font-size: 12px; margin: 2px 0 0; }
.c { color: #9a9aa5; font-size: 12px; margin: 0; }
.c.behind { color: #c4b5fd; }
.actions { display: flex; gap: 6px; flex-wrap: wrap; }
.btn {