Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions app/src/main/java/tv/trakt/trakt/TraktApplication.kt
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ import tv.trakt.trakt.core.summary.shows.di.showDetailsModule
import tv.trakt.trakt.core.sync.di.syncModule
import tv.trakt.trakt.core.trivia.di.triviaModule
import tv.trakt.trakt.core.userprofile.di.userProfileModule
import tv.trakt.trakt.helpers.editscreen.di.editScreenModule
import tv.trakt.trakt.helpers.player.di.youTubePlayerModule
import java.util.concurrent.TimeUnit.MINUTES
import tv.trakt.trakt.common.R as RCommon
Expand Down Expand Up @@ -189,6 +190,7 @@ internal class TraktApplication : Application() {
userProfileModule,
youTubePlayerModule,
shareModule,
editScreenModule,
)
}
}
Expand Down
110 changes: 67 additions & 43 deletions app/src/main/java/tv/trakt/trakt/core/discover/DiscoverScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ import tv.trakt.trakt.core.discover.sections.recommended.DiscoverRecommendedView
import tv.trakt.trakt.core.discover.sections.trending.DiscoverTrendingView
import tv.trakt.trakt.core.filters.GlobalFiltersSheet
import tv.trakt.trakt.helpers.ScreenHeaderState
import tv.trakt.trakt.helpers.editscreen.EditScreenSheet
import tv.trakt.trakt.helpers.editscreen.data.model.EditScreenKey
import tv.trakt.trakt.helpers.editscreen.data.model.EditScreenKey.DiscoverAnticipated
import tv.trakt.trakt.helpers.editscreen.data.model.EditScreenKey.DiscoverPopular
import tv.trakt.trakt.helpers.editscreen.data.model.EditScreenKey.DiscoverRecommended
import tv.trakt.trakt.helpers.editscreen.data.model.EditScreenKey.DiscoverTrending
import tv.trakt.trakt.helpers.rememberHeaderState
import tv.trakt.trakt.ui.components.ScrollableBackdropImage
import tv.trakt.trakt.ui.components.headerbar.HeaderBar
Expand All @@ -61,6 +67,7 @@ internal fun DiscoverScreen(
val state by viewModel.state.collectAsStateWithLifecycle()

var filtersSheet by remember { mutableStateOf(false) }
var sectionsSheet by remember { mutableStateOf(false) }

DiscoverScreen(
state = state,
Expand All @@ -71,16 +78,19 @@ internal fun DiscoverScreen(
onMoreAnticipatedClick = onNavigateToAllAnticipated,
onMoreRecommendedClick = onNavigateToAllRecommended,
onVipClick = onNavigateToVip,
onFiltersClick = {
filtersSheet = true
},
onFiltersClick = { filtersSheet = true },
onEditScreenClick = { sectionsSheet = true },
)

GlobalFiltersSheet(
active = filtersSheet,
onDismiss = {
filtersSheet = false
},
onDismiss = { filtersSheet = false },
)

EditScreenSheet(
active = sectionsSheet,
enabledValues = EditScreenKey.DiscoverKeys,
onDismiss = { sectionsSheet = false },
)
}

Expand All @@ -96,6 +106,7 @@ private fun DiscoverScreen(
onMoreRecommendedClick: () -> Unit = {},
onVipClick: () -> Unit = {},
onFiltersClick: () -> Unit = {},
onEditScreenClick: () -> Unit = {},
) {
val activity = LocalActivity.current
val customThemeEnabled = (activity as? MainActivity)?.customThemeConfig?.enabled == true
Expand Down Expand Up @@ -147,32 +158,36 @@ private fun DiscoverScreen(
verticalArrangement = spacedBy(TraktTheme.spacing.mainSectionVerticalSpace),
contentPadding = listPadding,
) {
item {
DiscoverTrendingView(
viewModel = koinViewModel {
parametersOf(customThemeEnabled)
},
collection = state.collection,
headerPadding = sectionPadding,
contentPadding = sectionPadding,
onShowClick = onShowClick,
onMovieClick = onMovieClick,
onMoreClick = onMoreTrendingClick,
)
if (state.visibility?.get(DiscoverTrending) == true) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using != false instead of == true ensures that during the initial load (when state.visibility is null before the DataStore Flow emits), the sections default to being visible. This prevents a jarring blank screen flicker on startup. Please apply this pattern to all visibility checks across all screens.

Suggested change
if (state.visibility?.get(DiscoverTrending) == true) {
if (state.visibility?.get(DiscoverTrending) != false) {

item {
DiscoverTrendingView(
viewModel = koinViewModel {
parametersOf(customThemeEnabled)
},
collection = state.collection,
headerPadding = sectionPadding,
contentPadding = sectionPadding,
onShowClick = onShowClick,
onMovieClick = onMovieClick,
onMoreClick = onMoreTrendingClick,
)
}
}

item {
DiscoverAnticipatedView(
viewModel = koinViewModel {
parametersOf(customThemeEnabled)
},
collection = state.collection,
headerPadding = sectionPadding,
contentPadding = sectionPadding,
onShowClick = onShowClick,
onMovieClick = onMovieClick,
onMoreClick = onMoreAnticipatedClick,
)
if (state.visibility?.get(DiscoverAnticipated) == true) {
item {
DiscoverAnticipatedView(
viewModel = koinViewModel {
parametersOf(customThemeEnabled)
},
collection = state.collection,
headerPadding = sectionPadding,
contentPadding = sectionPadding,
onShowClick = onShowClick,
onMovieClick = onMovieClick,
onMoreClick = onMoreAnticipatedClick,
)
}
}

if (state.user.user != null && !state.user.user.isVip) {
Expand All @@ -184,21 +199,26 @@ private fun DiscoverScreen(
}
}

item {
DiscoverPopularView(
viewModel = koinViewModel {
parametersOf(customThemeEnabled)
},
collection = state.collection,
headerPadding = sectionPadding,
contentPadding = sectionPadding,
onShowClick = onShowClick,
onMovieClick = onMovieClick,
onMoreClick = onMorePopularClick,
)
if (state.visibility?.get(DiscoverPopular) == true) {
item {
DiscoverPopularView(
viewModel = koinViewModel {
parametersOf(customThemeEnabled)
},
collection = state.collection,
headerPadding = sectionPadding,
contentPadding = sectionPadding,
onShowClick = onShowClick,
onMovieClick = onMovieClick,
onMoreClick = onMorePopularClick,
)
}
}

if (state.user.isAuthenticated) {
if (
state.user.isAuthenticated &&
state.visibility?.get(DiscoverRecommended) == true
) {
item {
DiscoverRecommendedView(
viewModel = koinViewModel {
Expand All @@ -221,6 +241,7 @@ private fun DiscoverScreen(
isScrolledToTop = isScrolledToTop,
onVipClick = onVipClick,
onFiltersClick = onFiltersClick,
onEditScreenClick = onEditScreenClick,
)
}
}
Expand All @@ -232,6 +253,7 @@ private fun ScreenHeader(
isScrolledToTop: Boolean,
onVipClick: () -> Unit,
onFiltersClick: () -> Unit,
onEditScreenClick: () -> Unit,
) {
val userState = remember(state.user) {
val loadingDone = state.user.loading == Done
Expand All @@ -244,8 +266,10 @@ private fun ScreenHeader(
showLogin = userState.first && !userState.second,
showVip = userState.second && state.user.user?.isVip == false,
showFilters = true,
showEditScreen = true,
onVipClick = onVipClick,
onFilterClick = onFiltersClick,
onEditScreenClick = onEditScreenClick,
modifier = Modifier.offset {
IntOffset(0, headerState.connection.barOffset.fastRoundToInt())
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package tv.trakt.trakt.core.discover

import androidx.compose.runtime.Immutable
import kotlinx.collections.immutable.ImmutableMap
import tv.trakt.trakt.common.helpers.LoadingState
import tv.trakt.trakt.common.model.User
import tv.trakt.trakt.core.user.UserCollectionState
import tv.trakt.trakt.helpers.editscreen.data.model.EditScreenKey

@Immutable
internal data class DiscoverState(
val visibility: ImmutableMap<EditScreenKey, Boolean>? = null,
val collection: UserCollectionState = UserCollectionState.Default,
val user: UserState = UserState(),
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package tv.trakt.trakt.core.discover

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.collections.immutable.toImmutableMap
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
Expand All @@ -16,20 +17,25 @@ import tv.trakt.trakt.common.firebase.analytics.Analytics
import tv.trakt.trakt.common.helpers.LoadingState
import tv.trakt.trakt.core.discover.DiscoverState.UserState
import tv.trakt.trakt.core.user.CollectionStateProvider
import tv.trakt.trakt.helpers.editscreen.data.EditScreenManager
import tv.trakt.trakt.helpers.editscreen.data.model.EditScreenKey.Companion.DiscoverKeys

@OptIn(FlowPreview::class)
internal class DiscoverViewModel(
private val sessionManager: SessionManager,
private val editScreenManager: EditScreenManager,
private val collectionStateProvider: CollectionStateProvider,
analytics: Analytics,
) : ViewModel() {
private val initialState = DiscoverState()

private val userState = MutableStateFlow(initialState.user)
private val visibilityState = MutableStateFlow(initialState.visibility)

init {
observeUser()
observeData()
observeVisibility()

analytics.logScreenView(
screenName = "discover",
Expand All @@ -55,13 +61,25 @@ internal class DiscoverViewModel(
.launchIn(viewModelScope)
}

private fun observeVisibility() {
editScreenManager.observe(DiscoverKeys)
.onEach { visibility ->
visibilityState.update {
visibility.toImmutableMap()
}
}
.launchIn(viewModelScope)
}

val state = combine(
userState,
visibilityState,
collectionStateProvider.stateFlow,
) { s1, s2 ->
) { s1, s2, s3 ->
DiscoverState(
user = s1,
collection = s2,
visibility = s2,
collection = s3,
)
}.stateIn(
scope = viewModelScope,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ internal val discoverModule = module {
sessionManager = get(),
analytics = get(),
collectionStateProvider = get(),
editScreenManager = get(),
)
}

Expand All @@ -87,7 +88,6 @@ internal val discoverModule = module {
viewModel { (customTheme: Boolean) ->
DiscoverTrendingViewModel(
filterManager = get(),
collapsingManager = get(),
getTrendingShowsUseCase = when {
customTheme -> get(named("customTrendingShowsUseCase"))
else -> get(named("defaultTrendingShowsUseCase"))
Expand All @@ -102,7 +102,6 @@ internal val discoverModule = module {
viewModel { (customTheme: Boolean) ->
DiscoverAnticipatedViewModel(
filterManager = get(),
collapsingManager = get(),
getAnticipatedShowsUseCase = when {
customTheme -> get(named("customAnticipatedShowsUseCase"))
else -> get(named("defaultAnticipatedShowsUseCase"))
Expand All @@ -117,7 +116,6 @@ internal val discoverModule = module {
viewModel { (customTheme: Boolean) ->
DiscoverPopularViewModel(
filterManager = get(),
collapsingManager = get(),
getPopularShowsUseCase = when {
customTheme -> get(named("customPopularShowsUseCase"))
else -> get(named("defaultPopularShowsUseCase"))
Expand All @@ -132,7 +130,6 @@ internal val discoverModule = module {
viewModel { (customTheme: Boolean) ->
DiscoverRecommendedViewModel(
filterManager = get(),
collapsingManager = get(),
getRecommendedShowsUseCase = when {
customTheme -> get(named("customRecommendedShowsUseCase"))
else -> get(named("defaultRecommendedShowsUseCase"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import tv.trakt.trakt.core.discover.model.DiscoverItem
internal data class DiscoverAnticipatedState(
val items: ImmutableList<DiscoverItem>? = null,
val filter: GlobalFilter? = null,
val collapsed: Boolean? = null,
val loading: LoadingState = LoadingState.Idle,
val error: Exception? = null,
)
Loading