From 1106568c52265ea3076b9d3f1943c052c83a2a89 Mon Sep 17 00:00:00 2001 From: Lukasz Kasprzak Date: Mon, 3 Aug 2026 23:59:50 +0200 Subject: mobile: add PartLabels so the app stops hardcoding part IDs --- mobile/mobile.go | 31 +++++++++++++++++++++++++++++++ mobile/mobile_test.go | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) (limited to 'mobile') diff --git a/mobile/mobile.go b/mobile/mobile.go index e79e748..d863463 100644 --- a/mobile/mobile.go +++ b/mobile/mobile.go @@ -184,6 +184,37 @@ func Days(start string, count int, form, lang string) string { return string(b) } +// partLabel is one section's machine ID and its human label. +type partLabel struct { + Part string `json:"part"` + Label string `json:"label"` +} + +// PartLabels returns the form's section IDs and their labels in lang, in display +// order, as a JSON array. The app builds its reading filters from this instead +// of hardcoding part IDs -- which is how it came to ship seven 1962 checkboxes +// the engine never emits. +// +// An array, not an object: JSON object key order is not guaranteed and the app +// renders these in order. +func PartLabels(form, lang string) string { + ids := readings.PartIDs(lectByForm(form)) + ui := i18n.Get(lang) + out := make([]partLabel, 0, len(ids)) + for _, id := range ids { + label := ui.PartLabel[id] + if label == "" { + label = id + } + out = append(out, partLabel{Part: id, Label: label}) + } + b, err := json.Marshal(out) + if err != nil { + return "[]" + } + return string(b) +} + // Ping is a trivial JNI smoke test: it returns "pong" so the app can confirm the // native engine loaded before issuing a real query. func Ping() string { return "pong" } diff --git a/mobile/mobile_test.go b/mobile/mobile_test.go index 57e835a..1a115f3 100644 --- a/mobile/mobile_test.go +++ b/mobile/mobile_test.go @@ -123,3 +123,48 @@ func BenchmarkDaysWeek(b *testing.B) { Days("2026-07-27", 7, "of", "pl") } } + +// This is the assertion that would have caught the app's dead 1962 checkboxes: +// it listed nine part IDs where the engine emits two. +func TestPartLabelsMatchesWhatTheEngineEmits(t *testing.T) { + var ef []map[string]any + if err := json.Unmarshal([]byte(PartLabels("ef", "pl")), &ef); err != nil { + t.Fatalf("invalid JSON: %v", err) + } + if len(ef) != 2 { + t.Fatalf("ef: got %d labels, want 2: %v", len(ef), ef) + } + if ef[0]["part"] != "epistola" || ef[0]["label"] != "Lekcja" { + t.Errorf("ef[0] = %v, want epistola/Lekcja", ef[0]) + } + if ef[1]["part"] != "evangelium" || ef[1]["label"] != "Ewangelia" { + t.Errorf("ef[1] = %v, want evangelium/Ewangelia", ef[1]) + } + + var of []map[string]any + if err := json.Unmarshal([]byte(PartLabels("of", "pl")), &of); err != nil { + t.Fatalf("invalid JSON: %v", err) + } + if len(of) != 5 { + t.Fatalf("of: got %d labels, want 5: %v", len(of), of) + } + // aklamacja was missing from the app's hardcoded list. + var seen []string + for _, e := range of { + seen = append(seen, e["part"].(string)) + } + want := []string{"pierwsze_czytanie", "psalm", "drugie_czytanie", "aklamacja", "ewangelia"} + for i := range want { + if seen[i] != want[i] { + t.Errorf("of order = %v, want %v", seen, want) + break + } + } +} + +func TestPartLabelsUnknownForm(t *testing.T) { + // An unknown form is treated as the modern one, matching lectByForm. + if got := PartLabels("nonsense", "en"); got == "[]" { + t.Error("unknown form should fall back to the modern lectionary, not empty") + } +} -- cgit v1.3