Commit graph

15 commits

Author SHA1 Message Date
37cbb816e5
Feature: Bring-style emoji & category icons for items
Every shopping item now gets a visual like in Bring: a product emoji on
a softly tinted category tile.

- ItemVisuals.kt: pure client-side classifier. German dictionary
  (~180 entries) maps item names to emoji + one of 13 categories
  (produce, drinks, bakery, dairy, meat&fish, frozen, pantry, sweets,
  household, drugstore, baby, pet, other), each with an accent color.
  Longest-keyword-first matching so compounds resolve to their most
  specific entry (Wassermelone is produce, not a drink); juice
  compounds (Apfelsaft, Orangensaft, ...) are listed explicitly because
  their fruit prefix is longer than 'saft'. Unknown items fall back to
  the generic cart on neutral grey. Works fully offline, nothing leaves
  the device.
- ListDetailScreen: emoji tile in every item row, emoji in the
  autocomplete suggestions dropdown, and a live emoji preview as the
  text field's leading icon while typing.
- ItemVisualsTest: longest-match priority, case/whitespace
  insensitivity, fallbacks, category coverage.

Verified: assembleDebug + unit tests green (JDK 21).
2026-08-22 10:16:37 +02:00
15b3f1071f
Fix: Android compile errors in AuthScreen and MainScreen preview
- AuthScreen.kt: FocusManager is imported from androidx.compose.ui.focus,
  not androidx.compose.ui.platform (only LocalFocusManager lives there).
  The fully-qualified platform.FocusManager parameter types therefore
  failed to resolve, cascading into the clearFocus() errors.
- MainScreen.kt: MitbringslTheme gained a required sessionManager
  parameter in 729865b; the leftover template preview now passes
  SessionManager(LocalContext.current).

Verified: ./gradlew compileDebugKotlin, assembleDebug and test all green.
Note: local builds must use JDK 21 (JAVA_HOME=/usr/lib/jvm/java-21-openjdk);
the system default JDK 26 breaks AGP's JdkImageTransform (jlink) on
android-36's core-for-system-modules.jar.
2026-08-22 10:00:42 +02:00
85c790ed23
Build: make Android build work behind restrictive proxies
- settings.gradle.kts: comment out the foojay-resolver-convention plugin.
  It tries to auto-download JDK toolchains from api.foojay.io, which fails
  with 503 behind restrictive proxies. Re-enable at home if you want
  auto-provisioning.
- app/build.gradle.kts: comment out jvmToolchain(17) for the same reason
  (triggers toolchain resolution -> foojay download). The build JDK 21
  plus compileOptions(source/target 17) achieves the same result locally.
- gradle-wrapper.properties: bump to gradle-9.6.1-all (matches the
  manually provided distribution).
- .gitignore: ignore .ssl-work/ (local corporate-CA truststore).
2026-08-06 11:43:03 +02:00
729865be78
Feature: Settings screen with account, theme, profile, reset + credits
Backend:
- New GET/PUT /api/me endpoint to read and update the authenticated
  user's profile (currently display_name). UserStore.UpdateDisplayName.
- Wired into the authed router.

App:
- New SettingsScreen + SettingsViewModel with five sections:
  * Account & Sync: login status, email, server URL, logout, connect.
  * Profile: edit display name (pushed to PUT /api/me when logged in).
  * Appearance: System / Light / Dark theme switch, persisted in
    SessionManager and applied via MitbringslTheme(sessionManager).
  * Data: 'Reset local data' wipes Room tables (server data kept).
  * About: version, 'Developed by Janik Dietz', and credits to
    GLM-5.2 + Gemini 3.6 Flash.
- Theme.kt now reads the user's theme preference (StateFlow) instead
  of only the system default; MainActivity passes SessionManager in.
- Navigation: new SettingsNavKey; settings gear icon in ListsScreen
  top bar; Settings links back to the Sync/Account screen.
- DTOs/API: UpdateMeRequestDto + getMe()/updateMe() for /api/me.
2026-08-06 10:39:12 +02:00
3f187f1ede
Feature: Server-driven auth method discovery + OIDC-only enforcement
Backend:
- New AUTH_PASSWORD_ENABLED flag (default true). When false, email/password
  registration and login return 403; the server enforces OIDC-only login.
- New OIDC_GENERIC_DISPLAY_NAME so the app can show 'Authentik'/'Keycloak'
  instead of a generic 'OIDC' label.
- New public endpoint GET /api/config returns which auth methods the
  server offers (password_enabled + per-provider OIDC capabilities).
  No auth required, so the login screen can query it before logging in.
- .env.example and docker-compose.yml expose the new env vars.

App:
- DTOs + MitbringslApi.getServerConfig() for /api/config.
- AuthViewModel: new 'connect' flow. The user enters the server URL,
  taps 'Verbinden', and the app fetches /api/config. The returned
  ServerAuthConfig drives which login options are shown:
    * password-only -> email/password form
    * OIDC-only     -> OIDC token form
    * both          -> toggle between the two
  If the server offers no method, a clear error is shown.
- AuthScreen: split into ConnectView (server URL) and LoginView (the
  login form matching the server's capabilities). The mode toggle only
  appears when the server offers more than one method.
2026-08-06 10:28:12 +02:00
b44bc8c3af
Fix: Critical sync, build and data-safety bugs in Android app
Sync engine (critical):
- SyncWorker now pulls server ops for EVERY tracked list, not just
  lists with pending local outbox ops. Previously remote edits on
  'quiet' lists (incl. shared/joined lists) never arrived.
- SyncWorker advances the local HLC with each incoming server op
  (tick(op.hlcTs)) so LWW is correct across devices with skewed
  clocks; previously a fast-clock device permanently won conflicts
  and a slow-clock device's own edits were silently rejected.
- Added missing 'list_create' branch in applyServerOpProjection.
- Use server hlc_ts for createdAt/updatedAt in projections so lists
  and items keep a stable order instead of jumping by sync time.
- Prune old synced op_log rows (deleteOldSynced) to bound growth.
- Added ListDao.getAllListIds() one-shot query for the pull loop.

Build / runtime (critical):
- Added proguard-rules.pro with keep rules for kotlinx.serialization
  serializers and Retrofit interfaces; release builds with R8 would
  otherwise crash with SerializationException on the first API call.
- Added network_security_config.xml allowing cleartext only to
  10.0.2.2/localhost so the debug build can reach the local backend
  (blocked by default on Android 9+).
- Manifest: disable default WorkManager initializer so Hilt's
  HiltWorkerFactory is used (otherwise SyncWorker can fail to
  instantiate); added ACCESS_NETWORK_STATE permission.

Data safety (critical/major):
- Removed fallbackToDestructiveMigration from DatabaseModule: in a
  local-first app a destructive migration on schema bump would wipe
  the source of truth. Provide explicit Migrations instead.
- ShoppingRepository: wrap every local projection write + op_log
  insert in db.withTransaction{} so a crash between them can no
  longer silently lose a pending sync op.
- ShoppingRepository: replace manual JSON string concatenation with
  kotlinx.serialization buildJsonObject; the old escapeJson did not
  handle tab/CR/control chars, producing malformed op payloads.
- Persist device clientId and clientSeq counter in SessionManager so
  they survive process restarts (idempotency stays stable per device).
- Trigger immediate + periodic sync after login/register/OIDC so
  users see their lists without waiting up to 15 minutes.

.gitignore: ignore desktop.ini and backend/.testbin.
2026-08-06 10:01:57 +02:00
97583340a4
Refactor: Require active server connection for sharing and joining lists
- ListDetailScreen: hide Share action icon when not connected to a server (isLoggedIn == false)
- ListsScreen: show informative prompt dialog if user attempts to join a list without active server connection
- ListDetailViewModel: expose sessionManager to check auth state cleanly
- ADB reinstall & launch verified 
2026-08-05 20:40:08 +02:00
69591df12a
Feature: Shared lists & Invite Code invitation mechanism
- Backend:
  - Migration 000002: add invite_code column to lists & list_members auto-population
  - ListStore: GetLists/GetList check owner_id & list_members; add GetInviteCode & JoinByInviteCode
  - HTTP API: add POST /api/lists/{id}/invite & POST /api/lists/join
- Android App:
  - DTOs & MitbringslApi: add JoinListRequestDto, InviteCodeResponseDto & endpoints
  - ListsScreen & ViewModel: add 'Liste beitreten' action button & dialog for entering invite code
  - ListDetailScreen & ViewModel: add 'Liste teilen' action icon in top bar with System Share Sheet
- ADB reinstall & launch verified 
2026-08-05 20:36:43 +02:00
47b24dfcdf
Feature: Self-Hosted Server URL configuration & Authentik OIDC support
- DynamicBaseUrlInterceptor: dynamically rewrites Retrofit HTTP requests to custom server URL
- SessionManager: persist custom server_url setting (e.g. https://mitbringsl.mydomain.com)
- AuthScreen & ViewModel: add Server URL chip & edit dialog + Authentik / OIDC login mode
- NetworkModule: inject SessionManager into DynamicBaseUrlInterceptor & AuthInterceptor
- ADB reinstall & launch verified 
2026-08-05 20:32:08 +02:00
04e5c55c2a
Fix: Resolve list selection crash & update to minimal flat app icon
- ListDetailViewModel & Screen: set listId safely via setListId() avoiding SavedStateHandle null crashes
- Navigation: pass listId = key.listId explicitly into ListDetailScreen
- App Icon: replace 3D icon with a clean, minimal flat line-art shopping bag & checkmark icon suited for Samsung One UI & stock Android adaptive icon masks
- ADB reinstall & launch verified 
2026-08-05 20:27:38 +02:00
b9f10b1a2e
Design: Add modern 3D vector shopping bag launcher icon resources
- Generate high-res 3D shopping bag icon with checkmark badge
- Populate mipmap densities (mdpi, hdpi, xhdpi, xxhdpi, xxxhdpi)
- Configure adaptive icon XML & dark blue background color
- Re-install via ADB verified 
2026-08-05 20:22:25 +02:00
a5ad5cd766
Refactor: Make account 100% optional, default to local-only mode
- SessionManager: return stable local_user ID when not logged in
- Navigation: start directly at ListsNavKey without requiring login
- ListsScreen: add 'Sync / Account' chip in top bar; lists work 100% locally by default
- AuthScreen: update text & add 'Zurück zu meinen Listen' button for returning to local mode
- ADB reinstall & launch verified 
2026-08-05 20:19:29 +02:00
a00db14cba
Phase F: NetworkMonitor, offline banner, README & architecture docs
- NetworkMonitor: ConnectivityState Flow using ConnectivityManager.NetworkCallback
- ListsScreen & ViewModel: live offline indicator banner when disconnected
- Documentation:
  - docs/ARCHITECTURE.md: system design & tech stack overview
  - docs/SYNC.md: HLC timestamping, op_log outbox & LWW projection specification
  - docs/API.md: REST API endpoint specification
  - README.md: quickstart guide for backend, docker compose & Android app
- Verification: backend & android test suites 100% green 
2026-08-05 20:14:04 +02:00
174aad535a
Android Phase D & E: Auth Screen, SyncEngine, Lists & Detail Screens
- Auth UI & Logic: AuthScreen (Login/Register), AuthViewModel, AuthRepository, SessionManager
- SyncEngine: HybridLogicalClock (client-side), SyncWorker (outbox drain + server cursor pull), SyncManager
- Repository Layer: ShoppingRepository for local-first Room mutations + op_log outbox queue
- Screens & UI: ListsScreen (list overview & creation dialog), ListDetailScreen (checked/open sectioning, autocomplete AddItemBar)
- Navigation: MainNavigation (AuthNavKey -> ListsNavKey -> ListDetailNavKey)
- Verification: ./gradlew assembleDebug & ./gradlew test green 
2026-08-05 20:12:28 +02:00
e44d645112
Android Phase D: Project foundation, Room DB, Retrofit API, Hilt
- Android CLI Setup: initialized empty-activity app (AGP 9.0, Kotlin 2.3.20)
- Version catalog: Compose BOM 2026.03.01, Material 3, Hilt 2.60.1, Room 2.7.2,
  Retrofit 2.11.0, OkHttp 4.12.0, WorkManager 2.10.2, Kotlinx Serialization
- Room Database (v1): ListEntity, ItemEntity, OpLogEntity
- Room DAOs: ListDao, ItemDao, OpLogDao with LWW upsert queries
- Network layer: MitbringslApi Retrofit interface + DTOs + AuthInterceptor
- Dependency Injection: DatabaseModule, NetworkModule, RepositoryModule, HiltAndroidApp
- Build verification: assembleDebug & test green 
2026-08-05 20:09:34 +02:00