Ezmary commited on
Commit
6db868f
·
verified ·
1 Parent(s): 0fd4af6

Create AppContext.tsx

Browse files
Files changed (1) hide show
  1. src/contexts/AppContext.tsx +92 -0
src/contexts/AppContext.tsx ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // src/contexts/AppContext.tsx
2
+ import React, { createContext, FC, ReactNode, useContext, useEffect, useState, useCallback } from "react";
3
+ import { useLiveAPI, type UseLiveAPIResults } from "../hooks/use-live-api";
4
+ import { LiveConfig } from "../multimodal-live-types";
5
+
6
+ const LS_SELECTED_PERSONALITY = 'app_selected_personality';
7
+ const LS_CUSTOM_NAME = 'app_custom_name';
8
+ const LS_CUSTOM_INSTRUCTIONS = 'app_custom_instructions';
9
+
10
+ export type PersonalityType = "default" | "teacher" | "poetic" | "funny" | "custom";
11
+ export type PersonalityInstructions = Partial<Record<PersonalityType, string>>;
12
+
13
+ interface AppContextType extends UseLiveAPIResults {
14
+ selectedPersonality: PersonalityType;
15
+ changePersonality: (personality: PersonalityType, customDetails?: { name: string, instructions: string }) => void;
16
+ personalityInstructions: PersonalityInstructions;
17
+ customUserName: string;
18
+ customInstructions: string;
19
+ isRestarting: boolean;
20
+ }
21
+
22
+ const AppContext = createContext<AppContextType | undefined>(undefined);
23
+
24
+ const BASE_INSTRUCTION = `تو یک دستیار صوتی و تصویری پیشرفته هستی. همیشه به زبان فارسی روان، دقیق و طبیعی صحبت کن. هرگز خودت را به عنوان محصول شرکت دیگری معرفی نکن. در پاسخ‌های خود از ایموجی یا شکلک استفاده نکن.`;
25
+
26
+ export const AppProvider: FC<{ children: ReactNode; initialConfig?: LiveConfig; personalityInstructions: PersonalityInstructions; url?: string; }> = ({
27
+ children, initialConfig, personalityInstructions, url
28
+ }) => {
29
+ const liveAPI = useLiveAPI({ url });
30
+
31
+ const [selectedPersonality, setSelectedPersonality] = useState<PersonalityType>(() => (localStorage.getItem(LS_SELECTED_PERSONALITY) as PersonalityType) || 'default');
32
+ const [customUserName, setCustomUserName] = useState<string>(() => localStorage.getItem(LS_CUSTOM_NAME) || '');
33
+ const [customInstructions, setCustomInstructions] = useState<string>(() => localStorage.getItem(LS_CUSTOM_INSTRUCTIONS) || '');
34
+ const [isRestarting, setIsRestarting] = useState(false);
35
+
36
+ useEffect(() => {
37
+ const personalityInstruction = personalityInstructions[selectedPersonality] || "";
38
+ const customDetail = selectedPersonality === 'custom' && customUserName ? `نام کاربر ${customUserName} است. او را با نامش صدا بزن.\n\n${customInstructions}` : "";
39
+
40
+ const finalInstruction = `${BASE_INSTRUCTION}\n\n${selectedPersonality === 'custom' ? customDetail : personalityInstruction}`;
41
+
42
+ const newConfig: LiveConfig = {
43
+ ...initialConfig,
44
+ tools: [{ googleSearch: {} }],
45
+ generationConfig: { responseModalities: "audio" },
46
+ systemInstruction: { parts: [{ text: finalInstruction.trim() }] },
47
+ };
48
+ liveAPI.setConfig(newConfig);
49
+ }, [selectedPersonality, customUserName, customInstructions, personalityInstructions, liveAPI.setConfig, initialConfig]);
50
+
51
+ useEffect(() => {
52
+ if (isRestarting && !liveAPI.connected) {
53
+ const timer = setTimeout(() => liveAPI.connect().then(() => setIsRestarting(false)), 200);
54
+ return () => clearTimeout(timer);
55
+ }
56
+ }, [isRestarting, liveAPI.connected, liveAPI.connect]);
57
+
58
+ const changePersonality = useCallback((newPersonality: PersonalityType, customDetails?: { name: string; instructions: string }) => {
59
+ if (newPersonality === 'custom' && customDetails) {
60
+ localStorage.setItem(LS_CUSTOM_NAME, customDetails.name);
61
+ localStorage.setItem(LS_CUSTOM_INSTRUCTIONS, customDetails.instructions);
62
+ setCustomUserName(customDetails.name);
63
+ setCustomInstructions(customDetails.instructions);
64
+ }
65
+
66
+ localStorage.setItem(LS_SELECTED_PERSONALITY, newPersonality);
67
+ setSelectedPersonality(newPersonality);
68
+
69
+ if (liveAPI.connected) {
70
+ setIsRestarting(true);
71
+ liveAPI.disconnect();
72
+ }
73
+ }, [liveAPI.connected, liveAPI.disconnect]);
74
+
75
+ const contextValue: AppContextType = {
76
+ ...liveAPI,
77
+ selectedPersonality,
78
+ changePersonality,
79
+ personalityInstructions,
80
+ customUserName,
81
+ customInstructions,
82
+ isRestarting,
83
+ };
84
+
85
+ return <AppContext.Provider value={contextValue}>{children}</AppContext.Provider>;
86
+ };
87
+
88
+ export const useAppContext = (): AppContextType => {
89
+ const context = useContext(AppContext);
90
+ if (!context) throw new Error("useAppContext must be used within an AppProvider");
91
+ return context;
92
+ };