The screen showed the quorum, the ladder and now the roster, but never named the member whose ceremony it was. Any member can open one and it settles the group's signing quorum for good, so who opened this one belongs on the screen that describes it — the same reason the chat notice names them. Alice started this ceremony. 2 of 3 members will be needed to sign with this key. It sits above the failure branch so it holds in every state. A ceremony that was abandoned or has already produced a key is still worth attributing: a member arriving at a finished ceremony they do not remember agreeing to should be able to see whose it was, and DkgSession.coordinatorPublicKey is kept for the life of the row either way. ## One naming rule, in one place HexKey.memberName() resolves a member's display name from the profiles joined onto the room, falling back to a shortened key. The roster switched to it, so the opener line and the rows below it cannot disagree about what to call somebody, and the chat notice's copy of the fallback went with it. This replaces a second private SHORTENED_PUBLIC_KEY_LENGTH I had added to ChatMessageListViewModel. A third still lives in SelectChatRoomTypeViewModel at a different value (12) and is deliberately untouched: that is a different choice about a different surface, not a duplicate of this one, and folding them together is a call about that screen rather than about this feature. ## Still reads a raw key on one surface The abandoned card shows DkgSession.failureReason verbatim, which for a ceremony ended by another member begins "Abandoned by 1a2b3c4d:" -- a truncated key where the chat line now shows a name. Naming them there needs the culprit stored beside the reason rather than inside it, which is a column on DkgSession and a schema version, so it is left as it is rather than parsed back out of the string. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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…