Skip to content

Commit b45c94a

Browse files
committed
fix: reconnect ble on home resume
1 parent a542413 commit b45c94a

7 files changed

Lines changed: 70 additions & 2 deletions

File tree

app/src/main/java/to/bitkit/repositories/HwWalletRepo.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ class HwWalletRepo @Inject constructor(
8787
/** Forwards UI-delivered transport events, e.g. the USB attach intent from the OS app picker. */
8888
fun onTransportRestored(transportType: TransportType) = trezorRepo.onTransportRestored(transportType)
8989

90+
fun onAppForegrounded() = trezorRepo.onAppForegrounded()
91+
9092
suspend fun resetState() = withContext(ioDispatcher) {
9193
activeWatchers.toList().forEach { watcherId ->
9294
trezorRepo.stopWatcher(watcherId)

app/src/main/java/to/bitkit/repositories/TrezorRepo.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -752,6 +752,17 @@ class TrezorRepo @Inject constructor(
752752
*/
753753
fun onTransportRestored(transportType: TransportType) = launchTransportReconnect(transportType)
754754

755+
fun onAppForegrounded() {
756+
scope.launch {
757+
if (_state.value.connected != null || isConnectInProgress()) return@launch
758+
val knownDevices = _state.value.knownDevices.ifEmpty { loadKnownDevices() }
759+
if (knownDevices.none { it.transportType == TransportType.BLUETOOTH }) return@launch
760+
761+
Logger.info("Attempting bluetooth auto-reconnect after app foregrounded", context = TAG)
762+
launchTransportReconnect(TransportType.BLUETOOTH)
763+
}
764+
}
765+
755766
/**
756767
* Serializes reconnect triggers into one in-flight retry loop. A Trezor
757768
* re-enumerates USB during its unlock flow, so a single replug delivers several

app/src/main/java/to/bitkit/ui/screens/wallets/HomeScreen.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ fun HomeScreen(
244244
DisposableEffect(lifecycle) {
245245
val observer = LifecycleEventObserver { _, event ->
246246
when (event) {
247-
Lifecycle.Event.ON_RESUME -> appViewModel.checkTimedSheets()
247+
Lifecycle.Event.ON_RESUME -> appViewModel.onHomeResumed()
248248
Lifecycle.Event.ON_PAUSE -> appViewModel.onLeftHome()
249249
else -> Unit
250250
}

app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3186,6 +3186,11 @@ class AppViewModel @Inject constructor(
31863186

31873187
fun checkTimedSheets() = timedSheetManager.onHomeScreenEntered()
31883188

3189+
fun onHomeResumed() {
3190+
checkTimedSheets()
3191+
hwWalletRepo.onAppForegrounded()
3192+
}
3193+
31893194
fun onLeftHome() = timedSheetManager.onHomeScreenExited()
31903195

31913196
fun dismissTimedSheet() = timedSheetManager.dismissCurrentSheet()

app/src/test/java/to/bitkit/repositories/HwWalletRepoTest.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,15 @@ class HwWalletRepoTest : BaseUnitTest() {
591591
verify(trezorRepo).onTransportRestored(TransportType.USB)
592592
}
593593

594+
@Test
595+
fun `forwards app foregrounded to the trezor repo`() = test {
596+
val sut = createRepo()
597+
598+
sut.onAppForegrounded()
599+
600+
verify(trezorRepo).onAppForegrounded()
601+
}
602+
594603
@Test
595604
fun `forwards pairing code calls to the trezor repo`() = test {
596605
val sut = createRepo()

app/src/test/java/to/bitkit/repositories/TrezorRepoTest.kt

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import com.synonym.bitkitcore.TrezorPublicKeyResponse
99
import com.synonym.bitkitcore.TrezorSignedMessageResponse
1010
import com.synonym.bitkitcore.TrezorTransportType
1111
import com.synonym.bitkitcore.WalletSelection
12+
import kotlinx.coroutines.ExperimentalCoroutinesApi
1213
import kotlinx.coroutines.flow.MutableSharedFlow
1314
import kotlinx.coroutines.flow.MutableStateFlow
1415
import kotlinx.coroutines.test.advanceUntilIdle
@@ -41,7 +42,7 @@ import kotlin.test.assertTrue
4142
import kotlin.time.Clock
4243
import kotlin.time.ExperimentalTime
4344

44-
@OptIn(ExperimentalTime::class)
45+
@OptIn(ExperimentalCoroutinesApi::class, ExperimentalTime::class)
4546
@Suppress("LargeClass")
4647
class TrezorRepoTest : BaseUnitTest() {
4748

@@ -355,6 +356,39 @@ class TrezorRepoTest : BaseUnitTest() {
355356
assertNotNull(sut.state.value.connected)
356357
}
357358

359+
@Test
360+
fun `app foreground auto-reconnects to a known bluetooth device`() = test {
361+
val features = mockFeatures()
362+
val device = mockDeviceInfo(
363+
transportType = TrezorTransportType.BLUETOOTH,
364+
path = "ble-path",
365+
)
366+
whenever(hwWalletStore.loadKnownDevices()).thenReturn(
367+
listOf(mockKnownDevice(transportType = TransportType.BLUETOOTH))
368+
)
369+
whenever(trezorService.isConnected()).thenReturn(false)
370+
whenever(trezorService.scan()).thenReturn(listOf(device))
371+
whenever(trezorService.connect(eq(DEVICE_ID), any(), eq(false))).thenReturn(features)
372+
sut = createSut()
373+
374+
sut.onAppForegrounded()
375+
advanceUntilIdle()
376+
377+
assertNotNull(sut.state.value.connected)
378+
verify(trezorService).connect(eq(DEVICE_ID), any(), eq(false))
379+
}
380+
381+
@Test
382+
fun `app foreground skips reconnect without a known bluetooth device`() = test {
383+
whenever(hwWalletStore.loadKnownDevices()).thenReturn(listOf(mockKnownDevice()))
384+
sut = createSut()
385+
386+
sut.onAppForegrounded()
387+
advanceUntilIdle()
388+
389+
verify(trezorService, never()).scan()
390+
}
391+
358392
@Test
359393
fun `onTransportRestored skips usb device without permission`() = test {
360394
val device = mockDeviceInfo()

app/src/test/java/to/bitkit/viewmodels/AppViewModelSendFlowTest.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,13 @@ class AppViewModelSendFlowTest : BaseUnitTest() {
263263
verify(hwWalletRepo).onTransportRestored(TransportType.USB)
264264
}
265265

266+
@Test
267+
fun `onHomeResumed forwards app foreground to the hardware wallet repo`() = test {
268+
sut.onHomeResumed()
269+
270+
verify(hwWalletRepo).onAppForegrounded()
271+
}
272+
266273
@Test
267274
fun `hardware received tx details navigate directly to hardware activity`() = test {
268275
val txId = "hardware-tx"

0 commit comments

Comments
 (0)