Phase 3 of docs/multiple-profiles.md. The startup screen learns to agree with the switch. The table that picks what to open is lifted out of the screen's remember into StartupChoice.resolve, where it can be read and tested, because its order was the whole decision and it was wrong in the one way a switch would hit: "!startWalletImmediately -> null" sat above "desiredWalletId != null", and nothing ever set the flag back to true. So after the first visit to the selector, every sign-in on that device landed on the selector instead of the profile it had just signed in. Two rows move: what a switch or a sign-in named goes above the user's earlier "show me the list", since it is the more specific instruction; and the single-identity row drops below it, since when both are set they name the same thing. The default is written. GlobalPrefs.getDefaultWallet has been read by startup since Phoenix and saved by nothing in this app, so a cold boot with two profiles was the selector every time with no memory of which one was open. setActiveIdentity now saves the id it activates -- every activation goes through it, startup for all three kinds and the two tails through startup -- so the default is always the profile most recently open. The two forget tails clear it, since the default is the one memory of an identity that would otherwise outlive it. Both writes are wrapped: a default that could not be recorded is a selector on the next boot, not a crash now. The screen reads the saved value as a default only when it names a wallet, which is the one thing left to decide at the call site. The startup screen's literals go to the catalogue, and "wallet" goes with them except in the one place a wallet is what is starting: "Starting wallet" is shown from StartupViewState.StartingBusiness, which only the branch with a wallet attached reaches, and stays. The rest become "Preparing profiles", "Opening profile", "Decrypting", "Loading preferences", "Unlock to continue" and "Could not load the profiles on this device"; the selector's title is "Choose a profile", and select_a_wallet goes. Tests: StartupChoiceTest in commonTest, one case per row and the two orderings this phase is for -- a desired id opens even after the user once asked for the list, and one identity with the list asked for still shows it. IdentitySwitchJvmTest gains the cold boot: activate A then B, and a fresh view model over the same directory resolves B without asking; forget the default, and it resolves nothing. Found on the way and recorded in the test: DataStoreManager caches the global preferences once per process, bound to whichever directory was current when the first test in the JVM asked -- the same trap the nsec plan recorded for user preferences -- so the test reads the default through the view model's own instance rather than one of its own. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Pulled-From: curated/curated@00fc996995
This is a Kotlin Multiplatform project targeting Android, iOS, Desktop (JVM).
-
/composeApp is for code that will be shared across your Compose Multiplatform applications. It contains several subfolders:
- commonMain is for code that’s common for all targets.
- Other folders are for Kotlin code that will be compiled for only the platform indicated in the folder name. For example, if you want to use Apple’s CoreCrypto for the iOS part of your Kotlin app, the iosMain folder would be the right place for such calls. Similarly, if you want to edit the Desktop (JVM) specific part, the jvmMain folder is the appropriate location.
-
/iosApp contains iOS applications. Even if you’re sharing your UI with Compose Multiplatform, you need this entry point for your iOS app. This is also where you should add SwiftUI code for your project.
Build and Run Android Application
To build and run the development version of the Android app, use the run configuration from the run widget in your IDE’s toolbar or build it directly from the terminal:
- on macOS/Linux
./gradlew :composeApp:assembleDebug - on Windows
.\gradlew.bat :composeApp:assembleDebug
Build and Run Desktop (JVM) Application
To build and run the development version of the desktop app, use the run configuration from the run widget in your IDE’s toolbar or run it directly from the terminal:
- on macOS/Linux
./gradlew :composeApp:run - on Windows
.\gradlew.bat :composeApp:run
Build and Run iOS Application
To build and run the development version of the iOS app, use the run configuration from the run widget in your IDE’s toolbar or open the /iosApp directory in Xcode and run it from there.
Learn more about Kotlin Multiplatform…