TTs whisper
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import { Picker } from "@react-native-picker/picker";
|
||||
import { router } from "expo-router";
|
||||
import { useEffect, useState } from "react";
|
||||
import {
|
||||
@@ -16,11 +17,20 @@ import {
|
||||
loadRecorderSettings,
|
||||
saveRecorderSettings,
|
||||
} from "@/lib/recorder-settings";
|
||||
import { AVAILABLE_LOCALES, t, type Locale, getStrings } from "@/lib/translations";
|
||||
|
||||
function localeLabel(locale: Locale) {
|
||||
if (locale === "ca") return "Catal\u00e0";
|
||||
if (locale === "en") return "English";
|
||||
return locale;
|
||||
}
|
||||
|
||||
export default function SettingsScreen() {
|
||||
const [backendUrl, setBackendUrl] = useState("");
|
||||
const [authToken, setAuthToken] = useState("");
|
||||
const [fieldName, setFieldName] = useState("file");
|
||||
const [language, setLanguage] = useState<Locale>("ca");
|
||||
const [strings, setStrings] = useState(() => getStrings("ca"));
|
||||
|
||||
useEffect(() => {
|
||||
let isMounted = true;
|
||||
@@ -36,9 +46,11 @@ export default function SettingsScreen() {
|
||||
setBackendUrl(settings.backendUrl);
|
||||
setAuthToken(settings.authToken);
|
||||
setFieldName(settings.fieldName);
|
||||
setLanguage(settings.language);
|
||||
setStrings(getStrings(settings.language));
|
||||
} catch {
|
||||
if (isMounted) {
|
||||
Alert.alert("Settings error", "Could not load backend settings.");
|
||||
Alert.alert(strings.loadError, strings.loadError);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -50,19 +62,28 @@ export default function SettingsScreen() {
|
||||
};
|
||||
}, []);
|
||||
|
||||
const langStrings = getStrings(language);
|
||||
|
||||
async function handleSave() {
|
||||
try {
|
||||
await saveRecorderSettings({
|
||||
authToken,
|
||||
backendUrl,
|
||||
fieldName,
|
||||
language,
|
||||
});
|
||||
setStrings(getStrings(language));
|
||||
router.back();
|
||||
} catch {
|
||||
Alert.alert("Save failed", "Could not save backend settings.");
|
||||
Alert.alert(langStrings.saveError, langStrings.saveError);
|
||||
}
|
||||
}
|
||||
|
||||
function handleLanguageChange(val: Locale) {
|
||||
setLanguage(val);
|
||||
setStrings(getStrings(val));
|
||||
}
|
||||
|
||||
return (
|
||||
<SafeAreaView style={styles.safeArea}>
|
||||
<KeyboardAvoidingView
|
||||
@@ -76,54 +97,73 @@ export default function SettingsScreen() {
|
||||
>
|
||||
<View style={styles.headerRow}>
|
||||
<Pressable onPress={() => router.back()} style={styles.navButton}>
|
||||
<Text style={styles.navButtonText}>Back</Text>
|
||||
<Text style={styles.navButtonText}>{langStrings.back}</Text>
|
||||
</Pressable>
|
||||
<Text style={styles.title}>Settings</Text>
|
||||
<Text style={styles.title}>{langStrings.settingsTitle}</Text>
|
||||
<Pressable onPress={handleSave} style={styles.navButton}>
|
||||
<Text style={styles.navButtonText}>Save</Text>
|
||||
<Text style={styles.navButtonText}>{langStrings.save}</Text>
|
||||
</Pressable>
|
||||
</View>
|
||||
|
||||
<View style={styles.panel}>
|
||||
<Text style={styles.label}>Backend URL</Text>
|
||||
<Text style={styles.label}>{langStrings.backendUrl}</Text>
|
||||
<TextInput
|
||||
autoCapitalize="none"
|
||||
autoCorrect={false}
|
||||
keyboardType="url"
|
||||
onChangeText={setBackendUrl}
|
||||
placeholder="https://api.example.com/upload"
|
||||
placeholder={langStrings.urlPlaceholder}
|
||||
placeholderTextColor="#8f8a7c"
|
||||
style={styles.input}
|
||||
value={backendUrl}
|
||||
/>
|
||||
|
||||
<Text style={styles.label}>Bearer token</Text>
|
||||
<Text style={styles.label}>{langStrings.bearerToken}</Text>
|
||||
<TextInput
|
||||
autoCapitalize="none"
|
||||
autoCorrect={false}
|
||||
onChangeText={setAuthToken}
|
||||
placeholder="Optional"
|
||||
placeholder={langStrings.tokenOptional}
|
||||
placeholderTextColor="#8f8a7c"
|
||||
secureTextEntry
|
||||
style={styles.input}
|
||||
value={authToken}
|
||||
/>
|
||||
|
||||
<Text style={styles.label}>Form field name</Text>
|
||||
<Text style={styles.label}>{langStrings.formFieldName}</Text>
|
||||
<TextInput
|
||||
autoCapitalize="none"
|
||||
autoCorrect={false}
|
||||
onChangeText={setFieldName}
|
||||
placeholder="file"
|
||||
placeholder={langStrings.fieldNamePlaceholder}
|
||||
placeholderTextColor="#8f8a7c"
|
||||
style={styles.input}
|
||||
value={fieldName}
|
||||
/>
|
||||
|
||||
<Text style={styles.helperText}>
|
||||
The recording is uploaded as multipart field `{fieldName.trim() || "file"}`.
|
||||
{t("helperText", language, fieldName.trim() || "file")}
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
<View style={styles.panel}>
|
||||
<Text style={styles.label}>{langStrings.languageTitle}</Text>
|
||||
<View style={styles.pickerWrapper}>
|
||||
<Picker
|
||||
selectedValue={language}
|
||||
onValueChange={handleLanguageChange}
|
||||
style={styles.picker}
|
||||
>
|
||||
{AVAILABLE_LOCALES.map((loc) => (
|
||||
<Picker.Item
|
||||
key={loc}
|
||||
label={localeLabel(loc)}
|
||||
value={loc}
|
||||
/>
|
||||
))}
|
||||
</Picker>
|
||||
</View>
|
||||
</View>
|
||||
</ScrollView>
|
||||
</KeyboardAvoidingView>
|
||||
</SafeAreaView>
|
||||
@@ -199,4 +239,14 @@ const styles = StyleSheet.create({
|
||||
fontSize: 13,
|
||||
lineHeight: 18,
|
||||
},
|
||||
pickerWrapper: {
|
||||
backgroundColor: "#f7f0e0",
|
||||
borderColor: "#d9ccb5",
|
||||
borderRadius: 16,
|
||||
borderWidth: 1,
|
||||
overflow: "hidden",
|
||||
},
|
||||
picker: {
|
||||
height: 50,
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user