mirror of
https://github.com/atsunatsu/Look4Sat.git
synced 2026-10-02 03:15:37 +00:00
fix: p12 import — pick file first, then password (matches normal usage)
The Choose .p12 button was gated on a non-blank password, which forced users to type the password before selecting the file. Now the file picker is always available; after selection the filename is shown, then the password field and an Import button appear.
This commit is contained in:
1 parent
797b1c19f7
commit
e19f098aa5
3 files changed
+38
-10
No files matched your search
@@ -202,6 +202,7 @@
|
|||||||
<string name="prefs_lotw_upload_cert_hint">导入你的 TrustedQSL .p12 证书(与 TQSL 同款)用于签名上传通联。密码仅加密保存在手机本地。</string>
|
<string name="prefs_lotw_upload_cert_hint">导入你的 TrustedQSL .p12 证书(与 TQSL 同款)用于签名上传通联。密码仅加密保存在手机本地。</string>
|
||||||
<string name="prefs_lotw_upload_password">证书密码</string>
|
<string name="prefs_lotw_upload_password">证书密码</string>
|
||||||
<string name="prefs_lotw_upload_import">选择 .p12 文件</string>
|
<string name="prefs_lotw_upload_import">选择 .p12 文件</string>
|
||||||
|
<string name="prefs_lotw_upload_import_confirm">导入</string>
|
||||||
<string name="prefs_lotw_upload_cert_info">%1$s · DXCC %2$d · 有效期至 %3$s</string>
|
<string name="prefs_lotw_upload_cert_info">%1$s · DXCC %2$d · 有效期至 %3$s</string>
|
||||||
<string name="prefs_lotw_upload_remove">移除证书</string>
|
<string name="prefs_lotw_upload_remove">移除证书</string>
|
||||||
<string name="prefs_lotw_upload_station_title">台址</string>
|
<string name="prefs_lotw_upload_station_title">台址</string>
|
||||||
|
|||||||
@@ -233,6 +233,7 @@
|
|||||||
<string name="prefs_lotw_upload_cert_hint">Import your TrustedQSL .p12 certificate (same one you use in TQSL) to sign and upload QSOs. The password is stored encrypted on this device only.</string>
|
<string name="prefs_lotw_upload_cert_hint">Import your TrustedQSL .p12 certificate (same one you use in TQSL) to sign and upload QSOs. The password is stored encrypted on this device only.</string>
|
||||||
<string name="prefs_lotw_upload_password">Certificate password</string>
|
<string name="prefs_lotw_upload_password">Certificate password</string>
|
||||||
<string name="prefs_lotw_upload_import">Choose .p12 file</string>
|
<string name="prefs_lotw_upload_import">Choose .p12 file</string>
|
||||||
|
<string name="prefs_lotw_upload_import_confirm">Import</string>
|
||||||
<string name="prefs_lotw_upload_cert_info">%1$s · DXCC %2$d · expires %3$s</string>
|
<string name="prefs_lotw_upload_cert_info">%1$s · DXCC %2$d · expires %3$s</string>
|
||||||
<string name="prefs_lotw_upload_remove">Remove certificate</string>
|
<string name="prefs_lotw_upload_remove">Remove certificate</string>
|
||||||
<string name="prefs_lotw_upload_station_title">Station location</string>
|
<string name="prefs_lotw_upload_station_title">Station location</string>
|
||||||
|
|||||||
+36
-10
@@ -9,6 +9,8 @@
|
|||||||
*/
|
*/
|
||||||
package com.rtbishop.look4sat.feature.settings
|
package com.rtbishop.look4sat.feature.settings
|
||||||
|
|
||||||
|
import android.net.Uri
|
||||||
|
import android.provider.OpenableColumns
|
||||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
@@ -39,6 +41,7 @@ import androidx.compose.ui.platform.LocalContext
|
|||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.input.KeyboardCapitalization
|
import androidx.compose.ui.text.input.KeyboardCapitalization
|
||||||
import androidx.compose.ui.text.input.PasswordVisualTransformation
|
import androidx.compose.ui.text.input.PasswordVisualTransformation
|
||||||
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import com.rtbishop.look4sat.core.domain.repository.LoTWCertificate
|
import com.rtbishop.look4sat.core.domain.repository.LoTWCertificate
|
||||||
@@ -82,23 +85,23 @@ fun LoTWUploadConfigDialog(
|
|||||||
onSaveStation: (LoTWStation) -> Unit
|
onSaveStation: (LoTWStation) -> Unit
|
||||||
) {
|
) {
|
||||||
var password by remember { mutableStateOf("") }
|
var password by remember { mutableStateOf("") }
|
||||||
|
var selectedFile by remember { mutableStateOf<Uri?>(null) }
|
||||||
var grid by remember { mutableStateOf(station?.grid.orEmpty()) }
|
var grid by remember { mutableStateOf(station?.grid.orEmpty()) }
|
||||||
var cqZone by remember { mutableStateOf(station?.cqZone.orEmpty()) }
|
var cqZone by remember { mutableStateOf(station?.cqZone.orEmpty()) }
|
||||||
var ituZone by remember { mutableStateOf(station?.ituZone.orEmpty()) }
|
var ituZone by remember { mutableStateOf(station?.ituZone.orEmpty()) }
|
||||||
var iota by remember { mutableStateOf(station?.iota.orEmpty()) }
|
var iota by remember { mutableStateOf(station?.iota.orEmpty()) }
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
|
||||||
|
// Pick the file first, then ask for the password — matches normal usage.
|
||||||
val filePicker = rememberLauncherForActivityResult(ActivityResultContracts.OpenDocument()) { uri ->
|
val filePicker = rememberLauncherForActivityResult(ActivityResultContracts.OpenDocument()) { uri ->
|
||||||
if (uri != null && password.isNotBlank()) {
|
if (uri != null) selectedFile = uri
|
||||||
val bytes = runCatching {
|
|
||||||
context.contentResolver.openInputStream(uri)?.use { it.readBytes() }
|
|
||||||
}.getOrNull()
|
|
||||||
if (bytes != null && bytes.isNotEmpty()) {
|
|
||||||
onImport(bytes, password.toCharArray())
|
|
||||||
password = ""
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun displayName(uri: Uri): String = runCatching {
|
||||||
|
context.contentResolver.query(uri, arrayOf(OpenableColumns.DISPLAY_NAME), null, null, null)?.use { cursor ->
|
||||||
|
if (cursor.moveToFirst()) cursor.getString(0) else null
|
||||||
}
|
}
|
||||||
|
}.getOrNull() ?: uri.lastPathSegment.orEmpty()
|
||||||
|
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
onDismissRequest = onDismiss,
|
onDismissRequest = onDismiss,
|
||||||
@@ -113,6 +116,19 @@ fun LoTWUploadConfigDialog(
|
|||||||
}
|
}
|
||||||
if (certificate == null) {
|
if (certificate == null) {
|
||||||
Text(stringResource(R.string.prefs_lotw_upload_cert_hint), fontSize = 13.sp)
|
Text(stringResource(R.string.prefs_lotw_upload_cert_hint), fontSize = 13.sp)
|
||||||
|
Button(
|
||||||
|
onClick = { filePicker.launch(arrayOf("*/*")) },
|
||||||
|
enabled = !busy,
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
) { Text(stringResource(R.string.prefs_lotw_upload_import), fontSize = 13.sp) }
|
||||||
|
selectedFile?.let { uri ->
|
||||||
|
Text(
|
||||||
|
text = displayName(uri),
|
||||||
|
fontSize = 12.sp,
|
||||||
|
maxLines = 1,
|
||||||
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
color = MaterialTheme.colorScheme.primary
|
||||||
|
)
|
||||||
OutlinedTextField(
|
OutlinedTextField(
|
||||||
value = password,
|
value = password,
|
||||||
onValueChange = { password = it },
|
onValueChange = { password = it },
|
||||||
@@ -122,10 +138,20 @@ fun LoTWUploadConfigDialog(
|
|||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier.fillMaxWidth()
|
||||||
)
|
)
|
||||||
Button(
|
Button(
|
||||||
onClick = { filePicker.launch(arrayOf("*/*")) },
|
onClick = {
|
||||||
|
val bytes = runCatching {
|
||||||
|
context.contentResolver.openInputStream(uri)?.use { it.readBytes() }
|
||||||
|
}.getOrNull()
|
||||||
|
if (bytes != null && bytes.isNotEmpty()) {
|
||||||
|
onImport(bytes, password.toCharArray())
|
||||||
|
password = ""
|
||||||
|
selectedFile = null
|
||||||
|
}
|
||||||
|
},
|
||||||
enabled = password.isNotBlank() && !busy,
|
enabled = password.isNotBlank() && !busy,
|
||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier.fillMaxWidth()
|
||||||
) { Text(stringResource(R.string.prefs_lotw_upload_import), fontSize = 13.sp) }
|
) { Text(stringResource(R.string.prefs_lotw_upload_import_confirm), fontSize = 13.sp) }
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Text(stringResource(R.string.prefs_lotw_upload_cert_info, certificate.callsign, certificate.dxcc, certificate.expires), fontSize = 13.sp)
|
Text(stringResource(R.string.prefs_lotw_upload_cert_info, certificate.callsign, certificate.dxcc, certificate.expires), fontSize = 13.sp)
|
||||||
OutlinedButton(onClick = onRemove, enabled = !busy) {
|
OutlinedButton(onClick = onRemove, enabled = !busy) {
|
||||||
|
|||||||
Reference in new issue
Block a user