Skip to content

feat: handle app lifecycle events (Pause/Resume/Background/Foreground)#736

Open
TigerInYourDream wants to merge 2 commits intoproject-robius:mainfrom
TigerInYourDream:feat/app-lifecycle-events
Open

feat: handle app lifecycle events (Pause/Resume/Background/Foreground)#736
TigerInYourDream wants to merge 2 commits intoproject-robius:mainfrom
TigerInYourDream:feat/app-lifecycle-events

Conversation

@TigerInYourDream
Copy link
Contributor

@TigerInYourDream TigerInYourDream commented Feb 12, 2026

Summary

Implements app lifecycle event handling as described in #458. The app now properly saves/restores state and stops/starts the Matrix sync service when the OS suspends, backgrounds, or resumes the application.

This is especially important on Android, where the OS may pause or kill the app at any time. Previously, only Shutdown was handled — meaning state could be lost if the process was killed without a clean shutdown.

Changes

Single file modified: src/app.rs (+118 / -27 lines)

New lifecycle event handling

Replaced the monolithic if let Event::Shutdown block with a match on lifecycle events:

Event Action
Pause / Background Save window geometry + AppState, stop sync service
Foreground / Resume Restore state, restart sync service, full UI redraw
Shutdown Save everything including TSP wallet state (destructive)

New methods on App

  • save_lifecycle_state — Saves window geometry and AppState to persistent storage. Best-effort: continues saving remaining parts even if one fails.
  • save_all_state — Calls save_lifecycle_state + saves TSP wallet state. TSP save is destructive (close_and_serialize consumes TspState), so this is only called on Shutdown.
  • restore_all_state — Restores window geometry and AppState. Preserves the current logged_in flag to avoid overwriting it with a stale persisted value.

Deduplication via state_saved flag

A state_saved: bool field on App prevents redundant saves during the outgoing lifecycle sequence (Pause → Background → Shutdown) and gates restores so they only run after a save actually occurred.

Design Decisions

  1. TSP only on Shutdown: close_and_serialize() consumes ownership and tsp_init() uses OnceLock (one-time init), so TSP state cannot be round-tripped across Pause/Resume cycles.

  2. Idempotent sync service calls: SyncService::stop() and start() are idempotent, so calling them on both Pause+Background (or Resume+Foreground) is safe.

  3. Timeouts on all blocking async: All block_on_async_with_timeout calls use 2–3 second timeouts to stay well under Android's 5-second ANR limit.

  4. No platform-specific code: All lifecycle events are platform-agnostic Makepad Event variants — no #[cfg(target_os)] needed.

  5. Preserve logged_in on restore: The persisted AppState may contain a stale logged_in value, so we explicitly preserve the current runtime value after restoring.

Closes #458

TigerInYourDream and others added 2 commits February 12, 2026 17:14
Save and restore app state across lifecycle transitions to support
mobile platforms (especially Android) where the OS may suspend or
background the app at any time.

Key changes:
- Replace monolithic Shutdown handler with a match on lifecycle events
- On Pause/Background: save window geometry + AppState, stop sync service
- On Foreground/Resume: restore state, restart sync, trigger full redraw
- On Shutdown: save everything including TSP wallet (destructive, exit-only)
- Add `state_saved` flag to deduplicate saves and gate restores
- Factor save/restore logic into three methods on App:
  `save_lifecycle_state`, `save_all_state`, `restore_all_state`

Design notes:
- TSP's close_and_serialize() consumes ownership and tsp_init() uses
  OnceLock, so TSP state can only be saved on Shutdown (not Pause)
- SyncService stop()/start() are idempotent — safe to call repeatedly
- All blocking async calls use timeouts (2-3s) to avoid ANR on Android
- Preserves logged_in state on restore to avoid stale persisted values

Closes project-robius#458
@kevinaboos kevinaboos added the waiting-on-review This issue is waiting to be reviewed label Feb 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

waiting-on-review This issue is waiting to be reviewed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Handle app lifecycle events: Pause, Resume, etc

2 participants