diff --git a/shared/src/commonMain/kotlin/com/vnidrop/app/feature/settings/SettingsViewModel.kt b/shared/src/commonMain/kotlin/com/vnidrop/app/feature/settings/SettingsViewModel.kt index a3b6a4f..7f450e2 100644 --- a/shared/src/commonMain/kotlin/com/vnidrop/app/feature/settings/SettingsViewModel.kt +++ b/shared/src/commonMain/kotlin/com/vnidrop/app/feature/settings/SettingsViewModel.kt @@ -101,18 +101,16 @@ class SettingsViewModel( val effectFlow = effects.receiveAsFlow() private var enableNotificationsAfterSettings = false private var usernamePersistJob: Job? = null + private var hasLocalUsernameDraft = false init { viewModelScope.launch { preferencesRepository.preferences.collect { preferences -> val previousFolder = _state.value.receiveFolder val receiveFolder = fileSystemService.effectiveReceiveFolder(preferences.receiveFolder) - // While the user is typing, keep the in-progress value. DataStore - // echoes can race keystrokes and trim trailing spaces mid-edit. - val editingUsername = usernamePersistJob?.isActive == true _state.update { current -> current.copy( - username = if (editingUsername) current.username else preferences.username, + username = if (hasLocalUsernameDraft) current.username else preferences.username, receiveFolder = receiveFolder, themeMode = preferences.themeMode, notificationsEnabled = preferences.notificationsEnabled, @@ -140,6 +138,7 @@ class SettingsViewModel( } fun setUsername(value: String) { + hasLocalUsernameDraft = true _state.update { it.copy(username = value) } usernamePersistJob?.cancel() usernamePersistJob = viewModelScope.launch { diff --git a/shared/src/commonTest/kotlin/com/vnidrop/app/feature/ViewModelsTest.kt b/shared/src/commonTest/kotlin/com/vnidrop/app/feature/ViewModelsTest.kt index 661b136..c026019 100644 --- a/shared/src/commonTest/kotlin/com/vnidrop/app/feature/ViewModelsTest.kt +++ b/shared/src/commonTest/kotlin/com/vnidrop/app/feature/ViewModelsTest.kt @@ -90,7 +90,7 @@ class ViewModelsTest { } @Test - fun settingsUsernameKeepsSpacesWhileTypingAndPersistsAfterDebounce() = runTest { + fun settingsUsernameDraftIsNotOverwrittenByPersistedEcho() = runTest { Dispatchers.setMain(StandardTestDispatcher(testScheduler)) val preferences = preferences() val viewModel = settingsViewModel(preferences) @@ -104,7 +104,11 @@ class ViewModelsTest { testScheduler.advanceTimeBy(400) advanceUntilIdle() assertEquals("Ada", preferences.mutablePreferences.value.username) - assertEquals("Ada", viewModel.state.value.username) + assertEquals("Ada ", viewModel.state.value.username) + + preferences.setThemeMode(ThemeMode.Dark) + advanceUntilIdle() + assertEquals("Ada ", viewModel.state.value.username) } @Test