- Move PUSH_GATEWAY_URL from hardcoded constant to BuildConfig field,
read from PUSH_GATEWAY_URL env var at build time
- Hardcode keyAlias="release" and remove storeType (PKCS12 is default),
since these are fixed values in android-signing-env
- Remove unused okhttp3.Interceptor import
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- onMessageReceived now calls MatrixSession.getInstance() so the session
initializes and the sync loop starts in FCM-woken processes (the critical
missing piece — without this, a fresh process never ran any sync)
- Replace global lastSyncTimestamp with per-room lastMsgTsPerRoom persisted
in prefs as last_msg_ts; correctly identifies new messages after restart
regardless of room history size, without clock-skew issues
- Seed lastMsgTsPerRoom in processSyncResponse else branch on first login;
save to prefs in isFirstSync block and after every subsequent sync
- Fix deferred notification filter: use >= instead of > so messages whose
timestamp equals the stored value are included after key arrival
- Change notification title from room name to sender display name
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Local notifications:
- NotificationHelper posts per-room notifications from the sync loop
- Notifications suppressed when room is active (ChatScreen DisposableEffect)
- Deferred for encrypted rooms until room key arrives; fires with real body
- Notification tap navigates to the room via pendingRoomId StateFlow
- POST_NOTIFICATIONS permission requested at runtime (API 33+)
FCM push (app killed):
- MatrixFirebaseMessagingService handles token refresh and data messages
- Pusher registered with homeserver pointing to Cloudflare Worker gateway
- gateway/src/index.js: Cloudflare Worker forwards Matrix pushes to FCM v1 API
using a service-account JWT signed with Web Crypto
- last_sync_token persisted in SharedPreferences so restored sessions start with
an incremental sync and fire notifications immediately (fixes missed-on-wake bug)
- Default FCM notification channel declared in manifest
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Six interconnected fixes to make Olm/Megolm state persist correctly
across restarts:
- Fix OlmAccount/OlmSession unpickle argument order (data, key) — was
reversed, causing INVALID_BASE64 on every restore
- Fix pickle byte encoding: pickle() returns ByteArray, not StringBuffer;
encode/decode with ISO_8859_1
- Track publishedOtkCount in SharedPreferences to avoid evicting existing
OTKs on restore (only generate MAX - published new keys)
- Delay startSync() until after uploadKeys() on fresh login to avoid
concurrent OlmAccount access (race condition causing BAD_MESSAGE_KEY_ID)
- Persist encryptedRooms to SharedPreferences so rooms stay encrypted
across restarts
- Check m.room.encryption in both state and timeline events (server
returns it in timeline for rooms where encryption was enabled early)
Also adds SAS device verification UI, DM naming improvements, and
updates state.md with full architecture and debugging notes.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>