import React from "react";
import { FlatList, Pressable, View } from "react-native";
import { ActivityIndicator, Text } from "react-native-paper";
import { SafeAreaView } from "react-native-safe-area-context";
import { useNavigation } from "@react-navigation/native";
import { parseBibleReference } from "../utils/bibleReferences.js";
import GlobalState from "../contexts/GlobalState.js";
const BibleChapterView = ({ route }) => {
const navigation = useNavigation();
const reference = route?.params?.reference || "";
const selectable = route?.params?.selectable === true;
const { chapterReference, verse: selectedVerse } = parseBibleReference(reference);
const [loading, setLoading] = React.useState(true);
const [error, setError] = React.useState("");
const [chapterData, setChapterData] = React.useState(null);
const listRef = React.useRef(null);
const autoScrolledRef = React.useRef(false);
React.useEffect(() => {
let mounted = true;
const loadChapter = async () => {
setLoading(true);
setError("");
try {
const response = await fetch(`https://bible-api.com/${encodeURIComponent(chapterReference)}`);
if (!response.ok) throw new Error("Failed chapter request");
const payload = await response.json();
if (!mounted) return;
setChapterData(payload);
} catch (_error) {
if (!mounted) return;
setError("Unable to load chapter.");
setChapterData(null);
} finally {
if (mounted) setLoading(false);
}
};
loadChapter();
return () => {
mounted = false;
};
}, [chapterReference]);
const verses = Array.isArray(chapterData?.verses) ? chapterData.verses : [];
const selectedVerseNumber = Number(selectedVerse || 1);
const selectedIndex = verses.findIndex((item) => Number(item?.verse || 0) === selectedVerseNumber);
React.useEffect(() => {
autoScrolledRef.current = false;
}, [chapterReference, selectedVerseNumber]);
const scrollToSelectedVerse = React.useCallback((animated = false) => {
if (autoScrolledRef.current) return;
if (!listRef.current || selectedIndex < 0 || !verses.length) return;
try {
listRef.current.scrollToIndex({
index: selectedIndex,
animated,
viewPosition: 0.35,
});
autoScrolledRef.current = true;
} catch (_error) {
// FlatList can throw before enough measurements are available.
}
}, [selectedIndex, verses.length]);
if (loading) {
return (
);
}
if (error) {
return (
{error}
);
}
const handleVersePress = (verseNumber) => {
if (!selectable) return;
GlobalState.bibleChapterSelection = {
...parseBibleReference(`${chapterReference}:${verseNumber}`),
ts: Date.now(),
};
navigation.goBack();
};
return (
{chapterData?.reference || chapterReference}
{chapterData?.translation_name || chapterData?.translation_id || "KJV"}
{selectable ? (
Tap a verse to select it.
) : null}
`${item?.verse || idx}`}
initialNumToRender={24}
onLayout={() => {
setTimeout(() => scrollToSelectedVerse(false), 40);
}}
onContentSizeChange={() => {
setTimeout(() => scrollToSelectedVerse(false), 40);
}}
onScrollToIndexFailed={({ index, averageItemLength }) => {
if (!listRef.current) return;
listRef.current.scrollToOffset({
offset: Math.max(0, (averageItemLength || 36) * index),
animated: false,
});
setTimeout(() => {
scrollToSelectedVerse(false);
}, 120);
}}
renderItem={({ item }) => {
const verseNumber = Number(item?.verse || 0);
const isSelected = verseNumber === selectedVerseNumber;
return (
handleVersePress(verseNumber)}
style={{
paddingVertical: 8,
paddingHorizontal: 10,
borderRadius: 8,
marginBottom: 6,
backgroundColor: isSelected ? "#fff3cd" : "transparent",
borderWidth: isSelected ? 1 : 0,
borderColor: isSelected ? "#f59e0b" : "transparent",
}}
>
{verseNumber}
{item?.text || ""}
);
}}
/>
);
};
export default BibleChapterView;