fix project layout and don't use fullscreen acitvity anymore

This commit is contained in:
Christian Schabesberger 2024-07-22 15:44:10 +02:00
parent b111b77e04
commit 356744814c
15 changed files with 237 additions and 342 deletions

View File

@ -20,34 +20,21 @@
package net.newpipe.newplayer package net.newpipe.newplayer
import android.app.Activity
import android.content.Context import android.content.Context
import android.util.AttributeSet import android.util.AttributeSet
import android.view.LayoutInflater import android.view.LayoutInflater
import android.widget.FrameLayout import android.widget.FrameLayout
import androidx.appcompat.app.AppCompatActivity import androidx.compose.ui.platform.ComposeView
import androidx.fragment.app.FragmentContainer import androidx.compose.ui.platform.ViewCompositionStrategy
import androidx.fragment.app.FragmentContainerView
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import net.newpipe.newplayer.internal.VideoPlayerFragment import net.newpipe.newplayer.model.VideoPlayerViewModel
import net.newpipe.newplayer.ui.VideoPlayerUI
import net.newpipe.newplayer.ui.theme.VideoPlayerTheme
@AndroidEntryPoint @AndroidEntryPoint
class VideoPlayerView : FrameLayout { class VideoPlayerView : FrameLayout {
val videoPlayerFragment:VideoPlayerFragment var viewModel: VideoPlayerViewModel? = null
var maxLayoutRatio: Float
get() = videoPlayerFragment.maxLayoutRatio
set(value) {videoPlayerFragment.maxLayoutRatio=value}
var minLayoutRatio: Float
get() = videoPlayerFragment.minLayoutRatio
set(value) {videoPlayerFragment.minLayoutRatio = value}
var fullScreenToggleListener: FullScreenToggleListener?
set(value) {videoPlayerFragment.fullScreenToggleListener = value}
get() = videoPlayerFragment.fullScreenToggleListener
@JvmOverloads @JvmOverloads
constructor( constructor(
@ -56,21 +43,16 @@ class VideoPlayerView : FrameLayout {
defStyleAttr: Int = 0 defStyleAttr: Int = 0
) : super(context, attrs, defStyleAttr) { ) : super(context, attrs, defStyleAttr) {
val view = LayoutInflater.from(context).inflate(R.layout.video_player_view, this) val view = LayoutInflater.from(context).inflate(R.layout.video_player_view, this)
val composeView = view.findViewById<ComposeView>(R.id.video_player_compose_view)
videoPlayerFragment = VideoPlayerFragment() composeView.apply {
when (context) { setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
is AppCompatActivity -> { setContent {
context.supportFragmentManager.beginTransaction() VideoPlayerTheme {
.add(R.id.video_player_fragment_container, videoPlayerFragment).commit() VideoPlayerUI(viewModel = viewModel)
} }
else -> {
throw Exception("The context that should host the NewPlayer Embedded VideoPlayerView is not an AppCompatActivity: $context")
} }
} }
}
interface FullScreenToggleListener {
fun fullscreenToggle(turnOn: Boolean)
} }
} }

View File

@ -1,125 +0,0 @@
/* NewPlayer
*
* @author Christian Schabesberger
*
* Copyright (C) NewPipe e.V. 2024 <code(at)newpipe-ev.de>
*
* NewPlayer is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* NewPlayer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NewPlayer. If not, see <http://www.gnu.org/licenses/>.
*/
package net.newpipe.newplayer.internal
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.platform.ViewCompositionStrategy
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsControllerCompat
import androidx.core.view.updateLayoutParams
import androidx.fragment.app.Fragment
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
import net.newpipe.newplayer.internal.ui.theme.VideoPlayerTheme
private const val TAG = "VideoPlayerFragment"
@AndroidEntryPoint
class VideoPlayerFragment() : Fragment() {
private val viewModel: VideoPlayerViewModel by viewModels<VideoPlayerViewModelImpl>()
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)
Log.e(
TAG,
"minLayoutRatio can not be 0 or smaller or bigger then maxLayoutRatio. Ignore: $value"
)
else {
field = value
updateViewRatio()
}
}
var maxLayoutRatio = 16F / 9F
set(value) {
if (value <= 0 && value < minLayoutRatio)
Log.e(
TAG,
"maxLayoutRatio can not be 0 smaller ans smaller then minLayoutRatio. Ignore: $value"
)
else {
field = value
updateViewRatio()
}
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val window = activity?.window!!
val insetsController = WindowCompat.getInsetsController(window, window.decorView)
insetsController.systemBarsBehavior =
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
val view = inflater.inflate(R.layout.video_player_framgent, container, false)
composeView = view.findViewById(R.id.player_copose_view)
viewModel.listener = object : VideoPlayerViewModel.Listener {
override fun requestUpdateLayoutRatio(videoRatio: Float) {
currentVideoRatio = videoRatio
updateViewRatio()
}
}
composeView.apply {
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
setContent {
VideoPlayerTheme {
VideoPlayerUI(viewModel = viewModel,
{fullscreenOn ->
fullScreenToggleListener?.fullscreenToggle(fullscreenOn)
})
}
}
}
return view
}
private fun updateViewRatio() {
if(this::composeView.isInitialized) {
composeView.updateLayoutParams<ConstraintLayout.LayoutParams> {
val ratio = currentVideoRatio.coerceIn(minLayoutRatio, maxLayoutRatio)
dimensionRatio = "$ratio:1"
}
}
}
}

View File

@ -1,152 +0,0 @@
/* NewPlayer
*
* @author Christian Schabesberger
*
* Copyright (C) NewPipe e.V. 2024 <code(at)newpipe-ev.de>
*
* NewPlayer is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* NewPlayer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NewPlayer. If not, see <http://www.gnu.org/licenses/>.
*/
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
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.ActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.viewinterop.AndroidView
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
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()
var lifecycle by remember {
mutableStateOf(Lifecycle.Event.ON_CREATE)
}
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
}
lifecycleOwner.lifecycle.addObserver(observer)
onDispose {
lifecycleOwner.lifecycle.removeObserver(observer)
}
}
// Handle Fullscreen/Embedded view transition
if(uiState.fullscreen) {
BackHandler {
//closeFullscreen(viewModel, activity!!)
}
}
val fullscreenLauncher =
rememberLauncherForActivityResult(
contract = ActivityResultContracts.StartActivityForResult()
) { result ->
println("gurken returned for result")
viewModel.initUIState(result.data?.extras!!)
}
LaunchedEffect(key1 = uiState.fullscreen) {
println("gurken launch fullscreen: ${uiState.fullscreen}")
}
// 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
) {
AndroidView(
modifier = Modifier.fillMaxSize(),
factory = { context ->
SurfaceView(context).also { view ->
viewModel.player?.setVideoSurfaceView(view)
}
}, update = { view ->
when (lifecycle) {
Lifecycle.Event.ON_RESUME -> {
viewModel.player?.setVideoSurfaceView(view)
}
else -> Unit
}
})
VideoPlayerControllerUI(
isPlaying = uiState.playing,
fullscreen = uiState.fullscreen,
play = viewModel::play,
pause = viewModel::pause,
prevStream = viewModel::prevStream,
nextStream = viewModel::nextStream,
switchToFullscreen = viewModel::switchToFullscreen,
switchToEmbeddedView = viewModel::switchToEmbeddedView
)
}
}
@Preview(device = "spec:width=1080px,height=700px,dpi=440,orientation=landscape")
@Composable
fun PlayerUIPreviewEmbeded() {
VideoPlayerTheme {
VideoPlayerUI(viewModel = VideoPlayerViewModelImpl.dummy, {})
}
}

View File

@ -18,7 +18,7 @@
* along with NewPlayer. If not, see <http://www.gnu.org/licenses/>. * along with NewPlayer. If not, see <http://www.gnu.org/licenses/>.
*/ */
package net.newpipe.newplayer.internal.model package net.newpipe.newplayer.model
import android.app.Application import android.app.Application
import android.os.Build import android.os.Build
@ -27,18 +27,14 @@ import android.os.Parcelable
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.viewModelScope
import androidx.media3.common.Player import androidx.media3.common.Player
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharedFlow
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch import net.newpipe.newplayer.utils.VideoSize
import net.newpipe.newplayer.internal.utils.VideoSize
import kotlinx.parcelize.Parcelize import kotlinx.parcelize.Parcelize
import net.newpipe.newplayer.NewPlayer import net.newpipe.newplayer.NewPlayer
@ -87,7 +83,6 @@ interface VideoPlayerViewModel {
class VideoPlayerViewModelImpl @Inject constructor( class VideoPlayerViewModelImpl @Inject constructor(
private val savedStateHandle: SavedStateHandle, private val savedStateHandle: SavedStateHandle,
application: Application, application: Application,
override var newPlayer: NewPlayer?
) : AndroidViewModel(application), VideoPlayerViewModel { ) : AndroidViewModel(application), VideoPlayerViewModel {
// private // private
@ -95,17 +90,18 @@ class VideoPlayerViewModelImpl @Inject constructor(
private var current_video_size = VideoSize.DEFAULT private var current_video_size = VideoSize.DEFAULT
//interface //interface
override var newPlayer: NewPlayer? = null
set(value) {
field = value
installExoPlayer()
}
override val uiState = mutableUiState.asStateFlow() override val uiState = mutableUiState.asStateFlow()
override var listener: VideoPlayerViewModel.Listener? = null override var listener: VideoPlayerViewModel.Listener? = null
override val player:Player? override val player:Player?
get() = newPlayer?.player get() = newPlayer?.player
init {
installExoPlayer()
println("gurken reinit ViewModel")
}
private fun installExoPlayer() { private fun installExoPlayer() {
player?.let { player -> player?.let { player ->
player.addListener(object : Player.Listener { player.addListener(object : Player.Listener {
@ -145,6 +141,11 @@ class VideoPlayerViewModelImpl @Inject constructor(
} }
} }
override fun onCleared() {
super.onCleared()
println("gurken viewmodel cleared")
}
@RequiresApi(Build.VERSION_CODES.TIRAMISU) @RequiresApi(Build.VERSION_CODES.TIRAMISU)
override fun initUIState(instanceState: Bundle) { override fun initUIState(instanceState: Bundle) {

View File

@ -18,7 +18,7 @@
* along with NewPlayer. If not, see <http://www.gnu.org/licenses/>. * along with NewPlayer. If not, see <http://www.gnu.org/licenses/>.
*/ */
package net.newpipe.newplayer.internal.ui package net.newpipe.newplayer.ui
import androidx.activity.compose.BackHandler import androidx.activity.compose.BackHandler
import androidx.compose.foundation.background import androidx.compose.foundation.background
@ -78,8 +78,8 @@ import androidx.compose.ui.unit.DpOffset
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import net.newpipe.newplayer.R import net.newpipe.newplayer.R
import net.newpipe.newplayer.internal.ui.theme.VideoPlayerTheme import net.newpipe.newplayer.ui.theme.VideoPlayerTheme
import net.newpipe.newplayer.internal.ui.theme.video_player_onSurface import net.newpipe.newplayer.ui.theme.video_player_onSurface
@Composable @Composable
fun VideoPlayerControllerUI( fun VideoPlayerControllerUI(
@ -392,7 +392,7 @@ fun PreviewBackgroundSurface(
} }
} }
@Preview(device = "spec:width=1080px,height=700px,dpi=440,orientation=landscape") @Preview(device = "spec:width=1080px,height=600px,dpi=440,orientation=landscape")
@Composable @Composable
fun VideoPlayerControllerUIPreviewEmbeded() { fun VideoPlayerControllerUIPreviewEmbeded() {
VideoPlayerTheme { VideoPlayerTheme {

View File

@ -0,0 +1,36 @@
package net.newpipe.newplayer.ui
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.width
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import net.newpipe.newplayer.ui.theme.VideoPlayerTheme
@Composable
fun VideoPlayerLoadingPlaceholder() {
Surface(
modifier = Modifier.fillMaxWidth().height(200.dp),
color = Color.Black
) {
Box {
CircularProgressIndicator(modifier = Modifier.width(64.dp).align((Alignment.Center)))
}
}
}
@Preview(device = "spec:width=1080px,height=600px,dpi=440,orientation=landscape")
@Composable
fun VideoPlayerLoaidingPlaceholderPreview() {
VideoPlayerTheme {
VideoPlayerLoadingPlaceholder()
}
}

View File

@ -0,0 +1,149 @@
/* NewPlayer
*
* @author Christian Schabesberger
*
* Copyright (C) NewPipe e.V. 2024 <code(at)newpipe-ev.de>
*
* NewPlayer is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* NewPlayer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NewPlayer. If not, see <http://www.gnu.org/licenses/>.
*/
package net.newpipe.newplayer.ui
import android.content.pm.ActivityInfo
import android.view.SurfaceView
import androidx.activity.compose.BackHandler
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.viewinterop.AndroidView
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import net.newpipe.newplayer.model.VideoPlayerViewModel
import net.newpipe.newplayer.model.VideoPlayerViewModelImpl
import net.newpipe.newplayer.ui.theme.VideoPlayerTheme
import net.newpipe.newplayer.utils.LockScreenOrientation
import net.newpipe.newplayer.utils.findActivity
@Composable
fun VideoPlayerUI(
viewModel: VideoPlayerViewModel?,
) {
if (viewModel?.player == null) {
VideoPlayerLoadingPlaceholder()
} else {
val uiState by viewModel.uiState.collectAsState()
var lifecycle by remember {
mutableStateOf(Lifecycle.Event.ON_CREATE)
}
val lifecycleOwner = LocalLifecycleOwner.current
// Prepare stuff for the SurfaceView to which the video will be rendered
DisposableEffect(lifecycleOwner) {
val observer = LifecycleEventObserver { _, event ->
lifecycle = event
}
lifecycleOwner.lifecycle.addObserver(observer)
onDispose {
lifecycleOwner.lifecycle.removeObserver(observer)
}
}
// Handle Fullscreen/Embedded view transition
if (uiState.fullscreen) {
BackHandler {
//closeFullscreen(viewModel, activity!!)
}
}
val fullscreenLauncher =
rememberLauncherForActivityResult(
contract = ActivityResultContracts.StartActivityForResult()
) { result ->
println("gurken returned for result")
viewModel.initUIState(result.data?.extras!!)
}
LaunchedEffect(key1 = uiState.fullscreen) {
println("gurken launch fullscreen: ${uiState.fullscreen}")
}
// 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
) {
AndroidView(
modifier = Modifier.fillMaxSize(),
factory = { context ->
SurfaceView(context).also { view ->
viewModel.player?.setVideoSurfaceView(view)
}
}, update = { view ->
when (lifecycle) {
Lifecycle.Event.ON_RESUME -> {
viewModel.player?.setVideoSurfaceView(view)
}
else -> Unit
}
})
VideoPlayerControllerUI(
isPlaying = uiState.playing,
fullscreen = uiState.fullscreen,
play = viewModel::play,
pause = viewModel::pause,
prevStream = viewModel::prevStream,
nextStream = viewModel::nextStream,
switchToFullscreen = viewModel::switchToFullscreen,
switchToEmbeddedView = viewModel::switchToEmbeddedView
)
}
}
}
@Preview(device = "spec:width=1080px,height=700px,dpi=440,orientation=landscape")
@Composable
fun PlayerUIPreviewEmbeded() {
VideoPlayerTheme {
VideoPlayerUI(viewModel = VideoPlayerViewModelImpl.dummy)
}
}

View File

@ -18,7 +18,7 @@
* along with NewPlayer. If not, see <http://www.gnu.org/licenses/>. * along with NewPlayer. If not, see <http://www.gnu.org/licenses/>.
*/ */
package net.newpipe.newplayer.internal.ui.theme package net.newpipe.newplayer.ui.theme
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color

View File

@ -18,7 +18,7 @@
* along with NewPlayer. If not, see <http://www.gnu.org/licenses/>. * along with NewPlayer. If not, see <http://www.gnu.org/licenses/>.
*/ */
package net.newpipe.newplayer.internal.ui.theme package net.newpipe.newplayer.ui.theme
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.darkColorScheme import androidx.compose.material3.darkColorScheme

View File

@ -18,7 +18,7 @@
* along with NewPlayer. If not, see <http://www.gnu.org/licenses/>. * along with NewPlayer. If not, see <http://www.gnu.org/licenses/>.
*/ */
package net.newpipe.newplayer.internal.ui.theme package net.newpipe.newplayer.ui.theme
import androidx.compose.material3.Typography import androidx.compose.material3.Typography
import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.TextStyle

View File

@ -1,4 +1,4 @@
package net.newpipe.newplayer.internal.utils package net.newpipe.newplayer.utils
data class VideoSize( data class VideoSize(
val width: Int, val width: Int,

View File

@ -18,19 +18,14 @@
* along with NewPlayer. If not, see <http://www.gnu.org/licenses/>. * along with NewPlayer. If not, see <http://www.gnu.org/licenses/>.
*/ */
package net.newpipe.newplayer.internal.utils package net.newpipe.newplayer.utils
import android.app.Activity import android.app.Activity
import android.content.Context import android.content.Context
import android.content.ContextWrapper 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.Composable
import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.DisposableEffect
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import net.newpipe.newplayer.internal.model.VIDEOPLAYER_UI_STATE
import net.newpipe.newplayer.internal.model.VideoPlayerViewModel
@Composable @Composable
fun LockScreenOrientation(orientation: Int) { fun LockScreenOrientation(orientation: Int) {

View File

@ -17,10 +17,8 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with NewPlayer. If not, see <http://www.gnu.org/licenses/>. along with NewPlayer. If not, see <http://www.gnu.org/licenses/>.
--> -->
<androidx.compose.ui.platform.ComposeView xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.fragment.app.FragmentContainerView xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/video_player_compose_view"
android:id="@+id/video_player_fragment_container"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content" />
android:minHeight="50dp" />

View File

@ -20,20 +20,25 @@
package net.newpipe.newplayer.testapp package net.newpipe.newplayer.testapp
import android.content.res.Configuration
import android.os.Bundle import android.os.Bundle
import androidx.activity.enableEdgeToEdge import androidx.activity.enableEdgeToEdge
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat
import androidx.lifecycle.viewmodel.compose.viewModel
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import net.newpipe.newplayer.NewPlayer import net.newpipe.newplayer.NewPlayer
import net.newpipe.newplayer.VideoPlayerView import net.newpipe.newplayer.VideoPlayerView
import net.newpipe.newplayer.model.VideoPlayerViewModel
import net.newpipe.newplayer.model.VideoPlayerViewModelImpl
import javax.inject.Inject import javax.inject.Inject
@AndroidEntryPoint @AndroidEntryPoint
class MainActivity : AppCompatActivity() { class MainActivity : AppCompatActivity() {
val videoPlayerViewModel: VideoPlayerViewModel by viewModels<VideoPlayerViewModelImpl>()
@Inject @Inject
lateinit var newPlayer: NewPlayer lateinit var newPlayer: NewPlayer
@ -43,7 +48,10 @@ class MainActivity : AppCompatActivity() {
setContentView(R.layout.activity_main) setContentView(R.layout.activity_main)
val video_view = findViewById<VideoPlayerView>(R.id.new_player_video_view) val video_view = findViewById<VideoPlayerView>(R.id.new_player_video_view)
video_view.viewModel = videoPlayerViewModel
videoPlayerViewModel.newPlayer = newPlayer
/*
video_view.fullScreenToggleListener = object : VideoPlayerView.FullScreenToggleListener { video_view.fullScreenToggleListener = object : VideoPlayerView.FullScreenToggleListener {
override fun fullscreenToggle(turnOn: Boolean) { override fun fullscreenToggle(turnOn: Boolean) {
if (turnOn) { if (turnOn) {
@ -70,7 +78,10 @@ class MainActivity : AppCompatActivity() {
} }
} }
} }
*/
newPlayer.playWhenReady = true newPlayer.playWhenReady = true
newPlayer.setStream(getString(R.string.ccc_chromebooks_video)) newPlayer.setStream(getString(R.string.ccc_chromebooks_video))

View File

@ -31,7 +31,7 @@
android:id="@+id/new_player_video_view" android:id="@+id/new_player_video_view"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:minHeight="50dp" android:minHeight="200dp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"