Skip to content

Commit 7086708

Browse files
authored
Merge pull request #3864 from CruGlobal/circuitLessonsScreen
GT-2437 Convert dashboard Lessons layout to use Circuit
2 parents 6cab6d3 + 55257df commit 7086708

23 files changed

Lines changed: 691 additions & 489 deletions

app/src/main/kotlin/org/cru/godtools/ui/dashboard/DashboardLayout.kt

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,7 @@ import org.cru.godtools.model.Tool
5858
import org.cru.godtools.shared.analytics.AnalyticsScreenNames
5959
import org.cru.godtools.ui.dashboard.home.AllFavoritesScreen
6060
import org.cru.godtools.ui.dashboard.home.HomeScreen
61-
import org.cru.godtools.ui.dashboard.lessons.DashboardLessonsEvent
62-
import org.cru.godtools.ui.dashboard.lessons.LessonsLayout
61+
import org.cru.godtools.ui.dashboard.lessons.LessonsScreen
6362
import org.cru.godtools.ui.dashboard.tools.ToolsScreen
6463
import org.cru.godtools.ui.drawer.DrawerMenuLayout
6564
import org.cru.godtools.ui.tooldetails.ToolDetailsScreen
@@ -68,7 +67,6 @@ internal sealed interface DashboardEvent {
6867
class OpenIntent(val intent: Intent) : DashboardEvent
6968
open class OpenTool(val tool: String?, val type: Tool.Type?, val lang1: Locale?, val lang2: Locale? = null) :
7069
DashboardEvent
71-
class OpenLesson(lesson: String?, lang: Locale?) : OpenTool(lesson, Tool.Type.LESSON, lang)
7270
class OpenToolDetails(val tool: String?, val lang: Locale? = null) : DashboardEvent
7371
}
7472

@@ -120,20 +118,13 @@ internal fun DashboardLayout(onEvent: (DashboardEvent) -> Unit, viewModel: Dashb
120118
Crossfade(currentPage, label = "Main Content Crossfade") { page ->
121119
saveableStateHolder.SaveableStateProvider(page) {
122120
when (page) {
123-
Page.LESSONS -> LessonsLayout(
124-
onEvent = {
125-
when (it) {
126-
is DashboardLessonsEvent.OpenLesson ->
127-
onEvent(DashboardEvent.OpenLesson(it.lesson, it.lang))
128-
}
129-
},
130-
)
131-
121+
Page.LESSONS,
132122
Page.HOME,
133123
Page.FAVORITE_TOOLS,
134124
Page.ALL_TOOLS -> {
135125
CircuitContent(
136126
screen = when (page) {
127+
Page.LESSONS -> LessonsScreen
137128
Page.HOME -> HomeScreen
138129
Page.FAVORITE_TOOLS -> AllFavoritesScreen
139130
Page.ALL_TOOLS -> ToolsScreen
Lines changed: 11 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -1,135 +1,40 @@
11
package org.cru.godtools.ui.dashboard.lessons
22

3-
import androidx.compose.foundation.ExperimentalFoundationApi
43
import androidx.compose.foundation.layout.Row
5-
import androidx.compose.foundation.layout.fillMaxWidth
64
import androidx.compose.foundation.layout.padding
7-
import androidx.compose.foundation.layout.sizeIn
8-
import androidx.compose.foundation.layout.wrapContentWidth
9-
import androidx.compose.foundation.lazy.itemsIndexed
10-
import androidx.compose.material3.ElevatedButton
11-
import androidx.compose.material3.ExperimentalMaterial3Api
12-
import androidx.compose.material3.ExposedDropdownMenuDefaults
13-
import androidx.compose.material3.HorizontalDivider
14-
import androidx.compose.material3.MenuDefaults
15-
import androidx.compose.material3.SearchBar
16-
import androidx.compose.material3.Surface
175
import androidx.compose.material3.Text
186
import androidx.compose.runtime.Composable
19-
import androidx.compose.runtime.collectAsState
20-
import androidx.compose.runtime.getValue
21-
import androidx.compose.runtime.mutableStateOf
22-
import androidx.compose.runtime.remember
23-
import androidx.compose.runtime.setValue
247
import androidx.compose.ui.Modifier
258
import androidx.compose.ui.platform.LocalContext
269
import androidx.compose.ui.res.pluralStringResource
2710
import androidx.compose.ui.res.stringResource
28-
import androidx.compose.ui.semantics.Role
29-
import androidx.compose.ui.semantics.role
30-
import androidx.compose.ui.semantics.semantics
31-
import androidx.compose.ui.text.style.TextOverflow
3211
import androidx.compose.ui.unit.dp
33-
import androidx.lifecycle.viewmodel.compose.viewModel
34-
import java.util.Locale
35-
import org.ccci.gto.android.common.androidx.compose.material3.ui.list.ListItemStartPadding
36-
import org.ccci.gto.android.common.androidx.compose.material3.ui.menu.LazyDropdownMenu
3712
import org.cru.godtools.R
3813
import org.cru.godtools.base.LocalAppLanguage
39-
import org.cru.godtools.base.ui.theme.GodToolsTheme
40-
import org.cru.godtools.model.Language
41-
import org.cru.godtools.ui.dashboard.filters.FilterMenuItem
14+
import org.cru.godtools.ui.dashboard.filters.LazyFilterMenu
4215
import org.cru.godtools.ui.languages.LanguageName
4316

44-
private val DROPDOWN_LESSON_MAX_HEIGHT = 700.dp
45-
private val DROPDOWN_LESSON_MAX_WIDTH = 350.dp
46-
4717
@Composable
48-
fun LessonFilters(modifier: Modifier = Modifier) {
18+
internal fun LessonFilters(state: LessonsScreen.UiState, modifier: Modifier = Modifier) {
4919
Row(modifier = modifier) {
5020
Text(
5121
stringResource(R.string.dashboard_lessons_section_filter_label),
5222
modifier = Modifier
5323
.alignByBaseline()
5424
.padding(end = 36.dp)
5525
)
56-
LessonLanguageFilter(
26+
LazyFilterMenu(
27+
state.languageFilter,
28+
buttonLabelText = state.languageFilter.selectedItem
29+
?.getDisplayName(LocalContext.current, LocalAppLanguage.current).orEmpty(),
30+
itemKey = { (it) -> it.code },
31+
itemLabel = { LanguageName(it.item.code) },
32+
itemSupportingText = { (_, count) ->
33+
pluralStringResource(R.plurals.dashboard_lessons_section_filter_available_lessons, count, count)
34+
},
5735
modifier = Modifier
5836
.weight(1f)
5937
.alignByBaseline()
6038
)
6139
}
6240
}
63-
64-
@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class)
65-
@Composable
66-
internal fun LessonLanguageFilter(modifier: Modifier = Modifier, viewModel: LessonsViewModel = viewModel()) {
67-
val context = LocalContext.current
68-
val selectedLanguage by viewModel.selectedLanguage.collectAsState(initial = Language(Locale.getDefault()))
69-
70-
val lessonLanguages by viewModel.filteredLanguages.collectAsState(emptyList())
71-
var expanded by remember { mutableStateOf(false) }
72-
73-
ElevatedButton(
74-
onClick = { expanded = true },
75-
modifier = modifier.semantics { role = Role.DropdownList }
76-
) {
77-
Text(
78-
selectedLanguage.getDisplayName(context, LocalAppLanguage.current),
79-
maxLines = 1,
80-
overflow = TextOverflow.Ellipsis,
81-
modifier = Modifier.weight(1f),
82-
)
83-
ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded)
84-
LazyDropdownMenu(
85-
expanded = expanded,
86-
onDismissRequest = { expanded = false },
87-
modifier = Modifier.sizeIn(maxHeight = DROPDOWN_LESSON_MAX_HEIGHT, maxWidth = DROPDOWN_LESSON_MAX_WIDTH)
88-
) {
89-
stickyHeader {
90-
Surface(color = MenuDefaults.containerColor) {
91-
val query by viewModel.query.collectAsState("")
92-
SearchBar(
93-
query = query,
94-
onQueryChange = { change ->
95-
viewModel.query.value = change
96-
},
97-
onSearch = {},
98-
active = false,
99-
onActiveChange = {},
100-
colors = GodToolsTheme.searchBarColors,
101-
placeholder = {
102-
Text(stringResource(R.string.language_settings_downloadable_languages_search))
103-
},
104-
content = {},
105-
modifier = Modifier
106-
.padding(horizontal = 8.dp)
107-
.fillMaxWidth()
108-
.wrapContentWidth()
109-
)
110-
}
111-
}
112-
113-
itemsIndexed(lessonLanguages, key = { _, (language) -> language.code }) { index, (lang, count) ->
114-
if (index > 0) {
115-
HorizontalDivider(Modifier.padding(start = ListItemStartPadding, end = ListItemStartPadding))
116-
}
117-
FilterMenuItem(
118-
label = { LanguageName(lang) },
119-
supportingText = pluralStringResource(
120-
R.plurals.dashboard_lessons_section_filter_available_lessons,
121-
count,
122-
count,
123-
),
124-
onClick = {
125-
expanded = false
126-
viewModel.updateSelectedLanguage(lang)
127-
viewModel.query.value = ""
128-
},
129-
// TODO: Animate item placement - Add back when Compose version 1.7 is released
130-
// modifier = Modifier.animateItemPlacement()
131-
)
132-
}
133-
}
134-
}
135-
}

app/src/main/kotlin/org/cru/godtools/ui/dashboard/lessons/LessonsLayout.kt

Lines changed: 8 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,46 +9,28 @@ import androidx.compose.material3.HorizontalDivider
99
import androidx.compose.material3.MaterialTheme
1010
import androidx.compose.material3.Text
1111
import androidx.compose.runtime.Composable
12-
import androidx.compose.runtime.collectAsState
13-
import androidx.compose.runtime.getValue
1412
import androidx.compose.ui.Modifier
1513
import androidx.compose.ui.res.stringResource
1614
import androidx.compose.ui.tooling.preview.Preview
1715
import androidx.compose.ui.unit.dp
18-
import androidx.lifecycle.viewmodel.compose.viewModel
19-
import java.util.Locale
16+
import com.slack.circuit.codegen.annotations.CircuitInject
17+
import dagger.hilt.components.SingletonComponent
2018
import org.cru.godtools.R
2119
import org.cru.godtools.ui.tools.LessonToolCard
22-
import org.cru.godtools.ui.tools.ToolCardEvent
23-
24-
internal sealed interface DashboardLessonsEvent {
25-
class OpenLesson(val lesson: String?, val lang: Locale?) : DashboardLessonsEvent
26-
}
2720

2821
@Composable
29-
internal fun LessonsLayout(viewModel: LessonsViewModel = viewModel(), onEvent: (DashboardLessonsEvent) -> Unit = {}) {
30-
val lessons by viewModel.lessons.collectAsState(emptyList())
31-
val selectedLanguage by viewModel.selectedLanguage.collectAsState()
32-
33-
LazyColumn(contentPadding = PaddingValues(16.dp)) {
22+
@CircuitInject(LessonsScreen::class, SingletonComponent::class)
23+
internal fun LessonsLayout(state: LessonsScreen.UiState, modifier: Modifier = Modifier) {
24+
LazyColumn(contentPadding = PaddingValues(16.dp), modifier = modifier) {
3425
item("header", "header") {
3526
LessonsHeader()
3627
HorizontalDivider(modifier = Modifier.padding(vertical = 12.dp))
37-
LessonFilters()
28+
LessonFilters(state)
3829
}
3930

40-
items(lessons, { it }, { "lesson" }) { lesson ->
31+
items(state.lessons, { it.toolCode.orEmpty() }, { "lesson" }) { toolState ->
4132
LessonToolCard(
42-
lesson,
43-
selectedLanguage = selectedLanguage,
44-
onEvent = {
45-
when (it) {
46-
is ToolCardEvent.OpenTool, is ToolCardEvent.Click -> {
47-
viewModel.recordOpenLessonInAnalytics(it.tool)
48-
onEvent(DashboardLessonsEvent.OpenLesson(it.tool, it.lang1))
49-
}
50-
}
51-
},
33+
toolState,
5234
modifier = Modifier
5335
.animateItem()
5436
.padding(top = 16.dp)

0 commit comments

Comments
 (0)