[#1147] Show transaction memo
- Improves the screen UI so we’re able to call click, and query transaction memos - These APIs will be useful once we approach screen refactoring according to the Figma design - Adds UI test for the new feature - Closes #1147 Changelog update
This commit is contained in:
parent
d4fdb9aec2
commit
b544de316d
|
@ -9,6 +9,9 @@ directly impact users rather than highlighting other key architectural updates.*
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Transaction history items now display Memos within the Android Toast, triggered by clicking the item
|
||||||
|
|
||||||
## [0.2.0 (517)] - 2023-12-21
|
## [0.2.0 (517)] - 2023-12-21
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
|
@ -104,15 +104,20 @@ fun TitleLarge(
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
@Suppress("LongParameterList")
|
||||||
fun Small(
|
fun Small(
|
||||||
text: String,
|
text: String,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
|
maxLines: Int = Int.MAX_VALUE,
|
||||||
|
overflow: TextOverflow = TextOverflow.Clip,
|
||||||
textAlign: TextAlign = TextAlign.Start,
|
textAlign: TextAlign = TextAlign.Start,
|
||||||
color: Color = MaterialTheme.colorScheme.onBackground,
|
color: Color = MaterialTheme.colorScheme.onBackground,
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = text,
|
text = text,
|
||||||
color = color,
|
color = color,
|
||||||
|
maxLines = maxLines,
|
||||||
|
overflow = overflow,
|
||||||
textAlign = textAlign,
|
textAlign = textAlign,
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
|
|
|
@ -10,11 +10,17 @@ class HistoryTestSetup(
|
||||||
private val composeTestRule: ComposeContentTestRule,
|
private val composeTestRule: ComposeContentTestRule,
|
||||||
initialHistorySyncState: TransactionHistorySyncState
|
initialHistorySyncState: TransactionHistorySyncState
|
||||||
) {
|
) {
|
||||||
private val onBackCount = AtomicInteger(0)
|
private val onBackClickCount = AtomicInteger(0)
|
||||||
|
private val onItemClickCount = AtomicInteger(0)
|
||||||
|
|
||||||
fun getOnBackCount(): Int {
|
fun getOnBackClickCount(): Int {
|
||||||
composeTestRule.waitForIdle()
|
composeTestRule.waitForIdle()
|
||||||
return onBackCount.get()
|
return onBackClickCount.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getOnItemClickCount(): Int {
|
||||||
|
composeTestRule.waitForIdle()
|
||||||
|
return onItemClickCount.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
@ -22,8 +28,11 @@ class HistoryTestSetup(
|
||||||
ZcashTheme {
|
ZcashTheme {
|
||||||
History(
|
History(
|
||||||
transactionState = initialHistorySyncState,
|
transactionState = initialHistorySyncState,
|
||||||
goBack = {
|
onBack = {
|
||||||
onBackCount.incrementAndGet()
|
onBackClickCount.incrementAndGet()
|
||||||
|
},
|
||||||
|
onItemClick = {
|
||||||
|
onItemClickCount.incrementAndGet()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package co.electriccoin.zcash.ui.screen.history.view
|
||||||
|
|
||||||
import androidx.compose.ui.test.assertHeightIsAtLeast
|
import androidx.compose.ui.test.assertHeightIsAtLeast
|
||||||
import androidx.compose.ui.test.junit4.createComposeRule
|
import androidx.compose.ui.test.junit4.createComposeRule
|
||||||
|
import androidx.compose.ui.test.onAllNodesWithTag
|
||||||
import androidx.compose.ui.test.onNodeWithContentDescription
|
import androidx.compose.ui.test.onNodeWithContentDescription
|
||||||
import androidx.compose.ui.test.onNodeWithTag
|
import androidx.compose.ui.test.onNodeWithTag
|
||||||
import androidx.compose.ui.test.onNodeWithText
|
import androidx.compose.ui.test.onNodeWithText
|
||||||
|
@ -105,10 +106,10 @@ class HistoryViewTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@MediumTest
|
@MediumTest
|
||||||
fun back() {
|
fun back_click_test() {
|
||||||
val testSetup = newTestSetup()
|
val testSetup = newTestSetup()
|
||||||
|
|
||||||
assertEquals(0, testSetup.getOnBackCount())
|
assertEquals(0, testSetup.getOnBackClickCount())
|
||||||
|
|
||||||
composeTestRule.onNodeWithContentDescription(
|
composeTestRule.onNodeWithContentDescription(
|
||||||
getStringResource(R.string.history_back_content_description)
|
getStringResource(R.string.history_back_content_description)
|
||||||
|
@ -116,7 +117,23 @@ class HistoryViewTest {
|
||||||
it.performClick()
|
it.performClick()
|
||||||
}
|
}
|
||||||
|
|
||||||
assertEquals(1, testSetup.getOnBackCount())
|
assertEquals(1, testSetup.getOnBackClickCount())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@MediumTest
|
||||||
|
fun item_click_test() {
|
||||||
|
val testSetup = newTestSetup(TransactionHistorySyncStateFixture.STATE)
|
||||||
|
|
||||||
|
assertEquals(0, testSetup.getOnItemClickCount())
|
||||||
|
|
||||||
|
composeTestRule.onAllNodesWithTag(HistoryTag.TRANSACTION_ITEM).also {
|
||||||
|
TransactionHistorySyncStateFixture.TRANSACTIONS.forEachIndexed { index, _ ->
|
||||||
|
it[index].performClick()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(TransactionHistorySyncStateFixture.TRANSACTIONS.size, testSetup.getOnItemClickCount())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun newTestSetup(
|
private fun newTestSetup(
|
||||||
|
|
|
@ -43,7 +43,9 @@ internal fun WrapAccount(
|
||||||
val isFiatConversionEnabled = ConfigurationEntries.IS_FIAT_CONVERSION_ENABLED.getValue(RemoteConfig.current)
|
val isFiatConversionEnabled = ConfigurationEntries.IS_FIAT_CONVERSION_ENABLED.getValue(RemoteConfig.current)
|
||||||
|
|
||||||
if (null == walletSnapshot) {
|
if (null == walletSnapshot) {
|
||||||
// Improve this by allowing screen composition and updating it after the data is available
|
// TODO [#1146]: Consider moving CircularScreenProgressIndicator from Android layer to View layer
|
||||||
|
// TODO [#1146]: Improve this by allowing screen composition and updating it after the data is available
|
||||||
|
// TODO [#1146]: https://github.com/Electric-Coin-Company/zashi-android/issues/1146
|
||||||
CircularScreenProgressIndicator()
|
CircularScreenProgressIndicator()
|
||||||
} else {
|
} else {
|
||||||
Account(
|
Account(
|
||||||
|
|
|
@ -28,7 +28,9 @@ private fun WrapWalletAddresses(
|
||||||
val walletAddresses = walletViewModel.addresses.collectAsStateWithLifecycle().value
|
val walletAddresses = walletViewModel.addresses.collectAsStateWithLifecycle().value
|
||||||
|
|
||||||
if (null == walletAddresses) {
|
if (null == walletAddresses) {
|
||||||
// Improve this by allowing screen composition and updating it after the data is available
|
// TODO [#1146]: Consider moving CircularScreenProgressIndicator from Android layer to View layer
|
||||||
|
// TODO [#1146]: Improve this by allowing screen composition and updating it after the data is available
|
||||||
|
// TODO [#1146]: https://github.com/Electric-Coin-Company/zashi-android/issues/1146
|
||||||
CircularScreenProgressIndicator()
|
CircularScreenProgressIndicator()
|
||||||
} else {
|
} else {
|
||||||
WalletAddresses(
|
WalletAddresses(
|
||||||
|
|
|
@ -46,7 +46,9 @@ internal fun WrapExportPrivateData(
|
||||||
val synchronizer = walletViewModel.synchronizer.collectAsStateWithLifecycle().value
|
val synchronizer = walletViewModel.synchronizer.collectAsStateWithLifecycle().value
|
||||||
|
|
||||||
if (synchronizer == null) {
|
if (synchronizer == null) {
|
||||||
// Improve this by allowing screen composition and updating it after the data is available
|
// TODO [#1146]: Consider moving CircularScreenProgressIndicator from Android layer to View layer
|
||||||
|
// TODO [#1146]: Improve this by allowing screen composition and updating it after the data is available
|
||||||
|
// TODO [#1146]: https://github.com/Electric-Coin-Company/zashi-android/issues/1146
|
||||||
CircularScreenProgressIndicator()
|
CircularScreenProgressIndicator()
|
||||||
} else {
|
} else {
|
||||||
val snackbarHostState = remember { SnackbarHostState() }
|
val snackbarHostState = remember { SnackbarHostState() }
|
||||||
|
|
|
@ -3,11 +3,17 @@ package co.electriccoin.zcash.ui.screen.history
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import cash.z.ecc.android.sdk.internal.Twig
|
import cash.z.ecc.android.sdk.internal.Twig
|
||||||
|
import co.electriccoin.zcash.spackle.ClipboardManagerUtil
|
||||||
import co.electriccoin.zcash.ui.MainActivity
|
import co.electriccoin.zcash.ui.MainActivity
|
||||||
|
import co.electriccoin.zcash.ui.R
|
||||||
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
|
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
|
||||||
|
import co.electriccoin.zcash.ui.design.component.CircularScreenProgressIndicator
|
||||||
import co.electriccoin.zcash.ui.screen.history.view.History
|
import co.electriccoin.zcash.ui.screen.history.view.History
|
||||||
|
import kotlinx.coroutines.flow.toList
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
internal fun MainActivity.WrapHistory(goBack: () -> Unit) {
|
internal fun MainActivity.WrapHistory(goBack: () -> Unit) {
|
||||||
|
@ -22,15 +28,41 @@ internal fun WrapHistory(
|
||||||
activity: ComponentActivity,
|
activity: ComponentActivity,
|
||||||
goBack: () -> Unit
|
goBack: () -> Unit
|
||||||
) {
|
) {
|
||||||
|
val queryScope = rememberCoroutineScope()
|
||||||
|
|
||||||
val walletViewModel by activity.viewModels<WalletViewModel>()
|
val walletViewModel by activity.viewModels<WalletViewModel>()
|
||||||
|
|
||||||
|
val synchronizer = walletViewModel.synchronizer.collectAsStateWithLifecycle().value
|
||||||
|
|
||||||
val transactionHistoryState =
|
val transactionHistoryState =
|
||||||
walletViewModel.transactionHistoryState.collectAsStateWithLifecycle().value
|
walletViewModel.transactionHistoryState.collectAsStateWithLifecycle().value
|
||||||
|
|
||||||
Twig.info { "Current transaction history state: $transactionHistoryState" }
|
Twig.info { "Current transaction history state: $transactionHistoryState" }
|
||||||
|
|
||||||
|
if (synchronizer == null) {
|
||||||
|
// TODO [#1146]: Consider moving CircularScreenProgressIndicator from Android layer to View layer
|
||||||
|
// TODO [#1146]: Improve this by allowing screen composition and updating it after the data is available
|
||||||
|
// TODO [#1146]: https://github.com/Electric-Coin-Company/zashi-android/issues/1146
|
||||||
|
CircularScreenProgressIndicator()
|
||||||
|
} else {
|
||||||
History(
|
History(
|
||||||
transactionState = transactionHistoryState,
|
transactionState = transactionHistoryState,
|
||||||
goBack = goBack
|
onBack = goBack,
|
||||||
|
onItemClick = { tx ->
|
||||||
|
Twig.debug { "Querying transaction memos..." }
|
||||||
|
val memos = synchronizer.getMemos(tx)
|
||||||
|
queryScope.launch {
|
||||||
|
memos.toList().run {
|
||||||
|
val merged = joinToString().ifEmpty { "-" }
|
||||||
|
Twig.info { "Transaction memos: count: $size, contains: $merged" }
|
||||||
|
ClipboardManagerUtil.copyToClipboard(
|
||||||
|
activity.applicationContext,
|
||||||
|
activity.getString(R.string.history_item_clipboard_tag),
|
||||||
|
merged
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -5,5 +5,6 @@ package co.electriccoin.zcash.ui.screen.history
|
||||||
*/
|
*/
|
||||||
object HistoryTag {
|
object HistoryTag {
|
||||||
const val TRANSACTION_LIST = "transaction_list"
|
const val TRANSACTION_LIST = "transaction_list"
|
||||||
|
const val TRANSACTION_ITEM = "transaction_item"
|
||||||
const val PROGRESS = "progress_bar"
|
const val PROGRESS = "progress_bar"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,18 @@
|
||||||
package co.electriccoin.zcash.ui.screen.history.view
|
package co.electriccoin.zcash.ui.screen.history.view
|
||||||
|
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxHeight
|
import androidx.compose.foundation.layout.fillMaxHeight
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.itemsIndexed
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.ArrowBack
|
import androidx.compose.material.icons.filled.ArrowBack
|
||||||
import androidx.compose.material.icons.filled.Cancel
|
import androidx.compose.material.icons.filled.Cancel
|
||||||
|
@ -22,6 +21,8 @@ import androidx.compose.material.icons.outlined.ArrowCircleUp
|
||||||
import androidx.compose.material.icons.twotone.ArrowCircleDown
|
import androidx.compose.material.icons.twotone.ArrowCircleDown
|
||||||
import androidx.compose.material.icons.twotone.ArrowCircleUp
|
import androidx.compose.material.icons.twotone.ArrowCircleUp
|
||||||
import androidx.compose.material3.CircularProgressIndicator
|
import androidx.compose.material3.CircularProgressIndicator
|
||||||
|
import androidx.compose.material3.Divider
|
||||||
|
import androidx.compose.material3.DividerDefaults
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
|
@ -65,7 +66,8 @@ private fun ComposablePreview() {
|
||||||
GradientSurface {
|
GradientSurface {
|
||||||
History(
|
History(
|
||||||
transactionState = TransactionHistorySyncState.Loading,
|
transactionState = TransactionHistorySyncState.Loading,
|
||||||
goBack = {}
|
onBack = {},
|
||||||
|
onItemClick = {}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -86,7 +88,8 @@ private fun ComposableHistoryListPreview() {
|
||||||
TransactionOverviewFixture.new(netValue = Zatoshi(300000000)),
|
TransactionOverviewFixture.new(netValue = Zatoshi(300000000)),
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
goBack = {}
|
onBack = {},
|
||||||
|
onItemClick = {}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,13 +106,15 @@ val dateFormat: DateFormat by lazy {
|
||||||
@Composable
|
@Composable
|
||||||
fun History(
|
fun History(
|
||||||
transactionState: TransactionHistorySyncState,
|
transactionState: TransactionHistorySyncState,
|
||||||
goBack: () -> Unit
|
onBack: () -> Unit,
|
||||||
|
onItemClick: (TransactionOverview) -> Unit
|
||||||
) {
|
) {
|
||||||
Scaffold(topBar = {
|
Scaffold(topBar = {
|
||||||
HistoryTopBar(onBack = goBack)
|
HistoryTopBar(onBack = onBack)
|
||||||
}) { paddingValues ->
|
}) { paddingValues ->
|
||||||
HistoryMainContent(
|
HistoryMainContent(
|
||||||
transactionState = transactionState,
|
transactionState = transactionState,
|
||||||
|
onItemClick = onItemClick,
|
||||||
modifier =
|
modifier =
|
||||||
Modifier
|
Modifier
|
||||||
.fillMaxHeight()
|
.fillMaxHeight()
|
||||||
|
@ -142,6 +147,7 @@ private fun HistoryTopBar(onBack: () -> Unit) {
|
||||||
@Composable
|
@Composable
|
||||||
private fun HistoryMainContent(
|
private fun HistoryMainContent(
|
||||||
transactionState: TransactionHistorySyncState,
|
transactionState: TransactionHistorySyncState,
|
||||||
|
onItemClick: (TransactionOverview) -> Unit,
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
Box(modifier = modifier.fillMaxSize()) {
|
Box(modifier = modifier.fillMaxSize()) {
|
||||||
|
@ -169,7 +175,10 @@ private fun HistoryMainContent(
|
||||||
end = ZcashTheme.dimens.spacingDefault
|
end = ZcashTheme.dimens.spacingDefault
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
HistoryList(transactions = transactionState.transactions)
|
HistoryList(
|
||||||
|
transactions = transactionState.transactions,
|
||||||
|
onItemClick = onItemClick
|
||||||
|
)
|
||||||
}
|
}
|
||||||
// Add progress indicator only in the state of empty transaction
|
// Add progress indicator only in the state of empty transaction
|
||||||
if (transactionState.hasNoTransactions()) {
|
if (transactionState.hasNoTransactions()) {
|
||||||
|
@ -191,7 +200,10 @@ private fun HistoryMainContent(
|
||||||
.align(alignment = Center)
|
.align(alignment = Center)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
HistoryList(transactions = transactionState.transactions)
|
HistoryList(
|
||||||
|
transactions = transactionState.transactions,
|
||||||
|
onItemClick = onItemClick
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -199,17 +211,25 @@ private fun HistoryMainContent(
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun HistoryList(transactions: ImmutableList<TransactionOverview>) {
|
private fun HistoryList(
|
||||||
val currency = ZcashCurrency.fromResources(LocalContext.current)
|
transactions: ImmutableList<TransactionOverview>,
|
||||||
LazyColumn(
|
onItemClick: (TransactionOverview) -> Unit
|
||||||
contentPadding = PaddingValues(all = ZcashTheme.dimens.spacingDefault),
|
|
||||||
modifier = Modifier.testTag(HistoryTag.TRANSACTION_LIST)
|
|
||||||
) {
|
) {
|
||||||
items(transactions) {
|
val currency = ZcashCurrency.fromResources(LocalContext.current)
|
||||||
|
LazyColumn(modifier = Modifier.testTag(HistoryTag.TRANSACTION_LIST)) {
|
||||||
|
itemsIndexed(transactions) { index, item ->
|
||||||
HistoryItem(
|
HistoryItem(
|
||||||
transaction = it,
|
transaction = item,
|
||||||
currency = currency
|
currency = currency,
|
||||||
|
onItemClick = onItemClick,
|
||||||
|
modifier = Modifier.testTag(HistoryTag.TRANSACTION_ITEM)
|
||||||
)
|
)
|
||||||
|
if (index < transactions.lastIndex) {
|
||||||
|
Divider(
|
||||||
|
color = ZcashTheme.colors.dividerColor,
|
||||||
|
thickness = DividerDefaults.Thickness
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -218,56 +238,67 @@ private fun HistoryList(transactions: ImmutableList<TransactionOverview>) {
|
||||||
@Suppress("LongMethod")
|
@Suppress("LongMethod")
|
||||||
fun HistoryItem(
|
fun HistoryItem(
|
||||||
transaction: TransactionOverview,
|
transaction: TransactionOverview,
|
||||||
currency: ZcashCurrency
|
currency: ZcashCurrency,
|
||||||
|
onItemClick: (TransactionOverview) -> Unit,
|
||||||
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
Row(
|
val transactionTypeText: String
|
||||||
modifier =
|
val transactionTypeIcon: ImageVector
|
||||||
Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.padding(vertical = ZcashTheme.dimens.spacingSmall),
|
|
||||||
verticalAlignment = Alignment.CenterVertically
|
|
||||||
) {
|
|
||||||
val transactionText: String
|
|
||||||
val transactionIcon: ImageVector
|
|
||||||
when (transaction.getExtendedState()) {
|
when (transaction.getExtendedState()) {
|
||||||
TransactionExtendedState.SENT -> {
|
TransactionExtendedState.SENT -> {
|
||||||
transactionText = stringResource(id = R.string.history_item_sent)
|
transactionTypeText = stringResource(id = R.string.history_item_sent)
|
||||||
transactionIcon = Icons.TwoTone.ArrowCircleUp
|
transactionTypeIcon = Icons.TwoTone.ArrowCircleUp
|
||||||
}
|
}
|
||||||
TransactionExtendedState.SENDING -> {
|
TransactionExtendedState.SENDING -> {
|
||||||
transactionText = stringResource(id = R.string.history_item_sending)
|
transactionTypeText = stringResource(id = R.string.history_item_sending)
|
||||||
transactionIcon = Icons.Outlined.ArrowCircleUp
|
transactionTypeIcon = Icons.Outlined.ArrowCircleUp
|
||||||
}
|
}
|
||||||
TransactionExtendedState.RECEIVED -> {
|
TransactionExtendedState.RECEIVED -> {
|
||||||
transactionText = stringResource(id = R.string.history_item_received)
|
transactionTypeText = stringResource(id = R.string.history_item_received)
|
||||||
transactionIcon = Icons.TwoTone.ArrowCircleDown
|
transactionTypeIcon = Icons.TwoTone.ArrowCircleDown
|
||||||
}
|
}
|
||||||
TransactionExtendedState.RECEIVING -> {
|
TransactionExtendedState.RECEIVING -> {
|
||||||
transactionText = stringResource(id = R.string.history_item_receiving)
|
transactionTypeText = stringResource(id = R.string.history_item_receiving)
|
||||||
transactionIcon = Icons.Outlined.ArrowCircleDown
|
transactionTypeIcon = Icons.Outlined.ArrowCircleDown
|
||||||
}
|
}
|
||||||
TransactionExtendedState.EXPIRED -> {
|
TransactionExtendedState.EXPIRED -> {
|
||||||
transactionText = stringResource(id = R.string.history_item_expired)
|
transactionTypeText = stringResource(id = R.string.history_item_expired)
|
||||||
transactionIcon = Icons.Filled.Cancel
|
transactionTypeIcon = Icons.Filled.Cancel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Row(
|
||||||
|
modifier =
|
||||||
|
modifier.then(
|
||||||
|
Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.clickable { onItemClick(transaction) }
|
||||||
|
.padding(
|
||||||
|
horizontal = ZcashTheme.dimens.spacingDefault,
|
||||||
|
vertical = ZcashTheme.dimens.spacingDefault
|
||||||
|
)
|
||||||
|
),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
Image(
|
Image(
|
||||||
imageVector = transactionIcon,
|
imageVector = transactionTypeIcon,
|
||||||
contentDescription = transactionText,
|
contentDescription = transactionTypeText,
|
||||||
modifier = Modifier.padding(all = ZcashTheme.dimens.spacingTiny)
|
modifier = Modifier.padding(all = ZcashTheme.dimens.spacingTiny)
|
||||||
)
|
)
|
||||||
|
Spacer(modifier = Modifier.width(ZcashTheme.dimens.spacingTiny))
|
||||||
|
Column(modifier = Modifier.fillMaxWidth()) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier.weight(1f)
|
modifier = Modifier.weight(1f)
|
||||||
) {
|
) {
|
||||||
Body(
|
Body(
|
||||||
text = transactionText,
|
text = transactionTypeText,
|
||||||
color = Color.Black
|
color = Color.Black
|
||||||
)
|
)
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingTiny))
|
|
||||||
|
|
||||||
val dateString =
|
val dateString =
|
||||||
transaction.minedHeight?.let {
|
transaction.minedHeight?.let {
|
||||||
transaction.blockTimeEpochSeconds?.let { blockTimeEpochSeconds ->
|
transaction.blockTimeEpochSeconds?.let { blockTimeEpochSeconds ->
|
||||||
|
@ -302,6 +333,8 @@ fun HistoryItem(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
enum class TransactionExtendedState {
|
enum class TransactionExtendedState {
|
||||||
SENT,
|
SENT,
|
||||||
|
|
|
@ -130,7 +130,6 @@ fun Home(
|
||||||
thickness = DividerDefaults.Thickness,
|
thickness = DividerDefaults.Thickness,
|
||||||
color = ZcashTheme.colors.dividerColor
|
color = ZcashTheme.colors.dividerColor
|
||||||
)
|
)
|
||||||
|
|
||||||
TabRow(
|
TabRow(
|
||||||
selectedTabIndex = pagerState.currentPage,
|
selectedTabIndex = pagerState.currentPage,
|
||||||
// Don't use the predefined divider, as it's fixed position is below the tabs bar
|
// Don't use the predefined divider, as it's fixed position is below the tabs bar
|
||||||
|
|
|
@ -34,7 +34,9 @@ internal fun WrapReceive(
|
||||||
onAddressDetails: () -> Unit,
|
onAddressDetails: () -> Unit,
|
||||||
) {
|
) {
|
||||||
if (null == walletAddresses) {
|
if (null == walletAddresses) {
|
||||||
// Improve this by allowing screen composition and updating it after the data is available
|
// TODO [#1146]: Consider moving CircularScreenProgressIndicator from Android layer to View layer
|
||||||
|
// TODO [#1146]: Improve this by allowing screen composition and updating it after the data is available
|
||||||
|
// TODO [#1146]: https://github.com/Electric-Coin-Company/zashi-android/issues/1146
|
||||||
CircularScreenProgressIndicator()
|
CircularScreenProgressIndicator()
|
||||||
} else {
|
} else {
|
||||||
Receive(
|
Receive(
|
||||||
|
|
|
@ -30,7 +30,9 @@ private fun WrapRequest(
|
||||||
val walletAddresses = walletViewModel.addresses.collectAsStateWithLifecycle().value
|
val walletAddresses = walletViewModel.addresses.collectAsStateWithLifecycle().value
|
||||||
|
|
||||||
if (null == walletAddresses) {
|
if (null == walletAddresses) {
|
||||||
// Improve this by allowing screen composition and updating it after the data is available
|
// TODO [#1146]: Consider moving CircularScreenProgressIndicator from Android layer to View layer
|
||||||
|
// TODO [#1146]: Improve this by allowing screen composition and updating it after the data is available
|
||||||
|
// TODO [#1146]: https://github.com/Electric-Coin-Company/zashi-android/issues/1146
|
||||||
CircularScreenProgressIndicator()
|
CircularScreenProgressIndicator()
|
||||||
} else {
|
} else {
|
||||||
Request(
|
Request(
|
||||||
|
|
|
@ -41,7 +41,9 @@ fun WrapScan(
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
if (synchronizer == null) {
|
if (synchronizer == null) {
|
||||||
// Improve this by allowing screen composition and updating it after the data is available
|
// TODO [#1146]: Consider moving CircularScreenProgressIndicator from Android layer to View layer
|
||||||
|
// TODO [#1146]: Improve this by allowing screen composition and updating it after the data is available
|
||||||
|
// TODO [#1146]: https://github.com/Electric-Coin-Company/zashi-android/issues/1146
|
||||||
CircularScreenProgressIndicator()
|
CircularScreenProgressIndicator()
|
||||||
} else {
|
} else {
|
||||||
Scan(
|
Scan(
|
||||||
|
|
|
@ -40,7 +40,9 @@ private fun WrapSeedRecovery(
|
||||||
val synchronizer = walletViewModel.synchronizer.collectAsStateWithLifecycle().value
|
val synchronizer = walletViewModel.synchronizer.collectAsStateWithLifecycle().value
|
||||||
|
|
||||||
if (null == synchronizer || null == persistableWallet) {
|
if (null == synchronizer || null == persistableWallet) {
|
||||||
// Improve this by allowing screen composition and updating it after the data is available
|
// TODO [#1146]: Consider moving CircularScreenProgressIndicator from Android layer to View layer
|
||||||
|
// TODO [#1146]: Improve this by allowing screen composition and updating it after the data is available
|
||||||
|
// TODO [#1146]: https://github.com/Electric-Coin-Company/zashi-android/issues/1146
|
||||||
CircularScreenProgressIndicator()
|
CircularScreenProgressIndicator()
|
||||||
} else {
|
} else {
|
||||||
SeedRecovery(
|
SeedRecovery(
|
||||||
|
|
|
@ -100,7 +100,9 @@ internal fun WrapSend(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (null == synchronizer || null == spendableBalance || null == spendingKey) {
|
if (null == synchronizer || null == spendableBalance || null == spendingKey) {
|
||||||
// Improve this by allowing screen composition and updating it after the data is available
|
// TODO [#1146]: Consider moving CircularScreenProgressIndicator from Android layer to View layer
|
||||||
|
// TODO [#1146]: Improve this by allowing screen composition and updating it after the data is available
|
||||||
|
// TODO [#1146]: https://github.com/Electric-Coin-Company/zashi-android/issues/1146
|
||||||
CircularScreenProgressIndicator()
|
CircularScreenProgressIndicator()
|
||||||
} else {
|
} else {
|
||||||
Send(
|
Send(
|
||||||
|
|
|
@ -72,7 +72,9 @@ private fun WrapSettings(
|
||||||
null == isBackgroundSyncEnabled ||
|
null == isBackgroundSyncEnabled ||
|
||||||
null == isKeepScreenOnWhileSyncing
|
null == isKeepScreenOnWhileSyncing
|
||||||
) {
|
) {
|
||||||
// Improve this by allowing screen composition and updating it after the data is available
|
// TODO [#1146]: Consider moving CircularScreenProgressIndicator from Android layer to View layer
|
||||||
|
// TODO [#1146]: Improve this by allowing screen composition and updating it after the data is available
|
||||||
|
// TODO [#1146]: https://github.com/Electric-Coin-Company/zashi-android/issues/1146
|
||||||
CircularScreenProgressIndicator()
|
CircularScreenProgressIndicator()
|
||||||
} else {
|
} else {
|
||||||
Settings(
|
Settings(
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
<string name="history_back_content_description">Back</string>
|
<string name="history_back_content_description">Back</string>
|
||||||
<string name="history_syncing">Additional transactions may be found after syncing completes…</string>
|
<string name="history_syncing">Additional transactions may be found after syncing completes…</string>
|
||||||
<string name="history_empty">No transactions yet</string>
|
<string name="history_empty">No transactions yet</string>
|
||||||
|
<string name="history_item_clipboard_tag">Transaction memo</string>
|
||||||
|
|
||||||
<string name="history_item_sent">Sent</string>
|
<string name="history_item_sent">Sent</string>
|
||||||
<string name="history_item_received">Received</string>
|
<string name="history_item_received">Received</string>
|
||||||
|
|
Loading…
Reference in New Issue