Skip to content
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
12cc5f1
implemented feature where touch and hold updates the playbackSpeed to…
aricodeine Nov 18, 2025
3b68c58
updated CHANGELOG.md
aricodeine Nov 18, 2025
3b51110
updated VideoFragment.kt to use a constant in place of a hardcoded nu…
aricodeine Nov 18, 2025
6780afc
updated CHANGELOG.md
aricodeine Nov 19, 2025
8493529
fixed several issues with long press 2x playback speed feature and ad…
aricodeine Nov 23, 2025
370c82e
Merge branch 'main' of https://github.com/aricodeine/Gallery into gal…
aricodeine Nov 23, 2025
3369833
updated VideoFragment.kt
aricodeine Nov 23, 2025
13a9ccf
Merge branch 'gallery_issue_660' of https://github.com/aricodeine/Gal…
aricodeine Nov 30, 2025
2e397d5
added a callable to detect vertical gesture and prevent 2x playback g…
aricodeine Nov 30, 2025
727587e
updated CHANGELOG.md
aricodeine Nov 30, 2025
656046e
Merge branch 'gallery_issue_660' of https://github.com/aricodeine/Gal…
aricodeine Dec 1, 2025
ca25671
update CHANGELOG.md
aricodeine Dec 1, 2025
480d438
Merge branch 'main' into gallery_issue_666
aricodeine Dec 1, 2025
e4c54e1
Merge branch 'gallery_issue_660' of https://github.com/aricodeine/Gal…
aricodeine Dec 6, 2025
9d494ee
fixed a few issues with 2x playback long press gesture feature when z…
aricodeine Dec 6, 2025
9d7e0a0
Merge remote-tracking branch 'origin/gallery_issue_666' into gallery_…
aricodeine Dec 6, 2025
5005edc
reformat code
aricodeine Dec 6, 2025
0bad54f
update conditional logic to succeed detekt
aricodeine Dec 6, 2025
739d532
Merge branch 'main' into gallery_issue_666
aricodeine Dec 8, 2025
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]
### Added
- Long press gesture to play videos at 2x speed ([#666])
- 2x speed pill to indicate triggering of 2x playback speed gesture

## [1.9.1] - 2025-11-25
### Changed
Expand Down Expand Up @@ -247,6 +250,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
[#754]: https://github.com/FossifyOrg/Gallery/issues/754
[#759]: https://github.com/FossifyOrg/Gallery/issues/759
[#786]: https://github.com/FossifyOrg/Gallery/issues/786
[#666]: https://github.com/FossifyOrg/Gallery/issues/666

[Unreleased]: https://github.com/FossifyOrg/Gallery/compare/1.9.1...HEAD
[1.9.1]: https://github.com/FossifyOrg/Gallery/compare/1.9.0...1.9.1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ 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
Expand Down Expand Up @@ -66,6 +67,7 @@ import org.fossify.gallery.activities.BaseViewerActivity
import org.fossify.gallery.activities.VideoActivity
import org.fossify.gallery.databinding.PagerVideoItemBinding
import org.fossify.gallery.extensions.config
import org.fossify.gallery.extensions.getActionBarHeight
import org.fossify.gallery.extensions.getBottomActionsHeight
import org.fossify.gallery.extensions.getFormattedDuration
import org.fossify.gallery.extensions.getFriendlyMessage
Expand All @@ -91,6 +93,8 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener,
companion object {
private const val PROGRESS = "progress"
private const val UPDATE_INTERVAL_MS = 250L
private const val TOUCH_HOLD_DURATION_MS = 300L
private const val TOUCH_HOLD_SPEED_MULTIPLIER = 2.0f
}

private var mIsFullscreen = false
Expand Down Expand Up @@ -118,6 +122,18 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener,
private var mStoredBottomActions = true
private var mStoredExtendedDetails = 0
private var mStoredRememberLastVideoPosition = false
private var mOriginalPlaybackSpeed = 1f
private var mIsLongPressActive = false

private val mTouchHoldRunnable = Runnable {
mView.parent.requestDisallowInterceptTouchEvent(true)
// This code runs after the delay, only if the user is still holding down.
mIsLongPressActive = true
mOriginalPlaybackSpeed = mExoPlayer?.playbackParameters?.speed ?: mConfig.playbackSpeed
updatePlaybackSpeed(TOUCH_HOLD_SPEED_MULTIPLIER)

mPlaybackSpeedPill.fadeIn()
}

private lateinit var mTimeHolder: View
private lateinit var mBrightnessSideScroll: MediaSideScroll
Expand All @@ -130,6 +146,7 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener,
private lateinit var mCurrTimeView: TextView
private lateinit var mPlayPauseButton: ImageView
private lateinit var mSeekBar: SeekBar
private lateinit var mPlaybackSpeedPill: TextView

override fun onCreateView(
inflater: LayoutInflater,
Expand Down Expand Up @@ -170,6 +187,7 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener,
}

mSeekBar = bottomVideoTimeHolder.videoSeekbar
mPlaybackSpeedPill = playbackSpeedPill
mSeekBar.setOnSeekBarChangeListener(this@VideoFragment)
// adding an empty click listener just to avoid ripple animation at toggling fullscreen
mSeekBar.setOnClickListener { }
Expand All @@ -178,6 +196,12 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener,
mCurrTimeView = bottomVideoTimeHolder.videoCurrTime
mBrightnessSideScroll = videoBrightnessController
mVolumeSideScroll = videoVolumeController
mBrightnessSideScroll.onVerticalScroll = {
mTimerHandler.removeCallbacks(mTouchHoldRunnable)
}
mVolumeSideScroll.onVerticalScroll = {
mTimerHandler.removeCallbacks(mTouchHoldRunnable)
}
mTextureView = videoSurface
mTextureView.surfaceTextureListener = this@VideoFragment

Expand Down Expand Up @@ -215,6 +239,7 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener,
if (videoSurfaceFrame.controller.state.zoom == 1f) {
handleEvent(event)
}
handleTouchHoldEvent(event)

gestureDetector.onTouchEvent(event)
false
Expand All @@ -223,6 +248,15 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener,

ViewCompat.setOnApplyWindowInsetsListener(binding.videoHolder) { _, insets ->
val system = insets.getInsetsIgnoringVisibility(Type.systemBars())

val pillTopMargin = system.top + resources.getActionBarHeight(context) +
resources.getDimension(org.fossify.commons.R.dimen.normal_margin).toInt()
(mPlaybackSpeedPill.layoutParams as? RelativeLayout.LayoutParams)?.apply {
setMargins(
0, pillTopMargin, 0, 0
)
}

binding.bottomActionsDummy.updateLayoutParams<ViewGroup.LayoutParams> {
height = resources.getBottomActionsHeight() + system.bottom
}
Expand Down Expand Up @@ -288,7 +322,6 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener,
doubleTap = { x, y ->
doSkip(false)
})

mVolumeSideScroll.initialize(
activity,
slideInfo,
Expand Down Expand Up @@ -942,4 +975,24 @@ class VideoFragment : ViewPagerFragment(), TextureView.SurfaceTextureListener,
mTextureView.layoutParams = this
}
}

private fun handleTouchHoldEvent(event: MotionEvent) {
when (event.action) {
MotionEvent.ACTION_DOWN -> {
if (mIsPlaying) {
mTimerHandler.postDelayed(mTouchHoldRunnable, TOUCH_HOLD_DURATION_MS)
}
}

MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
mTimerHandler.removeCallbacks(mTouchHoldRunnable)

if (mIsLongPressActive) {
updatePlaybackSpeed(mOriginalPlaybackSpeed)
mIsLongPressActive = false
mPlaybackSpeedPill.fadeOut()
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class MediaSideScroll(context: Context, attrs: AttributeSet) : RelativeLayout(co

private var mSlideInfoText = ""
private var mSlideInfoFadeHandler = Handler()
internal var onVerticalScroll: (() -> Unit)? = null
private var mParentView: ViewGroup? = null
private var activity: Activity? = null
private var doubleTap: ((Float, Float) -> Unit)? = null
Expand Down Expand Up @@ -106,6 +107,7 @@ class MediaSideScroll(context: Context, attrs: AttributeSet) : RelativeLayout(co
val diffY = mTouchDownY - event.rawY

if (Math.abs(diffY) > dragThreshold && Math.abs(diffY) > Math.abs(diffX)) {
onVerticalScroll?.invoke()
var percent = ((diffY / mViewHeight) * 100).toInt() * 3
percent = Math.min(100, Math.max(-100, percent))

Expand Down
7 changes: 7 additions & 0 deletions app/src/main/res/drawable/playback_pill_background.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#99000000" />
<corners android:radius="@dimen/bottom_sheet_corner_radius" />

</shape>
20 changes: 20 additions & 0 deletions app/src/main/res/layout/pager_video_item.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,26 @@
android:layout_height="match_parent"
android:layoutDirection="ltr">

<TextView
android:id="@+id/playback_speed_pill"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="@dimen/label_start_margin"
android:background="@drawable/playback_pill_background"
android:elevation="10dp"
android:paddingStart="@dimen/list_item_padding_horizontal"
android:paddingTop="@dimen/list_item_padding_vertical"
android:paddingEnd="@dimen/list_item_padding_horizontal"
android:paddingBottom="@dimen/list_item_padding_vertical"
android:text="@string/playback_speed_display_text"
android:textColor="@android:color/white"
android:textSize="@dimen/list_secondary_text_size"
android:textStyle="bold"
android:visibility="gone"
tools:visibility="visible" />

<ImageView
android:id="@+id/video_preview"
android:layout_width="match_parent"
Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,7 @@
<string name="faq_17_text">That stopped working due to the system changes that came with Android 11 too, the app cannot browse real folders anymore, it relies on the so called MediaStore at fetching data.</string>
<string name="faq_18_title">Why do I see ads during video playback?</string>
<string name="faq_18_text">Our apps have no ads whatsoever. If you see them during video playback, you must be using some other apps video player. Try finding your default video player in the device settings, then do a \"Clear defaults\" on it. The next time you invoke some video intent you will see an app picker prompt, where you can select what app you want to use.</string>
<string name="playback_speed_display_text">2x >></string>
<!--
Haven't found some strings? There's more at
https://github.com/FossifyOrg/Commons/tree/master/commons/src/main/res
Expand Down
Loading