add whisper download utils. add react-navigator.
This commit is contained in:
@ -1,71 +1,71 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { ScrollView, Text, TouchableHighlight, View } from "react-native";
|
||||
import { useNavigation, Route } from "@react-navigation/native";
|
||||
import { Conversation, Message } from "@/app/lib/conversation";
|
||||
import MessageBubble from "@/components/ui/MessageBubble";
|
||||
import { WhisperContext } from "whisper.rn";
|
||||
import { NavigationProp, ParamListBase } from "@react-navigation/native";
|
||||
import {
|
||||
CachedTranslator,
|
||||
language_matrix_entry,
|
||||
Translator,
|
||||
} from "@/app/i18n/api";
|
||||
import { CachedTranslator, LanguageServer } from "@/app/i18n/api";
|
||||
import { getDb } from "@/app/lib/db";
|
||||
import LiveAudioStream from 'react-native-live-audio-stream';
|
||||
import LiveAudioStream from "react-native-live-audio-stream";
|
||||
|
||||
const lasOptions = {
|
||||
sampleRate: 32000, // default is 44100 but 32000 is adequate for accurate voice recognition
|
||||
channels: 1, // 1 or 2, default 1
|
||||
bitsPerSample: 16, // 8 or 16, default 16
|
||||
audioSource: 6, // android only (see below)
|
||||
bufferSize: 4096 // default is 2048
|
||||
sampleRate: 32000, // default is 44100 but 32000 is adequate for accurate voice recognition
|
||||
channels: 1, // 1 or 2, default 1
|
||||
bitsPerSample: 16, // 8 or 16, default 16
|
||||
audioSource: 6, // android only (see below)
|
||||
bufferSize: 4096, // default is 2048
|
||||
};
|
||||
// LiveAudioStream.init(lasOptions as any);
|
||||
|
||||
interface ConversationThreadProps {
|
||||
conversation: Conversation;
|
||||
whisperContext: WhisperContext;
|
||||
onGoBack?: () => any;
|
||||
}
|
||||
const ConversationThread = ({ route } : {route?: Route<"Conversation", {conversation : Conversation}>}) => {
|
||||
const navigation = useNavigation();
|
||||
|
||||
if (!route) {
|
||||
return (<View><Text>Missing Params!</Text></View>)
|
||||
}
|
||||
|
||||
/* 2. Get the param */
|
||||
const { conversation } = route?.params;
|
||||
|
||||
const ConversationThread = (p: ConversationThreadProps) => {
|
||||
const [messages, setMessages] = useState<Message[]>([]);
|
||||
const [guestSpeak, setGuestSpeak] = useState<string | undefined>();
|
||||
const [guestSpeakLoaded, setGuestSpeakLoaded] = useState<boolean>(false);
|
||||
const ct = new CachedTranslator("en", p.conversation.guest.language);
|
||||
const [cachedTranslator, setCachedTranslator] = useState<
|
||||
undefined | CachedTranslator
|
||||
>();
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
(async () => {
|
||||
setCachedTranslator(
|
||||
new CachedTranslator(
|
||||
"en",
|
||||
conversation.guest.language,
|
||||
await LanguageServer.getDefault()
|
||||
)
|
||||
);
|
||||
if (!cachedTranslator) throw new Error("cachedTranslator is undefined");
|
||||
setGuestSpeak(await cachedTranslator.translate("Speak"));
|
||||
})();
|
||||
const updateMessages = (c: Conversation) => {
|
||||
setMessages([...c]);
|
||||
};
|
||||
|
||||
p.conversation.onAddMessage = updateMessages;
|
||||
p.conversation.onTranslationDone = updateMessages;
|
||||
conversation.onAddMessage = updateMessages;
|
||||
conversation.onTranslationDone = updateMessages;
|
||||
|
||||
return () => {
|
||||
p.conversation.onAddMessage = undefined;
|
||||
p.conversation.onTranslationDone = undefined;
|
||||
conversation.onAddMessage = undefined;
|
||||
conversation.onTranslationDone = undefined;
|
||||
};
|
||||
}, [p.conversation, guestSpeak]);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchData = async () => {
|
||||
setGuestSpeak(await ct.translate("Speak"));
|
||||
}
|
||||
|
||||
fetchData();
|
||||
}, [guestSpeak])
|
||||
}, [conversation, guestSpeak]);
|
||||
|
||||
const renderMessages = () =>
|
||||
messages.map((message, index) => (
|
||||
<MessageBubble key={index} message={message} />
|
||||
));
|
||||
|
||||
function onGoBack() {
|
||||
p.onGoBack && p.onGoBack();
|
||||
}
|
||||
|
||||
return (
|
||||
return cachedTranslator ? (
|
||||
<View style={{ flex: 1, flexDirection: "column" }}>
|
||||
<ScrollView
|
||||
style={{
|
||||
@ -85,7 +85,7 @@ const ConversationThread = (p: ConversationThreadProps) => {
|
||||
</TouchableHighlight>
|
||||
<TouchableHighlight
|
||||
style={{ backgroundColor: "gray", padding: 3, borderRadius: 5 }}
|
||||
onPress={onGoBack}
|
||||
onPress={navigation.goBack}
|
||||
>
|
||||
<Text style={{ color: "white", fontSize: 30 }}>Go Back</Text>
|
||||
</TouchableHighlight>
|
||||
@ -98,6 +98,10 @@ const ConversationThread = (p: ConversationThreadProps) => {
|
||||
</TouchableHighlight>
|
||||
</View>
|
||||
</View>
|
||||
) : (
|
||||
<View>
|
||||
<Text>Loading...</Text>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -1,12 +1,13 @@
|
||||
// Import necessary packages
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { View, Text, TextInput, StyleSheet } from "react-native"; // Add Picker import
|
||||
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;
|
||||
@ -22,6 +23,8 @@ const SettingsComponent: React.FC = () => {
|
||||
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 () => {
|
||||
@ -33,16 +36,35 @@ const SettingsComponent: React.FC = () => {
|
||||
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);
|
||||
|
||||
@ -86,6 +108,38 @@ const SettingsComponent: React.FC = () => {
|
||||
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>
|
||||
);
|
||||
};
|
||||
|
Reference in New Issue
Block a user