Thorium-android-app/app/src/main/java/net/schueller/peertube/feature_video/presentation/video_play/VideoPlayScreen.kt

217 lines
8.4 KiB
Kotlin

package net.schueller.peertube.feature_video.presentation.video_play
import android.content.res.Configuration
import android.widget.Toast
import androidx.compose.animation.*
import androidx.compose.animation.core.LinearEasing
import androidx.compose.animation.core.tween
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavController
import androidx.paging.compose.LazyPagingItems
import androidx.paging.compose.collectAsLazyPagingItems
import androidx.paging.compose.itemsIndexed
import com.google.accompanist.systemuicontroller.SystemUiController
import com.google.accompanist.systemuicontroller.rememberSystemUiController
import kotlinx.coroutines.flow.collectLatest
import net.schueller.peertube.feature_server_address.presentation.address_add_edit.AddEditAddressViewModel
import net.schueller.peertube.feature_video.domain.model.Video
import net.schueller.peertube.feature_video.presentation.video_list.components.VideoListItem
import net.schueller.peertube.feature_video.presentation.video_play.components.VideoDescriptionScreen
import net.schueller.peertube.feature_video.presentation.video_play.components.VideoMeta
import net.schueller.peertube.feature_video.presentation.video_play.components.VideoScreen
import net.schueller.peertube.feature_video.presentation.video_play.player.ExoPlayerHolder
import net.schueller.peertube.presentation.Screen
var enteringPIPMode: Boolean = false
@ExperimentalMaterialApi
@Composable
fun VideoPlayScreen(
exoPlayerHolder: ExoPlayerHolder,
navController: NavController,
viewModel: VideoPlayViewModel = hiltViewModel()
) {
val state = viewModel.state.value
val context = LocalContext.current
var descriptionVisible by remember { mutableStateOf(false) }
// Show toasts
LaunchedEffect(key1 = true) {
viewModel.eventFlow.collectLatest { event ->
when(event) {
is VideoPlayViewModel.UiEvent.ShowToast -> {
Toast.makeText(
context,
event.message,
event.length
).show()
}
is VideoPlayViewModel.UiEvent.ShowDescription -> {
descriptionVisible = true
}
is VideoPlayViewModel.UiEvent.HideDescription -> {
descriptionVisible = false
}
}
}
}
// Related Videos
val lazyRelatedVideoItems: LazyPagingItems<Video> = viewModel.relatedVideos.collectAsLazyPagingItems()
Box(modifier = Modifier
.fillMaxSize()
.background(Color.Black)) {
val configuration = LocalConfiguration.current
state.video?.let { video ->
val systemUiController: SystemUiController = rememberSystemUiController()
when(configuration.orientation) {
Configuration.ORIENTATION_LANDSCAPE -> {
// Full screen
systemUiController.isStatusBarVisible = false
systemUiController.isNavigationBarVisible = false
systemUiController.isSystemBarsVisible = false
VideoScreen(exoPlayerHolder, video)
} else -> {
systemUiController.isStatusBarVisible = true
systemUiController.isNavigationBarVisible = true
systemUiController.isSystemBarsVisible = true
// TODO: Swipe video down
val squareSize = 200.dp
val swipeableState = rememberSwipeableState(initialValue = 0)
val sizePx = with(LocalDensity.current) { squareSize.toPx() }
val anchors = mapOf(sizePx to 1, 0f to 0)
Column(
modifier = Modifier
.fillMaxWidth()
.swipeable(
state = swipeableState,
anchors = anchors,
thresholds = { _, _ -> FractionalThreshold(0.3f) },
orientation = Orientation.Vertical,
)
) {
VideoScreen(exoPlayerHolder, video)
Box() {
LazyColumn(
modifier = Modifier.fillMaxSize()
) {
item {
VideoMeta(video)
}
itemsIndexed(lazyRelatedVideoItems) { _, video ->
if (video != null) {
VideoListItem(
video = video,
onItemClick = {
navController.navigate(Screen.VideoPlayScreen.route + "/${video.uuid}")
}
)
}
}
}
Column(Modifier.fillMaxSize()) {
AnimatedVisibility(
visible = descriptionVisible,
modifier = Modifier.fillMaxSize(),
enter = slideInVertically(
initialOffsetY = { it }, // it == fullWidth
animationSpec = tween(
durationMillis = 150,
easing = LinearEasing
)
),
exit = slideOutVertically(
targetOffsetY = { it },
animationSpec = tween(
durationMillis = 150,
easing = LinearEasing
)
)
) {
VideoDescriptionScreen()
}
}
}
}
}
}
}
if(state.error.isNotBlank()) {
Text(
text = state.error,
color = MaterialTheme.colors.error,
textAlign = TextAlign.Center,
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 20.dp)
.align(Alignment.Center)
)
}
if(state.isLoading) {
CircularProgressIndicator(modifier = Modifier.align(Alignment.Center))
}
}
// BackHandler(enabled = true) {
// Log.v("back", "back pressed")
//
// enterPIPMode(activity)
// }
}
//fun enterPIPMode(activity: Activity): Boolean {
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// if (enteringPIPMode) {
// return true
// }
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
// ) {
// enteringPIPMode = true
// val params = PictureInPictureParams.Builder().build()
// try {
// activity.enterPictureInPictureMode(params)
// return true
// } catch (ex: IllegalStateException) {
// // pass
// enteringPIPMode = false
// }
// }
// }
// return false
//}