@@ -21,60 +21,37 @@ import androidx.compose.material3.Surface
2121import androidx.compose.material3.Text
2222import androidx.compose.runtime.Composable
2323import androidx.compose.runtime.LaunchedEffect
24- import androidx.compose.runtime.collectAsState
25- import androidx.compose.runtime.derivedStateOf
2624import androidx.compose.runtime.getValue
27- import androidx.compose.runtime.remember
25+ import androidx.compose.runtime.rememberUpdatedState
2826import androidx.compose.ui.Alignment
2927import androidx.compose.ui.Modifier
3028import androidx.compose.ui.graphics.RectangleShape
3129import androidx.compose.ui.res.stringResource
3230import androidx.compose.ui.text.style.TextAlign
33- import androidx.compose.ui.tooling.preview.Preview
3431import androidx.compose.ui.unit.dp
35- import androidx.lifecycle.viewmodel.compose.viewModel
36- import java.util.Locale
37- import org.cru.godtools.BuildConfig
32+ import com.slack.circuit.codegen.annotations.CircuitInject
33+ import dagger.hilt.components.SingletonComponent
3834import org.cru.godtools.R
39- import org.cru.godtools.analytics.model.OpenAnalyticsActionEvent.Companion.ACTION_OPEN_LESSON
40- import org.cru.godtools.analytics.model.OpenAnalyticsActionEvent.Companion.ACTION_OPEN_TOOL
41- import org.cru.godtools.analytics.model.OpenAnalyticsActionEvent.Companion.ACTION_OPEN_TOOL_DETAILS
42- import org.cru.godtools.analytics.model.OpenAnalyticsActionEvent.Companion.SOURCE_FAVORITE
43- import org.cru.godtools.analytics.model.OpenAnalyticsActionEvent.Companion.SOURCE_FEATURED
44- import org.cru.godtools.model.Tool
4535import org.cru.godtools.ui.banner.Banners
36+ import org.cru.godtools.ui.dashboard.home.HomeScreen.UiEvent
37+ import org.cru.godtools.ui.dashboard.home.HomeScreen.UiState
4638import org.cru.godtools.ui.tools.LessonToolCard
47- import org.cru.godtools.ui.tools.PreloadTool
4839import org.cru.godtools.ui.tools.SquareToolCard
49- import org.cru.godtools.ui.tools.ToolCardEvent
5040
5141private val PADDING_HORIZONTAL = 16 .dp
5242
53- internal sealed interface DashboardHomeEvent {
54- open class OpenTool (val tool : String? , val type : Tool .Type ? , val lang1 : Locale ? , val lang2 : Locale ? = null ) :
55- DashboardHomeEvent {
56- constructor (event: ToolCardEvent ) : this (event.tool, event.toolType, event.lang1, event.lang2)
57- }
58- open class OpenToolDetails (val tool : String? ) : DashboardHomeEvent {
59- constructor (event: ToolCardEvent .OpenToolDetails ) : this (event.tool)
60- }
61- class OpenLesson (event : ToolCardEvent ) : OpenTool(event.tool, Tool .Type .LESSON , event.lang1)
62- data object ViewAllFavorites : DashboardHomeEvent
63- data object ViewAllTools : DashboardHomeEvent
64- }
65-
6643@Composable
67- internal fun HomeContent (onEvent : (DashboardHomeEvent ) -> Unit , viewModel : HomeViewModel = viewModel()) {
68- val favoriteTools by viewModel.favoriteTools.collectAsState()
69- val spotlightLessons by viewModel.spotlightLessons.collectAsState()
70- val favoriteToolsLoaded by remember { derivedStateOf { favoriteTools != null } }
71- val hasFavoriteTools by remember { derivedStateOf { ! favoriteTools.isNullOrEmpty() } }
44+ @CircuitInject(HomeScreen ::class , SingletonComponent ::class )
45+ internal fun HomeLayout (state : UiState , modifier : Modifier = Modifier ) {
46+ val banner by rememberUpdatedState(state.banner)
47+ val favoriteToolsLoaded by rememberUpdatedState(state.favoriteToolsLoaded)
48+
49+ val hasFavoriteTools by rememberUpdatedState(state.favoriteTools.isNotEmpty())
7250
7351 val columnState = rememberLazyListState()
74- val banner by viewModel.banner.collectAsState()
7552 LaunchedEffect (banner) { if (banner != null ) columnState.animateScrollToItem(0 ) }
7653
77- LazyColumn (state = columnState, contentPadding = PaddingValues (bottom = 16 .dp)) {
54+ LazyColumn (state = columnState, contentPadding = PaddingValues (bottom = 16 .dp), modifier = modifier ) {
7855 item(" banners" , " banners" ) {
7956 Banners (
8057 { banner },
@@ -94,7 +71,7 @@ internal fun HomeContent(onEvent: (DashboardHomeEvent) -> Unit, viewModel: HomeV
9471 }
9572
9673 // featured lessons
97- if (spotlightLessons.isNotEmpty()) {
74+ if (state. spotlightLessons.isNotEmpty()) {
9875 item(" lesson-header" , " lesson-header" ) {
9976 FeaturedLessonsHeader (
10077 modifier = Modifier
@@ -104,20 +81,13 @@ internal fun HomeContent(onEvent: (DashboardHomeEvent) -> Unit, viewModel: HomeV
10481 )
10582 }
10683
107- items(spotlightLessons, key = { it }, contentType = { " lesson-tool-card" }) { lesson ->
84+ items(
85+ state.spotlightLessons,
86+ key = { it.toolCode.orEmpty() },
87+ contentType = { " lesson-tool-card" }
88+ ) { lessonState ->
10889 LessonToolCard (
109- lesson,
110- onEvent = {
111- when (it) {
112- is ToolCardEvent .Click , is ToolCardEvent .OpenTool -> {
113- viewModel.recordOpenClickInAnalytics(ACTION_OPEN_LESSON , it.tool, SOURCE_FEATURED )
114- onEvent(DashboardHomeEvent .OpenLesson (it))
115- }
116- is ToolCardEvent .OpenToolDetails -> {
117- if (BuildConfig .DEBUG ) error(" $it is currently unsupported for Lesson Cards" )
118- }
119- }
120- },
90+ lessonState,
12191 modifier = Modifier
12292 .animateItem()
12393 .padding(horizontal = PADDING_HORIZONTAL )
@@ -130,8 +100,7 @@ internal fun HomeContent(onEvent: (DashboardHomeEvent) -> Unit, viewModel: HomeV
130100 if (favoriteToolsLoaded) {
131101 item(" favorites-header" ) {
132102 FavoritesHeader (
133- showViewAll = { hasFavoriteTools },
134- onEvent = onEvent,
103+ state = state,
135104 modifier = Modifier
136105 .animateItem()
137106 .padding(horizontal = PADDING_HORIZONTAL )
@@ -142,22 +111,7 @@ internal fun HomeContent(onEvent: (DashboardHomeEvent) -> Unit, viewModel: HomeV
142111 if (hasFavoriteTools) {
143112 item(" favorites" , " favorites" ) {
144113 HorizontalFavoriteTools (
145- { favoriteTools.orEmpty().take(5 ) },
146- onEvent = {
147- when {
148- it is DashboardHomeEvent .OpenTool -> viewModel.recordOpenClickInAnalytics(
149- ACTION_OPEN_TOOL ,
150- it.tool,
151- SOURCE_FAVORITE
152- )
153- it is DashboardHomeEvent .OpenToolDetails -> viewModel.recordOpenClickInAnalytics(
154- ACTION_OPEN_TOOL_DETAILS ,
155- it.tool,
156- SOURCE_FAVORITE
157- )
158- }
159- onEvent(it)
160- },
114+ state,
161115 modifier = Modifier
162116 .animateItem()
163117 .fillMaxWidth()
@@ -166,7 +120,7 @@ internal fun HomeContent(onEvent: (DashboardHomeEvent) -> Unit, viewModel: HomeV
166120 } else {
167121 item(" favorites-empty" , " favorites-empty" ) {
168122 NoFavoriteTools (
169- onEvent = onEvent ,
123+ state = state ,
170124 modifier = Modifier
171125 .animateItem()
172126 .padding(horizontal = PADDING_HORIZONTAL )
@@ -192,11 +146,9 @@ private fun FeaturedLessonsHeader(modifier: Modifier = Modifier) = Text(
192146)
193147
194148@Composable
195- private fun FavoritesHeader (
196- showViewAll : () -> Boolean ,
197- onEvent : (DashboardHomeEvent ) -> Unit ,
198- modifier : Modifier = Modifier ,
199- ) = Row (modifier = modifier.fillMaxWidth()) {
149+ private fun FavoritesHeader (state : UiState , modifier : Modifier = Modifier ) = Row (modifier = modifier.fillMaxWidth()) {
150+ val eventSink by rememberUpdatedState(state.eventSink)
151+
200152 Text (
201153 stringResource(R .string.dashboard_home_section_favorites_title),
202154 style = MaterialTheme .typography.titleLarge,
@@ -206,7 +158,7 @@ private fun FavoritesHeader(
206158 )
207159
208160 AnimatedVisibility (
209- showViewAll (),
161+ state.favoriteTools.isNotEmpty (),
210162 enter = fadeIn(),
211163 exit = fadeOut(),
212164 modifier = Modifier .alignByBaseline()
@@ -215,47 +167,38 @@ private fun FavoritesHeader(
215167 stringResource(R .string.dashboard_home_section_favorites_action_view_all),
216168 style = MaterialTheme .typography.bodySmall,
217169 color = MaterialTheme .colorScheme.primary,
218- modifier = Modifier .clickable { onEvent( DashboardHomeEvent .ViewAllFavorites ) }
170+ modifier = Modifier .clickable { eventSink( UiEvent .ViewAllFavorites ) }
219171 )
220172 }
221173}
222174
223175@Composable
224- private fun HorizontalFavoriteTools (
225- tools : () -> List <Tool >,
226- onEvent : (DashboardHomeEvent ) -> Unit ,
227- modifier : Modifier = Modifier ,
228- ) = LazyRow (
229- contentPadding = PaddingValues (horizontal = 16 .dp),
230- horizontalArrangement = Arrangement .spacedBy(16 .dp),
231- modifier = modifier
232- ) {
233- items(tools(), key = { it.code.orEmpty() }) {
234- PreloadTool (it)
235-
236- SquareToolCard (
237- toolCode = it.code.orEmpty(),
238- confirmRemovalFromFavorites = true ,
239- onEvent = {
240- when (it) {
241- is ToolCardEvent .Click , is ToolCardEvent .OpenTool -> onEvent(DashboardHomeEvent .OpenTool (it))
242- is ToolCardEvent .OpenToolDetails -> onEvent(DashboardHomeEvent .OpenToolDetails (it))
243- }
244- },
245- modifier = Modifier .animateItem()
246- )
176+ private fun HorizontalFavoriteTools (state : UiState , modifier : Modifier = Modifier ) {
177+ LazyRow (
178+ contentPadding = PaddingValues (horizontal = 16 .dp),
179+ horizontalArrangement = Arrangement .spacedBy(16 .dp),
180+ modifier = modifier
181+ ) {
182+ items(state.favoriteTools, key = { it.toolCode.orEmpty() }) { toolState ->
183+ SquareToolCard (
184+ state = toolState,
185+ confirmRemovalFromFavorites = true ,
186+ modifier = Modifier .animateItem()
187+ )
188+ }
247189 }
248190}
249191
250- @Preview
251192@Composable
252- private fun NoFavoriteTools (modifier : Modifier = Modifier , onEvent : ( DashboardHomeEvent ) -> Unit = {} ) = Surface (
193+ private fun NoFavoriteTools (state : UiState , modifier : Modifier = Modifier ) = Surface (
253194 color = MaterialTheme .colorScheme.surfaceVariant,
254195 shape = RectangleShape ,
255196 modifier = modifier
256197 .fillMaxWidth()
257198 .heightIn(min = 215 .dp)
258199) {
200+ val eventSink by rememberUpdatedState(state.eventSink)
201+
259202 Column (verticalArrangement = Arrangement .Center , modifier = Modifier .padding(16 .dp)) {
260203 Text (
261204 stringResource(R .string.dashboard_home_section_favorites_no_tools_title),
@@ -270,7 +213,7 @@ private fun NoFavoriteTools(modifier: Modifier = Modifier, onEvent: (DashboardHo
270213 modifier = Modifier .fillMaxWidth()
271214 )
272215 Button (
273- onClick = { onEvent( DashboardHomeEvent .ViewAllTools ) },
216+ onClick = { eventSink( UiEvent .ViewAllTools ) },
274217 modifier = Modifier
275218 .padding(top = 8 .dp)
276219 .align(Alignment .CenterHorizontally )
0 commit comments