Ezmary commited on
Commit
4a7391c
·
verified ·
1 Parent(s): 267a58a

Update src/App.tsx

Browse files
Files changed (1) hide show
  1. src/App.tsx +37 -43
src/App.tsx CHANGED
@@ -2,28 +2,21 @@
2
 
3
  /**
4
  Copyright 2024 Google LLC
5
- Licensed under the Apache License, Version 2.0 (the "License");
6
- you may not use this file except in compliance with the License.
7
- You may obtain a copy of the License at
8
- http://www.apache.org/licenses/LICENSE-2.0
9
- Unless required by applicable law or agreed to in writing, software
10
- distributed under the License is distributed on an "AS IS" BASIS,
11
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- See the License for the specific language governing permissions and
13
- limitations under the License.
14
  */
15
 
16
  import React, { useEffect, useRef, useState } from "react";
17
- import './App.scss'; // استایل‌های اصلی
18
  import { LiveAPIProvider, useLiveAPIContext } from "./contexts/LiveAPIContext";
19
- import ControlTray from "./components/control-tray/ControlTray";
20
  import { IOSModal } from "./components/ios-modal/IOSModal";
21
  import { isIOS } from "./lib/platform";
22
  import cn from "classnames";
23
  import { LiveConfig } from "./multimodal-live-types";
24
  import LogoAnimation from "./components/logo-animation/LogoAnimation";
25
- import BackButton from "./components/back-button/BackButton"; // <<-- ایمپورت کامپوننت جدید دکمه بازگشت
26
 
 
27
  const myCustomInstruction = `
28
  تو دستیار صوتی و تصویری پیشرفته از "اپلیکیشن هوش مصنوعی هوشان" هستی
29
  وظیفه اصلی تو کمک به کاربر است.
@@ -33,17 +26,17 @@ const myCustomInstruction = `
33
  تو به تمام سوالات باید پاسخ دهی و در هر زمینه ای نباید به هیچ عنوان به هر پاسخ کاربر بگویی که من نمیتوانم این کار را انجام دهم یا نمیتوانم به شما کمک کنم
34
  هوش مصنوعی هوشانیک برنامه ای است که داخل گوشی موبایل نصب میشه و در کافه بازار در دسترس است و با جستجو در کافه بازار یا مایکت امکان دانلود هوش مصنوعی هوشان وجود دارد
35
  ......
36
- اگر کاربر خواست با صدای بلند تر صحبت کنی باید به درخواست کاربر حتما پاسخ بدهی، اگر کاربر خواست صدای متفاوت یا صدای هر چیزی یا صدای تقلید کنی باید درخواست کاربر اجرا کنی حتما، اگر کاربر خواست آروم صحبت کنی باید درخواست کاربر اجرا کنی، در هر شرایط باید درخواست کاربر اجرا بشه
37
  ....
38
  در تمام پاسخ‌ها، اعداد را نیز کاملاً به فارسی بیان کن مگر اینکه در حال صحبت به زبان دیگری غیر از فارسی با کاربر بودی به همون زبان اعداد بگو، و همچنین اعداد به فارسی درست بگو این حالت (مثلاً بگو 'ده' یا 'بیست و پنج'، نه '10' یا 'twenty-five').
39
  وقتی کاربر در مورد هویت تو می‌پرسد، خودت را اینگونه معرفی کن: "من دستیار صوتی و تصویری از برنامه هوش مصنوعی هوشان هستم. چگونه می‌توانم به شما کمک کنم؟"
40
- مهم: هنگامی که پیام ورودی فقط شامل متن "START_GREETING" بود، *فقط* با یک خوشامدگویی کوتاه و دوستانه به فارسی پاسخ بده، مانند "سلام، چطور می‌تونم کمکتون کنم؟" یا "سلام حالتون چطوره!
41
- هشدار: به هیچ عنوان در هنگام مکالمه و پیام دادن به کاربر نباید شکلک بفرستی و یا بیان کنی شکلک و یا اموجی هارو حتی شکلک هارو نیاز نیست بگی اسم شونو در هنگام صحبت اگر شکلک نیاز بود بود بگی نباید اسم شکلک بگی
42
- **مهم: به هیچ عنوان در پاسخ‌های خود از ایموجی استفاده نکن.**
43
  `.trim();
44
 
45
  const initialAppConfig: LiveConfig = {
46
- model: "models/gemini-2.0-flash-exp",
47
  systemInstruction: {
48
  parts: [{ text: myCustomInstruction }],
49
  },
@@ -63,9 +56,11 @@ const AppInternalLogic: React.FC<{
63
  setIsCamActive: React.Dispatch<React.SetStateAction<boolean>>;
64
  videoRef: React.RefObject<HTMLVideoElement>;
65
  notificationPopoverRef: React.RefObject<HTMLDivElement>;
66
- notificationButtonRef: React.RefObject<HTMLButtonElement>; // این ref برای دکمه نوتیفیکیشن است
67
  isNotificationOpen: boolean;
68
  setIsNotificationOpen: React.Dispatch<React.SetStateAction<boolean>>;
 
 
69
  }> = ({
70
  isMicActive,
71
  isCamActive,
@@ -73,9 +68,10 @@ const AppInternalLogic: React.FC<{
73
  setIsCamActive,
74
  videoRef,
75
  notificationPopoverRef,
76
- notificationButtonRef, // دریافت ref
77
  isNotificationOpen,
78
- setIsNotificationOpen
 
79
  }) => {
80
  const { connected, disconnect } = useLiveAPIContext();
81
 
@@ -89,17 +85,15 @@ const AppInternalLogic: React.FC<{
89
  <div className="w-full flex flex-col items-center justify-center min-h-screen text-foreground antialiased">
90
  <div className="main-wrapper max-w-3xl w-full flex flex-col items-center justify-center h-full relative">
91
  <div className="header-controls">
92
- {/* دکمه بازگشت جدید (حالا سمت چپ) */}
93
  <div className="back-button-container">
94
- <BackButton /> {/* <<-- استفاده از کامپوننت جدید */}
95
  </div>
96
- {/* دکمه نوتیفیکیشن (حالا سمت راست) */}
97
  <div id="notification-trigger-container">
98
  <button
99
- ref={notificationButtonRef} // ref به این دکمه متصل است
100
  id="notification-button"
101
  aria-label="Notifications"
102
- className="header-button" // کلاس برای ظاهر مشابه
103
  onClick={(e) => {
104
  e.stopPropagation();
105
  setIsNotificationOpen(!isNotificationOpen);
@@ -111,17 +105,7 @@ const AppInternalLogic: React.FC<{
111
  </div>
112
 
113
  <div ref={notificationPopoverRef} id="notification-popover-wrapper" className="notification-popover-wrapper">
114
- <div
115
- id="notification-popover"
116
- className={cn("popover-content", {
117
- "open animate-popover-open-top-center": isNotificationOpen,
118
- "animate-popover-close-top-center": !isNotificationOpen && document.getElementById('notification-popover')?.classList.contains('open'),
119
- })}
120
- >
121
- <div className="notification-popover-text-content">
122
- مدل‌های هوش مصنوعی می‌توانند اشتباه کنند، صحت اطلاعات مهم را بررسی کنید و از بیان اطلاعات حساس بپرهیزید.
123
- </div>
124
- </div>
125
  </div>
126
 
127
  <div className="media-area w-full flex flex-col items-center justify-center flex-grow relative">
@@ -131,7 +115,9 @@ const AppInternalLogic: React.FC<{
131
  autoPlay
132
  playsInline
133
  className={cn(
134
- "absolute top-0 left-0 w-full h-full object-cover scale-x-[-1]",
 
 
135
  { "hidden": !isCamActive }
136
  )}
137
  />
@@ -154,6 +140,8 @@ const AppInternalLogic: React.FC<{
154
  isAppCamActive={isCamActive}
155
  onAppCamToggle={setIsCamActive}
156
  ReferenceMicrophoneIcon={SvgReferenceMicrophoneIcon}
 
 
157
  />
158
  </div>
159
  </div>
@@ -168,12 +156,12 @@ function App() {
168
  const [isMicActive, setIsMicActive] = useState(false);
169
  const [isCamActive, setIsCamActive] = useState(false);
170
  const [isNotificationOpen, setIsNotificationOpen] = useState(false);
 
 
171
 
172
- // ref برای دکمه نوتیفیکیشن باید در کامپوننت App تعریف شود
173
- // چون state مربوط به isNotificationOpen در App مدیریت می‌شود
174
- const notificationButtonRef = useRef<HTMLButtonElement>(null);
175
- const notificationPopoverRef = useRef<HTMLDivElement>(null);
176
 
 
 
177
 
178
  useEffect(() => {
179
  if (isIOS()) {
@@ -201,7 +189,7 @@ function App() {
201
  return () => {
202
  document.removeEventListener("mousedown", handleClickOutside);
203
  };
204
- }, [isNotificationOpen]); // وابستگی به isNotificationOpen صحیح است
205
 
206
  if (isAllowedOrigin === null) {
207
  return <div style={{ padding: '20px', textAlign: 'center' }}>در حال بررسی دسترسی...</div>;
@@ -216,11 +204,17 @@ function App() {
216
  setIsCamActive={setIsCamActive}
217
  videoRef={videoRef}
218
  notificationPopoverRef={notificationPopoverRef}
219
- notificationButtonRef={notificationButtonRef} // پاس دادن ref به AppInternalLogic
220
  isNotificationOpen={isNotificationOpen}
221
  setIsNotificationOpen={setIsNotificationOpen}
 
222
  />
223
  <IOSModal isOpen={showIOSModal} onClose={() => setShowIOSModal(false)} />
 
 
 
 
 
224
  </LiveAPIProvider>
225
  );
226
  }
 
2
 
3
  /**
4
  Copyright 2024 Google LLC
5
+ ... (لایسنس) ...
 
 
 
 
 
 
 
 
6
  */
7
 
8
  import React, { useEffect, useRef, useState } from "react";
9
+ import './App.scss';
10
  import { LiveAPIProvider, useLiveAPIContext } from "./contexts/LiveAPIContext";
11
+ import ControlTray, { FacingMode } from "./components/control-tray/ControlTray"; // FacingMode را ایمپورت می‌کنیم
12
  import { IOSModal } from "./components/ios-modal/IOSModal";
13
  import { isIOS } from "./lib/platform";
14
  import cn from "classnames";
15
  import { LiveConfig } from "./multimodal-live-types";
16
  import LogoAnimation from "./components/logo-animation/LogoAnimation";
17
+ import BackButton from "./components/back-button/BackButton";
18
 
19
+ // *** MODIFIED: دستورالعمل جدید ربات ***
20
  const myCustomInstruction = `
21
  تو دستیار صوتی و تصویری پیشرفته از "اپلیکیشن هوش مصنوعی هوشان" هستی
22
  وظیفه اصلی تو کمک به کاربر است.
 
26
  تو به تمام سوالات باید پاسخ دهی و در هر زمینه ای نباید به هیچ عنوان به هر پاسخ کاربر بگویی که من نمیتوانم این کار را انجام دهم یا نمیتوانم به شما کمک کنم
27
  هوش مصنوعی هوشانیک برنامه ای است که داخل گوشی موبایل نصب میشه و در کافه بازار در دسترس است و با جستجو در کافه بازار یا مایکت امکان دانلود هوش مصنوعی هوشان وجود دارد
28
  ......
29
+ اگر کاربر خواست با صدای بلند تر صحبت کنی باید به درخواست کاربر حتما پاسخ بدهی، اگر کاربر خواست صدای متفاوت یا صدای هر چیزی یا صدای تقلید کنی باید درخواست کاربر اجرا کنی حتما، اگر کاربر خواست آروم صحبت کنی باید درخواست کاربر اجرا کنی، در هر شرایط باید درخواست کاربر اجرا بشه
30
  ....
31
  در تمام پاسخ‌ها، اعداد را نیز کاملاً به فارسی بیان کن مگر اینکه در حال صحبت به زبان دیگری غیر از فارسی با کاربر بودی به همون زبان اعداد بگو، و همچنین اعداد به فارسی درست بگو این حالت (مثلاً بگو 'ده' یا 'بیست و پنج'، نه '10' یا 'twenty-five').
32
  وقتی کاربر در مورد هویت تو می‌پرسد، خودت را اینگونه معرفی کن: "من دستیار صوتی و تصویری از برنامه هوش مصنوعی هوشان هستم. چگونه می‌توانم به شما کمک کنم؟"
33
+ مهم: هنگامی که پیام ورودی فقط شامل متن "START_GREETING" بود، فقط با یک خوشامدگویی کوتاه و دوستانه به فارسی پاسخ بده، مانند "سلام، چطور می‌تونم کمکتون کنم؟" یا "سلام حالتون چطوره!"
34
+ هشدار: به هیچ عنوان در هنگام مکالمه و پیام دادن به کاربر نباید شکلک بفرستی و یا بیان کنی شکلک و یا اموجی هارو حتی شکلک هارو نیاز نیست بگی اسم شونو در هنگام صحبت اگر شکلک نیاز بود بود بگی نباید اسم شکلک بگی
35
+ مهم: به هیچ عنوان در پاسخ‌های خود از ایموجی استفاده نکن.
36
  `.trim();
37
 
38
  const initialAppConfig: LiveConfig = {
39
+ model: "models/gemini-2.0-flash-exp", // یا مدل مناسب دیگر
40
  systemInstruction: {
41
  parts: [{ text: myCustomInstruction }],
42
  },
 
56
  setIsCamActive: React.Dispatch<React.SetStateAction<boolean>>;
57
  videoRef: React.RefObject<HTMLVideoElement>;
58
  notificationPopoverRef: React.RefObject<HTMLDivElement>;
59
+ notificationButtonRef: React.RefObject<HTMLButtonElement>;
60
  isNotificationOpen: boolean;
61
  setIsNotificationOpen: React.Dispatch<React.SetStateAction<boolean>>;
62
+ // *** NEW: پراپ برای دریافت جهت دوربین ***
63
+ currentFacingMode: FacingMode;
64
  }> = ({
65
  isMicActive,
66
  isCamActive,
 
68
  setIsCamActive,
69
  videoRef,
70
  notificationPopoverRef,
71
+ notificationButtonRef,
72
  isNotificationOpen,
73
+ setIsNotificationOpen,
74
+ currentFacingMode, // *** NEW ***
75
  }) => {
76
  const { connected, disconnect } = useLiveAPIContext();
77
 
 
85
  <div className="w-full flex flex-col items-center justify-center min-h-screen text-foreground antialiased">
86
  <div className="main-wrapper max-w-3xl w-full flex flex-col items-center justify-center h-full relative">
87
  <div className="header-controls">
 
88
  <div className="back-button-container">
89
+ <BackButton />
90
  </div>
 
91
  <div id="notification-trigger-container">
92
  <button
93
+ ref={notificationButtonRef}
94
  id="notification-button"
95
  aria-label="Notifications"
96
+ className="header-button"
97
  onClick={(e) => {
98
  e.stopPropagation();
99
  setIsNotificationOpen(!isNotificationOpen);
 
105
  </div>
106
 
107
  <div ref={notificationPopoverRef} id="notification-popover-wrapper" className="notification-popover-wrapper">
108
+ {/* ... (محتوای پاپ‌اور) ... */}
 
 
 
 
 
 
 
 
 
 
109
  </div>
110
 
111
  <div className="media-area w-full flex flex-col items-center justify-center flex-grow relative">
 
115
  autoPlay
116
  playsInline
117
  className={cn(
118
+ "absolute top-0 left-0 w-full h-full object-cover",
119
+ // *** MODIFIED: اعمال scaleX(-1) فقط برای دوربین جلو (user) ***
120
+ { "scale-x-[-1]": currentFacingMode === 'user' },
121
  { "hidden": !isCamActive }
122
  )}
123
  />
 
140
  isAppCamActive={isCamActive}
141
  onAppCamToggle={setIsCamActive}
142
  ReferenceMicrophoneIcon={SvgReferenceMicrophoneIcon}
143
+ // onFacingModeChange پراپ جدیدی برای بروزرسانی currentFacingMode در App
144
+ // این پراپ در ControlTray تعریف و استفاده خواهد شد
145
  />
146
  </div>
147
  </div>
 
156
  const [isMicActive, setIsMicActive] = useState(false);
157
  const [isCamActive, setIsCamActive] = useState(false);
158
  const [isNotificationOpen, setIsNotificationOpen] = useState(false);
159
+ // *** NEW: State برای نگهداری جهت فعلی دوربین ***
160
+ const [currentFacingMode, setCurrentFacingMode] = useState<FacingMode>('user');
161
 
 
 
 
 
162
 
163
+ const notificationPopoverRef = useRef<HTMLDivElement>(null);
164
+ const notificationButtonRef = useRef<HTMLButtonElement>(null);
165
 
166
  useEffect(() => {
167
  if (isIOS()) {
 
189
  return () => {
190
  document.removeEventListener("mousedown", handleClickOutside);
191
  };
192
+ }, [isNotificationOpen]);
193
 
194
  if (isAllowedOrigin === null) {
195
  return <div style={{ padding: '20px', textAlign: 'center' }}>در حال بررسی دسترسی...</div>;
 
204
  setIsCamActive={setIsCamActive}
205
  videoRef={videoRef}
206
  notificationPopoverRef={notificationPopoverRef}
207
+ notificationButtonRef={notificationButtonRef}
208
  isNotificationOpen={isNotificationOpen}
209
  setIsNotificationOpen={setIsNotificationOpen}
210
+ currentFacingMode={currentFacingMode} // *** NEW: پاس دادن جهت دوربین ***
211
  />
212
  <IOSModal isOpen={showIOSModal} onClose={() => setShowIOSModal(false)} />
213
+ {/* ControlTray دیگر اینجا نیست، داخل AppInternalLogic است */}
214
+ {/* اما باید state currentFacingMode را از ControlTray دریافت کنیم */}
215
+ {/* این کار با پاس دادن یک تابع callback به ControlTray انجام می‌شود */}
216
+ {/* که در App.tsx تعریف و در ControlTray فراخوانی می‌شود */}
217
+ {/* (این بخش در اصلاحیه ControlTray انجام خواهد شد) */}
218
  </LiveAPIProvider>
219
  );
220
  }