4.8 KiB
Adaptive Android shell
The single MainActivity is a FragmentActivity (a ComponentActivity subclass)
so AndroidX BiometricPrompt can retain its OS authentication fragment. Compose,
Hilt ViewModels, lifecycle-aware StateFlow collection, and Navigation 3 1.2.0
present the Rust-owned Home, Passwords, Search, TOTP, and Preferences pages.
The shell uses actual available window width: bottom navigation below 600 dp, and a scrollable navigation rail at larger widths. Passwords retains Material 3 Adaptive list/detail panes and the library's fold/hinge-aware directives. Live window changes recompute both layouts without replacing native handles or repository identities. Large text uses labelled navigation icons on compact windows, leaving accessible names and 48 dp or larger selectable touch targets. Page headings, selected tab semantics, radio groups, and keyboard activation use Compose semantics rather than display-string interpretation.
Navigation 3 renders each top-level root and Preferences' Appearance child. Each destination retains its own navigation: Rust owns Passwords' directory, entry, parent and revision; Preferences retains its child independently of tab switches. Home and TOTP have root stacks, and Search hands a typed result to Passwords. The TOTP root presents Rust shell availability; the TOTP list/detail workflow is assigned to #107, discovery to #110, and full preferences to #104.
SavedStateHandle stores only the selected tab, Appearance child flag, and Password directory/entry/revision identifiers. Navigation 3 deliberately has no saveable screen-content decorator. Search text, passphrases, editors, decrypted fields, codes, credentials and native handles never enter navigation saved state. Existing Rust process-recreated authentication starts locked and checks restored object revisions before opening an entry. Backgrounding does not renew a lease. Leaving Passwords invalidates pending operations, clears protected presentation, and revokes the lease without treating a tab switch as manual search-history clearing. Navigation cancels setup, Home and Search work before switching destinations and clears setup secrets before opening Appearance or another tab. Outgoing animated entries do not cancel work belonging to the incoming destination; sequence/revision checks reject late native results. Cleanup registrations use distinct owner tokens: removing a screen with the same surface callback cannot remove another screen's protection. The unchanged immediate memory-pressure masking assertion also covers setup destinations during screen replacement.
Appearance is read and written through Rust's existing mobile appearance API. The shell's only decision is translating System/Light/Dark into Material color schemes, using the OS preference for System. System-bar icon contrast follows the active Material background while the activity remains edge-to-edge. Failed operations preserve the last confirmed appearance. No Android preference store or domain policy is added.
Rust fixtures generate Loading, Empty, Ready, Locked, Error and Stale pages for all five destinations; no repository or secret is needed to exercise them. Tests cover initial async loading versus restored selection, stale completion rejection, all fixture pages, compact/expanded navigation, large text, keyboard activation, independent Preferences navigation and reconstruction from primitive saved state. The native encrypted-store fixture checks appearance persistence and locked restoration along with entry navigation and viewer operations.
Validation used ARM64 emulators on API 26 (4 KB), API 37 (4 KB), and API 37 (strict 16 KB), including app/core/bridge instrumentation and five cold starts per device. Both supported ARM ABIs passed release packaging, native linker, backup exclusion, architecture, dependency/license and SBOM gates. All four Rust workspace gates passed.
Computer use in Android Studio's embedded emulator verified portrait bottom navigation, landscape rail, Appearance navigation and light/dark/system changes. TalkBack focus and activation were observed on Search and Preferences; text at 160% with 520 dpi display scaling retained accessible controls. Accessibility, font and density settings were restored afterward. Instrumentation also exercises keyboard activation and expanded navigation with 200% text. TalkBack audio was not recorded; no fold-posture or desktop-window AVD was available, so those use the adaptive library's directives without a claim of device-specific validation. ARMv7 was built and packaged; the available live emulator images were ARM64.
The additive shared shell-state contract regenerated the hardened Swift bindings. The iPhone and dependent watch simulator targets built after XcodeGen generation; the iPhone app was installed over its existing container and computer use verified locked folder navigation. Existing biometric enrollment and app data were retained.