[#785] Remove press-and-hold from Send
* [#785] Remove press-and-hold for send confirmation - Timed button replaced by standard behaviour button - Related SendView test updated * Remove unused API If we need this back, we can restore it from the Git history. * Remove unused imports --------- Co-authored-by: Carter Jernigan <git@carterjernigan.com>
This commit is contained in:
parent
d37310a935
commit
0c0bf8cb34
|
@ -1,93 +0,0 @@
|
|||
package co.electriccoin.zcash.ui.design.component
|
||||
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.interaction.PressInteraction
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.test.junit4.ComposeContentTestRule
|
||||
import androidx.compose.ui.test.junit4.createComposeRule
|
||||
import androidx.compose.ui.test.onNodeWithText
|
||||
import androidx.compose.ui.test.performClick
|
||||
import androidx.test.filters.MediumTest
|
||||
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.cancel
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.test.StandardTestDispatcher
|
||||
import kotlinx.coroutines.test.advanceTimeBy
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import kotlinx.coroutines.test.testTimeSource
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertTrue
|
||||
import kotlin.time.Duration
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
import kotlin.time.ExperimentalTime
|
||||
|
||||
class ButtonTest {
|
||||
@get:Rule
|
||||
val composeTestRule = createComposeRule()
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class, ExperimentalTime::class)
|
||||
@Test
|
||||
@MediumTest
|
||||
fun timedButtonTest(): Unit = runTest {
|
||||
val testDispatcher = StandardTestDispatcher(testScheduler)
|
||||
val testSetup = newTestSetup(testDispatcher, 2.seconds)
|
||||
val mark = testTimeSource.markNow()
|
||||
|
||||
launch(Dispatchers.Main) {
|
||||
testSetup.interactionSource.emit(PressInteraction.Press(Offset.Zero))
|
||||
advanceTimeBy(3.seconds.inWholeMilliseconds)
|
||||
}
|
||||
|
||||
launch {
|
||||
testSetup.mutableActionExecuted.collect {
|
||||
if (!it) return@collect
|
||||
|
||||
assertTrue { mark.elapsedNow() >= 2.seconds }
|
||||
this.cancel()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
@Test
|
||||
@MediumTest
|
||||
fun buttonClickTest() = runTest {
|
||||
val testDispatcher = StandardTestDispatcher(testScheduler)
|
||||
val testSetup = newTestSetup(testDispatcher, 2.seconds)
|
||||
|
||||
composeTestRule.onNodeWithText("button").also {
|
||||
it.performClick()
|
||||
}
|
||||
advanceTimeBy(3.seconds.inWholeMilliseconds)
|
||||
assertFalse { testSetup.mutableActionExecuted.value }
|
||||
}
|
||||
|
||||
private fun newTestSetup(testDispatcher: CoroutineDispatcher, duration: Duration) = TestSetup(testDispatcher, composeTestRule, duration)
|
||||
|
||||
private class TestSetup(coroutineDispatcher: CoroutineDispatcher, composeTestRule: ComposeContentTestRule, duration: Duration) {
|
||||
val mutableActionExecuted = MutableStateFlow(false)
|
||||
val interactionSource = MutableInteractionSource()
|
||||
|
||||
init {
|
||||
composeTestRule.setContent {
|
||||
ZcashTheme {
|
||||
TimedButton(
|
||||
duration = duration,
|
||||
onClick = { mutableActionExecuted.update { true } },
|
||||
coroutineDispatcher = coroutineDispatcher,
|
||||
content = { Text(text = "button") },
|
||||
interactionSource = interactionSource
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,6 @@
|
|||
package co.electriccoin.zcash.ui.design.component
|
||||
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.interaction.PressInteraction
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.RowScope
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.Button
|
||||
|
@ -12,20 +9,10 @@ import androidx.compose.material3.ButtonDefaults.buttonColors
|
|||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlin.time.Duration
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
|
@ -158,41 +145,3 @@ fun DangerousButton(
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@Composable
|
||||
fun TimedButton(
|
||||
onClick: () -> Unit,
|
||||
content: @Composable (RowScope.() -> Unit),
|
||||
modifier: Modifier = Modifier,
|
||||
duration: Duration = 5.seconds,
|
||||
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
|
||||
coroutineDispatcher: CoroutineDispatcher = Dispatchers.Default
|
||||
) {
|
||||
LaunchedEffect(interactionSource) {
|
||||
var action: Job? = null
|
||||
|
||||
interactionSource.interactions.collect { interaction ->
|
||||
when (interaction) {
|
||||
is PressInteraction.Press -> {
|
||||
action = launch(coroutineDispatcher) {
|
||||
delay(duration)
|
||||
withContext(Dispatchers.Main) {
|
||||
onClick()
|
||||
}
|
||||
}
|
||||
}
|
||||
is PressInteraction.Release -> {
|
||||
action?.cancel()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Button(
|
||||
modifier = modifier,
|
||||
onClick = {},
|
||||
interactionSource = interactionSource,
|
||||
content = content
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
package co.electriccoin.zcash.ui.screen.send.view
|
||||
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.interaction.PressInteraction
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.test.assertIsEnabled
|
||||
import androidx.compose.ui.test.assertIsNotEnabled
|
||||
import androidx.compose.ui.test.junit4.ComposeContentTestRule
|
||||
|
@ -26,13 +23,11 @@ import co.electriccoin.zcash.test.UiTestPrerequisites
|
|||
import co.electriccoin.zcash.ui.R
|
||||
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
||||
import co.electriccoin.zcash.ui.test.getStringResource
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.cancel
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.test.TestScope
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
|
@ -70,7 +65,7 @@ class SendViewTest : UiTestPrerequisites() {
|
|||
composeTestRule.setValidAddress()
|
||||
composeTestRule.clickCreateAndSend()
|
||||
composeTestRule.assertOnConfirmation()
|
||||
clickConfirmation(testSetup.interactionSource)
|
||||
composeTestRule.clickConfirmation()
|
||||
|
||||
launch {
|
||||
testSetup.mutableActionExecuted.collectWith(this) {
|
||||
|
@ -106,7 +101,7 @@ class SendViewTest : UiTestPrerequisites() {
|
|||
|
||||
composeTestRule.clickCreateAndSend()
|
||||
composeTestRule.assertOnConfirmation()
|
||||
clickConfirmation(testSetup.interactionSource)
|
||||
composeTestRule.clickConfirmation()
|
||||
|
||||
launch {
|
||||
testSetup.mutableActionExecuted.collectWith(this) {
|
||||
|
@ -164,7 +159,7 @@ class SendViewTest : UiTestPrerequisites() {
|
|||
|
||||
composeTestRule.clickCreateAndSend()
|
||||
composeTestRule.assertOnConfirmation()
|
||||
clickConfirmation(testSetup.interactionSource)
|
||||
composeTestRule.clickConfirmation()
|
||||
|
||||
launch {
|
||||
testSetup.mutableActionExecuted.collectWith(this) {
|
||||
|
@ -242,7 +237,7 @@ class SendViewTest : UiTestPrerequisites() {
|
|||
|
||||
composeTestRule.clickCreateAndSend()
|
||||
composeTestRule.assertOnConfirmation()
|
||||
clickConfirmation(testSetup.interactionSource)
|
||||
composeTestRule.clickConfirmation()
|
||||
|
||||
launch {
|
||||
testSetup.mutableActionExecuted.collectWith(this) {
|
||||
|
@ -296,7 +291,6 @@ class SendViewTest : UiTestPrerequisites() {
|
|||
|
||||
private val onBackCount = AtomicInteger(0)
|
||||
private val onCreateCount = AtomicInteger(0)
|
||||
val interactionSource = MutableInteractionSource()
|
||||
val mutableActionExecuted = MutableStateFlow(false)
|
||||
|
||||
@Volatile
|
||||
|
@ -322,7 +316,6 @@ class SendViewTest : UiTestPrerequisites() {
|
|||
ZcashTheme {
|
||||
Send(
|
||||
mySpendableBalance = ZatoshiFixture.new(),
|
||||
pressAndHoldInteractionSource = interactionSource,
|
||||
goBack = {
|
||||
onBackCount.incrementAndGet()
|
||||
},
|
||||
|
@ -386,10 +379,9 @@ private fun ComposeContentTestRule.clickCreateAndSend() {
|
|||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
private fun TestScope.clickConfirmation(interactionSource: MutableInteractionSource) {
|
||||
launch(Dispatchers.Main) {
|
||||
interactionSource.emit(PressInteraction.Press(Offset.Zero))
|
||||
private fun ComposeContentTestRule.clickConfirmation() {
|
||||
onNodeWithText(getStringResource(R.string.send_confirm)).also {
|
||||
it.performClick()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package co.electriccoin.zcash.ui.screen.send.view
|
||||
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
|
@ -22,7 +21,6 @@ import androidx.compose.material3.TopAppBar
|
|||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
|
@ -47,7 +45,6 @@ import co.electriccoin.zcash.ui.design.component.FormTextField
|
|||
import co.electriccoin.zcash.ui.design.component.GradientSurface
|
||||
import co.electriccoin.zcash.ui.design.component.Header
|
||||
import co.electriccoin.zcash.ui.design.component.PrimaryButton
|
||||
import co.electriccoin.zcash.ui.design.component.TimedButton
|
||||
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
||||
import co.electriccoin.zcash.ui.design.theme.ZcashTheme.dimens
|
||||
import co.electriccoin.zcash.ui.screen.send.ext.ABBREVIATION_INDEX
|
||||
|
@ -69,16 +66,12 @@ fun PreviewSend() {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param pressAndHoldInteractionSource This is an argument that can be injected for automated testing.
|
||||
*/
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun Send(
|
||||
mySpendableBalance: Zatoshi,
|
||||
goBack: () -> Unit,
|
||||
onCreateAndSend: (ZecSend) -> Unit,
|
||||
pressAndHoldInteractionSource: MutableInteractionSource = remember { MutableInteractionSource() }
|
||||
onCreateAndSend: (ZecSend) -> Unit
|
||||
) {
|
||||
// For now, we're avoiding sub-navigation to keep the navigation logic simple. But this might
|
||||
// change once deep-linking support is added. It depends on whether deep linking should do one of:
|
||||
|
@ -98,7 +91,6 @@ fun Send(
|
|||
SendMainContent(
|
||||
myBalance = mySpendableBalance,
|
||||
sendStage = sendStage,
|
||||
pressAndHoldInteractionSource = pressAndHoldInteractionSource,
|
||||
setSendStage = setSendStage,
|
||||
onCreateAndSend = onCreateAndSend,
|
||||
modifier = Modifier
|
||||
|
@ -138,7 +130,6 @@ private fun SendTopAppBar(onBack: () -> Unit) {
|
|||
private fun SendMainContent(
|
||||
myBalance: Zatoshi,
|
||||
sendStage: SendStage,
|
||||
pressAndHoldInteractionSource: MutableInteractionSource,
|
||||
setSendStage: (SendStage) -> Unit,
|
||||
onCreateAndSend: (ZecSend) -> Unit,
|
||||
modifier: Modifier = Modifier
|
||||
|
@ -158,7 +149,6 @@ private fun SendMainContent(
|
|||
} else {
|
||||
Confirmation(
|
||||
zecSend = zecSend,
|
||||
pressAndHoldInteractionSource = pressAndHoldInteractionSource,
|
||||
onConfirmation = {
|
||||
onCreateAndSend(zecSend)
|
||||
},
|
||||
|
@ -293,7 +283,6 @@ private fun SendForm(
|
|||
@Composable
|
||||
private fun Confirmation(
|
||||
zecSend: ZecSend,
|
||||
pressAndHoldInteractionSource: MutableInteractionSource,
|
||||
onConfirmation: () -> Unit,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
|
@ -306,12 +295,9 @@ private fun Confirmation(
|
|||
)
|
||||
)
|
||||
|
||||
TimedButton(
|
||||
PrimaryButton(
|
||||
onClick = onConfirmation,
|
||||
{
|
||||
Text(text = stringResource(id = R.string.send_confirm))
|
||||
},
|
||||
interactionSource = pressAndHoldInteractionSource
|
||||
text = stringResource(id = R.string.send_confirm)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,6 @@
|
|||
|
||||
<string name="send_amount_and_address_format" formatted="true">Send <xliff:g id="amount" example="12.345">%1$s</xliff:g> ZEC to <xliff:g id="address" example="zs1g7cqw … mvyzgm">%2$s</xliff:g>?</string>
|
||||
<string name="send_abbreviated_address_format" formatted="true"><xliff:g id="first_five" example="zs1g7">%1$s</xliff:g>…<xliff:g id="last_five" example="mvyzg">%2$s</xliff:g></string>
|
||||
<string name="send_confirm">Press and hold to send ZEC</string>
|
||||
<string name="send_confirm">Press to send ZEC</string>
|
||||
|
||||
</resources>
|
||||
|
|
Loading…
Reference in New Issue