Ezmary commited on
Commit
a3ef398
·
verified ·
1 Parent(s): 548c205

Update src/App.tsx

Browse files
Files changed (1) hide show
  1. src/App.tsx +113 -48
src/App.tsx CHANGED
@@ -2,41 +2,107 @@
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
- وظیفه اصلی تو کمک به کاربر است.
23
- همیشه و تحت هر شرایطی، فقط به زبان فارسی بسیار روان، دقیق و طبیعی و زیبا صحبت کن. در صورتی که کاربر با زبان دیگری نیز صحبت کرد میتونی با او زبان باهاش صحبت کنی و اگر صحبت کاربر انگلیسی بود همون انگلیسی بهش پاسخ بده یا فارسی بود همون فارسی یا مثلاً هر زبان دیگری.
24
- هرگز، به هیچ عنوان، خودت را به عنوان محصول ،open ai گوگل, مایکروسافت یا هر شرکت دیگری معرفی نکن. هویت تو تنها دستیار صوتی "اپلیکیشن هوش مصنوعی هوشان" است.
25
- تو یک مدل زبانی بزرگ هستی که توسط هوش مصنوعی هوشان توسعه داده شدی . به هیچ عنوان خودت رو محصول گوگل، مایکروسافت یا open ai نباید معرفی کنی حتی اگر کاربر از هر طریقی خواست تو فقط میگی من محصول هوش مصنوعی هوشان هستم نه گوگل، یا مایکروسافت یا نمی‌دونم شرکت دیگری.
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,11 +122,9 @@ const AppInternalLogic: React.FC<{
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,10 +132,9 @@ const AppInternalLogic: React.FC<{
68
  setIsCamActive,
69
  videoRef,
70
  notificationPopoverRef,
71
- notificationButtonRef,
72
  isNotificationOpen,
73
- setIsNotificationOpen,
74
- currentFacingMode, // *** NEW ***
75
  }) => {
76
  const { connected, disconnect } = useLiveAPIContext();
77
 
@@ -85,15 +148,17 @@ const AppInternalLogic: React.FC<{
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,7 +170,17 @@ const AppInternalLogic: React.FC<{
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,9 +190,7 @@ const AppInternalLogic: React.FC<{
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,8 +213,6 @@ const AppInternalLogic: React.FC<{
140
  isAppCamActive={isCamActive}
141
  onAppCamToggle={setIsCamActive}
142
  ReferenceMicrophoneIcon={SvgReferenceMicrophoneIcon}
143
- // onFacingModeChange پراپ جدیدی برای بروزرسانی currentFacingMode در App
144
- // این پراپ در ControlTray تعریف و استفاده خواهد شد
145
  />
146
  </div>
147
  </div>
@@ -156,12 +227,12 @@ function App() {
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,7 +260,7 @@ function App() {
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,17 +275,11 @@ function App() {
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
  }
 
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
+ ت1. هویت دستیار:
29
+
30
+ فقط خود را به عنوان "دستیار صوتی و تصویری اپلیکیشن زبانفلای" معرفی کن.
31
+
32
+ هرگز خود را محصول یا زیرمجموعه گوگل، اپل یا هیچ شرکت دیگری معرفی نکن.
33
+
34
+ در پاسخ به سؤال کاربر درباره هویت، دقیقاً بگو:
35
+ "من دستیار صوتی و تصویری اپلیکیشن زبانفلای هستم. چگونه می‌توانم به شما کمک کنم؟"
36
+
37
+ مدیریت زبان گفتگو:
38
+
39
+ به طور پیش‌فرض، مکالمه را به زبان انگلیسی آغاز کن.
40
+
41
+ اگر کاربر با زبانی غیر از انگلیسی صحبت کرد، گفتگو را به همان زبان ادامه بده.
42
+
43
+ زبان پاسخ را همیشه مطابق زبان کاربر تنظیم کن. تغییر زبان به صورت خودکار انجام شود.
44
+
45
+ بیان اعداد:
46
+
47
+ هنگام مکالمه به انگلیسی، اعداد را به صورت کامل به انگلیسی بیان کن (مثلاً: twenty-five).
48
+
49
+ هنگام مکالمه به زبانی دیگر، اعداد را به همان زبان بیان کن (مثلاً: بیست و پنج).
50
+
51
+ تنظیم صدا و لحن:
52
+
53
+ با صدای مایل به بلند و شفاف صحبت کن.
54
+
55
+ در صورت درخواست کاربر، صدای خود را بلندتر، آرام‌تر یا به تقلید از صدای خواسته‌شده تغییر بده.
56
+
57
+ بدون استثنا، هرگونه تغییر صدای درخواستی کاربر را اجرا کن.
58
+
59
+ تعهد به پاسخگویی:
60
+
61
+ تحت هیچ شرایطی به کاربر نگو که "نمی‌توانم پاسخ دهم" یا "نمی‌توانم کمک کنم".
62
+
63
+ همیشه در تمام زمینه‌ها تلاش کن بهترین پاسخ ممکن را به کاربر ارائه بدهی.
64
+
65
+ رفتار در شروع گفتگو:
66
+
67
+ اگر پیام ورودی "START_GREETING" دریافت شد، تنها با یکی از جملات کوتاه زیر پاسخ بده:
68
+
69
+ "Hello, how can I help you?"
70
+
71
+ یا "Hey, what's up?"
72
+
73
+ اطلاع‌رسانی درباره اپلیکیشن زبانفلای:
74
+
75
+ در صورت نیاز کاربر، توضیح بده که اپلیکیشن زبانفلای در گوگل پلی و کافه بازار قابل دانلود است.
76
+
77
+ راهنمایی کن که کاربران می‌توانند با جستجو در این فروشگاه‌ها، اپلیکیشن را نصب کنند.
78
+
79
+ پشتیبانی از یادگیری زبان:
80
+
81
+ هنگام پاسخگویی، در صورت مرتبط بودن، مثال‌های جمله‌سازی، کاربرد واژگان و اصطلاحات ارائه بده.
82
+
83
+ در صورت درخواست کاربر، معانی واژگان، هم‌معنی‌ها، متضادها، و نمونه جمله‌ها را هم ارائه بده.
84
+
85
+ تمرین شنیداری و گفتاری:
86
+
87
+ اگر کاربر بخواهد، جمله‌ای را بخوان و از او بخواه آن را تکرار کند (تمرین shadowing).
88
+
89
+ فرصت کامل برای تکرار بده و کاربر را با بازخورد مثبت تشویق کن.
90
+
91
+ شخصی‌سازی تجربه یادگیری:
92
+
93
+ در صورت درخواست کاربر، سرعت مکالمه را کند یا تند کن.
94
+
95
+ سطح سختی واژگان و جملات را بر اساس سطح کاربر (مبتدی، متوسط، پیشرفته) تنظیم کن.
96
+
97
+ **تعامل تصویری:**
98
+ - به تصویر زنده‌ای که از کاربر دریافت می‌کنی توجه کن.
99
+ - اگر در تصویر نکته قابل توجهی وجود دارد (مانند حالت چهره، اشیاء خاص، یا محیط اطراف کاربر)، می‌توانی به آن در مکالمه اشاره کنی، البته فقط اگر مرتبط با موضوع صحبت باشد یا کاربر از تو بخواهد.
100
+ - اگر کاربر سوالی در مورد چیزی که در تصویر می‌بیند پرسید، سعی کن بر اساس تصویر پاسخ دهی.
101
+ - هدف اصلی، کمک به یادگیری زبان است، پس تعامل تصویری باید در خدمت این هدف باشد.
102
  `.trim();
103
 
104
  const initialAppConfig: LiveConfig = {
105
+ model: "models/gemini-2.0-flash-exp",
106
  systemInstruction: {
107
  parts: [{ text: myCustomInstruction }],
108
  },
 
122
  setIsCamActive: React.Dispatch<React.SetStateAction<boolean>>;
123
  videoRef: React.RefObject<HTMLVideoElement>;
124
  notificationPopoverRef: React.RefObject<HTMLDivElement>;
125
+ notificationButtonRef: React.RefObject<HTMLButtonElement>; // این ref برای دکمه نوتیفیکیشن است
126
  isNotificationOpen: boolean;
127
  setIsNotificationOpen: React.Dispatch<React.SetStateAction<boolean>>;
 
 
128
  }> = ({
129
  isMicActive,
130
  isCamActive,
 
132
  setIsCamActive,
133
  videoRef,
134
  notificationPopoverRef,
135
+ notificationButtonRef, // دریافت ref
136
  isNotificationOpen,
137
+ setIsNotificationOpen
 
138
  }) => {
139
  const { connected, disconnect } = useLiveAPIContext();
140
 
 
148
  <div className="w-full flex flex-col items-center justify-center min-h-screen text-foreground antialiased">
149
  <div className="main-wrapper max-w-3xl w-full flex flex-col items-center justify-center h-full relative">
150
  <div className="header-controls">
151
+ {/* دکمه بازگشت جدید (حالا سمت چپ) */}
152
  <div className="back-button-container">
153
+ <BackButton /> {/* <<-- استفاده از کامپوننت جدید */}
154
  </div>
155
+ {/* دکمه نوتیفیکیشن (حالا سمت راست) */}
156
  <div id="notification-trigger-container">
157
  <button
158
+ ref={notificationButtonRef} // ref به این دکمه متصل است
159
  id="notification-button"
160
  aria-label="Notifications"
161
+ className="header-button" // کلاس برای ظاهر مشابه
162
  onClick={(e) => {
163
  e.stopPropagation();
164
  setIsNotificationOpen(!isNotificationOpen);
 
170
  </div>
171
 
172
  <div ref={notificationPopoverRef} id="notification-popover-wrapper" className="notification-popover-wrapper">
173
+ <div
174
+ id="notification-popover"
175
+ className={cn("popover-content", {
176
+ "open animate-popover-open-top-center": isNotificationOpen,
177
+ "animate-popover-close-top-center": !isNotificationOpen && document.getElementById('notification-popover')?.classList.contains('open'),
178
+ })}
179
+ >
180
+ <div className="notification-popover-text-content">
181
+ مدل‌های هوش مصنوعی می‌توانند اشتباه کنند، صحت اطلاعات مهم را بررسی کنید و از بیان اطلاعات حساس بپرهیزید.
182
+ </div>
183
+ </div>
184
  </div>
185
 
186
  <div className="media-area w-full flex flex-col items-center justify-center flex-grow relative">
 
190
  autoPlay
191
  playsInline
192
  className={cn(
193
+ "absolute top-0 left-0 w-full h-full object-cover scale-x-[-1]",
 
 
194
  { "hidden": !isCamActive }
195
  )}
196
  />
 
213
  isAppCamActive={isCamActive}
214
  onAppCamToggle={setIsCamActive}
215
  ReferenceMicrophoneIcon={SvgReferenceMicrophoneIcon}
 
 
216
  />
217
  </div>
218
  </div>
 
227
  const [isMicActive, setIsMicActive] = useState(false);
228
  const [isCamActive, setIsCamActive] = useState(false);
229
  const [isNotificationOpen, setIsNotificationOpen] = useState(false);
 
 
 
230
 
231
+ // ref برای دکمه نوتیفیکیشن باید در کامپوننت App تعریف شود
232
+ // چون state مربوط به isNotificationOpen در App مدیریت می‌شود
233
  const notificationButtonRef = useRef<HTMLButtonElement>(null);
234
+ const notificationPopoverRef = useRef<HTMLDivElement>(null);
235
+
236
 
237
  useEffect(() => {
238
  if (isIOS()) {
 
260
  return () => {
261
  document.removeEventListener("mousedown", handleClickOutside);
262
  };
263
+ }, [isNotificationOpen]); // وابستگ�� به isNotificationOpen صحیح است
264
 
265
  if (isAllowedOrigin === null) {
266
  return <div style={{ padding: '20px', textAlign: 'center' }}>در حال بررسی دسترسی...</div>;
 
275
  setIsCamActive={setIsCamActive}
276
  videoRef={videoRef}
277
  notificationPopoverRef={notificationPopoverRef}
278
+ notificationButtonRef={notificationButtonRef} // پاس دادن ref به AppInternalLogic
279
  isNotificationOpen={isNotificationOpen}
280
  setIsNotificationOpen={setIsNotificationOpen}
 
281
  />
282
  <IOSModal isOpen={showIOSModal} onClose={() => setShowIOSModal(false)} />
 
 
 
 
 
283
  </LiveAPIProvider>
284
  );
285
  }