import * as FileSystem from "expo-file-system"; import { useNavigation } from "expo-router"; import * as Sharing from "expo-sharing"; import { useCallback, useEffect, useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import { ScrollView, TouchableOpacity, View } from "react-native"; import Collapsible from "react-native-collapsible"; import { Text } from "@/components/common/Text"; import { FilterButton } from "@/components/filters/FilterButton"; import { Loader } from "@/components/Loader"; import { LogLevel, useLog, writeErrorLog } from "@/utils/log"; export default function page() { const navigation = useNavigation(); const { logs } = useLog(); const { t } = useTranslation(); const defaultLevels: LogLevel[] = ["INFO", "ERROR", "DEBUG", "WARN"]; const codeBlockStyle = { backgroundColor: "#000", padding: 10, fontFamily: "monospace", maxHeight: 300, }; const [loading, setLoading] = useState(false); const [state, setState] = useState>({}); const [order, setOrder] = useState<"asc" | "desc">("desc"); const [levels, setLevels] = useState(defaultLevels); const filteredLogs = useMemo( () => logs ?.filter((log) => levels.includes(log.level)) ?.[ // Already in asc order as they are recorded. just reverse for desc order === "desc" ? "reverse" : "concat" ]?.(), [logs, order, levels], ); // Sharing it as txt while its formatted allows us to share it with many more applications const share = useCallback(async () => { const uri = `${FileSystem.documentDirectory}logs.txt`; setLoading(true); FileSystem.writeAsStringAsync(uri, JSON.stringify(filteredLogs)) .then(() => { setLoading(false); Sharing.shareAsync(uri, { mimeType: "txt", UTI: "txt" }); }) .catch((e) => writeErrorLog("Something went wrong attempting to export", e), ) .finally(() => setLoading(false)); }, [filteredLogs]); useEffect(() => { navigation.setOptions({ headerRight: () => loading ? ( ) : ( {t("home.settings.logs.export_logs")} ), }); }, [share, loading]); return ( <> ["asc", "desc"]} set={(values) => setOrder(values[0])} values={[order]} title={t("library.filters.sort_order")} renderItemLabel={(order) => t(`library.filters.${order}`)} showSearch={false} /> defaultLevels} set={setLevels} values={levels} title={t("home.settings.logs.level")} renderItemLabel={(level) => level} showSearch={false} multiple={true} /> {filteredLogs?.map((log, index) => ( setState((v) => ({ ...v, [log.timestamp]: !v[log.timestamp], })) } > {log.level} {new Date(log.timestamp).toLocaleString()} {log.message} {log.data && ( <> {!state[log.timestamp] && ( {t("home.settings.logs.click_for_more_info")} )} {JSON.stringify(log.data, null, 2)} )} ))} {filteredLogs?.length === 0 && ( {t("home.settings.logs.no_logs_available")} )} ); }