Spaces:
Sleeping
Sleeping
| import React, { useState, useRef, useEffect } from 'react'; | |
| import './App.css'; | |
| import { VideoManagerLocal } from './utils/VideoManagerLocal'; | |
| // 引入我们刚刚拆分好的组件 | |
| // 注意:确保你的文件名和这里 import 的名字完全一致 | |
| import Home from './components/Home'; | |
| import FocusPageLocal from './components/FocusPageLocal'; | |
| import Achievement from './components/Achievement'; | |
| import Records from './components/Records'; | |
| import Customise from './components/Customise'; | |
| import Help from './components/Help'; | |
| function App() { | |
| // 定义状态:当前显示哪个页面 | |
| const [activeTab, setActiveTab] = useState('home'); | |
| // 全局VideoManagerLocal实例和session状态 | |
| const videoManagerRef = useRef(null); | |
| const [isSessionActive, setIsSessionActive] = useState(false); | |
| const [sessionResult, setSessionResult] = useState(null); | |
| // 初始化VideoManagerLocal(只创建一次) | |
| useEffect(() => { | |
| const callbacks = { | |
| onSessionStart: () => { | |
| setIsSessionActive(true); | |
| setSessionResult(null); | |
| }, | |
| onSessionEnd: (summary) => { | |
| console.log("App.jsx: onSessionEnd called"); | |
| console.log("App.jsx: Session Summary:", summary); | |
| setIsSessionActive(false); | |
| if (summary) { | |
| console.log("App.jsx: Setting sessionResult with summary"); | |
| setSessionResult(summary); | |
| } else { | |
| console.warn("App.jsx: Summary is null or undefined"); | |
| } | |
| } | |
| }; | |
| videoManagerRef.current = new VideoManagerLocal(callbacks); | |
| // 清理函数:只在整个App卸载时才清理 | |
| return () => { | |
| if (videoManagerRef.current) { | |
| videoManagerRef.current.stopStreaming(); | |
| } | |
| }; | |
| }, []); | |
| // 页面切换时保持session连接,不自动断开 | |
| return ( | |
| <div className="app-container"> | |
| {/* 顶部导航栏 (Top Menu) - 它是全局共用的,所以留在 App.jsx 里 */} | |
| <nav id="top-menu"> | |
| <button | |
| className={`menu-btn ${activeTab === 'focus' ? 'active' : ''}`} | |
| onClick={() => setActiveTab('focus')} | |
| > | |
| Start Focus {isSessionActive && <span style={{marginLeft: '8px', color: '#00FF00'}}>●</span>} | |
| </button> | |
| <div className="separator"></div> | |
| <button | |
| className={`menu-btn ${activeTab === 'achievement' ? 'active' : ''}`} | |
| onClick={() => setActiveTab('achievement')} | |
| > | |
| My Achievement | |
| </button> | |
| <div className="separator"></div> | |
| <button | |
| className={`menu-btn ${activeTab === 'records' ? 'active' : ''}`} | |
| onClick={() => setActiveTab('records')} | |
| > | |
| My Records | |
| </button> | |
| <div className="separator"></div> | |
| <button | |
| className={`menu-btn ${activeTab === 'customise' ? 'active' : ''}`} | |
| onClick={() => setActiveTab('customise')} | |
| > | |
| Customise | |
| </button> | |
| <div className="separator"></div> | |
| <button | |
| className={`menu-btn ${activeTab === 'help' ? 'active' : ''}`} | |
| onClick={() => setActiveTab('help')} | |
| > | |
| Help | |
| </button> | |
| </nav> | |
| {/* 页面内容区域:根据 activeTab 的值,渲染对应的组件 */} | |
| {/* Home 页:我们需要把 setActiveTab 传给它,因为它的 'Start' 按钮要能跳转页面 */} | |
| {activeTab === 'home' && <Home setActiveTab={setActiveTab} />} | |
| {/* FocusPageLocal 保持常驻,避免切页中断视频/连接 - 使用本地处理,不依赖WebRTC */} | |
| <FocusPageLocal | |
| videoManager={videoManagerRef.current} | |
| sessionResult={sessionResult} | |
| setSessionResult={setSessionResult} | |
| isActive={activeTab === 'focus'} | |
| /> | |
| {activeTab === 'achievement' && <Achievement />} | |
| {activeTab === 'records' && <Records />} | |
| {activeTab === 'customise' && <Customise />} | |
| {activeTab === 'help' && <Help />} | |
| </div> | |
| ); | |
| } | |
| export default App; | |