增加了发布通道

This commit is contained in:
sansen
2026-07-23 19:37:20 +08:00
parent e3d03d74ea
commit e8a45032f8
35 changed files with 1489 additions and 413 deletions
+44 -16
View File
@@ -60,25 +60,44 @@ Communication flows through two bridge layers:
**Event flow**: Go library → event queue → single consumer goroutine → JNI callback → Kotlin callback → ViewModel
### Android Layer Structure
### Android MVVM + Repository Pattern
```
android/app/src/main/java/com/tsmobile/app/
├── MainActivity.kt # Entry point
├── TSBridge.kt # Go bridge wrapper
├── ui/
│ ├── components/ # Reusable UI components
│ ├── screens/ # Top-level screens
│ ├── navigation/NavGraph.kt # App navigation
│ └── theme/ # Material Design 3 theme
└── viewmodel/ # State management
├── ChannelViewModel.kt # Channel list & navigation
├── ChatViewModel.kt # Text messaging
├── ServerViewModel.kt # Connection & server info
└── VoiceViewModel.kt # Voice communication
Go Library → TSBridge (JNI) → ServerViewModel (callbacks) → Repository (state) → ViewModels → Compose Screens
User Actions → Compose UI → ViewModel methods → TSBridge → Go Library
```
State flows from ViewModels → Screens via `StateFlow`. User actions flow back via ViewModel methods.
**Repository** (`data/Repository.kt`): Singleton object, single source of truth for shared state — channels, clients, channel→clients mapping, current channel, unread counts. Uses `ConcurrentHashMap` for thread-safe message archives (max 500 per session, keyed by `targetMode_targetId`).
**ViewModels**: Cross-references set by `NavGraph` (e.g. `serverViewModel.channelViewModel = channelViewModel`). `ServerViewModel` dispatches all bridge callbacks to other ViewModels.
**State machines** (sealed classes in `data/Models.kt`): `ConnectionState`, `MessageSendState`, `MessageDeliveryState`, `VoiceState`, `SyncState`, `ChannelSwitchState` — use `when` for pattern matching.
### Voice System Ownership Split
- **Go side** owns the full decode/mix pipeline: per-client jitter buffers, Opus decoders, stereo mixing. Delivers mixed PCM16 as 20ms frames (48kHz, interleaved stereo) via `onPCM` callback. Speaking detection: 400ms silence timeout.
- **Kotlin side** owns capture: `AudioRecord` (mono, 48kHz) → `OpusEncoder``TSBridge.sendVoice()`. Noise suppressor support. Speaking detection via RMS threshold (0.015).
### Message Delivery Confirmation
Messages appear immediately as `PENDING` in UI. Server echo (`OnTextMessage` with matching content) confirms → `SENT`. 10-second timeout → `FAILED`. Duplicate detection prevents self-message re-archival.
### Navigation Routes
Four routes in `NavGraph.kt`: `server_config` (connection form) → `channel_list` (channel tree + members) → `chat` (text chat) → `kicked` (kick notification). Navigation driven by `ConnectionState` changes via `LaunchedEffect`.
### Known SDK Limitations
- **No channel CRUD events**: The SDK does not fire events for channel create/update/delete. Channel list is refreshed after 5 minutes of staleness or before channel switch operations.
- **Unreliable ChannelID in enter events**: `notifycliententerview` ChannelID is not effective per SDK docs. Client enter/leave events trigger a full `clientlist` refresh instead of incremental updates.
- **Auto-reconnect disabled by default**: Frequent reconnect attempts cause server-side rate limiting/bans.
### Thread Safety
- `TSClient.mu` mutex protects Go-side client access
- `TSBridge.connectLock` synchronizes Kotlin-side connection lifecycle
- `connectionGeneration` counter prevents stale callbacks from reaching current session
- Event queue PCM events capped at 12 with oldest eviction to prevent buildup
## Critical Build Details
@@ -102,6 +121,10 @@ The `go/_patches/github.com/honeybbq/teamspeak-go/` directory contains modified
Do not remove this directory or the replace directive.
### Go Module and CGo
Go module name is `tsmobile`. Unlike upstream teamspeak-go (zero CGO), this project enables CGO for the Android libopus decoder. Pre-built static libraries live in `go/teamspeak/.opus/lib/{abi}/libopus.a` for all four Android ABIs.
## Common Issues
### "javac: 非法字符" or "GBK unmappable character"
@@ -119,8 +142,13 @@ Missing `-Wl,--hash-style=both` flag. Rebuild AAR with correct flags.
### "Unresolved reference: teamspeak"
AAR not compiled or not in `android/app/libs/teamspeak.aar`. Run Step 1 of manual build.
## Error Conventions
- **Go bridge**: Empty string return = success, non-empty = error message. All IDs are strings for JSON transport.
- **Kotlin**: Chinese-language user-facing errors. `ServerViewModel.classifyError()` maps raw errors to friendly messages. `ChannelViewModel.mapMoveError()` handles channel switch errors.
## Testing
Run from IDE with connected device or emulator. Check Logcat in IDE for runtime logs.
No automated test suite currently exists.
Go unit tests exist for the audio receive pipeline (`go/teamspeak/receive_audio_test.go`): `cd go && go test ./teamspeak/`