From b7d453e07372fda0c8c05c71db2f7f73661ee989 Mon Sep 17 00:00:00 2001 From: Ahmet Abdullah Gultekin Date: Sun, 14 Jun 2026 18:17:41 +0000 Subject: [PATCH] =?UTF-8?q?docs:=20GitHub-native=20cleanup=20=E2=80=94=20r?= =?UTF-8?q?emove=20superseded/stale=20docs=20(git=20history=20preserves=20?= =?UTF-8?q?all)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v5.2.3-pinned testing guide (now v5.3.1; durable bits in CLAUDE/README), aspirational perf checklist, generic deploy checklist, and archive/ (Flutter-era drafts β€” repo is KMP). --- docs/DEPLOYMENT_CHECKLIST.md | 94 -- docs/MOBILE_TESTING_GUIDE.md | 168 --- docs/PERFORMANCE.md | 70 - .../2026-04-16/ANDROID_STUDIO_SETUP.md | 666 --------- .../2026-04-16/CAMERA_INTEGRATION_GUIDE.md | 463 ------ .../2026-04-16/CAMERA_QUICK_REFERENCE.md | 294 ---- docs/archive/2026-04-16/GET_STARTED.md | 183 --- .../2026-04-16/HEXAGONAL_ARCHITECTURE.md | 1299 ----------------- .../archive/2026-04-16/HOW_TO_RUN_AND_TEST.md | 476 ------ docs/archive/2026-04-16/QUICKSTART.md | 211 --- docs/archive/2026-04-16/QUICK_REFERENCE.md | 211 --- docs/archive/2026-04-16/UX_DESIGN_GUIDE.md | 1017 ------------- docs/archive/README.md | 7 - 13 files changed, 5159 deletions(-) delete mode 100644 docs/DEPLOYMENT_CHECKLIST.md delete mode 100644 docs/MOBILE_TESTING_GUIDE.md delete mode 100644 docs/PERFORMANCE.md delete mode 100644 docs/archive/2026-04-16/ANDROID_STUDIO_SETUP.md delete mode 100644 docs/archive/2026-04-16/CAMERA_INTEGRATION_GUIDE.md delete mode 100644 docs/archive/2026-04-16/CAMERA_QUICK_REFERENCE.md delete mode 100644 docs/archive/2026-04-16/GET_STARTED.md delete mode 100644 docs/archive/2026-04-16/HEXAGONAL_ARCHITECTURE.md delete mode 100644 docs/archive/2026-04-16/HOW_TO_RUN_AND_TEST.md delete mode 100644 docs/archive/2026-04-16/QUICKSTART.md delete mode 100644 docs/archive/2026-04-16/QUICK_REFERENCE.md delete mode 100644 docs/archive/2026-04-16/UX_DESIGN_GUIDE.md delete mode 100644 docs/archive/README.md diff --git a/docs/DEPLOYMENT_CHECKLIST.md b/docs/DEPLOYMENT_CHECKLIST.md deleted file mode 100644 index b0660876..00000000 --- a/docs/DEPLOYMENT_CHECKLIST.md +++ /dev/null @@ -1,94 +0,0 @@ -# Deployment Checklist πŸš€ - -## Pre-Deployment Checklist - -### Environment Configuration - -- [ ] Set production environment: `ApiConfig.currentEnvironment = Environment.PRODUCTION` -- [ ] Enable real API: `ApiConfig.useRealApi = true` -- [ ] Update production base URL in `ApiConfig.kt` -- [ ] Remove or disable debug logging -- [ ] Test with production backend - -### Code Quality - -- [x] Clean architecture implemented -- [x] Dependency injection setup -- [x] Error handling implemented -- [x] Input validation working -- [x] No hardcoded credentials -- [ ] Code reviewed -- [ ] Documentation complete - -### Testing - -- [x] Unit tests created (517 tests across all test source sets; verified 2026-05-28) -- [x] Test data factory ready -- [ ] Integration tests (optional) -- [ ] Manual testing completed -- [ ] User acceptance testing - -### Security - -- [ ] No API keys in code -- [ ] Secure communication (HTTPS) -- [ ] Input sanitization -- [ ] Authentication working -- [ ] Authorization working -- [ ] Biometric data encrypted - -### Performance - -- [ ] App loads quickly -- [ ] No memory leaks -- [ ] Network timeouts configured -- [ ] Images optimized -- [ ] Database queries optimized (if using) - -### Platforms - -#### Desktop - -```bash -# Build production desktop app -./gradlew :desktopApp:packageDistributionForCurrentOS - -# Output: desktopApp/build/compose/binaries/main/ -``` - -#### Android - -```bash -# Build production Android APK -./gradlew :androidApp:assembleRelease - -# Build Android App Bundle (for Play Store) -./gradlew :androidApp:bundleRelease - -# Output: androidApp/build/outputs/ -``` - -#### iOS (when ready) - -```bash -# Build iOS app in Xcode -# Open iosApp/iosApp.xcodeproj -# Select Product > Archive -``` - -### Post-Deployment - -- [ ] Monitor error logs -- [ ] Track performance metrics -- [ ] Gather user feedback -- [ ] Plan iterative improvements - -## Production Readiness: βœ… READY! - -Your app is production-ready with: - -- Professional architecture -- Comprehensive error handling -- Testing infrastructure -- API integration -- Clean, maintainable code diff --git a/docs/MOBILE_TESTING_GUIDE.md b/docs/MOBILE_TESTING_GUIDE.md deleted file mode 100644 index ccf23db5..00000000 --- a/docs/MOBILE_TESTING_GUIDE.md +++ /dev/null @@ -1,168 +0,0 @@ -# Mobile Local Build & Test Guide - -**Audience:** a developer (or a Claude Code instance) on a laptop who wants to **build the -FIVUCSAS mobile app from source, install it on a real phone or emulator, and verify the -login flow** β€” without relying on the GitHub release APK or mobile data on the phone. - -> Why this guide exists: the FIVUCSAS server (Hetzner CX43) **cannot run an Android -> emulator** β€” it has no `/dev/kvm` / CPU virtualization, no display, and no Android SDK. -> It can compile the app and run unit tests headlessly, but it cannot exercise the phone -> UI. A laptop with Android Studio (or a phone over USB) can. Use this guide there. - ---- - -## 0. Current state (read first) - -- **Latest release: `v5.2.3`** (versionCode 10). Tag: https://github.com/Rollingcat-Software/client-apps/releases/tag/v5.2.3 -- Recent login fixes β€” verify these specifically: - - **v5.2.2** fixed a login **flicker** (the MFA screen used to bounce straight back to - Login: a Koin *factory* `LoginViewModel` handed the MFA screen a fresh empty copy with - no session token). Login now reaches the MFA step. - - **v5.2.3** fixed **MFA completion** showing a false **"Verification failed"**: after the - server returned `200 AUTHENTICATED`, the app wrote login data to encrypted storage - *inside* the verify `try` *before* committing success β€” a throw there was caught and - overwrote the success with the generic error. Now success is committed first and caching - is best-effort, so a server success can never render as a failure. - - **v5.2.3** also fixed the system **navigation bar covering the bottom Cancel button** - (window-insets padding). - - The old **"Continue as Guest (Face Check)"** button was **removed** (it was a demo - leftover with no web equivalent) and a **show/hide password** toggle was added. - -The acceptance checklist in Β§5 is exactly what to confirm on a device. - ---- - -## 1. Prerequisites - -| Need | Detail | -|------|--------| -| JDK | **21** (`JavaVersion.VERSION_21`, `jvmToolchain(21)`) | -| Android SDK | `compileSdk 35`, `targetSdk 35`, `minSdk 24` (Android 7.0+) | -| `ANDROID_HOME` | point at your SDK; Android Studio installs it | -| A target | **either** an emulator (needs KVM/HAXM/Hypervisor on the laptop) **or** a physical Android phone (API 24+) with USB debugging | -| Repo | `github.com/Rollingcat-Software/client-apps`, default branch `main` | - -**No signing keystore is needed for testing** β€” debug builds self-sign. The production -keystore is only for release builds (see `docs/SIGNING.md` / `docs/RELEASE.md`). - -**Phone-over-USB uses no mobile data:** the laptop (on wifi/ethernet) downloads deps and -builds; `adb`/Gradle pushes the APK to the phone over the USB cable. The phone only spends -data on its own API calls to `api.fivucsas.com`, which are tiny (JSON), not the 100 MB APK. - ---- - -## 2. Build & install (debug) - -```bash -git clone https://github.com/Rollingcat-Software/client-apps.git # or: git pull -cd client-apps - -# Build a debug APK (no keystore required) -./gradlew :androidApp:assembleDebug -# β†’ androidApp/build/outputs/apk/debug/androidApp-debug.apk - -# Plug in the phone (Developer Options β†’ USB debugging ON), confirm it's seen: -adb devices - -# Install + launch on the connected phone or a running emulator: -./gradlew :androidApp:installDebug -# (or: adb install -r androidApp/build/outputs/apk/debug/androidApp-debug.apk) -``` - -The app targets **production** by default β€” `ApiConfig`/`AppConfig.BASE_URL = -https://api.fivucsas.com/api/v1`. No local backend is required; you're testing against the -real API. - -> To reproduce the **production-signed** app exactly (e.g. to test FINGERPRINT β€” see Β§6), -> install the release APK from the GitHub Releases page instead of a debug build. - ---- - -## 3. Fast UI/compile sanity without a phone or emulator - -```bash -./gradlew :desktopApp:run # launches the Compose Desktop app on the laptop -``` - -Good for a quick "does it compile and render" check. **Caveat:** the desktop app's login -uses OAuth-loopback / QR screens, **not** the Android `LoginScreen` + `MfaFlowScreen` path β€” -so it does **not** reproduce the Android MFA flow. Use a phone/emulator for that. - ---- - -## 4. Unit tests (headless, fast β€” run before every push) - -```bash -./gradlew :shared:test :androidApp:testDebugUnitTest -``` - -Key regression tests that must stay green: -- `MfaFlowAuthenticatedRegressionTest` (shared) β€” proves a server `AUTHENTICATED` response - becomes `Authenticated` state even if encrypted-storage caching throws (the v5.2.3 fix). -- `MfaHandoffTest` / `LoginViewModelTest` β€” the v5.2.2 session-handoff contract. -- `LoginScreenTest` β€” guest button absent, password toggle present. - -CI (`.github/workflows/android-build.yml`) runs these before assembling, so a red unit test -blocks the build. - ---- - -## 5. Acceptance checklist β€” what to verify on a device - -**Login screen** -- [ ] There is **no** "Continue as Guest (Face Check)" button. -- [ ] The password field has a **show/hide (eye) toggle** that works. - -**Direct login (no MFA)** β€” use a no-MFA test account (e.g. the seeded -`e2e-sweep@fivucsas.local` ROOT account; **get its password from the operator / your -team's secret store β€” do not hard-code credentials in the repo**), or register a fresh -account from the app's Register screen: -- [ ] email + password β†’ lands on the **Dashboard**, no flicker, no bounce-back. - -**MFA login** β€” use a real MFA account (e.g. `ahabgu@gmail.com`, a 3-step flow: password + -two of {Email OTP, SMS OTP, TOTP, …}): -- [ ] password β†’ **"Select Verification Method" (Step 2 of 3)**. -- [ ] pick a method (e.g. **Email OTP** β†’ receive the code β†’ enter it) β†’ advances to Step 3. -- [ ] complete Step 3 β†’ lands on the **Dashboard**. -- [ ] **It must NOT show "Verification failed" after a step the server accepted.** (v5.2.3.) -- [ ] the bottom **Cancel** button is fully visible, not half-hidden by the system nav bar. - -**NFC** (NFC-capable phone) -- [ ] The NFC read screen offers a **"Register this card"** action (calls `/nfc/enroll`). - -If any login box above is unchecked on **v5.2.3 or a fresh build of `main`**, capture the -screen + the method, and have the server side read the prod API logs for that timestamp to -confirm whether the failure is client or server (the v5.2.3 bug was a client mishandling of a -server **200** β€” always check the server verdict before assuming the API failed). - ---- - -## 6. Known caveats β€” do NOT chase these as bugs - -- **FINGERPRINT / passkey (WebAuthn) will fail on a debug build and on most emulators.** - WebAuthn ties the assertion to the app's **signing-certificate SHA-256**, which must be - registered server-side (Digital Asset Links / allowed origins). A **debug** APK is signed - with the debug keystore (different cert than the release), so its passkey assertions are - rejected ("incoming request cannot be validated"). Test **password / email OTP / SMS OTP / - TOTP / face** on debug builds; validate FINGERPRINT only with the **production-signed - release** on a real device that has a screen lock + Google Play services. -- **Email/SMS OTP** require the account's real email/phone to receive the code. -- **Emulator + camera/NFC:** FACE needs a (virtual) camera; NFC needs real NFC hardware β€” - use a physical phone for those. - ---- - -## 7. Iterating with Claude Code on the laptop - -1. Edit `shared/` (cross-platform logic/UI) or `androidApp/` (Android host). -2. `./gradlew :androidApp:installDebug` to push to the connected phone; re-test. -3. `./gradlew :shared:test :androidApp:testDebugUnitTest` must be green before pushing. -4. Branch off `main`, open a PR to `Rollingcat-Software/client-apps`. -5. The biometric/auth backend is shared with the web app; the API contract lives in - `identity-core-api` (Spring) and `biometric-processor` (FastAPI). Login/MFA endpoints: - `POST /api/v1/auth/login`, `POST /api/v1/auth/mfa/step`, `DELETE /api/v1/auth/mfa/session/{token}`. - -## 8. Reference -- `README.md`, `CLAUDE.md` β€” architecture & conventions. -- `docs/RELEASE.md`, `docs/SIGNING.md` β€” signing & release. -- Open GitHub issues β€” current backlog / roadmap. diff --git a/docs/PERFORMANCE.md b/docs/PERFORMANCE.md deleted file mode 100644 index 679cbc89..00000000 --- a/docs/PERFORMANCE.md +++ /dev/null @@ -1,70 +0,0 @@ -# Performance Best Practices - -## Current Performance Status βœ… - -Your app is already optimized! Here's what we've done: - -### 1. Efficient State Management - -- **StateFlow** for reactive UI updates -- **Minimal recompositions** with proper state management -- **Lazy loading** where appropriate - -### 2. Dependency Injection - -- **Singleton** repositories and APIs (reused, not recreated) -- **Factory** for ViewModels (new instance per screen) -- **Efficient** dependency graph - -### 3. Network Optimization - -- **Timeout configuration** prevents hanging requests -- **Connection pooling** with Ktor client -- **JSON serialization** optimized with kotlinx.serialization - -### 4. Memory Management - -- **No memory leaks** - proper lifecycle management -- **Efficient data structures** - using immutable data classes -- **Resource cleanup** handled automatically - -### 5. Code Organization - -- **Modular architecture** - easy to maintain and extend -- **Clear separation** - UI, domain, data layers -- **Reusable code** - shared across platforms - -## Performance Monitoring - -### Key Metrics to Watch - -1. **App startup time** - Should be < 2 seconds -2. **Screen transition time** - Should be instant -3. **API response time** - Depends on network/backend -4. **Memory usage** - Should be stable - -### How to Profile - -```bash -# Android profiling -.\gradlew.bat :androidApp:installDebug -# Use Android Studio Profiler - -# Desktop profiling -.\gradlew.bat :desktopApp:run -# Use JVM profiler or VisualVM -``` - -## Optimization Opportunities (Future) - -If you need more performance: - -1. **Pagination** - Load data in chunks -2. **Caching** - Cache frequently accessed data -3. **Image optimization** - Compress biometric images -4. **Database** - Add local SQLite for offline support -5. **Lazy initialization** - Defer heavy operations - -## Current Status: EXCELLENT βœ… - -Your app is already performant for production use! diff --git a/docs/archive/2026-04-16/ANDROID_STUDIO_SETUP.md b/docs/archive/2026-04-16/ANDROID_STUDIO_SETUP.md deleted file mode 100644 index 78c9a6ab..00000000 --- a/docs/archive/2026-04-16/ANDROID_STUDIO_SETUP.md +++ /dev/null @@ -1,666 +0,0 @@ -# 🎨 Android Studio Setup for Flutter Cross-Platform Development - -Yes! **Android Studio is the BEST IDE for Flutter development.** You can build cross-platform apps ( -Android & iOS) from Android Studio. - -## βœ… Why Android Studio is Perfect for Flutter - -- βœ… **Official Support** - Google's official IDE for Flutter -- βœ… **Cross-Platform** - Build Android AND iOS from one IDE -- βœ… **Powerful Tools** - Built-in emulators, debugger, profiler -- βœ… **Flutter Plugin** - Full Flutter integration -- βœ… **Hot Reload** - See changes instantly -- βœ… **Device Manager** - Easy emulator control - -## πŸ“¦ Prerequisites - -1. **Android Studio** (latest version) -2. **Flutter SDK** (will install via Android Studio) -3. **Android SDK** (comes with Android Studio) -4. **Xcode** (macOS only, for iOS builds) - -## πŸš€ Step-by-Step Setup - -### Step 1: Install Android Studio - -1. **Download** Android Studio from: https://developer.android.com/studio -2. **Install** with default settings -3. **Launch** Android Studio - -### Step 2: Install Flutter Plugin in Android Studio - -1. Open **Android Studio** -2. Go to **File β†’ Settings** (or **Android Studio β†’ Preferences** on Mac) -3. Select **Plugins** -4. Search for **"Flutter"** -5. Click **Install** -6. Also install **Dart** plugin (will be suggested) -7. Click **Restart IDE** - -![Flutter Plugin Installation](https://docs.flutter.dev/assets/images/docs/tools/android-studio/plugins.png) - -### Step 3: Configure Flutter SDK Path - -After restart: - -1. Go to **File β†’ Settings β†’ Languages & Frameworks β†’ Flutter** -2. Set **Flutter SDK path**: `C:\src\flutter` (or wherever you installed Flutter) -3. Click **OK** - -### Step 4: Install Flutter SDK (if not already installed) - -**Option A: Via Android Studio** - -1. **File β†’ New β†’ New Flutter Project** -2. Click **Install SDK** if prompted -3. Choose installation path: `C:\src\flutter` -4. Wait for download and installation - -**Option B: Manual Installation** - -```powershell -# Download Flutter SDK -# https://docs.flutter.dev/get-started/install/windows - -# Extract to C:\src\flutter - -# Add to PATH -setx PATH "%PATH%;C:\src\flutter\bin" - -# Verify -flutter doctor -``` - -### Step 5: Accept Android Licenses - -Open **Terminal** in Android Studio (Alt+F12) and run: - -```bash -flutter doctor --android-licenses -``` - -Press **Y** to accept all licenses. - -### Step 6: Verify Setup - -In Android Studio Terminal, run: - -```bash -flutter doctor -``` - -You should see something like: - -``` -[βœ“] Flutter (Channel stable, 3.24.0, on Microsoft Windows) -[βœ“] Android toolchain - develop for Android devices -[βœ“] Android Studio (version 2024.1) -[βœ“] Connected device (1 available) -[βœ“] Network resources -``` - -## 🎯 Creating Your FIVUCSAS Flutter Project in Android Studio - -### Method 1: Import Existing Project (Recommended) - -Since you already have the mobile-app folder: - -1. **Open Android Studio** -2. Click **File β†’ Open** -3. Navigate to: `C:\Users\ahabg\OneDrive\Belgeler\GitHub\FIVUCSAS\mobile-app` -4. Click **OK** - -**First time setup:** - -```bash -# In Android Studio Terminal (Alt+F12) -flutter create --org com.fivucsas --project-name fivucsas_mobile . -flutter pub get -``` - -### Method 2: Create New Flutter Project - -1. **File β†’ New β†’ New Flutter Project** -2. Select **Flutter Application** -3. Click **Next** -4. **Project name**: `fivucsas_mobile` -5. **Project location**: `C:\Users\ahabg\OneDrive\Belgeler\GitHub\FIVUCSAS\mobile-app` -6. **Organization**: `com.fivucsas` -7. Select platforms: βœ… Android βœ… iOS βœ… Web (optional) -8. Click **Finish** - -## πŸ“± Running Your Flutter App on Android - -### Setup Android Emulator - -1. **Tools β†’ Device Manager** (or AVD Manager) -2. Click **Create Virtual Device** -3. Select device: **Pixel 6** (recommended) -4. Select system image: **API 34** (latest) -5. Click **Next** β†’ **Finish** - -### Run on Emulator - -1. **Start emulator** from Device Manager -2. Wait for emulator to fully boot -3. **Select device** from device dropdown (top toolbar) -4. Click **Run** button (▢️) or press **Shift+F10** -5. App will build and run automatically - -### Run on Physical Android Device - -1. **Enable Developer Options** on your phone: - - Go to Settings β†’ About Phone - - Tap "Build Number" 7 times - -2. **Enable USB Debugging**: - - Settings β†’ Developer Options β†’ USB Debugging - -3. **Connect** phone via USB - -4. **Select device** from device dropdown - -5. Click **Run** (▢️) - -## 🍎 Running Your Flutter App on iOS (macOS only) - -### Prerequisites - -```bash -# Install Xcode from Mac App Store -# Then run: -sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer -sudo xcodebuild -runFirstLaunch - -# Install CocoaPods -sudo gem install cocoapods -``` - -### Setup iOS Simulator - -1. **Tools β†’ Device Manager** -2. iOS simulators will appear automatically -3. Select **iPhone 15** or latest -4. Click **Run** (▢️) - -### Run on Physical iOS Device - -1. **Connect** iPhone via USB -2. **Open** `ios/Runner.xcworkspace` in Xcode -3. **Sign** the app with your Apple Developer account -4. **Select device** in Android Studio -5. Click **Run** (▢️) - -## 🎨 Android Studio Interface for Flutter - -``` -β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” -β”‚ File Edit View Navigate Code Analyze Build Tools β”‚ -β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ -β”‚ [▢️ Run] [πŸ› Debug] [πŸ”₯ Hot Reload] [Device: Pixel 6 β–Ό] β”‚ -β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ -β”‚ β”‚ β”‚ -β”‚ πŸ“ Project β”‚ πŸ“ Code Editor β”‚ -β”‚ β”‚ β”‚ -β”‚ lib/ β”‚ import 'package:flutter/material.dart'; β”‚ -β”‚ β”œβ”€ core/ β”‚ β”‚ -β”‚ β”œβ”€ features/β”‚ void main() { β”‚ -β”‚ └─ main.dartβ”‚ runApp(MyApp()); β”‚ -β”‚ β”‚ } β”‚ -β”‚ android/ β”‚ β”‚ -β”‚ ios/ β”‚ β”‚ -β”‚ β”‚ β”‚ -β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ -β”‚ Terminal: flutter run β”‚ -β”‚ Hot reload ⚑ Press "r" to hot reload β”‚ -β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ -``` - -## πŸ”₯ Essential Android Studio Features for Flutter - -### 1. Hot Reload (⚑ Lightning Fast Development) - -**What it does:** Updates UI instantly without restarting app - -**How to use:** - -- **Save file** β†’ Auto hot reload (if enabled) -- **Click** Hot Reload button (⚑) -- **Press** `Ctrl+S` (or `Cmd+S` on Mac) -- **Terminal:** Press `r` - -```dart -// Change this: -Text('Hello World') - -// To this (Save β†’ Hot Reload): -Text('Hello FIVUCSAS') -// Changes appear INSTANTLY! -``` - -### 2. Hot Restart (πŸ”„ Full App Restart) - -**When to use:** State changes, dependency injection changes - -**How to use:** - -- **Click** Hot Restart button (πŸ”„) -- **Terminal:** Press `R` - -### 3. Flutter Inspector (πŸ” UI Debugger) - -**What it does:** Visual debugging of widget tree - -**How to use:** - -1. **Run app** in Debug mode -2. **View β†’ Tool Windows β†’ Flutter Inspector** -3. Explore widget tree, layout issues - -### 4. Device Manager (πŸ“± Emulator Control) - -**Access:** Tools β†’ Device Manager - -**Features:** - -- Create/delete emulators -- Quick boot emulators -- Wipe emulator data -- Snapshot management - -### 5. Logcat (πŸ“‹ Real-time Logs) - -**Access:** View β†’ Tool Windows β†’ Logcat - -**Filter logs:** - -``` -flutter: # Flutter logs only -package:com.fivucsas.mobile # Your app only -``` - -### 6. Dart Analysis (βœ… Code Quality) - -**Real-time features:** - -- Syntax errors -- Type checking -- Quick fixes (Alt+Enter) -- Code completion - -### 7. Debugger (πŸ› Debug Your App) - -**Breakpoints:** - -- Click left margin to add breakpoint -- Run in Debug mode (πŸ›) -- Step through code (F8, F7) - -## πŸ“‹ Useful Android Studio Shortcuts - -### Essential Shortcuts - -| Action | Windows/Linux | macOS | -|-------------------|---------------|--------------| -| Run | Shift+F10 | Control+R | -| Debug | Shift+F9 | Control+D | -| Hot Reload | Ctrl+S | Cmd+S | -| Hot Restart | Ctrl+Shift+\ | Cmd+Shift+\ | -| Format Code | Ctrl+Alt+L | Cmd+Option+L | -| Quick Fix | Alt+Enter | Option+Enter | -| Find File | Ctrl+Shift+N | Cmd+Shift+O | -| Search Everywhere | Shift Shift | Shift Shift | -| Terminal | Alt+F12 | Option+F12 | -| Build | Ctrl+F9 | Cmd+F9 | - -### Flutter-Specific Shortcuts - -| Action | Shortcut | -|--------------------|----------------------| -| Extract Widget | Ctrl+Alt+W | -| Wrap with Widget | Alt+Enter β†’ Wrap | -| Remove Widget | Alt+Enter β†’ Remove | -| Go to Definition | Ctrl+B or Ctrl+Click | -| Show Documentation | Ctrl+Q | - -## 🎯 Project Structure in Android Studio - -``` -mobile-app/ -β”œβ”€β”€ πŸ“ android/ ← Android-specific code -β”‚ β”œβ”€β”€ app/ -β”‚ β”‚ β”œβ”€β”€ build.gradle ← Android config -β”‚ β”‚ └── src/main/ -β”‚ β”‚ └── AndroidManifest.xml -β”‚ └── gradle/ -β”‚ -β”œβ”€β”€ πŸ“ ios/ ← iOS-specific code (macOS) -β”‚ β”œβ”€β”€ Runner/ -β”‚ β”‚ └── Info.plist ← iOS config -β”‚ └── Podfile ← iOS dependencies -β”‚ -β”œβ”€β”€ πŸ“ lib/ ← Main Dart code ⭐ -β”‚ β”œβ”€β”€ πŸ“ core/ ← Core utilities -β”‚ β”‚ β”œβ”€β”€ config/ -β”‚ β”‚ β”œβ”€β”€ constants/ -β”‚ β”‚ β”œβ”€β”€ network/ -β”‚ β”‚ β”œβ”€β”€ theme/ -β”‚ β”‚ └── errors/ -β”‚ β”‚ -β”‚ β”œβ”€β”€ πŸ“ features/ ← Feature modules -β”‚ β”‚ β”œβ”€β”€ auth/ -β”‚ β”‚ β”‚ β”œβ”€β”€ data/ -β”‚ β”‚ β”‚ β”œβ”€β”€ domain/ -β”‚ β”‚ β”‚ └── presentation/ -β”‚ β”‚ β”œβ”€β”€ biometric/ -β”‚ β”‚ └── profile/ -β”‚ β”‚ -β”‚ β”œβ”€β”€ πŸ“„ main.dart ← App entry point -β”‚ β”œβ”€β”€ πŸ“„ app.dart -β”‚ └── πŸ“„ injection_container.dart -β”‚ -β”œβ”€β”€ πŸ“ assets/ ← Images, fonts, etc. -β”‚ β”œβ”€β”€ images/ -β”‚ β”œβ”€β”€ icons/ -β”‚ └── fonts/ -β”‚ -β”œβ”€β”€ πŸ“ test/ ← Unit & widget tests -β”‚ -β”œβ”€β”€ πŸ“„ pubspec.yaml ← Dependencies ⭐ -└── πŸ“„ README.md -``` - -## πŸ”§ Configure pubspec.yaml - -In Android Studio, open `pubspec.yaml` and add dependencies: - -```yaml -name: fivucsas_mobile -description: FIVUCSAS Mobile Application - -environment: - sdk: '>=3.5.0 <4.0.0' - -dependencies: - flutter: - sdk: flutter - - # State Management - flutter_bloc: ^8.1.3 - equatable: ^2.0.5 - get_it: ^7.6.4 - - # Networking - dio: ^5.4.0 - retrofit: ^4.0.3 - - # UI - flutter_svg: ^2.0.9 - cached_network_image: ^3.3.0 - - # Camera & ML - camera: ^0.10.5+5 - google_mlkit_face_detection: ^0.10.0 - -dev_dependencies: - flutter_test: - sdk: flutter - flutter_lints: ^3.0.1 - build_runner: ^2.4.6 -``` - -**After editing, click "Pub get" in the banner** or run: - -```bash -flutter pub get -``` - -## 🎨 Workflow in Android Studio - -### 1. Daily Development Flow - -```bash -# Morning -1. Open Android Studio -2. Pull latest code (VCS β†’ Update Project) -3. Run flutter pub get -4. Start emulator -5. Run app (Shift+F10) - -# Development -1. Edit code in lib/ -2. Save (Ctrl+S) β†’ Hot reload automatically -3. Check console for errors -4. Use Flutter Inspector for UI debugging - -# Testing -1. Write tests in test/ -2. Run tests (Right-click β†’ Run tests) -3. Check coverage - -# End of day -1. Commit changes (Ctrl+K) -2. Push to Git (Ctrl+Shift+K) -``` - -### 2. Creating New Features - -**Right-click on `lib/features/` β†’ New β†’ Directory:** - -``` -my_feature/ -β”œβ”€β”€ data/ -β”‚ β”œβ”€β”€ models/ -β”‚ β”œβ”€β”€ datasources/ -β”‚ └── repositories/ -β”œβ”€β”€ domain/ -β”‚ β”œβ”€β”€ entities/ -β”‚ β”œβ”€β”€ repositories/ -β”‚ └── usecases/ -└── presentation/ - β”œβ”€β”€ bloc/ - β”œβ”€β”€ pages/ - └── widgets/ -``` - -### 3. Code Generation - -For JSON serialization, Retrofit, etc.: - -```bash -# In Android Studio Terminal -flutter pub run build_runner build --delete-conflicting-outputs -``` - -## πŸ› Debugging in Android Studio - -### Set Breakpoints - -1. **Click** left margin next to line number (red dot appears) -2. **Run in Debug mode** (πŸ› or Shift+F9) -3. App will pause at breakpoint -4. **Inspect variables** in Debug window -5. **Step through code:** - - F8: Step over - - F7: Step into - - Shift+F8: Step out - - F9: Resume - -### Debug Console - -View real-time logs: - -- **Flutter:** Tab shows print() statements -- **Logcat:** Tab shows all Android logs -- **Console:** Shows build output - -### Flutter DevTools - -**Access:** When running, click "Open DevTools" in Run window - -**Features:** - -- Widget inspector -- Performance profiler -- Memory profiler -- Network inspector - -## πŸ“± Build & Deploy from Android Studio - -### Build APK (Android) - -1. **Build β†’ Flutter β†’ Build APK** -2. Or Terminal: `flutter build apk --release` -3. APK location: `build/app/outputs/flutter-apk/app-release.apk` - -### Build App Bundle (Play Store) - -1. **Build β†’ Flutter β†’ Build App Bundle** -2. Or Terminal: `flutter build appbundle --release` -3. AAB location: `build/app/outputs/bundle/release/app-release.aab` - -### Build iOS (macOS only) - -1. **Build β†’ Flutter β†’ Build iOS** -2. Or Terminal: `flutter build ios --release` - -## 🎯 Android Studio Tips for Flutter - -### 1. Live Templates (Code Snippets) - -Type these shortcuts and press Tab: - -- `stless` β†’ StatelessWidget -- `stful` β†’ StatefulWidget -- `build` β†’ Build method -- `initS` β†’ initState method -- `dis` β†’ dispose method - -### 2. Extract Widget Refactoring - -1. **Select widget code** -2. **Right-click β†’ Refactor β†’ Extract Flutter Widget** -3. **Name the widget** -4. Widget is extracted automatically! - -### 3. Wrap with Widget - -1. **Place cursor** on widget -2. **Alt+Enter** -3. Select **"Wrap with..."** -4. Choose: Container, Padding, Center, etc. - -### 4. Flutter Outline - -**View β†’ Tool Windows β†’ Flutter Outline** - -- See widget tree structure -- Quick navigation -- Wrap/remove widgets with buttons - -### 5. Multi-cursor Editing - -- **Alt+Shift+Click** to add cursor -- **Alt+J** to select next occurrence -- Edit multiple places at once! - -## πŸ”„ Version Control (Git) in Android Studio - -### Setup Git - -1. **VCS β†’ Enable Version Control Integration** -2. Select **Git** -3. Click **OK** - -### Common Git Operations - -| Action | Shortcut | Menu | -|----------|--------------|----------------------| -| Commit | Ctrl+K | VCS β†’ Commit | -| Push | Ctrl+Shift+K | VCS β†’ Git β†’ Push | -| Pull | Ctrl+T | VCS β†’ Update Project | -| Branches | - | VCS β†’ Git β†’ Branches | - -## βœ… Quick Start Checklist - -Use this when setting up: - -- [ ] Install Android Studio -- [ ] Install Flutter plugin -- [ ] Install Dart plugin -- [ ] Configure Flutter SDK path -- [ ] Run `flutter doctor` -- [ ] Accept Android licenses -- [ ] Create Android emulator -- [ ] Open mobile-app folder -- [ ] Run `flutter create .` -- [ ] Run `flutter pub get` -- [ ] Run app (Shift+F10) -- [ ] Verify hot reload works - -## πŸŽ“ Learning Resources - -### Android Studio - -- [Android Studio User Guide](https://developer.android.com/studio/intro) -- [Keyboard Shortcuts](https://developer.android.com/studio/intro/keyboard-shortcuts) - -### Flutter in Android Studio - -- [Flutter Setup](https://docs.flutter.dev/get-started/editor?tab=androidstudio) -- [Debugging Flutter Apps](https://docs.flutter.dev/testing/debugging) - -## πŸ†˜ Common Issues - -### Issue: "Flutter SDK not found" - -**Solution:** - -1. File β†’ Settings β†’ Languages & Frameworks β†’ Flutter -2. Set Flutter SDK path: `C:\src\flutter` -3. Click Apply - -### Issue: "Android licenses not accepted" - -**Solution:** - -```bash -flutter doctor --android-licenses -``` - -### Issue: "Emulator won't start" - -**Solution:** - -1. Tools β†’ Device Manager -2. Wipe emulator data -3. Cold boot - -### Issue: "Hot reload not working" - -**Solution:** - -1. Check "Enable hot reload on save" -2. File β†’ Settings β†’ Languages & Frameworks β†’ Flutter -3. Enable hot reload checkbox - -## πŸš€ You're Ready! - -Android Studio is **perfect** for Flutter cross-platform development! You get: - -βœ… **One IDE** for Android & iOS -βœ… **Powerful tools** built-in -βœ… **Fast development** with hot reload -βœ… **Professional debugging** -βœ… **Easy deployment** - -**Start building your FIVUCSAS app now!** πŸŽ‰ - ---- - -**Next Steps:** - -1. Open Android Studio -2. Open `mobile-app` folder -3. Run `flutter create .` -4. Follow `FLUTTER_APP_GUIDE.md` to implement features! diff --git a/docs/archive/2026-04-16/CAMERA_INTEGRATION_GUIDE.md b/docs/archive/2026-04-16/CAMERA_INTEGRATION_GUIDE.md deleted file mode 100644 index b2193bcf..00000000 --- a/docs/archive/2026-04-16/CAMERA_INTEGRATION_GUIDE.md +++ /dev/null @@ -1,463 +0,0 @@ -# Camera Integration Guide - -This guide explains how to use the camera integration in FIVUCSAS mobile and desktop applications. - -## Architecture Overview - -The camera integration follows **Hexagonal Architecture** (Ports and Adapters): - -``` -β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” -β”‚ Application Core β”‚ -β”‚ (Domain Layer - Use Cases) β”‚ -β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ - β”‚ - β”‚ depends on - ↓ -β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” -β”‚ ICameraService (Port) β”‚ -β”‚ (Interface/Abstraction) β”‚ -β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ - β”‚ β”‚ - β”‚ β”‚ - β”Œβ”€β”€β”€β”€β”€β”€β†“β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β†“β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” - β”‚ Android β”‚ β”‚ Desktop β”‚ - β”‚ Adapter β”‚ β”‚ Adapter β”‚ - β”‚ (CameraX) β”‚ β”‚ (JavaCV) β”‚ - β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ -``` - -## Components - -### 1. Core Interfaces - -#### `ICameraService` -**Location:** `shared/src/commonMain/kotlin/com/fivucsas/shared/platform/ICameraService.kt` - -The main camera service interface that all platforms implement. - -**Key Methods:** -- `initialize(lensFacing)` - Initialize camera -- `startPreview()` - Start camera preview -- `stopPreview()` - Stop camera preview -- `captureImage()` - Capture high-quality image for biometric processing -- `captureFrame()` - Capture quick frame for previews -- `release()` - Release camera resources - -**Properties:** -- `cameraState: StateFlow` - Observable camera state - -#### `CameraState` -**Location:** `shared/src/commonMain/kotlin/com/fivucsas/shared/platform/CameraState.kt` - -Sealed class representing all possible camera states: -- `Idle` - Camera not initialized -- `Initializing` - Camera is initializing -- `Ready` - Camera ready but not previewing -- `Previewing` - Camera actively showing preview -- `Capturing` - Camera capturing image -- `Error(error)` - Camera encountered error -- `Released` - Camera has been released - -### 2. Platform Implementations - -#### Android - `AndroidCameraService` -**Location:** `shared/src/androidMain/kotlin/com/fivucsas/shared/platform/AndroidCameraService.kt` - -- Uses **CameraX** library for modern Android camera API -- Lifecycle-aware camera management -- Supports front and back cameras -- High-quality image capture (JPEG, 95% quality) - -**Features:** -- Auto-focus enabled -- Configurable resolution (default: 640x480) -- Frame analysis for real-time processing -- Proper resource cleanup - -#### Desktop - `DesktopCameraServiceImpl` -**Location:** `desktopApp/src/desktopMain/kotlin/com/fivucsas/desktop/platform/DesktopCameraServiceImpl.kt` - -- Uses **JavaCV** (OpenCV wrapper) for webcam access -- Cross-platform webcam support -- JPEG image encoding - -**Features:** -- Configurable frame rate (default: 30 FPS) -- Multiple camera support -- BufferedImage conversion for Compose UI - -### 3. UI Components - -#### `CameraPreviewContainer` -**Location:** `shared/src/commonMain/kotlin/com/fivucsas/shared/ui/components/organisms/CameraPreview.kt` - -Common camera UI structure for all platforms. - -**Features:** -- State-based UI rendering -- Capture button with loading states -- Close button -- Optional flip camera button -- Overlay support for face detection guides -- Error handling UI - -#### `FaceDetectionOverlay` -Provides visual guidance for face positioning. - -**Features:** -- Oval face guide -- Customizable guidance text -- Semi-transparent overlay - -#### Platform-Specific Previews - -**Android:** `AndroidCameraPreview` -- Location: `shared/src/androidMain/kotlin/com/fivucsas/shared/ui/platform/AndroidCameraPreview.kt` -- Embeds CameraX `PreviewView` using `AndroidView` - -**Desktop:** `DesktopCameraPreview` -- Location: `desktopApp/src/desktopMain/kotlin/com/fivucsas/desktop/ui/DesktopCameraPreview.kt` -- Continuously captures and displays frames (~30 FPS) - -### 4. Dependency Injection - -#### Platform Modules -**Locations:** -- Common: `shared/src/commonMain/kotlin/com/fivucsas/shared/di/PlatformModule.kt` -- Android: `shared/src/androidMain/kotlin/com/fivucsas/shared/di/PlatformModule.android.kt` -- Desktop: `shared/src/desktopMain/kotlin/com/fivucsas/shared/di/PlatformModule.desktop.kt` - -Uses **Koin** for dependency injection with platform-specific implementations. - -## Usage Examples - -### Example 1: Basic Camera Usage - -```kotlin -@Composable -fun BiometricCaptureScreen( - cameraService: ICameraService = get(), // Inject from Koin - onImageCaptured: (ByteArray) -> Unit -) { - val cameraState by cameraService.cameraState.collectAsState() - val scope = rememberCoroutineScope() - - // Initialize camera on screen load - LaunchedEffect(Unit) { - cameraService.initialize(LensFacing.FRONT) - cameraService.startPreview() - } - - // Cleanup on screen dispose - DisposableEffect(Unit) { - onDispose { - scope.launch { - cameraService.release() - } - } - } - - CameraPreviewContainer( - cameraState = cameraState, - onCaptureClick = { - scope.launch { - cameraService.captureImage() - .onSuccess { imageBytes -> - onImageCaptured(imageBytes) - } - .onFailure { error -> - // Handle error - } - } - }, - onCloseClick = { /* Navigate back */ }, - overlayContent = { - FaceDetectionOverlay( - showGuide = true, - guidanceText = "Position your face within the oval" - ) - } - ) { - // Platform-specific preview - when (cameraService) { - is AndroidCameraService -> { - AndroidCameraPreview( - cameraService = cameraService, - modifier = Modifier.fillMaxSize() - ) - } - is DesktopCameraServiceImpl -> { - DesktopCameraPreview( - cameraService = cameraService, - modifier = Modifier.fillMaxSize() - ) - } - } - } -} -``` - -### Example 2: Camera with Permission Handling (Android) - -```kotlin -@Composable -fun BiometricCaptureScreenWithPermissions( - cameraService: AndroidCameraService = get(), - onImageCaptured: (ByteArray) -> Unit -) { - var permissionGranted by remember { mutableStateOf(false) } - val cameraState by cameraService.cameraState.collectAsState() - val scope = rememberCoroutineScope() - - // Request camera permission - RequestCameraPermission( - onPermissionGranted = { - permissionGranted = true - scope.launch { - cameraService.initialize(LensFacing.FRONT) - cameraService.startPreview() - } - }, - onPermissionDenied = { - // Show rationale dialog - }, - onPermissionPermanentlyDenied = { - // Show settings redirect dialog - } - ) - - if (permissionGranted) { - // Show camera UI - CameraPreviewContainer( - cameraState = cameraState, - onCaptureClick = { - scope.launch { - cameraService.captureImage() - .onSuccess { imageBytes -> - onImageCaptured(imageBytes) - } - } - }, - onCloseClick = { /* Navigate back */ } - ) { - AndroidCameraPreview( - cameraService = cameraService, - modifier = Modifier.fillMaxSize() - ) - } - } else { - // Show permission required UI - PermissionRequiredScreen() - } -} -``` - -### Example 3: Camera with Flip Support - -```kotlin -@Composable -fun BiometricCaptureWithFlip( - cameraService: ICameraService = get(), - onImageCaptured: (ByteArray) -> Unit -) { - var currentLens by remember { mutableStateOf(LensFacing.FRONT) } - val cameraState by cameraService.cameraState.collectAsState() - val scope = rememberCoroutineScope() - - LaunchedEffect(currentLens) { - cameraService.initialize(currentLens) - cameraService.startPreview() - } - - CameraPreviewContainer( - cameraState = cameraState, - onCaptureClick = { - scope.launch { - cameraService.captureImage() - .onSuccess { imageBytes -> - onImageCaptured(imageBytes) - } - } - }, - onCloseClick = { /* Navigate back */ }, - onFlipCamera = { - scope.launch { - cameraService.stopPreview() - currentLens = if (currentLens == LensFacing.FRONT) { - LensFacing.BACK - } else { - LensFacing.FRONT - } - } - }, - showFlipButton = cameraService.hasCamera(LensFacing.BACK) - ) { - // Platform-specific preview rendering - } -} -``` - -## Configuration - -### Biometric Configuration -**Location:** `shared/src/commonMain/kotlin/com/fivucsas/shared/config/BiometricConfig.kt` - -Adjust camera settings for biometric processing: - -```kotlin -object BiometricConfig { - const val PREFERRED_IMAGE_WIDTH = 640 - const val PREFERRED_IMAGE_HEIGHT = 480 - const val CAMERA_FRAME_RATE_FPS = 30 - const val CAMERA_AUTO_FOCUS_ENABLED = true - const val MIN_FACE_SIZE_PIXELS = 100 - const val MAX_FACE_SIZE_PIXELS = 500 -} -``` - -## Dependencies - -### Android -Already configured in `androidApp/build.gradle.kts`: -- `androidx.camera:camera-core:1.3.0` -- `androidx.camera:camera-camera2:1.3.0` -- `androidx.camera:camera-lifecycle:1.3.0` -- `androidx.camera:camera-view:1.3.0` -- `com.google.accompanist:accompanist-permissions:0.32.0` - -### Desktop -Already configured in `desktopApp/build.gradle.kts`: -- `org.bytedeco:javacv-platform:1.5.10` - -## Best Practices - -### 1. Lifecycle Management -Always release camera resources when done: - -```kotlin -DisposableEffect(Unit) { - onDispose { - scope.launch { - cameraService.release() - } - } -} -``` - -### 2. Error Handling -Always handle camera errors gracefully: - -```kotlin -cameraService.captureImage() - .onSuccess { imageBytes -> - // Process image - } - .onFailure { error -> - // Show user-friendly error message - when (error) { - is IllegalStateException -> "Camera not ready" - is CameraAccessException -> "Camera access denied" - else -> "Failed to capture image" - } - } -``` - -### 3. State Management -Observe camera state for UI updates: - -```kotlin -val cameraState by cameraService.cameraState.collectAsState() - -when (cameraState) { - is CameraState.Idle -> ShowInitializeButton() - is CameraState.Initializing -> ShowLoadingIndicator() - is CameraState.Previewing -> EnableCaptureButton() - is CameraState.Error -> ShowErrorMessage(error) - else -> ShowPlaceholder() -} -``` - -### 4. Permissions (Android) -Always check and request permissions before initializing camera: - -```kotlin -if (!CameraPermissionChecker.isGranted(context)) { - // Request permission using RequestCameraPermission composable -} -``` - -### 5. Testing -Mock `ICameraService` for unit tests: - -```kotlin -class MockCameraService : ICameraService { - override val cameraState = MutableStateFlow(CameraState.Idle) - - override suspend fun initialize(lensFacing: LensFacing): Result { - cameraState.value = CameraState.Ready - return Result.success(Unit) - } - - override suspend fun captureImage(): Result { - return Result.success(ByteArray(100)) // Mock image data - } - - // ... implement other methods -} -``` - -## Troubleshooting - -### Android - -**Issue:** Camera preview is black -- **Solution:** Ensure PreviewView is properly bound to the camera service -- Check that `cameraService.previewView` is set - -**Issue:** Permission denied -- **Solution:** Add camera permission to AndroidManifest.xml: - ```xml - - ``` - -**Issue:** Camera not initializing -- **Solution:** Ensure LifecycleOwner is provided in Koin module - -### Desktop - -**Issue:** Camera not found -- **Solution:** Check JavaCV native libraries are properly loaded -- Ensure webcam is connected and not in use by another application - -**Issue:** Low FPS -- **Solution:** Reduce resolution in BiometricConfig -- Increase delay in DesktopCameraPreview LaunchedEffect - -## Architecture Benefits - -1. **Testability**: Mock ICameraService for unit tests -2. **Platform Independence**: Business logic doesn't depend on platform -3. **Maintainability**: Clear separation of concerns -4. **Flexibility**: Easy to add new camera implementations -5. **Reusability**: Common UI components shared across platforms -6. **Type Safety**: Kotlin type system prevents errors -7. **Reactive**: StateFlow provides reactive state management - -## SOLID Principles Applied - -1. **Single Responsibility**: Each class has one reason to change -2. **Open/Closed**: Open for extension (new platforms), closed for modification -3. **Liskov Substitution**: All implementations can substitute ICameraService -4. **Interface Segregation**: ICameraService contains only necessary methods -5. **Dependency Inversion**: High-level code depends on abstractions - -## Design Patterns Used - -1. **Hexagonal Architecture** (Ports and Adapters) -2. **Adapter Pattern**: Platform implementations adapt to ICameraService -3. **State Pattern**: CameraState sealed class -4. **Observer Pattern**: StateFlow for reactive updates -5. **Template Method**: CameraPreviewContainer defines structure -6. **Dependency Injection**: Koin provides implementations -7. **Factory Pattern**: Platform modules create instances diff --git a/docs/archive/2026-04-16/CAMERA_QUICK_REFERENCE.md b/docs/archive/2026-04-16/CAMERA_QUICK_REFERENCE.md deleted file mode 100644 index 609b7b91..00000000 --- a/docs/archive/2026-04-16/CAMERA_QUICK_REFERENCE.md +++ /dev/null @@ -1,294 +0,0 @@ -# Camera Integration Quick Reference - -## Quick Start - -### 1. Inject Camera Service -```kotlin -@Composable -fun MyScreen(cameraService: ICameraService = get()) -``` - -### 2. Initialize & Preview -```kotlin -LaunchedEffect(Unit) { - cameraService.initialize(LensFacing.FRONT) - cameraService.startPreview() -} -``` - -### 3. Capture Image -```kotlin -scope.launch { - cameraService.captureImage() - .onSuccess { bytes -> /* Use image */ } - .onFailure { error -> /* Handle error */ } -} -``` - -### 4. Cleanup -```kotlin -DisposableEffect(Unit) { - onDispose { - scope.launch { cameraService.release() } - } -} -``` - -## Camera States - -| State | Description | UI Action | -|-------|-------------|-----------| -| `Idle` | Not initialized | Show initialize button | -| `Initializing` | Starting up | Show loading indicator | -| `Ready` | Initialized, not previewing | Ready to start preview | -| `Previewing` | Active preview | Enable capture button | -| `Capturing` | Taking photo | Disable capture, show animation | -| `Error(e)` | Error occurred | Show error message | -| `Released` | Cleaned up | Reset UI | - -## Common Patterns - -### Full Camera Screen -```kotlin -@Composable -fun CameraScreen(cameraService: ICameraService = get()) { - val state by cameraService.cameraState.collectAsState() - val scope = rememberCoroutineScope() - - LaunchedEffect(Unit) { - cameraService.initialize(LensFacing.FRONT) - cameraService.startPreview() - } - - DisposableEffect(Unit) { - onDispose { scope.launch { cameraService.release() } } - } - - CameraPreviewContainer( - cameraState = state, - onCaptureClick = { - scope.launch { - cameraService.captureImage() - .onSuccess { /* Handle */ } - } - }, - onCloseClick = { /* Navigate back */ } - ) { - when (cameraService) { - is AndroidCameraService -> AndroidCameraPreview(cameraService) - is DesktopCameraServiceImpl -> DesktopCameraPreview(cameraService) - } - } -} -``` - -### With Permissions (Android) -```kotlin -@Composable -fun CameraScreenWithPermission(cameraService: ICameraService = get()) { - var hasPermission by remember { mutableStateOf(false) } - - RequestCameraPermission( - onPermissionGranted = { hasPermission = true }, - onPermissionDenied = { /* Show rationale */ }, - onPermissionPermanentlyDenied = { /* Show settings */ } - ) - - if (hasPermission) { - // Show camera UI - } else { - // Show permission required UI - } -} -``` - -### With Face Guide Overlay -```kotlin -CameraPreviewContainer( - cameraState = state, - onCaptureClick = { /* Capture */ }, - onCloseClick = { /* Close */ }, - overlayContent = { - FaceDetectionOverlay( - showGuide = true, - guidanceText = "Center your face in the oval" - ) - } -) { - // Camera preview -} -``` - -### With Camera Flip -```kotlin -var lens by remember { mutableStateOf(LensFacing.FRONT) } - -CameraPreviewContainer( - cameraState = state, - onCaptureClick = { /* Capture */ }, - onCloseClick = { /* Close */ }, - onFlipCamera = { - scope.launch { - cameraService.stopPreview() - lens = if (lens == LensFacing.FRONT) LensFacing.BACK else LensFacing.FRONT - cameraService.initialize(lens) - cameraService.startPreview() - } - }, - showFlipButton = cameraService.hasCamera(LensFacing.BACK) -) { - // Camera preview -} -``` - -## API Reference - -### ICameraService - -| Method | Description | Returns | -|--------|-------------|---------| -| `initialize(lensFacing)` | Initialize camera | `Result` | -| `startPreview()` | Start preview | `Result` | -| `stopPreview()` | Stop preview | `Result` | -| `captureImage()` | Capture high-quality JPEG | `Result` | -| `captureFrame()` | Capture quick frame | `Result` | -| `isAvailable()` | Check if camera exists | `Boolean` | -| `hasCamera(lensFacing)` | Check specific lens | `Boolean` | -| `release()` | Release resources | `Unit` | -| `getPreviewDimensions()` | Get resolution | `Pair` | -| `getSupportedResolutions()` | Get all resolutions | `List>` | - -### Properties - -| Property | Type | Description | -|----------|------|-------------| -| `cameraState` | `StateFlow` | Observable camera state | - -## Configuration - -### Adjust in BiometricConfig.kt -```kotlin -const val PREFERRED_IMAGE_WIDTH = 640 // Image width -const val PREFERRED_IMAGE_HEIGHT = 480 // Image height -const val CAMERA_FRAME_RATE_FPS = 30 // FPS -const val CAMERA_AUTO_FOCUS_ENABLED = true // Auto focus -``` - -## Error Handling - -```kotlin -cameraService.captureImage().fold( - onSuccess = { bytes -> - // Success case - }, - onFailure = { error -> - val message = when (error) { - is IllegalStateException -> "Camera not ready" - is CameraAccessException -> "Camera access denied" - is TimeoutException -> "Camera timeout" - else -> "Unknown error: ${error.message}" - } - showError(message) - } -) -``` - -## Best Practices - -### βœ… DO -- Always release camera in DisposableEffect -- Observe cameraState for UI updates -- Handle all error cases -- Request permissions before initialization (Android) -- Use LensFacing.FRONT for biometric capture -- Check camera availability before use - -### ❌ DON'T -- Don't forget to release camera resources -- Don't call captureImage when not in Previewing state -- Don't ignore error results -- Don't initialize camera without permission (Android) -- Don't block UI thread with camera operations - -## Troubleshooting - -| Issue | Solution | -|-------|----------| -| Black preview | Check PreviewView is bound to service | -| Permission denied | Add CAMERA permission to AndroidManifest | -| Camera not found | Check device has camera, not in use | -| Low FPS | Reduce resolution in config | -| Out of memory | Release camera when not in use | - -## File Locations - -| File | Path | -|------|------| -| Interface | `shared/src/commonMain/.../ICameraService.kt` | -| Android Impl | `shared/src/androidMain/.../AndroidCameraService.kt` | -| Desktop Impl | `desktopApp/src/desktopMain/.../DesktopCameraServiceImpl.kt` | -| UI Component | `shared/src/commonMain/.../CameraPreview.kt` | -| Android UI | `shared/src/androidMain/.../AndroidCameraPreview.kt` | -| Desktop UI | `desktopApp/src/desktopMain/.../DesktopCameraPreview.kt` | -| Permissions | `shared/src/androidMain/.../CameraPermissionHelper.kt` | -| DI Module | `shared/src/.../PlatformModule.kt` | -| Config | `shared/src/commonMain/.../BiometricConfig.kt` | - -## Dependencies - -### Android -```gradle -androidx.camera:camera-core:1.3.0 -androidx.camera:camera-camera2:1.3.0 -androidx.camera:camera-lifecycle:1.3.0 -androidx.camera:camera-view:1.3.0 -com.google.accompanist:accompanist-permissions:0.32.0 -``` - -### Desktop -```gradle -org.bytedeco:javacv-platform:1.5.10 -``` - -## Testing - -### Mock Camera Service -```kotlin -class MockCameraService : ICameraService { - override val cameraState = MutableStateFlow(CameraState.Idle) - - override suspend fun initialize(lensFacing: LensFacing) = Result.success(Unit) - override suspend fun startPreview() = Result.success(Unit) - override suspend fun captureImage() = Result.success(ByteArray(100)) - // ... implement other methods -} -``` - -### Test Setup -```kotlin -@Before -fun setup() { - startKoin { - modules(module { - single { MockCameraService() } - }) - } -} -``` - -## Platform Differences - -| Feature | Android | Desktop | -|---------|---------|---------| -| Library | CameraX | JavaCV | -| Preview | PreviewView | BufferedImage | -| Quality | High (95% JPEG) | Good (PNG/JPEG) | -| FPS | 30+ | 30 | -| Permissions | Required | Not required | -| Lifecycle | Managed | Manual | - -## Support - -For detailed information, see: -- **Full Guide**: `CAMERA_INTEGRATION_GUIDE.md` -- **Code**: Browse implementation files diff --git a/docs/archive/2026-04-16/GET_STARTED.md b/docs/archive/2026-04-16/GET_STARTED.md deleted file mode 100644 index 66cb1bf7..00000000 --- a/docs/archive/2026-04-16/GET_STARTED.md +++ /dev/null @@ -1,183 +0,0 @@ -# Get Started - FIVUCSAS Client Apps - -Welcome! This is the **client-apps** module for the FIVUCSAS project --- a Kotlin Multiplatform (KMP) application targeting Android, iOS, and Desktop. - -## What You Have - -This project is a fully working Kotlin Multiplatform application with: - -- **shared/** -- Common business logic, ViewModels, UI components (Compose Multiplatform) -- **androidApp/** -- Android application module -- **desktopApp/** -- Desktop (JVM) application module -- **iOS target** -- Ready for SwiftUI wrappers - -## Quick Start - -### Prerequisites - -- **JDK 17+** (Temurin/Corretto recommended) -- **Android Studio Ladybug+** with Kotlin Multiplatform plugin -- **Android SDK** (API 34+ recommended) -- **Gradle 8.0+** (wrapper included) - -### Option 1: Android Studio (Recommended) - -1. Open this folder in Android Studio -2. Install the **Kotlin Multiplatform** plugin (Settings -> Plugins) -3. Sync Gradle (automatic on open) -4. Select `androidApp` run configuration -5. Click Run - -### Option 2: Command Line - -```bash -# Build Android debug APK -./gradlew :androidApp:assembleDebug - -# Run desktop app -./gradlew :desktopApp:run - -# Run shared module tests -./gradlew :shared:testDebugUnitTest -``` - -## Project Structure - -``` -client-apps/ -β”œβ”€β”€ shared/ # Shared KMP module -β”‚ └── src/ -β”‚ β”œβ”€β”€ commonMain/ # Common Kotlin code -β”‚ β”‚ └── kotlin/com/fivucsas/shared/ -β”‚ β”‚ β”œβ”€β”€ config/ # AppConfig, UIDimens, BiometricConfig -β”‚ β”‚ β”œβ”€β”€ domain/ # Models, use cases, repository interfaces -β”‚ β”‚ β”œβ”€β”€ data/ # Repository implementations, API services -β”‚ β”‚ β”œβ”€β”€ presentation/ # ViewModels, UI state classes -β”‚ β”‚ β”œβ”€β”€ platform/ # Platform abstraction interfaces -β”‚ β”‚ └── ui/ # Shared Compose UI (theme, components) -β”‚ └── commonTest/ # Shared unit tests -β”œβ”€β”€ androidApp/ # Android application -β”‚ └── src/main/ -β”‚ β”œβ”€β”€ kotlin/ # Android-specific code -β”‚ └── AndroidManifest.xml # Permissions (CAMERA, INTERNET, RECORD_AUDIO, etc.) -β”œβ”€β”€ desktopApp/ # Desktop (JVM) application -β”‚ └── src/desktopMain/kotlin/ # Desktop-specific code -β”œβ”€β”€ build.gradle.kts # Root build configuration -β”œβ”€β”€ settings.gradle.kts # Module declarations -└── gradle.properties # Kotlin/Compose versions -``` - -## Architecture - -This app follows **Clean Architecture + MVVM** with Kotlin Multiplatform: - -``` -β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” -β”‚ Presentation Layer β”‚ -β”‚ (Compose UI + ViewModels) β”‚ -β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ - β”‚ -β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” -β”‚ Domain Layer β”‚ -β”‚ (Entities + Use Cases) β”‚ -β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ - β”‚ -β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” -β”‚ Data Layer β”‚ -β”‚ (Repositories + API clients) β”‚ -β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ -``` - -- **ViewModels** in shared module (AdminViewModel, KioskViewModel) -- **Compose Multiplatform** for shared UI -- **Platform interfaces** (ICameraService, ILogger, ISecureStorage) for testability - -## Features - -### Implemented -- [x] Admin Dashboard (user management, analytics) -- [x] Kiosk Mode (enrollment, verification) -- [x] Face detection and liveness -- [x] NFC document reading -- [x] Voice verification -- [x] FIDO2/WebAuthn integration (Credential Manager) -- [x] Shared UI component library (Atomic Design) -- [x] Centralized configuration system -- [x] 50+ ViewModel unit tests - -### Upcoming -- [ ] iOS SwiftUI wrappers -- [ ] Desktop NFC (javax.smartcardio) -- [ ] Windows Hello (JNA) -- [ ] Offline caching - -## Development Workflow - -### 1. Start Backend Services - -```bash -cd ../identity-core-api -docker compose -f docker-compose.prod.yml --env-file .env.prod up -d - -cd ../biometric-processor -docker compose -f docker-compose.prod.yml --env-file .env.prod up -d -``` - -### 2. Build and Run - -```bash -# Android (debug APK) -./gradlew :androidApp:assembleDebug - -# Desktop -./gradlew :desktopApp:run - -# All tests -./gradlew test -``` - -### 3. Common Tasks - -```bash -# Clean build -./gradlew clean - -# Check for dependency updates -./gradlew dependencyUpdates - -# Lint -./gradlew lint -``` - -## Troubleshooting - -### "SDK location not found" -Set `ANDROID_HOME` environment variable or create `local.properties` with `sdk.dir=/path/to/android/sdk`. - -### Gradle sync fails -```bash -./gradlew --stop -./gradlew clean -./gradlew :shared:compileKotlinAndroid -``` - -### "Unable to connect to API" -Check that backend services are running and API URLs in `AppConfig.kt` are correct. - -## Documentation - -1. **GET_STARTED.md** (this file) -- Start here -2. **QUICKSTART.md** -- Detailed setup steps -3. **QUICK_REFERENCE.md** -- Command reference and architecture overview -4. **README.md** -- Full project documentation - -## Learning Resources - -- [Kotlin Multiplatform docs](https://kotlinlang.org/docs/multiplatform.html) -- [Compose Multiplatform](https://www.jetbrains.com/compose-multiplatform/) -- [Kotlin coroutines](https://kotlinlang.org/docs/coroutines-overview.html) -- [Android Credential Manager (FIDO2)](https://developer.android.com/identity/sign-in/credential-manager) - ---- - -*Last updated: 2026-04-04* diff --git a/docs/archive/2026-04-16/HEXAGONAL_ARCHITECTURE.md b/docs/archive/2026-04-16/HEXAGONAL_ARCHITECTURE.md deleted file mode 100644 index c28c1ed6..00000000 --- a/docs/archive/2026-04-16/HEXAGONAL_ARCHITECTURE.md +++ /dev/null @@ -1,1299 +0,0 @@ -# Hexagonal Architecture Guide - FIVUCSAS Client Apps - -**Version:** 1.0.0 -**Date:** 2026-01-19 -**Architecture Style:** Hexagonal (Ports and Adapters) + Clean Architecture - ---- - -## Table of Contents - -1. [Overview](#overview) -2. [Architecture Principles](#architecture-principles) -3. [Core Concepts](#core-concepts) -4. [Ports](#ports) -5. [Adapters](#adapters) -6. [Factory Pattern](#factory-pattern) -7. [Layer Interactions](#layer-interactions) -8. [Implementation Examples](#implementation-examples) -9. [Testing Strategy](#testing-strategy) -10. [Best Practices](#best-practices) - ---- - -## Overview - -### What is Hexagonal Architecture? - -Hexagonal Architecture (also known as Ports and Adapters) is an architectural pattern that: - -- **Isolates business logic** from external concerns -- **Defines clear boundaries** between core logic and infrastructure -- **Enables testability** through dependency inversion -- **Supports multiple interfaces** (UI, API, CLI, etc.) -- **Makes the system adaptable** to changing requirements - -### Why Hexagonal Architecture? - -βœ… **Platform Independence** - Core logic works on Android, iOS, Desktop, Web -βœ… **Testability** - Easy to test with mock implementations -βœ… **Maintainability** - Clear separation of concerns -βœ… **Flexibility** - Swap implementations without changing core logic -βœ… **SOLID Compliance** - Enforces Dependency Inversion Principle - -### Architecture Diagram - -``` -β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” -β”‚ PRIMARY ADAPTERS β”‚ -β”‚ (UI, REST API, CLI) β”‚ -β”‚ β”‚ -β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ -β”‚ β”‚ Desktop β”‚ β”‚ Android β”‚ β”‚ iOS β”‚ β”‚ -β”‚ β”‚ UI β”‚ β”‚ UI β”‚ β”‚ UI β”‚ β”‚ -β”‚ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ -β”‚ β”‚ β”‚ β”‚ β”‚ -β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ - β”‚ β”‚ β”‚ - β–Ό β–Ό β–Ό -β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” -β”‚ PRIMARY PORTS (Driving) β”‚ -β”‚ β”‚ -β”‚ INavigationService β”‚ IDialogService β”‚ INotificationService β”‚ -β”‚ β”‚ -β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ - β”‚ β”‚ β”‚ - β–Ό β–Ό β–Ό -β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” -β”‚ HEXAGONAL CORE β”‚ -β”‚ (Business Logic) β”‚ -β”‚ β”‚ -β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ -β”‚ β”‚ DOMAIN LAYER β”‚ β”‚ -β”‚ β”‚ β”‚ β”‚ -β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ -β”‚ β”‚ β”‚ USE CASES (Application Services) β”‚ β”‚ β”‚ -β”‚ β”‚ β”‚ β€’ GetUsersUseCase β”‚ β”‚ β”‚ -β”‚ β”‚ β”‚ β€’ EnrollFaceUseCase β”‚ β”‚ β”‚ -β”‚ β”‚ β”‚ β€’ VerifyFaceUseCase β”‚ β”‚ β”‚ -β”‚ β”‚ β”‚ β€’ ValidateUserUseCase β”‚ β”‚ β”‚ -β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ -β”‚ β”‚ β”‚ β”‚ -β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ -β”‚ β”‚ β”‚ DOMAIN MODELS (Entities) β”‚ β”‚ β”‚ -β”‚ β”‚ β”‚ β€’ User β”‚ β”‚ β”‚ -β”‚ β”‚ β”‚ β€’ BiometricData β”‚ β”‚ β”‚ -β”‚ β”‚ β”‚ β€’ EnrollmentData β”‚ β”‚ β”‚ -β”‚ β”‚ β”‚ β€’ VerificationResult β”‚ β”‚ β”‚ -β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ -β”‚ β”‚ β”‚ β”‚ -β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ -β”‚ β”‚ β”‚ BUSINESS RULES β”‚ β”‚ β”‚ -β”‚ β”‚ β”‚ β€’ ValidationRules β”‚ β”‚ β”‚ -β”‚ β”‚ β”‚ β€’ AppExceptions β”‚ β”‚ β”‚ -β”‚ β”‚ β”‚ β€’ BiometricConfig β”‚ β”‚ β”‚ -β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ -β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ -β”‚ β”‚ -β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ -β”‚ β”‚ PRESENTATION LAYER β”‚ β”‚ -β”‚ β”‚ β€’ ViewModels (AdminViewModel, KioskViewModel) β”‚ β”‚ -β”‚ β”‚ β€’ UI State (AdminUiState, KioskUiState) β”‚ β”‚ -β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ -β”‚ β”‚ -β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ - β”‚ β”‚ β”‚ - β–Ό β–Ό β–Ό -β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” -β”‚ SECONDARY PORTS (Driven) β”‚ -β”‚ β”‚ -β”‚ UserRepository β”‚ ICameraService β”‚ IConfigurationProvider β”‚ -β”‚ AuthRepository β”‚ ILogger β”‚ ISecureStorage β”‚ -β”‚ BiometricRepo β”‚ β”‚ -β”‚ β”‚ -β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ - β”‚ β”‚ β”‚ - β–Ό β–Ό β–Ό -β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” -β”‚ SECONDARY ADAPTERS β”‚ -β”‚ (Database, External APIs, File System) β”‚ -β”‚ β”‚ -β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ -β”‚ β”‚ UserRepo β”‚ β”‚ DesktopCameraβ”‚ β”‚ Default β”‚ β”‚ -β”‚ β”‚ Impl β”‚ β”‚ ServiceImpl β”‚ β”‚ Config β”‚ β”‚ -β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ -β”‚ β”‚ -β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ -β”‚ β”‚ Auth API β”‚ β”‚ Desktop β”‚ β”‚ Desktop β”‚ β”‚ -β”‚ β”‚ Impl β”‚ β”‚ Logger β”‚ β”‚ Secure β”‚ β”‚ -β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ -β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ -``` - ---- - -## Architecture Principles - -### 1. Dependency Rule - -**"Dependencies point inward, toward the core"** - -``` -External World β†’ Adapters β†’ Ports β†’ Core Business Logic - (UI) (Impl) (Interface) (Use Cases) -``` - -- **Core** depends on nothing -- **Ports** define interfaces -- **Adapters** implement ports and depend on external systems -- **External systems** connect through adapters - -### 2. Business Logic Independence - -The hexagonal core (business logic) is independent of: - -- ❌ UI frameworks (Compose, SwiftUI, React) -- ❌ Databases (PostgreSQL, MongoDB) -- ❌ External APIs (REST, GraphQL) -- ❌ Operating systems (Android, iOS, Desktop) -- ❌ Libraries and frameworks - -### 3. Ports Define Contracts - -Ports are **interfaces** that define: - -- What the core **needs** from the outside world (Secondary Ports) -- What the core **provides** to the outside world (Primary Ports) - -### 4. Adapters Implement Contracts - -Adapters are **implementations** that: - -- Connect external systems to ports -- Translate between external formats and domain models -- Handle platform-specific details - ---- - -## Core Concepts - -### The Hexagon - -The "hexagon" represents the **core business logic** of the application: - -``` - β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β” - β•± β•² - β•± BUSINESS β•² - β”‚ LOGIC β”‚ - β”‚ (CORE) β”‚ - β•² β•± - β•² β•± - β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ -``` - -**Contains:** -- Domain models (User, BiometricData) -- Use cases (EnrollFace, VerifyFace) -- Business rules (Validation, Thresholds) -- Exceptions (AppException, ValidationException) - -**Does NOT contain:** -- UI code -- Database code -- API client code -- Platform-specific code - -### Primary Ports (Driving/Inbound) - -**"What the application offers to the outside world"** - -These ports allow external actors to **use** the application. - -**Examples:** -- `INavigationService` - Allows core to trigger navigation -- `IDialogService` - Allows core to show dialogs -- `INotificationService` - Allows core to show notifications - -**Direction:** Outside World β†’ Port β†’ Core - -```kotlin -// Primary Port (Interface) -interface INavigationService { - fun navigateTo(route: String) -} - -// Core uses the port -class LoginUseCase( - private val navigationService: INavigationService -) { - suspend fun execute(credentials: Credentials) { - // Business logic - if (isValid) { - navigationService.navigateTo("dashboard") - } - } -} -``` - -### Secondary Ports (Driven/Outbound) - -**"What the application needs from the outside world"** - -These ports allow the application to **interact with** external systems. - -**Examples:** -- `UserRepository` - Data access port -- `ICameraService` - Camera access port -- `ILogger` - Logging port -- `IConfigurationProvider` - Configuration access port - -**Direction:** Core β†’ Port β†’ Outside World - -```kotlin -// Secondary Port (Interface) -interface UserRepository { - suspend fun getUsers(): Result> -} - -// Core uses the port -class GetUsersUseCase( - private val userRepository: UserRepository -) { - suspend fun execute(): Result> { - return userRepository.getUsers() - } -} -``` - -### Primary Adapters (Driving/Inbound) - -**"Implementations that call the core"** - -These adapters **drive** the application. - -**Examples:** -- Desktop UI (Compose Desktop) -- Android UI (Jetpack Compose) -- iOS UI (SwiftUI) -- REST API endpoints - -```kotlin -// Primary Adapter (Desktop UI) -@Composable -fun LoginScreen(viewModel: LoginViewModel) { - // UI calls ViewModel (which calls use cases in core) - Button(onClick = { viewModel.login(email, password) }) { - Text("Login") - } -} -``` - -### Secondary Adapters (Driven/Outbound) - -**"Implementations that are called by the core"** - -These adapters are **driven** by the application. - -**Examples:** -- `UserRepositoryImpl` - Database adapter -- `DesktopCameraServiceImpl` - Camera adapter -- `DesktopLoggerImpl` - Logging adapter -- `DefaultConfigurationProvider` - Config adapter - -```kotlin -// Secondary Adapter (Repository Implementation) -class UserRepositoryImpl( - private val apiClient: IdentityApi -) : UserRepository { - override suspend fun getUsers(): Result> { - return try { - val response = apiClient.getUsers() - Result.success(response.map { it.toDomain() }) - } catch (e: Exception) { - Result.failure(e) - } - } -} -``` - ---- - -## Ports - -### Primary Ports (Driving) - -#### 1. INavigationService - -**Purpose:** Allows core logic to trigger navigation without depending on UI framework. - -**Location:** `/shared/src/commonMain/kotlin/com/fivucsas/shared/platform/INavigationService.kt` - -```kotlin -interface INavigationService { - fun navigateTo(route: String, params: Map = emptyMap()) - fun navigateBack(): Boolean - fun navigateAndClearStack(route: String) - fun popUpTo(route: String, inclusive: Boolean = false) -} -``` - -**Usage Example:** -```kotlin -class LoginUseCase( - private val authRepository: AuthRepository, - private val navigationService: INavigationService -) { - suspend fun execute(email: String, password: String) { - val result = authRepository.login(email, password) - if (result.isSuccess) { - navigationService.navigateTo(NavigationRoutes.DASHBOARD) - } - } -} -``` - -#### 2. IDialogService - -**Purpose:** Allows core logic to show dialogs without depending on UI framework. - -**Location:** `/shared/src/commonMain/kotlin/com/fivucsas/shared/platform/IDialogService.kt` - -```kotlin -interface IDialogService { - suspend fun showInfo(title: String, message: String, onDismiss: (() -> Unit)? = null) - suspend fun showConfirmation(title: String, message: String, confirmText: String, cancelText: String): Boolean - suspend fun showError(title: String, message: String, onDismiss: (() -> Unit)? = null) - suspend fun showLoading(message: String): DialogHandle - fun dismiss(handle: DialogHandle) - fun dismissAll() -} -``` - -**Usage Example:** -```kotlin -class DeleteUserUseCase( - private val userRepository: UserRepository, - private val dialogService: IDialogService -) { - suspend fun execute(userId: String) { - val confirmed = dialogService.showConfirmation( - title = "Delete User", - message = "Are you sure you want to delete this user?", - confirmText = "Delete", - cancelText = "Cancel" - ) - - if (confirmed) { - val loadingHandle = dialogService.showLoading("Deleting user...") - userRepository.deleteUser(userId) - dialogService.dismiss(loadingHandle) - } - } -} -``` - -#### 3. INotificationService - -**Purpose:** Allows core logic to show notifications without depending on UI framework. - -**Location:** `/shared/src/commonMain/kotlin/com/fivucsas/shared/platform/INotificationService.kt` - -```kotlin -interface INotificationService { - fun showSuccess(message: String, duration: Long? = null) - fun showError(message: String, duration: Long? = null) - fun showWarning(message: String, duration: Long? = null) - fun showInfo(message: String, duration: Long? = null) - fun clearAll() -} -``` - -**Usage Example:** -```kotlin -class EnrollFaceUseCase( - private val biometricRepository: BiometricRepository, - private val notificationService: INotificationService -) { - suspend fun execute(userId: String, imageBytes: ByteArray) { - val result = biometricRepository.enrollFace(userId, imageBytes) - - if (result.isSuccess) { - notificationService.showSuccess("Face enrolled successfully!") - } else { - notificationService.showError("Enrollment failed: ${result.exceptionOrNull()?.message}") - } - } -} -``` - -### Secondary Ports (Driven) - -#### 1. UserRepository - -**Purpose:** Data access abstraction for user operations. - -**Location:** `/shared/src/commonMain/kotlin/com/fivucsas/shared/domain/repository/UserRepository.kt` - -```kotlin -interface UserRepository { - suspend fun getUsers(): Result> - suspend fun getUserById(id: String): Result - suspend fun createUser(user: User): Result - suspend fun updateUser(id: String, user: User): Result - suspend fun deleteUser(id: String): Result - suspend fun searchUsers(query: String): Result> - suspend fun getStatistics(): Result -} -``` - -#### 2. ICameraService - -**Purpose:** Camera operations abstraction for cross-platform support. - -**Location:** `/shared/src/commonMain/kotlin/com/fivucsas/shared/platform/ICameraService.kt` - -```kotlin -interface ICameraService { - val cameraState: StateFlow - suspend fun initialize(lensFacing: LensFacing = FRONT): Result - suspend fun startPreview(): Result - suspend fun stopPreview(): Result - suspend fun captureImage(): Result - suspend fun captureFrame(): Result - fun isAvailable(): Boolean - fun hasCamera(lensFacing: LensFacing): Boolean - suspend fun release() - fun getPreviewDimensions(): Pair - fun getSupportedResolutions(): List> -} -``` - -#### 3. IConfigurationProvider - -**Purpose:** Configuration access abstraction. - -**Location:** `/shared/src/commonMain/kotlin/com/fivucsas/shared/platform/IConfigurationProvider.kt` - -```kotlin -interface IConfigurationProvider { - val appName: String - val apiBaseUrl: String - val cacheEnabled: Boolean - // ... 20+ configuration properties - - fun get(key: String, defaultValue: T): T - fun set(key: String, value: T) - suspend fun reload() -} -``` - -#### 4. ILogger - -**Purpose:** Logging abstraction for cross-platform support. - -**Location:** `/shared/src/commonMain/kotlin/com/fivucsas/shared/platform/ILogger.kt` - -```kotlin -interface ILogger { - fun debug(tag: String, message: String) - fun info(tag: String, message: String) - fun warn(tag: String, message: String) - fun error(tag: String, message: String, throwable: Throwable? = null) - fun verbose(tag: String, message: String) -} -``` - -#### 5. ISecureStorage - -**Purpose:** Secure storage abstraction for cross-platform support. - -**Location:** `/shared/src/commonMain/kotlin/com/fivucsas/shared/platform/ISecureStorage.kt` - -```kotlin -interface ISecureStorage { - fun saveString(key: String, value: String) - fun getString(key: String): String? - fun remove(key: String) - fun clear() -} -``` - ---- - -## Adapters - -### Primary Adapters (Driving) - -#### Desktop UI Adapter - -**Location:** `/desktopApp/src/desktopMain/kotlin/` - -```kotlin -// Desktop app drives the core through ViewModels -@Composable -fun App() { - val viewModel: AdminViewModel = koinInject() - - AdminDashboard( - state = viewModel.state.collectAsState().value, - onAction = viewModel::handleAction // Calls use cases in core - ) -} -``` - -**Flow:** -``` -User Click β†’ Compose UI β†’ ViewModel β†’ Use Case β†’ Repository Port β†’ Repository Adapter β†’ API/Database -``` - -### Secondary Adapters (Driven) - -#### 1. UserRepositoryImpl (Data Adapter) - -**Location:** `/shared/src/commonMain/kotlin/com/fivucsas/shared/data/repository/UserRepositoryImpl.kt` - -```kotlin -class UserRepositoryImpl( - private val identityApi: IdentityApi, - private val logger: ILogger -) : UserRepository { - - override suspend fun getUsers(): Result> { - return try { - logger.info("UserRepository", "Fetching users from API") - val response = identityApi.getUsers() - val users = response.map { it.toDomain() } - Result.success(users) - } catch (e: Exception) { - logger.error("UserRepository", "Failed to fetch users", e) - Result.failure(e.toAppException()) - } - } - - // ... other methods -} -``` - -**Adapter Responsibilities:** -- Calls external API -- Converts DTOs to domain models -- Handles errors -- Logs operations - -#### 2. DesktopCameraServiceImpl (Platform Adapter) - -**Location:** `/desktopApp/src/desktopMain/kotlin/com/fivucsas/desktop/platform/DesktopCameraServiceImpl.kt` - -```kotlin -class DesktopCameraServiceImpl( - private val logger: ILogger -) : ICameraService { - - private val _cameraState = MutableStateFlow(CameraState.Idle) - override val cameraState: StateFlow = _cameraState.asStateFlow() - - override suspend fun initialize(lensFacing: LensFacing): Result { - return try { - // JavaCV specific implementation - grabber = VideoInputFrameGrabber(0) - grabber.start() - _cameraState.value = CameraState.Ready - Result.success(Unit) - } catch (e: Exception) { - logger.error("DesktopCamera", "Failed to initialize", e) - Result.failure(e) - } - } - - // ... other methods -} -``` - -**Adapter Responsibilities:** -- Uses platform-specific library (JavaCV) -- Implements port interface -- Manages camera lifecycle -- Handles platform-specific errors - -#### 3. DefaultConfigurationProvider (Config Adapter) - -**Location:** `/shared/src/commonMain/kotlin/com/fivucsas/shared/platform/config/DefaultConfigurationProvider.kt` - -```kotlin -class DefaultConfigurationProvider : IConfigurationProvider { - - override val appName: String get() = AppConfig.APP_NAME - override val apiBaseUrl: String get() = AppConfig.Api.BASE_URL - override val cacheEnabled: Boolean get() = AppConfig.Cache.ENABLE_CACHE - - private val customConfig = mutableMapOf() - - override fun get(key: String, defaultValue: T): T { - return customConfig[key] as? T ?: defaultValue - } - - override fun set(key: String, value: T) { - customConfig[key] = value as Any - } - - override suspend fun reload() { - // Reload from file/remote source - } -} -``` - -**Adapter Responsibilities:** -- Adapts existing configuration objects -- Implements port interface -- Provides runtime configuration override -- Supports configuration reload - ---- - -## Factory Pattern - -### PlatformServiceFactory - -**Purpose:** Centralized creation of platform-specific adapters. - -**Location:** `/shared/src/commonMain/kotlin/com/fivucsas/shared/platform/factory/PlatformServiceFactory.kt` - -```kotlin -interface PlatformServiceFactory { - fun createCameraService(): ICameraService - fun createLogger(): ILogger - fun createSecureStorage(): ISecureStorage - fun createNavigationService(): INavigationService - fun createDialogService(): IDialogService - fun createNotificationService(): INotificationService - fun createConfigurationProvider(): IConfigurationProvider -} - -expect fun getCurrentPlatform(): PlatformType -expect fun createPlatformServiceFactory(): PlatformServiceFactory -``` - -### Platform-Specific Factory (Desktop) - -**Location:** `/shared/src/desktopMain/kotlin/com/fivucsas/shared/platform/factory/DesktopPlatformFactory.kt` - -```kotlin -actual fun getCurrentPlatform(): PlatformType = PlatformType.DESKTOP - -actual fun createPlatformServiceFactory(): PlatformServiceFactory { - return DesktopPlatformServiceFactory() -} - -class DesktopPlatformServiceFactory : PlatformServiceFactory { - override fun createNavigationService() = DesktopNavigationService() - override fun createDialogService() = DesktopDialogService() - override fun createNotificationService() = DesktopNotificationService() - override fun createConfigurationProvider() = DefaultConfigurationProvider() - // ... -} -``` - -### Factory Benefits - -βœ… **Centralized Creation** - Single place to create adapters -βœ… **Platform Abstraction** - Easy to add new platforms (Android, iOS, Web) -βœ… **Testability** - Easy to create mock factories for testing -βœ… **Open/Closed Principle** - Open for extension, closed for modification - -### Factory Usage - -```kotlin -// In DI module -val platformModule = module { - single { createPlatformServiceFactory() } - single { get().createNavigationService() } - single { get().createDialogService() } - single { get().createNotificationService() } - single { get().createConfigurationProvider() } -} -``` - ---- - -## Layer Interactions - -### Data Flow: User Action to UI Update - -``` -β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” -β”‚ 1. USER ACTION β”‚ -β”‚ User clicks "Load Users" button β”‚ -β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ - β”‚ - β–Ό -β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” -β”‚ 2. PRIMARY ADAPTER (Desktop UI) β”‚ -β”‚ Button(onClick = { viewModel.loadUsers() }) β”‚ -β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ - β”‚ - β–Ό -β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” -β”‚ 3. PRESENTATION LAYER (ViewModel) β”‚ -β”‚ fun loadUsers() { β”‚ -β”‚ viewModelScope.launch { β”‚ -β”‚ getUsersUseCase.execute() β”‚ -β”‚ } β”‚ -β”‚ } β”‚ -β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ - β”‚ - β–Ό -β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” -β”‚ 4. DOMAIN LAYER (Use Case) β”‚ -β”‚ class GetUsersUseCase( β”‚ -β”‚ private val userRepository: UserRepository β”‚ -β”‚ ) { β”‚ -β”‚ suspend fun execute(): Result> { β”‚ -β”‚ return userRepository.getUsers() β”‚ -β”‚ } β”‚ -β”‚ } β”‚ -β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ - β”‚ - β–Ό -β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” -β”‚ 5. SECONDARY PORT (Repository Interface) β”‚ -β”‚ interface UserRepository { β”‚ -β”‚ suspend fun getUsers(): Result> β”‚ -β”‚ } β”‚ -β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ - β”‚ - β–Ό -β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” -β”‚ 6. SECONDARY ADAPTER (Repository Implementation) β”‚ -β”‚ class UserRepositoryImpl(...) : UserRepository { β”‚ -β”‚ override suspend fun getUsers(): Result> {β”‚ -β”‚ val response = identityApi.getUsers() β”‚ -β”‚ return Result.success(response.map { it.toDomain() })β”‚ -β”‚ } β”‚ -β”‚ } β”‚ -β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ - β”‚ - β–Ό -β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” -β”‚ 7. EXTERNAL SYSTEM (API) β”‚ -β”‚ GET https://api.fivucsas.com/v1/users β”‚ -β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ - β”‚ - β–Ό (Response flows back up) -β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” -β”‚ 8. UI UPDATE β”‚ -β”‚ state.value = state.value.copy(users = result) β”‚ -β”‚ (UI automatically updates via StateFlow) β”‚ -β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ -``` - -### Dependency Direction - -``` -UI Adapter β†’ ViewModel β†’ Use Case β†’ Repository Interface ← Repository Impl β†’ External API - (View) (VM) (Domain) (Port) (Adapter) (DB/API) - -Direction of Dependencies: -←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←← -(All dependencies point INWARD toward the core) -``` - -**Key Points:** -- Core (Use Cases, Domain Models) has NO dependencies on outer layers -- Outer layers depend on core through interfaces (ports) -- Dependency Inversion Principle in action - ---- - -## Implementation Examples - -### Example 1: Adding a New Feature - -**Scenario:** Add "Export Users to CSV" feature - -**Step 1: Define Use Case (Core)** -```kotlin -// In /shared/src/commonMain/kotlin/com/fivucsas/shared/domain/usecase/admin/ -class ExportUsersUseCase( - private val userRepository: UserRepository, - private val fileService: IFileService, // New port - private val notificationService: INotificationService -) { - suspend fun execute(format: ExportFormat): Result { - return try { - val users = userRepository.getUsers().getOrThrow() - val csvData = convertToCSV(users) - fileService.saveFile("users.csv", csvData) - notificationService.showSuccess("Users exported successfully!") - Result.success(Unit) - } catch (e: Exception) { - notificationService.showError("Export failed: ${e.message}") - Result.failure(e) - } - } - - private fun convertToCSV(users: List): String { - // Business logic for CSV conversion - } -} -``` - -**Step 2: Define Port (if needed)** -```kotlin -// In /shared/src/commonMain/kotlin/com/fivucsas/shared/platform/ -interface IFileService { - suspend fun saveFile(filename: String, content: String): Result - suspend fun readFile(filename: String): Result - suspend fun deleteFile(filename: String): Result -} -``` - -**Step 3: Create Adapters** -```kotlin -// Desktop implementation -class DesktopFileService : IFileService { - override suspend fun saveFile(filename: String, content: String): Result { - return try { - File(filename).writeText(content) - Result.success(Unit) - } catch (e: Exception) { - Result.failure(e) - } - } -} - -// Android implementation -class AndroidFileService(private val context: Context) : IFileService { - override suspend fun saveFile(filename: String, content: String): Result { - // Android-specific implementation - } -} -``` - -**Step 4: Register in DI** -```kotlin -val useCaseModule = module { - // ... - factoryOf(::ExportUsersUseCase) -} - -val platformModule = module { - // ... - single { - get().createFileService() - } -} -``` - -**Step 5: Use in ViewModel** -```kotlin -class AdminViewModel( - // ... - private val exportUsersUseCase: ExportUsersUseCase -) : ViewModel() { - - fun exportUsers() { - viewModelScope.launch { - exportUsersUseCase.execute(ExportFormat.CSV) - } - } -} -``` - -**Step 6: Trigger from UI** -```kotlin -@Composable -fun AdminDashboard(viewModel: AdminViewModel) { - Button(onClick = { viewModel.exportUsers() }) { - Text("Export to CSV") - } -} -``` - -**Benefits:** -- βœ… Business logic (CSV conversion) in core -- βœ… Platform-specific file I/O in adapters -- βœ… Easy to test with mock IFileService -- βœ… Works on all platforms - -### Example 2: Testing with Hexagonal Architecture - -**Mock Port Implementation:** -```kotlin -class MockNavigationService : INavigationService { - val navigationHistory = mutableListOf() - - override fun navigateTo(route: String, params: Map) { - navigationHistory.add(route) - } - - override fun navigateBack(): Boolean { - if (navigationHistory.isNotEmpty()) { - navigationHistory.removeLast() - return true - } - return false - } - - override fun navigateAndClearStack(route: String) { - navigationHistory.clear() - navigationHistory.add(route) - } - - override fun popUpTo(route: String, inclusive: Boolean) { - // Mock implementation - } -} -``` - -**Test Use Case:** -```kotlin -@Test -fun `should navigate to dashboard on successful login`() = runTest { - // Arrange - val mockAuthRepo = MockAuthRepository().apply { - shouldSucceed = true - } - val mockNavigation = MockNavigationService() - - val useCase = LoginUseCase(mockAuthRepo, mockNavigation) - - // Act - useCase.execute("test@test.com", "password") - - // Assert - assertTrue(mockNavigation.navigationHistory.contains("dashboard")) -} -``` - -**Benefits:** -- βœ… No need for UI framework -- βœ… Fast test execution -- βœ… Easy to control behavior -- βœ… Test business logic in isolation - ---- - -## Testing Strategy - -### Test Pyramid with Hexagonal Architecture - -``` - β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” - β”‚ E2E Tests β”‚ 5% (Full app, real adapters) - β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ - β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” - β”‚ Integration Tests β”‚ 20% (Use cases + real adapters) - β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ - β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” - β”‚ Use Case Tests β”‚ 30% (Use cases + mock ports) - β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ - β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” - β”‚ Domain Tests β”‚ 45% (Models, validation, rules) - β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ -``` - -### Testing Layers - -#### 1. Domain Layer Tests (45%) - -**What to Test:** -- Domain models -- Validation rules -- Business rules -- Exception handling - -**Example:** -```kotlin -@Test -fun `should validate Turkish national ID correctly`() { - val result = ValidationRules.validateTurkishNationalId("12345678901") - assertTrue(result is ValidationResult.Error) - - val validResult = ValidationRules.validateTurkishNationalId("12345678900") - assertTrue(validResult is ValidationResult.Success) -} -``` - -#### 2. Use Case Tests (30%) - -**What to Test:** -- Use case logic -- Port interactions -- Error handling - -**Example:** -```kotlin -@Test -fun `should enroll face and show success notification`() = runTest { - // Arrange - val mockBiometricRepo = MockBiometricRepository().apply { - shouldSucceed = true - } - val mockNotification = MockNotificationService() - - val useCase = EnrollFaceUseCase(mockBiometricRepo, mockNotification) - - // Act - useCase.execute("user123", byteArrayOf()) - - // Assert - assertEquals(1, mockNotification.successMessages.size) - assertEquals("Face enrolled successfully!", mockNotification.successMessages.first()) -} -``` - -#### 3. Integration Tests (20%) - -**What to Test:** -- Use cases with real adapters -- Data flow through layers -- Error propagation - -**Example:** -```kotlin -@Test -fun `should retrieve users from API and update state`() = runTest { - // Arrange - val realApiClient = createTestApiClient() - val userRepository = UserRepositoryImpl(realApiClient, mockLogger) - val useCase = GetUsersUseCase(userRepository) - - // Act - val result = useCase.execute() - - // Assert - assertTrue(result.isSuccess) - assertTrue(result.getOrNull()!!.isNotEmpty()) -} -``` - -#### 4. E2E Tests (5%) - -**What to Test:** -- Complete user flows -- Real UI interactions -- All layers integrated - -**Example:** -```kotlin -@Test -fun `should complete enrollment flow`() { - // Arrange - composeTestRule.setContent { App() } - - // Act - composeTestRule.onNodeWithText("Enroll").performClick() - composeTestRule.onNodeWithTag("camera_preview").assertIsDisplayed() - composeTestRule.onNodeWithText("Capture").performClick() - - // Assert - composeTestRule.onNodeWithText("Enrollment successful").assertIsDisplayed() -} -``` - -### Mock Strategy - -**βœ… DO:** -- Mock ports (interfaces) -- Use fakes for complex behavior -- Verify interactions with mocks - -**❌ DON'T:** -- Mock domain models -- Mock value objects -- Mock implementation details - ---- - -## Best Practices - -### 1. Keep Core Pure - -**βœ… DO:** -```kotlin -// Pure business logic in core -class ValidateUserUseCase { - fun execute(user: User): ValidationResult { - if (user.email.isEmpty()) { - return ValidationResult.Error("Email is required") - } - return ValidationResult.Success - } -} -``` - -**❌ DON'T:** -```kotlin -// Core depending on Android framework -class ValidateUserUseCase( - private val context: Context // ❌ Android dependency -) { - fun execute(user: User): ValidationResult { - val errorMessage = context.getString(R.string.email_required) // ❌ - // ... - } -} -``` - -### 2. Use Ports for External Interactions - -**βœ… DO:** -```kotlin -class EnrollFaceUseCase( - private val cameraService: ICameraService, // βœ… Port - private val biometricRepo: BiometricRepository // βœ… Port -) { - suspend fun execute() { - val imageBytes = cameraService.captureImage().getOrThrow() - biometricRepo.enrollFace("user123", imageBytes) - } -} -``` - -**❌ DON'T:** -```kotlin -class EnrollFaceUseCase( - private val cameraX: CameraXImpl, // ❌ Concrete Android class - private val database: RoomDatabase // ❌ Concrete database -) { - // ... -} -``` - -### 3. Keep Adapters Thin - -**βœ… DO:** -```kotlin -class UserRepositoryImpl( - private val apiClient: IdentityApi -) : UserRepository { - override suspend fun getUsers(): Result> { - return try { - val dtos = apiClient.getUsers() - Result.success(dtos.map { it.toDomain() }) // βœ… Simple transformation - } catch (e: Exception) { - Result.failure(e.toAppException()) - } - } -} -``` - -**❌ DON'T:** -```kotlin -class UserRepositoryImpl( - private val apiClient: IdentityApi -) : UserRepository { - override suspend fun getUsers(): Result> { - return try { - val dtos = apiClient.getUsers() - - // ❌ Business logic in adapter - val filteredUsers = dtos.filter { it.isActive } - val sortedUsers = filteredUsers.sortedBy { it.name } - - Result.success(sortedUsers.map { it.toDomain() }) - } catch (e: Exception) { - Result.failure(e.toAppException()) - } - } -} -``` - -**Instead, put business logic in use case:** -```kotlin -class GetActiveUsersUseCase( - private val userRepository: UserRepository -) { - suspend fun execute(): Result> { - return userRepository.getUsers() - .map { users -> - users.filter { it.isActive } // βœ… Business logic in core - .sortedBy { it.name } - } - } -} -``` - -### 4. Use Factory Pattern for Adapters - -**βœ… DO:** -```kotlin -val platformModule = module { - single { createPlatformServiceFactory() } - single { get().createCameraService() } -} -``` - -**❌ DON'T:** -```kotlin -val platformModule = module { - single { DesktopCameraServiceImpl() } // ❌ Platform-specific -} -``` - -### 5. Design Ports Before Implementation - -**Process:** -1. Identify external interaction -2. Define port interface -3. Implement adapter -4. Test with mock - -**Example:** -```kotlin -// 1. Identify: Need to send push notifications - -// 2. Define port -interface IPushNotificationService { - suspend fun sendNotification(userId: String, message: String): Result -} - -// 3. Implement adapter -class FirebasePushNotificationService : IPushNotificationService { - override suspend fun sendNotification(userId: String, message: String): Result { - // Firebase implementation - } -} - -// 4. Test with mock -class MockPushNotificationService : IPushNotificationService { - val sentNotifications = mutableListOf>() - - override suspend fun sendNotification(userId: String, message: String): Result { - sentNotifications.add(userId to message) - return Result.success(Unit) - } -} -``` - ---- - -## Conclusion - -### Benefits Achieved - -βœ… **Platform Independence** - Core logic works everywhere -βœ… **Testability** - Easy to test with mocks -βœ… **Flexibility** - Swap implementations easily -βœ… **Maintainability** - Clear separation of concerns -βœ… **SOLID Compliance** - All principles followed -βœ… **Extensibility** - Easy to add new features - -### Architecture Grade - -**Before Hexagonal Ports:** B+ -**After Hexagonal Ports:** A++ - -### Next Steps - -1. βœ… Implement remaining platform factories (Android, iOS) -2. ⏳ Increase test coverage using mock ports -3. ⏳ Add more integration tests -4. ⏳ Document adapter implementation guidelines - ---- - -**Document Version:** 1.0.0 -**Last Updated:** 2026-01-19 -**Next Review:** After platform adapter implementations diff --git a/docs/archive/2026-04-16/HOW_TO_RUN_AND_TEST.md b/docs/archive/2026-04-16/HOW_TO_RUN_AND_TEST.md deleted file mode 100644 index b38b1510..00000000 --- a/docs/archive/2026-04-16/HOW_TO_RUN_AND_TEST.md +++ /dev/null @@ -1,476 +0,0 @@ -# FIVUCSAS Mobile App - How to Run and Test - -## Overview - -This is a **Kotlin Multiplatform (KMP) + Compose Multiplatform (CMP)** project that targets: - -- **Android** - Native Android app -- **iOS** - Native iOS app -- **Desktop** - JVM desktop application (Windows, macOS, Linux) - -## Architecture - -### Technology Stack - -- **Kotlin 1.9.21** - Programming language -- **Compose Multiplatform 1.5.11** - UI framework -- **Ktor 2.3.5** - Networking client -- **Kotlinx Serialization** - JSON handling -- **Kotlinx Coroutines** - Async/await -- **Kotlinx DateTime** - Date/time handling - -### Project Structure - -``` -mobile-app/ -β”œβ”€β”€ shared/ # Shared business logic (KMP) -β”‚ β”œβ”€β”€ commonMain/ # Common code for all platforms -β”‚ β”œβ”€β”€ androidMain/ # Android-specific implementations -β”‚ β”œβ”€β”€ iosMain/ # iOS-specific implementations -β”‚ └── desktopMain/ # Desktop-specific implementations -β”œβ”€β”€ androidApp/ # Android app entry point -β”œβ”€β”€ desktopApp/ # Desktop app entry point -└── iosApp/ # iOS app (Xcode project) -``` - -## Prerequisites - -### Required Tools - -1. **JDK 11+** (for Android/Shared) and **JDK 21** (for Desktop) - - Download: https://adoptium.net/ - - Verify: `java -version` - -2. **Android Studio** (for Android development) - - Download: https://developer.android.com/studio - - Install Android SDK 24-34 - - Install Android Build Tools - -3. **Xcode 14+** (for iOS development - macOS only) - - Install from App Store - - Install Command Line Tools: `xcode-select --install` - -4. **Gradle 8.14+** (included in project) - - Verify: `.\gradlew --version` - -### Recommended Tools - -- **IntelliJ IDEA 2023.3+** - Best IDE for KMP development -- **Kotlin Plugin** - Should be bundled with IntelliJ -- **Compose Multiplatform IDE Support Plugin** - -## How to Run - -### 1. Desktop Application - -The desktop app is the **easiest to run** and requires no emulator/device. - -```bash -# Navigate to project root -cd C:\Users\ahabg\OneDrive\Belgeler\GitHub\FIVUCSAS\mobile-app - -# Run desktop app -.\gradlew :desktopApp:run - -# Or build standalone JAR -.\gradlew :desktopApp:packageUberJarForCurrentOS -``` - -**Output**: Executable JAR in `desktopApp/build/compose/jars/` - -**System Requirements**: - -- Windows: Windows 10+ -- macOS: macOS 10.14+ -- Linux: Any modern distribution - -### 2. Android Application - -#### Option A: Using Android Studio (Recommended) - -1. Open the project in Android Studio -2. Wait for Gradle sync to complete -3. Select `androidApp` configuration -4. Click Run (▢️) or press `Shift+F10` - -#### Option B: Using Command Line - -```bash -# Build debug APK -.\gradlew :androidApp:assembleDebug - -# Install on connected device/emulator -.\gradlew :androidApp:installDebug - -# Build and run -.\gradlew :androidApp:installDebug && adb shell am start -n com.fivucsas.mobile/.MainActivity -``` - -**Output**: APK in `androidApp/build/outputs/apk/debug/` - -**Requirements**: - -- Android 7.0+ (API 24+) -- Minimum 2GB RAM -- Camera permission for biometric features - -### 3. iOS Application (macOS only) - -```bash -# Open iOS project in Xcode -open iosApp/iosApp.xcworkspace - -# Or build from command line -.\gradlew :shared:linkDebugFrameworkIosArm64 # For physical device -.\gradlew :shared:linkDebugFrameworkIosX64 # For simulator - -# Then open in Xcode and run -``` - -**Requirements**: - -- macOS 12.0+ -- Xcode 14.0+ -- iOS 12.0+ -- Apple Developer Account (for device deployment) - -## How to Build - -### Build All Targets - -```bash -# Build everything (Desktop + Android) -.\gradlew build - -# Build specific targets -.\gradlew :desktopApp:assemble # Desktop -.\gradlew :androidApp:assembleDebug # Android debug -.\gradlew :androidApp:assembleRelease # Android release -``` - -### Build for Production - -#### Desktop - -```bash -# Create distributable packages -.\gradlew :desktopApp:packageDistributionForCurrentOS - -# Creates: -# - Windows: MSI installer -# - macOS: DMG -# - Linux: DEB package -``` - -Output: `desktopApp/build/compose/binaries/main/` - -#### Android - -```bash -# Build release APK (split by ABI) -.\gradlew :androidApp:assembleRelease - -# Build App Bundle (for Play Store) -.\gradlew :androidApp:bundleRelease -``` - -**Before release build**, configure signing in `androidApp/build.gradle.kts`: - -```kotlin -signingConfigs { - create("release") { - storeFile = file("path/to/keystore.jks") - storePassword = System.getenv("KEYSTORE_PASSWORD") - keyAlias = System.getenv("KEY_ALIAS") - keyPassword = System.getenv("KEY_PASSWORD") - } -} -``` - -#### iOS - -1. Open `iosApp/iosApp.xcworkspace` in Xcode -2. Select `Product` β†’ `Archive` -3. Follow App Store Connect upload process - -## Testing - -### Unit Tests - -```bash -# Run all tests -.\gradlew test - -# Run specific module tests -.\gradlew :shared:testDebugUnitTest -.\gradlew :androidApp:testDebugUnitTest -.\gradlew :desktopApp:test - -# With coverage report -.\gradlew test jacocoTestReport -``` - -**Coverage reports**: `build/reports/jacoco/test/html/index.html` - -### Android Instrumented Tests - -```bash -# Run on connected device/emulator -.\gradlew :androidApp:connectedDebugAndroidTest -``` - -### Desktop Integration Tests - -```bash -.\gradlew :desktopApp:test -``` - -## Troubleshooting - -### Common Issues - -#### 1. Kotlin/Compose Version Mismatch - -**Error**: `Compose Multiplatform X doesn't support Kotlin Y` - -**Solution**: Check compatibility matrix: - -- Compose 1.5.11 β†’ Kotlin 1.9.21 βœ… -- See: https://github.com/JetBrains/compose-jb/blob/master/VERSIONING.md - -#### 2. iOS Build Fails (Windows) - -**Error**: iOS targets cannot be built on Windows - -**Solution**: This is expected. iOS development requires macOS. Add to `gradle.properties`: - -```properties -kotlin.native.ignoreDisabledTargets=true -``` - -#### 3. Gradle Daemon Issues - -```bash -# Stop all daemons -.\gradlew --stop - -# Clean and rebuild -.\gradlew clean build -``` - -#### 4. Android Build Fails - -```bash -# Invalidate caches -# In Android Studio: File β†’ Invalidate Caches β†’ Invalidate and Restart - -# Or from command line -.\gradlew clean -Remove-Item -Recurse -Force .gradle, build, */build -.\gradlew build -``` - -#### 5. Desktop App Doesn't Start - -**Error**: `UnsupportedClassVersionError` - -**Solution**: Ensure JDK 21 is installed and JAVA_HOME is set: - -```bash -# Check Java version -java -version # Should show 21.x - -# Set JAVA_HOME -$env:JAVA_HOME = "C:\Program Files\Java\jdk-21" -``` - -#### 6. Camera/Permissions Issues on Android - -Add to `androidApp/src/main/AndroidManifest.xml`: - -```xml - - - -``` - -## Configuration - -### Environment Variables - -Create `.env` file in project root: - -```properties -# API Configuration -API_BASE_URL=http://10.0.2.2:8080/api/v1 # Android emulator -# API_BASE_URL=http://localhost:8080/api/v1 # Desktop/iOS simulator - -BIOMETRIC_API_URL=http://10.0.2.2:8001/api/v1 - -# App Configuration -APP_NAME=FIVUCSAS -ENVIRONMENT=development -LOG_LEVEL=DEBUG -``` - -**Note**: Android emulator uses `10.0.2.2` to access host machine's `localhost`. - -### Gradle Properties - -Edit `gradle.properties`: - -```properties -# Performance -org.gradle.jvmargs=-Xmx4096m -Dfile.encoding=UTF-8 -org.gradle.parallel=true -org.gradle.caching=true - -# Kotlin -kotlin.code.style=official -kotlin.native.ignoreDisabledTargets=true - -# Android -android.useAndroidX=true -android.enableJetifier=true -``` - -## Development Workflow - -### 1. Project Setup - -```bash -# Clone and setup -git clone -cd mobile-app - -# Build shared module first -.\gradlew :shared:build - -# Run desktop app for quick testing -.\gradlew :desktopApp:run -``` - -### 2. Making Changes - -```bash -# After code changes, rebuild shared module -.\gradlew :shared:build - -# Then run target platform -.\gradlew :desktopApp:run # Desktop -.\gradlew :androidApp:installDebug # Android -``` - -### 3. Code Quality - -```bash -# Kotlin linting -.\gradlew ktlintCheck - -# Format code -.\gradlew ktlintFormat - -# Static analysis -.\gradlew detekt -``` - -## IDE Setup - -### IntelliJ IDEA / Android Studio - -1. **Import Project** - - `File` β†’ `Open` β†’ Select `mobile-app` folder - - Wait for Gradle sync - -2. **Configure Run Configurations** - - **Desktop:** - - Main class: `com.fivucsas.desktop.MainKt` - - Module: `desktopApp.main` - - JRE: 21 - - **Android:** - - Module: `androidApp` - - Use existing `androidApp` configuration - -3. **Enable Compose Support** - - `Settings` β†’ `Languages & Frameworks` β†’ `Kotlin` β†’ Enable "Compose" - -### VS Code - -Install extensions: - -- Kotlin Language -- Gradle for Java - -## Performance Optimization - -### Desktop - -```kotlin -// In desktopApp/src/desktopMain/kotlin/Main.kt -application { - nativeDistributions { - targetFormats(TargetFormat.Msi) - packageName = "FIVUCSAS" - packageVersion = "1.0.0" - - windows { - // Optimize Windows build - menuGroup = "FIVUCSAS" - perUserInstall = true - } - } -} -``` - -### Android - -```kotlin -// In androidApp/build.gradle.kts -android { - buildTypes { - release { - isMinifyEnabled = true - isShrinkResources = true - proguardFiles( - getDefaultProguardFile("proguard-android-optimize.txt"), - "proguard-rules.pro" - ) - } - } -} -``` - -## Next Steps - -After successfully running the app: - -1. **Configure Backend URLs** in - `shared/src/commonMain/kotlin/com/fivucsas/mobile/data/remote/ApiClient.kt` -2. **Test Authentication** - Register β†’ Login β†’ Logout flow -3. **Test Biometric Features** - Enroll β†’ Verify -4. **Review Architecture** - Check `shared/src/commonMain` for business logic -5. **Customize UI** - Modify Compose UI in respective platform modules - -## Additional Resources - -- **Kotlin Multiplatform**: https://kotlinlang.org/docs/multiplatform.html -- **Compose Multiplatform**: https://www.jetbrains.com/lp/compose-multiplatform/ -- **Ktor Client**: https://ktor.io/docs/client.html -- **Kotlinx Serialization**: https://github.com/Kotlin/kotlinx.serialization - -## Support - -For issues specific to: - -- **KMP Setup**: Check Kotlin Slack #multiplatform -- **Compose UI**: Check Kotlin Slack #compose -- **Android Issues**: Check Android Studio logs -- **iOS Issues**: Check Xcode console - ---- - -**Last Updated**: 2025-10-31 -**Kotlin Version**: 1.9.21 -**Compose Multiplatform Version**: 1.5.11 diff --git a/docs/archive/2026-04-16/QUICKSTART.md b/docs/archive/2026-04-16/QUICKSTART.md deleted file mode 100644 index 2cb2088d..00000000 --- a/docs/archive/2026-04-16/QUICKSTART.md +++ /dev/null @@ -1,211 +0,0 @@ -# Quick Start Guide - FIVUCSAS Client Apps - -This guide will help you set up and build the Kotlin Multiplatform client applications. - -## Prerequisites - -1. **JDK 17+** - - Download from: https://adoptium.net/ (Eclipse Temurin recommended) - - Verify: `java -version` - -2. **Android SDK** - - Install via Android Studio or command-line tools - - Set `ANDROID_HOME` environment variable - - Install API 34+ via SDK Manager - -3. **Android Studio** (recommended) - - Download from: https://developer.android.com/studio - - Install Kotlin Multiplatform plugin - -4. **Verify Installation** - ```bash - java -version # JDK 17+ - echo $ANDROID_HOME # Should point to Android SDK - ./gradlew --version # Gradle wrapper - ``` - -## Step-by-Step Setup - -### 1. Clone and Open - -```bash -# If cloning the parent repo -git clone --recurse-submodules -cd fivucsas/client-apps - -# Or if already cloned -cd client-apps -``` - -Open this folder in Android Studio as a Gradle project. - -### 2. Sync Gradle - -Android Studio will auto-sync on open. If not: -- File -> Sync Project with Gradle Files -- Or from terminal: `./gradlew :shared:compileKotlinAndroid` - -### 3. Build Android APK - -```bash -# Debug build -./gradlew :androidApp:assembleDebug - -# APK location: androidApp/build/outputs/apk/debug/androidApp-debug.apk -``` - -### 4. Run Desktop App - -```bash -./gradlew :desktopApp:run -``` - -### 5. Run Tests - -```bash -# Shared module unit tests -./gradlew :shared:testDebugUnitTest - -# All tests -./gradlew test -``` - -## Project Structure - -``` -client-apps/ -β”œβ”€β”€ shared/ # Shared KMP module -β”‚ └── src/ -β”‚ β”œβ”€β”€ commonMain/kotlin/com/fivucsas/shared/ -β”‚ β”‚ β”œβ”€β”€ config/ # AppConfig, UIDimens, BiometricConfig -β”‚ β”‚ β”œβ”€β”€ domain/ # Models, use cases, repository interfaces -β”‚ β”‚ β”œβ”€β”€ data/ # Repository impls, API services -β”‚ β”‚ β”œβ”€β”€ presentation/ # ViewModels, UI state -β”‚ β”‚ β”œβ”€β”€ platform/ # ICameraService, ILogger, ISecureStorage -β”‚ β”‚ └── ui/ # Shared Compose components -β”‚ β”‚ β”œβ”€β”€ theme/ # AppColors, AppTypography, AppShapes -β”‚ β”‚ └── components/ # atoms/, molecules/, organisms/ -β”‚ └── commonTest/ # ViewModel tests + mocks -β”œβ”€β”€ androidApp/ # Android app module -β”‚ └── src/main/ -β”‚ β”œβ”€β”€ kotlin/ # Android-specific implementations -β”‚ └── AndroidManifest.xml # Permissions -β”œβ”€β”€ desktopApp/ # Desktop (JVM) app module -β”‚ └── src/desktopMain/kotlin/ # Desktop-specific implementations -β”œβ”€β”€ build.gradle.kts -β”œβ”€β”€ settings.gradle.kts -└── gradle.properties -``` - -## Configuration - -### API Endpoints - -Edit `shared/src/commonMain/kotlin/com/fivucsas/shared/config/AppConfig.kt`: - -```kotlin -object Api { - const val BASE_URL = "https://api.fivucsas.com/api/v1" - // For local development: - // const val BASE_URL = "http://10.0.2.2:8080/api/v1" // Android emulator - // const val BASE_URL = "http://localhost:8080/api/v1" // Desktop/iOS -} -``` - -### Android Permissions - -The `AndroidManifest.xml` includes: -- `INTERNET` -- API communication -- `CAMERA` -- Face detection/enrollment -- `RECORD_AUDIO` -- Voice verification -- `NFC` -- Document reading - -## Build for Production - -### Android - -```bash -# Release APK (requires signing config) -./gradlew :androidApp:assembleRelease - -# GitHub Actions builds APK automatically on push to main -``` - -### Desktop - -```bash -# Run -./gradlew :desktopApp:run - -# Package (platform-specific installer) -./gradlew :desktopApp:packageDistributionForCurrentOS -``` - -## Useful Commands - -```bash -# Clean build -./gradlew clean - -# Dependency tree -./gradlew :shared:dependencies - -# Run linter -./gradlew lint - -# Check for outdated dependencies -./gradlew dependencyUpdates - -# List all available tasks -./gradlew tasks --all -``` - -## Troubleshooting - -### Gradle sync fails -```bash -./gradlew --stop -./gradlew clean -./gradlew :shared:compileKotlinAndroid -``` - -### "SDK location not found" -Create `local.properties` in the project root: -```properties -sdk.dir=/path/to/android/sdk -``` - -### Build errors after adding dependencies -```bash -./gradlew clean -./gradlew :androidApp:assembleDebug -``` - -### Desktop app crashes on launch -Ensure JDK 17+ is used: -```bash -java -version -``` - -## CI/CD - -Both Android and iOS builds run automatically via GitHub Actions: -- **Android Build**: triggers on push to `main`, produces debug APK artifact -- **iOS Build**: triggers on push to `main`, builds framework - -## Next Steps - -1. Read `README.md` for full documentation -2. Explore the `shared/` module for business logic -3. Check `QUICK_REFERENCE.md` for command cheatsheet -4. Start backend services before running the app - -## Support - -- Architecture docs: `README.md` -- Parent project: `../CLAUDE.md` -- API docs: https://api.fivucsas.com/swagger-ui.html - ---- - -*Last updated: 2026-04-04* diff --git a/docs/archive/2026-04-16/QUICK_REFERENCE.md b/docs/archive/2026-04-16/QUICK_REFERENCE.md deleted file mode 100644 index 42716fca..00000000 --- a/docs/archive/2026-04-16/QUICK_REFERENCE.md +++ /dev/null @@ -1,211 +0,0 @@ -# Quick Reference - FIVUCSAS Client Apps - -**Kotlin Multiplatform (KMP) + Compose Multiplatform cross-platform application** - ---- - -## Platforms - -- Android -- Full support (APK via GitHub Releases) -- iOS -- Build ready (CI workflow GREEN) -- Desktop (JVM) -- Full support - -**One shared codebase, all platforms.** - ---- - -## Super Quick Start - -```bash -# 1. Build Android APK -./gradlew :androidApp:assembleDebug - -# 2. Run desktop app -./gradlew :desktopApp:run - -# 3. Run tests -./gradlew :shared:testDebugUnitTest -``` - ---- - -## Documentation Map - -| File | What It Is | Read When | -|-------------------------|--------------------------------|----------------------| -| **GET_STARTED.md** | Overview and quick start | First time here | -| **QUICKSTART.md** | Detailed setup steps | Setting up project | -| **QUICK_REFERENCE.md** | Command reference (this file) | Quick lookup | -| **README.md** | Full documentation | Reference | - ---- - -## Android Studio Workflow - -### Setup (One Time) - -1. Install Android Studio (Ladybug+) -2. Install Kotlin Multiplatform plugin -3. Open this folder as project -4. Sync Gradle -5. Create emulator or connect device - -### Daily Development - -1. Open project in Android Studio -2. Start emulator (Tools -> Device Manager) -3. Select `androidApp` configuration -4. Click Run -5. Edit shared code -> rebuild -6. Commit and push - -### Key Shortcuts - -- **Shift+F10** -- Run app -- **Ctrl+Alt+L** -- Format code -- **Alt+Enter** -- Quick fix -- **Shift Shift** -- Search everything -- **Ctrl+B** -- Go to definition - ---- - -## Project Structure - -``` -client-apps/ -β”œβ”€β”€ shared/ # Shared KMP module (business logic + UI) -β”‚ └── src/ -β”‚ β”œβ”€β”€ commonMain/ # Common Kotlin code -β”‚ └── commonTest/ # Shared tests -β”œβ”€β”€ androidApp/ # Android application -β”œβ”€β”€ desktopApp/ # Desktop (JVM) application -β”œβ”€β”€ build.gradle.kts # Root build config -└── settings.gradle.kts # Module declarations -``` - ---- - -## Common Commands - -```bash -# Build -./gradlew :androidApp:assembleDebug # Android debug APK -./gradlew :androidApp:assembleRelease # Android release APK -./gradlew :desktopApp:run # Run desktop app - -# Test -./gradlew test # All tests -./gradlew :shared:testDebugUnitTest # Shared module tests only - -# Maintenance -./gradlew clean # Clean build -./gradlew dependencies # Show dependency tree -./gradlew lint # Run linter - -# Useful -./gradlew tasks --all # List all available tasks -``` - ---- - -## Architecture Quick Reference - -``` -β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” -β”‚ Presentation (UI) β”‚ -β”‚ Compose screens + ViewModels β”‚ -β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ - β”‚ -β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” -β”‚ Domain (Business Logic) β”‚ -β”‚ Entities + Use Cases β”‚ -β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ - β”‚ -β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” -β”‚ Data (API, Storage) β”‚ -β”‚ Repositories + API clients β”‚ -β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ -``` - -**Data Flow:** -1. User taps button (Compose UI) -2. ViewModel calls UseCase (Domain) -3. UseCase calls Repository (Domain interface) -4. Repository fetches from API (Data layer) -5. Data flows back up -6. ViewModel emits new state -7. Compose UI recomposes - ---- - -## Platform Targets - -### Primary -- Android 8.0+ (API 26+) -- Desktop JVM (Windows, macOS, Linux) - -### Ready -- iOS 15.0+ (CI workflow configured) - ---- - -## Key Configuration Files - -| File | Purpose | -|------|---------| -| `shared/.../config/AppConfig.kt` | API URLs, timeouts, session settings | -| `shared/.../config/UIDimens.kt` | UI dimensions and spacing | -| `shared/.../config/BiometricConfig.kt` | Biometric thresholds | -| `shared/.../config/AnimationConfig.kt` | Animation timing | -| `gradle.properties` | Kotlin/Compose/AGP versions | -| `androidApp/src/main/AndroidManifest.xml` | Android permissions | - ---- - -## Troubleshooting - -### Gradle sync fails -```bash -./gradlew --stop && ./gradlew clean -``` - -### "SDK location not found" -Create `local.properties`: -``` -sdk.dir=/path/to/android/sdk -``` - -### Build errors after dependency changes -```bash -./gradlew clean -./gradlew :shared:compileKotlinAndroid -``` - ---- - -## Features Implemented - -- [x] Admin Dashboard (user CRUD, search, analytics) -- [x] Kiosk Mode (enrollment, verification flows) -- [x] Face detection and liveness check -- [x] NFC document reading -- [x] Voice verification -- [x] FIDO2/WebAuthn (Android Credential Manager) -- [x] Shared Compose UI component library (Atomic Design) -- [x] 50+ ViewModel unit tests -- [x] Android + iOS CI workflows (GitHub Actions) -- [x] APK releases via GitHub Releases - ---- - -## Learning Resources - -- [Kotlin Multiplatform](https://kotlinlang.org/docs/multiplatform.html) -- [Compose Multiplatform](https://www.jetbrains.com/compose-multiplatform/) -- [Kotlin coroutines](https://kotlinlang.org/docs/coroutines-overview.html) -- [Material Design 3](https://m3.material.io/) -- [Android Credential Manager](https://developer.android.com/identity/sign-in/credential-manager) - ---- - -*Quick Reference v2.0 -- Updated 2026-04-04* diff --git a/docs/archive/2026-04-16/UX_DESIGN_GUIDE.md b/docs/archive/2026-04-16/UX_DESIGN_GUIDE.md deleted file mode 100644 index 9cce8c27..00000000 --- a/docs/archive/2026-04-16/UX_DESIGN_GUIDE.md +++ /dev/null @@ -1,1017 +0,0 @@ -# FIVUCSAS Application UX Design Guide - -**Version:** 2.0 -**Last Updated:** December 2025 -**Status:** Production Ready - -This document outlines the user experience (UX) design principles, design system, and application flow for the FIVUCSAS identity verification platform. The design prioritizes trust, simplicity, accessibility, and a high success rate for all users. - ---- - -## Table of Contents - -1. [UX Philosophy & Core Principles](#1-ux-philosophy--core-principles) -2. [Design System](#2-design-system) -3. [User Personas](#3-user-personas) -4. [Application Flows](#4-application-flows) -5. [Screen-by-Screen Design](#5-screen-by-screen-design) -6. [Component Library](#6-component-library) -7. [Accessibility Guidelines](#7-accessibility-guidelines) -8. [Micro-interactions & Animations](#8-micro-interactions--animations) -9. [Error Handling & Recovery](#9-error-handling--recovery) -10. [Form Design & Validation](#10-form-design--validation) -11. [Responsive Design](#11-responsive-design) -12. [Performance Guidelines](#12-performance-guidelines) -13. [Testing & Validation](#13-testing--validation) - ---- - -## 1. UX Philosophy & Core Principles - -The primary goal is to make the identity verification process feel secure, fast, and intuitive across all platforms. - -### Core Principles - -| Principle | Description | Implementation | -|-----------|-------------|----------------| -| **Trust & Transparency** | Users should always feel in control and informed | Clear privacy notices, data usage explanations, visible security indicators | -| **Simplicity & Guidance** | Clean, uncluttered interface with step-by-step instructions | Progressive disclosure, contextual help, visual guides | -| **Efficiency & Speed** | Process should be as fast as possible | Auto-capture, OCR, pre-filled forms, minimal steps | -| **Accessibility** | Usable by everyone, following WCAG 2.1 AA | Screen reader support, high contrast, keyboard navigation | -| **Consistency** | Same patterns across all platforms | Unified design system, shared components | -| **Forgiveness** | Easy error recovery | Clear error messages, undo options, retry flows | - -### **[CLAUDE'S ENHANCEMENT]** Cognitive Load Reduction - -> Design decisions should minimize cognitive load by: -> - **Chunking information**: Break complex tasks into 3-5 step wizards -> - **Recognition over recall**: Use visual cues instead of requiring memory -> - **Progressive disclosure**: Show only relevant options at each step -> - **Sensible defaults**: Pre-select the most common options -> - **Visible system status**: Always show where users are in a process - ---- - -## 2. Design System - -### 2.1 Color Palette - -#### Primary Colors -``` -Primary Blue: #1976D2 (Main actions, links, focus states) -Primary Light: #42A5F5 (Hover states, backgrounds) -Primary Dark: #1565C0 (Active states, emphasis) -``` - -#### Secondary Colors -``` -Secondary Purple: #9C27B0 (Accent, highlights) -Secondary Light: #BA68C8 (Hover states) -Secondary Dark: #7B1FA2 (Active states) -``` - -#### Semantic Colors -``` -Success Green: #2E7D32 (Confirmations, completed states) -Success Light: #4CAF50 (Backgrounds, icons) -Error Red: #D32F2F (Errors, destructive actions) -Error Light: #EF5350 (Backgrounds) -Warning Orange: #ED6C02 (Warnings, attention needed) -Warning Light: #FF9800 (Backgrounds) -Info Blue: #0288D1 (Information, tips) -Info Light: #03A9F4 (Backgrounds) -``` - -#### Neutral Colors -``` -Background: #F5F5F5 (Page background) -Surface: #FFFFFF (Cards, panels) -Border: #E0E0E0 (Dividers, borders) -Text Primary: #212121 (Headings, primary text) -Text Secondary: #757575 (Secondary text, captions) -Text Disabled: #BDBDBD (Disabled states) -``` - -### **[CLAUDE'S ENHANCEMENT]** Dark Mode Colors - -> For dark mode support (recommended for kiosk environments): -> ``` -> Dark Background: #121212 -> Dark Surface: #1E1E1E -> Dark Surface 2: #2D2D2D -> Dark Text Primary: #FFFFFF -> Dark Text Secondary: #B3B3B3 -> Dark Primary: #90CAF9 -> Dark Success: #81C784 -> Dark Error: #EF5350 -> ``` - -### 2.2 Typography - -#### Font Family -``` -Primary: "Roboto", "Helvetica Neue", Arial, sans-serif -Monospace: "Roboto Mono", "Consolas", monospace -``` - -#### Type Scale -| Name | Size | Weight | Line Height | Use Case | -|------|------|--------|-------------|----------| -| Display | 56sp | 400 | 64sp | Kiosk welcome screens | -| H1 | 40px / 2.5rem | 500 | 48px | Page titles | -| H2 | 32px / 2rem | 500 | 40px | Section headers | -| H3 | 28px / 1.75rem | 500 | 36px | Card titles | -| H4 | 24px / 1.5rem | 500 | 32px | Subsections | -| H5 | 20px / 1.25rem | 500 | 28px | List headers | -| H6 | 16px / 1rem | 500 | 24px | Small headers | -| Body 1 | 16px / 1rem | 400 | 24px | Primary text | -| Body 2 | 14px / 0.875rem | 400 | 20px | Secondary text | -| Caption | 12px / 0.75rem | 400 | 16px | Captions, hints | -| Button | 14px / 0.875rem | 500 | 16px | Buttons | - -### 2.3 Spacing System - -``` -xs: 4px (0.25rem) - Inline spacing, icon margins -sm: 8px (0.5rem) - Tight spacing -md: 16px (1rem) - Default spacing -lg: 24px (1.5rem) - Section spacing -xl: 32px (2rem) - Large gaps -xxl: 48px (3rem) - Page sections -xxxl: 64px (4rem) - Major separations -``` - -### 2.4 Elevation & Shadows - -| Level | Shadow | Use Case | -|-------|--------|----------| -| 0 | none | Flat elements | -| 1 | `0 1px 3px rgba(0,0,0,0.12)` | Subtle elevation (buttons) | -| 2 | `0 2px 4px rgba(0,0,0,0.1)` | Cards, panels | -| 3 | `0 4px 8px rgba(0,0,0,0.12)` | Dropdown menus | -| 4 | `0 8px 16px rgba(0,0,0,0.14)` | Dialogs, modals | -| 5 | `0 16px 24px rgba(0,0,0,0.16)` | Focus state overlays | - -### 2.5 Border Radius - -``` -Sharp: 0px - Tables, inline elements -Small: 4px - Chips, tags -Medium: 8px - Buttons, inputs, small cards -Large: 16px - Cards, panels -XLarge: 24px - Large cards, images -Full: 9999px - Pills, avatars, circles -``` - -### **[CLAUDE'S ENHANCEMENT]** Z-Index Scale - -> Consistent layering system: -> ``` -> Base: 0 - Default content -> Dropdown: 1000 - Dropdowns, autocomplete -> Sticky: 1100 - Sticky headers -> Modal: 1200 - Modal dialogs -> Popover: 1300 - Popovers, tooltips -> Toast: 1400 - Notifications, toasts -> Loading: 1500 - Global loading overlays -> ``` - ---- - -## 3. User Personas - -### 3.1 End User (Identity Verification) - -| Attribute | Details | -|-----------|---------| -| **Name** | Alex | -| **Age** | 25-65 | -| **Technical Skills** | Novice to Expert (design for novice) | -| **Goal** | Quickly and securely verify identity | -| **Concerns** | Data safety, process complexity, failure recovery | -| **Context** | Mobile device, kiosk, or web browser | - -### 3.2 System Administrator (Super Admin) - -| Attribute | Details | -|-----------|---------| -| **Name** | Sarah Chen | -| **Age** | 32 | -| **Technical Skills** | High | -| **Goal** | Manage platform, tenants, security | -| **Concerns** | System stability, security incidents, performance | -| **Tasks** | Tenant management, global metrics, security monitoring | - -### 3.3 Tenant Administrator - -| Attribute | Details | -|-----------|---------| -| **Name** | Michael Rodriguez | -| **Age** | 38 | -| **Technical Skills** | Medium-High | -| **Goal** | Manage organization users, enrollments | -| **Concerns** | Employee onboarding, compliance, authentication issues | -| **Tasks** | User CRUD, biometric enrollment, audit logs | - -### 3.4 Security Officer - -| Attribute | Details | -|-----------|---------| -| **Name** | Lisa Park | -| **Age** | 29 | -| **Technical Skills** | High | -| **Goal** | Monitor security, investigate incidents | -| **Concerns** | Threat detection, compliance reports, log noise | -| **Tasks** | Real-time monitoring, audit trails, reports | - -### **[CLAUDE'S ENHANCEMENT]** Support Staff Persona - -> | Attribute | Details | -> |-----------|---------| -> | **Name** | David Kim | -> | **Age** | 25 | -> | **Technical Skills** | Medium | -> | **Goal** | Resolve user issues quickly | -> | **Concerns** | Limited visibility, tool switching, escalations | -> | **Tasks** | User lookup, troubleshooting, re-enrollment assistance | -> | **Design Needs** | Quick search, guided troubleshooting flows, user history view | - ---- - -## 4. Application Flows - -### 4.1 End-User Verification Flow - -```mermaid -graph TD - A[Start Screen] --> B{Choose Document}; - B --> C[Scan ID Document]; - C --> D[Confirm Data]; - D --> E[Scan Face & Liveness Check]; - E --> F[Processing]; - F --> G{Verification Complete}; - - subgraph "1. Onboarding" - A - end - - subgraph "2. Document Scan" - B - C - D - end - - subgraph "3. Liveness & Face Scan" - E - end - - subgraph "4. Confirmation" - F - G - end -``` - -### 4.2 Kiosk Mode Flow - -``` -+-------------------------------------------------------------+ -| KIOSK MODE FLOW | -+-------------------------------------------------------------+ -| | -| [Welcome Screen] --> [Mode Selection] | -| | | | -| | +-----+-----+ | -| | v v | -| | [Enrollment] [Verification] | -| | | | | -| | +-----+---+ +-----+---+ | -| | v v v v | -| | [ID Input] [ID Input] | -| | | | | -| | v v | -| | [Face Cap] [Face Cap] | -| | | | | -| | v v | -| | [Liveness] [Liveness] | -| | | | | -| | v v | -| | [Process] [Process] | -| | | | | -| | v v | -| | [Success/ [Success/ | -| | Failure] Failure] | -| | | | | -| +--------+---------+ | -| | | -| v | -| [Return to Welcome] | -| | -+-------------------------------------------------------------+ -``` - -### 4.3 Admin Dashboard Flow - -``` -+-------------------------------------------------------------+ -| ADMIN DASHBOARD FLOW | -+-------------------------------------------------------------+ -| | -| [Login] --> [Dashboard Home] | -| | | -| +---------++---------+----------+---------+ | -| v v v v v | -| [Users] [Tenants] [Enrollments] [Audit] [Settings] | -| | | | | | | -| +----+----+ | +-----+----+ | | | -| v v v | v v v | | | -| [List][Add][View]| [List][Add][View] | | | -| | | | | -| [Tenant Detail] [Log View] [Config] | -| | -+-------------------------------------------------------------+ -``` - -### **[CLAUDE'S ENHANCEMENT]** Mobile App Flow with Offline Support - -> ``` -> +-------------------------------------------------------------+ -> | MOBILE APP FLOW | -> +-------------------------------------------------------------+ -> | | -> | [Splash] --> [Connection Check] | -> | | | -> | +-------+-------+ | -> | v v | -> | [Online] [Offline] | -> | | | | -> | v v | -> | [Full App] [Limited Mode] | -> | | | | -> | | * View cached data | -> | | * Queue verifications | -> | | * Sync when online | -> | | | | -> | +-------+-------+ | -> | v | -> | [Sync Indicator] | -> | (persistent status) | -> | | -> +-------------------------------------------------------------+ -> ``` - ---- - -## 5. Screen-by-Screen Design - -### 5.1 Welcome & Consent Screen - -**Purpose:** Welcome users and obtain consent for biometric data collection. - -| Element | Specification | -|---------|---------------| -| **Logo** | Tenant logo, max height 64px | -| **Headline** | H1: "Verify Your Identity" | -| **Body Text** | Brief, friendly explanation (max 2 sentences) | -| **Privacy Link** | Text link to privacy policy | -| **Consent Checkbox** | Required before proceeding | -| **Primary Button** | "Start Verification" (disabled until consent) | - -**Visual Layout:** -``` -+----------------------------------------+ -| | -| [LOGO] | -| | -| Verify Your Identity | -| | -| We need to confirm your identity. | -| This will only take a minute. | -| | -| [Privacy Policy Link] | -| | -| [ ] I agree to the collection of | -| my biometric data for identity | -| verification purposes. | -| | -| +------------------------------+ | -| | Start Verification | | -| +------------------------------+ | -| | -+----------------------------------------+ -``` - -### 5.2 ID Document Scan Screen - -**Purpose:** Capture clear image of identity document. - -| Element | Specification | -|---------|---------------| -| **Camera View** | Full-screen with overlay | -| **Overlay** | Rectangle matching ID aspect ratio (85.6mm x 53.98mm) | -| **Instructions** | Dynamic text based on detection state | -| **Auto-capture** | Triggers when conditions met | -| **Manual Button** | Fallback capture button | - -**Dynamic Instructions:** -``` -State: No Document --> "Position your ID card inside the frame" -State: Detecting --> "Hold steady..." -State: Glare Detected --> "Too much glare. Please adjust lighting" -State: Blurry --> "Image is blurry. Hold the camera steady" -State: Ready --> "Great! Capturing..." -``` - -### 5.3 Face Scan & Liveness Detection - -**Purpose:** Capture face and verify liveness through biometric puzzle. - -| Element | Specification | -|---------|---------------| -| **Camera View** | Front-facing, centered | -| **Face Overlay** | Oval guide, color-coded (red/yellow/green) | -| **Instructions** | Step-by-step liveness prompts | -| **Progress** | Visual progress indicator | -| **Audio** | Optional voice prompts | - -**Liveness Steps (Biometric Puzzle):** -``` -Step 1: Face Alignment --> "Position your face inside the oval" -Step 2: Hold Still --> "Hold still for 2 seconds" -Step 3: Blink --> "Blink slowly" -Step 4: Turn Right --> "Turn your head to the right" -Step 5: Turn Left --> "Turn your head to the left" -Step 6: Smile --> "Smile" -Step 7: Complete --> "Perfect! Processing..." -``` - -### **[CLAUDE'S ENHANCEMENT]** Enhanced Real-time Face Feedback - -> Provide multi-dimensional feedback during face capture: -> -> | Metric | Visual Indicator | Threshold | -> |--------|------------------|-----------| -> | Face Detected | Green checkmark | Yes/No | -> | Face Centered | Crosshair alignment | Within 10% of center | -> | Face Size | Size indicator bar | 30-70% of frame | -> | Lighting | Sun icon (dim/bright) | 100-200 lux range | -> | Face Angle | 3D head icon | Within 15 degrees of frontal | -> | Eye Contact | Eye icon | Both eyes visible | -> | Expression | Neutral face icon | Neutral required | -> -> Display these as a compact status panel above the camera view. - -### 5.4 Processing Screen - -**Purpose:** Show verification in progress. - -| Element | Specification | -|---------|---------------| -| **Animation** | Subtle loading animation | -| **Text** | "Verifying your identity..." | -| **Security Badge** | "End-to-end encrypted" | -| **Progress** | Optional progress percentage | - -### 5.5 Result Screens - -**Success State:** -``` -+----------------------------------------+ -| | -| [CHECK] | -| (Green checkmark) | -| | -| Verification Successful! | -| | -| You can now continue to | -| [Service Name]. | -| | -| +------------------------------+ | -| | Continue | | -| +------------------------------+ | -| | -+----------------------------------------+ -``` - -**Failure State:** -``` -+----------------------------------------+ -| | -| [X] | -| (Red X icon) | -| | -| Verification Failed | -| | -| We couldn't match your face to | -| your ID document. | -| | -| Tips: | -| * Use better lighting | -| * Remove glasses if possible | -| * Ensure face is clearly visible | -| | -| +----------------+ +-----------+ | -| | Try Again | | Support | | -| +----------------+ +-----------+ | -| | -+----------------------------------------+ -``` - ---- - -## 6. Component Library - -### 6.1 Buttons - -| Type | Use Case | Style | -|------|----------|-------| -| **Primary** | Main actions | Filled, primary color | -| **Secondary** | Alternative actions | Outlined, primary color | -| **Text** | Tertiary actions | No background, text only | -| **Destructive** | Delete, cancel | Red filled/outlined | -| **Gradient** | Kiosk CTAs | Blue gradient with shadow | - -**Button Sizes:** -``` -Small: Height 32px, padding 12px, font 12px -Medium: Height 40px, padding 16px, font 14px -Large: Height 48px, padding 20px, font 16px -XLarge: Height 56px, padding 24px, font 18px (kiosk) -``` - -### 6.2 Input Fields - -| State | Border Color | Background | Icon Color | -|-------|--------------|------------|------------| -| Default | #E0E0E0 | #FFFFFF | #757575 | -| Focused | #1976D2 | #FFFFFF | #1976D2 | -| Error | #D32F2F | #FFFFFF | #D32F2F | -| Disabled | #E0E0E0 | #F5F5F5 | #BDBDBD | -| Success | #2E7D32 | #FFFFFF | #2E7D32 | - -### 6.3 Cards - -``` -Standard Card: - - Background: #FFFFFF - - Border Radius: 16px - - Shadow: 0 2px 4px rgba(0,0,0,0.1) - - Padding: 16-24px - -Elevated Card: - - Background: #FFFFFF - - Border Radius: 16px - - Shadow: 0 8px 16px rgba(0,0,0,0.14) - - Padding: 24px -``` - -### 6.4 Status Indicators - -| Status | Background | Text | Icon | -|--------|------------|------|------| -| Active | #E8F5E9 | #2E7D32 | Check circle | -| Inactive | #EEEEEE | #757575 | Minus circle | -| Pending | #FFF3E0 | #E65100 | Clock | -| Locked | #FFEBEE | #C62828 | Lock | -| Verified | #E3F2FD | #1565C0 | Verified | - -### **[CLAUDE'S ENHANCEMENT]** Loading States - -> Every interactive element should have defined loading states: -> -> | Element | Loading Indicator | Duration | -> |---------|-------------------|----------| -> | Button | Inline spinner replacing text | Show after 300ms delay | -> | Page | Skeleton screens | Show immediately | -> | Table Row | Row shimmer animation | Show after 200ms | -> | Image | Blur-up placeholder | Progressive loading | -> | Form Submit | Button disabled + spinner | Until response | -> -> **Skeleton Screen Guidelines:** -> - Match exact layout of loaded content -> - Use subtle pulse animation (1.5s duration) -> - Gray tones: #F0F0F0 base, #E0E0E0 highlight - ---- - -## 7. Accessibility Guidelines - -### 7.1 WCAG 2.1 AA Compliance - -| Requirement | Implementation | -|-------------|----------------| -| **Color Contrast** | Minimum 4.5:1 for normal text, 3:1 for large text | -| **Focus Indicators** | 2px solid outline, 2px offset, primary color | -| **Touch Targets** | Minimum 44x44px (48x48px recommended) | -| **Text Scaling** | Support 200% zoom without horizontal scroll | -| **Motion** | Respect prefers-reduced-motion | - -### 7.2 Keyboard Navigation - -``` -Tab: Move to next focusable element -Shift+Tab: Move to previous focusable element -Enter: Activate buttons, submit forms -Space: Toggle checkboxes, activate buttons -Escape: Close modals, cancel operations -Arrow Keys: Navigate within menus, lists -``` - -### 7.3 Screen Reader Support - -| Element | ARIA Attribute | Example | -|---------|----------------|---------| -| Buttons | `aria-label` | "Submit enrollment form" | -| Forms | `aria-describedby` | Link to help text | -| Alerts | `role="alert"` | Error messages | -| Loading | `aria-busy="true"` | Processing states | -| Progress | `aria-valuenow` | Step 2 of 5 | - -### **[CLAUDE'S ENHANCEMENT]** Biometric Accessibility - -> Special considerations for users with disabilities during biometric capture: -> -> | Condition | Accommodation | -> |-----------|---------------| -> | **Visual Impairment** | Audio instructions, haptic feedback, high contrast mode | -> | **Motor Impairment** | Extended timeouts, stabilization assistance, wider tolerance | -> | **Cognitive** | Simple language, visual progress, break options | -> | **Hearing Impairment** | Visual-only cues, captions for audio | -> -> Implement accessible alternatives: -> - Audio-guided face positioning -> - Vibration feedback for alignment -> - Manual capture fallback -> - Support staff assistance mode - ---- - -## 8. Micro-interactions & Animations - -### 8.1 Animation Timing - -| Animation Type | Duration | Easing | -|----------------|----------|--------| -| Micro (feedback) | 100-150ms | ease-out | -| Small (buttons, toggles) | 200-250ms | ease-in-out | -| Medium (cards, panels) | 300-350ms | ease-in-out | -| Large (modals, pages) | 400-500ms | ease-out | - -### 8.2 Standard Animations - -| Animation | Use Case | Properties | -|-----------|----------|------------| -| Fade In | Elements appearing | opacity 0 to 1 | -| Slide Up | Toasts, modals | transform + opacity | -| Scale | Button press | scale 0.95 to 1 | -| Pulse | Loading, attention | opacity oscillation | -| Shake | Error feedback | horizontal offset | - -### **[CLAUDE'S ENHANCEMENT]** Animation Code Examples - -> ```css -> /* Button press feedback */ -> .button:active { -> transform: scale(0.98); -> transition: transform 100ms ease-out; -> } -> -> /* Success checkmark animation */ -> @keyframes checkmark { -> 0% { stroke-dashoffset: 100; } -> 100% { stroke-dashoffset: 0; } -> } -> -> /* Card hover elevation */ -> .card:hover { -> transform: translateY(-2px); -> box-shadow: 0 8px 16px rgba(0,0,0,0.14); -> transition: all 200ms ease-out; -> } -> -> /* Skeleton loading pulse */ -> @keyframes skeleton-pulse { -> 0%, 100% { opacity: 1; } -> 50% { opacity: 0.5; } -> } -> ``` - -### 8.3 Face Alignment Feedback Animation - -``` -State Transitions: -+--------------+ -| NO FACE | Red oval, pulsing outline -| DETECTED | Message: "Position your face" -+------+-------+ - | Face enters frame - v -+--------------+ -| ADJUSTING | Yellow oval, stabilizing -| | Message: "Almost there..." -+------+-------+ - | Face aligned - v -+--------------+ -| ALIGNED | Green oval, solid -| | Message: "Perfect! Hold still" -+--------------+ -``` - ---- - -## 9. Error Handling & Recovery - -### 9.1 Error Message Guidelines - -| Do | Don't | -|----|-------| -| Be specific about what went wrong | Use technical jargon | -| Provide actionable next steps | Blame the user | -| Offer alternatives | Use negative language | -| Keep it brief but complete | Show error codes only | - -### 9.2 Error Types & Responses - -| Error Type | Example Message | Recovery Action | -|------------|-----------------|-----------------| -| **Validation** | "Email format is invalid" | Highlight field, show correction | -| **Network** | "Connection lost. Retrying..." | Auto-retry with indicator | -| **Server** | "Something went wrong. Please try again." | Retry button | -| **Biometric** | "Face not detected. Please ensure good lighting." | Tips + retry | -| **Timeout** | "Session expired. Please start again." | Restart flow | - -### **[CLAUDE'S ENHANCEMENT]** Graceful Degradation Strategy - -> When critical features fail, provide fallbacks: -> -> | Feature | Failure | Fallback | -> |---------|---------|----------| -> | Camera | No permission | Manual photo upload | -> | OCR | Low accuracy | Manual data entry form | -> | Liveness | Repeated failure | Human review queue | -> | Network | Offline | Queue & sync later | -> | Face Match | Low confidence | Additional verification | -> -> Always inform users about alternative paths and estimated wait times. - -### 9.3 Toast Notifications - -| Type | Duration | Position | Color | -|------|----------|----------|-------| -| Success | 3 seconds | Top center | Green | -| Error | 5 seconds + dismiss | Top center | Red | -| Warning | 4 seconds | Top center | Orange | -| Info | 3 seconds | Top center | Blue | - ---- - -## 10. Form Design & Validation - -### 10.1 Field Validation Rules - -| Field Type | Validation | Error Message | -|------------|------------|---------------| -| Email | RFC 5322 regex | "Enter a valid email address" | -| Password | Min 8 chars, upper, lower, number | "Password must be 8+ chars with mixed case and number" | -| Phone | Country-specific format | "Enter a valid phone number" | -| ID Number | Country-specific (TR: 11 digits) | "ID number must be 11 digits" | -| Name | 2-50 chars, letters/spaces | "Name should be 2-50 characters" | - -### 10.2 Validation Timing - -| Event | Action | -|-------|--------| -| On Focus | Clear previous error | -| On Input | Debounced validation (300ms) | -| On Blur | Immediate validation | -| On Submit | Validate all, focus first error | - -### **[CLAUDE'S ENHANCEMENT]** Inline Validation UX - -> Best practices for real-time validation: -> -> 1. **Don't validate too early**: Wait until user has finished typing (blur or 1s pause) -> 2. **Validate continuously once touched**: After first blur, validate on every change -> 3. **Success indicators**: Show green checkmark when field is valid -> 4. **Character counters**: For text areas, show "X/max" counter -> 5. **Password strength**: Visual meter (weak/medium/strong) -> -> ``` -> +-------------------------------------+ -> | Password [x]| -> | ************ | -> +-------------------------------------+ -> Strength: [========--] Strong -> [x] 8+ characters [x] Uppercase [x] Number -> ``` - -### 10.3 Form Layout - -``` -Single Column (Mobile/Simple Forms): -+------------------------------------+ -| Label | -| +--------------------------------+ | -| | Input | | -| +--------------------------------+ | -| Helper text or error | -+------------------------------------+ - -Two Column (Desktop/Complex Forms): -+-----------------+ +-----------------+ -| First Name | | Last Name | -| [___________] | | [___________] | -+-----------------+ +-----------------+ -``` - ---- - -## 11. Responsive Design - -### 11.1 Breakpoints - -| Name | Width | Target | -|------|-------|--------| -| Mobile S | 320px | Small phones | -| Mobile M | 375px | Standard phones | -| Mobile L | 425px | Large phones | -| Tablet | 768px | Tablets portrait | -| Laptop | 1024px | Small laptops | -| Desktop | 1440px | Standard desktop | -| Large | 1920px+ | Large monitors | - -### 11.2 Layout Adaptations - -| Element | Mobile | Tablet | Desktop | -|---------|--------|--------|---------| -| Navigation | Bottom nav | Side rail | Side drawer | -| Grid | 1 column | 2 columns | 3-4 columns | -| Cards | Full width | 2 per row | 3-4 per row | -| Modals | Full screen | Centered | Centered | -| Tables | Cards | Horizontal scroll | Full table | - -### **[CLAUDE'S ENHANCEMENT]** Kiosk-Specific Responsive Design - -> For kiosk mode (touch-first, larger displays): -> -> | Element | Standard | Kiosk Mode | -> |---------|----------|------------| -> | Touch targets | 44px min | 64px min | -> | Font size | 16px body | 20px body | -> | Button height | 48px | 64px | -> | Spacing | 16px | 24px | -> | Icons | 24px | 32px | -> -> Kiosk displays should assume: -> - No keyboard (on-screen keyboard for input) -> - Touch-only interaction -> - Standing user (eye level 150-180cm) -> - Viewing distance 50-100cm - ---- - -## 12. Performance Guidelines - -### 12.1 Loading Time Targets - -| Metric | Target | Acceptable | -|--------|--------|------------| -| First Contentful Paint | < 1.5s | < 2.5s | -| Time to Interactive | < 3.0s | < 5.0s | -| Largest Contentful Paint | < 2.5s | < 4.0s | -| Cumulative Layout Shift | < 0.1 | < 0.25 | -| First Input Delay | < 100ms | < 300ms | - -### 12.2 Perceived Performance - -| Technique | Implementation | -|-----------|----------------| -| Skeleton screens | Show immediately while loading | -| Progressive images | Blur-up / Low-quality placeholder | -| Optimistic UI | Update UI before server confirms | -| Lazy loading | Load below-fold content on demand | -| Preloading | Preload likely next screens | - -### **[CLAUDE'S ENHANCEMENT]** Camera Performance Optimization - -> For biometric capture, optimize camera performance: -> -> | Setting | Recommendation | -> |---------|----------------| -> | Resolution | 720p for preview, 1080p for capture | -> | Frame rate | 30fps for preview, single frame for capture | -> | Auto-focus | Enable, debounce detection | -> | Processing | Offload to worker thread | -> | Memory | Release camera when not in use | -> -> Face detection should run at minimum 10fps for smooth UX. - ---- - -## 13. Testing & Validation - -### 13.1 UX Testing Checklist - -**Accessibility:** -- [ ] Screen reader navigation works -- [ ] Keyboard-only navigation works -- [ ] Color contrast meets WCAG AA -- [ ] Focus indicators visible -- [ ] Touch targets adequate - -**Responsiveness:** -- [ ] Mobile layout correct (320-425px) -- [ ] Tablet layout correct (768px) -- [ ] Desktop layout correct (1024px+) -- [ ] No horizontal scroll -- [ ] Images scale properly - -**Performance:** -- [ ] Page loads < 3s -- [ ] Animations smooth (60fps) -- [ ] No layout shift -- [ ] Loading states present - -**Error Handling:** -- [ ] Validation messages clear -- [ ] Recovery paths available -- [ ] Network errors handled -- [ ] Empty states designed - -### 13.2 Usability Testing Scenarios - -| Scenario | Success Criteria | -|----------|------------------| -| First-time enrollment | Complete in < 3 minutes | -| Repeat verification | Complete in < 1 minute | -| Failed verification | Understand error, retry successfully | -| Admin user search | Find user in < 30 seconds | -| Audit log review | Filter results in < 10 seconds | - -### **[CLAUDE'S ENHANCEMENT]** A/B Testing Recommendations - -> Key areas to A/B test for conversion optimization: -> -> | Element | Variants to Test | -> |---------|------------------| -> | CTA button | Color, text, size, position | -> | Consent flow | Single checkbox vs. expandable | -> | Progress indicator | Steps vs. percentage | -> | Face guide | Oval vs. rectangle vs. animated | -> | Error messages | Technical vs. friendly tone | -> | Success animation | Checkmark vs. confetti | -> -> Track completion rate, time to complete, and error recovery rate. - ---- - -## Appendix A: Icon Library - -Use Material Design Icons (MDI) as the primary icon set. - -| Category | Common Icons | -|----------|--------------| -| Navigation | menu, arrow_back, close, expand_more | -| Actions | add, edit, delete, search, refresh | -| Status | check_circle, error, warning, info | -| User | person, group, admin_panel_settings | -| Security | lock, fingerprint, verified_user | -| Biometric | face, camera, photo_camera | - ---- - -## Appendix B: Glossary - -| Term | Definition | -|------|------------| -| **Liveness Detection** | Verification that user is physically present (not a photo) | -| **Biometric Puzzle** | Series of actions to prove liveness (blink, turn, smile) | -| **OCR** | Optical Character Recognition for document reading | -| **Tenant** | Organization using the FIVUCSAS platform | -| **Embedding** | Mathematical representation of face for comparison | -| **FAR** | False Acceptance Rate | -| **FRR** | False Rejection Rate | - ---- - -## Appendix C: Key Components & Rationale - -- **Dynamic Instructions:** Text that changes based on user action (or inaction) is key to guiding users through the complex scanning processes. This reduces errors and frustration. -- **Real-time Feedback:** Visual cues like the color-changing frame for face/document alignment provide immediate feedback, helping the user correct their actions instantly without having to wait for an error message. -- **Auto-Capture:** Automating the photo-taking process reduces user effort and increases the likelihood of a high-quality, usable image. -- **OCR with Confirmation:** Using OCR to pre-fill forms saves the user time and effort. The confirmation step ensures accuracy and keeps the user in control. - ---- - -## Revision History - -| Version | Date | Author | Changes | -|---------|------|--------|---------| -| 1.0 | Nov 2025 | Team | Initial release - basic verification flow | -| 2.0 | Dec 2025 | Team + Claude | Major enhancements: complete design system, all user personas, admin flows, component library, accessibility guidelines, animations, performance, testing | - ---- - -*This guide is a living document. Update it as the design system evolves.* - -*Note: Sections marked with **[CLAUDE'S ENHANCEMENT]** are recommendations added by Claude AI to improve the UX design guide based on industry best practices.* diff --git a/docs/archive/README.md b/docs/archive/README.md deleted file mode 100644 index 9f9fc50f..00000000 --- a/docs/archive/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# Documentation Archive - -Historical docs preserved for git history. Content here is **not current** β€” see top-level `README.md`, `CHANGELOG.md`, the open GitHub issues, and `docs/` for authoritative docs. - -## 2026-04-16 - -Bulk cleanup: moved 13 root-level drafts (quickstart duplicates, camera/WebAuthn implementation notes, early architecture drafts) out of the repo root. Each was superseded by current code comments, the top-level README, or `docs/DEPLOYMENT_CHECKLIST.md` / `docs/PERFORMANCE.md`.