Ezmary commited on
Commit
6a6e08c
·
verified ·
1 Parent(s): aaac013

Update src/App.tsx

Browse files
Files changed (1) hide show
  1. src/App.tsx +47 -44
src/App.tsx CHANGED
@@ -104,10 +104,16 @@ const initialAppConfig: LiveConfig = {
104
  },
105
  };
106
 
107
- const SvgHumanIcon = () => (
108
- <svg width="70" height="70" viewBox="0 0 88 89" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M75.1481 81.6361H12.9259C9.66667 81.6361 7 78.9721 7 75.7161V58.5112C7 57.5862 7 57.1052 7.44444 56.2172C8.85185 52.9612 13 50.2232 19.4815 47.8922C24.1111 56.6982 33.3704 62.6921 44 62.6921C54.6296 62.6921 63.9259 56.6982 68.5185 47.8922C75 50.1862 79.1852 52.9982 80.5556 56.2172C81 56.6612 81 57.6232 81 58.5112V75.7161C81 78.9721 78.3333 81.6361 75.0741 81.6361H75.1481Z" stroke="currentColor" strokeWidth="6.42146" strokeLinecap="round" strokeLinejoin="round"/><path d="M44.0371 50.1862C33.8519 50.1862 25.5186 41.8612 25.5186 31.6863V26.1363C25.5186 15.9613 33.8519 7.63635 44.0371 7.63635C54.2223 7.63635 62.5556 15.9613 62.5556 26.1363V31.6863C62.5556 41.8612 54.2223 50.1862 44.0371 50.1862Z" stroke="currentColor" strokeWidth="6.42146" strokeLinecap="round" strokeLinejoin="round"/></svg>
 
 
 
 
 
109
  );
110
 
 
111
  const AppInternalLogic: React.FC<{
112
  isMicActive: boolean;
113
  isCamActive: boolean;
@@ -134,39 +140,37 @@ const AppInternalLogic: React.FC<{
134
  const { connected, disconnect } = useLiveAPIContext();
135
 
136
  useEffect(() => {
 
137
  if (!isMicActive && !isCamActive && connected) {
138
  disconnect();
139
  }
140
  }, [isMicActive, isCamActive, connected, disconnect]);
141
 
142
  return (
143
- <div className="w-full flex flex-col items-center justify-center min-h-screen text-foreground antialiased">
144
- <div className="max-w-3xl w-full flex flex-col items-center justify-center h-full relative">
145
  <div className="header-controls">
146
- <div id="notification-trigger-container"> {/* Wrapper is good for potential future styling or positioning */}
147
  <button
148
  ref={notificationButtonRef}
149
  id="notification-button"
150
  aria-label="Notifications"
151
- className="header-button" // Standard class for header buttons
152
  onClick={(e) => {
153
  e.stopPropagation();
154
  setIsNotificationOpen(!isNotificationOpen);
155
  }}
156
  >
157
- {/* Notification Icon SVG */}
158
  <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>
159
  </button>
160
  </div>
161
- <div className="back-button-container"> {/* Wrapper for the back button */}
162
- {/* *** MODIFIED: Ensure it uses the same `header-button` class *** */}
163
- <button // Changed from div to button for better accessibility and event handling
164
  id="back-button"
165
  aria-label="Go back"
166
- className="header-button" // Standard class for header buttons
167
  onClick={() => alert('Back clicked (implement navigation)')}
168
  >
169
- {/* Back Icon SVG - Ensure its size is consistent with notification icon or adjust padding */}
170
  <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"><path d="m15 18-6-6 6-6"></path></svg>
171
  </button>
172
  </div>
@@ -186,29 +190,21 @@ const AppInternalLogic: React.FC<{
186
  </div>
187
  </div>
188
 
189
- <div className="w-full flex flex-col items-center justify-center flex-grow relative">
 
190
  <video
191
  id="video-feed"
192
  ref={videoRef}
193
  autoPlay
194
  playsInline
195
- className={cn(
196
- "absolute top-0 left-0 w-full h-full object-cover scale-x-[-1]",
197
- { "hidden": !isCamActive }
198
- )}
199
  />
200
- <div
201
- id="large-logo-container"
202
- className={cn(
203
- "absolute top-0 left-0 w-full h-full",
204
- {
205
- "flex items-center justify-center": isMicActive && !isCamActive,
206
- "hidden": !isMicActive || isCamActive,
207
- }
208
- )}
209
- >
210
- {isMicActive && !isCamActive && createLogoFunction(false, true, 'human')}
211
- </div>
212
  </div>
213
 
214
  <ControlTray
@@ -226,20 +222,21 @@ const AppInternalLogic: React.FC<{
226
  );
227
  }
228
 
 
229
  const logoColorConfig = {
230
  blue: {
231
  ping: "bg-blue-200 dark:bg-blue-700",
232
- outer: "bg-blue-200 dark:bg-blue-700",
233
  mid: "bg-blue-300 dark:bg-blue-600",
234
- inner: "bg-blue-400 dark:bg-blue-500",
235
  },
236
- green: {
237
  ping: "bg-green-200 dark:bg-green-700",
238
  outer: "bg-green-200 dark:bg-green-700",
239
  mid: "bg-green-300 dark:bg-green-600",
240
  inner: "bg-green-400 dark:bg-green-500",
241
  },
242
- gray: {
243
  ping: "bg-gray-200 dark:bg-gray-700",
244
  outer: "bg-gray-200 dark:bg-gray-700",
245
  mid: "bg-gray-300 dark:bg-gray-600",
@@ -247,6 +244,7 @@ const logoColorConfig = {
247
  }
248
  };
249
 
 
250
  function App() {
251
  const videoRef = useRef<HTMLVideoElement>(null);
252
  const [showIOSModal, setShowIOSModal] = useState(false);
@@ -293,28 +291,33 @@ function App() {
293
 
294
  const createLogoFunction = (isMini: boolean, isActive: boolean, type: 'human' | 'ai' = 'human') => {
295
  if (!isActive) return null;
296
- const size = isMini ? 80 : 200;
297
- // const iconSize = isMini ? 35 : 70; // Unused for SvgHumanIcon
 
298
  const insetBase = isMini
299
- ? { ping: 10, outer: 0, mid: 5, inner: 12, icon: 22 }
300
- : { ping: 40, outer: 0, mid: 20, inner: 50, icon: 65 };
301
 
 
302
  const effectiveType = (type === 'human') ? 'blue' : (type === 'ai' ? 'green' : 'gray');
303
  const currentColors = logoColorConfig[effectiveType as keyof typeof logoColorConfig] || logoColorConfig.gray;
304
 
305
  return (
306
- <div className="relative" style={{ width: `${size}px`, height: `${size}px` }}>
307
- <div className={`absolute rounded-full opacity-50 animate-ping ${currentColors.ping}`} style={{ inset: `${insetBase.ping}px` }}></div>
308
- <div className={`absolute rounded-full opacity-50 ${currentColors.outer}`} style={{ inset: `${insetBase.outer}px` }}></div>
309
- <div className={`absolute rounded-full opacity-50 ${currentColors.mid}`} style={{ inset: `${insetBase.mid}px` }}></div>
310
- <div className={`absolute rounded-full opacity-50 ${currentColors.inner}`} style={{ inset: `${insetBase.inner}px` }}></div>
311
- <div className="z-10 absolute" style={{ inset: `${insetBase.icon}px`, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
312
- {type === 'human' && <SvgHumanIcon />}
 
 
313
  </div>
314
  </div>
315
  );
316
  };
317
 
 
318
  return (
319
  <LiveAPIProvider initialConfig={initialAppConfig}>
320
  <AppInternalLogic
 
104
  },
105
  };
106
 
107
+ // آیکون انسان از HTML شما (برای لوگوی بزرگ و کوچک)
108
+ // stroke="currentColor" باعث می‌شود رنگ خطوط از CSS (var(--foreground)) ارث‌بری کند
109
+ // ** مهم: آیکون انسان شما از HTML دارای stroke="#FCFCFC" است، آن را به "currentColor" تغییر می‌دهیم
110
+ // تا با تم برنامه هماهنگ شود یا اگر می‌خواهید سفید بماند، نیازی به تغییر نیست.
111
+ // برای سادگی فعلا همان کد HTML را استفاده می‌کنیم.
112
+ const SvgHumanIconFromHTML = () => (
113
+ <svg width="70" height="70" viewBox="0 0 88 89" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M75.1481 81.6361H12.9259C9.66667 81.6361 7 78.9721 7 75.7161V58.5112C7 57.5862 7 57.1052 7.44444 56.2172C8.85185 52.9612 13 50.2232 19.4815 47.8922C24.1111 56.6982 33.3704 62.6921 44 62.6921C54.6296 62.6921 63.9259 56.6982 68.5185 47.8922C75 50.1862 79.1852 52.9982 80.5556 56.2172C81 56.6612 81 57.6232 81 58.5112V75.7161C81 78.9721 78.3333 81.6361 75.0741 81.6361H75.1481Z" stroke="#FCFCFC" strokeWidth="6.42146" strokeLinecap="round" strokeLinejoin="round"/><path d="M44.0371 50.1862C33.8519 50.1862 25.5186 41.8612 25.5186 31.6863V26.1363C25.5186 15.9613 33.8519 7.63635 44.0371 7.63635C54.2223 7.63635 62.5556 15.9613 62.5556 26.1363V31.6863C62.5556 41.8612 54.2223 50.1862 44.0371 50.1862Z" stroke="#FCFCFC" strokeWidth="6.42146" strokeLinecap="round" strokeLinejoin="round"/></svg>
114
  );
115
 
116
+
117
  const AppInternalLogic: React.FC<{
118
  isMicActive: boolean;
119
  isCamActive: boolean;
 
140
  const { connected, disconnect } = useLiveAPIContext();
141
 
142
  useEffect(() => {
143
+ // Disconnect if neither mic nor cam is active, but connection exists
144
  if (!isMicActive && !isCamActive && connected) {
145
  disconnect();
146
  }
147
  }, [isMicActive, isCamActive, connected, disconnect]);
148
 
149
  return (
150
+ <div className="app-container"> {/* Renamed for clarity */}
151
+ <div className="app-content-wrapper"> {/* Renamed for clarity */}
152
  <div className="header-controls">
153
+ <div id="notification-trigger-container">
154
  <button
155
  ref={notificationButtonRef}
156
  id="notification-button"
157
  aria-label="Notifications"
158
+ className="header-button"
159
  onClick={(e) => {
160
  e.stopPropagation();
161
  setIsNotificationOpen(!isNotificationOpen);
162
  }}
163
  >
 
164
  <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>
165
  </button>
166
  </div>
167
+ <div className="back-button-container">
168
+ <button
 
169
  id="back-button"
170
  aria-label="Go back"
171
+ className="header-button"
172
  onClick={() => alert('Back clicked (implement navigation)')}
173
  >
 
174
  <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"><path d="m15 18-6-6 6-6"></path></svg>
175
  </button>
176
  </div>
 
190
  </div>
191
  </div>
192
 
193
+ {/* Media Area: Video and Large Logo */}
194
+ <div className="media-area"> {/* For video and large logo */}
195
  <video
196
  id="video-feed"
197
  ref={videoRef}
198
  autoPlay
199
  playsInline
200
+ className={cn("video-feed", { "hidden": !isCamActive })}
 
 
 
201
  />
202
+ {/* Large Logo for Mic-Only mode, centered */}
203
+ {isMicActive && !isCamActive && (
204
+ <div id="large-logo-container" className="large-logo-container">
205
+ {createLogoFunction(false, true, 'human')}
206
+ </div>
207
+ )}
 
 
 
 
 
 
208
  </div>
209
 
210
  <ControlTray
 
222
  );
223
  }
224
 
225
+ // For Tailwind JIT compatibility for dynamic classes
226
  const logoColorConfig = {
227
  blue: {
228
  ping: "bg-blue-200 dark:bg-blue-700",
229
+ outer: "bg-blue-200 dark:bg-blue-700", // Same as ping or different if desired
230
  mid: "bg-blue-300 dark:bg-blue-600",
231
+ inner: "bg-blue-400 dark:bg-blue-500", // Corrected inner class
232
  },
233
+ green: { // Example for AI, if you add it
234
  ping: "bg-green-200 dark:bg-green-700",
235
  outer: "bg-green-200 dark:bg-green-700",
236
  mid: "bg-green-300 dark:bg-green-600",
237
  inner: "bg-green-400 dark:bg-green-500",
238
  },
239
+ gray: { // Fallback
240
  ping: "bg-gray-200 dark:bg-gray-700",
241
  outer: "bg-gray-200 dark:bg-gray-700",
242
  mid: "bg-gray-300 dark:bg-gray-600",
 
244
  }
245
  };
246
 
247
+
248
  function App() {
249
  const videoRef = useRef<HTMLVideoElement>(null);
250
  const [showIOSModal, setShowIOSModal] = useState(false);
 
291
 
292
  const createLogoFunction = (isMini: boolean, isActive: boolean, type: 'human' | 'ai' = 'human') => {
293
  if (!isActive) return null;
294
+
295
+ const size = isMini ? 80 : 200; // As per HTML
296
+ // const iconSize = isMini ? 35 : 70; // SVG has fixed size, this is for container div
297
  const insetBase = isMini
298
+ ? { ping: 10, outer: 0, mid: 5, inner: 12, icon: 22 } // For small logo
299
+ : { ping: 40, outer: 0, mid: 20, inner: 50, icon: 65 }; // For large logo
300
 
301
+ // Determine color scheme based on type (human or AI)
302
  const effectiveType = (type === 'human') ? 'blue' : (type === 'ai' ? 'green' : 'gray');
303
  const currentColors = logoColorConfig[effectiveType as keyof typeof logoColorConfig] || logoColorConfig.gray;
304
 
305
  return (
306
+ <div className="logo-animation-wrapper" style={{ width: `${size}px`, height: `${size}px` }}>
307
+ {/* These class names (e.g., bg-blue-200) should exist in your Tailwind config or be full utility classes */}
308
+ <div className={`logo-ping ${currentColors.ping}`} style={{ inset: `${insetBase.ping}px` }}></div>
309
+ <div className={`logo-outer ${currentColors.outer}`} style={{ inset: `${insetBase.outer}px` }}></div>
310
+ <div className={`logo-mid ${currentColors.mid}`} style={{ inset: `${insetBase.mid}px` }}></div>
311
+ <div className={`logo-inner ${currentColors.inner}`} style={{ inset: `${insetBase.inner}px` }}></div>
312
+ <div className="logo-icon-container" style={{ inset: `${insetBase.icon}px` }}>
313
+ {type === 'human' && <SvgHumanIconFromHTML />}
314
+ {/* {type === 'ai' && <AiIconSVG />} You would define AiIconSVG similarly */}
315
  </div>
316
  </div>
317
  );
318
  };
319
 
320
+
321
  return (
322
  <LiveAPIProvider initialConfig={initialAppConfig}>
323
  <AppInternalLogic