File size: 4,126 Bytes
2083506
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
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;