From d8d0825f54475f4cda29424b7e5c7aab62aff908 Mon Sep 17 00:00:00 2001 From: atsunatsu Date: Fri, 25 Sep 2026 23:50:48 +0800 Subject: [PATCH] feat: show clear error when p12 certificate import fails The import previously swallowed all exceptions silently. Now the upload config dialog shows a specific message for: wrong password, expired certificate, invalid file, and unknown failures. --- .../src/main/res/values-zh/strings.xml | 4 ++++ core/presentation/src/main/res/values/strings.xml | 4 ++++ .../feature/settings/LoTWUploadConfigDialog.kt | 15 +++++++++++++++ .../look4sat/feature/settings/SettingsScreen.kt | 1 + .../look4sat/feature/settings/SettingsState.kt | 4 ++++ .../feature/settings/SettingsViewModel.kt | 13 ++++++++++--- 6 files changed, 38 insertions(+), 3 deletions(-) diff --git a/core/presentation/src/main/res/values-zh/strings.xml b/core/presentation/src/main/res/values-zh/strings.xml index 2cc39e27..91de84a7 100644 --- a/core/presentation/src/main/res/values-zh/strings.xml +++ b/core/presentation/src/main/res/values-zh/strings.xml @@ -203,6 +203,10 @@ 证书密码 选择 .p12 文件 导入 + 证书密码错误,请检查 TQSL 导出 .p12 时设置的密码 + 证书已过期或尚未生效 + 不是有效的 LoTW 证书文件 + 导入失败,请重试 %1$s · DXCC %2$d · 有效期至 %3$s 移除证书 台址 diff --git a/core/presentation/src/main/res/values/strings.xml b/core/presentation/src/main/res/values/strings.xml index a51eb2aa..6ca6bfdb 100644 --- a/core/presentation/src/main/res/values/strings.xml +++ b/core/presentation/src/main/res/values/strings.xml @@ -234,6 +234,10 @@ Certificate password Choose .p12 file Import + Incorrect certificate password. Check the password you set when exporting the .p12 from TQSL. + Certificate is expired or not yet valid. + Not a valid LoTW certificate file. + Import failed. Try again. %1$s · DXCC %2$d · expires %3$s Remove certificate Station location diff --git a/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/LoTWUploadConfigDialog.kt b/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/LoTWUploadConfigDialog.kt index 3babef41..12d6415d 100644 --- a/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/LoTWUploadConfigDialog.kt +++ b/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/LoTWUploadConfigDialog.kt @@ -78,6 +78,7 @@ fun LoTWUploadConfigDialog( certificate: LoTWCertificate?, station: LoTWStation?, busy: Boolean, + error: LoTWUploadError?, onDismiss: () -> Unit, onImport: (ByteArray, CharArray) -> Unit, onRemove: () -> Unit, @@ -122,6 +123,20 @@ fun LoTWUploadConfigDialog( isEnabled = !busy, modifier = Modifier.fillMaxWidth() ) + error?.let { + Text( + text = stringResource( + when (it) { + LoTWUploadError.PASSWORD -> R.string.prefs_lotw_upload_error_password + LoTWUploadError.EXPIRED -> R.string.prefs_lotw_upload_error_expired + LoTWUploadError.INVALID_FILE -> R.string.prefs_lotw_upload_error_invalid + LoTWUploadError.UNKNOWN -> R.string.prefs_lotw_upload_error_unknown + } + ), + color = MaterialTheme.colorScheme.error, + fontSize = 12.sp + ) + } selectedFile?.let { uri -> Text( text = displayName(uri), diff --git a/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/SettingsScreen.kt b/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/SettingsScreen.kt index ae653c74..1a813bb2 100644 --- a/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/SettingsScreen.kt +++ b/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/SettingsScreen.kt @@ -273,6 +273,7 @@ private fun SettingsScreen(uiState: SettingsState, onAction: (SettingsAction) -> certificate = uiState.lotwCertificate, station = uiState.lotwStation, busy = uiState.lotwUploadBusy, + error = uiState.lotwUploadError, onDismiss = { dialogs.lotwUpload = false }, onImport = { bytes, password -> onAction(SettingsAction.ImportLoTWCertificate(bytes, password)) }, onRemove = { onAction(SettingsAction.RemoveLoTWCertificate) }, diff --git a/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/SettingsState.kt b/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/SettingsState.kt index 19369431..1b3f947b 100644 --- a/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/SettingsState.kt +++ b/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/SettingsState.kt @@ -75,6 +75,8 @@ data class SettingsState( /** LoTW upload station location (null when unset). */ val lotwStation: com.rtbishop.look4sat.core.domain.repository.LoTWStation? = null, val lotwUploadBusy: Boolean = false, + /** Last certificate import outcome; shown inside the upload config dialog. */ + val lotwUploadError: LoTWUploadError? = null, /** 指南针校准精度等级 (校准对话框进度条). */ val compassAccuracy: CompassAccuracy = CompassAccuracy.UNRELIABLE, /** 校正后航向(度, 含磁偏角+手动偏置), 校准对话框实时显示. */ @@ -91,6 +93,8 @@ sealed interface LoTWError { data class Network(val detail: String) : LoTWError } +enum class LoTWUploadError { PASSWORD, INVALID_FILE, EXPIRED, UNKNOWN } + sealed interface SettingsAction { // Position data object SetGpsPosition : SettingsAction diff --git a/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/SettingsViewModel.kt b/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/SettingsViewModel.kt index 82dfc433..23ac6105 100644 --- a/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/SettingsViewModel.kt +++ b/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/SettingsViewModel.kt @@ -354,12 +354,19 @@ class SettingsViewModel( private fun importLoTWCertificate(bytes: ByteArray, password: CharArray) { viewModelScope.launch { - _uiState.update { it.copy(lotwUploadBusy = true) } + _uiState.update { it.copy(lotwUploadBusy = true, lotwUploadError = null) } try { val cert = lotwUploadRepository.importCertificate(bytes, password) - _uiState.update { it.copy(lotwCertificate = cert, lotwUploadBusy = false) } + _uiState.update { it.copy(lotwCertificate = cert, lotwUploadBusy = false, lotwUploadError = null) } + } catch (e: com.rtbishop.look4sat.core.domain.repository.LoTWOperationException) { + val error = when (e.reason) { + com.rtbishop.look4sat.core.domain.repository.LoTWProblem.CERTIFICATE_PASSWORD -> LoTWUploadError.PASSWORD + com.rtbishop.look4sat.core.domain.repository.LoTWProblem.CERTIFICATE_EXPIRED -> LoTWUploadError.EXPIRED + else -> LoTWUploadError.INVALID_FILE + } + _uiState.update { it.copy(lotwUploadBusy = false, lotwUploadError = error) } } catch (_: Exception) { - _uiState.update { it.copy(lotwUploadBusy = false) } + _uiState.update { it.copy(lotwUploadBusy = false, lotwUploadError = LoTWUploadError.UNKNOWN) } } } }