From 51b85c172027db84b516c469338ca3f69d0e96e7 Mon Sep 17 00:00:00 2001 From: Christian Schabesberger Date: Mon, 29 Jul 2024 17:32:44 +0200 Subject: [PATCH] add activity brainslug --- .../newpipe/newplayer/ActivityBrainSlug.kt | 116 ++++++++++++++++++ .../newplayer/model/VideoPlayerUIState.kt | 20 +++ .../newplayer/model/VideoPlayerViewModel.kt | 23 +++- .../model/VideoPlayerViewModelImpl.kt | 23 ++-- .../newpipe/newplayer/testapp/MainActivity.kt | 75 ++--------- 5 files changed, 179 insertions(+), 78 deletions(-) create mode 100644 new-player/src/main/java/net/newpipe/newplayer/ActivityBrainSlug.kt diff --git a/new-player/src/main/java/net/newpipe/newplayer/ActivityBrainSlug.kt b/new-player/src/main/java/net/newpipe/newplayer/ActivityBrainSlug.kt new file mode 100644 index 0000000..80d6a4b --- /dev/null +++ b/new-player/src/main/java/net/newpipe/newplayer/ActivityBrainSlug.kt @@ -0,0 +1,116 @@ +/* NewPlayer + * + * @author Christian Schabesberger + * + * Copyright (C) NewPipe e.V. 2024 + * + * 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 . + */ + +package net.newpipe.newplayer + +import android.view.View +import androidx.core.view.ViewCompat +import androidx.core.view.WindowInsetsCompat +import net.newpipe.newplayer.model.VideoPlayerViewModel + +class ActivityBrainSlug(val viewModel: VideoPlayerViewModel) { + + var rootView: View? = null + set(value) { + field = value + field?.let { + if (viewModel.uiState.value.fullscreen) { + removeSystemInsets() + } else { + addSystemInsets() + } + } + } + + private var viewsToHideOnFullscreen: MutableList = ArrayList() + var fullscreenPlayerView: VideoPlayerView? = null + set(value) { + field = value + if (viewModel.uiState.value.fullscreen) { + value?.visibility = View.VISIBLE + field?.viewModel = viewModel + } else { + value?.visibility = View.GONE + field?.viewModel = null + } + } + + var embeddedPlayerView: VideoPlayerView? = null + set(value) { + field = value + if (viewModel.uiState.value.fullscreen) { + field?.viewModel = null + value?.visibility = View.GONE + } else { + field?.viewModel = viewModel + value?.visibility = View.VISIBLE + } + } + + init { + viewModel.addCallbackListener(object : VideoPlayerViewModel.Listener { + override fun onFullscreenToggle(isFullscreen: Boolean) { + if (isFullscreen) { + removeSystemInsets() + viewsToHideOnFullscreen.forEach { it.visibility = View.GONE } + fullscreenPlayerView?.visibility = View.VISIBLE + } else { + addSystemInsets() + viewsToHideOnFullscreen.forEach { it.visibility = View.VISIBLE } + fullscreenPlayerView?.visibility = View.GONE + } + } + + }) + } + + fun addViewToHideOnFullscreen(view: View) { + viewsToHideOnFullscreen.add(view) + if (viewModel.uiState.value.fullscreen) { + view.visibility = View.GONE + } + } + + private fun addSystemInsets() { + rootView?.let { rootView -> + ViewCompat.setOnApplyWindowInsetsListener(rootView) { v, insets -> + val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) + v.setPadding( + systemBars.left, + systemBars.top, + systemBars.right, + systemBars.bottom + ) + insets + } + } + } + + private fun removeSystemInsets() { + rootView?.let { rootView -> + ViewCompat.setOnApplyWindowInsetsListener(rootView) { v, insets -> + v.setPadding( + 0, 0, 0, 0 + ) + insets + } + } + } +} \ No newline at end of file diff --git a/new-player/src/main/java/net/newpipe/newplayer/model/VideoPlayerUIState.kt b/new-player/src/main/java/net/newpipe/newplayer/model/VideoPlayerUIState.kt index 86ae2ae..5f51eaf 100644 --- a/new-player/src/main/java/net/newpipe/newplayer/model/VideoPlayerUIState.kt +++ b/new-player/src/main/java/net/newpipe/newplayer/model/VideoPlayerUIState.kt @@ -1,3 +1,23 @@ +/* NewPlayer + * + * @author Christian Schabesberger + * + * Copyright (C) NewPipe e.V. 2024 + * + * 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 . + */ + package net.newpipe.newplayer.model import android.os.Parcelable diff --git a/new-player/src/main/java/net/newpipe/newplayer/model/VideoPlayerViewModel.kt b/new-player/src/main/java/net/newpipe/newplayer/model/VideoPlayerViewModel.kt index 582a9d3..da08da2 100644 --- a/new-player/src/main/java/net/newpipe/newplayer/model/VideoPlayerViewModel.kt +++ b/new-player/src/main/java/net/newpipe/newplayer/model/VideoPlayerViewModel.kt @@ -1,3 +1,23 @@ +/* NewPlayer + * + * @author Christian Schabesberger + * + * Copyright (C) NewPipe e.V. 2024 + * + * 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 . + */ + package net.newpipe.newplayer.model import android.os.Bundle @@ -14,8 +34,8 @@ interface VideoPlayerViewModel { var minContentRatio: Float var maxContentRatio: Float var contentFitMode: ContentScale - var callbackListener: Listener? + fun addCallbackListener(listener: Listener) fun initUIState(instanceState: Bundle) fun play() fun pause() @@ -30,6 +50,5 @@ interface VideoPlayerViewModel { interface Listener { fun onFullscreenToggle(isFullscreen: Boolean) - fun onUiVissibleToggle(isVissible: Boolean) } } \ No newline at end of file diff --git a/new-player/src/main/java/net/newpipe/newplayer/model/VideoPlayerViewModelImpl.kt b/new-player/src/main/java/net/newpipe/newplayer/model/VideoPlayerViewModelImpl.kt index 661da78..fb935e9 100644 --- a/new-player/src/main/java/net/newpipe/newplayer/model/VideoPlayerViewModelImpl.kt +++ b/new-player/src/main/java/net/newpipe/newplayer/model/VideoPlayerViewModelImpl.kt @@ -59,9 +59,9 @@ class VideoPlayerViewModelImpl @Inject constructor( private var uiVisibilityJob: Job? = null private var progressUpdaterJob: Job? = null - //interface - override var callbackListener: VideoPlayerViewModel.Listener? = null + var callbackListeners: MutableList = ArrayList() + //interface override var newPlayer: NewPlayer? = null set(value) { field = value @@ -175,6 +175,10 @@ class VideoPlayerViewModelImpl @Inject constructor( } } + override fun addCallbackListener(listener: VideoPlayerViewModel.Listener) { + callbackListeners.add(listener) + } + override fun play() { hideUi() newPlayer?.play() @@ -197,9 +201,6 @@ class VideoPlayerViewModelImpl @Inject constructor( } override fun showUi() { - if (mutableUiState.value.fullscreen) - callbackListener?.onUiVissibleToggle(true) - mutableUiState.update { it.copy(uiVissible = true) } @@ -240,9 +241,6 @@ class VideoPlayerViewModelImpl @Inject constructor( } override fun hideUi() { - if (mutableUiState.value.fullscreen) - callbackListener?.onUiVissibleToggle(false) - progressUpdaterJob?.cancel() uiVisibilityJob?.cancel() mutableUiState.update { @@ -264,7 +262,7 @@ class VideoPlayerViewModelImpl @Inject constructor( } override fun switchToEmbeddedView() { - callbackListener?.onFullscreenToggle(false) + callbackListeners.forEach { it?.onFullscreenToggle(false) } uiVisibilityJob?.cancel() mutableUiState.update { it.copy(fullscreen = false, uiVissible = false) @@ -272,7 +270,7 @@ class VideoPlayerViewModelImpl @Inject constructor( } override fun switchToFullscreen() { - callbackListener?.onFullscreenToggle(true) + callbackListeners.forEach { it?.onFullscreenToggle(true) } uiVisibilityJob?.cancel() mutableUiState.update { @@ -300,12 +298,15 @@ class VideoPlayerViewModelImpl @Inject constructor( override var minContentRatio = 4F / 3F override var maxContentRatio = 16F / 9F override var contentFitMode = ContentScale.FIT_INSIDE - override var callbackListener: VideoPlayerViewModel.Listener? = null override fun initUIState(instanceState: Bundle) { println("dummy impl") } + override fun addCallbackListener(listener: VideoPlayerViewModel.Listener) { + println("dummy impl") + } + override fun play() { println("dummy impl") } diff --git a/test-app/src/main/java/net/newpipe/newplayer/testapp/MainActivity.kt b/test-app/src/main/java/net/newpipe/newplayer/testapp/MainActivity.kt index 4229a1f..8be9505 100644 --- a/test-app/src/main/java/net/newpipe/newplayer/testapp/MainActivity.kt +++ b/test-app/src/main/java/net/newpipe/newplayer/testapp/MainActivity.kt @@ -31,6 +31,7 @@ import androidx.core.view.WindowCompat import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsControllerCompat import dagger.hilt.android.AndroidEntryPoint +import net.newpipe.newplayer.ActivityBrainSlug import net.newpipe.newplayer.NewPlayer import net.newpipe.newplayer.VideoPlayerView import net.newpipe.newplayer.model.VideoPlayerViewModel @@ -46,6 +47,8 @@ class MainActivity : AppCompatActivity() { @Inject lateinit var newPlayer: NewPlayer + var activityBrainSlug: ActivityBrainSlug? = null + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() @@ -63,73 +66,15 @@ class MainActivity : AppCompatActivity() { } videoPlayerViewModel.newPlayer = newPlayer - - //videoPlayerViewModel.maxContentRatio = 4F/3F videoPlayerViewModel.contentFitMode = ContentScale.FIT_INSIDE - //val windowInsetsController = WindowCompat.getInsetsController(window, window.decorView) - //windowInsetsController.systemBarsBehavior = - //WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE - - - val setupFullscreen = { - ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets -> - v.setPadding(0, 0, 0, 0) - insets - } - buttonsLayout.visibility = View.GONE - embeddedPlayerLayout.visibility = View.GONE - fullscreenPlayer.visibility = View.VISIBLE - embeddedPlayer.viewModel = null - fullscreenPlayer.viewModel = videoPlayerViewModel - - //windowInsetsController.hide(WindowInsetsCompat.Type.systemBars()) - } - - val setupEmbeddedView = { - buttonsLayout.visibility = View.VISIBLE - - 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 - } - - buttonsLayout.visibility = View.VISIBLE - embeddedPlayerLayout.visibility = View.VISIBLE - fullscreenPlayer.visibility = View.GONE - fullscreenPlayer.viewModel = null - embeddedPlayer.viewModel = videoPlayerViewModel - - //windowInsetsController.show(WindowInsetsCompat.Type.systemBars()) - } - - if (videoPlayerViewModel.uiState.value.fullscreen) { - setupFullscreen() - } else { - setupEmbeddedView() - } - - videoPlayerViewModel.callbackListener = object : VideoPlayerViewModel.Listener { - override fun onFullscreenToggle(isFullscreen: Boolean) { - if (isFullscreen) - setupFullscreen() - else - setupEmbeddedView() - } - - override fun onUiVissibleToggle(isVissible: Boolean) { - if (isVissible) { - //windowInsetsController.show(WindowInsetsCompat.Type.systemBars()) - } else { - //windowInsetsController.hide(WindowInsetsCompat.Type.systemBars()) - } - } + activityBrainSlug = ActivityBrainSlug(videoPlayerViewModel) + activityBrainSlug?.let { + it.embeddedPlayerView = embeddedPlayer + it.addViewToHideOnFullscreen(buttonsLayout) + it.addViewToHideOnFullscreen(embeddedPlayerLayout) + it.fullscreenPlayerView = fullscreenPlayer + it.rootView = findViewById(R.id.main) } } } \ No newline at end of file