@@ -22,6 +22,7 @@ import android.app.Activity
2222import android.bluetooth.BluetoothAdapter
2323import android.content.Intent
2424import android.content.pm.PackageManager
25+ import android.net.Uri
2526import androidx.activity.compose.rememberLauncherForActivityResult
2627import androidx.activity.result.contract.ActivityResultContracts
2728import androidx.compose.foundation.layout.Arrangement
@@ -31,6 +32,7 @@ import androidx.compose.foundation.layout.Row
3132import androidx.compose.foundation.layout.Spacer
3233import androidx.compose.foundation.layout.fillMaxSize
3334import androidx.compose.foundation.layout.fillMaxWidth
35+ import androidx.compose.foundation.layout.height
3436import androidx.compose.foundation.layout.padding
3537import androidx.compose.foundation.layout.size
3638import androidx.compose.foundation.layout.width
@@ -41,10 +43,12 @@ import androidx.compose.material.icons.automirrored.filled.BluetoothSearching
4143import androidx.compose.material.icons.filled.BluetoothDisabled
4244import androidx.compose.material.icons.filled.CheckCircle
4345import androidx.compose.material.icons.filled.ErrorOutline
46+ import androidx.compose.material.icons.filled.Info
4447import androidx.compose.material.icons.filled.MoreVert
4548import androidx.compose.material.icons.filled.Search
4649import androidx.compose.material.icons.filled.Star
4750import androidx.compose.material.icons.filled.Warning
51+ import androidx.compose.material3.AlertDialog
4852import androidx.compose.material3.Button
4953import androidx.compose.material3.ButtonDefaults
5054import androidx.compose.material3.Card
@@ -62,6 +66,7 @@ import androidx.compose.material3.MaterialTheme
6266import androidx.compose.material3.OutlinedCard
6367import androidx.compose.material3.SnackbarDuration
6468import androidx.compose.material3.Text
69+ import androidx.compose.material3.TextButton
6570import androidx.compose.runtime.Composable
6671import androidx.compose.runtime.DisposableEffect
6772import androidx.compose.runtime.LaunchedEffect
@@ -79,6 +84,7 @@ import androidx.compose.ui.res.stringResource
7984import androidx.compose.ui.text.font.FontWeight
8085import androidx.compose.ui.unit.dp
8186import androidx.core.content.ContextCompat
87+ import androidx.glance.layout.height
8288import com.health.openscale.R
8389import com.health.openscale.core.bluetooth.modern.DeviceCapability
8490import com.health.openscale.core.bluetooth.modern.DeviceSupport
@@ -87,6 +93,7 @@ import com.health.openscale.core.service.ScannedDeviceInfo
8793import com.health.openscale.core.utils.LogManager
8894import com.health.openscale.ui.shared.SharedViewModel
8995import kotlinx.coroutines.launch
96+ import androidx.core.net.toUri
9097
9198/* *
9299 * Main Bluetooth settings screen.
@@ -123,6 +130,8 @@ fun BluetoothScreen(
123130 var pendingScan by remember { mutableStateOf(false ) }
124131 var showSavedMenu by remember { mutableStateOf(false ) }
125132 var showTuningMenu by remember { mutableStateOf(false ) }
133+ var showCompatibilityDialog by remember { mutableStateOf(false ) }
134+ var deviceToSave by remember { mutableStateOf<ScannedDeviceInfo ?>(null ) }
126135
127136 // Simple flag: a saved name of "Debug" indicates debug mode is active.
128137 val isDebugActive = (savedDevice?.name.orEmpty() == " Debug" )
@@ -451,6 +460,30 @@ fun BluetoothScreen(
451460 }
452461 }
453462
463+
464+ if (showCompatibilityDialog) {
465+ CompatibilityAlertDialog (
466+ onConfirm = {
467+ deviceToSave?.let {
468+ bluetoothViewModel.saveDeviceAsPreferred(it)
469+ scope.launch {
470+ sharedViewModel.showSnackbar(
471+ context.getString(
472+ R .string.device_saved_as_preferred,
473+ it.name
474+ ),
475+ duration = SnackbarDuration .Short
476+ )
477+ }
478+ }
479+ },
480+ onDismiss = {
481+ showCompatibilityDialog = false
482+ deviceToSave = null
483+ }
484+ )
485+ }
486+
454487 // Combined scan/connection error presentation
455488 if (hasPermissions && btEnabled) {
456489 val errorToShow = connectionError ? : scanError
@@ -476,18 +509,9 @@ fun BluetoothScreen(
476509 deviceInfo = device,
477510 savedAddress = savedDevice?.address,
478511 onSavePreferred = {
479- bluetoothViewModel.requestStopDeviceScan()
480512 if (device.isSupported) {
481- bluetoothViewModel.saveDeviceAsPreferred(device)
482- scope.launch {
483- sharedViewModel.showSnackbar(
484- context.getString(
485- R .string.device_saved_as_preferred,
486- device.name ? : context.getString(R .string.unknown_device)
487- ),
488- duration = SnackbarDuration .Short
489- )
490- }
513+ deviceToSave = device
514+ showCompatibilityDialog = true
491515 } else {
492516 scope.launch {
493517 sharedViewModel.showSnackbar(
@@ -598,6 +622,55 @@ private fun DebugBanner() {
598622 }
599623}
600624
625+ /* *
626+ * Shows a disclaimer dialog before saving a device.
627+ * The user must acknowledge the disclaimer to proceed with saving.
628+ */
629+ @Composable
630+ private fun CompatibilityAlertDialog (
631+ onConfirm : () -> Unit ,
632+ onDismiss : () -> Unit
633+ ) {
634+ val context = LocalContext .current
635+ val projectUrl = " https://github.com/oliexdev/openScale/"
636+
637+ AlertDialog (
638+ onDismissRequest = onDismiss,
639+ icon = { Icon (Icons .Default .Info , contentDescription = null ) },
640+ title = { Text (stringResource(R .string.compatibility_dialog_title)) },
641+ text = {
642+ Column {
643+ Text (stringResource(R .string.bluetooth_compatibility_disclaimer))
644+ Spacer (Modifier .height(16 .dp))
645+ TextButton (
646+ onClick = {
647+ val intent = Intent (Intent .ACTION_VIEW , projectUrl.toUri())
648+ context.startActivity(intent)
649+ },
650+ modifier = Modifier .align(Alignment .End )
651+ ) {
652+ Text (stringResource(id = R .string.go_to_project_website_button))
653+ }
654+ }
655+ },
656+ confirmButton = {
657+ TextButton (
658+ onClick = {
659+ onConfirm()
660+ onDismiss()
661+ }
662+ ) {
663+ Text (stringResource(R .string.compatibility_dialog_confirm_button))
664+ }
665+ },
666+ dismissButton = {
667+ TextButton (onClick = onDismiss) {
668+ Text (stringResource(R .string.cancel_button))
669+ }
670+ }
671+ )
672+ }
673+
601674/* *
602675 * Compact, icon-only capability row:
603676 * - Implemented features: normal tint (onSurface)
0 commit comments