Skip to content

Commit

Permalink
feat: no picture mode for tv.
Browse files Browse the repository at this point in the history
  • Loading branch information
oxyroid committed Jan 14, 2024
1 parent 3c49df7 commit 6b1cdd5
Show file tree
Hide file tree
Showing 7 changed files with 416 additions and 286 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,10 @@ class PlaylistRepositoryImpl @Inject constructor(
}
var count = 0

val needToBeInsertedstreams = streams.filterNot { it.url in existedUrls }
val total = needToBeInsertedstreams.size
val needToBeInsertedStreams = streams.filterNot { it.url in existedUrls }
val total = needToBeInsertedStreams.size

needToBeInsertedstreams.forEach { stream ->
needToBeInsertedStreams.forEach { stream ->
streamDao.insert(stream)
count++
onProcess(count / total * 100)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ internal fun PlaylistRoute(
contentPadding = contentPadding,
onFavorite = { id, target -> viewModel.onEvent(PlaylistEvent.Favourite(id, target)) },
ban = { id -> viewModel.onEvent(PlaylistEvent.Ban(id)) },
onSavePicture = {
savePicture = {
if (writeExternalPermissionRequired && writeExternalPermissionState.status is PermissionStatus.Denied) {
writeExternalPermissionState.launchPermissionRequest()
return@PlaylistScreen
Expand Down Expand Up @@ -163,7 +163,7 @@ private fun PlaylistScreen(
onScrollUp: () -> Unit,
onFavorite: (streamId: Int, target: Boolean) -> Unit,
ban: (streamId: Int) -> Unit,
onSavePicture: (streamId: Int) -> Unit,
savePicture: (streamId: Int) -> Unit,
createShortcut: (streamId: Int) -> Unit,
contentPadding: PaddingValues,
modifier: Modifier = Modifier
Expand Down Expand Up @@ -214,7 +214,7 @@ private fun PlaylistScreen(
onSort = onSort,
onFavorite = onFavorite,
ban = ban,
onSavePicture = onSavePicture,
onSavePicture = savePicture,
createShortcut = createShortcut,
modifier = modifier
)
Expand All @@ -231,7 +231,7 @@ private fun PlaylistScreen(
sort = sort,
onFavorite = onFavorite,
ban = ban,
onSavePicture = onSavePicture,
savePicture = savePicture,
createShortcut = createShortcut,
modifier = modifier
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
package com.m3u.features.playlist.components

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.Refresh
import androidx.compose.material.icons.rounded.Search
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.Dp
import androidx.tv.material3.Icon
import androidx.tv.material3.LocalContentColor
import androidx.tv.material3.MaterialTheme
import androidx.tv.material3.Text
import coil.compose.AsyncImage
import coil.request.ImageRequest
import com.m3u.core.wrapper.Message
import com.m3u.data.database.model.Stream
import com.m3u.features.playlist.R
import com.m3u.material.components.Background
import com.m3u.material.components.IconButton
import com.m3u.material.model.LocalSpacing
import com.m3u.ui.AppSnackHost

@Composable
internal fun ImmersiveBackground(
title: String,
stream: Stream?,
message: Message,
maxBrowserHeight: Dp,
onRefresh: () -> Unit,
modifier: Modifier = Modifier,
noPictureMode: Boolean = false,
) {
val context = LocalContext.current
val spacing = LocalSpacing.current
Background {
Box(modifier) {
if (stream != null) {
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.TopEnd
) {
if (!noPictureMode) {
val request = remember(stream.cover) {
ImageRequest.Builder(context)
.data(stream.cover.orEmpty())
.crossfade(1600)
.build()
}
AsyncImage(
model = request,
contentScale = ContentScale.Crop,
contentDescription = stream.title,
modifier = Modifier
.fillMaxWidth(0.78f)
.aspectRatio(16 / 9f)
)
Icon(
painter = painterResource(R.drawable.scrim),
contentDescription = null,
tint = MaterialTheme.colorScheme.background,
modifier = Modifier
.fillMaxWidth(0.78f)
.aspectRatio(16 / 9f)
)
}

Column(
Modifier
.align(Alignment.BottomCenter)
.padding(spacing.medium)
.fillMaxWidth()
) {
Text(
text = stream.title,
style = MaterialTheme.typography.headlineLarge,
fontWeight = FontWeight.ExtraBold,
maxLines = 1
)
Text(
text = stream.url,
style = MaterialTheme.typography.headlineMedium,
color = LocalContentColor.current.copy(0.68f),
maxLines = 1
)
Spacer(
modifier = Modifier.heightIn(min = maxBrowserHeight)
)
}
}
}
Column(
modifier = Modifier.padding(spacing.medium),
verticalArrangement = Arrangement.spacedBy(spacing.medium)
) {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(spacing.small),
) {
Text(
text = title,
style = MaterialTheme.typography.headlineLarge,
fontWeight = FontWeight.ExtraBold,
maxLines = 1
)
Spacer(modifier = Modifier.weight(1f))
IconButton(
icon = Icons.Rounded.Search,
contentDescription = "search",
onClick = { /*TODO*/ }
)
IconButton(
icon = Icons.Rounded.Refresh,
contentDescription = "refresh",
onClick = onRefresh
)
}
AppSnackHost(
message = message,
)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
package com.m3u.features.playlist.components

import androidx.activity.compose.BackHandler
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.rounded.Shortcut
import androidx.compose.material.icons.rounded.Delete
import androidx.compose.material.icons.rounded.Favorite
import androidx.compose.material.icons.rounded.Image
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.tv.material3.DrawerState
import androidx.tv.material3.DrawerValue
import androidx.tv.material3.Icon
import androidx.tv.material3.ModalNavigationDrawer
import androidx.tv.material3.NavigationDrawerItem
import androidx.tv.material3.Text
import com.m3u.data.database.model.Stream
import com.m3u.i18n.R
import com.m3u.material.model.LocalSpacing

@Composable
internal fun PlaylistDrawer(
drawerState: DrawerState,
stream: Stream?,
onFavorite: (streamId: Int, target: Boolean) -> Unit,
ban: (streamId: Int) -> Unit,
createShortcut: (streamId: Int) -> Unit,
savePicture: (streamId: Int) -> Unit,
modifier: Modifier = Modifier,
content: @Composable () -> Unit
) {
val spacing = LocalSpacing.current

BackHandler(drawerState.currentValue == DrawerValue.Open) {
drawerState.setValue(DrawerValue.Closed)
}

ModalNavigationDrawer(
drawerState = drawerState,
drawerContent = {
AnimatedVisibility(hasFocus) {
Column(
Modifier
.fillMaxHeight()
.padding(spacing.medium),
horizontalAlignment = Alignment.Start,
verticalArrangement = Arrangement.spacedBy(spacing.small)
) {
NavigationDrawerItem(
selected = false,
onClick = {
stream?.let { stream ->
onFavorite(stream.id, !stream.favourite)
}
},
leadingContent = {
Icon(
imageVector = Icons.Rounded.Favorite,
contentDescription = "favorite"
)
},
content = {
Text(
stringResource(
if (stream?.favourite == true) R.string.feat_playlist_dialog_favourite_cancel_title
else R.string.feat_playlist_dialog_favourite_title
).uppercase()
)
},
)

NavigationDrawerItem(
selected = false,
onClick = {
stream?.let { ban(it.id) }
drawerState.setValue(DrawerValue.Closed)
},
leadingContent = {
Icon(
imageVector = Icons.Rounded.Delete,
contentDescription = "ban"
)
},
content = {
Text(stringResource(R.string.feat_playlist_dialog_mute_title).uppercase())
}
)
NavigationDrawerItem(
selected = false,
onClick = {
stream?.let { createShortcut(it.id) }
drawerState.setValue(DrawerValue.Closed)
},
leadingContent = {
Icon(
imageVector = Icons.AutoMirrored.Rounded.Shortcut,
contentDescription = "shortcut"
)
},
content = {
Text(stringResource(R.string.feat_playlist_dialog_create_shortcut_title).uppercase())
}
)

NavigationDrawerItem(
selected = false,
onClick = {
stream?.let { savePicture(it.id) }
drawerState.setValue(DrawerValue.Closed)
},
leadingContent = {
Icon(
imageVector = Icons.Rounded.Image,
contentDescription = "save-cover"
)
},
content = {
Text(stringResource(R.string.feat_playlist_dialog_save_picture_title).uppercase())
}
)
}
}
},
modifier = modifier,
content = content
)
}
Loading

0 comments on commit 6b1cdd5

Please sign in to comment.