From f31f1f4a002618202ff0ee0986cdac5366fdffc3 Mon Sep 17 00:00:00 2001 From: jvsena42 Date: Wed, 20 May 2026 15:35:05 -0300 Subject: [PATCH 1/7] fix: caps selected block fields to 4 --- .../screens/widgets/blocks/BlockCardTest.kt | 169 ++++++-------- .../appwidget/config/AppWidgetConfigScreen.kt | 8 +- .../config/AppWidgetConfigViewModel.kt | 48 +--- .../appwidget/config/BlocksConfigContent.kt | 76 ++----- .../appwidget/model/AppWidgetPreferences.kt | 1 - .../ui/blocks/BlocksGlanceContent.kt | 103 +++------ .../main/java/to/bitkit/data/dto/BlockDTO.kt | 1 - .../to/bitkit/data/widgets/BlocksService.kt | 1 - .../to/bitkit/models/widget/BlockModel.kt | 2 - .../bitkit/models/widget/BlocksPreferences.kt | 1 - .../bitkit/models/widget/BlocksWidgetField.kt | 75 +++++++ .../to/bitkit/services/MigrationService.kt | 6 +- .../bitkit/ui/screens/wallets/HomeScreen.kt | 19 +- .../ui/screens/widgets/blocks/BlockCard.kt | 211 +++++------------- .../widgets/blocks/BlocksEditScreen.kt | 126 ++--------- .../widgets/blocks/BlocksPreviewScreen.kt | 35 +-- .../screens/widgets/blocks/BlocksViewModel.kt | 43 +--- app/src/main/res/values-ar/strings.xml | 1 - app/src/main/res/values-b+es+419/strings.xml | 1 - app/src/main/res/values-ca/strings.xml | 1 - app/src/main/res/values-cs/strings.xml | 1 - app/src/main/res/values-de/strings.xml | 1 - app/src/main/res/values-el/strings.xml | 1 - app/src/main/res/values-es-rES/strings.xml | 1 - app/src/main/res/values-es/strings.xml | 1 - app/src/main/res/values-fr/strings.xml | 1 - app/src/main/res/values-it/strings.xml | 1 - app/src/main/res/values-nl/strings.xml | 1 - app/src/main/res/values-pl/strings.xml | 1 - app/src/main/res/values-pt-rBR/strings.xml | 1 - app/src/main/res/values-pt/strings.xml | 1 - app/src/main/res/values-ru/strings.xml | 1 - app/src/main/res/values/strings.xml | 4 +- .../models/widget/BlocksWidgetFieldTest.kt | 96 ++++++++ 34 files changed, 392 insertions(+), 648 deletions(-) create mode 100644 app/src/main/java/to/bitkit/models/widget/BlocksWidgetField.kt create mode 100644 app/src/test/java/to/bitkit/models/widget/BlocksWidgetFieldTest.kt diff --git a/app/src/androidTest/java/to/bitkit/ui/screens/widgets/blocks/BlockCardTest.kt b/app/src/androidTest/java/to/bitkit/ui/screens/widgets/blocks/BlockCardTest.kt index 876aef7a4..51193b042 100644 --- a/app/src/androidTest/java/to/bitkit/ui/screens/widgets/blocks/BlockCardTest.kt +++ b/app/src/androidTest/java/to/bitkit/ui/screens/widgets/blocks/BlockCardTest.kt @@ -5,6 +5,8 @@ import androidx.compose.ui.test.junit4.createComposeRule import androidx.compose.ui.test.onNodeWithTag import org.junit.Rule import org.junit.Test +import to.bitkit.models.widget.BlockModel +import to.bitkit.models.widget.BlocksPreferences import to.bitkit.test.annotations.ComposeUi import to.bitkit.ui.theme.AppThemeSurface @@ -20,27 +22,23 @@ class BlockCardTest { private val testTransactions = "2,175" private val testSize = "1,606Kb" private val testFees = "25 059 357" - private val testSource = "mempool.io" + + private val fullBlock = BlockModel( + height = testBlock, + time = testTime, + date = testDate, + transactionCount = testTransactions, + size = testSize, + fees = testFees, + ) @Test - fun testBlockCardWithAllElements() { + fun testBlockCardWithDefaultFields() { composeTestRule.setContent { AppThemeSurface { BlockCard( - showBlock = true, - showTime = true, - showDate = true, - showTransactions = true, - showSize = true, - showFees = true, - showSource = true, - block = testBlock, - time = testTime, - date = testDate, - transactions = testTransactions, - size = testSize, - fees = testFees, - source = testSource, + preferences = BlocksPreferences(), + block = fullBlock, ) } } @@ -49,45 +47,42 @@ class BlockCardTest { composeTestRule.onNodeWithTag("time_row", useUnmergedTree = true).assertExists() composeTestRule.onNodeWithTag("date_row", useUnmergedTree = true).assertExists() composeTestRule.onNodeWithTag("transactions_row", useUnmergedTree = true).assertExists() - composeTestRule.onNodeWithTag("size_row", useUnmergedTree = true).assertExists() - composeTestRule.onNodeWithTag("fees_row", useUnmergedTree = true).assertExists() - composeTestRule.onNodeWithTag("source_row", useUnmergedTree = true).assertExists() + composeTestRule.onNodeWithTag("size_row", useUnmergedTree = true).assertDoesNotExist() + composeTestRule.onNodeWithTag("fees_row", useUnmergedTree = true).assertDoesNotExist() composeTestRule.onNodeWithTag("block_text", useUnmergedTree = true).assertTextEquals(testBlock) composeTestRule.onNodeWithTag("time_text", useUnmergedTree = true).assertTextEquals(testTime) composeTestRule.onNodeWithTag("date_text", useUnmergedTree = true).assertTextEquals(testDate) composeTestRule.onNodeWithTag("transactions_text", useUnmergedTree = true).assertTextEquals(testTransactions) - composeTestRule.onNodeWithTag("size_text", useUnmergedTree = true).assertTextEquals(testSize) - composeTestRule.onNodeWithTag("fees_text", useUnmergedTree = true).assertTextEquals(testFees) - composeTestRule.onNodeWithTag("source_text", useUnmergedTree = true).assertTextEquals(testSource) } @Test - fun testBlockCardWithoutSource() { + fun testBlockCardWithSizeAndFees() { composeTestRule.setContent { AppThemeSurface { BlockCard( - showBlock = true, - showTime = true, - showDate = true, - showTransactions = true, - showSize = true, - showFees = true, - showSource = false, - block = testBlock, - time = testTime, - date = testDate, - transactions = testTransactions, - size = testSize, - fees = testFees, - source = testSource, + preferences = BlocksPreferences( + showBlock = true, + showTime = true, + showDate = false, + showTransactions = false, + showSize = true, + showFees = true, + ), + block = fullBlock, ) } } composeTestRule.onNodeWithTag("block_row", useUnmergedTree = true).assertExists() - composeTestRule.onNodeWithTag("source_row", useUnmergedTree = true).assertDoesNotExist() - composeTestRule.onNodeWithTag("source_text", useUnmergedTree = true).assertDoesNotExist() + composeTestRule.onNodeWithTag("time_row", useUnmergedTree = true).assertExists() + composeTestRule.onNodeWithTag("size_row", useUnmergedTree = true).assertExists() + composeTestRule.onNodeWithTag("fees_row", useUnmergedTree = true).assertExists() + composeTestRule.onNodeWithTag("date_row", useUnmergedTree = true).assertDoesNotExist() + composeTestRule.onNodeWithTag("transactions_row", useUnmergedTree = true).assertDoesNotExist() + + composeTestRule.onNodeWithTag("size_text", useUnmergedTree = true).assertTextEquals(testSize) + composeTestRule.onNodeWithTag("fees_text", useUnmergedTree = true).assertTextEquals(testFees) } @Test @@ -95,20 +90,15 @@ class BlockCardTest { composeTestRule.setContent { AppThemeSurface { BlockCard( - showBlock = true, - showTime = true, - showDate = true, - showTransactions = true, - showSize = true, - showFees = false, - showSource = true, - block = testBlock, - time = testTime, - date = testDate, - transactions = testTransactions, - size = testSize, - fees = testFees, - source = testSource, + preferences = BlocksPreferences( + showBlock = true, + showTime = true, + showDate = true, + showTransactions = false, + showSize = false, + showFees = false, + ), + block = fullBlock, ) } } @@ -123,20 +113,22 @@ class BlockCardTest { composeTestRule.setContent { AppThemeSurface { BlockCard( - showBlock = true, - showTime = false, - showDate = false, - showTransactions = false, - showSize = false, - showFees = false, - showSource = false, - block = testBlock, - time = "", - date = "", - transactions = "", - size = "", - fees = "", - source = "", + preferences = BlocksPreferences( + showBlock = true, + showTime = false, + showDate = false, + showTransactions = false, + showSize = false, + showFees = false, + ), + block = BlockModel( + height = testBlock, + time = "", + date = "", + transactionCount = "", + size = "", + fees = "", + ), ) } } @@ -147,7 +139,6 @@ class BlockCardTest { composeTestRule.onNodeWithTag("transactions_row", useUnmergedTree = true).assertDoesNotExist() composeTestRule.onNodeWithTag("size_row", useUnmergedTree = true).assertDoesNotExist() composeTestRule.onNodeWithTag("fees_row", useUnmergedTree = true).assertDoesNotExist() - composeTestRule.onNodeWithTag("source_row", useUnmergedTree = true).assertDoesNotExist() } @Test @@ -155,20 +146,15 @@ class BlockCardTest { composeTestRule.setContent { AppThemeSurface { BlockCard( - showBlock = true, - showTime = true, - showDate = true, - showTransactions = true, - showSize = true, - showFees = true, - showSource = true, - block = "", - time = "", - date = "", - transactions = "", - size = "", - fees = "", - source = "", + preferences = BlocksPreferences(), + block = BlockModel( + height = "", + time = "", + date = "", + transactionCount = "", + size = "", + fees = "", + ), ) } } @@ -179,28 +165,15 @@ class BlockCardTest { composeTestRule.onNodeWithTag("transactions_row", useUnmergedTree = true).assertDoesNotExist() composeTestRule.onNodeWithTag("size_row", useUnmergedTree = true).assertDoesNotExist() composeTestRule.onNodeWithTag("fees_row", useUnmergedTree = true).assertDoesNotExist() - composeTestRule.onNodeWithTag("source_row", useUnmergedTree = true).assertDoesNotExist() } @Test - fun testBlockCardSmallWithAllElements() { + fun testBlockCardSmallWithDefaultFields() { composeTestRule.setContent { AppThemeSurface { BlockCardSmall( - showBlock = true, - showTime = true, - showDate = true, - showTransactions = true, - showSize = true, - showFees = true, - showSource = true, - block = testBlock, - time = testTime, - date = testDate, - transactions = testTransactions, - size = testSize, - fees = testFees, - source = testSource, + preferences = BlocksPreferences(), + block = fullBlock, ) } } diff --git a/app/src/main/java/to/bitkit/appwidget/config/AppWidgetConfigScreen.kt b/app/src/main/java/to/bitkit/appwidget/config/AppWidgetConfigScreen.kt index 718f965f5..6ca7a5906 100644 --- a/app/src/main/java/to/bitkit/appwidget/config/AppWidgetConfigScreen.kt +++ b/app/src/main/java/to/bitkit/appwidget/config/AppWidgetConfigScreen.kt @@ -34,13 +34,7 @@ fun AppWidgetConfigScreen( AppWidgetType.BLOCKS -> BlocksConfigContent( state = state, - onToggleBlock = { viewModel.toggleBlockShowBlock() }, - onToggleTime = { viewModel.toggleBlockShowTime() }, - onToggleDate = { viewModel.toggleBlockShowDate() }, - onToggleTransactions = { viewModel.toggleBlockShowTransactions() }, - onToggleSize = { viewModel.toggleBlockShowSize() }, - onToggleFees = { viewModel.toggleBlockShowFees() }, - onToggleSource = { viewModel.toggleBlockShowSource() }, + onToggleField = { viewModel.toggleBlockField(it) }, onReset = { viewModel.resetPreferences() }, onSave = { viewModel.saveAndFinish(onConfirm) }, onCancel = onCancel, diff --git a/app/src/main/java/to/bitkit/appwidget/config/AppWidgetConfigViewModel.kt b/app/src/main/java/to/bitkit/appwidget/config/AppWidgetConfigViewModel.kt index 0e4b9b38d..56e563522 100644 --- a/app/src/main/java/to/bitkit/appwidget/config/AppWidgetConfigViewModel.kt +++ b/app/src/main/java/to/bitkit/appwidget/config/AppWidgetConfigViewModel.kt @@ -25,6 +25,8 @@ import to.bitkit.data.dto.price.GraphPeriod import to.bitkit.data.dto.price.TradingPair import to.bitkit.models.widget.ArticleModel import to.bitkit.models.widget.BlocksPreferences +import to.bitkit.models.widget.BlocksWidgetField +import to.bitkit.models.widget.toggleField import to.bitkit.models.widget.HeadlinePreferences import to.bitkit.models.widget.PricePreferences import to.bitkit.models.widget.WeatherDataOption @@ -118,49 +120,9 @@ class AppWidgetConfigViewModel @Inject constructor( } } - fun toggleBlockShowBlock() { + fun toggleBlockField(field: BlocksWidgetField) { _uiState.update { - it.copy(blocksPreferences = it.blocksPreferences.copy(showBlock = !it.blocksPreferences.showBlock)) - } - } - - fun toggleBlockShowTime() { - _uiState.update { - it.copy(blocksPreferences = it.blocksPreferences.copy(showTime = !it.blocksPreferences.showTime)) - } - } - - fun toggleBlockShowDate() { - _uiState.update { - it.copy(blocksPreferences = it.blocksPreferences.copy(showDate = !it.blocksPreferences.showDate)) - } - } - - fun toggleBlockShowTransactions() { - _uiState.update { - it.copy( - blocksPreferences = it.blocksPreferences.copy( - showTransactions = !it.blocksPreferences.showTransactions, - ), - ) - } - } - - fun toggleBlockShowSize() { - _uiState.update { - it.copy(blocksPreferences = it.blocksPreferences.copy(showSize = !it.blocksPreferences.showSize)) - } - } - - fun toggleBlockShowFees() { - _uiState.update { - it.copy(blocksPreferences = it.blocksPreferences.copy(showFees = !it.blocksPreferences.showFees)) - } - } - - fun toggleBlockShowSource() { - _uiState.update { - it.copy(blocksPreferences = it.blocksPreferences.copy(showSource = !it.blocksPreferences.showSource)) + it.copy(blocksPreferences = it.blocksPreferences.toggleField(field)) } } @@ -307,7 +269,6 @@ private fun HomeBlocksPreferences.toInApp() = BlocksPreferences( showTransactions = showTransactions, showSize = showSize, showFees = showFees, - showSource = showSource, ) private fun BlocksPreferences.toHome() = HomeBlocksPreferences( @@ -317,7 +278,6 @@ private fun BlocksPreferences.toHome() = HomeBlocksPreferences( showTransactions = showTransactions, showSize = showSize, showFees = showFees, - showSource = showSource, ) private fun HomeWeatherPreferences.toInApp() = WeatherPreferences(selectedOption = selectedOption) diff --git a/app/src/main/java/to/bitkit/appwidget/config/BlocksConfigContent.kt b/app/src/main/java/to/bitkit/appwidget/config/BlocksConfigContent.kt index 0467326e1..6a1c0a4d8 100644 --- a/app/src/main/java/to/bitkit/appwidget/config/BlocksConfigContent.kt +++ b/app/src/main/java/to/bitkit/appwidget/config/BlocksConfigContent.kt @@ -22,6 +22,8 @@ import androidx.compose.ui.unit.dp import to.bitkit.R import to.bitkit.models.widget.BlockModel import to.bitkit.models.widget.BlocksPreferences +import to.bitkit.models.widget.BlocksWidgetField +import to.bitkit.models.widget.enabledFields import to.bitkit.ui.components.BodyM import to.bitkit.ui.components.BodySSB import to.bitkit.ui.components.Caption13Up @@ -32,17 +34,10 @@ import to.bitkit.ui.scaffold.AppTopBar import to.bitkit.ui.scaffold.ScreenColumn import to.bitkit.ui.theme.Colors -@Suppress("LongParameterList") @Composable internal fun BlocksConfigContent( state: AppWidgetConfigUiState, - onToggleBlock: () -> Unit, - onToggleTime: () -> Unit, - onToggleDate: () -> Unit, - onToggleTransactions: () -> Unit, - onToggleSize: () -> Unit, - onToggleFees: () -> Unit, - onToggleSource: () -> Unit, + onToggleField: (BlocksWidgetField) -> Unit, onReset: () -> Unit, onSave: () -> Unit, onCancel: () -> Unit, @@ -55,7 +50,6 @@ internal fun BlocksConfigContent( date = "11/2/2022", transactionCount = "2,175", size = "1,606 Kb", - source = "mempool.io", fees = "25 059 357", ) } @@ -75,60 +69,20 @@ internal fun BlocksConfigContent( VerticalSpacer(16.dp) Caption13Up( - text = stringResource(R.string.widgets__widget__data), + text = stringResource(R.string.widgets__blocks__data_header), color = Colors.White64, modifier = Modifier.padding(bottom = 16.dp) ) - BlockToggleRow( - icon = R.drawable.ic_cube, - label = stringResource(R.string.widgets__blocks__field__block), - value = previewBlock.height, - isEnabled = prefs.showBlock, - onToggle = onToggleBlock, - ) - BlockToggleRow( - icon = R.drawable.ic_clock, - label = stringResource(R.string.widgets__blocks__field__time), - value = previewBlock.time, - isEnabled = prefs.showTime, - onToggle = onToggleTime, - ) - BlockToggleRow( - icon = R.drawable.ic_calendar, - label = stringResource(R.string.widgets__blocks__field__date), - value = previewBlock.date, - isEnabled = prefs.showDate, - onToggle = onToggleDate, - ) - BlockToggleRow( - icon = R.drawable.ic_transfer, - label = stringResource(R.string.widgets__blocks__field__transactions), - value = previewBlock.transactionCount, - isEnabled = prefs.showTransactions, - onToggle = onToggleTransactions, - ) - BlockToggleRow( - icon = R.drawable.ic_file_text, - label = stringResource(R.string.widgets__blocks__field__size), - value = previewBlock.size, - isEnabled = prefs.showSize, - onToggle = onToggleSize, - ) - BlockToggleRow( - icon = R.drawable.ic_coins, - label = stringResource(R.string.widgets__blocks__field__fees), - value = previewBlock.fees, - isEnabled = prefs.showFees, - onToggle = onToggleFees, - ) - BlockToggleRow( - icon = R.drawable.ic_globe, - label = stringResource(R.string.widgets__widget__source), - value = previewBlock.source, - isEnabled = prefs.showSource, - onToggle = onToggleSource, - ) + BlocksWidgetField.entries.forEach { field -> + BlockToggleRow( + icon = field.icon, + label = stringResource(field.labelRes), + value = field.value(previewBlock), + isEnabled = field.isEnabled(prefs), + onToggle = { onToggleField(field) }, + ) + } } Row( @@ -147,9 +101,7 @@ internal fun BlocksConfigContent( PrimaryButton( text = stringResource(R.string.common__save), isLoading = state.isSaving, - enabled = !state.isSaving && prefs.run { - showBlock || showTime || showDate || showTransactions || showSize || showFees || showSource - }, + enabled = !state.isSaving && prefs.enabledFields().isNotEmpty(), fullWidth = false, onClick = onSave, modifier = Modifier.weight(1f) diff --git a/app/src/main/java/to/bitkit/appwidget/model/AppWidgetPreferences.kt b/app/src/main/java/to/bitkit/appwidget/model/AppWidgetPreferences.kt index 1fffc4892..91a3f88b2 100644 --- a/app/src/main/java/to/bitkit/appwidget/model/AppWidgetPreferences.kt +++ b/app/src/main/java/to/bitkit/appwidget/model/AppWidgetPreferences.kt @@ -52,7 +52,6 @@ data class HomeBlocksPreferences( val showTransactions: Boolean = true, val showSize: Boolean = false, val showFees: Boolean = false, - val showSource: Boolean = false, ) @Stable diff --git a/app/src/main/java/to/bitkit/appwidget/ui/blocks/BlocksGlanceContent.kt b/app/src/main/java/to/bitkit/appwidget/ui/blocks/BlocksGlanceContent.kt index 7c9299e45..782096d7b 100644 --- a/app/src/main/java/to/bitkit/appwidget/ui/blocks/BlocksGlanceContent.kt +++ b/app/src/main/java/to/bitkit/appwidget/ui/blocks/BlocksGlanceContent.kt @@ -3,7 +3,6 @@ package to.bitkit.appwidget.ui.blocks import android.appwidget.AppWidgetManager import android.content.Context import android.content.Intent -import androidx.annotation.DrawableRes import androidx.compose.runtime.Composable import androidx.compose.ui.unit.dp import androidx.glance.ColorFilter @@ -25,7 +24,6 @@ import androidx.glance.layout.size import androidx.glance.unit.Dimension import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.toImmutableList -import to.bitkit.R import to.bitkit.appwidget.config.AppWidgetConfigActivity import to.bitkit.appwidget.model.AppWidgetEntry import to.bitkit.appwidget.model.AppWidgetType @@ -38,16 +36,22 @@ import to.bitkit.appwidget.ui.components.GlanceWidgetScaffold import to.bitkit.appwidget.ui.components.HorizontalSpacer import to.bitkit.appwidget.ui.components.VerticalSpacer import to.bitkit.appwidget.ui.theme.GlanceColors +import to.bitkit.R import to.bitkit.models.widget.BlockModel +import to.bitkit.models.widget.BlocksWidgetField +import to.bitkit.models.widget.MAX_BLOCKS_FIELDS import to.bitkit.ui.theme.Colors -private const val MAX_SMALL_ROWS = 4 - -private data class BlockRow( - @DrawableRes val icon: Int, - val label: String, - val value: String, -) +fun HomeBlocksPreferences.enabledFields(): List = BlocksWidgetField.entries.filter { + when (it) { + BlocksWidgetField.BLOCK -> showBlock + BlocksWidgetField.TIME -> showTime + BlocksWidgetField.DATE -> showDate + BlocksWidgetField.TRANSACTIONS -> showTransactions + BlocksWidgetField.SIZE -> showSize + BlocksWidgetField.FEES -> showFees + } +} @Suppress("RestrictedApi") @Composable @@ -68,120 +72,83 @@ fun BlocksGlanceContent( return@GlanceWidgetScaffold } - val rows = buildRows(context, entry.blocksPreferences, block) - if (rows.isEmpty()) { + val fields = entry.blocksPreferences.enabledFields().filter { it.value(block).isNotEmpty() } + if (fields.isEmpty()) { CaptionB(text = context.getString(R.string.appwidget__loading)) return@GlanceWidgetScaffold } if (LocalSize.current.width >= GlanceLayoutDimens.WIDE_LAYOUT_MIN_WIDTH) { - WideContent(rows = rows) + WideContent(fields = fields.toImmutableList(), block = block, context = context) } else { - CompactContent(rows = rows.take(MAX_SMALL_ROWS).toImmutableList()) + CompactContent(fields = fields.take(MAX_BLOCKS_FIELDS).toImmutableList(), block = block) } } } @Suppress("RestrictedApi") @Composable -private fun WideContent(rows: ImmutableList) { +private fun WideContent(fields: ImmutableList, block: BlockModel, context: Context) { Column(modifier = GlanceModifier.fillMaxSize()) { - rows.forEach { row -> - WideRow(row = row, modifier = GlanceModifier.padding(vertical = 6.dp)) + fields.forEach { field -> + WideRow( + label = context.getString(field.labelRes), + value = field.value(block), + icon = field.icon, + modifier = GlanceModifier.padding(vertical = 6.dp) + ) } } } @Suppress("RestrictedApi") @Composable -private fun WideRow(row: BlockRow, modifier: GlanceModifier = GlanceModifier) { +private fun WideRow(label: String, value: String, icon: Int, modifier: GlanceModifier = GlanceModifier) { Row( verticalAlignment = Alignment.CenterVertically, modifier = modifier.fillMaxWidth() ) { Image( - provider = ImageProvider(row.icon), + provider = ImageProvider(icon), contentDescription = null, colorFilter = ColorFilter.tint(ColorProvider(day = Colors.Brand, night = Colors.Brand)), modifier = GlanceModifier.size(20.dp) ) HorizontalSpacer(8.dp) BodyMSB( - text = row.label, + text = label, color = GlanceColors.textSecondary, modifier = GlanceModifier.then(WidthModifier(Dimension.Expand)) ) - BodyMSB(text = row.value) + BodyMSB(text = value) } } @Suppress("RestrictedApi") @Composable -private fun CompactContent(rows: ImmutableList) { +private fun CompactContent(fields: ImmutableList, block: BlockModel) { Column(modifier = GlanceModifier.fillMaxWidth()) { - rows.forEachIndexed { index, row -> + fields.forEachIndexed { index, field -> if (index > 0) VerticalSpacer(16.dp) - CompactRow(row = row) + CompactRow(value = field.value(block), icon = field.icon) } } } @Suppress("RestrictedApi") @Composable -private fun CompactRow(row: BlockRow) { +private fun CompactRow(value: String, icon: Int) { Row( verticalAlignment = Alignment.CenterVertically, modifier = GlanceModifier.fillMaxWidth() ) { Image( - provider = ImageProvider(row.icon), + provider = ImageProvider(icon), contentDescription = null, colorFilter = ColorFilter.tint(ColorProvider(day = Colors.Brand, night = Colors.Brand)), modifier = GlanceModifier.size(20.dp) ) HorizontalSpacer(8.dp) - BodySSB(text = row.value) + BodySSB(text = value) } } - -private fun buildRows( - context: Context, - preferences: HomeBlocksPreferences, - block: BlockModel, -): ImmutableList = listOfNotNull( - BlockRow( - icon = R.drawable.ic_cube, - label = context.getString(R.string.widgets__blocks__field__block), - value = block.height, - ).takeIf { preferences.showBlock && block.height.isNotEmpty() }, - BlockRow( - icon = R.drawable.ic_clock, - label = context.getString(R.string.widgets__blocks__field__time), - value = block.time, - ).takeIf { preferences.showTime && block.time.isNotEmpty() }, - BlockRow( - icon = R.drawable.ic_calendar, - label = context.getString(R.string.widgets__blocks__field__date), - value = block.date, - ).takeIf { preferences.showDate && block.date.isNotEmpty() }, - BlockRow( - icon = R.drawable.ic_transfer, - label = context.getString(R.string.widgets__blocks__field__transactions), - value = block.transactionCount, - ).takeIf { preferences.showTransactions && block.transactionCount.isNotEmpty() }, - BlockRow( - icon = R.drawable.ic_file_text, - label = context.getString(R.string.widgets__blocks__field__size), - value = block.size, - ).takeIf { preferences.showSize && block.size.isNotEmpty() }, - BlockRow( - icon = R.drawable.ic_coins, - label = context.getString(R.string.widgets__blocks__field__fees), - value = block.fees, - ).takeIf { preferences.showFees && block.fees.isNotEmpty() }, - BlockRow( - icon = R.drawable.ic_globe, - label = context.getString(R.string.widgets__widget__source), - value = block.source, - ).takeIf { preferences.showSource && block.source.isNotEmpty() }, -).toImmutableList() diff --git a/app/src/main/java/to/bitkit/data/dto/BlockDTO.kt b/app/src/main/java/to/bitkit/data/dto/BlockDTO.kt index b273a5139..7fd348d37 100644 --- a/app/src/main/java/to/bitkit/data/dto/BlockDTO.kt +++ b/app/src/main/java/to/bitkit/data/dto/BlockDTO.kt @@ -12,6 +12,5 @@ data class BlockDTO( val weight: String, val difficulty: String, val merkleRoot: String, - val source: String, val fees: String = "", ) diff --git a/app/src/main/java/to/bitkit/data/widgets/BlocksService.kt b/app/src/main/java/to/bitkit/data/widgets/BlocksService.kt index 666c29da2..9492aaef0 100644 --- a/app/src/main/java/to/bitkit/data/widgets/BlocksService.kt +++ b/app/src/main/java/to/bitkit/data/widgets/BlocksService.kt @@ -89,7 +89,6 @@ class BlocksService @Inject constructor( weight = formattedWeight, difficulty = difficulty, merkleRoot = blockInfo.merkleRoot, - source = Env.mempoolBaseUrl.replace("https://", "").replaceAfter("/", "").replace("/", ""), fees = formattedFees, ) } diff --git a/app/src/main/java/to/bitkit/models/widget/BlockModel.kt b/app/src/main/java/to/bitkit/models/widget/BlockModel.kt index 7741ec1da..3580ba163 100644 --- a/app/src/main/java/to/bitkit/models/widget/BlockModel.kt +++ b/app/src/main/java/to/bitkit/models/widget/BlockModel.kt @@ -14,7 +14,6 @@ data class BlockModel( val date: String, val transactionCount: String, val size: String, - val source: String, val fees: String, ) @@ -24,6 +23,5 @@ fun BlockDTO.toBlockModel() = BlockModel( date = this.timestamp.toDateUTC(), transactionCount = this.transactionCount, size = this.size, - source = this.source, fees = this.fees, ) diff --git a/app/src/main/java/to/bitkit/models/widget/BlocksPreferences.kt b/app/src/main/java/to/bitkit/models/widget/BlocksPreferences.kt index 6d9a911de..b1264d8df 100644 --- a/app/src/main/java/to/bitkit/models/widget/BlocksPreferences.kt +++ b/app/src/main/java/to/bitkit/models/widget/BlocksPreferences.kt @@ -12,5 +12,4 @@ data class BlocksPreferences( val showTransactions: Boolean = true, val showSize: Boolean = false, val showFees: Boolean = false, - val showSource: Boolean = false, ) diff --git a/app/src/main/java/to/bitkit/models/widget/BlocksWidgetField.kt b/app/src/main/java/to/bitkit/models/widget/BlocksWidgetField.kt new file mode 100644 index 000000000..63890ece9 --- /dev/null +++ b/app/src/main/java/to/bitkit/models/widget/BlocksWidgetField.kt @@ -0,0 +1,75 @@ +package to.bitkit.models.widget + +import androidx.annotation.DrawableRes +import androidx.annotation.StringRes +import to.bitkit.R + +const val MAX_BLOCKS_FIELDS = 4 + +enum class BlocksWidgetField( + @DrawableRes val icon: Int, + @StringRes val labelRes: Int, + val testTag: String, +) { + BLOCK(R.drawable.ic_cube, R.string.widgets__blocks__field__block, "block"), + TIME(R.drawable.ic_clock, R.string.widgets__blocks__field__time, "time"), + DATE(R.drawable.ic_calendar, R.string.widgets__blocks__field__date, "date"), + TRANSACTIONS(R.drawable.ic_transfer, R.string.widgets__blocks__field__transactions, "transactions"), + SIZE(R.drawable.ic_file_text, R.string.widgets__blocks__field__size, "size"), + FEES(R.drawable.ic_coins, R.string.widgets__blocks__field__fees, "fees"); + + fun value(block: BlockModel): String = when (this) { + BLOCK -> block.height + TIME -> block.time + DATE -> block.date + TRANSACTIONS -> block.transactionCount + SIZE -> block.size + FEES -> block.fees + } + + fun isEnabled(prefs: BlocksPreferences): Boolean = when (this) { + BLOCK -> prefs.showBlock + TIME -> prefs.showTime + DATE -> prefs.showDate + TRANSACTIONS -> prefs.showTransactions + SIZE -> prefs.showSize + FEES -> prefs.showFees + } +} + +fun BlocksPreferences.enabledFields(): List = + BlocksWidgetField.entries.filter { it.isEnabled(this) } + +/** + * Toggles [field], enforcing the [MAX_BLOCKS_FIELDS] cap: an already-enabled field can always be + * turned off, but a disabled field cannot be turned on once the limit is reached (no-op). + */ +fun BlocksPreferences.toggleField(field: BlocksWidgetField): BlocksPreferences { + if (!field.isEnabled(this) && enabledFields().size >= MAX_BLOCKS_FIELDS) return this + return when (field) { + BlocksWidgetField.BLOCK -> copy(showBlock = !showBlock) + BlocksWidgetField.TIME -> copy(showTime = !showTime) + BlocksWidgetField.DATE -> copy(showDate = !showDate) + BlocksWidgetField.TRANSACTIONS -> copy(showTransactions = !showTransactions) + BlocksWidgetField.SIZE -> copy(showSize = !showSize) + BlocksWidgetField.FEES -> copy(showFees = !showFees) + } +} + +/** + * Caps enabled fields at [MAX_BLOCKS_FIELDS], keeping the first ones in declared order. Used when + * importing legacy preferences (e.g. RN migration) that predate the limit and may exceed it; live + * editing is already capped by [toggleField]. + */ +fun BlocksPreferences.limitedToMax(): BlocksPreferences { + var count = 0 + fun keep(enabled: Boolean): Boolean = (enabled && count < MAX_BLOCKS_FIELDS).also { if (it) count++ } + return BlocksPreferences( + showBlock = keep(showBlock), + showTime = keep(showTime), + showDate = keep(showDate), + showTransactions = keep(showTransactions), + showSize = keep(showSize), + showFees = keep(showFees), + ) +} diff --git a/app/src/main/java/to/bitkit/services/MigrationService.kt b/app/src/main/java/to/bitkit/services/MigrationService.kt index 059389f67..73fdef8e1 100644 --- a/app/src/main/java/to/bitkit/services/MigrationService.kt +++ b/app/src/main/java/to/bitkit/services/MigrationService.kt @@ -58,6 +58,7 @@ import to.bitkit.models.WidgetType import to.bitkit.models.WidgetWithPosition import to.bitkit.models.toSettingsString import to.bitkit.models.widget.BlocksPreferences +import to.bitkit.models.widget.limitedToMax import to.bitkit.models.widget.HeadlinePreferences import to.bitkit.models.widget.PricePreferences import to.bitkit.models.widget.WeatherDataOption @@ -1190,7 +1191,6 @@ class MigrationService @Inject constructor( val showTransactions = blocksJson["transactionCount"]?.jsonPrimitive?.content ?.toBooleanStrictOrNull() ?: false val showSize = blocksJson["size"]?.jsonPrimitive?.content?.toBooleanStrictOrNull() ?: false - val showSource = blocksJson["showSource"]?.jsonPrimitive?.content?.toBooleanStrictOrNull() ?: false widgetsStore.updateBlocksPreferences( BlocksPreferences( @@ -1199,8 +1199,7 @@ class MigrationService @Inject constructor( showDate = showDate, showTransactions = showTransactions, showSize = showSize, - showSource = showSource - ) + ).limitedToMax() ) }.onFailure { Logger.error("Failed to migrate blocks preferences: $it", it, context = TAG) @@ -2102,7 +2101,6 @@ class MigrationService @Inject constructor( put("date", getBool(prefs, "date", "showDate", defaultValue = true)) put("transactionCount", getBool(prefs, "transactionCount", "showTransactions", defaultValue = false)) put("size", getBool(prefs, "size", "showSize", defaultValue = false)) - put("showSource", getBool(prefs, "showSource", defaultValue = false)) } result["blocks"] = blocksOptions.toString().encodeToByteArray() } diff --git a/app/src/main/java/to/bitkit/ui/screens/wallets/HomeScreen.kt b/app/src/main/java/to/bitkit/ui/screens/wallets/HomeScreen.kt index 59d819201..f437ae078 100644 --- a/app/src/main/java/to/bitkit/ui/screens/wallets/HomeScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/wallets/HomeScreen.kt @@ -933,22 +933,10 @@ private fun Widgets( widgets.forEach { widgetsWithPosition -> when (widgetsWithPosition.type) { WidgetType.BLOCK -> { - homeUiState.currentBlock?.run { + homeUiState.currentBlock?.let { block -> BlockCard( - showBlock = homeUiState.blocksPreferences.showBlock, - showTime = homeUiState.blocksPreferences.showTime, - showDate = homeUiState.blocksPreferences.showDate, - showTransactions = homeUiState.blocksPreferences.showTransactions, - showSize = homeUiState.blocksPreferences.showSize, - showFees = homeUiState.blocksPreferences.showFees, - showSource = homeUiState.blocksPreferences.showSource, - time = time, - date = date, - transactions = transactionCount, - size = size, - fees = fees, - source = source, - block = height, + preferences = homeUiState.blocksPreferences, + block = block, modifier = Modifier .fillMaxWidth() .testTag("BlocksWidget") @@ -1175,7 +1163,6 @@ private val previewBlock = BlockModel( date = "01/2/2022", transactionCount = "2,175", size = "1,606kB", - source = "mempool.io", fees = "25 059 357", ) diff --git a/app/src/main/java/to/bitkit/ui/screens/widgets/blocks/BlockCard.kt b/app/src/main/java/to/bitkit/ui/screens/widgets/blocks/BlockCard.kt index aa94c62b4..19230fb96 100644 --- a/app/src/main/java/to/bitkit/ui/screens/widgets/blocks/BlockCard.kt +++ b/app/src/main/java/to/bitkit/ui/screens/widgets/blocks/BlockCard.kt @@ -21,7 +21,10 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import to.bitkit.R +import to.bitkit.models.widget.BlockModel +import to.bitkit.models.widget.BlocksPreferences +import to.bitkit.models.widget.MAX_BLOCKS_FIELDS +import to.bitkit.models.widget.enabledFields import to.bitkit.ui.components.BodyM import to.bitkit.ui.components.BodyMSB import to.bitkit.ui.components.BodySSB @@ -29,25 +32,14 @@ import to.bitkit.ui.screens.widgets.components.WidgetCardDimens import to.bitkit.ui.theme.AppThemeSurface import to.bitkit.ui.theme.Colors -@Suppress("CyclomaticComplexMethod") @Composable fun BlockCard( modifier: Modifier = Modifier, - showBlock: Boolean, - showTime: Boolean, - showDate: Boolean, - showTransactions: Boolean, - showSize: Boolean, - showFees: Boolean, - showSource: Boolean, - block: String, - time: String, - date: String, - transactions: String, - size: String, - fees: String, - source: String, + preferences: BlocksPreferences, + block: BlockModel, ) { + val fields = preferences.enabledFields().filter { it.value(block).isNotEmpty() } + Box( modifier = modifier .clip(shape = MaterialTheme.shapes.medium) @@ -59,95 +51,27 @@ fun BlockCard( .fillMaxWidth() .padding(16.dp) ) { - if (showBlock && block.isNotEmpty()) { - WidgetDataRow( - icon = R.drawable.ic_cube, - label = stringResource(R.string.widgets__blocks__field__block), - value = block, - testTagPrefix = "block", - ) - } - if (showTime && time.isNotEmpty()) { + fields.forEach { field -> WidgetDataRow( - icon = R.drawable.ic_clock, - label = stringResource(R.string.widgets__blocks__field__time), - value = time, - testTagPrefix = "time", - ) - } - if (showDate && date.isNotEmpty()) { - WidgetDataRow( - icon = R.drawable.ic_calendar, - label = stringResource(R.string.widgets__blocks__field__date), - value = date, - testTagPrefix = "date", - ) - } - if (showTransactions && transactions.isNotEmpty()) { - WidgetDataRow( - icon = R.drawable.ic_transfer, - label = stringResource(R.string.widgets__blocks__field__transactions), - value = transactions, - testTagPrefix = "transactions", - ) - } - if (showSize && size.isNotEmpty()) { - WidgetDataRow( - icon = R.drawable.ic_file_text, - label = stringResource(R.string.widgets__blocks__field__size), - value = size, - testTagPrefix = "size", - ) - } - if (showFees && fees.isNotEmpty()) { - WidgetDataRow( - icon = R.drawable.ic_coins, - label = stringResource(R.string.widgets__blocks__field__fees), - value = fees, - testTagPrefix = "fees", - ) - } - if (showSource && source.isNotEmpty()) { - WidgetDataRow( - icon = R.drawable.ic_globe, - label = stringResource(R.string.widgets__widget__source), - value = source, - testTagPrefix = "source", + icon = field.icon, + label = stringResource(field.labelRes), + value = field.value(block), + testTagPrefix = field.testTag, ) } } } } -@Suppress("CyclomaticComplexMethod") @Composable fun BlockCardSmall( modifier: Modifier = Modifier, - showBlock: Boolean, - showTime: Boolean, - showDate: Boolean, - showTransactions: Boolean, - showSize: Boolean, - showFees: Boolean, - showSource: Boolean, - block: String, - time: String, - date: String, - transactions: String, - size: String, - fees: String, - source: String, + preferences: BlocksPreferences, + block: BlockModel, ) { - val rows = listOfNotNull( - SmallRowData(R.drawable.ic_cube, block, "block").takeIf { showBlock && block.isNotEmpty() }, - SmallRowData(R.drawable.ic_clock, time, "time").takeIf { showTime && time.isNotEmpty() }, - SmallRowData(R.drawable.ic_calendar, date, "date").takeIf { showDate && date.isNotEmpty() }, - SmallRowData(R.drawable.ic_transfer, transactions, "transactions") - .takeIf { showTransactions && transactions.isNotEmpty() }, - SmallRowData(R.drawable.ic_file_text, size, "size").takeIf { showSize && size.isNotEmpty() }, - SmallRowData(R.drawable.ic_coins, fees, "fees").takeIf { showFees && fees.isNotEmpty() }, - SmallRowData(R.drawable.ic_globe, source, "source").takeIf { showSource && source.isNotEmpty() }, - ).take(MAX_SMALL_ROWS) + val fields = preferences.enabledFields() + .filter { it.value(block).isNotEmpty() } + .take(MAX_BLOCKS_FIELDS) Box( modifier = modifier @@ -161,25 +85,17 @@ fun BlockCardSmall( .fillMaxSize() .padding(16.dp) ) { - rows.forEach { row -> + fields.forEach { field -> SmallDataRow( - icon = row.icon, - value = row.value, - testTagPrefix = row.testTagPrefix, + icon = field.icon, + value = field.value(block), + testTagPrefix = field.testTag, ) } } } } -private const val MAX_SMALL_ROWS = 4 - -private data class SmallRowData( - @DrawableRes val icon: Int, - val value: String, - val testTagPrefix: String, -) - @Composable private fun WidgetDataRow( modifier: Modifier = Modifier, @@ -259,20 +175,20 @@ private fun PreviewLargeAll() { .padding(16.dp) ) { BlockCard( - showBlock = true, - showTime = true, - showDate = true, - showTransactions = true, - showSize = true, - showFees = true, - showSource = true, - block = "761,405", - time = "01:31:42 UTC", - date = "11/2/2022", - transactions = "2,175", - size = "1,606Kb", - fees = "25 059 357", - source = "mempool.io", + preferences = BlocksPreferences( + showBlock = true, + showTime = true, + showDate = true, + showTransactions = true, + ), + block = BlockModel( + height = "761,405", + time = "01:31:42 UTC", + date = "11/2/2022", + transactionCount = "2,175", + size = "1,606Kb", + fees = "25 059 357", + ), modifier = Modifier.fillMaxWidth() ) } @@ -281,7 +197,7 @@ private fun PreviewLargeAll() { @Preview(showBackground = true) @Composable -private fun PreviewLargeDefault() { +private fun PreviewLargeSizeAndFees() { AppThemeSurface { Column( verticalArrangement = Arrangement.spacedBy(8.dp), @@ -290,20 +206,22 @@ private fun PreviewLargeDefault() { .padding(16.dp) ) { BlockCard( - showBlock = true, - showTime = true, - showDate = true, - showTransactions = true, - showSize = false, - showFees = false, - showSource = false, - block = "761,405", - time = "01:31:42 UTC", - date = "11/2/2022", - transactions = "2,175", - size = "", - fees = "", - source = "", + preferences = BlocksPreferences( + showBlock = true, + showTime = true, + showDate = false, + showTransactions = false, + showSize = true, + showFees = true, + ), + block = BlockModel( + height = "761,405", + time = "01:31:42 UTC", + date = "11/2/2022", + transactionCount = "2,175", + size = "1,606Kb", + fees = "25 059 357", + ), modifier = Modifier.fillMaxWidth() ) } @@ -321,20 +239,15 @@ private fun PreviewSmall() { .padding(16.dp) ) { BlockCardSmall( - showBlock = true, - showTime = true, - showDate = true, - showTransactions = true, - showSize = false, - showFees = false, - showSource = false, - block = "761,405", - time = "01:31:42 UTC", - date = "11/2/2022", - transactions = "2,175", - size = "", - fees = "", - source = "", + preferences = BlocksPreferences(), + block = BlockModel( + height = "761,405", + time = "01:31:42 UTC", + date = "11/2/2022", + transactionCount = "2,175", + size = "", + fees = "", + ), ) } } diff --git a/app/src/main/java/to/bitkit/ui/screens/widgets/blocks/BlocksEditScreen.kt b/app/src/main/java/to/bitkit/ui/screens/widgets/blocks/BlocksEditScreen.kt index f852a0f4a..87956c18c 100644 --- a/app/src/main/java/to/bitkit/ui/screens/widgets/blocks/BlocksEditScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/widgets/blocks/BlocksEditScreen.kt @@ -23,6 +23,8 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import to.bitkit.R import to.bitkit.models.widget.BlockModel import to.bitkit.models.widget.BlocksPreferences +import to.bitkit.models.widget.BlocksWidgetField +import to.bitkit.models.widget.enabledFields import to.bitkit.ui.components.BodySSB import to.bitkit.ui.components.Caption13Up import to.bitkit.ui.components.FillHeight @@ -50,7 +52,6 @@ fun BlocksEditScreen( date = "", transactionCount = "", size = "", - source = "", fees = "", ) @@ -58,13 +59,7 @@ fun BlocksEditScreen( onBack = onBack, blocksPreferences = customPreference, block = currentBlock ?: blockPlaceholder, - onClickShowBlock = { blocksViewModel.toggleShowBlock() }, - onClickShowTime = { blocksViewModel.toggleShowTime() }, - onClickShowDate = { blocksViewModel.toggleShowDate() }, - onClickShowTransactions = { blocksViewModel.toggleShowTransactions() }, - onClickShowSize = { blocksViewModel.toggleShowSize() }, - onClickShowFees = { blocksViewModel.toggleShowFees() }, - onClickShowSource = { blocksViewModel.toggleShowSource() }, + onToggleField = { blocksViewModel.toggleField(it) }, onClickReset = { blocksViewModel.resetCustomPreferences() }, onClickPreview = navigatePreview, modifier = modifier @@ -74,13 +69,7 @@ fun BlocksEditScreen( @Composable private fun Content( onBack: () -> Unit, - onClickShowBlock: () -> Unit, - onClickShowTime: () -> Unit, - onClickShowDate: () -> Unit, - onClickShowTransactions: () -> Unit, - onClickShowSize: () -> Unit, - onClickShowFees: () -> Unit, - onClickShowSource: () -> Unit, + onToggleField: (BlocksWidgetField) -> Unit, onClickReset: () -> Unit, onClickPreview: () -> Unit, blocksPreferences: BlocksPreferences, @@ -103,75 +92,23 @@ private fun Content( VerticalSpacer(16.dp) Caption13Up( - text = stringResource(R.string.widgets__widget__data), + text = stringResource(R.string.widgets__blocks__data_header), color = Colors.White64, modifier = Modifier .padding(bottom = 16.dp) .testTag("data_section_header") ) - BlockEditOptionRow( - leadingIcon = R.drawable.ic_cube, - label = stringResource(R.string.widgets__blocks__field__block), - value = block.height, - isEnabled = blocksPreferences.showBlock, - onClick = onClickShowBlock, - testTagPrefix = "block", - ) - - BlockEditOptionRow( - leadingIcon = R.drawable.ic_clock, - label = stringResource(R.string.widgets__blocks__field__time), - value = block.time, - isEnabled = blocksPreferences.showTime, - onClick = onClickShowTime, - testTagPrefix = "time", - ) - - BlockEditOptionRow( - leadingIcon = R.drawable.ic_calendar, - label = stringResource(R.string.widgets__blocks__field__date), - value = block.date, - isEnabled = blocksPreferences.showDate, - onClick = onClickShowDate, - testTagPrefix = "date", - ) - - BlockEditOptionRow( - leadingIcon = R.drawable.ic_transfer, - label = stringResource(R.string.widgets__blocks__field__transactions), - value = block.transactionCount, - isEnabled = blocksPreferences.showTransactions, - onClick = onClickShowTransactions, - testTagPrefix = "transactions", - ) - - BlockEditOptionRow( - leadingIcon = R.drawable.ic_file_text, - label = stringResource(R.string.widgets__blocks__field__size), - value = block.size, - isEnabled = blocksPreferences.showSize, - onClick = onClickShowSize, - testTagPrefix = "size", - ) - - BlockEditOptionRow( - leadingIcon = R.drawable.ic_coins, - label = stringResource(R.string.widgets__blocks__field__fees), - value = block.fees, - isEnabled = blocksPreferences.showFees, - onClick = onClickShowFees, - testTagPrefix = "fees", - ) - - BlockEditOptionRow( - leadingIcon = R.drawable.ic_globe, - label = stringResource(R.string.widgets__widget__source), - value = block.source, - isEnabled = blocksPreferences.showSource, - onClick = onClickShowSource, - testTagPrefix = "source", - ) + BlocksWidgetField.entries.forEach { field -> + BlockEditOptionRow( + leadingIcon = field.icon, + label = stringResource(field.labelRes), + value = field.value(block), + isEnabled = field.isEnabled(blocksPreferences), + onClick = { onToggleField(field) }, + testTagPrefix = field.testTag, + ) + } FillHeight() @@ -194,9 +131,7 @@ private fun Content( PrimaryButton( text = stringResource(R.string.common__preview), - enabled = blocksPreferences.run { - showBlock || showTime || showDate || showTransactions || showSize || showFees || showSource - }, + enabled = blocksPreferences.enabledFields().isNotEmpty(), fullWidth = false, onClick = onClickPreview, modifier = Modifier @@ -277,13 +212,7 @@ private fun Preview() { AppThemeSurface { Content( onBack = {}, - onClickShowBlock = {}, - onClickShowTime = {}, - onClickShowDate = {}, - onClickShowTransactions = {}, - onClickShowSize = {}, - onClickShowFees = {}, - onClickShowSource = {}, + onToggleField = {}, onClickReset = {}, onClickPreview = {}, blocksPreferences = BlocksPreferences(), @@ -293,7 +222,6 @@ private fun Preview() { date = "01/2/2022", transactionCount = "2,175", size = "1,606kB", - source = "mempool.io", fees = "25 059 357", ), ) @@ -306,13 +234,7 @@ private fun PreviewWithSomeOptionsEnabled() { AppThemeSurface { Content( onBack = {}, - onClickShowBlock = {}, - onClickShowTime = {}, - onClickShowDate = {}, - onClickShowTransactions = {}, - onClickShowSize = {}, - onClickShowFees = {}, - onClickShowSource = {}, + onToggleField = {}, onClickReset = {}, onClickPreview = {}, blocksPreferences = BlocksPreferences( @@ -322,7 +244,6 @@ private fun PreviewWithSomeOptionsEnabled() { showTransactions = true, showSize = false, showFees = false, - showSource = true, ), block = BlockModel( height = "", @@ -330,7 +251,6 @@ private fun PreviewWithSomeOptionsEnabled() { date = "", transactionCount = "", size = "", - source = "", fees = "", ), ) @@ -343,13 +263,7 @@ private fun PreviewWithAllDisabled() { AppThemeSurface { Content( onBack = {}, - onClickShowBlock = {}, - onClickShowTime = {}, - onClickShowDate = {}, - onClickShowTransactions = {}, - onClickShowSize = {}, - onClickShowFees = {}, - onClickShowSource = {}, + onToggleField = {}, onClickReset = {}, onClickPreview = {}, blocksPreferences = BlocksPreferences( @@ -359,7 +273,6 @@ private fun PreviewWithAllDisabled() { showTransactions = false, showSize = false, showFees = false, - showSource = false, ), block = BlockModel( height = "", @@ -367,7 +280,6 @@ private fun PreviewWithAllDisabled() { date = "", transactionCount = "", size = "", - source = "", fees = "", ), ) diff --git a/app/src/main/java/to/bitkit/ui/screens/widgets/blocks/BlocksPreviewScreen.kt b/app/src/main/java/to/bitkit/ui/screens/widgets/blocks/BlocksPreviewScreen.kt index bf451492d..b79c06068 100644 --- a/app/src/main/java/to/bitkit/ui/screens/widgets/blocks/BlocksPreviewScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/widgets/blocks/BlocksPreviewScreen.kt @@ -119,39 +119,15 @@ private fun Content( WidgetSizeCarousel( smallContent = { BlockCardSmall( - showBlock = blocksPreferences.showBlock, - showTime = blocksPreferences.showTime, - showDate = blocksPreferences.showDate, - showTransactions = blocksPreferences.showTransactions, - showSize = blocksPreferences.showSize, - showFees = blocksPreferences.showFees, - showSource = blocksPreferences.showSource, - block = it.height, - time = it.time, - date = it.date, - transactions = it.transactionCount, - size = it.size, - fees = it.fees, - source = it.source, + preferences = blocksPreferences, + block = it, modifier = Modifier.testTag("block_card_small") ) }, wideContent = { BlockCard( - showBlock = blocksPreferences.showBlock, - showTime = blocksPreferences.showTime, - showDate = blocksPreferences.showDate, - showTransactions = blocksPreferences.showTransactions, - showSize = blocksPreferences.showSize, - showFees = blocksPreferences.showFees, - showSource = blocksPreferences.showSource, - block = it.height, - time = it.time, - date = it.date, - transactions = it.transactionCount, - size = it.size, - fees = it.fees, - source = it.source, + preferences = blocksPreferences, + block = it, modifier = Modifier .fillMaxWidth() .testTag("block_card_wide") @@ -215,7 +191,6 @@ private fun Preview() { date = "2023-01-01", transactionCount = "2,175", size = "1,606kB", - source = "mempool.space", fees = "25 059 357", ), isBlocksWidgetEnabled = false, @@ -238,7 +213,6 @@ private fun Preview2() { showDate = false, showTransactions = true, showSize = false, - showSource = true ), block = BlockModel( height = "123456", @@ -246,7 +220,6 @@ private fun Preview2() { date = "2023-01-01", transactionCount = "2,175", size = "1,606kB", - source = "mempool.space", fees = "25 059 357", ), isBlocksWidgetEnabled = true, diff --git a/app/src/main/java/to/bitkit/ui/screens/widgets/blocks/BlocksViewModel.kt b/app/src/main/java/to/bitkit/ui/screens/widgets/blocks/BlocksViewModel.kt index 70e7415f3..c798de02e 100644 --- a/app/src/main/java/to/bitkit/ui/screens/widgets/blocks/BlocksViewModel.kt +++ b/app/src/main/java/to/bitkit/ui/screens/widgets/blocks/BlocksViewModel.kt @@ -14,12 +14,13 @@ import kotlinx.coroutines.launch import to.bitkit.models.WidgetType import to.bitkit.models.widget.BlockModel import to.bitkit.models.widget.BlocksPreferences +import to.bitkit.models.widget.BlocksWidgetField import to.bitkit.models.widget.toBlockModel +import to.bitkit.models.widget.toggleField import to.bitkit.repositories.WidgetsRepo import javax.inject.Inject @HiltViewModel -@Suppress("TooManyFunctions") class BlocksViewModel @Inject constructor( private val widgetsRepo: WidgetsRepo ) : ViewModel() { @@ -70,45 +71,9 @@ class BlocksViewModel @Inject constructor( // MARK: - Public Methods - fun toggleShowBlock() { + fun toggleField(field: BlocksWidgetField) { _customPreferences.update { preferences -> - preferences.copy(showBlock = !preferences.showBlock) - } - } - - fun toggleShowTime() { - _customPreferences.update { preferences -> - preferences.copy(showTime = !preferences.showTime) - } - } - - fun toggleShowDate() { - _customPreferences.update { preferences -> - preferences.copy(showDate = !preferences.showDate) - } - } - - fun toggleShowTransactions() { - _customPreferences.update { preferences -> - preferences.copy(showTransactions = !preferences.showTransactions) - } - } - - fun toggleShowSize() { - _customPreferences.update { preferences -> - preferences.copy(showSize = !preferences.showSize) - } - } - - fun toggleShowFees() { - _customPreferences.update { preferences -> - preferences.copy(showFees = !preferences.showFees) - } - } - - fun toggleShowSource() { - _customPreferences.update { preferences -> - preferences.copy(showSource = !preferences.showSource) + preferences.toggleField(field) } } diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 32611ae2f..244bdcf5f 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -1009,6 +1009,5 @@ افتراضي يرجى اختيار الحقول التي تريد عرضها في أداة {name}. الأداة - المصدر الأدوات diff --git a/app/src/main/res/values-b+es+419/strings.xml b/app/src/main/res/values-b+es+419/strings.xml index b4e324581..f01ffc5ae 100644 --- a/app/src/main/res/values-b+es+419/strings.xml +++ b/app/src/main/res/values-b+es+419/strings.xml @@ -1009,6 +1009,5 @@ Por defecto Seleccione los campos que desea mostrar en el widget {name}. Widget - Fuente Widgets diff --git a/app/src/main/res/values-ca/strings.xml b/app/src/main/res/values-ca/strings.xml index b6d1ac319..41fc1dacf 100644 --- a/app/src/main/res/values-ca/strings.xml +++ b/app/src/main/res/values-ca/strings.xml @@ -1009,6 +1009,5 @@ Predeterminat Si us plau, selecciona quins camps vols mostrar al giny {name}. Giny - Origen Ginys diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 9e42f11c9..a78c902ce 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -1009,6 +1009,5 @@ Výchozí Vyberte, která pole chcete zobrazit ve widgetu {name}. Widget - Zdroj Widgety diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 471b47b09..53a6661d3 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -978,7 +978,6 @@ Standard Benutzerdefiniert Bitte wähle die Felder aus, die du im {name} Widget anzeigen möchtest. - Quelle Widget hinzufügen Widget löschen? Bist du sicher, dass du \'{name}\' aus deinen Widgets löschen möchtest? diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index 5626058ad..5770417f3 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -1009,6 +1009,5 @@ Προεπιλογή Επίλεξε ποια πεδία θέλεις να εμφανίζονται στο widget {name}. Widget - Πηγή Widgets diff --git a/app/src/main/res/values-es-rES/strings.xml b/app/src/main/res/values-es-rES/strings.xml index 9d7dc2dd8..14eed8d98 100644 --- a/app/src/main/res/values-es-rES/strings.xml +++ b/app/src/main/res/values-es-rES/strings.xml @@ -1009,6 +1009,5 @@ Por defecto Por favor, seleccione cuales campos quiere mostrar en el widget {name}. Widget - Fuente Widgets diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 3b28d0ac9..4c5fa1a4d 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -976,7 +976,6 @@ Widget Personalizar Por favor, seleccione cuales campos quiere mostrar en el widget {name}. - Fuente Añadir Widget ¿Borrar Widget? ¿Está seguro de querer borrar ‘{name}‘ de sus widgets? diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 3e05ac3a7..c2f57da98 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -978,7 +978,6 @@ Défaut Personnalisé Veuillez sélectionner les champs que vous souhaitez afficher dans le widget {name}. - Source Ajouter un widget Supprimer le widget ? Êtes-vous sûr de vouloir supprimer \'{name}\' de vos widgets ? diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 0efb275cc..725c9e63e 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -1009,6 +1009,5 @@ Predefinito Seleziona quali campi desideri visualizzare nel widget {name}. Widget - Fonte Widget diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 0c87b7fd0..8951ef9e4 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -1009,6 +1009,5 @@ Standaard Selecteer welke velden je wilt weergeven in de {name}-widget. Widget - Bron Widgets diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index d0c78dd15..9b70af610 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -978,7 +978,6 @@ Domyślne Własna Wybierz pola, które chcesz wyświetlić w widgecie {name}. - Źródło Dodaj widget Usunąć widget? Na pewno usunąć widget ‘{name}‘ z twoich widgetów? diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 81ad7407e..128f48de9 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -1009,6 +1009,5 @@ Padrão Por favor, selecione quais campos você deseja exibir no widget {name}. Widget - Fonte Widgets diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index fdb8c385a..642ce49c6 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -982,7 +982,6 @@ Padrão Personalizada Por favor, selecione quais campos você deseja exibir no widget {name}. - Fonte Adicionar Widget Excluir o Widget? Tem certeza de que deseja excluir \'{name}\' dos seus widgets? diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 08fad3fce..537077887 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -1037,6 +1037,5 @@ Bitkit должен увеличить приёмную ёмкость ваше По умолчанию Пожалуйста, выберите, какие поля вы хотите отображать в виджете {name}. Виджет - Источник Виджеты diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 790513476..7d61dee98 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1149,7 +1149,8 @@ Transfer To Spending Your withdrawal was unsuccessful. Please scan the QR code again or contact support. Add Widget - Examine various statistics on newly mined Bitcoin Blocks. + Data (max 4) + Examine various statistics on newly mined Bitcoin Blocks. Powered by mempool.space. Block Date Fees @@ -1201,6 +1202,5 @@ Widget Settings Small Wide - Source Widgets diff --git a/app/src/test/java/to/bitkit/models/widget/BlocksWidgetFieldTest.kt b/app/src/test/java/to/bitkit/models/widget/BlocksWidgetFieldTest.kt new file mode 100644 index 000000000..87a73afb0 --- /dev/null +++ b/app/src/test/java/to/bitkit/models/widget/BlocksWidgetFieldTest.kt @@ -0,0 +1,96 @@ +package to.bitkit.models.widget + +import org.junit.Test +import kotlin.test.assertEquals +import kotlin.test.assertFalse +import kotlin.test.assertTrue + +class BlocksWidgetFieldTest { + + @Test + fun `default preferences enable exactly the first four fields`() { + val enabled = BlocksPreferences().enabledFields() + + assertEquals( + listOf( + BlocksWidgetField.BLOCK, + BlocksWidgetField.TIME, + BlocksWidgetField.DATE, + BlocksWidgetField.TRANSACTIONS, + ), + enabled, + ) + } + + @Test + fun `toggleField turns off an enabled field even at the limit`() { + val result = BlocksPreferences().toggleField(BlocksWidgetField.BLOCK) + + assertFalse(result.showBlock) + assertEquals(3, result.enabledFields().size) + } + + @Test + fun `toggleField is a no-op when enabling a fifth field`() { + // Defaults already have 4 fields enabled (block, time, date, transactions) + val result = BlocksPreferences().toggleField(BlocksWidgetField.SIZE) + + assertFalse(result.showSize) + assertEquals(MAX_BLOCKS_FIELDS, result.enabledFields().size) + } + + @Test + fun `toggleField enables a disabled field when below the limit`() { + val prefs = BlocksPreferences( + showBlock = true, + showTime = true, + showDate = false, + showTransactions = false, + showSize = false, + showFees = false, + ) + + val result = prefs.toggleField(BlocksWidgetField.FEES) + + assertTrue(result.showFees) + assertEquals(3, result.enabledFields().size) + } + + @Test + fun `limitedToMax keeps only the first four enabled fields in declared order`() { + val prefs = BlocksPreferences( + showBlock = true, + showTime = true, + showDate = true, + showTransactions = true, + showSize = true, + showFees = true, + ) + + val result = prefs.limitedToMax() + + assertEquals( + listOf( + BlocksWidgetField.BLOCK, + BlocksWidgetField.TIME, + BlocksWidgetField.DATE, + BlocksWidgetField.TRANSACTIONS, + ), + result.enabledFields(), + ) + } + + @Test + fun `limitedToMax leaves compliant preferences unchanged`() { + val prefs = BlocksPreferences( + showBlock = true, + showTime = false, + showDate = true, + showTransactions = false, + showSize = true, + showFees = false, + ) + + assertEquals(prefs, prefs.limitedToMax()) + } +} From a74fd96bcf921345eb4e28c3204bfa97e9e51578 Mon Sep 17 00:00:00 2001 From: jvsena42 Date: Thu, 21 May 2026 10:38:00 -0300 Subject: [PATCH 2/7] fix: increase the glace widget vertical padding --- .../java/to/bitkit/appwidget/ui/blocks/BlocksGlanceContent.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/to/bitkit/appwidget/ui/blocks/BlocksGlanceContent.kt b/app/src/main/java/to/bitkit/appwidget/ui/blocks/BlocksGlanceContent.kt index 782096d7b..2f9321db1 100644 --- a/app/src/main/java/to/bitkit/appwidget/ui/blocks/BlocksGlanceContent.kt +++ b/app/src/main/java/to/bitkit/appwidget/ui/blocks/BlocksGlanceContent.kt @@ -90,7 +90,8 @@ fun BlocksGlanceContent( @Composable private fun WideContent(fields: ImmutableList, block: BlockModel, context: Context) { Column(modifier = GlanceModifier.fillMaxSize()) { - fields.forEach { field -> + fields.forEachIndexed { index, field -> + if (index > 0) VerticalSpacer(8.dp) WideRow( label = context.getString(field.labelRes), value = field.value(block), From dd52fb30b997180d6b561b2ab764ffe519b59a33 Mon Sep 17 00:00:00 2001 From: jvsena42 Date: Thu, 21 May 2026 10:52:33 -0300 Subject: [PATCH 3/7] fix: adapt the card style for glance --- .../bitkit/appwidget/ui/blocks/BlocksGlanceContent.kt | 8 ++++---- .../to/bitkit/appwidget/ui/components/GlanceText.kt | 10 ++++++++++ .../to/bitkit/appwidget/ui/theme/GlanceTextStyles.kt | 1 + 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/to/bitkit/appwidget/ui/blocks/BlocksGlanceContent.kt b/app/src/main/java/to/bitkit/appwidget/ui/blocks/BlocksGlanceContent.kt index 2f9321db1..fd133a555 100644 --- a/app/src/main/java/to/bitkit/appwidget/ui/blocks/BlocksGlanceContent.kt +++ b/app/src/main/java/to/bitkit/appwidget/ui/blocks/BlocksGlanceContent.kt @@ -24,10 +24,12 @@ import androidx.glance.layout.size import androidx.glance.unit.Dimension import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.toImmutableList +import to.bitkit.R import to.bitkit.appwidget.config.AppWidgetConfigActivity import to.bitkit.appwidget.model.AppWidgetEntry import to.bitkit.appwidget.model.AppWidgetType import to.bitkit.appwidget.model.HomeBlocksPreferences +import to.bitkit.appwidget.ui.components.BodyM import to.bitkit.appwidget.ui.components.BodyMSB import to.bitkit.appwidget.ui.components.BodySSB import to.bitkit.appwidget.ui.components.CaptionB @@ -35,8 +37,6 @@ import to.bitkit.appwidget.ui.components.GlanceLayoutDimens import to.bitkit.appwidget.ui.components.GlanceWidgetScaffold import to.bitkit.appwidget.ui.components.HorizontalSpacer import to.bitkit.appwidget.ui.components.VerticalSpacer -import to.bitkit.appwidget.ui.theme.GlanceColors -import to.bitkit.R import to.bitkit.models.widget.BlockModel import to.bitkit.models.widget.BlocksWidgetField import to.bitkit.models.widget.MAX_BLOCKS_FIELDS @@ -116,9 +116,9 @@ private fun WideRow(label: String, value: String, icon: Int, modifier: GlanceMod modifier = GlanceModifier.size(20.dp) ) HorizontalSpacer(8.dp) - BodyMSB( + BodyM( text = label, - color = GlanceColors.textSecondary, + color = ColorProvider(day = Colors.White80, night = Colors.White80), modifier = GlanceModifier.then(WidthModifier(Dimension.Expand)) ) BodyMSB(text = value) diff --git a/app/src/main/java/to/bitkit/appwidget/ui/components/GlanceText.kt b/app/src/main/java/to/bitkit/appwidget/ui/components/GlanceText.kt index b0b723a00..807a9dc01 100644 --- a/app/src/main/java/to/bitkit/appwidget/ui/components/GlanceText.kt +++ b/app/src/main/java/to/bitkit/appwidget/ui/components/GlanceText.kt @@ -17,6 +17,16 @@ fun Subtitle( Text(text = text, style = GlanceTextStyles.subtitle.withColor(color), maxLines = maxLines, modifier = modifier) } +@Composable +fun BodyM( + text: String, + modifier: GlanceModifier = GlanceModifier, + color: ColorProvider? = null, + maxLines: Int = Int.MAX_VALUE, +) { + Text(text = text, style = GlanceTextStyles.bodyM.withColor(color), maxLines = maxLines, modifier = modifier) +} + @Composable fun BodyMSB( text: String, diff --git a/app/src/main/java/to/bitkit/appwidget/ui/theme/GlanceTextStyles.kt b/app/src/main/java/to/bitkit/appwidget/ui/theme/GlanceTextStyles.kt index e37b669a6..3d748cb21 100644 --- a/app/src/main/java/to/bitkit/appwidget/ui/theme/GlanceTextStyles.kt +++ b/app/src/main/java/to/bitkit/appwidget/ui/theme/GlanceTextStyles.kt @@ -6,6 +6,7 @@ import androidx.glance.text.TextStyle object GlanceTextStyles { val subtitle = TextStyle(fontSize = 17.sp, fontWeight = FontWeight.Bold, color = GlanceColors.textPrimary) + val bodyM = TextStyle(fontSize = 17.sp, fontWeight = FontWeight.Normal, color = GlanceColors.textPrimary) val bodyMSB = TextStyle(fontSize = 17.sp, fontWeight = FontWeight.Medium, color = GlanceColors.textPrimary) val bodySSB = TextStyle(fontSize = 15.sp, fontWeight = FontWeight.Medium, color = GlanceColors.textPrimary) val bodySB = TextStyle(fontSize = 15.sp, fontWeight = FontWeight.Bold, color = GlanceColors.textPrimary) From f49cee7b3e83df4fa7069148a499b659588d549c Mon Sep 17 00:00:00 2001 From: jvsena42 Date: Thu, 21 May 2026 11:03:27 -0300 Subject: [PATCH 4/7] fix: wide vertical spacer --- .../java/to/bitkit/appwidget/ui/blocks/BlocksGlanceContent.kt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/src/main/java/to/bitkit/appwidget/ui/blocks/BlocksGlanceContent.kt b/app/src/main/java/to/bitkit/appwidget/ui/blocks/BlocksGlanceContent.kt index fd133a555..09a19a26e 100644 --- a/app/src/main/java/to/bitkit/appwidget/ui/blocks/BlocksGlanceContent.kt +++ b/app/src/main/java/to/bitkit/appwidget/ui/blocks/BlocksGlanceContent.kt @@ -19,7 +19,6 @@ import androidx.glance.layout.Row import androidx.glance.layout.WidthModifier import androidx.glance.layout.fillMaxSize import androidx.glance.layout.fillMaxWidth -import androidx.glance.layout.padding import androidx.glance.layout.size import androidx.glance.unit.Dimension import kotlinx.collections.immutable.ImmutableList @@ -91,12 +90,11 @@ fun BlocksGlanceContent( private fun WideContent(fields: ImmutableList, block: BlockModel, context: Context) { Column(modifier = GlanceModifier.fillMaxSize()) { fields.forEachIndexed { index, field -> - if (index > 0) VerticalSpacer(8.dp) + if (index > 0) VerticalSpacer(12.dp) WideRow( label = context.getString(field.labelRes), value = field.value(block), icon = field.icon, - modifier = GlanceModifier.padding(vertical = 6.dp) ) } } From 4e317d4e5369e395e8af3956824c7b42a8ac47c1 Mon Sep 17 00:00:00 2001 From: jvsena42 Date: Thu, 21 May 2026 11:16:07 -0300 Subject: [PATCH 5/7] fix: make the minResizeHeight 1 cell --- app/src/main/res/xml/appwidget_info_blocks.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/xml/appwidget_info_blocks.xml b/app/src/main/res/xml/appwidget_info_blocks.xml index a373fd82c..9cab01b61 100644 --- a/app/src/main/res/xml/appwidget_info_blocks.xml +++ b/app/src/main/res/xml/appwidget_info_blocks.xml @@ -4,7 +4,8 @@ android:minWidth="@dimen/appwidget_min_width" android:minHeight="@dimen/appwidget_min_height" android:minResizeWidth="@dimen/appwidget_min_resize_width" - android:minResizeHeight="@dimen/appwidget_min_resize_height" + android:minResizeHeight="40dp" + android:maxResizeHeight="@dimen/appwidget_min_height" android:targetCellWidth="@integer/appwidget_target_cell_width" android:targetCellHeight="@integer/appwidget_target_cell_height" android:resizeMode="horizontal|vertical" From 497272f921653a20066369b46c3597b042a56aec Mon Sep 17 00:00:00 2001 From: jvsena42 Date: Thu, 21 May 2026 11:30:05 -0300 Subject: [PATCH 6/7] fix: increase wide content padding --- .../java/to/bitkit/appwidget/ui/blocks/BlocksGlanceContent.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/to/bitkit/appwidget/ui/blocks/BlocksGlanceContent.kt b/app/src/main/java/to/bitkit/appwidget/ui/blocks/BlocksGlanceContent.kt index 09a19a26e..09d6d78aa 100644 --- a/app/src/main/java/to/bitkit/appwidget/ui/blocks/BlocksGlanceContent.kt +++ b/app/src/main/java/to/bitkit/appwidget/ui/blocks/BlocksGlanceContent.kt @@ -90,7 +90,7 @@ fun BlocksGlanceContent( private fun WideContent(fields: ImmutableList, block: BlockModel, context: Context) { Column(modifier = GlanceModifier.fillMaxSize()) { fields.forEachIndexed { index, field -> - if (index > 0) VerticalSpacer(12.dp) + if (index > 0) VerticalSpacer(16.dp) WideRow( label = context.getString(field.labelRes), value = field.value(block), From b8ef5a9f8a0b0f83a67ef5a86dfefae2527f94aa Mon Sep 17 00:00:00 2001 From: jvsena42 Date: Thu, 21 May 2026 11:49:12 -0300 Subject: [PATCH 7/7] fix: enforce max-4 block fields in wide layouts --- .../to/bitkit/appwidget/ui/blocks/BlocksGlanceContent.kt | 6 ++++-- .../java/to/bitkit/ui/screens/widgets/blocks/BlockCard.kt | 4 +++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/to/bitkit/appwidget/ui/blocks/BlocksGlanceContent.kt b/app/src/main/java/to/bitkit/appwidget/ui/blocks/BlocksGlanceContent.kt index 09d6d78aa..7d49a1c6d 100644 --- a/app/src/main/java/to/bitkit/appwidget/ui/blocks/BlocksGlanceContent.kt +++ b/app/src/main/java/to/bitkit/appwidget/ui/blocks/BlocksGlanceContent.kt @@ -71,7 +71,9 @@ fun BlocksGlanceContent( return@GlanceWidgetScaffold } - val fields = entry.blocksPreferences.enabledFields().filter { it.value(block).isNotEmpty() } + val fields = entry.blocksPreferences.enabledFields() + .filter { it.value(block).isNotEmpty() } + .take(MAX_BLOCKS_FIELDS) if (fields.isEmpty()) { CaptionB(text = context.getString(R.string.appwidget__loading)) return@GlanceWidgetScaffold @@ -80,7 +82,7 @@ fun BlocksGlanceContent( if (LocalSize.current.width >= GlanceLayoutDimens.WIDE_LAYOUT_MIN_WIDTH) { WideContent(fields = fields.toImmutableList(), block = block, context = context) } else { - CompactContent(fields = fields.take(MAX_BLOCKS_FIELDS).toImmutableList(), block = block) + CompactContent(fields = fields.toImmutableList(), block = block) } } } diff --git a/app/src/main/java/to/bitkit/ui/screens/widgets/blocks/BlockCard.kt b/app/src/main/java/to/bitkit/ui/screens/widgets/blocks/BlockCard.kt index 19230fb96..78bbd9b6b 100644 --- a/app/src/main/java/to/bitkit/ui/screens/widgets/blocks/BlockCard.kt +++ b/app/src/main/java/to/bitkit/ui/screens/widgets/blocks/BlockCard.kt @@ -38,7 +38,9 @@ fun BlockCard( preferences: BlocksPreferences, block: BlockModel, ) { - val fields = preferences.enabledFields().filter { it.value(block).isNotEmpty() } + val fields = preferences.enabledFields() + .filter { it.value(block).isNotEmpty() } + .take(MAX_BLOCKS_FIELDS) Box( modifier = modifier