remove FullScreen Activity

This commit is contained in:
Christian Schabesberger 2024-07-19 16:44:04 +02:00
parent be54682b93
commit b111b77e04
8 changed files with 118 additions and 92 deletions

View File

@ -45,6 +45,9 @@ class VideoPlayerView : FrameLayout {
get() = videoPlayerFragment.minLayoutRatio
set(value) {videoPlayerFragment.minLayoutRatio = value}
var fullScreenToggleListener: FullScreenToggleListener?
set(value) {videoPlayerFragment.fullScreenToggleListener = value}
get() = videoPlayerFragment.fullScreenToggleListener
@JvmOverloads
constructor(
@ -66,4 +69,8 @@ class VideoPlayerView : FrameLayout {
}
}
}
interface FullScreenToggleListener {
fun fullscreenToggle(turnOn: Boolean)
}
}

View File

@ -1,27 +0,0 @@
package net.newpipe.newplayer.internal
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.activity.viewModels
import dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint
class VideoPlayerActivity : ComponentActivity() {
private val viewModel: net.newpipe.newplayer.internal.model.VideoPlayerViewModel by viewModels<net.newpipe.newplayer.internal.model.VideoPlayerViewModelImpl>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModel.initUIState(intent.extras!!)
enableEdgeToEdge()
setContent {
net.newpipe.newplayer.internal.ui.theme.VideoPlayerTheme {
net.newpipe.newplayer.internal.ui.VideoPlayerUI(viewModel = viewModel)
}
}
}
}

View File

@ -36,6 +36,7 @@ import androidx.fragment.app.viewModels
import dagger.hilt.android.AndroidEntryPoint
import net.newpipe.newplayer.NewPlayer
import net.newpipe.newplayer.R
import net.newpipe.newplayer.VideoPlayerView
import net.newpipe.newplayer.internal.model.VideoPlayerViewModel
import net.newpipe.newplayer.internal.model.VideoPlayerViewModelImpl
import net.newpipe.newplayer.internal.ui.VideoPlayerUI
@ -50,6 +51,8 @@ class VideoPlayerFragment() : Fragment() {
private var currentVideoRatio = 0F
private lateinit var composeView: ComposeView
var fullScreenToggleListener: VideoPlayerView.FullScreenToggleListener? = null
var minLayoutRatio = 4F / 3F
set(value) {
if (value <= 0 && maxLayoutRatio < minLayoutRatio)
@ -100,7 +103,10 @@ class VideoPlayerFragment() : Fragment() {
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
setContent {
VideoPlayerTheme {
VideoPlayerUI(viewModel = viewModel)
VideoPlayerUI(viewModel = viewModel,
{fullscreenOn ->
fullScreenToggleListener?.fullscreenToggle(fullscreenOn)
})
}
}
}

View File

@ -63,7 +63,6 @@ interface VideoPlayerViewModel {
val player: Player?
val uiState: StateFlow<VideoPlayerUIState>
var listener: Listener?
val events: SharedFlow<Events>?
fun initUIState(instanceState: Bundle)
fun play()
@ -93,12 +92,10 @@ class VideoPlayerViewModelImpl @Inject constructor(
// private
private val mutableUiState = MutableStateFlow(VideoPlayerUIState.DEFAULT)
private val mutableEvent = MutableSharedFlow<VideoPlayerViewModel.Events>()
private var current_video_size = VideoSize.DEFAULT
//interface
override val uiState = mutableUiState.asStateFlow()
override val events: SharedFlow<VideoPlayerViewModel.Events> = mutableEvent
override var listener: VideoPlayerViewModel.Listener? = null
override val player:Player?
@ -106,6 +103,7 @@ class VideoPlayerViewModelImpl @Inject constructor(
init {
installExoPlayer()
println("gurken reinit ViewModel")
}
private fun installExoPlayer() {
@ -180,15 +178,14 @@ class VideoPlayerViewModelImpl @Inject constructor(
}
override fun switchToEmbeddedView() {
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)
}
}
@ -198,7 +195,7 @@ class VideoPlayerViewModelImpl @Inject constructor(
override val player: Player? = null
override val uiState = MutableStateFlow(VideoPlayerUIState.DEFAULT)
override var listener: VideoPlayerViewModel.Listener? = null
override val events: SharedFlow<VideoPlayerViewModel.Events>? = null
override fun initUIState(instanceState: Bundle) {
println("dummy impl")

View File

@ -22,6 +22,7 @@ package net.newpipe.newplayer.internal.ui
import android.app.Activity
import android.content.Intent
import android.content.pm.ActivityInfo
import android.view.SurfaceView
import androidx.activity.compose.BackHandler
import androidx.activity.compose.ManagedActivityResultLauncher
@ -46,17 +47,16 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.viewinterop.AndroidView
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import kotlinx.coroutines.flow.collectLatest
import net.newpipe.newplayer.internal.VideoPlayerActivity
import net.newpipe.newplayer.internal.model.VIDEOPLAYER_UI_STATE
import net.newpipe.newplayer.internal.model.VideoPlayerViewModel
import net.newpipe.newplayer.internal.model.VideoPlayerViewModelImpl
import net.newpipe.newplayer.internal.ui.theme.VideoPlayerTheme
import net.newpipe.newplayer.internal.utils.LockScreenOrientation
import net.newpipe.newplayer.internal.utils.findActivity
@Composable
fun VideoPlayerUI(
viewModel: VideoPlayerViewModel,
fullscreenToggled: (Boolean) -> Unit
) {
val uiState by viewModel.uiState.collectAsState()
@ -67,6 +67,8 @@ fun VideoPlayerUI(
val activity = LocalContext.current.findActivity()
val lifecycleOwner = LocalLifecycleOwner.current
// Prepare stuff for the SurfaceView to which the video will be rendered
DisposableEffect(lifecycleOwner) {
val observer = LifecycleEventObserver { _, event ->
lifecycle = event
@ -78,8 +80,12 @@ fun VideoPlayerUI(
}
}
BackHandler {
closeFullscreen(viewModel, activity!!)
// Handle Fullscreen/Embedded view transition
if(uiState.fullscreen) {
BackHandler {
//closeFullscreen(viewModel, activity!!)
}
}
val fullscreenLauncher =
@ -90,20 +96,20 @@ fun VideoPlayerUI(
viewModel.initUIState(result.data?.extras!!)
}
LaunchedEffect(key1 = Unit) {
viewModel.events?.collectLatest { event ->
when (event) {
VideoPlayerViewModel.Events.SwitchToEmbeddedView -> {
closeFullscreen(viewModel, activity!!)
}
LaunchedEffect(key1 = uiState.fullscreen) {
println("gurken launch fullscreen: ${uiState.fullscreen}")
}
VideoPlayerViewModel.Events.SwitchToFullscreen -> {
openFullscreen(viewModel, activity!!, fullscreenLauncher)
}
}
// Set Screen Rotation
if(uiState.fullscreen) {
if(uiState.contentRatio < 1) {
LockScreenOrientation(orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
} else {
LockScreenOrientation(orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)
}
}
// Set UI
Surface(
modifier = Modifier.fillMaxSize(),
color = Color.Black
@ -124,8 +130,6 @@ fun VideoPlayerUI(
}
})
val isPlaying = viewModel.player?.isPlaying ?: false
VideoPlayerControllerUI(
isPlaying = uiState.playing,
fullscreen = uiState.fullscreen,
@ -139,32 +143,10 @@ 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<Intent, ActivityResult>
) {
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() {
VideoPlayerTheme {
VideoPlayerUI(viewModel = VideoPlayerViewModelImpl.dummy)
VideoPlayerUI(viewModel = VideoPlayerViewModelImpl.dummy, {})
}
}

View File

@ -23,9 +23,14 @@ package net.newpipe.newplayer.internal.utils
import android.app.Activity
import android.content.Context
import android.content.ContextWrapper
import android.content.Intent
import androidx.activity.compose.ManagedActivityResultLauncher
import androidx.activity.result.ActivityResult
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.ui.platform.LocalContext
import net.newpipe.newplayer.internal.model.VIDEOPLAYER_UI_STATE
import net.newpipe.newplayer.internal.model.VideoPlayerViewModel
@Composable
fun LockScreenOrientation(orientation: Int) {

View File

@ -43,16 +43,47 @@ class MainActivity : AppCompatActivity() {
setContentView(R.layout.activity_main)
val video_view = findViewById<VideoPlayerView>(R.id.new_player_video_view)
video_view.fullScreenToggleListener = object : VideoPlayerView.FullScreenToggleListener {
override fun fullscreenToggle(turnOn: Boolean) {
if (turnOn) {
println("gurken blub")
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
v.setPadding(
0, 0, 0, 0
)
insets
}
} else {
println("gurken blab")
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(
systemBars.left,
systemBars.top,
systemBars.right,
systemBars.bottom
)
insets
}
}
}
}
newPlayer.playWhenReady = true
newPlayer.setStream(getString(R.string.ccc_chromebooks_video))
//TODO: This is a dirty hack. Fix this later on
if (getResources().configuration.orientation != Configuration.ORIENTATION_LANDSCAPE) {
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(
systemBars.left,
systemBars.top,
systemBars.right,
systemBars.bottom
)
insets
}
}

View File

@ -28,15 +28,40 @@
tools:context=".MainActivity">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/player_frament_view"
android:layout_width="match_parent"
<LinearLayout
android:id="@+id/player_column"
android:layout_width="0dp"
android:layout_height="match_parent"
app:layout_constraintEnd_toEndOf="parent"
android:orientation="vertical"
app:layout_constraintBaseline_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/hw_view"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="parent"
android:name="net.newpipe.newplayer.internal.VideoPlayerFragment"
/>
app:layout_constraintTop_toTopOf="parent">
<net.newpipe.newplayer.VideoPlayerView
android:id="@+id/new_player_video_view"
android:name="net.newpipe.newplayer.VideoPlayerFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="50dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</LinearLayout>
<TextView
android:id="@+id/hw_view"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/player_column"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>