Work the design critique down: chapter format, colour law, search, strip, a11y #11
+14
-7
@@ -200,14 +200,21 @@ func (h *webHandler) buildListView(tab string) (listView, error) {
|
||||
tab = "all"
|
||||
items = reading
|
||||
}
|
||||
// The strip is the head of the same updated_at DESC reading list the All tab
|
||||
// renders, so it only earns its ~230px of the first phone screen where it is
|
||||
// not a pure duplicate of what sits right below it: on All, with more series
|
||||
// than it shows. On the other tabs it either repeats the list or, worse,
|
||||
// puts reading series above the archived and finished buckets.
|
||||
// The strip is scoped to series with a chapter waiting, which is the one
|
||||
// question the list below it does not already answer: the list is ordered by
|
||||
// reading recency, so the head of it *is* the strip whenever the strip is
|
||||
// just "the most recent rows". Only on All — on Updated it would render the
|
||||
// same set twice, and on the other tabs it would contradict the bucket.
|
||||
//
|
||||
// It therefore disappears entirely on a library with nothing new. That is
|
||||
// the intended reading: an empty strip has nothing to say, and the ~240px it
|
||||
// costs on a phone belongs to the list.
|
||||
var recent []Bookmark
|
||||
if tab == "all" && len(reading) > recentCount {
|
||||
recent = reading[:recentCount]
|
||||
if tab == "all" {
|
||||
recent = withNew
|
||||
if len(recent) > recentCount {
|
||||
recent = recent[:recentCount]
|
||||
}
|
||||
}
|
||||
return listView{Tab: tab, Recent: recent, Items: items, NewCount: len(withNew)}, nil
|
||||
}
|
||||
|
||||
+50
-24
@@ -594,43 +594,69 @@ func stripOf(t *testing.T, srv http.Handler, cfg Config, tab string) string {
|
||||
return body
|
||||
}
|
||||
|
||||
// The strip is the head of the same list the All tab renders, so it only shows
|
||||
// where it is not a pure duplicate: on All, with more reading series than it
|
||||
// holds.
|
||||
func TestRecentStripOnlyOnAllAndOnlyWhenItAddsSomething(t *testing.T) {
|
||||
// The strip carries the series with a chapter waiting — the one thing the
|
||||
// updated_at-ordered list below it does not already say — and only on All.
|
||||
func TestRecentStripCarriesUnreadOnlyAndOnlyOnAll(t *testing.T) {
|
||||
cfg := webConfig()
|
||||
srv, store := newWebTestServer(t, cfg)
|
||||
seedStatusRows(t, store)
|
||||
seedStatusRows(t, store) // ReadingOne is at 10 with 11 out; the rest are not reading
|
||||
|
||||
for _, tab := range []string{"all", "new", "fav", "archived", "finished"} {
|
||||
if strings.Contains(stripOf(t, srv, cfg, tab), `class="recent"`) {
|
||||
t.Fatalf("tab %s rendered the strip for a library of one reading series", tab)
|
||||
// A reading series that is caught up has nothing waiting, so it stays out.
|
||||
caught := Bookmark{
|
||||
Key: "asura:caught", Site: "asura", SeriesID: "caught", Title: "CaughtUpOne",
|
||||
Status: statusReading, LastChapterNum: 40, LatestChapter: "40",
|
||||
LatestChapterNum: floatPtr(40), UpdatedAt: time.Now().UnixMilli(),
|
||||
}
|
||||
if _, err := store.Upsert(caught); err != nil {
|
||||
t.Fatalf("seed %s: %v", caught.Key, err)
|
||||
}
|
||||
|
||||
strip := stripOf(t, srv, cfg, "all")
|
||||
if !strings.Contains(strip, "ReadingOne") {
|
||||
t.Fatal("strip dropped the series with an unread chapter")
|
||||
}
|
||||
for _, unwanted := range []string{"CaughtUpOne", "ArchivedOne", "FinishedOne"} {
|
||||
if strings.Contains(strip, unwanted) {
|
||||
t.Fatalf("strip included %s", unwanted)
|
||||
}
|
||||
}
|
||||
for _, tab := range []string{"new", "fav", "archived", "finished"} {
|
||||
if strings.Contains(stripOf(t, srv, cfg, tab), "ReadingOne") {
|
||||
t.Fatalf("tab %s rendered the strip", tab)
|
||||
}
|
||||
}
|
||||
|
||||
// Past recentCount the strip stops repeating the whole list.
|
||||
// Nothing new anywhere: the strip has nothing to say and does not render.
|
||||
reading, _, err := store.Get("asura:reading")
|
||||
if err != nil {
|
||||
t.Fatalf("Get: %v", err)
|
||||
}
|
||||
reading.LatestChapterNum = floatPtr(reading.LastChapterNum)
|
||||
if _, err := store.Upsert(reading); err != nil {
|
||||
t.Fatalf("Upsert: %v", err)
|
||||
}
|
||||
if strings.Contains(stripOf(t, srv, cfg, "all"), `class="recent"`) {
|
||||
t.Fatal("strip rendered with no unread chapters anywhere")
|
||||
}
|
||||
}
|
||||
|
||||
// The strip never grows past recentCount, however many series are waiting.
|
||||
func TestRecentStripCapped(t *testing.T) {
|
||||
cfg := webConfig()
|
||||
srv, store := newWebTestServer(t, cfg)
|
||||
for i := 0; i <= recentCount; i++ {
|
||||
b := Bookmark{
|
||||
Key: fmt.Sprintf("asura:more%d", i), Site: "asura",
|
||||
SeriesID: fmt.Sprintf("more%d", i), Title: fmt.Sprintf("MoreReading%d", i),
|
||||
Status: statusReading, LastChapterNum: 1, UpdatedAt: time.Now().UnixMilli(),
|
||||
Key: fmt.Sprintf("asura:new%d", i), Site: "asura",
|
||||
SeriesID: fmt.Sprintf("new%d", i), Title: fmt.Sprintf("Waiting%d", i),
|
||||
Status: statusReading, LastChapterNum: 1, LatestChapter: "2",
|
||||
LatestChapterNum: floatPtr(2), UpdatedAt: time.Now().UnixMilli() + int64(i),
|
||||
}
|
||||
if _, err := store.Upsert(b); err != nil {
|
||||
t.Fatalf("seed %s: %v", b.Key, err)
|
||||
}
|
||||
}
|
||||
|
||||
strip := stripOf(t, srv, cfg, "all")
|
||||
if !strings.Contains(strip, `class="recent"`) {
|
||||
t.Fatal("strip missing on All with more reading series than it shows")
|
||||
}
|
||||
if strings.Contains(strip, "ArchivedOne") || strings.Contains(strip, "FinishedOne") {
|
||||
t.Fatal("recent strip included an archived or finished series")
|
||||
}
|
||||
for _, tab := range []string{"new", "fav", "archived", "finished"} {
|
||||
if strings.Contains(stripOf(t, srv, cfg, tab), `class="recent"`) {
|
||||
t.Fatalf("tab %s rendered the strip", tab)
|
||||
}
|
||||
if got := strings.Count(stripOf(t, srv, cfg, "all"), "recent-card"); got != recentCount {
|
||||
t.Fatalf("strip rendered %d cards, want %d", got, recentCount)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user