📱 技術堆疊 (Tech Stack)¶
核心技術¶
平台: iOS
技術選型
| 類別 | 技術 | 用途 |
|---|---|---|
| 框架 | React Native 0.73+ | 跨平台 App 開發 |
| 語言 | TypeScript | 型別安全的開發 |
| BLE | react-native-ble-plx | 藍牙裝置整合 |
| 狀態管理 | Redux Toolkit / Zustand | 全域狀態管理 |
| 網路 | Axios | HTTP 請求 |
| 本機儲存 | WatermelonDB | 本地資料庫 (見 03.4) |
| 影片播放 | react-native-video | 課程影片播放 |
| 導航 | React Navigation | 畫面路由 |
🏗️ App 分層架構¶
┌─────────────────────────────────────────┐
│ App Architecture │
│ │
│ ┌────────────────────────────────────┐│
│ │ UI Layer ││
│ │ (Screens / Components) ││
│ │ ││
│ │ - LoginScreen ││
│ │ - DeviceConnectionScreen ││
│ │ - WorkoutScreen ││
│ │ - WorkoutSummaryScreen ││
│ │ - HistoryScreen ││
│ │ - SettingsScreen ││
│ └────────────────────────────────────┘│
│ ▲│ │
│ ││ (State / Props) │
│ ▼│ │
│ ┌────────────────────────────────────┐│
│ │ Service Layer ││
│ │ ││
│ │ - WorkoutEngine ││
│ │ - BLEManager ││
│ │ - APIClient ││
│ │ - AuthService ││
│ │ - StorageService ││
│ └────────────────────────────────────┘│
│ │ │
│ ▼ │
│ ┌────────────────────────────────────┐│
│ │ Data Layer ││
│ │ ││
│ │ - WatermelonDB (local) ││
│ │ - Axios (network) ││
│ │ - react-native-ble-plx (BLE) ││
│ └────────────────────────────────────┘│
└─────────────────────────────────────────┘
🗂️ Navigation 結構¶
使用 React Navigation (Tab-based):
Root Navigator
├─ Auth Stack (未登入)
│ └─ LoginScreen
│
└─ Main Tab Navigator (已登入)
├─ Home Stack (訓練選擇)
│ ├─ TrainingListScreen
│ └─ TrainingDetailScreen
│
├─ Workout Stack (運動中)
│ ├─ DeviceConnectionScreen
│ ├─ WorkoutScreen
│ └─ WorkoutSummaryScreen
│
├─ History Stack (歷史記錄)
│ ├─ HistoryListScreen
│ └─ HistoryDetailScreen
│
└─ Settings Stack (設定)
└─ SettingsScreen
🎨 狀態管理¶
方案選擇¶
建議使用: Redux Toolkit 或 Zustand
狀態分類¶
| 類型 | 存放位置 | 範例 |
|---|---|---|
| 全域狀態 | Redux Store / Zustand | 使用者登入狀態、BLE 連線狀態、當前運動 session |
| 本地狀態 | React useState / useReducer |
表單輸入、UI 開關 |
| 伺服器狀態 | RTK Query / React Query | API 資料快取 |
| 持久化狀態 | WatermelonDB | 運動記錄、課程清單 |
設計原則¶
- 單一來源真相 (Single Source of Truth): 每個狀態只有一個來源
- 不可變性 (Immutability): 使用 Redux Toolkit 的 immer 確保狀態不可變
- 可預測性 (Predictability): 透過 Actions 和 Reducers 控制狀態變化
🔧 核心服務模組¶
1. WorkoutEngine (services/WorkoutEngine.ts)¶
職責: 管理運動 session 生命週期
功能:
- 開始 / 暫停 / 恢復 / 結束運動
- 接收 BLE metrics 事件並記錄
- 計算即時統計 (平均功率、總距離等)
- 完成 session 後生成摘要
- 觸發上傳至後端 (透過 APIClient)
實作方式: TypeScript Class 或 Custom Hook
狀態管理: Redux store 或 Zustand
資料儲存: 運動中寫入 WatermelonDB
2. BLEManager (services/BLEManager.ts)¶
職責: 藍牙設備連線與通訊
使用套件: react-native-ble-plx
功能:
- 掃描 SolidFocus 設備 (SF_PRIMARY_SERVICE_UUID)
- 連線、服務發現、特徵訂閱
- 解析 FTMS Indoor Bike Data / Rower Data
- 發送控制指令 (Start/Stop/Pause/阻力調整)
- 監聽 Device Status 通知
事件處理: EventEmitter 或 Redux Actions
權限管理:
- iOS:
Info.plist設定NSBluetoothAlwaysUsageDescription - Android:
PermissionsAndroid.request(BLUETOOTH_SCAN, BLUETOOTH_CONNECT)
詳細設計: 見 03.2 BLE 設備整合
3. APIClient (services/APIClient.ts)¶
職責: 與後端 API 通訊
使用套件: Axios
功能:
- 使用者登入 / SSO 認證
- 上傳運動紀錄 (Batch Upload)
- 下載課程清單與影片 metadata
- Token refresh (Interceptor 自動處理)
攔截器 (Interceptors):
- Request: 自動附加 JWT Token (
Authorization: Bearer <token>) - Response: 401 時自動 refresh token
錯誤處理: 統一錯誤處理與 Toast 提示
API 規格: 見 第 4 章:API Contract
4. StorageService (services/StorageService.ts)¶
職責: 本機資料持久化
使用套件: WatermelonDB
功能:
- 儲存運動中的 metrics (防止網路中斷遺失)
- 快取課程資訊 (Trainings, Videos)
- 儲存 Pending Sessions (待上傳)
- 離線 session 暫存,待網路恢復後上傳
Schema 設計: 見 03.4 本地資料庫 Schema
🚀 App 啟動流程¶
App.tsx (Entry Point)
↓
Redux Store / Zustand Store 初始化
↓
Check Login State (從 Local DB 讀取)
↓
├── Not Logged In → NavigationContainer → LoginScreen
│ ↓
│ Login Success
│ ↓
│ 資料同步 (Sync)
│ ↓
└────────────────────────────────────→ Main Tab Navigator
↓
Check BLE Permissions
↓
BLEManager.initialize()
↓
Auto-connect to last device
↓
Ready for Workout
重要設計原則
- 看到主畫面時,一定已經 Login + 資料同步 + BLE 連線完成
- Login 後必須先完成資料同步,才能進入主畫面
- 詳細流程見 03.3 資料流與同步策略
🔗 相關章節¶
- 03.2 BLE 設備整合 - BLE 連線詳細設計
- 03.3 資料流與同步策略 - 資料同步核心邏輯
- 03.4 本地資料庫 Schema - WatermelonDB Schema
- 第 4 章:API Contract - Backend API 規格