summaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-07-24 14:31:48 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-07-24 14:31:48 +0200
commitc769f80475e99b1f810fbb6c29eade3cc43a3786 (patch)
tree3d1b4fe2a540b6ccbb11256ad26305b15a3c074e /internal
parenta87f2fafbda90cc9eeb32ea856356c34e1d880b0 (diff)
downloadlectio-c769f80475e99b1f810fbb6c29eade3cc43a3786.tar.gz
lectio-c769f80475e99b1f810fbb6c29eade3cc43a3786.zip
web: empty pane when no version selected (hidden vset marker); config default checked on fresh load; v0.13.0
Diffstat (limited to 'internal')
-rw-r--r--internal/config/config.go2
-rw-r--r--internal/web/server.go29
-rw-r--r--internal/web/server_test.go30
-rw-r--r--internal/web/templates/index.html3
4 files changed, 56 insertions, 8 deletions
diff --git a/internal/config/config.go b/internal/config/config.go
index 9a6df04..493b4f5 100644
--- a/internal/config/config.go
+++ b/internal/config/config.go
@@ -24,7 +24,7 @@ var seedTOML []byte
// Version is lectio's release version, shared by every binary's
// -v/--version output (lectio, lectio-ui, lectio-web).
-const Version = "0.12.0"
+const Version = "0.13.0"
// validVersions are the five scripture versions lectio understands.
var validVersions = map[string]bool{
diff --git a/internal/web/server.go b/internal/web/server.go
index 667e986..6393076 100644
--- a/internal/web/server.go
+++ b/internal/web/server.go
@@ -89,13 +89,18 @@ func shiftDate(date string, days int) string {
}
// requestVersions returns the versions requested via one or more repeated
-// ?v= query params, falling back to a single cfg.DefaultVersion (not the
-// full cfg.Versions set) when none were given, so a plain visit checks
-// exactly one version box.
+// ?v= query params. The controls form always submits a hidden "vset" marker,
+// so a request that carries "vset" but no "v" means the user unchecked EVERY
+// version -- return none (the pane then shows nothing). A request with neither
+// (a fresh visit or a bare link) falls back to cfg.WebVersions, else a single
+// cfg.DefaultVersion, so a plain visit checks exactly one box.
func requestVersions(cfg config.Config, r *http.Request) []string {
if vs, ok := r.URL.Query()["v"]; ok && len(vs) > 0 {
return vs
}
+ if r.URL.Query().Has("vset") {
+ return nil // form submitted with every box unchecked
+ }
if len(cfg.WebVersions) > 0 {
return append([]string(nil), cfg.WebVersions...)
}
@@ -214,8 +219,15 @@ func indexHandler(cfg config.Config) http.HandlerFunc {
theme = cfg.WebTheme
}
- secs, dayInfo, loadVersions, err := loadSections(cfg, lectionary, date, all, versions)
- reading := renderOrError(secs, loadVersions, lectionary, display, cfg.UILanguage, dayInfo, err)
+ // No version selected -> fetch nothing and show nothing (empty pane, no
+ // day-info/headings); loadVersions stays nil so no box is checked.
+ var reading template.HTML
+ var loadVersions []string
+ if len(versions) > 0 {
+ secs, dayInfo, lv, err := loadSections(cfg, lectionary, date, all, versions)
+ loadVersions = lv
+ reading = renderOrError(secs, lv, lectionary, display, cfg.UILanguage, dayInfo, err)
+ }
// Check the boxes for the versions actually rendered (loadVersions),
// not the raw request: traditional/offline substitute pl->wuj, so the
@@ -264,8 +276,11 @@ func readingsHandler(cfg config.Config) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
date, lectionary, all, versions, display := resolveQuery(cfg, r)
- secs, dayInfo, loadVersions, err := loadSections(cfg, lectionary, date, all, versions)
- reading := renderOrError(secs, loadVersions, lectionary, display, cfg.UILanguage, dayInfo, err)
+ var reading template.HTML
+ if len(versions) > 0 {
+ secs, dayInfo, loadVersions, err := loadSections(cfg, lectionary, date, all, versions)
+ reading = renderOrError(secs, loadVersions, lectionary, display, cfg.UILanguage, dayInfo, err)
+ }
w.Header().Set("Content-Type", "text/html; charset=utf-8")
io.WriteString(w, string(reading))
diff --git a/internal/web/server_test.go b/internal/web/server_test.go
index 638eb2b..925ea18 100644
--- a/internal/web/server_test.go
+++ b/internal/web/server_test.go
@@ -407,6 +407,36 @@ func TestChooseListener(t *testing.T) {
})
}
+// TestVsetEmptyShowsNothing guards the "uncheck all -> show nothing" behavior:
+// a form submit (vset present) with no v param yields an empty pane, while a
+// fresh visit (no vset) checks the config default and renders it.
+func TestVsetEmptyShowsNothing(t *testing.T) {
+ srv := NewServer(config.Default())
+
+ // Form submit, every box unchecked: empty pane, nothing checked.
+ empty := httptest.NewRecorder()
+ srv.ServeHTTP(empty, httptest.NewRequest("GET", "/readings?vset=1&lectionary=traditional", nil))
+ if b := strings.TrimSpace(empty.Body.String()); b != "" {
+ t.Errorf("readings with vset and no v should be empty, got %q", b)
+ }
+
+ // Fresh visit (no vset): config default (bt for modern) box is checked.
+ fresh := httptest.NewRecorder()
+ srv.ServeHTTP(fresh, httptest.NewRequest("GET", "/", nil))
+ if !strings.Contains(fresh.Body.String(), `value="bt" checked`) {
+ t.Errorf("fresh visit should check the config default (bt) version box")
+ }
+
+ // Full page with vset and no v: no VERSION box checked (mono may be).
+ idx := httptest.NewRecorder()
+ srv.ServeHTTP(idx, httptest.NewRequest("GET", "/?vset=1", nil))
+ for _, v := range bibleVersions {
+ if strings.Contains(idx.Body.String(), `value="`+v+`" checked`) {
+ t.Errorf("index with vset and no v: %q box should not be checked", v)
+ }
+ }
+}
+
// TestReaderPaneOutsideForm guards the mono fix: #pane must render AFTER the
// controls </form> so its reading text inherits body's --font-reading (which
// the mono toggle flips) instead of the form's --font-ui.
diff --git a/internal/web/templates/index.html b/internal/web/templates/index.html
index 5dbe7da..6920fcb 100644
--- a/internal/web/templates/index.html
+++ b/internal/web/templates/index.html
@@ -24,6 +24,9 @@
<div class="page">
<form id="controls" class="controls" hx-get="/readings" hx-target="#pane" hx-trigger="change">
+ {{/* Always-present marker so the server can tell a form submit with every
+ version unchecked (show nothing) from a fresh visit (config default). */}}
+ <input type="hidden" name="vset" value="1">
<span class="date-nav">
<button type="button" hx-get="/readings" hx-target="#pane"
hx-vals='{"date":"{{.PrevDate}}"}'>&larr;</button>