Skip to content

Commit b0e6eb2

Browse files
authored
Merge pull request #169 from synonymdev/feat/widgets-base
2 parents eb4e54c + 5a4c132 commit b0e6eb2

File tree

16 files changed

+460
-2
lines changed

16 files changed

+460
-2
lines changed

app/src/main/java/to/bitkit/data/SettingsStore.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import to.bitkit.data.serializers.SettingsSerializer
1111
import to.bitkit.models.BitcoinDisplayUnit
1212
import to.bitkit.models.PrimaryDisplay
1313
import to.bitkit.models.TransactionSpeed
14+
import to.bitkit.models.WidgetWithPosition
1415
import to.bitkit.utils.Logger
1516
import javax.inject.Inject
1617
import javax.inject.Singleton
@@ -58,6 +59,7 @@ data class SettingsData(
5859
val defaultTransactionSpeed: TransactionSpeed = TransactionSpeed.Medium,
5960
val showEmptyState: Boolean = false,
6061
val hasSeenSpendingIntro: Boolean = false,
62+
val hasSeenWidgetsIntro: Boolean = false,
6163
val hasSeenTransferIntro: Boolean = false,
6264
val hasSeenSavingsIntro: Boolean = false,
6365
val hasSeenShopIntro: Boolean = false,
@@ -75,4 +77,5 @@ data class SettingsData(
7577
val showWidgets: Boolean = false,
7678
val showWidgetTitles: Boolean = false,
7779
val lastUsedTags: List<String> = emptyList(),
80+
val widgets: List<WidgetWithPosition> = emptyList()
7881
)
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package to.bitkit.models
2+
3+
enum class WidgetType {
4+
BLOCK,
5+
CALCULATOR,
6+
FACTS,
7+
NEWS,
8+
PRICE,
9+
WEATHER
10+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package to.bitkit.models
2+
3+
import kotlinx.serialization.Serializable
4+
5+
@Serializable
6+
data class WidgetWithPosition(
7+
val type: WidgetType,
8+
val position: Int,
9+
)

app/src/main/java/to/bitkit/ui/ContentView.kt

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import androidx.navigation.toRoute
2929
import kotlinx.coroutines.delay
3030
import kotlinx.coroutines.launch
3131
import kotlinx.serialization.Serializable
32+
import to.bitkit.currentActivity
3233
import to.bitkit.models.NewTransactionSheetDetails
3334
import to.bitkit.models.NodeLifecycleState
3435
import to.bitkit.ui.components.AuthCheckScreen
@@ -65,6 +66,8 @@ import to.bitkit.ui.screens.wallets.HomeScreen
6566
import to.bitkit.ui.screens.wallets.activity.ActivityDetailScreen
6667
import to.bitkit.ui.screens.wallets.activity.ActivityExploreScreen
6768
import to.bitkit.ui.screens.wallets.suggestion.BuyIntroScreen
69+
import to.bitkit.ui.screens.widgets.AddWidgetsScreen
70+
import to.bitkit.ui.screens.widgets.WidgetsIntroScreen
6871
import to.bitkit.ui.settings.AboutScreen
6972
import to.bitkit.ui.settings.AdvancedSettingsScreen
7073
import to.bitkit.ui.settings.BackupSettingsScreen
@@ -277,6 +280,7 @@ fun ContentView(
277280
authCheck(navController)
278281
logs(navController)
279282
suggestions(navController)
283+
widgets(navController, settingsViewModel, currencyViewModel)
280284

281285
// TODO extract transferNavigation
282286
navigation<Routes.TransferRoot>(
@@ -862,6 +866,31 @@ private fun NavGraphBuilder.suggestions(
862866
}
863867
}
864868

869+
private fun NavGraphBuilder.widgets(
870+
navController: NavHostController,
871+
settingsViewModel: SettingsViewModel,
872+
currencyViewModel: CurrencyViewModel,
873+
) {
874+
composableWithDefaultTransitions<Routes.WidgetsIntro> {
875+
WidgetsIntroScreen(
876+
onClose = { navController.navigateToHome() },
877+
onContinue = {
878+
settingsViewModel.setHasSeenWidgetsIntro(true)
879+
navController.navigate(Routes.AddWidget)
880+
}
881+
)
882+
}
883+
composableWithDefaultTransitions<Routes.AddWidget> {
884+
AddWidgetsScreen(
885+
onClose = { navController.navigateToHome() },
886+
onWidgetSelected = { widgetType ->
887+
888+
},
889+
fiatSymbol = currencyViewModel.getCurrencySymbol()
890+
)
891+
}
892+
}
893+
865894
// endregion
866895

867896
// region events
@@ -1239,4 +1268,10 @@ object Routes {
12391268

12401269
@Serializable
12411270
data object ShopDiscover
1271+
1272+
@Serializable
1273+
data object WidgetsIntro
1274+
1275+
@Serializable
1276+
data object AddWidget
12421277
}

app/src/main/java/to/bitkit/ui/components/settings/SettingsButtonRow.kt

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ import androidx.compose.ui.Modifier
1919
import androidx.compose.ui.draw.alpha
2020
import androidx.compose.ui.graphics.Color
2121
import androidx.compose.ui.res.painterResource
22+
import androidx.compose.ui.text.style.TextOverflow
2223
import androidx.compose.ui.tooling.preview.Preview
24+
import androidx.compose.ui.unit.Dp
2325
import androidx.compose.ui.unit.dp
2426
import to.bitkit.R
2527
import to.bitkit.ui.components.BodyM
@@ -45,6 +47,8 @@ fun SettingsButtonRow(
4547
description: String? = null,
4648
iconRes: Int? = null,
4749
iconTint: Color = Color.Unspecified,
50+
iconSize: Dp = 32.dp,
51+
maxLinesSubtitle: Int = Int.MAX_VALUE,
4852
enabled: Boolean = true,
4953
loading: Boolean = false,
5054
onClick: () -> Unit,
@@ -71,7 +75,7 @@ fun SettingsButtonRow(
7175
painter = painterResource(iconRes),
7276
contentDescription = null,
7377
tint = iconTint,
74-
modifier = Modifier.size(32.dp),
78+
modifier = Modifier.size(iconSize),
7579
)
7680
Spacer(modifier = Modifier.width(10.dp))
7781
}
@@ -84,7 +88,12 @@ fun SettingsButtonRow(
8488
if (subtitle != null) {
8589
BodyMSB(text = title)
8690
Spacer(modifier = Modifier.height(4.dp))
87-
BodySSB(text = subtitle, color = Colors.White64)
91+
BodySSB(
92+
text = subtitle,
93+
maxLines = maxLinesSubtitle,
94+
color = Colors.White64,
95+
overflow = TextOverflow.Ellipsis
96+
)
8897
} else {
8998
BodyM(text = title)
9099
}

app/src/main/java/to/bitkit/ui/screens/wallets/HomeScreen.kt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import androidx.compose.material.pullrefresh.PullRefreshIndicator
2828
import androidx.compose.material.pullrefresh.pullRefresh
2929
import androidx.compose.material.pullrefresh.rememberPullRefreshState
3030
import androidx.compose.material3.ExperimentalMaterial3Api
31+
import androidx.compose.material3.Icon
3132
import androidx.compose.material3.VerticalDivider
3233
import androidx.compose.runtime.Composable
3334
import androidx.compose.runtime.LaunchedEffect
@@ -65,6 +66,7 @@ import to.bitkit.ui.components.EmptyStateView
6566
import to.bitkit.ui.components.SheetHost
6667
import to.bitkit.ui.components.SuggestionCard
6768
import to.bitkit.ui.components.TabBar
69+
import to.bitkit.ui.components.TertiaryButton
6870
import to.bitkit.ui.components.Text13Up
6971
import to.bitkit.ui.components.WalletBalanceView
7072
import to.bitkit.ui.navigateToActivityItem
@@ -165,6 +167,7 @@ fun HomeScreen(
165167
val hasSeenShopIntro by settingsViewModel.hasSeenShopIntro.collectAsStateWithLifecycle()
166168
val hasSeenProfileIntro by settingsViewModel.hasSeenProfileIntro.collectAsStateWithLifecycle()
167169
val quickPayIntroSeen by settingsViewModel.quickPayIntroSeen.collectAsStateWithLifecycle()
170+
val hasSeenWidgetsIntro by settingsViewModel.hasSeenWidgetsIntro.collectAsStateWithLifecycle()
168171

169172
HomeContentView(
170173
uiState = uiState,
@@ -238,6 +241,13 @@ fun HomeScreen(
238241
}
239242
}
240243
},
244+
onClickAddWIdget = {
245+
if (!hasSeenWidgetsIntro) {
246+
rootNavController.navigate(Routes.WidgetsIntro)
247+
} else {
248+
rootNavController.navigate(Routes.AddWidget)
249+
}
250+
}
241251
)
242252
}
243253
composable<HomeRoutes.Savings>(
@@ -313,6 +323,7 @@ private fun HomeContentView(
313323
suggestions: List<Suggestion>,
314324
onRemoveSuggestion: (Suggestion) -> Unit,
315325
onClickSuggestion: (Suggestion) -> Unit,
326+
onClickAddWIdget: () -> Unit,
316327
rootNavController: NavController,
317328
walletNavController: NavController,
318329
onRefresh: () -> Unit,
@@ -404,6 +415,21 @@ private fun HomeContentView(
404415
}
405416
}
406417
Spacer(modifier = Modifier.height(32.dp))
418+
Text13Up(stringResource(R.string.widgets__widgets), color = Colors.White64)
419+
//TODO IMPLEMENT LIST IN OTHER PR
420+
Spacer(modifier = Modifier.height(32.dp))
421+
TertiaryButton(
422+
text = stringResource(R.string.widgets__add),
423+
icon = {
424+
Icon(
425+
painter = painterResource(R.drawable.ic_plus),
426+
contentDescription = null,
427+
tint = Colors.White80
428+
)
429+
},
430+
onClick = onClickAddWIdget
431+
)
432+
Spacer(modifier = Modifier.height(32.dp))
407433
Text13Up(stringResource(R.string.wallet__activity), color = Colors.White64)
408434
Spacer(modifier = Modifier.height(16.dp))
409435
val activity = activityListViewModel ?: return@Column
@@ -483,6 +509,7 @@ private fun HomeContentViewPreview() {
483509
onRefresh = {},
484510
onClickSuggestion = {},
485511
onRemoveSuggestion = {},
512+
onClickAddWIdget = {},
486513
)
487514
}
488515
}
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
package to.bitkit.ui.screens.widgets
2+
3+
import androidx.compose.foundation.layout.Column
4+
import androidx.compose.foundation.layout.padding
5+
import androidx.compose.runtime.Composable
6+
import androidx.compose.ui.Modifier
7+
import androidx.compose.ui.platform.testTag
8+
import androidx.compose.ui.res.stringResource
9+
import androidx.compose.ui.tooling.preview.Preview
10+
import androidx.compose.ui.unit.dp
11+
import to.bitkit.R
12+
import to.bitkit.models.WidgetType
13+
import to.bitkit.ui.components.settings.SettingsButtonRow
14+
import to.bitkit.ui.scaffold.AppTopBar
15+
import to.bitkit.ui.scaffold.CloseNavIcon
16+
import to.bitkit.ui.scaffold.ScreenColumn
17+
import to.bitkit.ui.theme.AppThemeSurface
18+
19+
@Composable
20+
fun AddWidgetsScreen(
21+
onClose: () -> Unit,
22+
onWidgetSelected: (WidgetType) -> Unit,
23+
fiatSymbol: String,
24+
) {
25+
ScreenColumn {
26+
AppTopBar(
27+
titleText = stringResource(R.string.widgets__add),
28+
onBackClick = null,
29+
actions = { CloseNavIcon(onClick = onClose) },
30+
)
31+
32+
Column(
33+
modifier = Modifier.padding(horizontal = 16.dp)
34+
) {
35+
SettingsButtonRow(
36+
title = stringResource(R.string.widgets__price__name),
37+
subtitle = stringResource(R.string.widgets__price__description),
38+
iconRes = R.drawable.widget_chart_line,
39+
iconSize = 48.dp,
40+
maxLinesSubtitle = 1,
41+
onClick = { onWidgetSelected(WidgetType.PRICE) },
42+
modifier = Modifier.testTag("Button_${WidgetType.PRICE}")
43+
)
44+
SettingsButtonRow(
45+
title = stringResource(R.string.widgets__news__name),
46+
subtitle = stringResource(R.string.widgets__news__description),
47+
iconRes = R.drawable.widget_newspaper,
48+
iconSize = 48.dp,
49+
maxLinesSubtitle = 1,
50+
onClick = { onWidgetSelected(WidgetType.NEWS) },
51+
modifier = Modifier.testTag("Button_${WidgetType.NEWS}")
52+
53+
)
54+
SettingsButtonRow(
55+
title = stringResource(R.string.widgets__blocks__name),
56+
subtitle = stringResource(R.string.widgets__blocks__description),
57+
iconRes = R.drawable.widget_cube,
58+
iconSize = 48.dp,
59+
maxLinesSubtitle = 1,
60+
onClick = { onWidgetSelected(WidgetType.BLOCK) },
61+
modifier = Modifier.testTag("Button_${WidgetType.BLOCK}")
62+
)
63+
SettingsButtonRow(
64+
title = stringResource(R.string.widgets__facts__name),
65+
subtitle = stringResource(R.string.widgets__facts__description),
66+
iconRes = R.drawable.widget_lightbulb,
67+
iconSize = 48.dp,
68+
maxLinesSubtitle = 1,
69+
onClick = { onWidgetSelected(WidgetType.FACTS) },
70+
modifier = Modifier.testTag("Button_${WidgetType.FACTS}")
71+
)
72+
SettingsButtonRow(
73+
title = stringResource(R.string.widgets__weather__name),
74+
subtitle = stringResource(R.string.widgets__weather__description),
75+
iconRes = R.drawable.widget_cloud,
76+
iconSize = 48.dp,
77+
maxLinesSubtitle = 1,
78+
onClick = { onWidgetSelected(WidgetType.WEATHER) },
79+
modifier = Modifier.testTag("Button_${WidgetType.WEATHER}")
80+
)
81+
SettingsButtonRow(
82+
title = stringResource(R.string.widgets__calculator__name),
83+
subtitle = stringResource(R.string.widgets__calculator__description).replace(
84+
"{fiatSymbol}",
85+
fiatSymbol
86+
),
87+
iconRes = R.drawable.widget_math_operation,
88+
iconSize = 48.dp,
89+
maxLinesSubtitle = 1,
90+
onClick = { onWidgetSelected(WidgetType.CALCULATOR) },
91+
modifier = Modifier.testTag("Button_${WidgetType.CALCULATOR}")
92+
)
93+
}
94+
}
95+
}
96+
97+
98+
@Preview(showBackground = true)
99+
@Composable
100+
private fun Preview() {
101+
AppThemeSurface {
102+
AddWidgetsScreen(
103+
onClose = {},
104+
onWidgetSelected = {},
105+
fiatSymbol = "$"
106+
)
107+
}
108+
}

0 commit comments

Comments
 (0)