Replace the placeholder iPhone screen with the native application shell and navigation language used by Gotcha.
Scope
Build a native tab bar with one navigation stack per tab: Home, Passwords, TOTP, and Preferences.
Follow Gotcha's established presentation conventions: UIKit navigation and table hierarchies, system symbols, disclosure rows, large/native titles where appropriate, pull-to-refresh, loading indicators, empty/error backgrounds, and system sheets/alerts. SwiftUI may be embedded for focused views where it reduces code without changing the interaction model.
Keep each tab's navigation history independent and restore the selected tab using storage-owned preference state where supported.
Extend the UniFFI boundary with view-ready records and commands from crates/storage; Swift owns only lifecycle, native controls, layout, focus, accessibility, and transient presentation state.
Cancel screen-scoped asynchronous work when its controller/view disappears and prevent stale results from replacing newer state.
Do not add a CLI command surface, command palette, subprocess launch, or direct password-store access.
Acceptance criteria
The iPhone app opens with four working native tabs and independent navigation stacks.
Loading, empty, ready, locked, and error states can be driven by deterministic Rust fixtures.
The visual and interaction conventions match the current Gotcha iPhone app rather than inventing a separate component system.
Swift contains no password-store traversal, parsing, Git, GPG, OTP, or persistence rules.
## Goal
Replace the placeholder iPhone screen with the native application shell and navigation language used by Gotcha.
## Scope
- Build a native tab bar with one navigation stack per tab: Home, Passwords, TOTP, and Preferences.
- Follow Gotcha's established presentation conventions: UIKit navigation and table hierarchies, system symbols, disclosure rows, large/native titles where appropriate, pull-to-refresh, loading indicators, empty/error backgrounds, and system sheets/alerts. SwiftUI may be embedded for focused views where it reduces code without changing the interaction model.
- Keep each tab's navigation history independent and restore the selected tab using storage-owned preference state where supported.
- Extend the UniFFI boundary with view-ready records and commands from `crates/storage`; Swift owns only lifecycle, native controls, layout, focus, accessibility, and transient presentation state.
- Cancel screen-scoped asynchronous work when its controller/view disappears and prevent stale results from replacing newer state.
- Do not add a CLI command surface, command palette, subprocess launch, or direct password-store access.
## Acceptance criteria
- The iPhone app opens with four working native tabs and independent navigation stacks.
- Loading, empty, ready, locked, and error states can be driven by deterministic Rust fixtures.
- The visual and interaction conventions match the current Gotcha iPhone app rather than inventing a separate component system.
- Swift contains no password-store traversal, parsing, Git, GPG, OTP, or persistence rules.
hugo
added this to the 04 - iPhone and Apple Watch apps milestone 2026-08-09 20:00:27 +00:00
Added storage-owned mobile shell state, selected-tab persistence, and deterministic loading/empty/ready/locked/error fixtures.
Added the mechanical UniFFI records and commands used by a native UIKit shell with four independent navigation stacks, native large titles/tables/system symbols/pull-to-refresh, accessibility, screen cancellation, and stale-result rejection.
Reused the existing IronStorage vault icon for the iPhone app and kept unfinished Watch/AutoFill targets out of this app build until their own issues.
Verified in isolation with cargo fmt --all -- --check; RUSTFLAGS="-D warnings" cargo check --workspace --all-targets; cargo clippy --workspace --all-targets -- -D warnings; cargo test --workspace; xcodegen generate; and an iPhone 17 Pro simulator build. Visually checked all four tabs in dark and light appearance and at the largest Dynamic Type size. A signed device build also succeeded and installed on the paired iPhone; automated launch was denied only because the device was locked.
Implemented in commit db89815.
- Added storage-owned mobile shell state, selected-tab persistence, and deterministic loading/empty/ready/locked/error fixtures.
- Added the mechanical UniFFI records and commands used by a native UIKit shell with four independent navigation stacks, native large titles/tables/system symbols/pull-to-refresh, accessibility, screen cancellation, and stale-result rejection.
- Reused the existing IronStorage vault icon for the iPhone app and kept unfinished Watch/AutoFill targets out of this app build until their own issues.
Verified in isolation with cargo fmt --all -- --check; RUSTFLAGS="-D warnings" cargo check --workspace --all-targets; cargo clippy --workspace --all-targets -- -D warnings; cargo test --workspace; xcodegen generate; and an iPhone 17 Pro simulator build. Visually checked all four tabs in dark and light appearance and at the largest Dynamic Type size. A signed device build also succeeded and installed on the paired iPhone; automated launch was denied only because the device was locked.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Goal
Replace the placeholder iPhone screen with the native application shell and navigation language used by Gotcha.
Scope
crates/storage; Swift owns only lifecycle, native controls, layout, focus, accessibility, and transient presentation state.Acceptance criteria
Implemented in commit
db89815.Verified in isolation with cargo fmt --all -- --check; RUSTFLAGS="-D warnings" cargo check --workspace --all-targets; cargo clippy --workspace --all-targets -- -D warnings; cargo test --workspace; xcodegen generate; and an iPhone 17 Pro simulator build. Visually checked all four tabs in dark and light appearance and at the largest Dynamic Type size. A signed device build also succeeded and installed on the paired iPhone; automated launch was denied only because the device was locked.