# BaoLife Android Code Review Issues

This document contains all issues and incomplete items found during code review.

---

## Review Status

| Reviewer | Area | Status |
|----------|------|--------|
| Reviewer 1 | Core/Infrastructure | ✅ Complete |
| Reviewer 2 | Domain Models | ✅ Complete |
| Reviewer 3 | Managers + Theme | ✅ Complete |
| Reviewer 4 | Dating Screens | ✅ Complete |
| Reviewer 5 | Home/Activities/Character/Events | ✅ Complete |
| Reviewer 6 | Messaging/Monetization | ✅ Complete |
| Reviewer 7 | Onboarding/Retention | ✅ Complete |
| Reviewer 8 | Settings/Store/Navigation | ✅ Complete |

---

## Issues Found

### Reviewer 1: Core/Infrastructure
**Status:** Complete

#### Critical Issues
- [PlayerViewModel.kt:37-173] **Memory Leak - CoroutineScopes never cancelled**: All derived StateFlows create new `CoroutineScope(Dispatchers.Default)` instead of using `viewModelScope`. These scopes are never cancelled when the ViewModel is cleared.
- [WebSocketManager.kt:73] **Memory Leak - CoroutineScope never cancelled**: The `scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)` is never cancelled.

#### Major Issues
- [BaoLifeApp.kt:9-12] Missing initialization for AppLifecycleObserver, NetworkMonitor, Firebase, logging, or crash reporting.
- [AppModule.kt:14-23] Incomplete DI configuration - only WebSocketManager is provided.
- [WebSocketManager.kt:235] Incorrect reconnection backoff - multiplier is 1.1 but CLAUDE.md specifies doubling.
- [WebSocketManager.kt:620-661] 11 empty message handler stubs.
- [WebSocketManager.kt:598-599] Empty relationship event handler.
- [WebSocketManager.kt:542-544] Empty conversation event handler.
- [GameStateViewModel.kt:126] Auto-connect on ViewModel creation in `init` block.
- [AppLifecycleObserver.kt:42-44] `initialize()` never called from BaoLifeApp.kt.
- [NetworkMonitor.kt:67] `startMonitoring()` never called from BaoLifeApp.kt.
- [WebSocketManager.kt:183] Uses deprecated `Settings.Secure.ANDROID_ID`.
- [WebSocketManager.kt:283] `webSocket?.send()` silently fails if null.
- [MainActivity.kt:17-30] Missing lifecycle handling - no `onDestroy()`, `onResume()`, `onPause()`.

#### Minor Issues
- [WebSocketManager.kt:60] Hardcoded PRODUCTION environment.
- [WebSocketManager.kt:325-327] Uses `e.printStackTrace()` instead of Timber.
- [WebSocketManager.kt:471] Magic number 50 for max events.
- [HapticFeedback.kt:72] Potential null from `context.getSystemService()`.

---

### Reviewer 2: Domain Models
**Status:** Complete

#### Critical Issues
None found.

#### Major Issues
- [MessageEvent.kt:43-45] Uses `var` for `claimed`, `claimedAt`, `category` fields - violates immutability.
- [Person.kt:22] `money` typed as `Int` but CLAUDE.md specifies `Double`.
- [MessageEvent.kt:38] `moneyCost` typed as `Int?` but should be `Double?`.
- [MessageEvent.kt:35] `hour` typed as `String?` but should be `Int`.

#### Minor Issues
- [Achievement.kt:3-4,29-36] Domain model imports UI layer classes (`Color`, `AppColors`). Violates clean architecture - domain should be UI-agnostic.
- [DailyQuest.kt:2-4,36-43] Same - domain model has UI dependencies (`Color`, `AppColors`).
- [Activity.kt:40] `energy_modifier` uses snake_case instead of Kotlin camelCase. Use `@SerialName("energy_modifier")` with camelCase property.
- [Player.kt:32-33] Inconsistent naming in `FocusOption`: `focus_name` vs `energyModifier`. Use consistent camelCase with `@SerialName`.
- [DateActivity.kt:52] `DateMiniGameState` not annotated with `@Serializable` while other classes in file are.
- [Conversation.kt:39] `isFromPlayer` treats `sender == null` as `true`. May cause bugs if server omits sender for non-player messages.
- [Question.kt:37-40] `canAfford` uses `money: Int` instead of `Double` to match CLAUDE.md specification.
- [RelationshipEvent.kt:38-40] Same as Question.kt - `canAfford` uses `money: Int` instead of `Double`.
- [StoreItem.kt:17,35] Inconsistent price types: `StoreItem.price` is `Int` while `InAppPurchaseItem.price` is `Double`.
- [Person.kt:18] Field named `ageYears` but CLAUDE.md shows `age`. Verify server API compatibility or add `@SerialName`.
- [Conversation.kt:4] Uses `java.util.UUID`. Kotlinx UUID would be more idiomatic.

---

### Reviewer 3: Managers + Theme
**Status:** Complete

#### Critical Issues
- [BaoLifeTheme.kt:74] **Potential crash from unsafe Activity cast** - The code casts `view.context as Activity` without null-safety check. If the context is not an Activity (e.g., when used in a Service or non-Activity context), this will throw a ClassCastException and crash the app.

#### Major Issues
- [ToastManager.kt:45-46] **Thread-safety race condition** - `toastQueue` is a regular `mutableListOf` with no synchronization. Concurrent access from multiple coroutines/threads can cause ConcurrentModificationException or data corruption. Should use `CopyOnWriteArrayList` or proper synchronization.
- [ToastManager.kt:104-112] **Conflicting DI patterns** - The class uses both Hilt `@Inject constructor` and a companion object singleton pattern (`shared`). This creates two separate instances - one managed by Hilt and one static. This defeats the purpose of dependency injection and can cause state inconsistencies.
- [ToastManager.kt:32] **Toast duration never used** - The `duration` parameter in `ToastData` is stored but never used to auto-dismiss toasts. The toast will remain visible indefinitely until manually dismissed.
- [BillingManager.kt:108-111] **Potential memory leak from Handler** - Uses `android.os.Handler.postDelayed()` but never cancels pending callbacks when `endConnection()` is called or when the manager is destroyed. This can cause memory leaks and callbacks firing after destruction.
- [AppTypography.kt:21-131] **Hardcoded colors break theming** - All TextStyle definitions include hardcoded `color = AppColors.primaryText` or `AppColors.secondaryText`. This prevents proper dark mode theming since colors should be applied via MaterialTheme.colorScheme at the composable level, not embedded in the styles.

#### Minor Issues
- [AnalyticsManager.kt:22-23] **Race condition on initialization** - `isInitialized` is a plain Boolean without `@Volatile` or atomic operations. In multi-threaded scenarios, one thread could read stale value while another is updating it.
- [SoundManager.kt:21-22] **Missing persistence for sound settings** - `isMuted` and `volume` are stored only in memory. User preferences will be lost on app restart. Should integrate with SharedPreferences or DataStore.
- [SoundManager.kt:80-82] **Asynchronous sound loading not handled** - `soundPool?.load()` is asynchronous, but the code immediately adds the soundId to the map. The sound may not be playable until `OnLoadCompleteListener` fires.
- [PushNotificationManager.kt:144] **Potential negative notification ID** - `hashCode().mod(1000)` can produce negative values for negative hashCodes. Should use `Math.abs()` or `and 0xFFFFFFFF` to ensure positive IDs.
- [ToastManager.kt:3-4] **Unused imports** - `LaunchedEffect` and `mutableStateOf`, `getValue`, `setValue` from Compose runtime are imported but never used in the file.
- [BaoLifeTheme.kt:84-87] **Missing custom typography and shapes** - The theme only sets colorScheme but does not integrate `AppTypography` into MaterialTheme's typography parameter, meaning Material3 components will use default typography instead of the app's custom styles.
- [AnalyticsManager.kt:23] **Unused userId field** - The `userId` variable is stored via `setUserId()` but never actually used in the stub implementation and has no getter method.
- [BillingManager.kt:117-122] **Empty stub methods** - `queryProducts()` and `restorePurchases()` are stub methods with only TODO comments. Consider throwing `NotImplementedError` or returning a meaningful error state to avoid silent failures.

---

### Reviewer 4: Dating Screens
**Status:** Complete

#### Critical Issues
None found

#### Major Issues
- [DateActivitySelectionScreen.kt:51-131] Hardcoded sample activities instead of fetching from server. Comment says "in real app, would come from server" but no implementation exists to fetch real data.
- [DateMiniGameScreen.kt:44-85] Hardcoded game state with sample questions. Comment says "in real app, would come from server" but no implementation exists to fetch real game data.
- [DateMiniGameScreen.kt:38-149] No dismiss/back button provided. User has no way to exit the mini-game early if they want to cancel.
- [DatingScreen.kt:194] Pass button onClick has TODO comment and does nothing: `onClick = { /* TODO: Pass */ }`
- [DatingScreen.kt:207] Like button onClick has TODO comment and does nothing: `onClick = { /* TODO: Like */ }`
- [DatingScreen.kt:222] Super Like button onClick has TODO comment and does nothing: `onClick = { /* TODO: Super like */ }`
- [DatingScreen.kt:350] RelationshipCard click handler is incomplete: `clickable { /* TODO: View relationship details */ }`
- [DatingScreen.kt:430] Message IconButton has TODO: `onClick = { /* TODO: Message */ }`
- [DatingScreen.kt:437] View IconButton has TODO: `onClick = { /* TODO: View */ }`
- [RelationshipDetailScreen.kt:364-378] FlowRow implementation is broken. It is just a wrapper around Row and does not provide actual flow/wrap behavior. When there are many interests, they will overflow horizontally instead of wrapping.
- [RelationshipsScreen.kt:42-55] Relationship filtering logic uses `status` field with hardcoded string matching (e.g., "dating", "married", "friend"). This may not correctly categorize relationships if the server returns different status strings.
- [SwipeDatingScreen.kt:119,130,139,182,200] Force unwrap `currentCandidate!!` used multiple times without null safety. If swipeCharacter updates to null during an action (e.g., network race condition), this will cause NullPointerException crash.

#### Minor Issues
- [DateMiniGameScreen.kt:384-391] FeedbackOverlay animation starts and ends at scale 1f, so no visible animation occurs. The spring animation has no effect because targetValue is always 1f with no initial value specified.
- [DatingScreen.kt:179] `person.compatibilityScore` displayed directly without null check. Model shows this is nullable (`Int?`), which could display "null% Compatible".
- [RelationshipDetailScreen.kt:158,234] Uses deprecated `Divider` composable instead of `HorizontalDivider` from Material3.
- [RelationshipDetailScreen.kt:144] QuickActionButton "Call" has placeholder: `onClick = { /* TODO */ }`
- [RelationshipDetailScreen.kt:149] QuickActionButton "Gift" has placeholder: `onClick = { /* TODO */ }`
- [RelationshipEventModal.kt:68] Uses `clickable(enabled = false)` to prevent dismiss when clicking card. Non-standard pattern; should use `clickable {}` with empty lambda or Modifier.consumeWindowInsets.
- [RelationshipEventModal.kt:121-122] `person.money.toInt()` loses precision for money amounts that have decimal values.
- [RelationshipsScreen.kt:42-55] People who don't match any category filter (romantic/family/friend) are silently excluded from display.
- [SwipeDatingScreen.kt:52,131,201] `showMatchAnimation` state is set to true but never used. Match animation UI is not implemented.
- [SwipeDatingScreen.kt:146-148] No animation when card returns to center after release without reaching swipe threshold. Card snaps back instantly.
- [DateActivitySelectionScreen.kt:460] Uses `AppSpacing.smallCornerRadius` which may not be defined in the theme (should verify AppSpacing has this property).
- [DatingScreen.kt:97] Uses `AppSpacing.largeCornerRadius` which may not be defined in AppSpacing (verify theme definition).

---

### Reviewer 5: Home/Activities/Character/Events
**Status:** Complete

#### Critical Issues
None found

#### Major Issues
- [HomeScreen.kt:258-274] **AvatarCard does not load actual images** - The `imageUrl` parameter is accepted but never used. The composable only displays initials in a gradient circle placeholder. Should use Coil's AsyncImage with SvgDecoder as per CLAUDE.md guidelines.
- [PersonDetailScreen.kt:73-81] **Infinite loading state with no timeout or error handling** - If person is null (not found or network failure), the screen shows a CircularProgressIndicator forever with no way to recover or go back.
- [PersonDetailScreen.kt:141-147] **Person model property mismatch** - Code references `person.likes` and `person.dislikes` but the Person model in CLAUDE.md defines `interests` and `personalityTraits`, not likes/dislikes. This will cause compilation errors or runtime crashes.
- [PersonDetailScreen.kt:131] **Relationship property type mismatch** - Code uses `person.relationship` (singular String) but the Person model defines `relationships` as `List<String>`. Property name and type do not match.
- [EventModal.kt:335-337] **Nested scrolling issue with fixed height LazyVerticalGrid** - LazyVerticalGrid with fixed height `(gridRows * 180).dp` inside a verticalScroll Column creates problematic nested scrolling. Content may clip or scroll behavior may be unpredictable.
- [EventModal.kt:396-404] **No affordability check before allowing answer selection** - Cost indicators show required resources but answers are not disabled when the user cannot afford them. Users can select options they cannot pay for.
- [ActivitiesScreen.kt:227] **Job selection not implemented** - TODO comment indicates occupation card click handler is not implemented. Users cannot select/apply for jobs.
- [ActivitiesScreen.kt:286] **Extracurricular selection not implemented** - TODO comment indicates extracurricular card click handler is not implemented.
- [ActivitiesScreen.kt:324] **Enroll action not implemented** - The "Join" button for extracurriculars has no implementation.

#### Minor Issues
- [HomeScreen.kt:180-181] **Money type inconsistency** - `ResourcesRow` accepts `money: Int` but the data model in CLAUDE.md shows `money` as `Double`. Potential loss of precision or type mismatch.
- [HomeScreen.kt:244] **Mood type inconsistency** - `AvatarCard` accepts `mood: String` but Person model shows `mood: Int` (0-100 scale).
- [HomeScreen.kt:540] **Incorrect null check for event.date** - Code checks `if (event.date != null)` but `date` is defined as non-nullable `String` in MessageEvent. Should check for empty string instead.
- [HomeScreen.kt:542] **Hour display issue** - Uses `${event.hour ?: ""}` which would hide midnight (hour 0) since 0 is falsy with elvis operator. Should format hour properly.
- [HomeScreen.kt:419] **Modifier order issue** - `.weight(1f).padding(horizontal: 2.dp)` - padding should generally come before weight for proper layout behavior.
- [DeathScreen.kt:124-131] **Stars positioning does not scale** - Star positions use fixed dp offsets (up to 400x600dp) that won't adapt to different screen sizes. Stars may appear off-screen or clustered on larger/smaller devices.
- [DeathScreen.kt:232] **Age zero check may hide valid data** - `if (p.ageYears > 0)` would hide age display for newborn characters (age 0), which could be valid for infant death scenarios.
- [DeathScreen.kt:41] **Empty default callback for onRestart** - The `onRestart` parameter defaults to empty lambda `{}`. If caller forgets to provide implementation, "Begin a New Journey" button does nothing with no user feedback.
- [PersonDetailScreen.kt:45-47] **Remember with mutable key** - Uses `remember(player.r, personId)` where `player.r` is a changing list. Consider using `derivedStateOf` for more predictable recomposition behavior.
- [EventModal.kt:19] **Unused import** - `import androidx.compose.ui.draw.shadow` is imported but never used in the file.
- [EventModal.kt:344-346] **Optimistic UI update without confirmation** - `onAnswerSelected()` is called immediately after `sendAnswer()` without waiting for server confirmation. If network request fails, modal still closes.
- [EventModal.kt:397-403] **Null assertion after null check** - Uses `answer.energyCost!!` after verifying `(answer.energyCost ?: 0) > 0`. While safe, could use `let` or capture the value for cleaner code.
- [ActivitiesScreen.kt:402] **Hardcoded quit duration** - Displays `${habit.quitProgress}/30 days` with hardcoded 30 days. Quit duration may vary by habit type.
- [ActivitiesScreen.kt] **No loading or error states** - Screen has no loading indicators during data fetch or error states for failed requests.

---

### Reviewer 6: Messaging/Monetization
**Status:** Complete

#### Critical Issues
None found.

#### Major Issues
- [ChatScreen.kt:76-78] Race condition in scroll animation - uses `messages.size - 1` from stale state before new message is added, may not scroll to the actual newest message
- [ChatScreen.kt:72] No error handling or user feedback when `sendChatMessage` fails
- [MessagesScreen.kt:60] Passing empty string as characterId when `conversation.character` is null could cause navigation issues or crashes in ChatScreen
- [MessagesScreen.kt:131] Avatar shows `conversation.character?.take(2)` which uses the raw characterId, not the actual person's name initials - should resolve person and show proper initials
- [MessagesScreen.kt:145] Displays raw character ID instead of resolved character name in conversation list
- [EnergyRefillModal.kt:202] After purchasing energy refill, modal does not dismiss automatically - poor user experience
- [TimeSkipModal.kt:186] After purchasing time skip, modal does not dismiss and does not navigate to the summary screen to show results
- [TimeSkipSummaryScreen.kt:38-40] `summary` parameter is nullable but the screen does not handle null case properly - shows empty content with just a button, should show error or loading state
- [TimeSkipSummaryScreen.kt:39] `gameStateViewModel` parameter is injected but never used in the composable

#### Minor Issues
- [ChatScreen.kt:112] `items(messages)` missing `key` parameter - could cause performance issues or animation glitches when messages change
- [ChatScreen.kt:170-173] Hardcoded "Online" status in header - should be dynamic based on actual character state
- [MessagesScreen.kt:57] `items(conversations)` missing `key` parameter for efficient list updates
- [MessagesScreen.kt:89-93] Edit icon in MessagesHeaderCard has no onClick handler - appears decorative but should be functional or removed
- [EnergyRefillModal.kt:100] `.shadow()` modifier applied after `.clip()` which prevents shadow from rendering correctly - shadow should be applied before clip
- [EnergyRefillModal.kt:95-97,349,361,387] Multiple hardcoded color values (Color(0xFFFFCC66), Color(0xFFFF9933), etc.) instead of using AppColors design system
- [EnergyRefillModal.kt:171] Using `forEach` for tier list instead of LazyColumn - not efficient for potentially many items
- [TimeSkipModal.kt:96] `.shadow()` modifier applied after `.clip()` - incorrect order prevents proper shadow rendering
- [TimeSkipModal.kt:91-93,312,324,350] Multiple hardcoded color values instead of using AppColors design system
- [TimeSkipModal.kt:155] Using `forEach` for tier list instead of LazyColumn
- [TimeSkipSummaryScreen.kt:119] `items(s.events)` missing `key` parameter
- [TimeSkipSummaryScreen.kt:85] `durationHours.toInt()` loses precision - should format properly (e.g., "2.5 hours")
- [TimeSkipSummaryScreen.kt:267] Uses `AppSpacing.smallCornerRadius` - verify this constant exists in AppSpacing object

---

### Reviewer 7: Onboarding/Retention
**Status:** Complete

#### Critical Issues
None found.

#### Major Issues
- [ConfirmationScreen.kt:253-257] No error handling for `gameStateViewModel.setupCharacter()`. If the call fails, the `loading` state remains true indefinitely, leaving users stuck on the screen with no way to proceed or recover.
- [AchievementUnlockModal.kt:131-134] Dialog is completely non-dismissible (`dismissOnBackPress = false, dismissOnClickOutside = false`). If the achievements list becomes empty during display or there is an error processing achievements, users could become permanently stuck in the modal with no escape.
- [AchievementsScreen.kt:193-208] CategoryFilterRow does not support horizontal scrolling. If there are many `AchievementCategory` entries, the filter chips will overflow the screen width and become inaccessible.

#### Minor Issues
- [CharacterSetupScreen.kt:47] Variable `showAgePicker` is declared but never used in the code.
- [CharacterSetupScreen.kt:57-64] `Brush.linearGradient` uses identical colors (`AppColors.background` twice), making the gradient pointless. Should either use a solid color or provide distinct gradient colors.
- [CharacterSetupScreen.kt:140-154] OutlinedTextField has no character limit, allowing users to enter extremely long names that could break UI layouts.
- [CharacterSetupScreen.kt:360] No name validation beyond empty check (no max length, special characters, or whitespace-only validation) before enabling Continue button.
- [ConfirmationScreen.kt:93-97] Same gradient issue: `Brush.linearGradient` uses identical colors.
- [WelcomeScreen.kt:82-88] Same gradient issue: `Brush.linearGradient` uses identical colors.
- [OnboardingContainerScreen.kt:365-366] `showConfetti` variable is suppressed as unused (`@Suppress("UNUSED_VARIABLE")`) but the variable is actually set and never read in the UI. The confetti visibility is never conditionally controlled based on this state.
- [AchievementUnlockModal.kt:362-369] Confetti initial X positions use hardcoded width (`400f`) that does not adapt to different screen sizes or orientations.
- [AchievementUnlockModal.kt:444-446] `getCategoryColor()` function is unnecessary indirection - it simply returns `category.color` directly.
- [AchievementsScreen.kt:114-116] `LaunchedEffect` for fetching achievements is placed at the end of the Composable. Should be positioned near the top for better readability and to ensure data fetching begins early.
- [DailyQuestsScreen.kt:75-126] Complex nesting with `?.let { } ?: run { }` pattern reduces code readability. Consider using early return pattern or when statement for cleaner code.
- [DailyQuestsScreen.kt:159] Hardcoded `8.dp` corner radius instead of using `AppSpacing.smallCornerRadius` for consistency with design system.
- [DailyRewardsScreen.kt:100-101] Hardcoded `8.dp` spacing values instead of using AppSpacing constants for consistency.
- [DailyRewardsScreen.kt:107] Logic `reward.id == state.currentStreak + 1` assumes reward IDs are 1-indexed and sequential. This is fragile and could break if reward ID structure changes.
- [DailyRewardsScreen.kt:10] Unused import `CircleShape` should be removed.

---

### Reviewer 8: Settings/Store/Navigation
**Status:** Complete

#### Critical Issues
- [AccountDeletionScreen.kt:85-87] Uses `android.os.Handler` with `postDelayed` instead of coroutines. This is not lifecycle-aware and can cause memory leaks or crashes if the composable is disposed before the callback fires. Should use `LaunchedEffect` with coroutines.

#### Major Issues
- [AccountDeletionScreen.kt:43] The `onConfirmDelete` callback parameter is never used. Account deletion is simulated locally but never communicated to the backend via WebSocket.
- [AccountDeletionScreen.kt:83-88] No actual WebSocket call to request account deletion from the server. The deletion is faked with a simple local delay.
- [DataExportScreen.kt:374-384] The `LaunchedEffect(Unit)` is broken. It checks `exportStatus == ExportStatus.REQUESTING` but this effect runs only once when first composed (when status is `IDLE`). The export simulation code never actually executes.
- [DataExportScreen.kt:297] `gameStateViewModel.requestDataExport()` is called but there is no WebSocket response handling - the simulated export code doesn't work as noted above.
- [SettingsScreen.kt:41-43] Settings toggle state (`soundEnabled`, `hapticEnabled`, `notificationsEnabled`) is not persisted. Uses `remember` which loses state on configuration change or navigation. Should use DataStore or SharedPreferences.
- [SettingsScreen.kt:133,141,149] Toggle callbacks only update local UI state but don't actually call any managers (SoundManager, etc.) to enable/disable the features system-wide.
- [StoreScreen.kt:78] TODO: Purchase is not sent to backend via WebSocket - the `onPurchase` callback only shows a celebration but doesn't persist the purchase.
- [StoreScreen.kt:149] Type mismatch: `currentMoney` is `Int` but `Person.money` is defined as `Double` in the data model. This could cause compilation errors or loss of precision.
- [StoreScreen.kt:74] References `person.items` which is not defined in the Person data model per CLAUDE.md. This will cause compilation errors if the property doesn't exist.
- [MainNavigation.kt:93-108] The `showBottomBar` logic is missing checks for date activity routes. Should add checks for routes starting with `date_activity/` and `date_mini_game/` to hide bottom bar on those screens.
- [MainNavigation.kt:297-309,318-328] In `DATE_ACTIVITY_SELECTION` and `DATE_MINI_GAME` composables, if `person` is null (invalid ID), nothing renders - user sees blank screen. Should handle null case with error message or navigation fallback.

#### Minor Issues
- [AccountDeletionScreen.kt:87] Hardcoded 2-second delay for "processing" - should be configurable or removed when real API is implemented.
- [DataExportScreen.kt:248-250] No user feedback (toast/snackbar) when clipboard copy completes.
- [SettingsScreen.kt:79,161,168,175] Several `onClick = {}` callbacks are empty placeholders (Profile, Version, Privacy Policy, Terms of Service).
- [SettingsScreen.kt:159] Hardcoded version "1.0.0 (Build 1)" instead of reading from BuildConfig.VERSION_NAME and BuildConfig.VERSION_CODE.
- [StoreScreen.kt:191] TODO comment: "Load actual image with Coil" - item images are not implemented, showing placeholder icons.
- [StoreScreen.kt:309] Uses emoji string directly in code - consider using drawable resource for consistency.
- [MainNavigation.kt:323-325] The `onComplete` callback in `DateMiniGameScreen` has empty body - `affinityGained` parameter is not used.

---

## Summary

**Total Issues Found:** 96
**Critical:** 4
**Major:** 54
**Minor:** 38

### Critical Issues (Must Fix)
1. PlayerViewModel memory leak - CoroutineScopes never cancelled
2. WebSocketManager memory leak - CoroutineScope never cancelled
3. BaoLifeTheme unsafe Activity cast crash
4. AccountDeletionScreen Handler memory leak

### Priority Recommendations
1. **Fix memory leaks** in PlayerViewModel and WebSocketManager (Critical)
2. **Complete empty WebSocket handlers** - 11+ message handlers are stubs
3. **Fix type mismatches** - money field should be Double, not Int
4. **Add null safety** - SwipeDatingScreen force unwraps can crash
5. **Initialize managers** - AppLifecycleObserver and NetworkMonitor never started

