docs: document in-app navigation persistence (no transfer interruption)
- README.md / README.zh-CN.md:
- Add feature bullet for in-app navigation persistence (same-tab SPA)
- Note boundaries: refresh/tab close/new tab not covered
- Frontend architecture (zh/en):
- Add “State & Connection Lifecycle (In-App Navigation)” section
- Explain Zustand store singleton and webrtcService singleton across routes
- Guidance: avoid leaveRoom()/store reset on route-change side effects
- System architecture (zh/en):
- Add “Runtime Session Model (Frontend)” summary
- AI Playbook:
- flows.zh-CN.md: add UX optimization item for in-app navigation persistence and debugging notes
- code-map.zh-CN.md: mark webrtcService and fileTransferStore as singletons (cross-route)
This commit is contained in:
@@ -76,4 +76,9 @@ graph TD
|
||||
|
||||
- **Privacy First**: Core file data is never uploaded to the server. The server only acts as an "introducer" or "matchmaker."
|
||||
- **Frontend-Backend Separation**: Responsibilities are clearly separated. The frontend handles all user interaction and the complex logic of WebRTC; the backend provides lightweight, efficient signaling and room management services.
|
||||
- **Horizontal Scalability**: The backend is stateless (with state managed in Redis), which theoretically allows it to be scaled horizontally by adding more Node.js instances to handle a large volume of concurrent signaling requests.
|
||||
- **Horizontal Scalability**: The backend is stateless (with state managed in Redis), which theoretically allows it to be scaled horizontally by adding more Node.js instances to handle a large volume of concurrent signaling requests.
|
||||
|
||||
## 4. Runtime Session Model (Frontend)
|
||||
|
||||
- **SPA In-App Navigation Persistence**: The frontend is an SPA (App Router). Within the same browser tab, in-app navigation does not tear down the singleton app state (Zustand) nor the WebRTC connection service (webrtcService). Ongoing transfers continue, and selected/received content remains available.
|
||||
- **Boundary**: Page refresh, closing the tab, or opening in a new tab are not covered. If changing layout/SSR strategy, avoid cleaning the connection during layout unmount.
|
||||
|
||||
@@ -77,3 +77,8 @@ graph TD
|
||||
- **隐私优先**: 核心文件数据永不上传到服务器。服务器只承担“介绍人”的角色。
|
||||
- **前后端分离**: 前后端职责清晰。前端负责所有与用户交互和 WebRTC 的复杂逻辑;后端则提供轻量、高效的信令和房间管理服务。
|
||||
- **水平扩展**: 后端是无状态的(状态存储在 Redis 中),理论上可以通过增加 Node.js 实例来水平扩展,以应对大量并发信令请求。
|
||||
|
||||
## 四、运行时会话模型(前端)
|
||||
|
||||
- **SPA 站内导航保持**:前端为单页应用(App Router)。在同一标签页内进行站内跳转时,应用状态(Zustand 单例)与 WebRTC 连接服务(webrtcService 单例)不会被销毁,进行中的传输不中断,已选择/已接收内容保持。
|
||||
- **边界说明**:页面刷新、关闭标签页或在新标签页打开页面,不属于保持范围;如调整布局/SSR 策略,需避免在布局卸载阶段清理连接。
|
||||
|
||||
@@ -135,6 +135,14 @@ Benefits:
|
||||
- **Automatic Detection**: `middleware.ts` intercepts requests and automatically redirects to the appropriate language path based on the `Accept-Language` header or a cookie.
|
||||
- **Dynamic Loading**: The `getDictionary` function in `lib/dictionary.ts` asynchronously loads the corresponding `messages/*.json` file based on the `lang` parameter, enabling code splitting.
|
||||
|
||||
### 3.4 State & Connection Lifecycle (In-App Navigation)
|
||||
|
||||
- **Singleton Store (Zustand)**: `frontend/stores/fileTransferStore.ts` is a module-level singleton, preserving in-memory state across routes (e.g., share content, files to send, received files/meta, progress states).
|
||||
- **Singleton Connection Service (webrtcService)**: `frontend/lib/webrtcService.ts` holds `RTCPeerConnection`/`RTCDataChannel` and FileSender/FileReceiver as a singleton. App Router page switches do not tear it down.
|
||||
- **Effect**: In the same browser tab, in-app navigation (App Router page switches) does not interrupt ongoing transfers, and selected/received content remains intact.
|
||||
- **Boundary**: Page refresh/closing the tab or opening in a new tab is not covered; when changing layout hierarchy/SSR behavior, avoid cleaning the connection in layout unmount.
|
||||
- **Note**: Do not call `webrtcService.leaveRoom()` or reset the global Store inside route-change side effects; only do so on explicit user actions.
|
||||
|
||||
## 4. Summary and Outlook
|
||||
|
||||
The current frontend architecture successfully deconstructs a complex WebRTC application into a series of clean, maintainable modules through layered design and Hook-centric logic encapsulation. The boundaries between UI, business logic, and underlying libraries are clear, laying a solid foundation for future feature expansion and maintenance.
|
||||
|
||||
@@ -135,6 +135,14 @@ graph TD
|
||||
- **自动检测**: `middleware.ts` 拦截请求,根据 `Accept-Language` 头或 Cookie 自动重定向到合适的语言路径。
|
||||
- **动态加载**: `lib/dictionary.ts` 中的 `getDictionary` 函数根据 `lang` 参数异步加载对应的 `messages/*.json` 文件,实现了代码分割。
|
||||
|
||||
### 3.4 状态与连接生命周期(站内导航保持)
|
||||
|
||||
- **单例 Store(Zustand)**:`frontend/stores/fileTransferStore.ts` 为模块级单例,跨路由保持内存状态(如分享内容、待发送文件、已接收文件/元信息、进度等)。
|
||||
- **单例连接服务(webrtcService)**:`frontend/lib/webrtcService.ts` 单例持有 `RTCPeerConnection`/`RTCDataChannel` 与 FileSender/FileReceiver。App Router 的页面切换不会销毁该实例。
|
||||
- **效果**:在同一标签页内的站内跳转(App Router 页面切换),进行中的传输不会中断,已选择/已接收的内容保持不丢失。
|
||||
- **边界**:刷新/关闭标签页或新开标签页不在此保证范围内;SSR/布局层级调整时需确保不在布局卸载处做连接清理。
|
||||
- **注意**:不要在路由切换副作用中调用 `webrtcService.leaveRoom()` 或重置全局 Store;离开房间应仅在用户显式操作时触发。
|
||||
|
||||
## 四、 总结与展望
|
||||
|
||||
当前的前端架构通过分层设计和以 Hooks 为中心的逻辑封装,成功地将一个复杂的 WebRTC 应用拆解为一系列清晰、可维护的模块。UI、业务逻辑和底层库之间的界限分明,为未来的功能扩展和维护奠定了坚实的基础。
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
- `frontend/lib/webrtc_base.ts` — WebRTC 基础类,提供 Socket.IO 信令、RTCPeerConnection 管理、ICE 候选者队列、双重断开检测重连机制、唤醒锁管理、数据通道发送重试(5 次递增间隔)、优雅断开跟踪(gracefullyDisconnectedPeers Set)和多格式数据类型兼容性支持(ArrayBuffer/Blob/Uint8Array/TypedArray)。
|
||||
- `frontend/lib/webrtc_Initiator.ts` — 发起方实现,处理`ready`/`recipient-ready`事件,创建 RTCPeerConnection 和主动式 DataChannel,发送 offer,处理 answer 响应,支持 256KB 缓冲阈值配置。
|
||||
- `frontend/lib/webrtc_Recipient.ts` — 接收方实现,处理`offer`事件,创建 RTCPeerConnection 和响应式 DataChannel(ondatachannel),生成并发送 answer,处理`initiator-online`重连信号和现有连接清理。
|
||||
- `frontend/lib/webrtcService.ts` — WebRTC 服务单例封装,管理 sender/receiver 实例,提供统一业务接口,处理连接状态变更、数据广播、文件请求和连接断开清理。
|
||||
- `frontend/lib/webrtcService.ts` — WebRTC 服务单例封装(跨路由常驻),管理 sender/receiver 实例,提供统一业务接口,处理连接状态变更、数据广播、文件请求和连接断开清理。
|
||||
- 发送(sender)
|
||||
- `frontend/lib/fileSender.ts` — 发送端向后兼容包装层,内部使用 FileTransferOrchestrator 提供统一服务。
|
||||
- `frontend/lib/transfer/FileTransferOrchestrator.ts` — 发送端主编排器,集成所有组件管理文件传输生命周期。
|
||||
@@ -84,7 +84,7 @@
|
||||
|
||||
- `frontend/stores/` — 共享应用状态(Zustand)。
|
||||
|
||||
- `frontend/stores/fileTransferStore.ts` — 传输进度/状态的唯一事实来源。
|
||||
- `frontend/stores/fileTransferStore.ts` — 传输进度/状态的唯一事实来源(Zustand 单例,跨路由保持)。
|
||||
|
||||
- `frontend/types/`、`frontend/constants/` — 类型定义与常量。
|
||||
|
||||
|
||||
@@ -247,6 +247,7 @@ Core Services (webrtcService) + Store (fileTransferStore)
|
||||
6. **全局拖拽优化**:ClipboardApp 使用 dragCounter 防止拖拽状态误判,支持 webkitGetAsEntry 文件树遍历
|
||||
7. **剪贴板兼容性**:useClipboardActions 支持现代 navigator.clipboard API 和 document.execCommand 降级方案
|
||||
8. **富文本安全处理**:useRichTextToPlainText 服务端渲染安全,客户端 DOM 转换处理块级元素
|
||||
9. **站内导航不中断(同一标签页)**:依赖 `frontend/stores/fileTransferStore.ts`(Zustand 单例)与 `frontend/lib/webrtcService.ts`(服务单例)。App Router 页面切换不打断传输且保留已选择/已接收内容。注意不要在路由切换副作用中调用 `webrtcService.leaveRoom()` 或重置 Store;刷新/新标签不在保证范围内。
|
||||
|
||||
### 前端组件架构特化
|
||||
|
||||
|
||||
Reference in New Issue
Block a user