mirror of
https://github.com/libre-tube/LibreTube.git
synced 2024-12-15 06:40:30 +05:30
Merge pull request #729 from Bnyro/master
Multi-Tap to seek forward/backward
This commit is contained in:
commit
6fb343a3e6
@ -38,7 +38,6 @@ import com.github.libretube.util.LocaleHelper
|
||||
import com.github.libretube.util.RetrofitInstance
|
||||
import com.github.libretube.util.ThemeHelper
|
||||
import com.google.android.material.color.DynamicColors
|
||||
import com.google.android.material.color.MaterialColors
|
||||
import com.google.android.material.elevation.SurfaceColors
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
|
@ -1,15 +0,0 @@
|
||||
package com.github.libretube.activities
|
||||
|
||||
import android.app.Activity
|
||||
import android.os.Bundle
|
||||
import com.github.libretube.R
|
||||
import com.google.android.material.color.DynamicColors
|
||||
|
||||
class Player : Activity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
DynamicColors.applyToActivityIfAvailable(this)
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_player)
|
||||
}
|
||||
}
|
@ -11,6 +11,8 @@ import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Build.VERSION.SDK_INT
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.os.PowerManager
|
||||
import android.support.v4.media.session.MediaSessionCompat
|
||||
import android.text.Html
|
||||
@ -21,6 +23,7 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Toast
|
||||
import androidx.constraintlayout.motion.widget.MotionLayout
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.net.toUri
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.core.view.isVisible
|
||||
@ -54,6 +57,7 @@ import com.github.libretube.util.CronetHelper
|
||||
import com.github.libretube.util.DescriptionAdapter
|
||||
import com.github.libretube.util.RetrofitInstance
|
||||
import com.github.libretube.util.formatShort
|
||||
import com.github.libretube.views.DoubleClickListener
|
||||
import com.google.android.exoplayer2.C
|
||||
import com.google.android.exoplayer2.DefaultLoadControl
|
||||
import com.google.android.exoplayer2.ExoPlayer
|
||||
@ -75,6 +79,7 @@ import com.google.android.exoplayer2.upstream.DataSource
|
||||
import com.google.android.exoplayer2.upstream.DefaultDataSource
|
||||
import com.google.android.exoplayer2.upstream.DefaultHttpDataSource
|
||||
import com.google.android.exoplayer2.util.RepeatModeUtil
|
||||
import com.google.android.exoplayer2.video.VideoSize
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.squareup.picasso.Picasso
|
||||
@ -319,10 +324,6 @@ class PlayerFragment : Fragment() {
|
||||
isFullScreen = !isFullScreen
|
||||
|
||||
// scale the exo player center controls
|
||||
playerBinding.exoFfwdWithAmount.scaleX = scaleFactor
|
||||
playerBinding.exoFfwdWithAmount.scaleY = scaleFactor
|
||||
playerBinding.exoRewWithAmount.scaleX = scaleFactor
|
||||
playerBinding.exoRewWithAmount.scaleY = scaleFactor
|
||||
playerBinding.exoPlayPause.scaleX = scaleFactor
|
||||
playerBinding.exoPlayPause.scaleY = scaleFactor
|
||||
}
|
||||
@ -691,6 +692,8 @@ class PlayerFragment : Fragment() {
|
||||
|
||||
playerBinding.exoTitle.text = response.title
|
||||
|
||||
enableDoubleTapToSeek()
|
||||
|
||||
// init the chapters recyclerview
|
||||
if (response.chapters != null) initializeChapters(response.chapters)
|
||||
|
||||
@ -705,7 +708,6 @@ class PlayerFragment : Fragment() {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
override fun onVideoSizeChanged(
|
||||
videoSize: VideoSize
|
||||
) {
|
||||
@ -713,14 +715,14 @@ class PlayerFragment : Fragment() {
|
||||
// height or width must be cast to float as int/int will give 0
|
||||
|
||||
// Redraw the player container with the new layout height
|
||||
val params = binding.player.layoutParams
|
||||
params.height = videoSize.height / videoSize.width * params.width
|
||||
binding.player.layoutParams = params
|
||||
binding.player.requestLayout()
|
||||
(binding.mainContainer.layoutParams as ConstraintLayout.LayoutParams).apply {
|
||||
matchConstraintPercentHeight = (
|
||||
videoSize.height / videoSize.width
|
||||
).toFloat()
|
||||
matchConstraintPercentHeight = (videoSize.height / videoSize.width).toFloat()
|
||||
}
|
||||
binding.mainContainer.requestLayout()
|
||||
}
|
||||
*/
|
||||
|
||||
@Deprecated(message = "Deprecated", level = DeprecationLevel.HIDDEN)
|
||||
override fun onPlayerStateChanged(
|
||||
@ -844,6 +846,51 @@ class PlayerFragment : Fragment() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun enableDoubleTapToSeek() {
|
||||
val seekIncrement =
|
||||
PreferenceHelper.getString(requireContext(), "seek_increment", "5")?.toLong()!! * 1000
|
||||
|
||||
// enable rewind button
|
||||
binding.rewindFL.setOnClickListener(
|
||||
DoubleClickListener(
|
||||
callback = object : DoubleClickListener.Callback {
|
||||
override fun doubleClicked() {
|
||||
binding.rewindBTN.visibility = View.VISIBLE
|
||||
exoPlayer.seekTo(exoPlayer.currentPosition - seekIncrement)
|
||||
Handler(Looper.getMainLooper()).postDelayed({
|
||||
binding.rewindBTN.visibility = View.INVISIBLE
|
||||
}, 700)
|
||||
}
|
||||
|
||||
override fun singleClicked() {
|
||||
if (exoPlayerView.isControllerFullyVisible) exoPlayerView.hideController()
|
||||
else exoPlayerView.showController()
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
// enable fast forward button
|
||||
binding.forwardFL.setOnClickListener(
|
||||
DoubleClickListener(
|
||||
callback = object : DoubleClickListener.Callback {
|
||||
override fun doubleClicked() {
|
||||
binding.forwardBTN.visibility = View.VISIBLE
|
||||
exoPlayer.seekTo(exoPlayer.currentPosition + seekIncrement)
|
||||
Handler(Looper.getMainLooper()).postDelayed({
|
||||
binding.forwardBTN.visibility = View.INVISIBLE
|
||||
}, 700)
|
||||
}
|
||||
|
||||
override fun singleClicked() {
|
||||
if (exoPlayerView.isControllerFullyVisible) exoPlayerView.hideController()
|
||||
else exoPlayerView.showController()
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private fun initializeChapters(chapters: List<ChapterSegment>) {
|
||||
if (chapters.isNotEmpty()) {
|
||||
binding.chaptersRecView.layoutManager =
|
||||
@ -1064,8 +1111,6 @@ class PlayerFragment : Fragment() {
|
||||
val visibility = if (isLocked) View.VISIBLE else View.GONE
|
||||
playerBinding.exoTopBarRight.visibility = visibility
|
||||
playerBinding.exoPlayPause.visibility = visibility
|
||||
playerBinding.exoFfwdWithAmount.visibility = visibility
|
||||
playerBinding.exoRewWithAmount.visibility = visibility
|
||||
playerBinding.exoBottomBar.visibility = visibility
|
||||
playerBinding.closeImageButton.visibility = visibility
|
||||
playerBinding.exoTitle.visibility = visibility
|
||||
|
@ -0,0 +1,49 @@
|
||||
package com.github.libretube.views
|
||||
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.view.View
|
||||
|
||||
class DoubleClickListener(
|
||||
private val doubleClickTimeLimitMills: Long = 300,
|
||||
private val callback: Callback
|
||||
) : View.OnClickListener {
|
||||
private var lastClicked: Long = -1L
|
||||
private var doubleClicked: Boolean = false
|
||||
|
||||
override fun onClick(v: View?) {
|
||||
lastClicked = when {
|
||||
lastClicked == -1L -> {
|
||||
doubleClicked = false
|
||||
System.currentTimeMillis()
|
||||
}
|
||||
isDoubleClicked() -> {
|
||||
doubleClicked = true
|
||||
callback.doubleClicked()
|
||||
-1L
|
||||
}
|
||||
else -> {
|
||||
Handler(Looper.getMainLooper()).postDelayed({
|
||||
if (!doubleClicked) callback.singleClicked()
|
||||
}, doubleClickTimeLimitMills)
|
||||
System.currentTimeMillis()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getTimeDiff(from: Long, to: Long): Long {
|
||||
return to - from
|
||||
}
|
||||
|
||||
private fun isDoubleClicked(): Boolean {
|
||||
return getTimeDiff(
|
||||
lastClicked,
|
||||
System.currentTimeMillis()
|
||||
) <= doubleClickTimeLimitMills
|
||||
}
|
||||
|
||||
interface Callback {
|
||||
fun doubleClicked()
|
||||
fun singleClicked()
|
||||
}
|
||||
}
|
10
app/src/main/res/drawable/ic_forward.xml
Normal file
10
app/src/main/res/drawable/ic_forward.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:tint="@android:color/white"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M4,18l8.5,-6L4,6v12zM13,6v12l8.5,-6L13,6z" />
|
||||
</vector>
|
10
app/src/main/res/drawable/ic_rewind.xml
Normal file
10
app/src/main/res/drawable/ic_rewind.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:tint="@android:color/white"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M11,18L11,6l-8.5,6 8.5,6zM11.5,12l8.5,6L20,6l-8.5,6z" />
|
||||
</vector>
|
@ -1,16 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@android:color/black"
|
||||
tools:context=".activities.Player">
|
||||
|
||||
<com.github.libretube.views.CustomExoPlayerView
|
||||
android:id="@+id/fullscreen_player"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@android:color/black" />
|
||||
|
||||
|
||||
</RelativeLayout>
|
@ -1,26 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!-- Copyright 2020 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<!-- 0dp dimensions are used to prevent this view from influencing the size of
|
||||
the parent view if it uses "wrap_content". It is expanded to occupy the
|
||||
entirety of the parent in code, after the parent's size has been
|
||||
determined. See: https://github.com/google/ExoPlayer/issues/8726.
|
||||
-->
|
||||
|
||||
<View
|
||||
android:id="@id/exo_controls_background"
|
||||
android:layout_width="0dp"
|
||||
@ -189,7 +170,6 @@
|
||||
android:id="@+id/progress_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="15dp"
|
||||
android:layout_above="@id/exo_basic_controls"
|
||||
android:layout_gravity="bottom"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginRight="10dp"
|
||||
@ -226,48 +206,15 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:background="@android:color/transparent"
|
||||
android:clipToPadding="false"
|
||||
android:gravity="center"
|
||||
android:padding="@dimen/exo_styled_controls_padding">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<Button
|
||||
android:id="@id/exo_rew_with_amount"
|
||||
style="@style/ExoStyledControls.Button.Center.RewWithAmount"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginStart="20dp"
|
||||
android:paddingLeft="4dp"
|
||||
android:paddingRight="4dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<ImageButton
|
||||
android:id="@id/exo_play_pause"
|
||||
style="@style/ExoStyledControls.Button.Center.PlayPause"
|
||||
app:tint="@android:color/white" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<Button
|
||||
android:id="@id/exo_ffwd_with_amount"
|
||||
style="@style/ExoStyledControls.Button.Center.FfwdWithAmount"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginEnd="20dp"
|
||||
android:paddingLeft="4dp"
|
||||
android:paddingRight="4dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</merge>
|
@ -358,11 +358,50 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/colorSurface"
|
||||
android:scaleType="centerCrop"
|
||||
app:layout_constraintBottom_toBottomOf="@id/main_container"
|
||||
app:layout_constraintStart_toStartOf="@id/main_container"
|
||||
app:layout_constraintTop_toTopOf="@id/main_container"
|
||||
app:show_buffering="always" />
|
||||
app:show_buffering="always">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/forwardFL"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center_vertical|end"
|
||||
android:layout_marginVertical="50dp">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/forwardBTN"
|
||||
android:layout_width="150dp"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?android:selectableItemBackgroundBorderless"
|
||||
android:clickable="false"
|
||||
android:src="@drawable/ic_forward"
|
||||
android:visibility="invisible"
|
||||
app:tint="@android:color/white" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/rewindFL"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center_vertical|start"
|
||||
android:layout_marginVertical="50dp">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/rewindBTN"
|
||||
android:layout_width="150dp"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?android:selectableItemBackgroundBorderless"
|
||||
android:clickable="false"
|
||||
android:src="@drawable/ic_rewind"
|
||||
android:visibility="invisible"
|
||||
app:tint="@android:color/white" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
</com.github.libretube.views.CustomExoPlayerView>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/close_imageView"
|
||||
|
Loading…
Reference in New Issue
Block a user