feat: automatic PiP animation (#648)

* Add automatic PiP animation

* Fix linting

* Fix linting

* chore: fix merge conflict

* fix: disable pip gesture when media is paused

* fix: crash when gestures are disabled

* fix: keep auto enter enabled after using button

---------

Co-authored-by: Cd16d <98320806+cd16b@users.noreply.github.com>
Co-authored-by: Jarne Demeulemeester <jarnedemeulemeester@gmail.com>
This commit is contained in:
Natanel Shitrit 2024-02-03 23:04:48 +02:00 committed by GitHub
parent 3ba5a73c74
commit 42df641c03
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 51 additions and 27 deletions

View file

@ -169,6 +169,11 @@ class PlayerActivity : BasePlayerActivity() {
viewModel.eventsChannelFlow.collect { event ->
when (event) {
is PlayerEvents.NavigateBack -> finish()
is PlayerEvents.IsPlayingChanged -> {
if (appPreferences.playerPipGesture) {
setPictureInPictureParams(pipParams(event.isPlaying))
}
}
}
}
}
@ -263,12 +268,16 @@ class PlayerActivity : BasePlayerActivity() {
}
override fun onUserLeaveHint() {
if (appPreferences.playerPipGesture && viewModel.player.isPlaying && !isControlsLocked) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S &&
appPreferences.playerPipGesture &&
viewModel.player.isPlaying &&
!isControlsLocked
) {
pictureInPicture()
}
}
private fun pipParams(): PictureInPictureParams {
private fun pipParams(enableAutoEnter: Boolean = viewModel.player.isPlaying): PictureInPictureParams {
val displayAspectRatio = Rational(binding.playerView.width, binding.playerView.height)
val aspectRatio = binding.playerView.player?.videoSize?.let {
@ -296,26 +305,21 @@ class PlayerActivity : BasePlayerActivity() {
)
}
return PictureInPictureParams.Builder()
val builder = PictureInPictureParams.Builder()
.setAspectRatio(aspectRatio)
.setSourceRectHint(sourceRectHint)
.build()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
builder.setAutoEnterEnabled(enableAutoEnter)
}
return builder.build()
}
private fun pictureInPicture() {
if (!isPipSupported) {
return
}
binding.playerView.useController = false
binding.playerView.findViewById<Button>(R.id.btn_skip_intro).isVisible = false
wasZoom = playerGestureHelper!!.isZoomEnabled
playerGestureHelper?.updateZoomMode(false)
// Brightness mode Auto
window.attributes = window.attributes.apply {
screenBrightness = WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE
}
try {
enterPictureInPictureMode(pipParams())
@ -327,19 +331,33 @@ class PlayerActivity : BasePlayerActivity() {
newConfig: Configuration,
) {
super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig)
if (!isInPictureInPictureMode) {
binding.playerView.useController = true
playerGestureHelper?.updateZoomMode(wasZoom)
when (isInPictureInPictureMode) {
true -> {
binding.playerView.useController = false
binding.playerView.findViewById<Button>(R.id.btn_skip_intro).isVisible = false
// Override auto brightness
window.attributes = window.attributes.apply {
screenBrightness = if (appPreferences.playerBrightnessRemember) {
appPreferences.playerBrightness
} else {
Settings.System.getInt(
contentResolver,
Settings.System.SCREEN_BRIGHTNESS,
).toFloat() / 255
wasZoom = playerGestureHelper?.isZoomEnabled ?: false
playerGestureHelper?.updateZoomMode(false)
// Brightness mode Auto
window.attributes = window.attributes.apply {
screenBrightness = WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE
}
}
false -> {
binding.playerView.useController = true
playerGestureHelper?.updateZoomMode(wasZoom)
// Override auto brightness
window.attributes = window.attributes.apply {
screenBrightness = if (appPreferences.playerBrightnessRemember) {
appPreferences.playerBrightness
} else {
Settings.System.getInt(
contentResolver,
Settings.System.SCREEN_BRIGHTNESS,
).toFloat() / 255
}
}
}
}

View file

@ -277,7 +277,7 @@ constructor(
} else {
item.name
}
_uiState.update { it.copy(currentItemTitle = itemTitle) }
_uiState.update { it.copy(currentItemTitle = itemTitle, fileLoaded = false) }
jellyfinRepository.postPlaybackStart(item.itemId)
@ -366,8 +366,14 @@ constructor(
}
}
}
override fun onIsPlayingChanged(isPlaying: Boolean) {
super.onIsPlayingChanged(isPlaying)
eventsChannel.trySend(PlayerEvents.IsPlayingChanged(isPlaying))
}
}
sealed interface PlayerEvents {
data object NavigateBack : PlayerEvents
data class IsPlayingChanged(val isPlaying: Boolean) : PlayerEvents
}