Files
027089af56 Feat/local notifications (#262)
* chore: add flutter local notifications and flutter foreground task deps

* feat: add bridge notifications methods

* feat: add foreground service to keep notifications stream alive

* feat: add notification service and provider

* feat: add provider to store active chat for notification purposes

* feat: add active chat provider to store if we are in a chat screen

* feat: add active chat route observer to clear active chat on navigation

* feat: add use active chat hook to cancel notifications on active chat

* feat: use active chat hook on invite and chat screen

* feat: translate notifications messages in notification provider

* fix: improve notification system reliability and reduce duplicate state tracking (#271)

* fix: improve notification system reliability and reduce duplicate state tracking

- Simplify useActiveChat hook: remove duplicate set/clear that overlaps
  with ActiveChatRouteObserver, keep only lifecycle handling and
  notification cancellation
- Fix provider modification during widget build: defer
  ActiveChatRouteObserver state updates via Future.microtask
- Add error handling in _initializeAndListen with try/catch
- Wire up battery optimization exemption request after foreground
  service start
- Replace non-deterministic String.hashCode with SHA-256-based
  notification ID generation
- Remove unused RECEIVE_BOOT_COMPLETED permission from manifest
- Expand test coverage for disabled-mode foreground service,
  notification service, and deterministic ID generation

* fix: restore active chat tracking in useActiveChat hook with deferred provider updates

The hook's setActiveChat/clearActiveChat calls were removed in the previous
commit, breaking notification clearing — users received notifications for
the chat they were actively viewing.

Restore the calls but defer them via Future.microtask() to avoid Riverpod's
'provider modification during build' error. Add ref.mounted guards to the
ActiveChatNotifier to handle disposal edge cases.

* feat: improve notifications for multiple accounts (#272)

* fix: improve notification system reliability and reduce duplicate state tracking

- Simplify useActiveChat hook: remove duplicate set/clear that overlaps
  with ActiveChatRouteObserver, keep only lifecycle handling and
  notification cancellation
- Fix provider modification during widget build: defer
  ActiveChatRouteObserver state updates via Future.microtask
- Add error handling in _initializeAndListen with try/catch
- Wire up battery optimization exemption request after foreground
  service start
- Replace non-deterministic String.hashCode with SHA-256-based
  notification ID generation
- Remove unused RECEIVE_BOOT_COMPLETED permission from manifest
- Expand test coverage for disabled-mode foreground service,
  notification service, and deterministic ID generation

* feat: show receiver name in notifications when multiple accounts are logged in

When more than one account exists, notification titles include the
receiver's display name in parentheses (e.g. 'Alice (MyAccount)') so
users know which account the notification is for. Single-account users
see no change.

Closes #265

* feat: switch to correct account when notification is tapped

Include receiver pubkey in the notification payload so the tap handler
can switch to the correct account before navigating to the chat or
invite screen. Exposes a navigator key from Routes so navigation can
happen outside the widget tree.

* fix: use fresh account count per notification and JSON-encode payloads

- Fetch accounts on each notification instead of capturing count once at
  init, so multi-account display stays current when accounts change
- Replace pipe-delimited notification payload with JSON encoding to
  avoid misparse when groupId contains '|' characters
- Add validation and error handling for malformed payloads
- Expand tests for JSON payload format and edge cases

* fix: address review feedback and upgrade flutter_local_notifications to v20

- Upgrade flutter_local_notifications ^19.0.0 → ^20.1.0 (named params)
- Upgrade crypto ^3.0.6 → ^3.0.7
- Bump Java compatibility to 17 for v20 compatibility
- Guard _initializeAndListen against provider disposal with ref.mounted
- Change _initializeAndListen to void return (fire-and-forget)
- Make Future.microtask timing consistent in useActiveChat hook
- Add _initialized warning in cancelForGroup for consistency
- Remove non-essential comments in onRepeatEvent
- Use valid 64-char hex pubkeys in tests
- Fix uninitService test to assert on its own mock

* fix: await show, validate payloads strictly, use realistic test pubkeys

- Await notificationService.show in _handleNotificationUpdate so errors
  propagate to the stream's try/catch
- Wrap stream callback in try/catch to prevent unhandled async exceptions
- Reject unknown triggers and empty receiverPubkey in _handleNotificationTap
- Replace placeholder pubkeys (pk1/pk2) with valid 64-char hex strings
- Add tests for empty receiverPubkey and unknown trigger rejection

* test: improve notification coverage from 98.05% to 99.40%

- Add tests for handleNotificationUpdate (active chat skip, multi-account
  receiver name, DM/group formatting, correct pubkey forwarding)
- Add tests for requestPermission (null plugin, granted, denied, null result)
- Add tests for foregroundServiceProvider and notificationServiceProvider
- Fix uninitService test to use its own mock
- Add coverage exclusions for platform-gated code that requires Android
  runtime (providers, _initializeAndListen, _onNotificationTap,
  _navigateToNotificationTarget, _KeepAliveTaskHandler, static
  FlutterForegroundTask calls)
- Make handleNotificationUpdate @visibleForTesting for direct testing

---------

Co-authored-by: JeffG <202880+erskingardner@users.noreply.github.com>
2026-02-16 14:36:05 +01:00
..