diff --git a/app/src/main/java/de/bollwerk/app/ui/settings/SettingsScreen.kt b/app/src/main/java/de/bollwerk/app/ui/settings/SettingsScreen.kt index 4e6593b..d5a002a 100644 --- a/app/src/main/java/de/bollwerk/app/ui/settings/SettingsScreen.kt +++ b/app/src/main/java/de/bollwerk/app/ui/settings/SettingsScreen.kt @@ -324,13 +324,33 @@ internal fun SettingsScreen( ) Spacer(modifier = Modifier.height(8.dp)) OutlinedButton( - onClick = viewModel::logout, + onClick = viewModel::onLogoutClicked, modifier = Modifier.fillMaxWidth() ) { Text("Abmelden") } } } + + if (uiState.showLogoutDialog) { + AlertDialog( + onDismissRequest = viewModel::onLogoutDialogDismissed, + title = { Text("Lokale Daten löschen?") }, + text = { + Text("Möchtest du alle lokal gespeicherten Daten (Inventar, Nachrichten, …) von diesem Gerät entfernen?") + }, + confirmButton = { + TextButton(onClick = { viewModel.logout(deleteLocalData = true) }) { + Text("Löschen") + } + }, + dismissButton = { + TextButton(onClick = { viewModel.logout(deleteLocalData = false) }) { + Text("Behalten") + } + } + ) + } } else { OutlinedTextField( value = uiState.loginUsername, diff --git a/app/src/main/java/de/bollwerk/app/ui/settings/SettingsUiState.kt b/app/src/main/java/de/bollwerk/app/ui/settings/SettingsUiState.kt index e3a5717..82e396c 100644 --- a/app/src/main/java/de/bollwerk/app/ui/settings/SettingsUiState.kt +++ b/app/src/main/java/de/bollwerk/app/ui/settings/SettingsUiState.kt @@ -27,7 +27,8 @@ internal data class SettingsUiState( val pendingQueueCount: Int = 0, val isSyncing: Boolean = false, val lastSyncTime: String? = null, - val openAiApiKey: String = "" + val openAiApiKey: String = "", + val showLogoutDialog: Boolean = false ) internal sealed interface ImportResult { diff --git a/app/src/main/java/de/bollwerk/app/ui/settings/SettingsViewModel.kt b/app/src/main/java/de/bollwerk/app/ui/settings/SettingsViewModel.kt index 63ce673..c402c6c 100644 --- a/app/src/main/java/de/bollwerk/app/ui/settings/SettingsViewModel.kt +++ b/app/src/main/java/de/bollwerk/app/ui/settings/SettingsViewModel.kt @@ -7,6 +7,7 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.qualifiers.ApplicationContext +import de.bollwerk.app.data.db.BollwerkDatabase import de.bollwerk.app.data.db.dao.PendingSyncOpDao import de.bollwerk.app.data.sync.ConnectionState import de.bollwerk.app.data.sync.WebSocketClient @@ -22,6 +23,7 @@ import de.bollwerk.app.domain.repository.ImportExportRepository import de.bollwerk.app.domain.repository.SettingsRepository import de.bollwerk.app.domain.repository.SyncService import de.bollwerk.app.notification.MessagingService +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow @@ -29,6 +31,7 @@ import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import java.io.File import java.time.Instant import java.time.ZoneId @@ -43,6 +46,7 @@ internal class SettingsViewModel @Inject constructor( private val syncService: SyncService, private val webSocketClient: WebSocketClient, private val pendingSyncOpDao: PendingSyncOpDao, + private val database: BollwerkDatabase, @ApplicationContext private val context: Context ) : ViewModel() { @@ -227,8 +231,21 @@ internal class SettingsViewModel @Inject constructor( } } - fun logout() { + fun onLogoutClicked() { + _uiState.update { it.copy(showLogoutDialog = true) } + } + + fun onLogoutDialogDismissed() { + _uiState.update { it.copy(showLogoutDialog = false) } + } + + fun logout(deleteLocalData: Boolean = false) { viewModelScope.launch { + if (deleteLocalData) { + withContext(Dispatchers.IO) { + database.clearAllTables() + } + } syncService.logout() webSocketClient.disconnect() MessagingService.stop(context) @@ -237,7 +254,8 @@ internal class SettingsViewModel @Inject constructor( isLoggedIn = false, loggedInUsername = "", connectionState = ConnectionState.NotConfigured, - syncActivity = null + syncActivity = null, + showLogoutDialog = false ) } } diff --git a/app/src/test/java/de/bollwerk/app/ui/settings/SettingsViewModelTest.kt b/app/src/test/java/de/bollwerk/app/ui/settings/SettingsViewModelTest.kt index 8eb0062..16704b1 100644 --- a/app/src/test/java/de/bollwerk/app/ui/settings/SettingsViewModelTest.kt +++ b/app/src/test/java/de/bollwerk/app/ui/settings/SettingsViewModelTest.kt @@ -4,6 +4,7 @@ import android.content.Context import androidx.core.content.FileProvider import android.content.ContentResolver import android.net.Uri +import de.bollwerk.app.data.db.BollwerkDatabase import de.bollwerk.app.data.db.dao.PendingSyncOpDao import de.bollwerk.app.data.db.entity.PendingSyncOpEntity import de.bollwerk.app.data.sync.WebSocketClient @@ -53,6 +54,7 @@ class SettingsViewModelTest { private lateinit var fakeSyncService: FakeSyncService private lateinit var fakeWebSocketClient: FakeWebSocketClient private lateinit var fakePendingSyncOpDao: FakePendingSyncOpDao + private lateinit var mockDatabase: BollwerkDatabase private lateinit var mockContext: Context private lateinit var tempDir: File private lateinit var viewModel: SettingsViewModel @@ -65,6 +67,7 @@ class SettingsViewModelTest { fakeSyncService = FakeSyncService() fakeWebSocketClient = FakeWebSocketClient() fakePendingSyncOpDao = FakePendingSyncOpDao() + mockDatabase = mockk(relaxed = true) tempDir = File(System.getProperty("java.io.tmpdir"), "test_exports") tempDir.mkdirs() mockContext = mockk(relaxed = true) { @@ -85,6 +88,7 @@ class SettingsViewModelTest { syncService = fakeSyncService, webSocketClient = fakeWebSocketClient, pendingSyncOpDao = fakePendingSyncOpDao, + database = mockDatabase, context = mockContext )