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