fix(ui): keep username draft stable while editing

This commit is contained in:
2026-07-15 20:28:00 +02:00
parent b355838edf
commit b22536eaf4
2 changed files with 9 additions and 6 deletions

View File

@@ -101,18 +101,16 @@ class SettingsViewModel(
val effectFlow = effects.receiveAsFlow() val effectFlow = effects.receiveAsFlow()
private var enableNotificationsAfterSettings = false private var enableNotificationsAfterSettings = false
private var usernamePersistJob: Job? = null private var usernamePersistJob: Job? = null
private var hasLocalUsernameDraft = false
init { init {
viewModelScope.launch { viewModelScope.launch {
preferencesRepository.preferences.collect { preferences -> preferencesRepository.preferences.collect { preferences ->
val previousFolder = _state.value.receiveFolder val previousFolder = _state.value.receiveFolder
val receiveFolder = fileSystemService.effectiveReceiveFolder(preferences.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 -> _state.update { current ->
current.copy( current.copy(
username = if (editingUsername) current.username else preferences.username, username = if (hasLocalUsernameDraft) current.username else preferences.username,
receiveFolder = receiveFolder, receiveFolder = receiveFolder,
themeMode = preferences.themeMode, themeMode = preferences.themeMode,
notificationsEnabled = preferences.notificationsEnabled, notificationsEnabled = preferences.notificationsEnabled,
@@ -140,6 +138,7 @@ class SettingsViewModel(
} }
fun setUsername(value: String) { fun setUsername(value: String) {
hasLocalUsernameDraft = true
_state.update { it.copy(username = value) } _state.update { it.copy(username = value) }
usernamePersistJob?.cancel() usernamePersistJob?.cancel()
usernamePersistJob = viewModelScope.launch { usernamePersistJob = viewModelScope.launch {

View File

@@ -90,7 +90,7 @@ class ViewModelsTest {
} }
@Test @Test
fun settingsUsernameKeepsSpacesWhileTypingAndPersistsAfterDebounce() = runTest { fun settingsUsernameDraftIsNotOverwrittenByPersistedEcho() = runTest {
Dispatchers.setMain(StandardTestDispatcher(testScheduler)) Dispatchers.setMain(StandardTestDispatcher(testScheduler))
val preferences = preferences() val preferences = preferences()
val viewModel = settingsViewModel(preferences) val viewModel = settingsViewModel(preferences)
@@ -104,7 +104,11 @@ class ViewModelsTest {
testScheduler.advanceTimeBy(400) testScheduler.advanceTimeBy(400)
advanceUntilIdle() advanceUntilIdle()
assertEquals("Ada", preferences.mutablePreferences.value.username) 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 @Test