diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 98bb49b..30fe8c1 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -18,8 +18,6 @@ * along with NewPlayer. If not, see . */ -import java.util.regex.Pattern.compile - plugins { alias(libs.plugins.android.application) alias(libs.plugins.jetbrains.kotlin.android) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 5cc8d32..1cf495e 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -6,6 +6,7 @@ + android:theme="@style/Theme.NewPlayer"> ? + fun initUIState(instanceState: Bundle) fun preparePlayer() fun play() fun pause() @@ -99,6 +103,7 @@ class VideoPlayerViewModelImpl @Inject constructor( override val events: SharedFlow = mutableEvent + override val uiState = mutableUiState.asStateFlow() override var listener: VideoPlayerViewModel.Listener? = null @@ -143,6 +148,22 @@ class VideoPlayerViewModelImpl @Inject constructor( }) } + @RequiresApi(Build.VERSION_CODES.TIRAMISU) + override fun initUIState(instanceState: Bundle) { + + val uiState = + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) + instanceState.getParcelable(VIDEOPLAYER_UI_STATE, VideoPlayerUIState::class.java) + else + instanceState.getParcelable(VIDEOPLAYER_UI_STATE) + + uiState?.let { uiState -> + mutableUiState.update { + uiState + } + } + } + override fun preparePlayer() { if (player.playbackState == Player.STATE_IDLE) { player.prepare() @@ -172,19 +193,12 @@ class VideoPlayerViewModelImpl @Inject constructor( viewModelScope.launch { mutableEvent.emit(VideoPlayerViewModel.Events.SwitchToEmbeddedView) } - //mutableUiState.update { - // it.copy(fullscreen = false) - //} } override fun switchToFullscreen() { viewModelScope.launch { mutableEvent.emit(VideoPlayerViewModel.Events.SwitchToFullscreen) } - //mutableUiState.update { - // it.copy(fullscreen = true) - //} - //listener?.switchToFullscreen() } companion object { @@ -194,6 +208,10 @@ class VideoPlayerViewModelImpl @Inject constructor( override var listener: VideoPlayerViewModel.Listener? = null override val events: SharedFlow? = null + override fun initUIState(instanceState: Bundle) { + println("dummy impl") + } + override fun preparePlayer() { println("dummy impl") } diff --git a/app/src/main/java/net/newpipe/newplayer/ui/VideoPlayerUI.kt b/app/src/main/java/net/newpipe/newplayer/ui/VideoPlayerUI.kt index 7d7711f..1b5d552 100644 --- a/app/src/main/java/net/newpipe/newplayer/ui/VideoPlayerUI.kt +++ b/app/src/main/java/net/newpipe/newplayer/ui/VideoPlayerUI.kt @@ -20,8 +20,15 @@ package net.newpipe.newplayer.ui +import android.app.Activity import android.content.Intent import android.view.SurfaceView +import androidx.activity.compose.BackHandler +import androidx.activity.compose.ManagedActivityResultLauncher +import androidx.activity.compose.rememberLauncherForActivityResult +import androidx.activity.result.ActivityResult +import androidx.activity.result.IntentSenderRequest +import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.Surface import androidx.compose.runtime.Composable @@ -40,6 +47,7 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.viewinterop.AndroidView import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleEventObserver +import androidx.lifecycle.VIEW_MODEL_STORE_OWNER_KEY import kotlinx.coroutines.flow.collectLatest import net.newpipe.newplayer.VideoPlayerActivity import net.newpipe.newplayer.model.VIDEOPLAYER_UI_STATE @@ -72,19 +80,27 @@ fun VideoPlayerUI( } } + BackHandler { + closeFullscreen(viewModel, activity!!) + } + + val fullscreenLauncher = + rememberLauncherForActivityResult( + contract = ActivityResultContracts.StartActivityForResult() + ) { result -> + println("gurken returned for result") + viewModel.initUIState(result.data?.extras!!) + } + LaunchedEffect(key1 = Unit) { viewModel.events?.collectLatest { event -> when (event) { VideoPlayerViewModel.Events.SwitchToEmbeddedView -> { - activity?.finish() + closeFullscreen(viewModel, activity!!) } VideoPlayerViewModel.Events.SwitchToFullscreen -> { - val fullscreen_activity_intent = - Intent(activity!!.findActivity(), VideoPlayerActivity::class.java) - fullscreen_activity_intent.putExtra(VIDEOPLAYER_UI_STATE, viewModel.uiState.value) - activity.startActivity(fullscreen_activity_intent) - + openFullscreen(viewModel, activity!!, fullscreenLauncher) } } } @@ -97,14 +113,18 @@ fun VideoPlayerUI( AndroidView( modifier = Modifier.fillMaxSize(), factory = { context -> - SurfaceView(context).also { - viewModel.player?.setVideoSurfaceView(it) + SurfaceView(context).also { view -> + viewModel.player?.setVideoSurfaceView(view) } - }, update = { + }, update = { view -> when (lifecycle) { Lifecycle.Event.ON_PAUSE -> { println("gurken state on pause") - viewModel.pause() + } + + Lifecycle.Event.ON_RESUME -> { + println("gurken resume") + viewModel.player?.setVideoSurfaceView(view) } else -> Unit @@ -112,7 +132,7 @@ fun VideoPlayerUI( }) val isPlaying = viewModel.player!!.isPlaying - println("is Player playing: $isPlaying") + VideoPlayerControllerUI( isPlaying = uiState.playing, fullscreen = uiState.fullscreen, @@ -126,6 +146,28 @@ fun VideoPlayerUI( } } +fun closeFullscreen(viewModel: VideoPlayerViewModel, activity: Activity) { + val return_fullscreen_intent = Intent() + var uiState = viewModel.uiState.value + uiState.fullscreen = false + return_fullscreen_intent.putExtra(VIDEOPLAYER_UI_STATE, uiState) + activity.setResult(0, return_fullscreen_intent) + activity.finish() +} + +fun openFullscreen( + viewModel: VideoPlayerViewModel, + activity: Activity, + fullscreenLauncher: ManagedActivityResultLauncher +) { + val fullscreen_activity_intent = + Intent(activity!!.findActivity(), VideoPlayerActivity::class.java) + var uiState = viewModel.uiState.value + uiState.fullscreen = true + fullscreen_activity_intent.putExtra(VIDEOPLAYER_UI_STATE, uiState) + fullscreenLauncher.launch(fullscreen_activity_intent) +} + @Preview(device = "spec:width=1080px,height=700px,dpi=440,orientation=landscape") @Composable fun PlayerUIPreviewEmbeded() { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 641a8fc..1921ebe 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -19,7 +19,7 @@ [versions] agp = "8.5.0" -kotlin = "2.0.0" +kotlin = "2.0.20-Beta2" coreKtx = "1.13.1" junit = "4.13.2" junitVersion = "1.2.1" @@ -30,16 +30,16 @@ androidx = "1.9.0" constraintlayout = "2.1.4" material3 = "1.2.1" uiTooling = "1.6.8" -materialIconsExtendedAndroid = "1.7.0-beta04" +materialIconsExtendedAndroid = "1.7.0-beta05" media3Ui = "1.4.0-beta01" hiltAndroid = "2.51.1" hiltCompiler = "1.2.0" hiltNavigationCompose = "1.2.0" lifecycleViewmodelCompose = "2.8.3" -kspVersion = "1.9.0-1.0.13" +kspVersion = "2.0.20-Beta2-1.0.23" fragmentKtx = "1.8.1" lifecycleRuntimeKtx = "2.8.3" -composeBom = "2024.04.01" +composeBom = "2024.06.01" kotlinParcelize = "2.0.20-Beta2" [libraries] @@ -65,7 +65,7 @@ androidx-lifecycle-viewmodel-compose = { group = "androidx.lifecycle", name = "l androidx-foundation = { group = "androidx.compose.foundation", name = "foundation", version.ref = "uiTooling" } androidx-fragment-ktx = { group = "androidx.fragment", name = "fragment-ktx", version.ref = "fragmentKtx" } androidx-lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycleRuntimeKtx" } -androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" } +androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version = "2024.06.00" } androidx-ui = { group = "androidx.compose.ui", name = "ui" } androidx-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" } androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" }