Chat notifications (production-ready)
- ChatDeeplinkService: resolves client chat ID from incoming push/WS payloads using the (senderId, chatId) matrix and switches selectedDeviceProvider when the payload references a different watch (multi-device deeplink)
- IncomingChatResolver in domain layer with full unit coverage of the 4-case matrix
- ChatContext provider (sealed: outsideChat / list / conversation) wired into ChatListScreen and ChatConversationScreen via initState/dispose to enable WhatsApp-style suppression
- notifications_init refactor: foreground CHAT_MESSAGE notifications are suppressed on chat list and matching conversation; tap navigation goes through ChatDeeplinkService
- ChatSyncService.subscribeToReconnect: reconciles from REST when the WebSocket comes back from a disconnect (recovers messages missed in background)
- 5s message-id dedup window in the WS listener (mitigates server-side duplicate chat-message-received events)
- Reconcile from remote on conversation mount (covers cached controller from background)
- AppBar refresh button + inverted pull-to-refresh in the conversation (overscroll either edge of the reverse list)
WS event parser fix
- chat-message-received normalises to chat_message_received; parser now accepts both that and chat_message so the conversation reactively refreshes when a watch sends a message
Chat application layer
- Split the conversation controller into services: chat_send_service, chat_sync_service, chat_participants_service, chat_permission_flow_service, chat_media_cleanup_service
- chat_conversation_config centralises page size, polling interval, dedup window
- chat_bubble_shell extracted; input bar split into smaller widgets
- emoji picker sheet + emoji blocking input formatter + watch_emoji_catalog
- Multipart upload header race fixed via synchronized.Lock around the shared Dio instance
Videocall (carryover from earlier work in this branch)
- Application services: incoming, outgoing, session
- Domain entities: VideocallIncomingArgs, VideocallRoom, VideocallUserId, parseDeviceIdFromRoom helper
- Views split: idle, incoming, active call, group call
- Widgets: picture_in_picture_video, remote_or_fallback_video, video_call_header
- videocall_config centralises timeouts, ringing duration, battery threshold
- Incoming via push (channel mode) with full-screen notification + ringtone
- Hangup-on-remote-left moved to controller; redirect on participant update documented
- treezor_token_interceptor: distinguish session expiry from operation-denied 401s
Localization & misc
- New keys for chat conversation, refresh, errors across en/es/de/fr/it/pt
- Location map: dispose ref-after-unmount fix; route history layer cleanup
- Legacy device view model: position update event handling
- AndroidManifest: notification channel + permissions for incoming-call full-screen intent
Phase 2 of multi-environment setup. Adds Firebase core, Crashlytics,
Analytics, Remote Config, Performance, Messaging and flutter_local_notifications,
plus full APNs configuration for iOS push.
- Wire setupFirebase(env) and setupNotifications() in initApp
- Add firebase_options for dev and staging via flutterfire (sf-platform-pre)
- Register google-services / firebase-perf / crashlytics gradle plugins
- Add per-flavor GoogleService-Info.plist with Build Phase script that
copies the right plist into the .app bundle based on \$CONFIGURATION
- Bump iOS deployment target 13.0 -> 15.0 (required by firebase_analytics)
- Pin flutter_local_notifications to ^19.4.2 (v20+ needs Dart SDK >=3.10)
- Add aps-environment to staging (development) and production entitlements;
development flavor intentionally excluded (no App Store Connect entry)
- Fix AppDelegate.swift to call super.application after forwarding to
AntelopAppDelegate, otherwise Firebase Messaging swizzling breaks and
the APNs token is never captured
- Crashlytics reports in all builds (debug + release) for early detection
- Tag analytics events with env user property per flavor
- App Check intentionally not included (debug-token friction with large
QA team); can be re-added release-only later