Skip to content

Commit a098902

Browse files
authored
Merge pull request #428 from code-payments/fix/handle-remote-send-confirmation-timeout
Fix/handle remote send confirmation timeout
2 parents c6d6f2e + 27ffa5a commit a098902

File tree

4 files changed

+74
-46
lines changed

4 files changed

+74
-46
lines changed

api/src/main/java/com/getcode/network/repository/SendTransactionRepository.kt

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
package com.getcode.network.repository
22

3-
import android.content.Context
4-
import com.getcode.ed25519.Ed25519
53
import com.getcode.analytics.AnalyticsService
4+
import com.getcode.ed25519.Ed25519
5+
import com.getcode.model.CodePayload
6+
import com.getcode.model.IntentMetadata
7+
import com.getcode.model.Kin
8+
import com.getcode.model.KinAmount
9+
import com.getcode.model.Kind
10+
import com.getcode.network.client.Client
11+
import com.getcode.network.client.pollIntentMetadata
12+
import com.getcode.network.client.transfer
613
import com.getcode.solana.keys.PublicKey
7-
import com.getcode.model.*
8-
import com.getcode.network.client.*
914
import com.getcode.solana.organizer.Organizer
10-
import com.getcode.utils.ErrorUtils
1115
import com.getcode.utils.nonce
12-
import dagger.hilt.android.qualifiers.ApplicationContext
1316
import io.reactivex.rxjava3.core.Flowable
1417
import kotlinx.coroutines.rx3.asFlowable
1518
import javax.inject.Inject
@@ -21,15 +24,17 @@ class SendTransactionRepository @Inject constructor(
2124
private val client: Client,
2225
) {
2326
private lateinit var amount: KinAmount
27+
private lateinit var organizer: Organizer
2428
private lateinit var owner: Ed25519.KeyPair
2529
private lateinit var payload: CodePayload
2630
lateinit var payloadData: List<Byte>
2731

2832
private lateinit var rendezvousKey: Ed25519.KeyPair
2933
private var receivingAccount: PublicKey? = null
3034

31-
fun init(amount: KinAmount, owner: Ed25519.KeyPair) {
35+
fun init(amount: KinAmount, organizer: Organizer, owner: Ed25519.KeyPair) {
3236
this.amount = amount
37+
this.organizer = organizer
3338
this.owner = owner
3439

3540
this.payload = CodePayload(
@@ -43,7 +48,7 @@ class SendTransactionRepository @Inject constructor(
4348
this.receivingAccount = null
4449
}
4550

46-
fun startTransaction(organizer: Organizer): Flowable<IntentMetadata> {
51+
fun startTransaction(): Flowable<IntentMetadata> {
4752
return messagingRepository.openMessageStream(rendezvousKey)
4853
.firstOrError()
4954
.flatMapPublisher { paymentRequest ->
Lines changed: 50 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,79 @@
11
package com.getcode.ui.components
22

3-
import androidx.compose.animation.*
3+
import androidx.compose.animation.AnimatedVisibility
44
import androidx.compose.animation.core.MutableTransitionState
55
import androidx.compose.animation.core.tween
6+
import androidx.compose.animation.slideInVertically
7+
import androidx.compose.animation.slideOutVertically
68
import androidx.compose.foundation.interaction.MutableInteractionSource
79
import androidx.compose.foundation.layout.Box
810
import androidx.compose.foundation.layout.fillMaxSize
9-
import androidx.compose.runtime.*
10-
import androidx.compose.runtime.livedata.observeAsState
11+
import androidx.compose.runtime.Composable
12+
import androidx.compose.runtime.LaunchedEffect
13+
import androidx.compose.runtime.collectAsState
14+
import androidx.compose.runtime.getValue
15+
import androidx.compose.runtime.mutableLongStateOf
16+
import androidx.compose.runtime.remember
17+
import androidx.compose.runtime.rememberCoroutineScope
18+
import androidx.compose.runtime.setValue
1119
import androidx.compose.ui.Modifier
1220
import com.getcode.CodeAppState
1321
import com.getcode.manager.BottomBarManager
1422
import com.getcode.ui.utils.rememberedClickable
15-
import java.util.*
16-
import kotlin.concurrent.timerTask
23+
import kotlinx.coroutines.delay
24+
import kotlinx.coroutines.launch
1725

1826
@Composable
1927
fun BottomBarContainer(appState: CodeAppState) {
28+
val scope = rememberCoroutineScope()
2029
val bottomBarMessage by appState.bottomBarMessage.collectAsState()
21-
val bottomBarVisibleState = remember { MutableTransitionState(false) }
30+
val bottomBarVisibleState = remember(bottomBarMessage?.id) { MutableTransitionState(false) }
2231
var bottomBarMessageDismissId by remember { mutableLongStateOf(0L) }
23-
val onClose: (bottomBarActionType: BottomBarManager.BottomBarActionType?) -> Unit = {
32+
val onClose: suspend (bottomBarActionType: BottomBarManager.BottomBarActionType?) -> Unit = {
2433
bottomBarMessageDismissId = bottomBarMessage?.id ?: 0
2534
bottomBarVisibleState.targetState = false
26-
2735
bottomBarMessage?.onClose?.invoke(it)
2836

29-
Timer().schedule(timerTask {
30-
BottomBarManager.setMessageShown(bottomBarMessageDismissId)
31-
}, 100)
32-
}
33-
val onBackPressed = {
34-
if (bottomBarMessage?.isDismissible == true) onClose(null)
37+
delay(100)
38+
BottomBarManager.setMessageShown(bottomBarMessageDismissId)
3539
}
3640

37-
if (!bottomBarVisibleState.targetState && !bottomBarVisibleState.currentState) {
38-
Timer().schedule(timerTask {
41+
// handle changes in visible state
42+
LaunchedEffect(bottomBarVisibleState) {
43+
if (!bottomBarVisibleState.targetState && !bottomBarVisibleState.currentState) {
44+
delay(50)
3945
bottomBarVisibleState.targetState = bottomBarMessage != null
40-
}, 50)
4146

42-
if (bottomBarMessageDismissId == bottomBarMessage?.id) {
47+
if (bottomBarMessageDismissId == bottomBarMessage?.id) {
48+
bottomBarMessageDismissId = 0
49+
}
50+
}
51+
}
52+
53+
// handle provided timeout duration; triggering onClose with no action
54+
LaunchedEffect(bottomBarMessage) {
55+
bottomBarMessage?.timeoutSeconds?.let {
56+
delay(it * 1000L)
4357
onClose(null)
44-
bottomBarMessageDismissId = 0
4558
}
4659
}
4760

61+
// add transparent touch handler if dismissible
4862
if (bottomBarVisibleState.targetState && bottomBarMessage != null) {
49-
Box(
50-
modifier = Modifier
51-
.fillMaxSize()
52-
.rememberedClickable(indication = null,
53-
interactionSource = remember { MutableInteractionSource() }) {
54-
if (bottomBarMessage?.isDismissible == true) onClose(null)
55-
}
56-
)
63+
bottomBarMessage?.let {
64+
if (it.isDismissible) {
65+
Box(
66+
modifier = Modifier
67+
.fillMaxSize()
68+
.rememberedClickable(indication = null,
69+
interactionSource = remember { MutableInteractionSource() }
70+
) {
71+
scope.launch { onClose(null) }
72+
}
73+
)
74+
}
75+
}
76+
5777
}
5878

5979
AnimatedVisibility(
@@ -68,14 +88,9 @@ fun BottomBarContainer(appState: CodeAppState) {
6888
animationSpec = tween(300)
6989
),
7090
) {
71-
BottomBarView(bottomBarMessage = bottomBarMessage, onClose, onBackPressed)
72-
}
73-
74-
LaunchedEffect(bottomBarMessage) {
75-
bottomBarMessage?.timeoutSeconds?.let { timeout ->
76-
Timer().schedule(timerTask {
77-
onClose(null)
78-
}, timeout.toLong() * 1000)
91+
val closeWith: (BottomBarManager.BottomBarActionType?) -> Unit = { type ->
92+
scope.launch { onClose(type) }
7993
}
94+
BottomBarView(bottomBarMessage = bottomBarMessage, closeWith, onBackPressed = { closeWith(null)})
8095
}
8196
}

app/src/main/java/com/getcode/ui/components/BottomBarView.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ fun BottomBarView(
3535
LaunchedEffect(bottomBarMessage) {
3636
trace("bottom bar message shown=${bottomBarMessage.title}")
3737
}
38-
BackHandler {
38+
BackHandler(enabled = bottomBarMessage.isDismissible) {
3939
onBackPressed()
4040
}
4141

app/src/main/java/com/getcode/view/main/home/HomeViewModel.kt

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -414,9 +414,9 @@ class HomeViewModel @Inject constructor(
414414

415415
// this should not be in the view model
416416
sendTransactionDisposable?.dispose()
417-
sendTransactionRepository.init(amount = amountFloor, owner = owner)
417+
sendTransactionRepository.init(amountFloor, organizer, owner)
418418
sendTransactionDisposable =
419-
sendTransactionRepository.startTransaction(organizer)
419+
sendTransactionRepository.startTransaction()
420420
.subscribe({
421421
cancelSend(PresentationStyle.Pop)
422422
vibrator.vibrate()
@@ -1413,6 +1413,8 @@ class HomeViewModel @Inject constructor(
14131413
}
14141414
delay(2500)
14151415

1416+
billDismissTimer?.cancel()
1417+
14161418
BottomBarManager.showMessage(
14171419
BottomBarManager.BottomBarMessage(
14181420
title = getString(R.string.prompt_title_didYouSendLink),
@@ -1429,6 +1431,12 @@ class HomeViewModel @Inject constructor(
14291431
cancelRemoteSend(giftCard, amount)
14301432
cancelSend(style = PresentationStyle.Slide)
14311433
},
1434+
onClose = {
1435+
if (it == null) {
1436+
cancelSend(style = PresentationStyle.Pop)
1437+
vibrator.vibrate()
1438+
}
1439+
},
14321440
type = BottomBarManager.BottomBarMessageType.REMOTE_SEND,
14331441
isDismissible = false,
14341442
timeoutSeconds = 60

0 commit comments

Comments
 (0)