Skip to content

Commit a6f5558

Browse files
authored
Merge pull request #922 from synonymdev/feat/blocks-v61
2 parents ae47db8 + d31c0b0 commit a6f5558

36 files changed

Lines changed: 1734 additions & 769 deletions

app/src/androidTest/java/to/bitkit/ui/screens/widgets/blocks/BlockCardTest.kt

Lines changed: 67 additions & 105 deletions
Large diffs are not rendered by default.

app/src/androidTest/java/to/bitkit/ui/screens/widgets/blocks/BlocksEditScreenTest.kt

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ class BlocksEditScreenTest {
2222
date = "11/2/2022",
2323
transactionCount = "2,175",
2424
size = "1,606Kb",
25-
source = "mempool.io"
25+
source = "mempool.io",
26+
fees = "25 059 357",
2627
)
2728

2829
private val defaultPreferences = BlocksPreferences()
@@ -36,6 +37,7 @@ class BlocksEditScreenTest {
3637
var dateClicked = false
3738
var transactionsClicked = false
3839
var sizeClicked = false
40+
var feesClicked = false
3941
var sourceClicked = false
4042
var resetClicked = false
4143
var previewClicked = false
@@ -50,6 +52,7 @@ class BlocksEditScreenTest {
5052
onClickShowDate = { dateClicked = true },
5153
onClickShowTransactions = { transactionsClicked = true },
5254
onClickShowSize = { sizeClicked = true },
55+
onClickShowFees = { feesClicked = true },
5356
onClickShowSource = { sourceClicked = true },
5457
onClickReset = { resetClicked = true },
5558
onClickPreview = { previewClicked = true },
@@ -63,13 +66,14 @@ class BlocksEditScreenTest {
6366
composeTestRule.onNodeWithTag("blocks_edit_screen").assertExists()
6467
composeTestRule.onNodeWithTag("WidgetEditScrollView").assertExists()
6568

66-
// Verify description
67-
composeTestRule.onNodeWithTag("edit_description").assertExists()
69+
// Verify section header
70+
composeTestRule.onNodeWithTag("data_section_header").assertExists()
6871

6972
// Verify all setting rows exist
70-
listOf("block", "time", "date", "transactions", "size", "source").forEach { prefix ->
73+
listOf("block", "time", "date", "transactions", "size", "fees", "source").forEach { prefix ->
7174
composeTestRule.onNodeWithTag("${prefix}_setting_row").assertExists()
7275
composeTestRule.onNodeWithTag("${prefix}_label").assertExists()
76+
composeTestRule.onNodeWithTag("${prefix}_leading_icon", useUnmergedTree = true).assertExists()
7377
if (testBlock.getFieldValue(prefix).isNotEmpty()) {
7478
composeTestRule.onNodeWithTag("${prefix}_text").assertExists()
7579
}
@@ -115,6 +119,7 @@ class BlocksEditScreenTest {
115119
onClickShowDate = {},
116120
onClickShowTransactions = {},
117121
onClickShowSize = {},
122+
onClickShowFees = {},
118123
onClickShowSource = {},
119124
onClickReset = { resetClicked = true },
120125
onClickPreview = {},
@@ -146,6 +151,7 @@ class BlocksEditScreenTest {
146151
onClickShowDate = {},
147152
onClickShowTransactions = {},
148153
onClickShowSize = {},
154+
onClickShowFees = {},
149155
onClickShowSource = {},
150156
onClickReset = {},
151157
onClickPreview = {},
@@ -167,6 +173,7 @@ class BlocksEditScreenTest {
167173
showDate = false,
168174
showTransactions = false,
169175
showSize = false,
176+
showFees = false,
170177
showSource = false
171178
)
172179

@@ -179,6 +186,7 @@ class BlocksEditScreenTest {
179186
onClickShowDate = {},
180187
onClickShowTransactions = {},
181188
onClickShowSize = {},
189+
onClickShowFees = {},
182190
onClickShowSource = {},
183191
onClickReset = {},
184192
onClickPreview = {},
@@ -199,6 +207,7 @@ class BlocksEditScreenTest {
199207
var dateClicked = false
200208
var transactionsClicked = false
201209
var sizeClicked = false
210+
var feesClicked = false
202211
var sourceClicked = false
203212
var resetClicked = false
204213
var previewClicked = false
@@ -209,6 +218,7 @@ class BlocksEditScreenTest {
209218
showDate = false,
210219
showTransactions = false,
211220
showSize = true,
221+
showFees = false,
212222
showSource = true
213223
)
214224

@@ -221,6 +231,7 @@ class BlocksEditScreenTest {
221231
onClickShowDate = { dateClicked = true },
222232
onClickShowTransactions = { transactionsClicked = true },
223233
onClickShowSize = { sizeClicked = true },
234+
onClickShowFees = { feesClicked = true },
224235
onClickShowSource = { sourceClicked = true },
225236
onClickReset = { resetClicked = true },
226237
onClickPreview = { previewClicked = true },
@@ -246,6 +257,9 @@ class BlocksEditScreenTest {
246257
composeTestRule.onNodeWithTag("size_toggle_button").performClick()
247258
assert(sizeClicked)
248259

260+
composeTestRule.onNodeWithTag("fees_toggle_button").performClick()
261+
assert(feesClicked)
262+
249263
composeTestRule.onNodeWithTag("source_toggle_button").performClick()
250264
assert(sourceClicked)
251265

@@ -265,7 +279,8 @@ class BlocksEditScreenTest {
265279
date = "",
266280
transactionCount = "",
267281
size = "",
268-
source = ""
282+
source = "",
283+
fees = "",
269284
)
270285

271286
composeTestRule.setContent {
@@ -277,6 +292,7 @@ class BlocksEditScreenTest {
277292
onClickShowDate = {},
278293
onClickShowTransactions = {},
279294
onClickShowSize = {},
295+
onClickShowFees = {},
280296
onClickShowSource = {},
281297
onClickReset = {},
282298
onClickPreview = {},
@@ -287,7 +303,7 @@ class BlocksEditScreenTest {
287303
}
288304

289305
// Assert that text elements don't exist when values are empty
290-
listOf("block", "time", "date", "transactions", "size", "source").forEach { prefix ->
306+
listOf("block", "time", "date", "transactions", "size", "fees", "source").forEach { prefix ->
291307
composeTestRule.onNodeWithTag("${prefix}_text").assertDoesNotExist()
292308
}
293309
}
@@ -304,6 +320,7 @@ class BlocksEditScreenTest {
304320
onClickShowDate = {},
305321
onClickShowTransactions = {},
306322
onClickShowSize = {},
323+
onClickShowFees = {},
307324
onClickShowSource = {},
308325
onClickReset = {},
309326
onClickPreview = {},
@@ -313,6 +330,7 @@ class BlocksEditScreenTest {
313330
showDate = false,
314331
showTransactions = false,
315332
showSize = true,
333+
showFees = false,
316334
showSource = true
317335
),
318336
block = testBlock
@@ -323,11 +341,12 @@ class BlocksEditScreenTest {
323341
// Assert all tagged elements exist
324342
composeTestRule.onNodeWithTag("blocks_edit_screen").assertExists()
325343
composeTestRule.onNodeWithTag("WidgetEditScrollView").assertExists()
326-
composeTestRule.onNodeWithTag("edit_description").assertExists()
344+
composeTestRule.onNodeWithTag("data_section_header").assertExists()
327345

328-
listOf("block", "time", "date", "transactions", "size", "source").forEach { prefix ->
346+
listOf("block", "time", "date", "transactions", "size", "fees", "source").forEach { prefix ->
329347
composeTestRule.onNodeWithTag("${prefix}_setting_row").assertExists()
330348
composeTestRule.onNodeWithTag("${prefix}_label").assertExists()
349+
composeTestRule.onNodeWithTag("${prefix}_leading_icon", useUnmergedTree = true).assertExists()
331350
composeTestRule.onNodeWithTag("${prefix}_toggle_button").assertExists()
332351
composeTestRule.onNodeWithTag("${prefix}_toggle_icon", useUnmergedTree = true).assertExists()
333352
composeTestRule.onNodeWithTag("${prefix}_divider").assertExists()
@@ -347,6 +366,7 @@ private fun BlockModel.getFieldValue(prefix: String): String {
347366
"date" -> date
348367
"transactions" -> transactionCount
349368
"size" -> size
369+
"fees" -> fees
350370
"source" -> source
351371
else -> ""
352372
}

app/src/androidTest/java/to/bitkit/ui/screens/widgets/blocks/BlocksPreviewScreenTest.kt

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ class BlocksPreviewContentTest {
2121
date = "2023-01-01",
2222
transactionCount = "2,175",
2323
size = "1,606kB",
24-
source = "mempool.space"
24+
source = "mempool.space",
25+
fees = "25 059 357",
2526
)
2627
private val defaultPreferences = BlocksPreferences()
2728

@@ -41,7 +42,6 @@ class BlocksPreviewContentTest {
4142
onClickEdit = { editClicked = true },
4243
onClickDelete = { deleteClicked = true },
4344
onClickSave = { saveClicked = true },
44-
showWidgetTitles = true,
4545
isBlocksWidgetEnabled = true,
4646
blocksPreferences = defaultPreferences,
4747
block = testBlock
@@ -96,7 +96,6 @@ class BlocksPreviewContentTest {
9696
onClickEdit = { editClicked = true },
9797
onClickDelete = { deleteClicked = true },
9898
onClickSave = { saveClicked = true },
99-
showWidgetTitles = false,
10099
isBlocksWidgetEnabled = false,
101100
blocksPreferences = defaultPreferences,
102101
block = testBlock
@@ -137,7 +136,6 @@ class BlocksPreviewContentTest {
137136
onClickEdit = {},
138137
onClickDelete = {},
139138
onClickSave = {},
140-
showWidgetTitles = true,
141139
isBlocksWidgetEnabled = true,
142140
blocksPreferences = customPreferences,
143141
block = testBlock
@@ -161,7 +159,6 @@ class BlocksPreviewContentTest {
161159
onClickEdit = {},
162160
onClickDelete = {},
163161
onClickSave = {},
164-
showWidgetTitles = true,
165162
isBlocksWidgetEnabled = true,
166163
blocksPreferences = defaultPreferences,
167164
block = testBlock
@@ -197,7 +194,6 @@ class BlocksPreviewContentTest {
197194
onClickEdit = {},
198195
onClickDelete = {},
199196
onClickSave = {},
200-
showWidgetTitles = true,
201197
isBlocksWidgetEnabled = true,
202198
blocksPreferences = defaultPreferences,
203199
block = testBlock
@@ -228,7 +224,6 @@ class BlocksPreviewContentTest {
228224
onClickEdit = {},
229225
onClickDelete = {},
230226
onClickSave = {},
231-
showWidgetTitles = false,
232227
isBlocksWidgetEnabled = false,
233228
blocksPreferences = minimalPreferences,
234229
block = testBlock
@@ -253,7 +248,6 @@ class BlocksPreviewContentTest {
253248
onClickEdit = {},
254249
onClickDelete = {},
255250
onClickSave = {},
256-
showWidgetTitles = true,
257251
isBlocksWidgetEnabled = true,
258252
blocksPreferences = defaultPreferences,
259253
block = testBlock
@@ -285,7 +279,6 @@ class BlocksPreviewContentTest {
285279
onClickEdit = {},
286280
onClickDelete = {},
287281
onClickSave = {},
288-
showWidgetTitles = true,
289282
isBlocksWidgetEnabled = true,
290283
blocksPreferences = customPreferences,
291284
block = testBlock
@@ -307,7 +300,6 @@ class BlocksPreviewContentTest {
307300
onClickEdit = {},
308301
onClickDelete = {},
309302
onClickSave = {},
310-
showWidgetTitles = true,
311303
isBlocksWidgetEnabled = true,
312304
blocksPreferences = defaultPreferences,
313305
block = null

app/src/main/AndroidManifest.xml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,19 @@
217217
android:resource="@xml/appwidget_info_headlines" />
218218
</receiver>
219219

220+
<!-- Blocks Widget -->
221+
<receiver
222+
android:name=".appwidget.ui.blocks.BlocksGlanceReceiver"
223+
android:exported="true"
224+
android:label="@string/widgets__blocks__name">
225+
<intent-filter>
226+
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
227+
</intent-filter>
228+
<meta-data
229+
android:name="android.appwidget.provider"
230+
android:resource="@xml/appwidget_info_blocks" />
231+
</receiver>
232+
220233
</application>
221234

222235
</manifest>

app/src/main/java/to/bitkit/appwidget/AppWidgetDataRepository.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ package to.bitkit.appwidget
33
import kotlinx.coroutines.CoroutineDispatcher
44
import kotlinx.coroutines.withContext
55
import to.bitkit.data.dto.ArticleDTO
6+
import to.bitkit.data.dto.BlockDTO
67
import to.bitkit.data.dto.price.GraphPeriod
78
import to.bitkit.data.dto.price.PriceDTO
9+
import to.bitkit.data.widgets.BlocksService
810
import to.bitkit.data.widgets.NewsService
911
import to.bitkit.data.widgets.PriceService
1012
import to.bitkit.di.IoDispatcher
@@ -16,6 +18,7 @@ class AppWidgetDataRepository @Inject constructor(
1618
@IoDispatcher private val ioDispatcher: CoroutineDispatcher,
1719
private val priceService: PriceService,
1820
private val newsService: NewsService,
21+
private val blocksService: BlocksService,
1922
) {
2023
suspend fun fetchPriceData(period: GraphPeriod = GraphPeriod.ONE_DAY): Result<PriceDTO> =
2124
withContext(ioDispatcher) {
@@ -26,4 +29,9 @@ class AppWidgetDataRepository @Inject constructor(
2629
withContext(ioDispatcher) {
2730
newsService.fetchData()
2831
}
32+
33+
suspend fun fetchBlock(): Result<BlockDTO> =
34+
withContext(ioDispatcher) {
35+
blocksService.fetchData()
36+
}
2937
}

app/src/main/java/to/bitkit/appwidget/AppWidgetPreferencesStore.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import to.bitkit.appwidget.model.AppWidgetData
1414
import to.bitkit.appwidget.model.AppWidgetEntry
1515
import to.bitkit.appwidget.model.AppWidgetType
1616
import to.bitkit.data.dto.ArticleDTO
17+
import to.bitkit.data.dto.BlockDTO
1718
import to.bitkit.data.dto.price.GraphPeriod
1819
import to.bitkit.data.dto.price.PriceDTO
1920
import to.bitkit.data.serializers.AppWidgetDataSerializer
@@ -32,6 +33,7 @@ interface AppWidgetEntryPoint {
3233
}
3334

3435
@Singleton
36+
@Suppress("TooManyFunctions")
3537
class AppWidgetPreferencesStore @Inject constructor(
3638
@ApplicationContext private val context: Context,
3739
) {
@@ -90,4 +92,8 @@ class AppWidgetPreferencesStore @Inject constructor(
9092
)
9193
}
9294
}
95+
96+
suspend fun cacheBlock(block: BlockDTO) {
97+
store.updateData { it.copy(cachedBlock = block) }
98+
}
9399
}

app/src/main/java/to/bitkit/appwidget/AppWidgetRefreshWorker.kt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import androidx.work.WorkerParameters
1616
import dagger.assisted.Assisted
1717
import dagger.assisted.AssistedInject
1818
import to.bitkit.appwidget.model.AppWidgetType
19+
import to.bitkit.appwidget.ui.blocks.BlocksGlanceReceiver
20+
import to.bitkit.appwidget.ui.blocks.BlocksGlanceWidget
1921
import to.bitkit.appwidget.ui.headlines.HeadlinesGlanceReceiver
2022
import to.bitkit.appwidget.ui.headlines.HeadlinesGlanceWidget
2123
import to.bitkit.appwidget.ui.price.PriceGlanceReceiver
@@ -65,6 +67,7 @@ class AppWidgetRefreshWorker @AssistedInject constructor(
6567
private fun receiverClassFor(type: AppWidgetType): Class<out GlanceAppWidgetReceiver> = when (type) {
6668
AppWidgetType.PRICE -> PriceGlanceReceiver::class.java
6769
AppWidgetType.HEADLINES -> HeadlinesGlanceReceiver::class.java
70+
AppWidgetType.BLOCKS -> BlocksGlanceReceiver::class.java
6871
}
6972
}
7073

@@ -96,6 +99,15 @@ class AppWidgetRefreshWorker @AssistedInject constructor(
9699
}
97100
HeadlinesGlanceWidget().updateAll(appContext)
98101
}
102+
103+
AppWidgetType.BLOCKS -> {
104+
dataRepository.fetchBlock()
105+
.onSuccess { preferencesStore.cacheBlock(it) }
106+
.onFailure {
107+
Logger.warn("Failed to refresh block", it, context = TAG)
108+
}
109+
BlocksGlanceWidget().updateAll(appContext)
110+
}
99111
}
100112
}
101113

app/src/main/java/to/bitkit/appwidget/config/AppWidgetConfigActivity.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import androidx.glance.appwidget.updateAll
1111
import dagger.hilt.android.AndroidEntryPoint
1212
import to.bitkit.appwidget.AppWidgetRefreshWorker
1313
import to.bitkit.appwidget.model.AppWidgetType
14+
import to.bitkit.appwidget.ui.blocks.BlocksGlanceReceiver
15+
import to.bitkit.appwidget.ui.blocks.BlocksGlanceWidget
1416
import to.bitkit.appwidget.ui.headlines.HeadlinesGlanceReceiver
1517
import to.bitkit.appwidget.ui.headlines.HeadlinesGlanceWidget
1618
import to.bitkit.appwidget.ui.price.PriceGlanceReceiver
@@ -55,6 +57,7 @@ class AppWidgetConfigActivity : ComponentActivity() {
5557
when (viewModel.uiState.value.type) {
5658
AppWidgetType.PRICE -> PriceGlanceWidget().updateAll(this@AppWidgetConfigActivity)
5759
AppWidgetType.HEADLINES -> HeadlinesGlanceWidget().updateAll(this@AppWidgetConfigActivity)
60+
AppWidgetType.BLOCKS -> BlocksGlanceWidget().updateAll(this@AppWidgetConfigActivity)
5861
}
5962
AppWidgetRefreshWorker.enqueue(this@AppWidgetConfigActivity)
6063
val result = Intent().putExtra(
@@ -80,6 +83,7 @@ class AppWidgetConfigActivity : ComponentActivity() {
8083
return when (providerClass) {
8184
HeadlinesGlanceReceiver::class.java.name -> AppWidgetType.HEADLINES
8285
PriceGlanceReceiver::class.java.name -> AppWidgetType.PRICE
86+
BlocksGlanceReceiver::class.java.name -> AppWidgetType.BLOCKS
8387
else -> {
8488
Logger.warn(
8589
"Encountered unknown provider class '$providerClass' " +

0 commit comments

Comments
 (0)