Skip to content

Commit

Permalink
fix: disable programme gallery if the playlist is xtream vod or serie…
Browse files Browse the repository at this point in the history
…s, or the playlist is m3u but not refer to any epg.
  • Loading branch information
oxyroid committed May 18, 2024
1 parent 75bf610 commit b690b0a
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 57 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ import com.m3u.material.components.mask.MaskInterceptor
import com.m3u.material.components.mask.MaskState
import com.m3u.material.components.mask.rememberMaskState
import com.m3u.material.components.rememberPullPanelLayoutState
import com.m3u.material.ktx.isTelevision
import com.m3u.material.ktx.plus
import com.m3u.ui.Player
import com.m3u.ui.helper.LocalHelper
Expand All @@ -78,8 +77,6 @@ fun StreamRoute(
val context = LocalContext.current
val configuration = LocalConfiguration.current

val tv = isTelevision()

val playerState: PlayerState by viewModel.playerState.collectAsStateWithLifecycle()
val stream by viewModel.stream.collectAsStateWithLifecycle()
val playlist by viewModel.playlist.collectAsStateWithLifecycle()
Expand All @@ -92,6 +89,9 @@ fun StreamRoute(

val volume by viewModel.volume.collectAsStateWithLifecycle()
val isSeriesPlaylist by viewModel.isSeriesPlaylist.collectAsStateWithLifecycle()
val isProgrammeSupported by viewModel.isProgrammeSupported.collectAsStateWithLifecycle(
initialValue = false
)

val neighboring = viewModel.neighboring.collectAsLazyPagingItems()
val programmes = viewModel.programmes.collectAsLazyPagingItems()
Expand Down Expand Up @@ -188,7 +188,8 @@ fun StreamRoute(
playlistTitle = playlist?.title.orEmpty(),
streamId = stream?.id ?: -1,
isPanelExpanded = isPanelExpanded,
isSeriesPlaylist = isSeriesPlaylist,
isChannelsSupported = !isSeriesPlaylist,
isProgrammeSupported = isProgrammeSupported,
channels = neighboring,
programmes = programmes,
programmeRange = programmeRange
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@ import com.m3u.core.architecture.dispatcher.M3uDispatchers.Main
import com.m3u.core.architecture.logger.Logger
import com.m3u.core.architecture.logger.Profiles
import com.m3u.core.architecture.logger.install
import com.m3u.data.database.model.DataSource
import com.m3u.data.database.model.Playlist
import com.m3u.data.database.model.Programme
import com.m3u.data.database.model.ProgrammeRange
import com.m3u.data.database.model.Stream
import com.m3u.data.database.model.epgUrlsOrXtreamXmlUrl
import com.m3u.data.database.model.isSeries
import com.m3u.data.database.model.isVod
import com.m3u.data.repository.playlist.PlaylistRepository
import com.m3u.data.repository.programme.ProgrammeRepository
import com.m3u.data.repository.stream.StreamRepository
Expand Down Expand Up @@ -78,15 +80,24 @@ class StreamViewModel @Inject constructor(
internal val stream: StateFlow<Stream?> = playerManager.stream
internal val playlist: StateFlow<Playlist?> = playerManager.playlist

internal val isSeriesPlaylist: StateFlow<Boolean> = playerManager
.playlist
internal val isSeriesPlaylist: StateFlow<Boolean> = playlist
.map { it?.isSeries ?: false }
.stateIn(
scope = viewModelScope,
initialValue = false,
started = SharingStarted.WhileSubscribed(5_000L)
)

internal val isProgrammeSupported: Flow<Boolean> = playlist.map {
it ?: return@map false
if (it.isSeries || it.isVod) return@map false
when (it.source) {
DataSource.Xtream -> true
DataSource.M3U -> it.epgUrls.isNotEmpty()
else -> false
}
}

internal val tracks: StateFlow<Map<Int, List<Format>>> = playerManager
.tracks
.map { all ->
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
package com.m3u.features.stream.components

import android.view.KeyEvent
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.basicMarquee
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListScope
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.items
Expand All @@ -24,9 +26,13 @@ import androidx.compose.material3.surfaceColorAtElevation
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusDirection
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.input.key.onKeyEvent
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.paging.compose.LazyPagingItems
Expand All @@ -39,6 +45,7 @@ import com.m3u.data.database.model.Stream
import com.m3u.data.service.MediaCommand
import com.m3u.material.components.Background
import com.m3u.material.ktx.isTelevision
import com.m3u.material.ktx.thenIf
import com.m3u.material.model.LocalSpacing
import com.m3u.material.shape.AbsoluteSmoothCornerShape
import com.m3u.ui.FontFamilies
Expand All @@ -54,98 +61,100 @@ internal fun PlayerPanel(
title: String,
playlistTitle: String,
streamId: Int,
isSeriesPlaylist: Boolean,
isChannelsSupported: Boolean,
isProgrammeSupported: Boolean,
isPanelExpanded: Boolean,
channels: LazyPagingItems<Stream>,
programmes: LazyPagingItems<Programme>,
programmeRange: ProgrammeRange,
modifier: Modifier = Modifier
) {
val configuration = LocalConfiguration.current
val useVertical = configuration.screenWidthDp < configuration.screenHeightDp
val spacing = LocalSpacing.current

val useVertical = configuration.screenWidthDp < configuration.screenHeightDp
Background(
shape = if (useVertical) RectangleShape else AbsoluteSmoothCornerShape(
cornerRadiusTL = spacing.medium,
cornerRadiusBL = spacing.medium
)
) {
Column(
verticalArrangement = Arrangement.spacedBy(spacing.small),
modifier = modifier
.fillMaxSize()
.thenIf(!useVertical) {
Modifier.statusBarsPadding()
}
.padding(vertical = spacing.medium)
) {
AnimatedVisibility(
visible = isPanelExpanded && useVertical,
modifier = Modifier.padding(horizontal = spacing.medium)
) {
Text(
text = title.trim(),
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.ExtraBold,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
modifier = Modifier.basicMarquee()
)
}
AnimatedVisibility(
visible = isPanelExpanded && useVertical,
enter = fadeIn(),
exit = fadeOut(),
modifier = Modifier.padding(horizontal = spacing.medium)
) {
Text(
text = playlistTitle.trim().uppercase(),
style = MaterialTheme.typography.labelMedium,
maxLines = 1,
color = LocalContentColor.current.copy(0.54f),
fontFamily = FontFamilies.LexendExa,
overflow = TextOverflow.Ellipsis,
modifier = Modifier.basicMarquee()
)
Column {
Text(
text = title.trim(),
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.ExtraBold,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
modifier = Modifier.basicMarquee()
)
Text(
text = playlistTitle.trim().uppercase(),
style = MaterialTheme.typography.labelMedium,
maxLines = 1,
color = LocalContentColor.current.copy(0.54f),
fontFamily = FontFamilies.LexendExa,
overflow = TextOverflow.Ellipsis,
modifier = Modifier.basicMarquee()
)
}
}

if (!isSeriesPlaylist) {
if (isChannelsSupported) {
ChannelGallery(
// TODO
value = ChannelGalleryValue.PagingChannel(channels, streamId),
isPanelExpanded = isPanelExpanded
isPanelExpanded = isPanelExpanded,
vertical = !isProgrammeSupported
)
}

ProgramGuide(
isPanelExpanded = isPanelExpanded,
programmes = programmes,
range = programmeRange,
modifier = Modifier
.fillMaxWidth()
.weight(1f)
)
if (isProgrammeSupported) {
ProgramGuide(
isPanelExpanded = isPanelExpanded,
programmes = programmes,
range = programmeRange,
modifier = Modifier
.fillMaxWidth()
.weight(1f)
)
}
}
}
}

@OptIn(ExperimentalComposeUiApi::class)
@Composable
private fun ChannelGallery(
value: ChannelGalleryValue,
isPanelExpanded: Boolean,
modifier: Modifier = Modifier
modifier: Modifier = Modifier,
vertical: Boolean = false
) {
val spacing = LocalSpacing.current
val lazyListState = rememberLazyListState()
val tv = isTelevision()

ScrollToCurrentEffect(
value = value,
isPanelExpanded = isPanelExpanded,
lazyListState = lazyListState
)

LazyRow(
state = lazyListState,
horizontalArrangement = Arrangement.spacedBy(spacing.medium),
contentPadding = PaddingValues(spacing.medium),
modifier = modifier
) {
val content: LazyListScope.() -> Unit = {
when (value) {
is ChannelGalleryValue.PagingChannel -> {
val channels = value.channels
Expand All @@ -168,6 +177,37 @@ private fun ChannelGallery(
}
}
}
if (!vertical) {
LazyRow(
state = lazyListState,
horizontalArrangement = Arrangement.spacedBy(spacing.medium),
contentPadding = PaddingValues(spacing.medium),
modifier = modifier,
content = content
)
} else {
val focusManager = LocalFocusManager.current
LazyColumn(
state = lazyListState,
verticalArrangement = Arrangement.spacedBy(spacing.medium),
contentPadding = PaddingValues(spacing.medium),
modifier = modifier
.fillMaxWidth()
.thenIf(tv) {
Modifier.onKeyEvent {
when (it.nativeKeyEvent.keyCode) {
KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.KEYCODE_DPAD_RIGHT -> {
focusManager.moveFocus(FocusDirection.Exit)
true
}

else -> false
}
}
},
content = content
)
}
}

private sealed class ChannelGalleryValue {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,6 @@ fun PullPanelLayout(
targetValue = offset,
label = "offset"
)
LaunchedEffect(enabled) {
if (!enabled) {
state.collapse()
}
}
SubcomposeLayout(
modifier
.draggable(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ import com.m3u.material.ktx.InteractionType
import com.m3u.material.ktx.interactionBorder
import com.m3u.material.ktx.isTelevision
import androidx.tv.material3.MaterialTheme as TvMaterialTheme
import androidx.tv.material3.Text as TvText

@Composable
fun TextField(
Expand Down Expand Up @@ -376,7 +377,7 @@ private fun TvTextFieldImpl(
) {
innerTextField()
if (value.isEmpty()) {
androidx.tv.material3.Text(
TvText(
modifier = Modifier.graphicsLayer { alpha = 0.6f },
text = placeholder,
style = TvMaterialTheme.typography.titleSmall
Expand Down

0 comments on commit b690b0a

Please sign in to comment.