Spaces:
Running
Running
Update src/App.tsx
Browse files- src/App.tsx +17 -28
src/App.tsx
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
-
// src/App.tsx (نسخه نهایی
|
2 |
import React, { useEffect, useRef, useState, FC } from "react";
|
3 |
import './App.scss';
|
4 |
import { AppProvider, useAppContext, PersonalityType, PersonalityInstructions } from "./contexts/AppContext";
|
@@ -9,7 +9,7 @@ import cn from "classnames";
|
|
9 |
import Logo from "./components/logo/Logo";
|
10 |
import { LiveConfig } from "./multimodal-live-types";
|
11 |
|
12 |
-
// کامپوننت مودال
|
13 |
interface CustomModalProps {
|
14 |
isOpen: boolean;
|
15 |
onClose: () => void;
|
@@ -21,22 +21,27 @@ const CustomModal: FC<CustomModalProps> = ({ isOpen, onClose, onSave, initialNam
|
|
21 |
const [name, setName] = useState(initialName);
|
22 |
const [instructions, setInstructions] = useState(initialInstructions);
|
23 |
useEffect(() => {
|
24 |
-
if (isOpen) {
|
|
|
|
|
|
|
25 |
}, [isOpen, initialName, initialInstructions]);
|
26 |
if (!isOpen) return null;
|
27 |
const handleSave = () => {
|
28 |
-
if (name.trim() && instructions.trim()) {
|
29 |
-
|
|
|
|
|
30 |
};
|
31 |
return (
|
32 |
<div className="modal-overlay" onClick={onClose}>
|
33 |
<div className="modal-content" onClick={(e) => e.stopPropagation()}>
|
34 |
<div className="modal-header"><h3>ساخت شخصیت اختصاصی</h3><button className="close-button" onClick={onClose}>×</button></div>
|
35 |
<div className="modal-body">
|
36 |
-
<div className="form-group"><label htmlFor="name">نام
|
37 |
-
<div className="form-group"><label htmlFor="instructions"
|
38 |
</div>
|
39 |
-
<div className="modal-footer"><button className="save-button" onClick={handleSave}
|
40 |
</div>
|
41 |
</div>
|
42 |
);
|
@@ -88,7 +93,7 @@ const AppInternal: React.FC = () => {
|
|
88 |
};
|
89 |
return (
|
90 |
<>
|
91 |
-
<div className="main-wrapper">
|
92 |
<div className="header-controls">
|
93 |
<button aria-label="انتخاب شخصیت" className="header-icon-button" onClick={() => setIsPersonalityMenuOpen(v => !v)}>
|
94 |
<span className="material-symbols-outlined">psychology</span>
|
@@ -100,28 +105,12 @@ const AppInternal: React.FC = () => {
|
|
100 |
{isNotificationOpen && <div className="notification-popover-wrapper open"><div className="popover-content">مدلهای هوش مصنوعی میتوانند اشتباه کنند.</div></div>}
|
101 |
<PersonalityMenu isOpen={isPersonalityMenuOpen} onClose={() => setIsPersonalityMenuOpen(false)} onSelect={handleSelectPersonality} />
|
102 |
|
103 |
-
<div className="media-area">
|
104 |
-
<video
|
105 |
-
id="video-feed"
|
106 |
-
ref={videoRef}
|
107 |
-
autoPlay
|
108 |
-
playsInline
|
109 |
-
className={cn('absolute top-0 left-0 w-full h-full object-cover', { hidden: !isCamActive }, { "scale-x-[-1]": currentFacingMode === 'user' })}
|
110 |
-
/>
|
111 |
{isMicActive && !isCamActive && <div id="large-logo-container"><Logo isMini={false} isActive={true} isAi={false} speakingVolume={volume} isUserSpeaking={isUserSpeaking} /></div>}
|
112 |
</div>
|
113 |
|
114 |
-
{
|
115 |
-
<ControlTray
|
116 |
-
videoRef={videoRef}
|
117 |
-
onUserSpeakingChange={setIsUserSpeaking}
|
118 |
-
isAppMicActive={isMicActive}
|
119 |
-
onAppMicToggle={setIsMicActive}
|
120 |
-
isAppCamActive={isCamActive} /* <-- متغیر صحیح پاس داده شد */
|
121 |
-
onAppCamToggle={setIsCamActive}
|
122 |
-
currentFacingMode={currentFacingMode}
|
123 |
-
onFacingModeChange={setCurrentFacingMode}
|
124 |
-
/>
|
125 |
</div>
|
126 |
<CustomModal isOpen={isCustomModalOpen} onClose={() => setIsCustomModalOpen(false)} onSave={(name, instructions) => changePersonality('custom', { name, instructions })} initialName={customUserName} initialInstructions={customInstructions} />
|
127 |
</>
|
|
|
1 |
+
// src/App.tsx (نسخه نهایی و تصحیح شده برای رفع مشکل ظاهری)
|
2 |
import React, { useEffect, useRef, useState, FC } from "react";
|
3 |
import './App.scss';
|
4 |
import { AppProvider, useAppContext, PersonalityType, PersonalityInstructions } from "./contexts/AppContext";
|
|
|
9 |
import Logo from "./components/logo/Logo";
|
10 |
import { LiveConfig } from "./multimodal-live-types";
|
11 |
|
12 |
+
// کامپوننت مودال (که قبلاً در فایل جدا بود، برای سادگی اینجا قرار گرفته)
|
13 |
interface CustomModalProps {
|
14 |
isOpen: boolean;
|
15 |
onClose: () => void;
|
|
|
21 |
const [name, setName] = useState(initialName);
|
22 |
const [instructions, setInstructions] = useState(initialInstructions);
|
23 |
useEffect(() => {
|
24 |
+
if (isOpen) {
|
25 |
+
setName(initialName);
|
26 |
+
setInstructions(initialInstructions);
|
27 |
+
}
|
28 |
}, [isOpen, initialName, initialInstructions]);
|
29 |
if (!isOpen) return null;
|
30 |
const handleSave = () => {
|
31 |
+
if (name.trim() && instructions.trim()) {
|
32 |
+
onSave(name.trim(), instructions.trim());
|
33 |
+
onClose();
|
34 |
+
} else { alert("لطفا نام و دستورالعملها را وارد کنید."); }
|
35 |
};
|
36 |
return (
|
37 |
<div className="modal-overlay" onClick={onClose}>
|
38 |
<div className="modal-content" onClick={(e) => e.stopPropagation()}>
|
39 |
<div className="modal-header"><h3>ساخت شخصیت اختصاصی</h3><button className="close-button" onClick={onClose}>×</button></div>
|
40 |
<div className="modal-body">
|
41 |
+
<div className="form-group"><label htmlFor="name">نام شما (برای صدا زدن)</label><input id="name" type="text" placeholder="مثلا: علی" value={name} onChange={(e) => setName(e.target.value)} /></div>
|
42 |
+
<div className="form-group"><label htmlFor="instructions">دستورالعملهای شخصیت</label><textarea id="instructions" placeholder="مثلا: خیلی خودمونی و بامزه صحبت کن..." value={instructions} onChange={(e) => setInstructions(e.target.value)} rows={6} /><small>اینجا فقط رفتار و سبک صحبت کردن دستیار را مشخص کنید.</small></div>
|
43 |
</div>
|
44 |
+
<div className="modal-footer"><button className="save-button" onClick={handleSave}>ذخیره و فعالسازی</button></div>
|
45 |
</div>
|
46 |
</div>
|
47 |
);
|
|
|
93 |
};
|
94 |
return (
|
95 |
<>
|
96 |
+
<div className="main-wrapper"> {/* ✅ این ساختار اصلی حفظ شده است */}
|
97 |
<div className="header-controls">
|
98 |
<button aria-label="انتخاب شخصیت" className="header-icon-button" onClick={() => setIsPersonalityMenuOpen(v => !v)}>
|
99 |
<span className="material-symbols-outlined">psychology</span>
|
|
|
105 |
{isNotificationOpen && <div className="notification-popover-wrapper open"><div className="popover-content">مدلهای هوش مصنوعی میتوانند اشتباه کنند.</div></div>}
|
106 |
<PersonalityMenu isOpen={isPersonalityMenuOpen} onClose={() => setIsPersonalityMenuOpen(false)} onSelect={handleSelectPersonality} />
|
107 |
|
108 |
+
<div className="media-area"> {/* ✅ این بخش برای نمایش ویدیو و لوگو ضروری است */}
|
109 |
+
<video id="video-feed" ref={videoRef} autoPlay playsInline className={cn({ hidden: !isCamActive }, { "scale-x-[-1]": currentFacingMode === 'user' })} />
|
|
|
|
|
|
|
|
|
|
|
|
|
110 |
{isMicActive && !isCamActive && <div id="large-logo-container"><Logo isMini={false} isActive={true} isAi={false} speakingVolume={volume} isUserSpeaking={isUserSpeaking} /></div>}
|
111 |
</div>
|
112 |
|
113 |
+
<ControlTray videoRef={videoRef} onUserSpeakingChange={setIsUserSpeaking} isAppMicActive={isMicActive} onAppMicToggle={setIsMicActive} isAppCamActive={isCamActive} onAppCamToggle={setIsCamActive} currentFacingMode={currentFacingMode} onFacingModeChange={setCurrentFacingMode} />
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
114 |
</div>
|
115 |
<CustomModal isOpen={isCustomModalOpen} onClose={() => setIsCustomModalOpen(false)} onSave={(name, instructions) => changePersonality('custom', { name, instructions })} initialName={customUserName} initialInstructions={customInstructions} />
|
116 |
</>
|