Phase 8, item three. The tree had 51 previews and every one of them rendered one thing: a light theme, at whatever width the preview pane happened to be, at 100% text. That is the only condition under which this app has never had a defect. `@ConformancePreviews` replaces the bare `@Preview` at all 53 sites -- the two outside `ui/` included -- and renders each under five: light, dark, 200% text, compact 400dp, expanded 1000dp. `@Preview` is `@Repeatable`, so this is one annotation rather than five copied onto every preview and drifting apart. Each of the four new conditions is where a defect in this app has actually been: a colour that only fails in dark, a fixed-height container that clips at 200%, a layout that stretches because nothing held it, a row that reflows badly at phone width. It also gives phase 6 the check it could not make. "Every screen renders correctly at 400dp, 700dp, 1000dp, 1400dp and 1800dp" was verified structurally -- the measure applied at every root and asserted at those widths -- but never looked at per screen. Two of those widths are now one click away on every screen in the app. **High contrast is deliberately not in the annotation**, and the argument is worth stating because the omission looks like a gap. Contrast is a property of the *scheme*, not of a screen: the app declares six, `ColorSchemeContrastTest` measures every pair in all six, and a screen right in the default scheme is right in the high-contrast one by construction. Per-screen high-contrast previews would be 51 more renders of something already proved -- and there is no `@Preview` parameter for it in any case, since it needs `TorchTheme(contrast = …)` in the body. `ThemeGallery` covers them instead, once, over components rather than screens: all six schemes side by side, with body copy on surface, a card holding a list item -- the arrangement that rendered a headline at 1.00:1 before phase 3 -- and the three button emphases. `dynamicColor = false` on purpose, or an android 12+ preview paints all six columns from the wallpaper and the gallery shows nothing. It is the only place the medium and high contrast schemes can be seen at all: in the app they are reachable only through a platform setting, and on android only with dynamic colour off. 99 lines changed across 50 files, all of them one annotation and its import. 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…