diff --git a/core/presentation/src/main/java/com/rtbishop/look4sat/core/presentation/Components.kt b/core/presentation/src/main/java/com/rtbishop/look4sat/core/presentation/Components.kt
index 8918cbc5..b22fdeea 100644
--- a/core/presentation/src/main/java/com/rtbishop/look4sat/core/presentation/Components.kt
+++ b/core/presentation/src/main/java/com/rtbishop/look4sat/core/presentation/Components.kt
@@ -210,12 +210,20 @@ fun RowScope.NextPassRow(pass: OrbitalPass, modifier: Modifier = Modifier, isUtc
}
@Composable
-fun CardButton(onClick: () -> Unit, text: String, modifier: Modifier = Modifier) {
+fun CardButton(
+ onClick: () -> Unit,
+ text: String,
+ modifier: Modifier = Modifier,
+ isEnabled: Boolean = true
+) {
ElevatedButton(
onClick = onClick,
+ enabled = isEnabled,
colors = ButtonDefaults.buttonColors(
containerColor = MaterialTheme.colorScheme.surfaceVariant,
- contentColor = MaterialTheme.colorScheme.onSurfaceVariant
+ contentColor = MaterialTheme.colorScheme.onSurfaceVariant,
+ disabledContainerColor = MaterialTheme.colorScheme.surfaceVariant,
+ disabledContentColor = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.4f)
),
shape = MaterialTheme.shapes.small,
modifier = modifier,
@@ -316,9 +324,21 @@ fun InfoDialog(
@Composable
fun SharedDialog(
- title: String, onCancel: () -> Unit, onAccept: () -> Unit, content: @Composable () -> Unit
+ title: String,
+ onCancel: () -> Unit,
+ onAccept: () -> Unit,
+ acceptText: String? = null,
+ acceptEnabled: Boolean = true,
+ content: @Composable () -> Unit
) {
- SharedDialog(title = title, onDismissRequest = onCancel, onCancel = onCancel, onAccept = onAccept) { _ ->
+ SharedDialog(
+ title = title,
+ onDismissRequest = onCancel,
+ onCancel = onCancel,
+ onAccept = onAccept,
+ acceptText = acceptText,
+ acceptEnabled = acceptEnabled
+ ) { _ ->
content()
}
}
@@ -329,6 +349,8 @@ fun SharedDialog(
onDismissRequest: () -> Unit,
onCancel: (() -> Unit)? = null,
onAccept: (() -> Unit)? = null,
+ acceptText: String? = null,
+ acceptEnabled: Boolean = true,
titleFontSize: Int = 16,
titleTextAlign: TextAlign = if (onCancel != null && onAccept != null) TextAlign.Center else TextAlign.Start,
content: @Composable (padding: Dp) -> Unit
@@ -356,7 +378,11 @@ fun SharedDialog(
.padding(horizontal = if (onCancel != null && onAccept != null) padding else 0.dp)
)
if (onAccept != null) {
- CardButton(onClick = onAccept, text = stringResource(R.string.btn_accept))
+ CardButton(
+ onClick = onAccept,
+ text = acceptText ?: stringResource(R.string.btn_accept),
+ isEnabled = acceptEnabled
+ )
}
}
content(padding)
diff --git a/core/presentation/src/main/res/values-zh/strings.xml b/core/presentation/src/main/res/values-zh/strings.xml
index 63554612..05d22c58 100644
--- a/core/presentation/src/main/res/values-zh/strings.xml
+++ b/core/presentation/src/main/res/values-zh/strings.xml
@@ -151,8 +151,8 @@
LoTW 已确认网格
LoTW 呼号
LoTW 密码
- 直接从 ARRL LoTW 拉取已确认 QSO 的网格并与 Wavelog 网格合并(当前 %1$d 个)。密码仅保存在手机本地。填好直接点同步,会自动保存并拉取。
- 立即同步
+ 直接从 ARRL LoTW 拉取该呼号已确认 QSO 的网格并覆盖本地已存集合(当前 %1$d 个)。密码仅保存在手机本地。点"同步"会自动保存凭据并拉取。
+ 同步
同步中…
已从 LoTW 同步 — 共 %1$d 个网格
未配置 — 直接登录 ARRL LoTW 拉取已确认 QSO 的网格,无需自建服务器
diff --git a/core/presentation/src/main/res/values/strings.xml b/core/presentation/src/main/res/values/strings.xml
index 2f08f8f8..95cad857 100644
--- a/core/presentation/src/main/res/values/strings.xml
+++ b/core/presentation/src/main/res/values/strings.xml
@@ -186,8 +186,8 @@
LoTW confirmed grids
LoTW callsign
LoTW password
- Fetch confirmed-QSO grids directly from ARRL LoTW and merge them with Wavelog grids (currently %1$d). The password is stored on this device only. Just tap Sync — credentials are saved automatically.
- Sync now
+ Fetch confirmed-QSO grids directly from ARRL LoTW for this callsign and replace the stored set (currently %1$d). The password is stored on this device only. Tapping Sync saves the credentials and fetches in one step.
+ Sync
Syncing…
Synced from LoTW — %1$d grids total
Not configured — pull confirmed grids directly from ARRL LoTW, no self-hosted server needed
diff --git a/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/SettingsDialog.kt b/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/SettingsDialog.kt
index abc1abba..1aeba80b 100644
--- a/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/SettingsDialog.kt
+++ b/feature/settings/src/main/java/com/rtbishop/look4sat/feature/settings/SettingsDialog.kt
@@ -238,10 +238,13 @@ fun LoTWDialog(
SharedDialog(
title = stringResource(R.string.prefs_lotw_title),
onCancel = dismiss,
+ // The confirm button IS the sync action: saving credentials and
+ // fetching confirmed grids happen in one step.
onAccept = {
- onSave(com.rtbishop.look4sat.core.domain.model.LoTWSettings(call.value, pass.value))
- dismiss()
- }
+ onSync(com.rtbishop.look4sat.core.domain.model.LoTWSettings(call.value, pass.value))
+ },
+ acceptText = stringResource(if (isSyncing) R.string.prefs_lotw_syncing else R.string.prefs_lotw_sync),
+ acceptEnabled = !isSyncing
) {
OutlinedTextField(
value = call.value,
@@ -273,20 +276,6 @@ fun LoTWDialog(
modifier = Modifier.padding(horizontal = LocalSpacing.current.large)
)
}
- // Sync uses the values typed in the fields directly — saving and syncing
- // happen in one step, no need to close and reopen the dialog.
- Row(
- horizontalArrangement = Arrangement.End,
- modifier = Modifier.fillMaxWidth().padding(horizontal = LocalSpacing.current.large)
- ) {
- TextButton(
- onClick = { onSync(com.rtbishop.look4sat.core.domain.model.LoTWSettings(call.value, pass.value)) },
- enabled = !isSyncing
- ) {
- Text(text = if (isSyncing) stringResource(R.string.prefs_lotw_syncing)
- else stringResource(R.string.prefs_lotw_sync))
- }
- }
Spacer(modifier = Modifier.height(0.dp))
}
}