@@ -3,29 +3,29 @@ package dev.silenium.multimedia.compose
33import androidx.compose.foundation.background
44import androidx.compose.foundation.isSystemInDarkTheme
55import androidx.compose.foundation.layout.*
6- import androidx.compose.foundation.rememberScrollState
7- import androidx.compose.foundation.verticalScroll
6+ import androidx.compose.foundation.lazy.LazyColumn
7+ import androidx.compose.foundation.lazy.rememberLazyListState
88import androidx.compose.material.MaterialTheme
99import androidx.compose.material.Text
1010import androidx.compose.material.darkColors
1111import androidx.compose.material.lightColors
1212import androidx.compose.runtime.*
13+ import androidx.compose.ui.Alignment
1314import androidx.compose.ui.Modifier
15+ import androidx.compose.ui.focus.FocusRequester
1416import androidx.compose.ui.unit.dp
1517import androidx.compose.ui.window.Window
1618import androidx.compose.ui.window.awaitApplication
1719import dev.silenium.multimedia.compose.player.VideoSurfaceWithControls
1820import dev.silenium.multimedia.compose.player.rememberVideoPlayer
1921import dev.silenium.multimedia.compose.util.LocalFullscreenProvider
2022import dev.silenium.multimedia.core.annotation.InternalMultimediaApi
21- import kotlinx.coroutines.Dispatchers
22- import kotlinx.coroutines.delay
23- import kotlinx.coroutines.isActive
24- import kotlinx.coroutines.withContext
23+ import kotlinx.coroutines.*
2524import java.nio.file.Files
2625import kotlin.io.path.absolutePathString
2726import kotlin.io.path.outputStream
2827import kotlin.time.Duration.Companion.milliseconds
28+ import kotlin.time.Duration.Companion.seconds
2929
3030@OptIn(InternalMultimediaApi ::class )
3131@Composable
@@ -38,55 +38,110 @@ fun App() {
3838 }
3939 videoFile.apply { toFile().deleteOnExit() }
4040 }
41- val player = rememberVideoPlayer()
4241 var ready by remember { mutableStateOf(false ) }
42+ val coroutineScope = rememberCoroutineScope()
43+ val player = rememberVideoPlayer(
44+ onInitialized = {
45+ ready = true
46+ },
47+ )
48+ DisposableEffect (Unit ) {
49+ onDispose {
50+ ready = false
51+ }
52+ }
53+ LaunchedEffect (file) {
54+ withContext(Dispatchers .Default ) {
55+ while (! ready && isActive) delay(10 .milliseconds)
56+ player.command(" loadfile" , file.absolutePathString())
57+ }
58+ }
59+ val fullscreen = LocalFullscreenProvider .current.isFullscreen
60+ val lazyState = rememberLazyListState()
4361 BoxWithConstraints (
44- modifier = Modifier .fillMaxSize(). background(MaterialTheme .colors.background)
62+ modifier = Modifier .background(MaterialTheme .colors.background).fillMaxSize( )
4563 ) {
46- val fullscreen = LocalFullscreenProvider .current.isFullscreen
47- val scroll = rememberScrollState()
48- Column (
49- modifier = Modifier .verticalScroll(scroll, ! LocalFullscreenProvider .current.isFullscreen).fillMaxSize()
50- ) {
51- VideoSurfaceWithControls (
52- player = player,
53- modifier = Modifier .let {
54- when {
55- fullscreen -> it.size(this @BoxWithConstraints.maxWidth, this @BoxWithConstraints.maxHeight)
56- else -> it.requiredSizeIn(
57- this @BoxWithConstraints.minWidth,
58- this @BoxWithConstraints.minHeight,
59- this @BoxWithConstraints.maxWidth,
60- this @BoxWithConstraints.maxHeight,
61- )
62- }
63- },
64- showStats = true ,
65- onInitialized = {
66- ready = true
67- }
64+ var visible by remember { mutableStateOf(true ) }
65+ var wasPaused by remember { mutableStateOf(" no" ) }
66+ LaunchedEffect (Unit ) {
67+ while (isActive) {
68+ delay(2 .seconds)
69+ visible = ! visible
70+ }
71+ }
72+ val modifier = when {
73+ fullscreen -> Modifier .size(
74+ this @BoxWithConstraints.maxWidth,
75+ this @BoxWithConstraints.maxHeight
6876 )
69- Text (
70- text = " This is a test video player" ,
71- modifier = Modifier .padding(16 .dp),
72- style = MaterialTheme .typography.h6,
73- color = MaterialTheme .colors.onBackground
77+
78+ else -> Modifier .requiredSizeIn(
79+ this @BoxWithConstraints.minWidth,
80+ this @BoxWithConstraints.minHeight,
81+ this @BoxWithConstraints.maxWidth,
82+ this @BoxWithConstraints.maxHeight,
7483 )
7584 }
76- var previousPosition by remember { mutableStateOf(0 ) }
77- LaunchedEffect (fullscreen) {
78- if (fullscreen) {
79- previousPosition = scroll.value
80- scroll.scrollTo(0 )
85+ LazyColumn (
86+ modifier = modifier,
87+ state = lazyState,
88+ userScrollEnabled = ! fullscreen,
89+ ) {
90+ if (visible) {
91+ item(key = " video" , contentType = " video" ) {
92+ VideoSurfaceWithControls (
93+ player = player,
94+ modifier = Modifier .fillParentMaxSize().animateItem(),
95+ showStats = true ,
96+ controlFocusRequester = remember { FocusRequester () },
97+ )
98+ DisposableEffect (Unit ) {
99+ coroutineScope.launch {
100+ println (" Setting pause to $wasPaused " )
101+ player.setProperty(" pause" , wasPaused)
102+ }
103+
104+ onDispose {
105+ coroutineScope.launch {
106+ wasPaused = player.getProperty<String >(" pause" ).getOrNull() ? : " no"
107+ player.setProperty(" pause" , " yes" )
108+ }
109+ }
110+ }
111+ }
81112 } else {
82- scroll.scrollTo(previousPosition)
113+ item(key = " video" , contentType = " empty" ) {
114+ Box (
115+ modifier = Modifier .fillParentMaxSize().animateItem(),
116+ ) {
117+ Text (
118+ text = " Video player is not visible" ,
119+ modifier = Modifier .padding(16 .dp).align(Alignment .Center ),
120+ style = MaterialTheme .typography.h6,
121+ color = MaterialTheme .colors.onBackground
122+ )
123+ }
124+ }
125+ }
126+ item(key = " text" , contentType = " text" ) {
127+ Text (
128+ text = " This is a test video player" ,
129+ modifier = Modifier .padding(16 .dp),
130+ style = MaterialTheme .typography.h6,
131+ color = MaterialTheme .colors.onBackground
132+ )
83133 }
84134 }
85135 }
86- LaunchedEffect (file) {
87- withContext(Dispatchers .Default ) {
88- while (! ready && isActive) delay(10 .milliseconds)
89- player.command(" loadfile" , file.absolutePathString())
136+ var previousIndex by remember { mutableStateOf(0 ) }
137+ var previousOffset by remember { mutableStateOf(0 ) }
138+ LaunchedEffect (fullscreen) {
139+ if (fullscreen) {
140+ previousIndex = lazyState.firstVisibleItemIndex
141+ previousOffset = lazyState.firstVisibleItemScrollOffset
142+ lazyState.scrollToItem(0 )
143+ } else {
144+ lazyState.scrollToItem(previousIndex, previousOffset)
90145 }
91146 }
92147 }
0 commit comments