Conversation
- Upgrade compileSdk and targetSdkVersion from 34 to 36 - Update Kotlin stdlib and plugin to 2.1.0 - Update Android Gradle Plugin to 8.7.0 - Update Gradle wrapper to 8.9
- Add Pods xcconfig includes for iOS and macOS builds - Register wakelock_plus and package_info_plus plugins for macOS - Add Podfiles for iOS and macOS dependency management
Add PTTButton enum and PTTConfiguration class for multi-button support: - Volume buttons (device volume down/up) - Play/Pause button (Bluetooth/wired headsets) - On-Screen button (universal fallback) - System PTT (iOS 16+ only) Add wakelock_plus dependency for screen wake lock during rides.
…tion Add comprehensive button handling in MainActivity.kt: - Volume button interception via onKeyDown/onKeyUp - Play/pause button handling via dispatchKeyEvent - Long-press detection to prevent Google Assistant activation - Dynamic button routing based on configuration - Screen wake lock support via FLAG_KEEP_SCREEN_ON - Toggle and Hold mode support with debounce Add MODIFY_AUDIO_SETTINGS permission for audio session control.
Add comprehensive button handling in AppDelegate.swift: - VolumeButtonObserver class using KVO for volume button capture - Automatic volume reset to prevent actual volume changes - MPRemoteCommandCenter for headset button handling - Screen wake lock via isIdleTimerDisabled - Dynamic button configuration via platform channel Note: iOS cannot prevent Siri activation on long-press (system restriction)
Extend PTTService with configuration capabilities: - PTTConfiguration class for mode, button, and screen lock settings - Dynamic native platform synchronization via method channel - WakeLock integration with wakelock_plus package - Auto-switch to toggle mode for play/pause button - Real-time configuration updates without restart
Add interactive on-screen PTT button to HomeScreen: - Tap/hold gesture support based on PTT mode - Visual feedback with glow effects - Current button configuration display - Dynamic instruction text Create SettingsScreen with complete configuration UI: - PTT mode selector (toggle/hold) - Button type selector with platform filtering - Screen lock toggle switch - Platform-specific tips and limitation warnings
Add comprehensive PTT documentation: - PTT_IMPLEMENTATION_SUMMARY.md: Complete feature overview and architecture - TESTING.md: Voice assistant prevention testing guide - PHASE1_VOLUME_BUTTON_TESTING.md: Volume button validation - PHASE2_ONSCREEN_BUTTON_TESTING.md: On-screen button validation - PHASE3_SETTINGS_UI_TESTING.md: Settings UI validation - VOICE_ASSISTANT_FIX.md: Voice assistant prevention details - QUICK_START.md: Quick setup instructions - WIRELESS_DEBUG_SETUP.md: Wireless debugging setup - docs/bluetooth-ptt-implementation.md: Bluetooth integration details
- Update .nvmrc from v22 to v24 - Update README.md with PTT documentation links and known limitations - Add .claude/settings.json for Claude Code configuration - Add connect-android.sh for wireless ADB debugging workflow
Implement WebSocket-based signaling server for WebRTC peer coordination: - Hub for managing rooms and client connections - Client handling with read/write pumps - Message types for offers, answers, ICE candidates, and PTT events - Health check and stats endpoints - Docker build support
Add Flutter services for P2P voice communication: - SignalingClient: WebSocket client for room/peer management - WebRTCService: Peer connection and audio stream handling - Dependencies: flutter_webrtc, web_socket_channel, uuid
Add CallScreen for P2P voice calls: - Shows connected peers and their talking status - PTT button integration with WebRTC mute/unmute - Connection status indicator - Join room dialog from home screen
Add infrastructure for running services: - docker-compose.yaml for local development - k3s/signaling-deployment.yaml for Kubernetes - Prepared placeholders for Redis, Postgres, Kafka (Phase 2)
Document the signaling service and WebRTC integration: - Updated architecture diagram with services structure - MVP status and test matrix - Quick start for running signaling server - WebSocket message reference - Connection example code - Next steps for testing
Extract PTT media-button handling from MainActivity into a foreground
MediaSessionService (PttMediaSessionService + PttPlayer) so headset
play/pause events keep arriving when the activity is backgrounded or
the screen is off. KeyEvents flow back to the activity via PttEventBus
for translation into Flutter MethodChannel calls.
Bug fix: BT headset play/pause buttons emit ACTION_DOWN+ACTION_UP
back-to-back at release time, which in hold mode produced a brief
green flash that immediately reverted to red. handleKeyEventForPTT
now forces toggle semantics for media keycodes (HEADSETHOOK,
MEDIA_PLAY_PAUSE, MEDIA_PLAY, MEDIA_PAUSE) regardless of pttMode,
so volume buttons can stay in hold mode while play/pause taps
toggle cleanly.
Also fixes the native default pttButton ("volumeDown" -> "volume")
to match the Dart-side enum name and adds verbose KeyEvent logging
under the PTT tag.
Introduce RecorderService wrapping microphone capture (record pkg) and local playback (audioplayers pkg) for the PTT loopback POC: press records, release stops + plays the clip through the device speaker. PTTService drives the recorder lifecycle from its state transitions so every press/release path (system PTT, headset, on-screen, manual trigger) flows through one place. PTTService now pushes its full configuration to the native side at construction so Dart defaults and native defaults can never drift silently. Removes the setButton auto-switch that forced toggle mode on play/pause selection: the Android handler now forces toggle for media keycodes regardless of mode, so the user can keep hold mode for volume buttons without breaking play/pause taps. Adds the corresponding plugin registrant updates for linux, macos, and windows targets generated by flutter pub get.
Add PTTSystemManager wrapping iOS 16+ PTChannelManager so the user can opt into the system-level PushToTalk experience (works from the lock screen, surfaces in Control Center). Flutter calls joinPTTChannel / leavePTTChannel and the manager reports begin/end transmit back over the existing PTT method channel. AppDelegate now routes joinPTTChannel, leavePTTChannel, beginSystemPTTTransmit and stopSystemPTTTransmit method calls to the manager (gated on iOS 16+). Adds the Runner.entitlements file required by the PushToTalk framework.
Covers the state machine and configuration paths that were silently fragile before: - initial config push to native at construction (the regression that let Dart and native defaults drift, breaking the first press) - pttPressed / pttReleased state transitions driving the recorder - idempotent state transitions don't double-fire the recorder - setMode / setPreventScreenLock forward to native - setButton(playPause) preserves mode (regression test for the removed auto-switch — native now forces toggle for play/pause keycodes regardless of mode) - active recording is stopped when configuration changes - dispose tears down the recorder
CLAUDE.md and the PTT implementation docs still described Bluetooth headset button capture as the project's unsolved "major blocker" and described an outdated architecture (dispatchKeyEvent, MediaSessionCompat, MPRemoteCommandCenter-only). The current branch already implements a working solution on both platforms: a foreground Media3 MediaSessionService on Android and Apple's PushToTalk framework on iOS. - Rewrite .claude/CLAUDE.md to reflect the current architecture and status instead of the historical blocker framing - Rewrite docs/bluetooth-ptt-implementation.md to document the actual PttMediaSessionService / PTTSystemManager implementation and the remaining AVRCP protocol constraints (not bugs) - Update PTT_IMPLEMENTATION_SUMMARY.md's architecture section and future-enhancements list to match what's actually built - Replace the ad-hoc "# Working Roadmap.md" scratch file with ROADMAP.md: current status, confirmed protocol limitations, and a prioritized next-steps list (headset volume-button PTT via VolumeProvider, wiring PTT state to WebRTC audio, defaulting iOS to systemPTT, config persistence)
Design for wiring PTT state to WebRTC mic mute-gating over a persistent peer connection, a minimal club-BBB/7-group room model, and a LAN-first (STUN-only) 2-device test milestone. Establishes RideSession as the coordinator that supersedes the local loopback recorder.
…a group picker Extract the PTT->WebRTC sync out of CallScreen's build method into RideSession (muted by default, unmute on PTT hold), fixing the every-rebuild side-effect and wiring pre-existing-peer connection. Home screen now routes to the club BBB group picker. Also wrap the home body in a scroll view to fix a pre-existing layout overflow surfaced by the smoke test.
The Flutter tooling migrator added android.builtInKotlin=false and android.newDsl=false when building against the current SDK. Commit them so builds are reproducible across machines instead of re-migrating on each run.
Headset volume buttons never reached the app: with AVRCP absolute volume the headset sends SET_ABSOLUTE_VOLUME straight to the audio system, so no KeyEvent is ever generated and only the phone's physical volume keys worked. Claim remote device volume on the media session (the Media3 equivalent of a legacy VolumeProvider) so the framework delivers those steps to PttPlayer as increase/decrease callbacks instead. Volume is pinned to the middle of the range after each step, so the user's real media volume is never changed and there is always headroom in both directions. Remote volume is claimed only while the volume button is selected for PTT, via a shared PttConfig, so users driving PTT from headset play/pause keep normal system volume behaviour. AVRCP only ever reports discrete steps, never a down/up pair, so headset volume PTT is toggle-only by protocol. These arrive on a separate PttEventBus discrete channel and share MainActivity's single debounced toggleRecording() transition, keeping every input source indistinguishable downstream.
|
A local macOS build of the signaling server (Mach-O executable) had been committed. Remove it from the index and ignore the build output and coverage profile so they can't be committed again. Also apply gofmt -s to messages.go, the only unformatted file, ahead of formatting becoming a CI gate.
The signaling service is the live backend for PTT but had no tests, so a CI job for it would have been a hollow gate. Unit tests drive the hub handlers directly: joiners receive the existing peer list and existing peers are notified; switching and leaving rooms notifies the old room and removes empty rooms; unregistering closes the send channel without double-close panics; offers are forwarded only to a target in the same room (room isolation); broadcasts honour exclusions; a full send buffer drops instead of blocking the hub. A wire-format test pins the JSON field names the Flutter client depends on. Integration tests (build tag "integration") run the real HTTP handlers over real WebSocket connections: two riders in one group negotiate offer/answer/ICE with the server stamping the sender, PTT start/end reaches the group but not the talker or another group, disconnects notify the group, and PTT before joining or unknown message types are rejected.
ALLOWED_ORIGINS is documented as a list, but getEnvList returned the whole environment value as a single entry, so "https://a, https://b" became one bogus origin. Split on commas, trim whitespace, and drop empty entries, falling back to the default when nothing remains. Found by the new config tests, which also cover defaults, environment overrides, and fallback on malformed PORT/LOG_JSON values.
govulncheck reported GO-2026-6278 (weak PRNG for the WebSocket mask key) in gorilla/websocket v1.5.1, reachable from the client read/write pumps and the upgrade handler. Upgrade to the fixed v1.5.3; govulncheck now reports no vulnerabilities reachable from our code. Also move the Dockerfile builder from Go 1.21 to 1.27 so the shipped binary uses the same standard library that CI builds, tests, and vulnerability-scans.
Make the mobile code pass the stricter checks the CI pipeline enforces (dart format and flutter analyze --fatal-infos): - add missing @OverRide annotations on SignalingChannel / VoiceTransport implementations - replace deprecated Color.withOpacity with withValues(alpha:) and Switch.activeColor with activeThumbColor - add const constructors where suggested - format 7 files No behaviour change; all 20 tests pass.
The existing workflows never produced a green run: mobile CI derived Flutter from pubspec's lower bound (3.16 / Dart 3.2) and failed at pub get, the live signaling service had no job, and triggers only covered main and the deleted dev branch. Add one pipeline modelled on the tempsdarret.studio setup, sized to this repo: 1. Quality: dart format + flutter analyze --fatal-infos; go mod verify/tidy, gofmt, go vet 2. Build & Unit, in parallel: flutter tests with coverage; Android debug APK (compiles the Kotlin PTT layer); iOS no-codesign build (compiles the Swift PushToTalk layer); signaling build, race-enabled unit tests, container image 3. Integration: real WebSocket signaling flows 4. Security: CodeQL (Go and workflows), govulncheck, full-history gitleaks scan 5. CI Status: aggregate job that fails unless every gate succeeded, intended as the single required check on main Toolchains are pinned (Flutter 3.47.1, Go 1.27.x, Java 17). Runs on main and feat/fix/hotfix/chore/ci branches plus PRs into main, cancelling superseded runs. The one gitleaks finding in history, a TURN credential example inside a comment of the archived upstream webrtc demo, is reviewed and allowlisted.
Catch failures before they reach CI. Pre-commit runs only for the staged file types: dart format and flutter analyze for Dart, gofmt and go vet for Go. Pre-push runs the Flutter tests and the signaling unit and integration tests. Lefthook was chosen over husky because the repo has no Node toolchain.
Add docs/ci-pipeline.md: stage diagram, what each job checks with the command to reproduce it locally, toolchain pins and what to keep in sync, lefthook setup, what is deliberately not automated (headset E2E, Dart/Kotlin CodeQL, legacy server), and per-job troubleshooting. Update CLAUDE.md with the signaling test commands, CI/hook conventions, and mark the headset volume-button workaround as implemented rather than planned.
|
You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool. What Enabling Code Scanning Means:
For more information about GitHub Code Scanning, check out the documentation. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.




Summary
Changes
Core PTT Features
PTTButtonenum andPTTConfigurationclass for multi-button supportdispatchKeyEvent()on Android to intercept buttons before system handlersVolumeButtonObserveron iOS using KVO for volume button capturePTTServicewith configuration management and wakelock integrationUI
SettingsScreenwith mode selector, button selector, and platform tipsDocumentation
Test plan