From 2e59d54de6a7d2584d3b345e788e98bc48b8a0dd Mon Sep 17 00:00:00 2001 From: Gato Date: Sat, 6 Jun 2026 07:18:34 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20sauvegarde=20du=20compte=20CalDAV=20m?= =?UTF-8?q?=C3=AAme=20si=20la=20connexion=20=C3=A9choue,=20avec=20indicate?= =?UTF-8?q?ur=20visuel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mobile/ui/settings/SettingsScreen.kt | 29 ++++++++++++++++--- .../mobile/ui/settings/SettingsViewModel.kt | 22 ++++++++++++++ 2 files changed, 47 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/planify/mobile/ui/settings/SettingsScreen.kt b/app/src/main/java/com/planify/mobile/ui/settings/SettingsScreen.kt index a70d491..3c7a37b 100644 --- a/app/src/main/java/com/planify/mobile/ui/settings/SettingsScreen.kt +++ b/app/src/main/java/com/planify/mobile/ui/settings/SettingsScreen.kt @@ -15,6 +15,7 @@ import androidx.compose.material.icons.outlined.Add import androidx.compose.material.icons.outlined.Delete import androidx.compose.material.icons.outlined.Download import androidx.compose.material.icons.outlined.Sync +import androidx.compose.material.icons.outlined.Warning import androidx.compose.material3.AlertDialog import androidx.compose.material3.Button import androidx.compose.material3.ExperimentalMaterial3Api @@ -23,6 +24,7 @@ import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.ListItem import androidx.compose.material3.MaterialTheme +import androidx.compose.foundation.layout.Column import androidx.compose.material3.OutlinedButton import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.SegmentedButton @@ -185,9 +187,10 @@ fun SettingsScreen( } discovery.second?.let { error -> Text( - text = error, + text = "Connexion échouée — le compte a été ajouté sans synchronisation : $error", color = MaterialTheme.colorScheme.error, - modifier = Modifier.padding(horizontal = 16.dp), + style = MaterialTheme.typography.bodySmall, + modifier = Modifier.padding(horizontal = 16.dp, vertical = 4.dp), ) } @@ -240,10 +243,28 @@ private fun SectionTitle(text: String) { @Composable private fun CalDavSourceRow(source: Source, onDelete: () -> Unit) { + val connectionFailed = source.caldavData?.calendarHomeUrl == null ListItem( - leadingContent = { Icon(Icons.Outlined.AccountCircle, contentDescription = null) }, + leadingContent = { + if (connectionFailed) { + Icon(Icons.Outlined.Warning, contentDescription = "Connexion échouée", tint = MaterialTheme.colorScheme.error) + } else { + Icon(Icons.Outlined.AccountCircle, contentDescription = null) + } + }, headlineContent = { Text(source.displayName) }, - supportingContent = { Text(source.caldavData?.serverUrl ?: "") }, + supportingContent = { + Column { + Text(source.caldavData?.serverUrl ?: "") + if (connectionFailed) { + Text( + text = "Non connecté", + color = MaterialTheme.colorScheme.error, + style = MaterialTheme.typography.labelSmall, + ) + } + } + }, trailingContent = { IconButton(onClick = onDelete) { Icon(Icons.Outlined.Delete, contentDescription = "Supprimer", tint = MaterialTheme.colorScheme.error) diff --git a/app/src/main/java/com/planify/mobile/ui/settings/SettingsViewModel.kt b/app/src/main/java/com/planify/mobile/ui/settings/SettingsViewModel.kt index 9103b39..e4d850d 100644 --- a/app/src/main/java/com/planify/mobile/ui/settings/SettingsViewModel.kt +++ b/app/src/main/java/com/planify/mobile/ui/settings/SettingsViewModel.kt @@ -11,6 +11,8 @@ import com.planify.mobile.data.preferences.AppPreferences import com.planify.mobile.data.preferences.ThemeMode import com.planify.mobile.data.sync.SyncScheduler import com.planify.mobile.domain.model.Source +import com.planify.mobile.domain.model.SourceCalDavData +import com.planify.mobile.domain.model.SourceType import com.planify.mobile.domain.repository.ProjectRepository import com.planify.mobile.domain.repository.SourceRepository import com.planify.mobile.domain.repository.TaskRepository @@ -23,6 +25,9 @@ import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch +import java.time.LocalDateTime +import java.time.format.DateTimeFormatter +import java.util.UUID import javax.inject.Inject data class SettingsUiState( @@ -98,6 +103,23 @@ class SettingsViewModel @Inject constructor( if (uiState.value.syncEnabled) syncScheduler.schedule() } is DiscoveryResult.Failure -> { + // Save the account anyway so the user keeps their credentials + val now = LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME) + val sourceId = UUID.randomUUID().toString() + val fallback = Source( + id = sourceId, + type = SourceType.CALDAV, + displayName = username, + addedAt = now, + updatedAt = now, + caldavData = SourceCalDavData( + serverUrl = baseUrl, + username = username, + calendarHomeUrl = null, + ), + ) + credentialStore.savePassword(sourceId, password) + sourceRepository.insertSource(fallback) _discoveryState.update { false to result.message } } }