Simple play/pause overlay
This commit is contained in:
parent
e9778d6feb
commit
e24d5b3ca4
|
@ -21,6 +21,10 @@ sealed class AttachmentEvents {
|
||||||
}
|
}
|
||||||
|
|
||||||
interface AttachmentEventListener {
|
interface AttachmentEventListener {
|
||||||
|
|
||||||
fun onEvent(event: AttachmentEvents)
|
fun onEvent(event: AttachmentEvents)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sealed class AttachmentCommands {
|
||||||
|
object PauseVideo : AttachmentCommands()
|
||||||
|
object StartVideo : AttachmentCommands()
|
||||||
|
}
|
||||||
|
|
|
@ -152,6 +152,7 @@ abstract class AttachmentViewerActivity : AppCompatActivity(), AttachmentEventLi
|
||||||
super.onResume()
|
super.onResume()
|
||||||
attachmentsAdapter.onResume(currentPosition)
|
attachmentsAdapter.onResume(currentPosition)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
|
override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
|
||||||
// The zoomable view is configured to disallow interception when image is zoomed
|
// The zoomable view is configured to disallow interception when image is zoomed
|
||||||
|
|
||||||
|
@ -302,6 +303,12 @@ abstract class AttachmentViewerActivity : AppCompatActivity(), AttachmentEventLi
|
||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public fun handle(commands: AttachmentCommands) {
|
||||||
|
(attachmentsAdapter.recyclerView?.findViewHolderForAdapterPosition(currentPosition) as? BaseViewHolder)?.let {
|
||||||
|
it.handleCommand(commands)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun hideSystemUI() {
|
private fun hideSystemUI() {
|
||||||
systemUiVisibility = false
|
systemUiVisibility = false
|
||||||
// Enables regular immersive mode.
|
// Enables regular immersive mode.
|
||||||
|
|
|
@ -31,6 +31,8 @@ abstract class BaseViewHolder constructor(itemView: View) :
|
||||||
open fun entersBackground() {}
|
open fun entersBackground() {}
|
||||||
open fun entersForeground() {}
|
open fun entersForeground() {}
|
||||||
open fun onSelected(selected: Boolean) {}
|
open fun onSelected(selected: Boolean) {}
|
||||||
|
|
||||||
|
open fun handleCommand(commands: AttachmentCommands) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AttachmentViewHolder constructor(itemView: View) :
|
class AttachmentViewHolder constructor(itemView: View) :
|
||||||
|
@ -123,7 +125,6 @@ class AttachmentsAdapter() : RecyclerView.Adapter<BaseViewHolder>() {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun onPause(position: Int) {
|
fun onPause(position: Int) {
|
||||||
val holder = recyclerView?.findViewHolderForAdapterPosition(position) as? BaseViewHolder
|
val holder = recyclerView?.findViewHolderForAdapterPosition(position) as? BaseViewHolder
|
||||||
holder?.entersBackground()
|
holder?.entersBackground()
|
||||||
|
@ -132,7 +133,6 @@ class AttachmentsAdapter() : RecyclerView.Adapter<BaseViewHolder>() {
|
||||||
fun onResume(position: Int) {
|
fun onResume(position: Int) {
|
||||||
val holder = recyclerView?.findViewHolderForAdapterPosition(position) as? BaseViewHolder
|
val holder = recyclerView?.findViewHolderForAdapterPosition(position) as? BaseViewHolder
|
||||||
holder?.entersForeground()
|
holder?.entersForeground()
|
||||||
|
|
||||||
}
|
}
|
||||||
// override fun getItemCount(): Int {
|
// override fun getItemCount(): Int {
|
||||||
// return 8
|
// return 8
|
||||||
|
|
|
@ -26,7 +26,6 @@ import androidx.core.view.isVisible
|
||||||
import io.reactivex.Observable
|
import io.reactivex.Observable
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||||
import io.reactivex.disposables.Disposable
|
import io.reactivex.disposables.Disposable
|
||||||
import kotlinx.coroutines.selects.select
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.lang.ref.WeakReference
|
import java.lang.ref.WeakReference
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
@ -41,6 +40,7 @@ class VideoViewHolder constructor(itemView: View) :
|
||||||
private var mVideoPath: String? = null
|
private var mVideoPath: String? = null
|
||||||
private var progressDisposable: Disposable? = null
|
private var progressDisposable: Disposable? = null
|
||||||
private var progress: Int = 0
|
private var progress: Int = 0
|
||||||
|
private var wasPaused = false
|
||||||
|
|
||||||
var eventListener: WeakReference<AttachmentEventListener>? = null
|
var eventListener: WeakReference<AttachmentEventListener>? = null
|
||||||
|
|
||||||
|
@ -99,7 +99,6 @@ class VideoViewHolder constructor(itemView: View) :
|
||||||
videoView.stopPlayback()
|
videoView.stopPlayback()
|
||||||
videoView.pause()
|
videoView.pause()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun entersForeground() {
|
override fun entersForeground() {
|
||||||
|
@ -111,11 +110,11 @@ class VideoViewHolder constructor(itemView: View) :
|
||||||
if (videoView.isPlaying) {
|
if (videoView.isPlaying) {
|
||||||
progress = videoView.currentPosition
|
progress = videoView.currentPosition
|
||||||
videoView.stopPlayback()
|
videoView.stopPlayback()
|
||||||
progressDisposable?.dispose()
|
|
||||||
progressDisposable = null
|
|
||||||
} else {
|
} else {
|
||||||
progress = 0
|
progress = 0
|
||||||
}
|
}
|
||||||
|
progressDisposable?.dispose()
|
||||||
|
progressDisposable = null
|
||||||
} else {
|
} else {
|
||||||
if (mVideoPath != null) {
|
if (mVideoPath != null) {
|
||||||
startPlaying()
|
startPlaying()
|
||||||
|
@ -144,13 +143,30 @@ class VideoViewHolder constructor(itemView: View) :
|
||||||
}
|
}
|
||||||
|
|
||||||
videoView.setVideoPath(mVideoPath)
|
videoView.setVideoPath(mVideoPath)
|
||||||
videoView.start()
|
if (!wasPaused) {
|
||||||
if (progress > 0) {
|
videoView.start()
|
||||||
videoView.seekTo(progress)
|
if (progress > 0) {
|
||||||
|
videoView.seekTo(progress)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun handleCommand(commands: AttachmentCommands) {
|
||||||
|
if (!isSelected) return
|
||||||
|
when (commands) {
|
||||||
|
AttachmentCommands.StartVideo -> {
|
||||||
|
wasPaused = false
|
||||||
|
videoView.start()
|
||||||
|
}
|
||||||
|
AttachmentCommands.PauseVideo -> {
|
||||||
|
wasPaused = true
|
||||||
|
videoView.pause()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun bind(attachmentInfo: AttachmentInfo) {
|
override fun bind(attachmentInfo: AttachmentInfo) {
|
||||||
progress = 0
|
progress = 0
|
||||||
|
wasPaused = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ class AttachmentOverlayView @JvmOverloads constructor(
|
||||||
|
|
||||||
var onShareCallback: (() -> Unit)? = null
|
var onShareCallback: (() -> Unit)? = null
|
||||||
var onBack: (() -> Unit)? = null
|
var onBack: (() -> Unit)? = null
|
||||||
|
var onPlayPause: ((play: Boolean) -> Unit)? = null
|
||||||
|
|
||||||
private val counterTextView: TextView
|
private val counterTextView: TextView
|
||||||
private val infoTextView: TextView
|
private val infoTextView: TextView
|
||||||
|
@ -42,6 +43,8 @@ class AttachmentOverlayView @JvmOverloads constructor(
|
||||||
private val overlayPlayPauseButton: ImageView
|
private val overlayPlayPauseButton: ImageView
|
||||||
private val overlaySeekBar: SeekBar
|
private val overlaySeekBar: SeekBar
|
||||||
|
|
||||||
|
var isPlaying = false
|
||||||
|
|
||||||
val videoControlsGroup: Group
|
val videoControlsGroup: Group
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
@ -61,6 +64,9 @@ class AttachmentOverlayView @JvmOverloads constructor(
|
||||||
findViewById<ImageView>(R.id.overlayShareButton).setOnClickListener {
|
findViewById<ImageView>(R.id.overlayShareButton).setOnClickListener {
|
||||||
onShareCallback?.invoke()
|
onShareCallback?.invoke()
|
||||||
}
|
}
|
||||||
|
findViewById<ImageView>(R.id.overlayPlayPauseButton).setOnClickListener {
|
||||||
|
onPlayPause?.invoke(!isPlaying)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateWith(counter: String, senderInfo: String) {
|
fun updateWith(counter: String, senderInfo: String) {
|
||||||
|
@ -74,6 +80,7 @@ class AttachmentOverlayView @JvmOverloads constructor(
|
||||||
overlayPlayPauseButton.setImageResource(if (!event.isPlaying) R.drawable.ic_play_arrow else R.drawable.ic_pause)
|
overlayPlayPauseButton.setImageResource(if (!event.isPlaying) R.drawable.ic_play_arrow else R.drawable.ic_pause)
|
||||||
val safeDuration = (if (event.duration == 0) 100 else event.duration).toFloat()
|
val safeDuration = (if (event.duration == 0) 100 else event.duration).toFloat()
|
||||||
val percent = ((event.progress / safeDuration) * 100f).toInt().coerceAtMost(100)
|
val percent = ((event.progress / safeDuration) * 100f).toInt().coerceAtMost(100)
|
||||||
|
isPlaying = event.isPlaying
|
||||||
overlaySeekBar.progress = percent
|
overlaySeekBar.progress = percent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,7 @@ class RoomAttachmentProvider(
|
||||||
interface InteractionListener {
|
interface InteractionListener {
|
||||||
fun onDismissTapped()
|
fun onDismissTapped()
|
||||||
fun onShareTapped()
|
fun onShareTapped()
|
||||||
|
fun onPlayPause(play: Boolean)
|
||||||
}
|
}
|
||||||
|
|
||||||
var interactionListener: InteractionListener? = null
|
var interactionListener: InteractionListener? = null
|
||||||
|
@ -197,6 +198,9 @@ class RoomAttachmentProvider(
|
||||||
overlayView?.onShareCallback = {
|
overlayView?.onShareCallback = {
|
||||||
interactionListener?.onShareTapped()
|
interactionListener?.onShareTapped()
|
||||||
}
|
}
|
||||||
|
overlayView?.onPlayPause = { play ->
|
||||||
|
interactionListener?.onPlayPause(play)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
val item = attachments[position]
|
val item = attachments[position]
|
||||||
val dateString = item.root.localDateTime().let {
|
val dateString = item.root.localDateTime().let {
|
||||||
|
|
|
@ -39,6 +39,7 @@ import im.vector.matrix.android.api.session.room.model.message.getFileUrl
|
||||||
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
||||||
import im.vector.matrix.android.internal.crypto.attachments.toElementToDecrypt
|
import im.vector.matrix.android.internal.crypto.attachments.toElementToDecrypt
|
||||||
import im.vector.riotx.R
|
import im.vector.riotx.R
|
||||||
|
import im.vector.riotx.attachmentviewer.AttachmentCommands
|
||||||
import im.vector.riotx.attachmentviewer.AttachmentViewerActivity
|
import im.vector.riotx.attachmentviewer.AttachmentViewerActivity
|
||||||
import im.vector.riotx.core.di.ActiveSessionHolder
|
import im.vector.riotx.core.di.ActiveSessionHolder
|
||||||
import im.vector.riotx.core.di.DaggerScreenComponent
|
import im.vector.riotx.core.di.DaggerScreenComponent
|
||||||
|
@ -242,6 +243,10 @@ class VectorAttachmentViewerActivity : AttachmentViewerActivity(), RoomAttachmen
|
||||||
animateClose()
|
animateClose()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onPlayPause(play: Boolean) {
|
||||||
|
handle(if (play) AttachmentCommands.StartVideo else AttachmentCommands.PauseVideo)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onShareTapped() {
|
override fun onShareTapped() {
|
||||||
// Share
|
// Share
|
||||||
eventList?.get(currentPosition)?.let { timelineEvent ->
|
eventList?.get(currentPosition)?.let { timelineEvent ->
|
||||||
|
|
Loading…
Reference in New Issue