From 859387b3315b3d5045b5f9bd46ffa79af06f496d Mon Sep 17 00:00:00 2001 From: James Rich <2199651+jamesarich@users.noreply.github.com> Date: Wed, 2 Jul 2025 16:43:04 +0000 Subject: [PATCH] Refactor: Display scanning indicator during Bluetooth scan (#2321) Signed-off-by: James Rich <2199651+jamesarich@users.noreply.github.com> --- .../com/geeksville/mesh/model/BTScanModel.kt | 5 ++--- .../mesh/ui/connections/Connections.kt | 2 +- .../ui/connections/components/BLEDevices.kt | 21 +++++++++++++++++++ app/src/main/res/values/strings.xml | 4 +--- 4 files changed, 25 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/com/geeksville/mesh/model/BTScanModel.kt b/app/src/main/java/com/geeksville/mesh/model/BTScanModel.kt index d3d0ad0b2..fa79a5d71 100644 --- a/app/src/main/java/com/geeksville/mesh/model/BTScanModel.kt +++ b/app/src/main/java/com/geeksville/mesh/model/BTScanModel.kt @@ -23,7 +23,6 @@ import android.bluetooth.BluetoothDevice import android.content.Context import android.hardware.usb.UsbManager import android.os.RemoteException -import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope @@ -306,8 +305,8 @@ class BTScanModel @Inject constructor( } } - private val _spinner = MutableLiveData(false) - val spinner: LiveData get() = _spinner + private val _spinner = MutableStateFlow(false) + val spinner: StateFlow get() = _spinner.asStateFlow() } const val NO_DEVICE_SELECTED = "n" diff --git a/app/src/main/java/com/geeksville/mesh/ui/connections/Connections.kt b/app/src/main/java/com/geeksville/mesh/ui/connections/Connections.kt index 28c20f4f3..6816e627d 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/connections/Connections.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/connections/Connections.kt @@ -140,7 +140,7 @@ fun ConnectionsScreen( val scanStatusText by scanModel.errorText.observeAsState("") val connectionState by uiViewModel.connectionState.collectAsState(MeshService.ConnectionState.DISCONNECTED) val devices by scanModel.devices.observeAsState(emptyMap()) - val scanning by scanModel.spinner.observeAsState(false) + val scanning by scanModel.spinner.collectAsStateWithLifecycle(false) val receivingLocationUpdates by uiViewModel.receivingLocationUpdates.collectAsState(false) val context = LocalContext.current val app = (context.applicationContext as GeeksvilleApplication) diff --git a/app/src/main/java/com/geeksville/mesh/ui/connections/components/BLEDevices.kt b/app/src/main/java/com/geeksville/mesh/ui/connections/components/BLEDevices.kt index a96ef52f5..c4276f14a 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/connections/components/BLEDevices.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/connections/components/BLEDevices.kt @@ -28,16 +28,19 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Bluetooth import androidx.compose.material.icons.filled.BluetoothDisabled import androidx.compose.material3.Button +import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment.Companion.CenterHorizontally import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.core.app.ActivityCompat +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.geeksville.mesh.R import com.geeksville.mesh.android.getBluetoothPermissions import com.geeksville.mesh.model.BTScanModel @@ -52,6 +55,7 @@ fun BLEDevices( scanModel: BTScanModel ) { val context = LocalContext.current + val isScanning by scanModel.spinner.collectAsStateWithLifecycle(false) Row { Text( text = stringResource(R.string.bluetooth), @@ -69,6 +73,22 @@ fun BLEDevices( scanModel.onSelected(device) } } + } else if (isScanning) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 8.dp), + horizontalAlignment = CenterHorizontally + ) { + CircularProgressIndicator( + modifier = Modifier.size(96.dp) + ) + Text( + text = stringResource(R.string.scanning), + style = MaterialTheme.typography.bodyMedium, + modifier = Modifier.padding(vertical = 8.dp) + ) + } } else { Column( modifier = Modifier @@ -89,6 +109,7 @@ fun BLEDevices( } } Button( + enabled = !isScanning, modifier = Modifier.fillMaxWidth(), onClick = { val bluetoothPermissions = context.getBluetoothPermissions() diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2c78a3d6c..a1740630f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -13,9 +13,6 @@ ~ ~ You should have received a copy of the GNU General Public License ~ along with this program. If not, see . - ~ - ~ NOTE: Only modify this english strings.xml file directly. - ~ Other languages are managed by CrowdIn --> @@ -709,4 +706,5 @@ No USB Serial devices found. Scroll to bottom Meshtastic + Scanning