No description
Find a file
Bruno Deanoz 1b4cc475f9 design polish: bug fixes, token migration, a11y touch targets
- GlassSurface: derive shadow geometry from shape (pill/circle now curve correctly)
  new shape-aware kaizenShadow(stack, shape) overload in Shadow.kt
  drop cornerRadius parameter from GlassSurface and all 8 call sites

- EmptyHero: replace remember { LocalDateTime.now() } with produceState that
  re-emits on minute boundaries; clock no longer freezes on first composition

- ChatScreen + MeshBackground: skip blob layer + dither while LiveCallOverlay
  is up (renderBlobs flag); avoids two animated MeshBackgrounds compositing
  in parallel

- Color tokens: add KaizenSemanticColors.warning/warningDeep,
  KaizenNeutralWashes (idle/hover/selected), KaizenGlassTint
  (darkTop/darkBottom/lightTop/lightBottom)

- Migrate inline Color(0xFF...) literals to tokens in LiveCallOverlay,
  ChatScreen (version-skew banner), Sidebar (4x neutral washes),
  LoginScreen / PasswordUnlockDialog / SecuritySection (glass tints),
  GlassSurface (use KaizenGlassTint)

- New ui/theme/Spacing.kt: KaizenSpacing scale (xxs-xxl),
  KaizenTouch (minTouch/comfortable/hero), KaizenIconSize (xs-xl)

- Accessibility touch targets:
  Sidebar Settings/Logout 30 -> 44dp
  Sidebar New-Chat 34 -> 44dp
  Sidebar history kebab 28 -> 44dp
  ChatInput Plus/Tune/Mic/Send/Call/Stop 40 -> 48dp

- Remove no-op pointerInput(Unit) {} on KaizenOrb
- Expose SquircleShape.radius (val instead of private) so shadow can read it
2026-06-24 13:39:42 +02:00
app design polish: bug fixes, token migration, a11y touch targets 2026-06-24 13:39:42 +02:00
gradle feat: KaizenIcons system — Lucide base, full Material Icons migration 2026-06-22 14:11:34 +02:00
.gitignore Remove temporary bug screenshots + ignore bugs/ dir 2026-06-24 03:27:53 +02:00
build.gradle.kts feat: offline-first cache layer with Room 2026-06-21 12:50:46 +02:00
CLAUDE.md Update CLAUDE.md with ChatScreenViewModel architecture 2026-06-24 10:10:43 +02:00
DESIGN.md feat: design system v2 — P3 colors, squircle shapes, glass surfaces, multi-theme, motion tokens 2026-06-21 14:32:25 +02:00
gradle.properties feat: offline-first cache layer with Room 2026-06-21 12:50:46 +02:00
gradlew fix: set gradlew execute permission 2026-06-23 07:15:17 +02:00
gradlew.bat Initial commit - Kaizen App 2026-06-18 15:08:09 +02:00
LATER.md feat: wire chat to the real Kaizen backend (in-app login + streaming) 2026-06-19 01:04:55 +02:00
OFFLINE_CACHE_ADD.md feat: offline-first cache layer with Room 2026-06-21 12:50:46 +02:00
PASSKEY_PLAN.md docs: passkey registration plan (WebAuthn/FIDO2 via Credential Manager) 2026-06-23 01:53:04 +02:00
README.md feat: wire chat to the real Kaizen backend (in-app login + streaming) 2026-06-19 01:04:55 +02:00
settings.gradle.kts Initial commit - Kaizen App 2026-06-18 15:08:09 +02:00

Kaizen — Android

Native Android-App für Kaizen (Jetpack Compose + Kotlin). Kein WebView, kein Tauri.

Phase 1 — echtes Backend (aktiv)

Der Feel-Prototyp redet jetzt mit dem echten Kaizen-Backend — echte, gestreamte Antworten statt fakeReply. Die App ist deployment-agnostisch: ein Binary, das auf die offizielle Instanz ODER jeden Self-Host zeigt, über einen einheitlichen Authorization: Bearer-Contract. SaaS vs. Self-Host ist nur „welche Base-URL".

Drin:

  • In-App-Login (auth/LoginScreen.kt): Server-URL (Default = offizielle Instanz, editierbar = die „offiziell/Self-Host"-Adresse) + E-Mail + Passwort → POST {baseUrl}/api/v1/auth/tokenkzn_-Token. Kein Token-Copy-Paste.
  • Sichere Token-Ablage (net/SecureStore.kt): EncryptedSharedPreferences (AES-256-GCM, Schlüssel im Android-KeyStore/StrongBox) — der Token liegt nie im Klartext, auch nicht auf gerooteten Geräten.
  • Modell vom Server (net/SessionViewModel.kt): nach dem Login holt die App per GET /api/v1/me das vom Nutzer unter /settings/models gewählte Default-Modell — kein hartgecodetes Modell.
  • Echtes Streaming (net/KaizenApi.kt + net/StreamConsumer.kt): POST /api/v1/chat, liest den text/plain-Chunked-Stream inkrementell und strippt die Sentinels (Port von lib/chat/stream-consumer.ts aus dem Backend, JVM-unit-getestet).
  • Design + Haptik + Orb unverändert — nur die Datenquelle hat sich geändert.

Bewusst noch nicht drin (siehe LATER.md): Conversation-History vom Server, Passkey-Login nativ, Bild/Video, Biometric-Lock, WebSocket-Streaming.

Bauen & laufen

Wichtig: Auf dem echten S25 Ultra laufen lassen, nicht im Emulator — der Emulator kann keine echte Haptik, und genau die wollen wir fühlen.

  1. Projekt in Android Studio öffnen, Gradle syncen (neue Deps: OkHttp, kotlinx-serialization, security-crypto + INTERNET-Permission).
  2. S25 Ultra per Wireless Debugging oder USB verbinden.
  3. Run ▶ auf das Gerät → Login-Screen erscheint. Server-URL prüfen, einloggen.

DEFAULT_BASE_URL (net/ServerConfig.kt) ist die vorausgefüllte Instanz-Adresse — bei Domainwechsel hier anpassen.

Der Test

Eine Woche nutzen. Geht der Finger anfangen hierher statt zu Gemini → wir bauen voll aus (History, Passkey, Medien = Phase 2). Wenn nicht → wir wissen billig, woran's liegt.