# AGENTS.md ## Project MyIce — Kotlin Multiplatform ice hockey schedule/convocation viewer (Android, iOS, Desktop). Port of the Flutter app at `~/work/gitea.parano.ch/herel/myice/myice_mobile/`. ## Build Commands ```bash # Compile (desktop) ./gradlew composeApp:compileKotlinDesktop # Run desktop app ./gradlew composeApp:run # Tests (desktop target — KMP has no commonTest task) ./gradlew composeApp:desktopTest # Android debug APK ./gradlew composeApp:assembleDebug # Android release APK (requires keystore.properties at project root) ./gradlew composeApp:assembleRelease # macOS DMG ./gradlew composeApp:packageDistributionForCurrentOS ``` ## Lint / Typecheck There is no separate lint task. Compilation is the type check: ```bash ./gradlew composeApp:compileKotlinDesktop ``` ## Tech Stack - Kotlin 2.3.20, Compose Multiplatform 1.11.1, Material 3 - Ktor 3.5.1 (CIO on Android/Desktop, Darwin on iOS) - kotlinx.serialization 1.11.0 - multiplatform-settings 1.3.0 - lifecycle-viewmodel-compose 2.10.0 - Gradle 9.5.1, AGP 8.13.2 ## Architecture Layered: `models → network → cache → filter → viewmodel → ui` - **commonMain**: all shared code (models, networking, caching, filtering, viewmodels, UI) - **androidMain**: Android OAuth (Custom Tabs), MainActivity, CIO engine - **iosMain**: iOS OAuth (ASWebAuthenticationSession), MainViewController, Darwin engine - **desktopMain**: Desktop OAuth (local HTTP server), Main.kt, CIO engine Package: `ch.parano.myice` ## Conventions - Single `composeApp` module, shared UI approach (not per-platform UI) - French UI strings (matching the Flutter app) - TDD: write tests in `commonTest`, run via `desktopTest` target - `expect/actual` for platform-specific code (HttpClient engine, OAuth) - No comments in code unless explicitly requested - Follow existing file structure: one class per file, organized by layer ## Backend API at `https://myice.parano.ch` (hardcoded in `network/ApiConfig.kt`). Endpoints: `/login`, `/userinfo`, `/accounts`, `/schedule?account=`, `/game/{id}?account=` ## Secrets - `keystore.properties` and `*.keystore` are gitignored — never commit - OAuth tokens stored via multiplatform-settings (plaintext, same as Flutter app) ## License GPL-3.0-or-later. See [LICENSE](LICENSE). All source files include SPDX headers. ## Known Limitations - iOS `.xcodeproj` must be created manually in Xcode (Swift files exist in `iosApp/`) - ViewModels use `remember{}` instead of `viewModel()` (state lost on Android rotation) - No URL-decoding in token parser (JWT tokens don't need it) - `AuthViewModel.init()` logs out on any network error, not just 401