124 lines
4.3 KiB
JavaScript
124 lines
4.3 KiB
JavaScript
import React, { useMemo, useState } from "react";
|
|
import { StyleSheet, Text, View } from "react-native";
|
|
import { ActivityIndicator, Chip } from "react-native-paper";
|
|
import { useNavigation } from "@react-navigation/native";
|
|
import { extractBibleReferences, fetchBiblePassage, translateBibleReference } from "../utils/bibleReferences.js";
|
|
import GlobalState from "../contexts/GlobalState.js";
|
|
import { useSnapshot } from "valtio";
|
|
import i18n from "../i18nMessages.js";
|
|
|
|
const BibleEmbeddedView = ({ content = "", compact = false, openChapterOnPress = false }) => {
|
|
const navigation = useNavigation();
|
|
const gState = useSnapshot(GlobalState);
|
|
const references = useMemo(() => extractBibleReferences(content), [content]);
|
|
const [selectedRef, setSelectedRef] = useState("");
|
|
const [byReference, setByReference] = useState({});
|
|
|
|
if (!references.length) return null;
|
|
|
|
const handleSelectReference = async (reference) => {
|
|
if (openChapterOnPress) {
|
|
navigation.navigate("BibleChapter", { reference });
|
|
return;
|
|
}
|
|
setSelectedRef(reference);
|
|
const current = byReference[reference];
|
|
if (current?.loading || current?.text || current?.error) return;
|
|
|
|
setByReference((prev) => ({ ...prev, [reference]: { loading: true } }));
|
|
try {
|
|
const preferredTranslation = GlobalState.me?.data?.bibleTranslation || "";
|
|
const data = await fetchBiblePassage(reference, i18n.locale, preferredTranslation);
|
|
setByReference((prev) => ({ ...prev, [reference]: { loading: false, ...data } }));
|
|
} catch (_error) {
|
|
setByReference((prev) => ({ ...prev, [reference]: { loading: false, error: true } }));
|
|
}
|
|
};
|
|
|
|
const selectedData = selectedRef ? byReference[selectedRef] : null;
|
|
|
|
return (
|
|
<View style={[styles.container, compact ? styles.compactContainer : null]}>
|
|
<Text style={styles.label}>{i18n.t("message.bible")}</Text>
|
|
<View style={styles.chipsWrap}>
|
|
{references.map((reference) => (
|
|
<Chip
|
|
key={reference}
|
|
mode={selectedRef === reference ? "flat" : "outlined"}
|
|
selected={selectedRef === reference}
|
|
compact
|
|
style={styles.chip}
|
|
onPress={() => handleSelectReference(reference)}
|
|
>
|
|
{translateBibleReference(reference, i18n.locale)}
|
|
</Chip>
|
|
))}
|
|
</View>
|
|
{selectedData?.loading ? <ActivityIndicator size="small" style={styles.loader} /> : null}
|
|
{selectedData?.text ? (
|
|
<View style={styles.previewBox}>
|
|
<Text style={styles.previewText}>{selectedData.text.slice(0, compact ? 160 : 280)}</Text>
|
|
<Text style={styles.previewMeta}>
|
|
{translateBibleReference(selectedData.reference, i18n.locale)} ({selectedData.translation})
|
|
</Text>
|
|
</View>
|
|
) : null}
|
|
{selectedData?.error ? <Text style={styles.errorText}>{i18n.t("message.unableLoadPassage")}</Text> : null}
|
|
</View>
|
|
);
|
|
};
|
|
|
|
export default BibleEmbeddedView;
|
|
|
|
const styles = StyleSheet.create({
|
|
container: {
|
|
paddingTop: 6,
|
|
paddingHorizontal: 8,
|
|
},
|
|
compactContainer: {
|
|
paddingTop: 4,
|
|
paddingHorizontal: 0,
|
|
},
|
|
label: {
|
|
fontSize: 12,
|
|
color: "#4b5563",
|
|
fontWeight: "700",
|
|
marginBottom: 4,
|
|
},
|
|
chipsWrap: {
|
|
flexDirection: "row",
|
|
flexWrap: "wrap",
|
|
},
|
|
chip: {
|
|
marginRight: 6,
|
|
marginBottom: 6,
|
|
backgroundColor: "#f8fafc",
|
|
},
|
|
loader: {
|
|
alignSelf: "flex-start",
|
|
},
|
|
previewBox: {
|
|
marginTop: 2,
|
|
backgroundColor: "#f8fafc",
|
|
borderWidth: 1,
|
|
borderColor: "#e5e7eb",
|
|
borderRadius: 10,
|
|
padding: 8,
|
|
},
|
|
previewText: {
|
|
fontSize: 13,
|
|
color: "#111827",
|
|
},
|
|
previewMeta: {
|
|
marginTop: 4,
|
|
fontSize: 11,
|
|
color: "#6b7280",
|
|
fontWeight: "600",
|
|
},
|
|
errorText: {
|
|
marginTop: 2,
|
|
fontSize: 12,
|
|
color: "#b91c1c",
|
|
},
|
|
});
|