feat: confirm dialog before starting sync on mobile data

Replace the disabled-Start + secondary-Start-Anyway button pattern
with a single always-enabled Start button that shows an AlertDialog
when the connection is metered/mobile, requiring explicit confirmation
before running a potentially gigabyte-scale operation.

https://claude.ai/code/session_01U8qF9mK4UBvXsXP1zNMXfX
This commit is contained in:
Claude
2026-03-13 22:49:40 +00:00
parent 90d7b0c678
commit 9d49b2da4f
2 changed files with 37 additions and 10 deletions
@@ -31,6 +31,7 @@ import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Card import androidx.compose.material3.Card
@@ -40,8 +41,12 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
@@ -63,6 +68,7 @@ fun EventSyncScreen(
val syncState by syncViewModel.syncState.collectAsStateWithLifecycle() val syncState by syncViewModel.syncState.collectAsStateWithLifecycle()
val isMobileOrMetered by accountViewModel.settings.isMobileOrMeteredConnection.collectAsStateWithLifecycle() val isMobileOrMetered by accountViewModel.settings.isMobileOrMeteredConnection.collectAsStateWithLifecycle()
var showMobileDataDialog by remember { mutableStateOf(false) }
Scaffold( Scaffold(
topBar = { topBar = {
@@ -152,20 +158,17 @@ fun EventSyncScreen(
is EventSyncViewModel.SyncState.Error, is EventSyncViewModel.SyncState.Error,
-> { -> {
Button( Button(
onClick = { syncViewModel.start() }, onClick = {
if (isMobileOrMetered) {
showMobileDataDialog = true
} else {
syncViewModel.start()
}
},
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
enabled = !isMobileOrMetered || syncState !is EventSyncViewModel.SyncState.Idle,
) { ) {
Text(stringRes(R.string.event_sync_start)) Text(stringRes(R.string.event_sync_start))
} }
if (isMobileOrMetered && syncState is EventSyncViewModel.SyncState.Idle) {
OutlinedButton(
onClick = { syncViewModel.start() },
modifier = Modifier.fillMaxWidth(),
) {
Text(stringRes(R.string.event_sync_start_anyway))
}
}
} }
is EventSyncViewModel.SyncState.Running -> { is EventSyncViewModel.SyncState.Running -> {
@@ -182,6 +185,29 @@ fun EventSyncScreen(
} }
} }
if (showMobileDataDialog) {
AlertDialog(
onDismissRequest = { showMobileDataDialog = false },
title = { Text(stringRes(R.string.event_sync_mobile_data_dialog_title)) },
text = { Text(stringRes(R.string.event_sync_wifi_warning)) },
confirmButton = {
Button(
onClick = {
showMobileDataDialog = false
syncViewModel.start()
},
) {
Text(stringRes(R.string.event_sync_start_anyway))
}
},
dismissButton = {
TextButton(onClick = { showMobileDataDialog = false }) {
Text(stringRes(R.string.event_sync_cancel))
}
},
)
}
Spacer(Modifier.height(16.dp)) Spacer(Modifier.height(16.dp))
} }
} }
+1
View File
@@ -1760,6 +1760,7 @@
<string name="event_sync_step2">Download all events that mention you and send them to your inbox relays.</string> <string name="event_sync_step2">Download all events that mention you and send them to your inbox relays.</string>
<string name="event_sync_step3">Download all direct messages addressed to you and send them to your DM relays.</string> <string name="event_sync_step3">Download all direct messages addressed to you and send them to your DM relays.</string>
<string name="event_sync_wifi_warning">⚠ You appear to be on a metered or mobile connection. This operation can transfer a very large amount of data. Connect to Wi-Fi before starting.</string> <string name="event_sync_wifi_warning">⚠ You appear to be on a metered or mobile connection. This operation can transfer a very large amount of data. Connect to Wi-Fi before starting.</string>
<string name="event_sync_mobile_data_dialog_title">Use Mobile Data?</string>
<string name="event_sync_start">Start Sync</string> <string name="event_sync_start">Start Sync</string>
<string name="event_sync_start_anyway">Start Anyway (mobile data)</string> <string name="event_sync_start_anyway">Start Anyway (mobile data)</string>
<string name="event_sync_cancel">Cancel</string> <string name="event_sync_cancel">Cancel</string>