feat: Add continuous Bible reading mode, backend-driven translation API integration, localized book names, and preference caching

This commit is contained in:
Adolfo Reyna
2026-02-25 18:13:53 -05:00
parent fc6f740fd2
commit 9da5874977
8 changed files with 460 additions and 56 deletions

88
Views/Bible.js Normal file
View File

@@ -0,0 +1,88 @@
import React from "react";
import { FlatList, View } from "react-native";
import { Button, Chip, Text } from "react-native-paper";
import { useNavigation } from "@react-navigation/native";
import { BIBLE_BOOKS, getBookChapterCount } from "../utils/bibleReferences.js";
import i18n from "../i18nMessages.js";
const Bible = () => {
const navigation = useNavigation();
const [selectedBook, setSelectedBook] = React.useState("");
const [activeStep, setActiveStep] = React.useState("book");
const selectedBookChapterCount = React.useMemo(() => getBookChapterCount(selectedBook), [selectedBook]);
const chapterOptions = React.useMemo(
() => Array.from({ length: selectedBookChapterCount }, (_v, i) => String(i + 1)),
[selectedBookChapterCount]
);
return (
<View style={{ flex: 1, paddingHorizontal: 12, paddingTop: 12 }}>
<Text style={{ fontSize: 22, fontWeight: "700", marginBottom: 6 }}>{i18n.t("message.bible") || "Read the Bible"}</Text>
<Text style={{ color: "#6b7280", marginBottom: 10 }}>
{i18n.t("message.biblePickerSubtitlePost") || "Select a book and chapter to start reading."}
</Text>
<View style={{ flexDirection: "row", marginBottom: 10 }}>
<Button mode={activeStep === "book" ? "contained-tonal" : "text"} onPress={() => setActiveStep("book")}>
{i18n.t("message.book") || "Book"}
</Button>
<Button
mode={activeStep === "chapter" ? "contained-tonal" : "text"}
disabled={!selectedBook}
onPress={() => setActiveStep("chapter")}
>
{i18n.t("message.chapter") || "Chapter"}
</Button>
</View>
{activeStep === "book" ? (
<>
<Text style={{ fontSize: 14, fontWeight: "600", marginBottom: 8 }}>{i18n.t("message.books") || "Books"}</Text>
<FlatList
data={BIBLE_BOOKS}
numColumns={2}
keyExtractor={(item) => item}
renderItem={({ item }) => (
<Chip
selected={selectedBook === item}
style={{ marginRight: 6, marginBottom: 6, width: "48%" }}
onPress={() => {
setSelectedBook(item);
setActiveStep("chapter");
}}
>
{item}
</Chip>
)}
/>
</>
) : null}
{activeStep === "chapter" ? (
<>
<Text style={{ fontSize: 14, fontWeight: "600", marginBottom: 8 }}>
{i18n.t("message.chapters") || "Chapters"} {selectedBook ? `(${selectedBook})` : ""}
</Text>
<FlatList
data={chapterOptions}
numColumns={6}
keyExtractor={(item) => item}
renderItem={({ item }) => (
<Chip
style={{ marginRight: 6, marginBottom: 6, minWidth: 44 }}
onPress={() => {
navigation.navigate("BibleChapter", { reference: `${selectedBook} ${item}`, selectable: false });
}}
>
{item}
</Chip>
)}
/>
</>
) : null}
</View>
);
};
export default Bible;