Date: October 21, 2025
Issue: Currency resets to "৳" when navigating away from Settings
Status: ✅ FIXED
When updating currency in Settings:
- ✅ Currency saved to database successfully
- ✅ UI updated immediately to show new currency
- ❌ But when navigating away and returning to Settings, currency displayed as "৳" (default)
Two Sources of Truth causing synchronization issues:
// ❌ BEFORE (Lines 48-55)
val userProfile by database.userProfileDao().getProfile().collectAsState(initial = null)
var selectedCurrency by remember { mutableStateOf("৳") } // ❌ Always starts with "৳"
LaunchedEffect(userProfile) {
userProfile?.let { profile ->
selectedCurrency = profile.currency // Updates later, race condition
}
}Problems:
remember { mutableStateOf("৳") }always initializes to default "৳"LaunchedEffectruns asynchronously, creating a race condition- Manual state management (
selectedCurrency = newCurrency) required - Two states to keep in sync (database Flow + local state)
// ✅ AFTER (Lines 48-49)
val userProfile by database.userProfileDao().getProfile().collectAsState(initial = null)
val selectedCurrency = userProfile?.currency ?: "৳" // Derived directly from databaseBenefits:
- ✅ Only one source of truth (database)
- ✅ No manual synchronization needed
- ✅ No race conditions
- ✅ Reactive updates via Flow
- ✅ Always shows correct value on navigation
// ❌ BEFORE (Line 377)
selectedCurrency = newCurrency // Manual state sync
// ✅ AFTER (Line 371)
// No need to update local state - Flow will automatically update UIChange 1: Simplified State Management (Lines 47-49)
// Load user profile for currency setting
val userProfile by database.userProfileDao().getProfile().collectAsState(initial = null)
- var selectedCurrency by remember { mutableStateOf("৳") }
-
- LaunchedEffect(userProfile) {
- userProfile?.let { profile ->
- selectedCurrency = profile.currency
- }
- }
+ val selectedCurrency = userProfile?.currency ?: "৳" // Derived directly from databaseChange 2: Removed Manual State Update (Lines 360-376)
scope.launch {
try {
withContext(Dispatchers.IO) {
userProfile?.let { profile ->
val updatedProfile = profile.copy(
currency = newCurrency,
updatedAt = System.currentTimeMillis()
)
database.userProfileDao().updateProfile(updatedProfile)
}
}
- selectedCurrency = newCurrency
+ // No need to update local state - Flow will automatically update UI
operationMessage = "✅ Currency updated to $newCurrency" to true
} catch (e: Exception) {
operationMessage = "❌ Failed to update currency: ${e.message}" to false
}
}- Open Settings
- Tap Currency → Select "$ (USD)"
- Observe: "Current: $" shows immediately
- Navigate to Home screen
- Return to Settings
- ✅ Verify: Still shows "Current: $" (not reverted to "৳")
- Settings → Currency → "€ (EUR)"
- Back to Home
- Settings → Currency → "¥ (CNY)"
- Back to Home
- Settings → Should show "Current: ¥"
- Settings → Currency → "£ (GBP)"
- Close app completely
- Reopen app
- Settings → Should show "Current: £" (persisted)
- Settings → Currency → "₹ (INR)"
- Go to Expense Tracker → Add expense
- ✅ Verify: Shows "₹" symbol
- Go to Subscription Tracker → Add subscription
- ✅ Verify: Shows "₹" symbol
| Aspect | Before (Broken) | After (Fixed) |
|---|---|---|
| State Sources | 2 (DB + local) | 1 (DB only) |
| Initialization | Always "৳" | From DB or "৳" |
| Sync Method | Manual + LaunchedEffect | Automatic (derived) |
| Race Conditions | Yes | No |
| Navigation Behavior | Resets to "৳" | Maintains value |
| Code Lines | 8 lines | 1 line |
| Complexity | High | Low |
val selectedCurrency = userProfile?.currency ?: "৳"This expression:
- Watches
userProfile(which is a Flow from Room) - Automatically recomposes when
userProfilechanges - Returns
profile.currencyif profile exists - Falls back to "৳" if profile is null (first launch)
- No manual state management needed
Reactive Programming Principles:
- ✅ Single source of truth (database)
- ✅ Unidirectional data flow (DB → UI)
- ✅ No manual synchronization
- ✅ Compose recomposition handles updates
Traditional State Management (Removed):
- ❌ Multiple sources of truth
- ❌ Manual synchronization required
- ❌ Potential for bugs (race conditions)
- ❌ More complex code
Build Status: ✅ SUCCESS in 5 seconds
Install Status: ✅ SUCCESS
Linter Errors: 0
SettingsScreen.kt- Currency display and managementUserProfileDao.kt- Database access for user profileExpenseTrackerScreen.kt- Uses currency for expensesSubscriptionTrackerScreen.kt- Uses currency for subscriptionsHomeScreen.kt- Displays currency-formatted values
Before:
Settings → Currency → $ → Back → Settings → Shows "৳" ❌
After:
Settings → Currency → $ → Back → Settings → Shows "$" ✅
Status: 🎉 FIXED - Currency now persists correctly across navigation!
Always prefer derived state from a single source of truth (like Room Flow) over manual state synchronization.
This pattern:
- Reduces bugs
- Simplifies code
- Improves maintainability
- Leverages Compose's reactive architecture
Report Generated: October 21, 2025
Fix Applied By: AI Assistant
Verification: Ready for user testing