docs: plan cible desktop macOS
This commit is contained in:
1 file changed
+147
@@ -0,0 +1,147 @@
|
|||||||
|
# Livrets — cible desktop macOS — Plan d'implémentation
|
||||||
|
|
||||||
|
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||||
|
|
||||||
|
**Goal:** Lancer l'app Livrets en natif sur macOS via `./gradlew :desktopApp:run`, sans toucher au code existant.
|
||||||
|
|
||||||
|
**Architecture:** Nouveau module hôte `desktopApp` (kotlin-jvm + Compose Multiplatform desktop) qui dépend de `:sharedUI` et ouvre `App(filesDirPath = ~/.livrets)` dans une fenêtre 480×800 — miroir d'`androidApp`.
|
||||||
|
|
||||||
|
**Tech Stack:** Kotlin 2.4.10, Compose Multiplatform 1.12.0 (desktop), JVM 17 bytecode (JDK 18 hôte).
|
||||||
|
|
||||||
|
**Spec:** `docs/superpowers/specs/2026-08-28-livrets-desktop-design.md`
|
||||||
|
|
||||||
|
## Global Constraints
|
||||||
|
|
||||||
|
- Zéro modification des modules existants (`sharedUI`, `androidApp`, `iosApp`) hormis `settings.gradle.kts` (+include) et `README.MD` (+section)
|
||||||
|
- UI texte français ; pas de commentaires dans le code ; YAGNI (pas de packaging, pas d'icône)
|
||||||
|
- Faisabilité déjà validée en sandbox sur cette machine (module, `:desktopApp:jar`, `:desktopApp:run` avec fenêtre visible)
|
||||||
|
- Tests régression : `./gradlew :sharedUI:jvmTest` (20/20) doit rester vert
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Task 1: Module desktopApp + lancement + README
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `settings.gradle.kts` (+include)
|
||||||
|
- Create: `desktopApp/build.gradle.kts`, `desktopApp/src/main/kotlin/com/livrets/desktop/Main.kt`
|
||||||
|
- Modify: `README.MD` (+section macOS desktop)
|
||||||
|
|
||||||
|
**Interfaces:**
|
||||||
|
- Consumes: `App(filesDirPath: String, onThemeChanged: @Composable (isDark: Boolean) -> Unit = {})` (App.kt existant — signature inchangée)
|
||||||
|
- Produces: point d'entrée desktop `com.livrets.desktop.MainKt` ; tâches `:desktopApp:run` / `:desktopApp:jar`
|
||||||
|
|
||||||
|
- [ ] **Step 1: Inclure le module et créer son build file**
|
||||||
|
|
||||||
|
Dans `settings.gradle.kts`, après la ligne `include(":androidApp")`, ajouter :
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
include(":desktopApp")
|
||||||
|
```
|
||||||
|
|
||||||
|
Créer `desktopApp/build.gradle.kts` :
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
alias(libs.plugins.kotlin.jvm)
|
||||||
|
alias(libs.plugins.compose.compiler)
|
||||||
|
alias(libs.plugins.compose.multiplatform)
|
||||||
|
}
|
||||||
|
|
||||||
|
java {
|
||||||
|
sourceCompatibility = JavaVersion.VERSION_17
|
||||||
|
targetCompatibility = JavaVersion.VERSION_17
|
||||||
|
}
|
||||||
|
|
||||||
|
kotlin {
|
||||||
|
compilerOptions { jvmTarget.set(JvmTarget.JVM_17) }
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation(project(":sharedUI"))
|
||||||
|
implementation(compose.desktop.currentOs)
|
||||||
|
}
|
||||||
|
|
||||||
|
compose.desktop {
|
||||||
|
application {
|
||||||
|
mainClass = "com.livrets.desktop.MainKt"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
(Les alias `kotlin-jvm`, `compose-compiler`, `compose-multiplatform` sont déjà déclarés `apply(false)` à la racine ; `compile.desktop.currentOs` se résout via le plugin compose-multiplatform, hors catalogue.)
|
||||||
|
|
||||||
|
- [ ] **Step 2: Créer le point d'entrée desktop**
|
||||||
|
|
||||||
|
Créer `desktopApp/src/main/kotlin/com/livrets/desktop/Main.kt` :
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
package com.livrets.desktop
|
||||||
|
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.window.Window
|
||||||
|
import androidx.compose.ui.window.application
|
||||||
|
import androidx.compose.ui.window.rememberWindowState
|
||||||
|
import com.livrets.App
|
||||||
|
|
||||||
|
fun main() = application {
|
||||||
|
Window(
|
||||||
|
onCloseRequest = ::exitApplication,
|
||||||
|
title = "Livrets",
|
||||||
|
state = rememberWindowState(width = 480.dp, height = 800.dp),
|
||||||
|
) {
|
||||||
|
App(filesDirPath = storageDir())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun storageDir(): String =
|
||||||
|
System.getProperty("user.home") + "/.livrets"
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 3: Vérifier la compilation**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./gradlew :desktopApp:jar :sharedUI:jvmTest
|
||||||
|
```
|
||||||
|
|
||||||
|
Attendu : `BUILD SUCCESSFUL`, 20/20 tests. (Si erreur « Inconsistent JVM Target Compatibility » : le fichier ci-dessus est déjà corrigé — vérifier que `java {}` ET `kotlin { jvmTarget }` sont bien les deux présents.)
|
||||||
|
|
||||||
|
- [ ] **Step 4: Ajouter la section desktop au README**
|
||||||
|
|
||||||
|
Dans `README.MD`, après la section `### iOS`, ajouter :
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
### macOS desktop
|
||||||
|
|
||||||
|
Lancer l'application en fenêtre (480×800) depuis le terminal :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./gradlew :desktopApp:run
|
||||||
|
```
|
||||||
|
|
||||||
|
Les données sont stockées dans `~/.livrets/`.
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 5: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add -A
|
||||||
|
git commit -m "feat: cible desktop macOS via :desktopApp:run"
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 6: Vérification du lancement (contrôleur ou utilisateur)**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./gradlew :desktopApp:run
|
||||||
|
```
|
||||||
|
|
||||||
|
Attendu : fenêtre « Livrets » 480×800, écran d'accueil avec les 3 réglages. Fermer la fenêtre arrête le processus. (Bloque jusqu'à fermeture — à lancer de façon interactive, pas dans la boucle de tests.)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Notes d'exécution
|
||||||
|
|
||||||
|
- Ne pas toucher à `sharedUI`/`androidApp`/`iosApp` — si `:desktopApp:jar` révèle une incompatibilité, rapporter BLOCKED avec la sortie exacte.
|
||||||
|
- `:desktopApp:run` est interactif (fenêtre bloquante) : la vérification automatisée = `:desktopApp:jar` + processus JVM vivant pendant un run en arrière-plan ; la confirmation visuelle finale revient à l'utilisateur.
|
||||||
|
- `~/.livrets` est créé à la première partie terminée (HistoryRepository.createDirectories) ; l'écran Historique affiche « Aucune partie enregistrée » avant.
|
||||||
Reference in new issue
Block a user