// Import necessary packages import React, { useState, useEffect } from "react"; import { View, Text, TextInput, StyleSheet, Pressable } from "react-native"; // Add Picker import import { getDb } from "@/app/lib/db"; import { Settings } from "@/app/lib/settings"; import { LanguageServer, fetchWithTimeout } from "@/app/i18n/api"; import { Picker } from "@react-native-picker/picker"; import { longLang } from "@/app/i18n/lang"; import { LIBRETRANSLATE_BASE_URL } from "@/constants/api"; import { WHISPER_MODELS, WHISPER_MODEL_DIR, downloadWhisperModel, download_status, getWhisperDownloadStatus, getWhisperTarget, whisper_model_tag_t, } from "@/app/lib/whisper"; import { Paths } from "expo-file-system/next"; type Language = { code: string; name: string; }; type LanguageMatrix = { [key: string]: Language; }; type connection_test_t = | { success: true; } | { success: false; error: string; }; const SettingsComponent: React.FC = () => { const [hostLanguage, setHostLanguage] = useState(null); const [libretranslateBaseUrl, setLibretranslateBaseUrl] = useState< string | null >(null); const [languages, setLanguages] = useState(); const [isLoaded, setIsLoaded] = useState(false); const [whisperModel, setWhisperModel] = useState< undefined | whisper_model_tag_t >(); const [downloadStatus, setDownloadStatus] = useState< undefined | download_status >(); const [langServerConn, setLangServerConn] = useState< undefined | connection_test_t >(); const fillHostLanguageOptions = async () => { const settings = await Settings.getDefault(); const hostLang = await settings.getHostLanguage(); setHostLanguage(hostLang || "en"); const langServer = new LanguageServer( libretranslateBaseUrl || LIBRETRANSLATE_BASE_URL ); // Fetch languages from API try { const langData = await langServer.fetchLanguages(); setLanguages(langData); setLangServerConn({ success: true }); } catch (err) { console.warn("Got an error fetching: %s", err); setLangServerConn({ success: false, error: `Could not connect to ${libretranslateBaseUrl}: ${err}`, }); } } useEffect(() => { (async () => { // Fetch the database connection // const db = await getDb("down"); const settings = await Settings.getDefault(); await fillHostLanguageOptions(); console.log("Fetched settings"); // Get the current settings values const libretranslateUrl = (await settings.getLibretranslateBaseUrl()) || LIBRETRANSLATE_BASE_URL; setLibretranslateBaseUrl(libretranslateUrl); console.log("libretranslate url = %s", libretranslateUrl); try { const wModel = await settings.getWhisperModel(); setWhisperModel(wModel || "small"); } catch (err) { console.warn(err); } // setWhisperModel(wModel); setIsLoaded(true); // console.log("Set is loaded: %s", isLoaded); })(); // Check for whether a model is currently downloading and set the status. setInterval(async () => { if (!whisperModel) return null; const dlStatus = await getWhisperDownloadStatus(whisperModel); setDownloadStatus(dlStatus); }, 200); setInterval(async () => { if (!libretranslateBaseUrl) return; try { const resp = await fetchWithTimeout( libretranslateBaseUrl + "/languages", { method: "HEAD", headers: { Accept: "application/json", "Content-Type": "application/json", }, }, 5000 ); if (resp.status !== 200) { throw new Error(resp.statusText); } setLangServerConn({ success: true }); } catch (err) { setLangServerConn({ success: false, error: `Could not connect to ${libretranslateBaseUrl}: ${err}`, }); } }, 1000); setInterval(async () => { const settings = await Settings.getDefault(); await settings.setHostLanguage(hostLanguage || "en"); await settings.setLibretranslateBaseUrl( libretranslateBaseUrl || LIBRETRANSLATE_BASE_URL ); await settings.setWhisperModel(whisperModel || "small"); }, 1000); }, []); const doReadownload = async () => { if (!whisperModel) return; await downloadWhisperModel(whisperModel, { force_redownload: true }); }; const doDownload = async () => { if (!whisperModel) return; await downloadWhisperModel(whisperModel); }; const handleHostLanguageChange = async (value: string) => { setHostLanguage(value); // Fetch the database connection const db = await getDb(); const settings = new Settings(db); // Save the updated setting value await settings.setHostLanguage(value); }; const handleLibretranslateBaseUrlChange = async (value: string) => { setLibretranslateBaseUrl(value); const settings = await Settings.getDefault(); // Save the updated setting value await settings.setLibretranslateBaseUrl(value); await fillHostLanguageOptions(); }; return isLoaded ? ( Host Language: {languages && Object.entries(languages).map((lang) => ( ))} LibreTranslate Base URL: {langServerConn && (langServerConn.success ? ( Success connecting to {libretranslateBaseUrl} ) : ( Error connecting to {libretranslateBaseUrl}: {langServerConn.error} ))} {Object.entries(WHISPER_MODELS).map(([key, { label }]) => ( ))} {whisperModel && ( {downloadStatus?.status === "complete" ? ( Re-Download ) : downloadStatus?.status === "in_progress" ? ( {(downloadStatus.bytes.done / downloadStatus.bytes.total) * 100.0}{" "} % complete {downloadStatus.bytes.done} bytes of {downloadStatus.bytes.total} ) : ( Download This will download to {Paths.join(WHISPER_MODEL_DIR, WHISPER_MODELS[whisperModel].target)} )} )} ) : ( Loading ... ); }; // Create styles for the component const styles = StyleSheet.create({ button: { backgroundColor: "blue", flexDirection: "row", display: "flex", flexShrink: 1, padding: 20, alignItems: "center", alignContent: "center", }, buttonText: { color: "white", alignSelf: "center", }, container: { flex: 1, padding: 20, }, label: { fontSize: 16, marginBottom: 8, }, input: { height: 40, borderColor: "gray", borderWidth: 1, marginBottom: 20, paddingHorizontal: 8, }, }); export default SettingsComponent;