diff --git a/app/src/main/kotlin/org/fossify/gallery/activities/VideoPlayerActivity.kt b/app/src/main/kotlin/org/fossify/gallery/activities/VideoPlayerActivity.kt index b4e58c0b6..a4274b130 100644 --- a/app/src/main/kotlin/org/fossify/gallery/activities/VideoPlayerActivity.kt +++ b/app/src/main/kotlin/org/fossify/gallery/activities/VideoPlayerActivity.kt @@ -13,11 +13,21 @@ import android.net.Uri import android.os.Bundle import android.os.Handler import android.util.DisplayMetrics -import android.view.* +import android.view.GestureDetector +import android.view.MotionEvent +import android.view.Surface +import android.view.TextureView +import android.view.View +import android.view.WindowManager import android.widget.RelativeLayout import android.widget.SeekBar import androidx.appcompat.content.res.AppCompatResources -import androidx.media3.common.* +import androidx.media3.common.AudioAttributes +import androidx.media3.common.C +import androidx.media3.common.MediaItem +import androidx.media3.common.PlaybackException +import androidx.media3.common.Player +import androidx.media3.common.VideoSize import androidx.media3.common.util.UnstableApi import androidx.media3.datasource.ContentDataSource import androidx.media3.datasource.DataSource @@ -28,17 +38,56 @@ import androidx.media3.exoplayer.SeekParameters import androidx.media3.exoplayer.source.DefaultMediaSourceFactory import androidx.media3.exoplayer.source.MediaSource import androidx.media3.exoplayer.source.ProgressiveMediaSource -import org.fossify.commons.extensions.* +import org.fossify.commons.extensions.actionBarHeight +import org.fossify.commons.extensions.beGone +import org.fossify.commons.extensions.beVisible +import org.fossify.commons.extensions.beVisibleIf +import org.fossify.commons.extensions.fadeIn +import org.fossify.commons.extensions.getColoredDrawableWithColor +import org.fossify.commons.extensions.getFilenameFromUri +import org.fossify.commons.extensions.getFormattedDuration +import org.fossify.commons.extensions.getProperTextColor +import org.fossify.commons.extensions.navigationBarHeight +import org.fossify.commons.extensions.navigationBarOnSide +import org.fossify.commons.extensions.navigationBarWidth +import org.fossify.commons.extensions.onGlobalLayout +import org.fossify.commons.extensions.portrait +import org.fossify.commons.extensions.setDrawablesRelativeWithIntrinsicBounds +import org.fossify.commons.extensions.showErrorToast +import org.fossify.commons.extensions.statusBarHeight +import org.fossify.commons.extensions.updateTextColors +import org.fossify.commons.extensions.viewBinding import org.fossify.gallery.R import org.fossify.gallery.databinding.ActivityVideoPlayerBinding -import org.fossify.gallery.extensions.* +import org.fossify.gallery.extensions.config +import org.fossify.gallery.extensions.getFriendlyMessage +import org.fossify.gallery.extensions.hasNavBar +import org.fossify.gallery.extensions.hideSystemUI +import org.fossify.gallery.extensions.mute +import org.fossify.gallery.extensions.openPath +import org.fossify.gallery.extensions.shareMediumPath +import org.fossify.gallery.extensions.showSystemUI +import org.fossify.gallery.extensions.unmute import org.fossify.gallery.fragments.PlaybackSpeedFragment -import org.fossify.gallery.helpers.* +import org.fossify.gallery.helpers.DRAG_THRESHOLD +import org.fossify.gallery.helpers.EXOPLAYER_MAX_BUFFER_MS +import org.fossify.gallery.helpers.EXOPLAYER_MIN_BUFFER_MS +import org.fossify.gallery.helpers.FAST_FORWARD_VIDEO_MS +import org.fossify.gallery.helpers.GO_TO_NEXT_ITEM +import org.fossify.gallery.helpers.GO_TO_PREV_ITEM +import org.fossify.gallery.helpers.HIDE_SYSTEM_UI_DELAY +import org.fossify.gallery.helpers.MAX_CLOSE_DOWN_GESTURE_DURATION +import org.fossify.gallery.helpers.ROTATE_BY_ASPECT_RATIO +import org.fossify.gallery.helpers.ROTATE_BY_DEVICE_ROTATION +import org.fossify.gallery.helpers.ROTATE_BY_SYSTEM_SETTING +import org.fossify.gallery.helpers.SHOW_NEXT_ITEM +import org.fossify.gallery.helpers.SHOW_PREV_ITEM import org.fossify.gallery.interfaces.PlaybackSpeedListener import java.text.DecimalFormat @UnstableApi -open class VideoPlayerActivity : SimpleActivity(), SeekBar.OnSeekBarChangeListener, TextureView.SurfaceTextureListener, PlaybackSpeedListener { +open class VideoPlayerActivity : SimpleActivity(), SeekBar.OnSeekBarChangeListener, + TextureView.SurfaceTextureListener, PlaybackSpeedListener { private val PLAY_WHEN_READY_DRAG_DELAY = 100L private var mIsFullscreen = false @@ -122,11 +171,18 @@ open class VideoPlayerActivity : SimpleActivity(), SeekBar.OnSeekBarChangeListen } private fun setupOptionsMenu() { - (binding.videoAppbar.layoutParams as RelativeLayout.LayoutParams).topMargin = statusBarHeight + (binding.videoAppbar.layoutParams as RelativeLayout.LayoutParams).topMargin = + statusBarHeight binding.videoToolbar.apply { setTitleTextColor(Color.WHITE) - overflowIcon = resources.getColoredDrawableWithColor(org.fossify.commons.R.drawable.ic_three_dots_vector, Color.WHITE) - navigationIcon = resources.getColoredDrawableWithColor(org.fossify.commons.R.drawable.ic_arrow_left_vector, Color.WHITE) + overflowIcon = resources.getColoredDrawableWithColor( + org.fossify.commons.R.drawable.ic_three_dots_vector, + Color.WHITE + ) + navigationIcon = resources.getColoredDrawableWithColor( + org.fossify.commons.R.drawable.ic_arrow_left_vector, + Color.WHITE + ) } updateMenuItemColors(binding.videoToolbar.menu, forceWhiteIcons = true) @@ -154,7 +210,8 @@ open class VideoPlayerActivity : SimpleActivity(), SeekBar.OnSeekBarChangeListen } binding.topShadow.layoutParams.height = statusBarHeight + actionBarHeight - (binding.videoAppbar.layoutParams as RelativeLayout.LayoutParams).topMargin = statusBarHeight + (binding.videoAppbar.layoutParams as RelativeLayout.LayoutParams).topMargin = + statusBarHeight if (!portrait && navigationBarOnSide && navigationBarWidth > 0) { binding.videoToolbar.setPadding(0, 0, navigationBarWidth, 0) } else { @@ -195,18 +252,29 @@ open class VideoPlayerActivity : SimpleActivity(), SeekBar.OnSeekBarChangeListen binding.videoSurfaceFrame.setOnClickListener { toggleFullscreen() } binding.videoSurfaceFrame.controller.settings.swallowDoubleTaps = true - binding.bottomVideoTimeHolder.videoNextFile.beVisibleIf(intent.getBooleanExtra(SHOW_NEXT_ITEM, false)) + binding.bottomVideoTimeHolder.videoNextFile.beVisibleIf( + intent.getBooleanExtra( + SHOW_NEXT_ITEM, + false + ) + ) binding.bottomVideoTimeHolder.videoNextFile.setOnClickListener { handleNextFile() } - binding.bottomVideoTimeHolder.videoPrevFile.beVisibleIf(intent.getBooleanExtra(SHOW_PREV_ITEM, false)) + binding.bottomVideoTimeHolder.videoPrevFile.beVisibleIf( + intent.getBooleanExtra( + SHOW_PREV_ITEM, + false + ) + ) binding.bottomVideoTimeHolder.videoPrevFile.setOnClickListener { handlePrevFile() } - val gestureDetector = GestureDetector(this, object : GestureDetector.SimpleOnGestureListener() { - override fun onDoubleTap(e: MotionEvent): Boolean { - handleDoubleTap(e.rawX) - return true - } - }) + val gestureDetector = + GestureDetector(this, object : GestureDetector.SimpleOnGestureListener() { + override fun onDoubleTap(e: MotionEvent): Boolean { + handleDoubleTap(e.rawX) + return true + } + }) binding.videoSurfaceFrame.setOnTouchListener { view, event -> handleEvent(event) @@ -218,17 +286,29 @@ open class VideoPlayerActivity : SimpleActivity(), SeekBar.OnSeekBarChangeListen binding.videoSurface.surfaceTextureListener = this if (config.allowVideoGestures) { - binding.videoBrightnessController.initialize(this, binding.slideInfo, true, binding.videoPlayerHolder, singleTap = { x, y -> - toggleFullscreen() - }, doubleTap = { x, y -> - doSkip(false) - }) + binding.videoBrightnessController.initialize( + this, + binding.slideInfo, + true, + binding.videoPlayerHolder, + singleTap = { x, y -> + toggleFullscreen() + }, + doubleTap = { x, y -> + doSkip(false) + }) - binding.videoVolumeController.initialize(this, binding.slideInfo, false, binding.videoPlayerHolder, singleTap = { x, y -> - toggleFullscreen() - }, doubleTap = { x, y -> - doSkip(true) - }) + binding.videoVolumeController.initialize( + this, + binding.slideInfo, + false, + binding.videoPlayerHolder, + singleTap = { x, y -> + toggleFullscreen() + }, + doubleTap = { x, y -> + doSkip(true) + }) } else { binding.videoBrightnessController.beGone() binding.videoVolumeController.beGone() @@ -257,7 +337,12 @@ open class VideoPlayerActivity : SimpleActivity(), SeekBar.OnSeekBarChangeListen .createMediaSource(MediaItem.fromUri(fileDataSource.uri!!)) val loadControl = DefaultLoadControl.Builder() - .setBufferDurationsMs(EXOPLAYER_MIN_BUFFER_MS, EXOPLAYER_MAX_BUFFER_MS, EXOPLAYER_MIN_BUFFER_MS, EXOPLAYER_MIN_BUFFER_MS) + .setBufferDurationsMs( + EXOPLAYER_MIN_BUFFER_MS, + EXOPLAYER_MAX_BUFFER_MS, + EXOPLAYER_MIN_BUFFER_MS, + EXOPLAYER_MIN_BUFFER_MS + ) .setPrioritizeTimeOverSizeThresholds(true) .build() @@ -287,7 +372,11 @@ open class VideoPlayerActivity : SimpleActivity(), SeekBar.OnSeekBarChangeListen private fun ExoPlayer.initListeners() { addListener(object : Player.Listener { - override fun onPositionDiscontinuity(oldPosition: Player.PositionInfo, newPosition: Player.PositionInfo, @Player.DiscontinuityReason reason: Int) { + override fun onPositionDiscontinuity( + oldPosition: Player.PositionInfo, + newPosition: Player.PositionInfo, + @Player.DiscontinuityReason reason: Int + ) { // Reset progress views when video loops. if (reason == Player.DISCONTINUITY_REASON_AUTO_TRANSITION) { binding.bottomVideoTimeHolder.videoSeekbar.progress = 0 @@ -327,7 +416,8 @@ open class VideoPlayerActivity : SimpleActivity(), SeekBar.OnSeekBarChangeListen binding.bottomVideoTimeHolder.videoTogglePlayPause.beVisible() binding.bottomVideoTimeHolder.videoPlaybackSpeed.beVisible() binding.bottomVideoTimeHolder.videoToggleMute.beVisible() - binding.bottomVideoTimeHolder.videoPlaybackSpeed.text = "${DecimalFormat("#.##").format(config.playbackSpeed)}x" + binding.bottomVideoTimeHolder.videoPlaybackSpeed.text = + "${DecimalFormat("#.##").format(config.playbackSpeed)}x" mDuration = (mExoPlayer!!.duration / 1000).toInt() binding.bottomVideoTimeHolder.videoSeekbar.max = mDuration binding.bottomVideoTimeHolder.videoDuration.text = mDuration.getFormattedDuration() @@ -430,7 +520,8 @@ open class VideoPlayerActivity : SimpleActivity(), SeekBar.OnSeekBarChangeListen clearLastVideoSavedProgress() mCurrTime = (mExoPlayer!!.duration / 1000).toInt() - binding.bottomVideoTimeHolder.videoSeekbar.progress = binding.bottomVideoTimeHolder.videoSeekbar.max + binding.bottomVideoTimeHolder.videoSeekbar.progress = + binding.bottomVideoTimeHolder.videoSeekbar.max binding.bottomVideoTimeHolder.videoCurrTime.text = mDuration.getFormattedDuration() pauseVideo() } @@ -443,7 +534,10 @@ open class VideoPlayerActivity : SimpleActivity(), SeekBar.OnSeekBarChangeListen private fun saveVideoProgress() { if (!didVideoEnd()) { - config.saveLastVideoPosition(mUri.toString(), mExoPlayer!!.currentPosition.toInt() / 1000) + config.saveLastVideoPosition( + mUri.toString(), + mExoPlayer!!.currentPosition.toInt() / 1000 + ) } } @@ -489,11 +583,12 @@ open class VideoPlayerActivity : SimpleActivity(), SeekBar.OnSeekBarChangeListen private fun changeOrientation() { mIsOrientationLocked = true - requestedOrientation = if (resources.configuration.orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) { - ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE - } else { - ActivityInfo.SCREEN_ORIENTATION_PORTRAIT - } + requestedOrientation = + if (resources.configuration.orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) { + ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE + } else { + ActivityInfo.SCREEN_ORIENTATION_PORTRAIT + } } private fun toggleFullscreen() { @@ -553,13 +648,20 @@ open class VideoPlayerActivity : SimpleActivity(), SeekBar.OnSeekBarChangeListen if (isSlow != binding.bottomVideoTimeHolder.videoPlaybackSpeed.tag as? Boolean) { binding.bottomVideoTimeHolder.videoPlaybackSpeed.tag = isSlow - val drawableId = if (isSlow) R.drawable.ic_playback_speed_slow_vector else R.drawable.ic_playback_speed_vector + val drawableId = + if (isSlow) R.drawable.ic_playback_speed_slow_vector else R.drawable.ic_playback_speed_vector binding.bottomVideoTimeHolder.videoPlaybackSpeed - .setDrawablesRelativeWithIntrinsicBounds(AppCompatResources.getDrawable(this, drawableId)) + .setDrawablesRelativeWithIntrinsicBounds( + AppCompatResources.getDrawable( + this, + drawableId + ) + ) } @SuppressLint("SetTextI18n") - binding.bottomVideoTimeHolder.videoPlaybackSpeed.text = "${DecimalFormat("#.##").format(speed)}x" + binding.bottomVideoTimeHolder.videoPlaybackSpeed.text = + "${DecimalFormat("#.##").format(speed)}x" mExoPlayer?.setPlaybackSpeed(speed) } @@ -590,7 +692,8 @@ open class VideoPlayerActivity : SimpleActivity(), SeekBar.OnSeekBarChangeListen if (mExoPlayer != null && !mIsDragged && mIsPlaying) { mCurrTime = (mExoPlayer!!.currentPosition / 1000).toInt() binding.bottomVideoTimeHolder.videoSeekbar.progress = mCurrTime - binding.bottomVideoTimeHolder.videoCurrTime.text = mCurrTime.getFormattedDuration() + binding.bottomVideoTimeHolder.videoCurrTime.text = + mCurrTime.getFormattedDuration() } mTimerHandler.postDelayed(this, 1000) @@ -604,9 +707,11 @@ open class VideoPlayerActivity : SimpleActivity(), SeekBar.OnSeekBarChangeListen } val curr = mExoPlayer!!.currentPosition - val newProgress = if (forward) curr + FAST_FORWARD_VIDEO_MS else curr - FAST_FORWARD_VIDEO_MS + val newProgress = + if (forward) curr + FAST_FORWARD_VIDEO_MS else curr - FAST_FORWARD_VIDEO_MS val roundProgress = Math.round(newProgress / 1000f) - val limitedProgress = Math.max(Math.min(mExoPlayer!!.duration.toInt() / 1000, roundProgress), 0) + val limitedProgress = + Math.max(Math.min(mExoPlayer!!.duration.toInt() / 1000, roundProgress), 0) setPosition(limitedProgress) if (!mIsPlaying) { togglePlayPause() @@ -627,7 +732,10 @@ open class VideoPlayerActivity : SimpleActivity(), SeekBar.OnSeekBarChangeListen val diffX = event.rawX - mTouchDownX val diffY = event.rawY - mTouchDownY - if (mIsDragged || (Math.abs(diffX) > mDragThreshold && Math.abs(diffX) > Math.abs(diffY)) && binding.videoSurfaceFrame.controller.state.zoom == 1f) { + if (mIsDragged || (Math.abs(diffX) > mDragThreshold && Math.abs(diffX) > Math.abs( + diffY + )) && binding.videoSurfaceFrame.controller.state.zoom == 1f + ) { if (!mIsDragged) { arrayOf( binding.bottomVideoTimeHolder.videoCurrTime, @@ -644,7 +752,8 @@ open class VideoPlayerActivity : SimpleActivity(), SeekBar.OnSeekBarChangeListen val skipLength = (mDuration * 1000f) * (percent / 100f) var newProgress = mProgressAtDown + skipLength - newProgress = Math.max(Math.min(mExoPlayer!!.duration.toFloat(), newProgress), 0f) + newProgress = + Math.max(Math.min(mExoPlayer!!.duration.toFloat(), newProgress), 0f) val newSeconds = (newProgress / 1000).toInt() setPosition(newSeconds) resetPlayWhenReady() diff --git a/app/src/main/kotlin/org/fossify/gallery/extensions/Player.kt b/app/src/main/kotlin/org/fossify/gallery/extensions/Player.kt index 39d0a67da..ccf55328f 100644 --- a/app/src/main/kotlin/org/fossify/gallery/extensions/Player.kt +++ b/app/src/main/kotlin/org/fossify/gallery/extensions/Player.kt @@ -2,7 +2,14 @@ package org.fossify.gallery.extensions import android.content.Context import androidx.media3.common.PlaybackException -import androidx.media3.common.PlaybackException.* +import androidx.media3.common.PlaybackException.ERROR_CODE_DECODER_INIT_FAILED +import androidx.media3.common.PlaybackException.ERROR_CODE_DECODING_FAILED +import androidx.media3.common.PlaybackException.ERROR_CODE_DECODING_FORMAT_EXCEEDS_CAPABILITIES +import androidx.media3.common.PlaybackException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED +import androidx.media3.common.PlaybackException.ERROR_CODE_PARSING_CONTAINER_MALFORMED +import androidx.media3.common.PlaybackException.ERROR_CODE_PARSING_CONTAINER_UNSUPPORTED +import androidx.media3.common.PlaybackException.ERROR_CODE_PARSING_MANIFEST_MALFORMED +import androidx.media3.common.PlaybackException.ERROR_CODE_PARSING_MANIFEST_UNSUPPORTED import androidx.media3.common.Player import org.fossify.gallery.R @@ -14,7 +21,7 @@ fun Player.unmute() { volume = 1f } -fun PlaybackException.getFriendlyMessage(context: Context): String? { +fun PlaybackException.getFriendlyMessage(context: Context): String { val resource = when (errorCode) { ERROR_CODE_PARSING_CONTAINER_MALFORMED, ERROR_CODE_PARSING_MANIFEST_MALFORMED -> R.string.file_is_malformed_or_corrupted diff --git a/app/src/main/kotlin/org/fossify/gallery/fragments/VideoFragment.kt b/app/src/main/kotlin/org/fossify/gallery/fragments/VideoFragment.kt index 89ef889d6..463bff663 100644 --- a/app/src/main/kotlin/org/fossify/gallery/fragments/VideoFragment.kt +++ b/app/src/main/kotlin/org/fossify/gallery/fragments/VideoFragment.kt @@ -9,14 +9,26 @@ import android.net.Uri import android.os.Bundle import android.os.Handler import android.util.DisplayMetrics -import android.view.* +import android.view.GestureDetector +import android.view.LayoutInflater +import android.view.MotionEvent +import android.view.Surface +import android.view.TextureView +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager import android.widget.ImageView import android.widget.RelativeLayout import android.widget.SeekBar import android.widget.TextView import androidx.appcompat.content.res.AppCompatResources import androidx.core.view.children -import androidx.media3.common.* +import androidx.media3.common.AudioAttributes +import androidx.media3.common.C +import androidx.media3.common.MediaItem +import androidx.media3.common.PlaybackException +import androidx.media3.common.Player +import androidx.media3.common.VideoSize import androidx.media3.common.util.UnstableApi import androidx.media3.datasource.ContentDataSource import androidx.media3.datasource.DataSource @@ -29,13 +41,42 @@ import androidx.media3.exoplayer.source.DefaultMediaSourceFactory import androidx.media3.exoplayer.source.MediaSource import androidx.media3.exoplayer.source.ProgressiveMediaSource import com.bumptech.glide.Glide -import org.fossify.commons.extensions.* +import org.fossify.commons.extensions.beGone +import org.fossify.commons.extensions.beGoneIf +import org.fossify.commons.extensions.beInvisible +import org.fossify.commons.extensions.beInvisibleIf +import org.fossify.commons.extensions.beVisible +import org.fossify.commons.extensions.beVisibleIf +import org.fossify.commons.extensions.fadeIn +import org.fossify.commons.extensions.getDuration +import org.fossify.commons.extensions.getFormattedDuration +import org.fossify.commons.extensions.getProperTextColor +import org.fossify.commons.extensions.getVideoResolution +import org.fossify.commons.extensions.isGone +import org.fossify.commons.extensions.isVisible +import org.fossify.commons.extensions.navigationBarHeight +import org.fossify.commons.extensions.navigationBarWidth +import org.fossify.commons.extensions.onGlobalLayout +import org.fossify.commons.extensions.realScreenSize +import org.fossify.commons.extensions.setDrawablesRelativeWithIntrinsicBounds +import org.fossify.commons.extensions.showErrorToast +import org.fossify.commons.extensions.updateTextColors import org.fossify.commons.helpers.ensureBackgroundThread import org.fossify.gallery.R import org.fossify.gallery.activities.VideoActivity import org.fossify.gallery.databinding.PagerVideoItemBinding -import org.fossify.gallery.extensions.* -import org.fossify.gallery.helpers.* +import org.fossify.gallery.extensions.config +import org.fossify.gallery.extensions.getFriendlyMessage +import org.fossify.gallery.extensions.hasNavBar +import org.fossify.gallery.extensions.mute +import org.fossify.gallery.extensions.parseFileChannel +import org.fossify.gallery.extensions.unmute +import org.fossify.gallery.helpers.Config +import org.fossify.gallery.helpers.EXOPLAYER_MAX_BUFFER_MS +import org.fossify.gallery.helpers.EXOPLAYER_MIN_BUFFER_MS +import org.fossify.gallery.helpers.FAST_FORWARD_VIDEO_MS +import org.fossify.gallery.helpers.MEDIUM +import org.fossify.gallery.helpers.SHOULD_INIT_FRAGMENT import org.fossify.gallery.interfaces.PlaybackSpeedListener import org.fossify.gallery.models.Medium import org.fossify.gallery.views.MediaSideScroll @@ -44,7 +85,8 @@ import java.io.FileInputStream import java.text.DecimalFormat @UnstableApi -class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, SeekBar.OnSeekBarChangeListener, PlaybackSpeedListener { +class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, + SeekBar.OnSeekBarChangeListener, PlaybackSpeedListener { private val PROGRESS = "progress" private var mIsFullscreen = false @@ -85,7 +127,11 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S private lateinit var mPlayPauseButton: ImageView private lateinit var mSeekBar: SeekBar - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { val context = requireContext() val activity = requireActivity() val arguments = requireArguments() @@ -131,29 +177,30 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S mTextureView = videoSurface mTextureView.surfaceTextureListener = this@VideoFragment - val gestureDetector = GestureDetector(context, object : GestureDetector.SimpleOnGestureListener() { - override fun onSingleTapConfirmed(e: MotionEvent): Boolean { - if (!mConfig.allowInstantChange) { - toggleFullscreen() + val gestureDetector = + GestureDetector(context, object : GestureDetector.SimpleOnGestureListener() { + override fun onSingleTapConfirmed(e: MotionEvent): Boolean { + if (!mConfig.allowInstantChange) { + toggleFullscreen() + return true + } + + val viewWidth = root.width + val instantWidth = viewWidth / 7 + val clickedX = e.rawX + when { + clickedX <= instantWidth -> listener?.goToPrevItem() + clickedX >= viewWidth - instantWidth -> listener?.goToNextItem() + else -> toggleFullscreen() + } return true } - val viewWidth = root.width - val instantWidth = viewWidth / 7 - val clickedX = e.rawX - when { - clickedX <= instantWidth -> listener?.goToPrevItem() - clickedX >= viewWidth - instantWidth -> listener?.goToNextItem() - else -> toggleFullscreen() + override fun onDoubleTap(e: MotionEvent): Boolean { + handleDoubleTap(e.rawX) + return true } - return true - } - - override fun onDoubleTap(e: MotionEvent): Boolean { - handleDoubleTap(e.rawX) - return true - } - }) + }) videoPreview.setOnTouchListener { view, event -> handleEvent(event) @@ -183,7 +230,8 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S mIsFragmentVisible = true } - mIsFullscreen = activity.window.decorView.systemUiVisibility and View.SYSTEM_UI_FLAG_FULLSCREEN == View.SYSTEM_UI_FLAG_FULLSCREEN + mIsFullscreen = + activity.window.decorView.systemUiVisibility and View.SYSTEM_UI_FLAG_FULLSCREEN == View.SYSTEM_UI_FLAG_FULLSCREEN initTimeHolder() // checkIfPanorama() TODO: Implement panorama using a FOSS library @@ -213,25 +261,37 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S setVideoSize() binding.apply { - mBrightnessSideScroll.initialize(activity, slideInfo, true, container, singleTap = { x, y -> - if (mConfig.allowInstantChange) { - listener?.goToPrevItem() - } else { - toggleFullscreen() - } - }, doubleTap = { x, y -> - doSkip(false) - }) + mBrightnessSideScroll.initialize( + activity, + slideInfo, + true, + container, + singleTap = { x, y -> + if (mConfig.allowInstantChange) { + listener?.goToPrevItem() + } else { + toggleFullscreen() + } + }, + doubleTap = { x, y -> + doSkip(false) + }) - mVolumeSideScroll.initialize(activity, slideInfo, false, container, singleTap = { x, y -> - if (mConfig.allowInstantChange) { - listener?.goToNextItem() - } else { - toggleFullscreen() - } - }, doubleTap = { x, y -> - doSkip(true) - }) + mVolumeSideScroll.initialize( + activity, + slideInfo, + false, + container, + singleTap = { x, y -> + if (mConfig.allowInstantChange) { + listener?.goToNextItem() + } else { + toggleFullscreen() + } + }, + doubleTap = { x, y -> + doSkip(true) + }) videoSurface.onGlobalLayout { if (mIsFragmentVisible && mConfig.autoplayVideos && !mConfig.openVideosOnSeparateScreen) { @@ -251,7 +311,8 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S override fun onResume() { super.onResume() - mConfig = requireContext().config // make sure we get a new config, in case the user changed something in the app settings + mConfig = + requireContext().config // make sure we get a new config, in case the user changed something in the app settings requireActivity().updateTextColors(binding.videoHolder) val allowVideoGestures = mConfig.allowVideoGestures mTextureView.beGoneIf(mConfig.openVideosOnSeparateScreen || mIsPanorama) @@ -321,7 +382,10 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S private fun saveVideoProgress() { if (!videoEnded()) { if (mExoPlayer != null) { - mConfig.saveLastVideoPosition(mMedium.path, mExoPlayer!!.currentPosition.toInt() / 1000) + mConfig.saveLastVideoPosition( + mMedium.path, + mExoPlayer!!.currentPosition.toInt() / 1000 + ) } else { mConfig.saveLastVideoPosition(mMedium.path, mPositionAtPause.toInt() / 1000) } @@ -387,7 +451,12 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S mPlayOnPrepared = true val loadControl = DefaultLoadControl.Builder() - .setBufferDurationsMs(EXOPLAYER_MIN_BUFFER_MS, EXOPLAYER_MAX_BUFFER_MS, EXOPLAYER_MIN_BUFFER_MS, EXOPLAYER_MIN_BUFFER_MS) + .setBufferDurationsMs( + EXOPLAYER_MIN_BUFFER_MS, + EXOPLAYER_MAX_BUFFER_MS, + EXOPLAYER_MIN_BUFFER_MS, + EXOPLAYER_MIN_BUFFER_MS + ) .setPrioritizeTimeOverSizeThresholds(true) .build() @@ -570,7 +639,8 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S private fun showPlaybackSpeedPicker() { val fragment = PlaybackSpeedFragment() - childFragmentManager.beginTransaction().add(fragment, fragment::class.java.simpleName).commit() + childFragmentManager.beginTransaction().add(fragment, fragment::class.java.simpleName) + .commit() fragment.setListener(this) } @@ -579,19 +649,28 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S if (isSlow != binding.bottomVideoTimeHolder.videoPlaybackSpeed.tag as? Boolean) { binding.bottomVideoTimeHolder.videoPlaybackSpeed.tag = isSlow - val drawableId = if (isSlow) R.drawable.ic_playback_speed_slow_vector else R.drawable.ic_playback_speed_vector + val drawableId = + if (isSlow) R.drawable.ic_playback_speed_slow_vector else R.drawable.ic_playback_speed_vector binding.bottomVideoTimeHolder.videoPlaybackSpeed - .setDrawablesRelativeWithIntrinsicBounds(AppCompatResources.getDrawable(requireContext(), drawableId)) + .setDrawablesRelativeWithIntrinsicBounds( + AppCompatResources.getDrawable( + requireContext(), + drawableId + ) + ) } @SuppressLint("SetTextI18n") - binding.bottomVideoTimeHolder.videoPlaybackSpeed.text = "${DecimalFormat("#.##").format(speed)}x" + binding.bottomVideoTimeHolder.videoPlaybackSpeed.text = + "${DecimalFormat("#.##").format(speed)}x" mExoPlayer?.setPlaybackSpeed(speed) } private fun getExtendedDetailsY(height: Int): Float { - val smallMargin = context?.resources?.getDimension(org.fossify.commons.R.dimen.small_margin) ?: return 0f - val fullscreenOffset = smallMargin + if (mIsFullscreen) 0 else requireContext().navigationBarHeight + val smallMargin = + context?.resources?.getDimension(org.fossify.commons.R.dimen.small_margin) ?: return 0f + val fullscreenOffset = + smallMargin + if (mIsFullscreen) 0 else requireContext().navigationBarHeight var actionsHeight = 0f if (!mIsFullscreen) { if (binding.bottomVideoTimeHolder.root.children.any { isVisible }) { @@ -623,9 +702,11 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S } val curr = mExoPlayer!!.currentPosition - val newProgress = if (forward) curr + FAST_FORWARD_VIDEO_MS else curr - FAST_FORWARD_VIDEO_MS + val newProgress = + if (forward) curr + FAST_FORWARD_VIDEO_MS else curr - FAST_FORWARD_VIDEO_MS val roundProgress = Math.round(newProgress / 1000f) - val limitedProgress = Math.max(Math.min(mExoPlayer!!.duration.toInt() / 1000, roundProgress), 0) + val limitedProgress = + Math.max(Math.min(mExoPlayer!!.duration.toInt() / 1000, roundProgress), 0) setPosition(limitedProgress) if (!mIsPlaying) { togglePlayPause() @@ -734,7 +815,8 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener, S mPlayPauseButton.beVisible() binding.bottomVideoTimeHolder.videoToggleMute.beVisible() binding.bottomVideoTimeHolder.videoPlaybackSpeed.beVisible() - binding.bottomVideoTimeHolder.videoPlaybackSpeed.text = "${DecimalFormat("#.##").format(mConfig.playbackSpeed)}x" + binding.bottomVideoTimeHolder.videoPlaybackSpeed.text = + "${DecimalFormat("#.##").format(mConfig.playbackSpeed)}x" } mWasVideoStarted = true