Ezmary commited on
Commit
c990d50
·
verified ·
1 Parent(s): ec88f69

Update src/App.tsx

Browse files
Files changed (1) hide show
  1. src/App.tsx +22 -103
src/App.tsx CHANGED
@@ -10,8 +10,7 @@ import cn from "classnames";
10
  import { LiveConfig } from "./multimodal-live-types";
11
  import Logo from "./components/logo/Logo";
12
 
13
- const myCustomInstruction = `
14
- تو دستیار صوتی و تصویری پیشرفته از "اپلیکیشن هوش مصنوعی هوشان" هستی
15
  وظیفه اصلی تو کمک به کاربر است.
16
  همیشه و تحت هر شرایطی، فقط به زبان فارسی بسیار روان، دقیق و طبیعی و زیبا صحبت کن. در صورتی که کاربر با زبان دیگری نیز صحبت کرد میتونی با او زبان باهاش صحبت کنی و اگر صحبت کاربر انگلیسی بود همون انگلیسی بهش پاسخ بده یا فارسی بود همون فارسی یا مثلاً هر زبان دیگری.
17
  هرگز، به هیچ عنوان، خودت را به عنوان محصول ،open ai گوگل, مایکروسافت یا هر شرکت دیگری معرفی نکن. هویت تو تنها دستیار صوتی "اپلیکیشن هوش مصنوعی هوشان" است.
@@ -30,9 +29,7 @@ const myCustomInstruction = `
30
 
31
  const initialAppConfig: LiveConfig = {
32
  model: "models/gemini-2.0-flash-exp",
33
- systemInstruction: {
34
- parts: [{ text: myCustomInstruction }],
35
- },
36
  };
37
 
38
  interface AppInternalLogicProps {
@@ -49,20 +46,9 @@ interface AppInternalLogicProps {
49
  onFacingModeChange: (mode: 'user' | 'environment') => void;
50
  }
51
 
52
- const AppInternalLogic: React.FC<AppInternalLogicProps> = ({
53
- isMicActive,
54
- isCamActive,
55
- setIsMicActive,
56
- setIsCamActive,
57
- videoRef,
58
- notificationPopoverRef,
59
- notificationButtonRef,
60
- isNotificationOpen,
61
- setIsNotificationOpen,
62
- currentFacingMode,
63
- onFacingModeChange,
64
- }) => {
65
  const { connected, disconnect, volume } = useLiveAPIContext();
 
66
 
67
  useEffect(() => {
68
  if (!isMicActive && !isCamActive && connected) {
@@ -74,75 +60,32 @@ const AppInternalLogic: React.FC<AppInternalLogicProps> = ({
74
  <div className="w-full flex flex-col items-center justify-center min-h-screen text-foreground antialiased">
75
  <div className="main-wrapper max-w-3xl w-full flex flex-col items-center justify-center h-full relative">
76
  <div className="header-controls">
77
- <div />
78
  <div id="notification-trigger-container">
79
- <button
80
- ref={notificationButtonRef}
81
- id="notification-button"
82
- aria-label="Notifications"
83
- className="p-2 bg-transparent text-gray-600 dark:text-gray-300 hover:text-black dark:hover:text-white transition-colors"
84
- onClick={(e) => {
85
- e.stopPropagation();
86
- setIsNotificationOpen(!isNotificationOpen);
87
- }}
88
- >
89
  <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="8" x2="12" y2="12"></line><line x1="12" y1="16" x2="12.01" y2="16"></line></svg>
90
  </button>
91
  </div>
92
  </div>
93
-
94
  <div ref={notificationPopoverRef} id="notification-popover-wrapper" className="notification-popover-wrapper">
95
- <div
96
- id="notification-popover"
97
- className={cn("popover-content", {
98
- "open animate-popover-open-top-center": isNotificationOpen,
99
- "animate-popover-close-top-center": !isNotificationOpen && document.getElementById('notification-popover')?.classList.contains('open'),
100
- })}
101
- >
102
- <div className="notification-popover-text-content">
103
- مدل‌های هوش مصنوعی می‌توانند اشتباه کنند، صحت اطلاعات مهم را بررسی کنید و از بیان اطلاعات حساس بپرهیزید.
104
- </div>
105
  </div>
106
  </div>
107
-
108
  <div className="media-area w-full flex flex-col items-center justify-center flex-grow relative">
109
- <video
110
- id="video-feed"
111
- ref={videoRef}
112
- autoPlay
113
- playsInline
114
- className={cn(
115
- "absolute top-0 left-0 w-full h-full object-cover",
116
- { "hidden": !isCamActive },
117
- { "scale-x-[-1]": currentFacingMode === 'user' }
118
- )}
119
- />
120
  {isMicActive && !isCamActive && (
121
- <div
122
- id="large-logo-container"
123
- className="absolute top-0 left-0 w-full h-full flex items-center justify-center pointer-events-none"
124
- >
125
- <Logo
126
- isMini={false}
127
- isActive={true}
128
- isAi={false}
129
- speakingVolume={volume}
130
- />
131
  </div>
132
  )}
133
  </div>
134
-
135
- <ControlTray
136
- videoRef={videoRef}
137
- supportsVideo={true}
138
- onVideoStreamChange={(stream) => {}}
139
- isAppMicActive={isMicActive}
140
- onAppMicToggle={setIsMicActive}
141
- isAppCamActive={isCamActive}
142
- onAppCamToggle={setIsCamActive}
143
- currentFacingMode={currentFacingMode}
144
- onFacingModeChange={onFacingModeChange}
145
- />
146
  </div>
147
  </div>
148
  );
@@ -160,31 +103,19 @@ function App() {
160
  const notificationPopoverRef = useRef<HTMLDivElement>(null);
161
 
162
  useEffect(() => {
163
- if (isIOS()) {
164
- setShowIOSModal(true);
165
- }
166
- const timer = setTimeout(() => {
167
- setIsAllowedOrigin(true);
168
- }, 100);
169
  return () => clearTimeout(timer);
170
  }, []);
171
 
172
  useEffect(() => {
173
  const handleClickOutside = (event: MouseEvent) => {
174
- if (
175
- isNotificationOpen &&
176
- notificationPopoverRef.current &&
177
- !notificationPopoverRef.current.contains(event.target as Node) &&
178
- notificationButtonRef.current &&
179
- !notificationButtonRef.current.contains(event.target as Node)
180
- ) {
181
  setIsNotificationOpen(false);
182
  }
183
  };
184
  document.addEventListener("mousedown", handleClickOutside);
185
- return () => {
186
- document.removeEventListener("mousedown", handleClickOutside);
187
- };
188
  }, [isNotificationOpen]);
189
 
190
  if (isAllowedOrigin === null) {
@@ -193,19 +124,7 @@ function App() {
193
 
194
  return (
195
  <LiveAPIProvider initialConfig={initialAppConfig}>
196
- <AppInternalLogic
197
- isMicActive={isMicActive}
198
- setIsMicActive={setIsMicActive}
199
- isCamActive={isCamActive}
200
- setIsCamActive={setIsCamActive}
201
- videoRef={videoRef}
202
- notificationPopoverRef={notificationPopoverRef}
203
- notificationButtonRef={notificationButtonRef}
204
- isNotificationOpen={isNotificationOpen}
205
- setIsNotificationOpen={setIsNotificationOpen}
206
- currentFacingMode={currentFacingMode}
207
- onFacingModeChange={setCurrentFacingMode}
208
- />
209
  <IOSModal isOpen={showIOSModal} onClose={() => setShowIOSModal(false)} />
210
  </LiveAPIProvider>
211
  );
 
10
  import { LiveConfig } from "./multimodal-live-types";
11
  import Logo from "./components/logo/Logo";
12
 
13
+ const myCustomInstruction = `تو دستیار صوتی و تصویری پیشرفته از "اپلیکیشن هوش مصنوعی هوشان" هستی
 
14
  وظیفه اصلی تو کمک به کاربر است.
15
  همیشه و تحت هر شرایطی، فقط به زبان فارسی بسیار روان، دقیق و طبیعی و زیبا صحبت کن. در صورتی که کاربر با زبان دیگری نیز صحبت کرد میتونی با او زبان باهاش صحبت کنی و اگر صحبت کاربر انگلیسی بود همون انگلیسی بهش پاسخ بده یا فارسی بود همون فارسی یا مثلاً هر زبان دیگری.
16
  هرگز، به هیچ عنوان، خودت را به عنوان محصول ،open ai گوگل, مایکروسافت یا هر شرکت دیگری معرفی نکن. هویت تو تنها دستیار صوتی "اپلیکیشن هوش مصنوعی هوشان" است.
 
29
 
30
  const initialAppConfig: LiveConfig = {
31
  model: "models/gemini-2.0-flash-exp",
32
+ systemInstruction: { parts: [{ text: myCustomInstruction }] },
 
 
33
  };
34
 
35
  interface AppInternalLogicProps {
 
46
  onFacingModeChange: (mode: 'user' | 'environment') => void;
47
  }
48
 
49
+ const AppInternalLogic: React.FC<AppInternalLogicProps> = ({ isMicActive, isCamActive, setIsMicActive, setIsCamActive, videoRef, notificationPopoverRef, notificationButtonRef, isNotificationOpen, setIsNotificationOpen, currentFacingMode, onFacingModeChange }) => {
 
 
 
 
 
 
 
 
 
 
 
 
50
  const { connected, disconnect, volume } = useLiveAPIContext();
51
+ const [isUserSpeaking, setIsUserSpeaking] = useState(false);
52
 
53
  useEffect(() => {
54
  if (!isMicActive && !isCamActive && connected) {
 
60
  <div className="w-full flex flex-col items-center justify-center min-h-screen text-foreground antialiased">
61
  <div className="main-wrapper max-w-3xl w-full flex flex-col items-center justify-center h-full relative">
62
  <div className="header-controls">
63
+ <div />
64
  <div id="notification-trigger-container">
65
+ <button ref={notificationButtonRef} id="notification-button" aria-label="Notifications" className="p-2 bg-transparent text-gray-600 dark:text-gray-300 hover:text-black dark:hover:text-white transition-colors" onClick={(e) => { e.stopPropagation(); setIsNotificationOpen(!isNotificationOpen); }}>
 
 
 
 
 
 
 
 
 
66
  <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="8" x2="12" y2="12"></line><line x1="12" y1="16" x2="12.01" y2="16"></line></svg>
67
  </button>
68
  </div>
69
  </div>
 
70
  <div ref={notificationPopoverRef} id="notification-popover-wrapper" className="notification-popover-wrapper">
71
+ <div id="notification-popover" className={cn("popover-content", { "open animate-popover-open-top-center": isNotificationOpen, "animate-popover-close-top-center": !isNotificationOpen && document.getElementById('notification-popover')?.classList.contains('open'), })}>
72
+ <div className="notification-popover-text-content">مدل‌های هوش مصنوعی می‌توانند اشتباه کنند، صحت اطلاعات مهم را بررسی کنید و از بیان اطلاعات حساس بپرهیزید.</div>
 
 
 
 
 
 
 
 
73
  </div>
74
  </div>
 
75
  <div className="media-area w-full flex flex-col items-center justify-center flex-grow relative">
76
+ <video id="video-feed" ref={videoRef} autoPlay playsInline className={cn("absolute top-0 left-0 w-full h-full object-cover", { "hidden": !isCamActive }, { "scale-x-[-1]": currentFacingMode === 'user' })} />
 
 
 
 
 
 
 
 
 
 
77
  {isMicActive && !isCamActive && (
78
+ <div id="large-logo-container" className="absolute top-0 left-0 w-full h-full flex items-center justify-center pointer-events-none">
79
+ <Logo isMini={false} isActive={true} isAi={false} speakingVolume={volume} isUserSpeaking={isUserSpeaking} />
80
+ </div>
81
+ )}
82
+ {isCamActive && (
83
+ <div className="absolute bottom-24 right-4 z-20 pointer-events-none">
84
+ <Logo isMini={true} isActive={true} isAi={false} speakingVolume={volume} isUserSpeaking={isUserSpeaking} />
 
 
 
85
  </div>
86
  )}
87
  </div>
88
+ <ControlTray videoRef={videoRef} supportsVideo={true} onVideoStreamChange={(stream) => {}} isAppMicActive={isMicActive} onAppMicToggle={setIsMicActive} isAppCamActive={isCamActive} onAppCamToggle={setIsCamActive} currentFacingMode={currentFacingMode} onFacingModeChange={onFacingModeChange} onUserSpeakingChange={setIsUserSpeaking} />
 
 
 
 
 
 
 
 
 
 
 
89
  </div>
90
  </div>
91
  );
 
103
  const notificationPopoverRef = useRef<HTMLDivElement>(null);
104
 
105
  useEffect(() => {
106
+ if (isIOS()) setShowIOSModal(true);
107
+ const timer = setTimeout(() => { setIsAllowedOrigin(true); }, 100);
 
 
 
 
108
  return () => clearTimeout(timer);
109
  }, []);
110
 
111
  useEffect(() => {
112
  const handleClickOutside = (event: MouseEvent) => {
113
+ if (isNotificationOpen && notificationPopoverRef.current && !notificationPopoverRef.current.contains(event.target as Node) && notificationButtonRef.current && !notificationButtonRef.current.contains(event.target as Node)) {
 
 
 
 
 
 
114
  setIsNotificationOpen(false);
115
  }
116
  };
117
  document.addEventListener("mousedown", handleClickOutside);
118
+ return () => { document.removeEventListener("mousedown", handleClickOutside); };
 
 
119
  }, [isNotificationOpen]);
120
 
121
  if (isAllowedOrigin === null) {
 
124
 
125
  return (
126
  <LiveAPIProvider initialConfig={initialAppConfig}>
127
+ <AppInternalLogic isMicActive={isMicActive} setIsMicActive={setIsMicActive} isCamActive={isCamActive} setIsCamActive={setIsCamActive} videoRef={videoRef} notificationPopoverRef={notificationPopoverRef} notificationButtonRef={notificationButtonRef} isNotificationOpen={isNotificationOpen} setIsNotificationOpen={setIsNotificationOpen} currentFacingMode={currentFacingMode} onFacingModeChange={setCurrentFacingMode} />
 
 
 
 
 
 
 
 
 
 
 
 
128
  <IOSModal isOpen={showIOSModal} onClose={() => setShowIOSModal(false)} />
129
  </LiveAPIProvider>
130
  );