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) }
}
}
}