Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 2 additions & 16 deletions app/src/main/java/com/nextcloud/client/player/ui/PlayerActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -136,17 +136,6 @@ class PlayerActivity :
}
}

override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)

val videoPlayerView = playerView as? VideoPlayerView ?: return
if (isInPictureInPictureMode) {
videoPlayerView.hideControls()
} else {
videoPlayerView.showControls()
}
}

override fun onUserLeaveHint() {
super.onUserLeaveHint()
if (canUsePictureInPictureMode()) {
Expand All @@ -166,14 +155,11 @@ class PlayerActivity :
null
}

// Finish the activity if the user closes the PIP window
if (!isInPictureInPictureMode && lifecycle.currentState == Lifecycle.State.CREATED) {
finish() // Finish the activity if the user closes the PIP window
finish()
return
}

if (!isInPictureInPictureMode) {
(playerView as? VideoPlayerView)?.showControls()
}
}

private fun canUsePictureInPictureMode(): Boolean =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,16 @@
package com.nextcloud.client.player.ui.video

import android.content.Context
import android.view.MotionEvent
import android.view.WindowInsets
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.WindowInsetsCompat.Type
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import com.nextcloud.client.player.model.file.PlaybackFile
import com.nextcloud.client.player.ui.PlayerView
import com.owncloud.android.R
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlin.time.Duration.Companion.milliseconds

class VideoPlayerView(context: Context) : PlayerView(context) {

companion object {
private const val HIDE_CONTROLS_DELAY = 5000L
}

override val layoutRes get() = R.layout.player_video_view

override val createFragment: (PlaybackFile) -> Fragment get() = { VideoFileFragment.createInstance(it) }
Expand All @@ -39,13 +28,6 @@ class VideoPlayerView(context: Context) : PlayerView(context) {
topBar.setBackgroundResource(R.drawable.player_video_top_scrim)
}

override fun onStart() {
super.onStart()
if (!activity.isInPictureInPictureMode) {
showControls()
}
}

override fun onStop() {
super.onStop()
cancelHideControlsTimer()
Expand All @@ -65,45 +47,6 @@ class VideoPlayerView(context: Context) : PlayerView(context) {
return WindowInsetsCompat.CONSUMED.toWindowInsets()
}

override fun dispatchTouchEvent(event: MotionEvent): Boolean {
if (event.action == MotionEvent.ACTION_DOWN) {
val isTouchOutsideControls = event.y < playerControlView.y && event.y > topBar.height
when {
!playerControlView.isVisible -> showControls()
isTouchOutsideControls -> hideControls()
else -> restartHideControlsTimer()
}
}
return super.dispatchTouchEvent(event)
}

fun showControls() {
windowWrapper.showSystemBars()
topBar.visibility = VISIBLE
playerControlView.visibility = VISIBLE
restartHideControlsTimer()
}

fun hideControls() {
windowWrapper.hideSystemBars()
topBar.visibility = GONE
playerControlView.visibility = GONE
cancelHideControlsTimer()
}

private fun restartHideControlsTimer() {
hideControlsTimerJob?.cancel()

if (activity.isInPictureInPictureMode) {
return
}

hideControlsTimerJob = activity.lifecycleScope.launch {
delay(HIDE_CONTROLS_DELAY.milliseconds)
hideControls()
}
}

private fun cancelHideControlsTimer() {
hideControlsTimerJob?.cancel()
hideControlsTimerJob = null
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2026 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

package com.nextcloud.utils.extensions

import android.view.View
import android.view.Window
import androidx.appcompat.app.ActionBar
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.WindowInsetsControllerCompat

fun ActionBar.toggle(show: Boolean) {
if (show) {
show()
} else {
hide()
}
}

fun Window.showSystemBar(show: Boolean, view: View) {
WindowCompat.getInsetsController(this, view).run {
val types = WindowInsetsCompat.Type.systemBars()
if (show) {
show(types)
} else {
systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
hide(types)
}
}
}

fun Window.showNavigationBar(show: Boolean, view: View) {
WindowCompat.getInsetsController(this, view).run {
val types = WindowInsetsCompat.Type.navigationBars()
if (show) {
show(types)
} else {
systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
hide(types)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import com.nextcloud.model.WorkerState
import com.nextcloud.utils.extensions.getParcelableArgument
import com.nextcloud.utils.extensions.getSerializableArgument
import com.nextcloud.utils.extensions.observeWorker
import com.nextcloud.utils.extensions.toggle
import com.owncloud.android.MainApp
import com.owncloud.android.R
import com.owncloud.android.datamodel.FileDataStorageManager
Expand Down Expand Up @@ -195,12 +196,8 @@ class PreviewImageActivity :
private fun displayCutOutSafeInsetTop(): Int =
ViewCompat.getRootWindowInsets(window.decorView)?.displayCutout?.safeInsetTop ?: 0

fun toggleActionBarVisibility(hide: Boolean) {
if (hide) {
supportActionBar?.hide()
} else {
supportActionBar?.show()
}
fun toggleActionBarVisibility(show: Boolean) {
supportActionBar?.toggle(show)
}

private fun initViewPager(user: User) {
Expand Down Expand Up @@ -543,11 +540,11 @@ class PreviewImageActivity :

if (isInPictureInPictureMode) {
wasSystemUiVisibleBeforePictureInPicture = isSystemUIVisible
toggleActionBarVisibility(true)
toggleActionBarVisibility(false)
return
}

toggleActionBarVisibility(!wasSystemUiVisibleBeforePictureInPicture)
toggleActionBarVisibility(wasSystemUiVisibleBeforePictureInPicture)

if (lifecycle.currentState != Lifecycle.State.CREATED) return

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ import androidx.core.content.res.ResourcesCompat
import androidx.core.graphics.drawable.toDrawable
import androidx.core.view.MenuHost
import androidx.core.view.MenuProvider
import androidx.fragment.app.Fragment
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import com.caverock.androidsvg.SVG
Expand All @@ -49,6 +48,7 @@ import com.nextcloud.client.account.UserAccountManager
import com.nextcloud.client.di.Injectable
import com.nextcloud.client.jobs.BackgroundJobManager
import com.nextcloud.client.network.ConnectivityService
import com.nextcloud.client.player.model.file.PlaybackCollection
import com.nextcloud.ui.fileactions.FileAction
import com.nextcloud.ui.fileactions.FileActionsBottomSheet.Companion.newInstance
import com.nextcloud.utils.extensions.clickWithDebounce
Expand All @@ -57,7 +57,6 @@ import com.nextcloud.utils.extensions.getParcelableArgument
import com.nextcloud.utils.extensions.getSmallThumbnail
import com.nextcloud.utils.extensions.typedActivity
import com.owncloud.android.MainApp
import com.nextcloud.client.player.model.file.PlaybackCollection
import com.owncloud.android.R
import com.owncloud.android.databinding.PreviewImageFragmentBinding
import com.owncloud.android.datamodel.OCFile
Expand Down Expand Up @@ -162,7 +161,7 @@ class PreviewImageFragment :

private fun hideActionBar() {
(requireActivity() as PreviewImageActivity).run {
toggleActionBarVisibility(true)
toggleActionBarVisibility(false)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,21 @@ import com.nextcloud.client.player.media3.PlaybackModel
import com.nextcloud.client.player.model.PlayerThumbnailLoader
import com.nextcloud.client.player.model.file.PlaybackCollection
import com.nextcloud.client.player.model.file.PlaybackFile
import com.nextcloud.client.player.util.PlayerUtil.toPlaybackFile
import com.nextcloud.client.player.model.state.PlaybackState
import com.nextcloud.client.player.model.state.VideoSize
import com.nextcloud.client.player.ui.MediaNavigator
import com.nextcloud.client.player.ui.PlayerLauncher
import com.nextcloud.client.player.util.PlayerUtil.applyVideoSize
import com.nextcloud.client.player.util.PlayerUtil.isPictureInPictureAllowed
import com.nextcloud.client.player.util.PlayerUtil.ownsPlayback
import com.nextcloud.client.player.util.PlayerUtil.toPlaybackFile
import com.nextcloud.ui.fileactions.FileAction
import com.nextcloud.ui.fileactions.FileActionsBottomSheet
import com.nextcloud.utils.extensions.getParcelableArgument
import com.nextcloud.utils.extensions.getSerializableArgument
import com.nextcloud.utils.extensions.setVisibilityWithAnimation
import com.nextcloud.utils.extensions.showNavigationBar
import com.nextcloud.utils.extensions.showSystemBar
import com.owncloud.android.R
import com.owncloud.android.databinding.PreviewPlaybackFragmentBinding
import com.owncloud.android.datamodel.OCFile
Expand Down Expand Up @@ -120,6 +123,7 @@ class PreviewPlaybackFragment :
private var renderedVideoSize: VideoSize? = null

private var pictureInPictureCallback: OnBackPressedCallback? = null
private var isFullScreen = false

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Expand All @@ -138,6 +142,8 @@ class PreviewPlaybackFragment :
loadThumbnail()
registerPictureInPictureOnBack()
binding.playerControlView.navigator = activity as? MediaNavigator
isFullScreen = previewActivity()?.isSystemUIVisible == false
binding.surfaceView.setOnClickListener { toggleFullScreen() }
updatePlayerControlsVisibility()
binding.root.addOnLayoutChangeListener { _, _, _, _, _, _, _, _, _ ->
if (ownsPlayback(binding.surfaceView)) render(playbackModel.state)
Expand Down Expand Up @@ -399,8 +405,27 @@ class PreviewPlaybackFragment :

private fun isInPictureInPictureMode(): Boolean = activity?.isInPictureInPictureMode == true

private fun toggleFullScreen() {
val previewActivity = previewActivity() ?: return
isFullScreen = !isFullScreen
previewActivity.toggleActionBarVisibility(!isFullScreen)
binding.playerControlView.setVisibilityWithAnimation(!isFullScreen)
previewActivity.window.run {
showSystemBar(!isFullScreen, binding.root)
showNavigationBar(!isFullScreen, binding.root)
}
}

private fun updatePlayerControlsVisibility() {
binding.playerControlView.isVisible = !isInPictureInPictureMode()
if (isInPictureInPictureMode()) {
binding.playerControlView.isVisible = false
return
}

// playback updates arrive every second, so they must not undo full screen or cut the fade short
if (!isFullScreen) {
binding.playerControlView.isVisible = true
}
}

private fun showVideo(videoSize: VideoSize?) {
Expand Down
Loading