diff --git a/app/src/main/kotlin/org/cru/godtools/ui/dashboard/DashboardLayout.kt b/app/src/main/kotlin/org/cru/godtools/ui/dashboard/DashboardLayout.kt index 7f3ec28c70..d47e509ad8 100644 --- a/app/src/main/kotlin/org/cru/godtools/ui/dashboard/DashboardLayout.kt +++ b/app/src/main/kotlin/org/cru/godtools/ui/dashboard/DashboardLayout.kt @@ -57,8 +57,7 @@ import org.cru.godtools.base.ui.theme.GodToolsTheme import org.cru.godtools.model.Tool import org.cru.godtools.shared.analytics.AnalyticsScreenNames import org.cru.godtools.ui.dashboard.home.AllFavoritesScreen -import org.cru.godtools.ui.dashboard.home.DashboardHomeEvent -import org.cru.godtools.ui.dashboard.home.HomeContent +import org.cru.godtools.ui.dashboard.home.HomeScreen import org.cru.godtools.ui.dashboard.lessons.DashboardLessonsEvent import org.cru.godtools.ui.dashboard.lessons.LessonsLayout import org.cru.godtools.ui.dashboard.tools.ToolsScreen @@ -130,26 +129,12 @@ internal fun DashboardLayout(onEvent: (DashboardEvent) -> Unit, viewModel: Dashb }, ) - Page.HOME -> HomeContent( - onEvent = { - when (it) { - DashboardHomeEvent.ViewAllFavorites -> { - saveableStateHolder.removeState(Page.FAVORITE_TOOLS) - viewModel.updateCurrentPage(Page.FAVORITE_TOOLS, false) - } - DashboardHomeEvent.ViewAllTools -> viewModel.updateCurrentPage(Page.ALL_TOOLS) - is DashboardHomeEvent.OpenTool -> - onEvent(DashboardEvent.OpenTool(it.tool, it.type, it.lang1, it.lang2)) - is DashboardHomeEvent.OpenToolDetails -> - onEvent(DashboardEvent.OpenToolDetails(it.tool)) - } - } - ) - + Page.HOME, Page.FAVORITE_TOOLS, Page.ALL_TOOLS -> { CircuitContent( screen = when (page) { + Page.HOME -> HomeScreen Page.FAVORITE_TOOLS -> AllFavoritesScreen Page.ALL_TOOLS -> ToolsScreen else -> error("Page $page is not converted to Circuit yet") @@ -157,6 +142,10 @@ internal fun DashboardLayout(onEvent: (DashboardEvent) -> Unit, viewModel: Dashb onNavEvent = { when (it) { is NavEvent.GoTo -> when (val screen = it.screen) { + AllFavoritesScreen -> { + saveableStateHolder.removeState(Page.FAVORITE_TOOLS) + viewModel.updateCurrentPage(Page.FAVORITE_TOOLS, false) + } is IntentScreen -> onEvent(DashboardEvent.OpenIntent(screen.intent)) is ToolDetailsScreen -> onEvent( DashboardEvent.OpenToolDetails( @@ -165,6 +154,9 @@ internal fun DashboardLayout(onEvent: (DashboardEvent) -> Unit, viewModel: Dashb ) ) } + is NavEvent.ResetRoot -> when (it.newRoot) { + ToolsScreen -> viewModel.updateCurrentPage(Page.ALL_TOOLS) + } else -> Unit } }, diff --git a/app/src/main/kotlin/org/cru/godtools/ui/dashboard/home/HomeLayout.kt b/app/src/main/kotlin/org/cru/godtools/ui/dashboard/home/HomeLayout.kt index fe964472b3..431db7efb1 100644 --- a/app/src/main/kotlin/org/cru/godtools/ui/dashboard/home/HomeLayout.kt +++ b/app/src/main/kotlin/org/cru/godtools/ui/dashboard/home/HomeLayout.kt @@ -21,9 +21,7 @@ import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue -import androidx.compose.runtime.key import androidx.compose.runtime.rememberUpdatedState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -31,111 +29,19 @@ import androidx.compose.ui.graphics.RectangleShape import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp -import androidx.lifecycle.viewmodel.compose.viewModel -import java.util.Locale -import org.cru.godtools.BuildConfig +import com.slack.circuit.codegen.annotations.CircuitInject +import dagger.hilt.components.SingletonComponent import org.cru.godtools.R -import org.cru.godtools.analytics.model.OpenAnalyticsActionEvent.Companion.ACTION_OPEN_LESSON -import org.cru.godtools.analytics.model.OpenAnalyticsActionEvent.Companion.ACTION_OPEN_TOOL -import org.cru.godtools.analytics.model.OpenAnalyticsActionEvent.Companion.ACTION_OPEN_TOOL_DETAILS -import org.cru.godtools.analytics.model.OpenAnalyticsActionEvent.Companion.SOURCE_FAVORITE -import org.cru.godtools.analytics.model.OpenAnalyticsActionEvent.Companion.SOURCE_FEATURED -import org.cru.godtools.model.Tool import org.cru.godtools.ui.banner.Banners import org.cru.godtools.ui.dashboard.home.HomeScreen.UiEvent import org.cru.godtools.ui.dashboard.home.HomeScreen.UiState import org.cru.godtools.ui.tools.LessonToolCard import org.cru.godtools.ui.tools.SquareToolCard -import org.cru.godtools.ui.tools.ToolCard -import org.cru.godtools.ui.tools.ToolCardEvent -import org.cru.godtools.ui.tools.toolViewModels private val PADDING_HORIZONTAL = 16.dp -internal sealed interface DashboardHomeEvent { - open class OpenTool(val tool: String?, val type: Tool.Type?, val lang1: Locale?, val lang2: Locale? = null) : - DashboardHomeEvent { - constructor(event: ToolCardEvent) : this(event.tool, event.toolType, event.lang1, event.lang2) - } - open class OpenToolDetails(val tool: String?) : DashboardHomeEvent { - constructor(event: ToolCardEvent.OpenToolDetails) : this(event.tool) - } - class OpenLesson(event: ToolCardEvent) : OpenTool(event.tool, Tool.Type.LESSON, event.lang1) - data object ViewAllFavorites : DashboardHomeEvent - data object ViewAllTools : DashboardHomeEvent -} - -@Composable -internal fun HomeContent(onEvent: (DashboardHomeEvent) -> Unit, viewModel: HomeViewModel = viewModel()) { - val favoriteTools by viewModel.favoriteTools.collectAsState() - - val state = UiState( - banner = viewModel.banner.collectAsState().value, - spotlightLessons = viewModel.spotlightLessons.collectAsState().value.mapNotNull { lesson -> - key(lesson) { - lateinit var lessonState: ToolCard.State - lessonState = toolViewModels[lesson.code ?: return@mapNotNull null, lesson].toState { - when (it) { - ToolCard.Event.Click -> { - viewModel.recordOpenClickInAnalytics(ACTION_OPEN_LESSON, lesson.code, SOURCE_FEATURED) - onEvent( - DashboardHomeEvent.OpenLesson( - ToolCardEvent.Click( - lessonState.tool?.code, - lessonState.tool?.type, - lessonState.translation?.languageCode - ) - ) - ) - } - - else -> if (BuildConfig.DEBUG) error("$it is currently unsupported for Lesson Cards") - } - } - lessonState - } - }, - favoriteTools = favoriteTools.orEmpty().take(5).mapNotNull { tool -> - key(tool.code) { - val toolViewModel = toolViewModels[tool.code ?: return@mapNotNull null, tool] - lateinit var toolState: ToolCard.State - toolState = toolViewModel.toState { - when (it) { - ToolCard.Event.Click, ToolCard.Event.OpenTool -> { - viewModel.recordOpenClickInAnalytics(ACTION_OPEN_TOOL, tool.code, SOURCE_FAVORITE) - onEvent( - DashboardHomeEvent.OpenTool( - ToolCardEvent.Click( - tool = tool.code, - type = tool.type, - lang1 = toolState.translation?.languageCode, - ) - ) - ) - } - ToolCard.Event.OpenToolDetails -> { - viewModel.recordOpenClickInAnalytics(ACTION_OPEN_TOOL_DETAILS, tool.code, SOURCE_FAVORITE) - onEvent(DashboardHomeEvent.OpenToolDetails(tool.code)) - } - ToolCard.Event.PinTool -> toolViewModel.pinTool() - ToolCard.Event.UnpinTool -> toolViewModel.unpinTool() - } - } - toolState - } - }, - favoriteToolsLoaded = favoriteTools != null, - ) { - when (it) { - UiEvent.ViewAllFavorites -> onEvent(DashboardHomeEvent.ViewAllFavorites) - UiEvent.ViewAllTools -> onEvent(DashboardHomeEvent.ViewAllTools) - } - } - - HomeLayout(state) -} - @Composable +@CircuitInject(HomeScreen::class, SingletonComponent::class) internal fun HomeLayout(state: UiState, modifier: Modifier = Modifier) { val banner by rememberUpdatedState(state.banner) val favoriteToolsLoaded by rememberUpdatedState(state.favoriteToolsLoaded) diff --git a/app/src/main/kotlin/org/cru/godtools/ui/dashboard/home/HomeViewModel.kt b/app/src/main/kotlin/org/cru/godtools/ui/dashboard/home/HomeViewModel.kt deleted file mode 100644 index 2591728b45..0000000000 --- a/app/src/main/kotlin/org/cru/godtools/ui/dashboard/home/HomeViewModel.kt +++ /dev/null @@ -1,45 +0,0 @@ -package org.cru.godtools.ui.dashboard.home - -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import dagger.hilt.android.lifecycle.HiltViewModel -import java.util.Locale -import javax.inject.Inject -import kotlinx.coroutines.flow.SharingStarted -import kotlinx.coroutines.flow.map -import kotlinx.coroutines.flow.stateIn -import org.cru.godtools.analytics.model.OpenAnalyticsActionEvent -import org.cru.godtools.base.Settings -import org.cru.godtools.db.repository.ToolsRepository -import org.cru.godtools.tutorial.PageSet -import org.cru.godtools.ui.banner.BannerType -import org.greenrobot.eventbus.EventBus - -@HiltViewModel -class HomeViewModel @Inject constructor( - private val eventBus: EventBus, - settings: Settings, - toolsRepository: ToolsRepository -) : ViewModel() { - val banner = settings.isFeatureDiscoveredFlow(Settings.FEATURE_TUTORIAL_FEATURES) - .map { featureTutorial -> - when { - !featureTutorial && PageSet.FEATURES.supportsLocale(Locale.getDefault()) -> BannerType.TUTORIAL_FEATURES - else -> null - } - } - .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null) - - val spotlightLessons = toolsRepository.getLessonsFlow() - .map { it.filter { !it.isHidden && it.isSpotlight } } - .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), emptyList()) - - val favoriteTools = toolsRepository.getFavoriteToolsFlow() - .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null) - - // region Analytics - fun recordOpenClickInAnalytics(action: String, tool: String?, source: String) { - eventBus.post(OpenAnalyticsActionEvent(action, tool, source)) - } - // endregion Analytics -}