166 lines
6.0 KiB
TypeScript

// 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 } 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, downloadWhisperModel, download_status, getWhisperDownloadStatus, whisper_model_tag_t } from "@/app/lib/whisper";
type Language = {
code: string;
name: string;
};
type LanguageMatrix = {
[key: string]: Language;
};
const SettingsComponent: React.FC = () => {
const [hostLanguage, setHostLanguage] = useState<string | null>(null);
const [libretranslateBaseUrl, setLibretranslateBaseUrl] = useState<string | null>(null);
const [languages, setLanguages] = useState<undefined|LanguageMatrix>();
const [isLoaded, setIsLoaded] = useState<boolean>(false);
const [whisperModel, setWhisperModel] = useState<undefined|whisper_model_tag_t>()
const [downloadStatus, setDownloadStatus] = useState<undefined|download_status>();
useEffect(() => {
(async () => {
// Fetch the database connection
const db = await getDb();
const settings = new Settings(db);
// Get the current settings values
const hostLang = await settings.getHostLanguage();
const libretranslateUrl = await settings.getLibretranslateBaseUrl();
const langServer = new LanguageServer(libretranslateBaseUrl || LIBRETRANSLATE_BASE_URL);
const wModel = await settings.getWhisperModel()
// Fetch languages from API
const langData = await langServer.fetchLanguages();
setLanguages(langData);
setHostLanguage(hostLang || "en");
setLibretranslateBaseUrl(libretranslateUrl);
setWhisperModel(wModel);
setIsLoaded(true);
})();
// 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);
}, []);
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);
// Fetch the database connection
const db = await getDb();
const settings = new Settings(db);
// Save the updated setting value
await settings.setLibretranslateBaseUrl(value);
};
return (
isLoaded ? <View style={styles.container}>
<Text style={styles.label}>Host Language:</Text>
<Picker
selectedValue={hostLanguage || ""}
style={{ height: 50, width: "100%" }}
onValueChange={handleHostLanguageChange}
accessibilityHint="language"
>
{languages && Object.keys(languages).map((langCode) => (
<Picker.Item key={langCode} label={longLang(langCode)} value={langCode} />
))}
</Picker>
<Text style={styles.label}>LibreTranslate Base URL:</Text>
<TextInput
style={styles.input}
value={libretranslateBaseUrl || ""}
onChangeText={handleLibretranslateBaseUrlChange}
accessibilityHint="libretranslate base url"
/>
<Picker
selectedValue={whisperModel || ""}
style={{ height: 50, width: "100%" }}
onValueChange={setWhisperModel}
accessibilityHint="language"
>
{Object.entries(WHISPER_MODELS).map(([key, {label}]) => (
<Picker.Item key={key} label={label} value={key} />
))}
</Picker>
{whisperModel && (
<View>
{
downloadStatus?.status === "complete" ? (
<Pressable onPress={doReadownload}>
Re-Download
</Pressable>
) : (
downloadStatus?.status === "in_progress" ? (
<Text>
{downloadStatus.bytes.done / downloadStatus.bytes.total * 100.0} % complete
{ downloadStatus.bytes.done } bytes of { downloadStatus.bytes.total }
</Text>
) : (
<Pressable onPress={doDownload}>
Download
</Pressable>
)
)
}
</View>
)}
</View> : <View><Text>Loading ...</Text></View>
);
};
// Create styles for the component
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 20,
},
label: {
fontSize: 16,
marginBottom: 8,
},
input: {
height: 40,
borderColor: "gray",
borderWidth: 1,
marginBottom: 20,
paddingHorizontal: 8,
},
});
export default SettingsComponent;