Fixing Queue and hiding next/prev buttons

This commit is contained in:
Kelvin 2023-12-08 10:44:20 +01:00
commit 1c0cfa89a3
3 changed files with 57 additions and 57 deletions

View file

@ -468,8 +468,8 @@ class VideoDetailView : ConstraintLayout {
nextVideo(); nextVideo();
}; };
_player.onDatasourceError.subscribe(::onDataSourceError); _player.onDatasourceError.subscribe(::onDataSourceError);
_player.onNext.subscribe { nextVideo(true) }; _player.onNext.subscribe { nextVideo(true, true) };
_player.onPrevious.subscribe { previousVideo(true) }; _player.onPrevious.subscribe { prevVideo(true) };
_minimize_controls_play.setOnClickListener { handlePlay(); }; _minimize_controls_play.setOnClickListener { handlePlay(); };
_minimize_controls_pause.setOnClickListener { handlePause(); }; _minimize_controls_pause.setOnClickListener { handlePause(); };
@ -547,7 +547,7 @@ class VideoDetailView : ConstraintLayout {
MediaControlReceiver.onPlayReceived.subscribe(this) { handlePlay() }; MediaControlReceiver.onPlayReceived.subscribe(this) { handlePlay() };
MediaControlReceiver.onPauseReceived.subscribe(this) { handlePause() }; MediaControlReceiver.onPauseReceived.subscribe(this) { handlePause() };
MediaControlReceiver.onNextReceived.subscribe(this) { nextVideo(true) }; MediaControlReceiver.onNextReceived.subscribe(this) { nextVideo(true) };
MediaControlReceiver.onPreviousReceived.subscribe(this) { previousVideo(true) }; MediaControlReceiver.onPreviousReceived.subscribe(this) { prevVideo(true) };
MediaControlReceiver.onCloseReceived.subscribe(this) { MediaControlReceiver.onCloseReceived.subscribe(this) {
Logger.i(TAG, "MediaControlReceiver.onCloseReceived") Logger.i(TAG, "MediaControlReceiver.onCloseReceived")
onClose.emit() onClose.emit()
@ -1542,63 +1542,26 @@ class VideoDetailView : ConstraintLayout {
_slideUpOverlay = _overlay_quality_selector; _slideUpOverlay = _overlay_quality_selector;
} }
private fun getPreviousVideo(withoutRemoval: Boolean, forceLoop: Boolean = false): IPlatformVideo? {
if (!StatePlayer.instance.hasQueue) { fun prevVideo(withoutRemoval: Boolean = false) {
if (forceLoop) { Logger.i(TAG, "prevVideo")
return StatePlayer.instance.currentVideo val next = StatePlayer.instance.prevQueueItem(withoutRemoval || _player.duration < 100 || (_player.position.toFloat() / _player.duration) < 0.9);
} else { if(next != null) {
return null setVideoOverview(next);
} }
} }
val shouldNotRemove = _player.duration < 100 || (_player.position.toFloat() / _player.duration) < 0.9 fun nextVideo(forceLoop: Boolean = false, withoutRemoval: Boolean = false): Boolean {
var previous = StatePlayer.instance.prevQueueItem(withoutRemoval || shouldNotRemove); Logger.i(TAG, "nextVideo")
if(previous == null && forceLoop) var next = StatePlayer.instance.nextQueueItem(withoutRemoval || _player.duration < 100 || (_player.position.toFloat() / _player.duration) < 0.9);
previous = StatePlayer.instance.getQueue().last();
return previous;
}
private fun getNextVideo(withoutRemoval: Boolean, forceLoop: Boolean = false): IPlatformVideo? {
if (!StatePlayer.instance.hasQueue) {
if (forceLoop) {
return StatePlayer.instance.currentVideo
} else {
return null
}
}
val shouldNotRemove = _player.duration < 100 || (_player.position.toFloat() / _player.duration) < 0.9
var next = StatePlayer.instance.nextQueueItem(withoutRemoval || shouldNotRemove);
if(next == null && forceLoop) if(next == null && forceLoop)
next = StatePlayer.instance.restartQueue(); next = StatePlayer.instance.restartQueue();
return next;
}
fun previousVideo(forceLoop: Boolean = false): Boolean {
Logger.i(TAG, "previousVideo")
val previous = getPreviousVideo(false, forceLoop);
if(previous != null) {
setVideoOverview(previous);
return true;
} else {
StatePlayer.instance.setCurrentlyPlaying(null);
}
return false;
}
fun nextVideo(forceLoop: Boolean = false): Boolean {
Logger.i(TAG, "nextVideo")
val next = getNextVideo(false, forceLoop);
if(next != null) { if(next != null) {
setVideoOverview(next); setVideoOverview(next);
return true; return true;
} else {
StatePlayer.instance.setCurrentlyPlaying(null);
} }
else
StatePlayer.instance.setCurrentlyPlaying(null);
return false; return false;
} }

View file

@ -373,7 +373,28 @@ class StatePlayer {
return null; return null;
} }
fun getNextQueueItem() : IPlatformVideo? { fun getPrevQueueItem(forceLoop: Boolean = false) : IPlatformVideo? {
synchronized(_queue) {
val shuffledQueue = _queueShuffled;
val queue = if (queueShuffle && shuffledQueue != null) {
shuffledQueue;
} else {
_queue;
}
//Init Behavior
if(_queuePosition == -1 && queue.isNotEmpty())
return queue[0];
//Standard Behavior
if(_queuePosition - 1 > 0)
return queue[_queuePosition - 1];
//Repeat Behavior (End of queue)
if(_queuePosition - 1 < 0 && queue.isNotEmpty() && (forceLoop || queueRepeat))
return queue[_queue.size - 1];
}
return null;
}
fun getNextQueueItem(forceLoop: Boolean = false) : IPlatformVideo? {
if(loopVideo) if(loopVideo)
return currentVideo; return currentVideo;
synchronized(_queue) { synchronized(_queue) {
@ -391,7 +412,7 @@ class StatePlayer {
if(_queuePosition + 1 < queue.size) if(_queuePosition + 1 < queue.size)
return queue[_queuePosition + 1]; return queue[_queuePosition + 1];
//Repeat Behavior (End of queue) //Repeat Behavior (End of queue)
if(_queuePosition + 1 == queue.size && queue.isNotEmpty() && queueRepeat) if(_queuePosition + 1 == queue.size && queue.isNotEmpty() && (forceLoop || queueRepeat))
return queue[0]; return queue[0];
} }
return null; return null;

View file

@ -35,7 +35,10 @@ import com.google.android.exoplayer2.ui.PlayerControlView
import com.google.android.exoplayer2.ui.StyledPlayerView import com.google.android.exoplayer2.ui.StyledPlayerView
import com.google.android.exoplayer2.ui.TimeBar import com.google.android.exoplayer2.ui.TimeBar
import com.google.android.exoplayer2.video.VideoSize import com.google.android.exoplayer2.video.VideoSize
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import java.util.concurrent.Executors import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
@ -300,6 +303,17 @@ class FutoVideoPlayer : FutoVideoPlayerBase {
} }
} }
StatePlayer.instance.onQueueChanged.subscribe(this) {
CoroutineScope(Dispatchers.Main).launch(Dispatchers.Main) {
updateNextPrevious();
}
}
StatePlayer.instance.onVideoChanging.subscribe(this) {
CoroutineScope(Dispatchers.Main).launch(Dispatchers.Main) {
updateNextPrevious();
}
}
updateLoopVideoUI(); updateLoopVideoUI();
if(!isInEditMode) { if(!isInEditMode) {
@ -307,10 +321,12 @@ class FutoVideoPlayer : FutoVideoPlayerBase {
} }
} }
/*fun updateNextPrevious(hasNext: Boolean, hasPrevious: Boolean) { fun updateNextPrevious() {
_buttonNext.visibility = if (hasNext) View.VISIBLE else View.GONE val vidPrev = StatePlayer.instance.getPrevQueueItem(true);
_buttonPrevious.visibility = if (hasPrevious) View.VISIBLE else View.GONE val vidNext = StatePlayer.instance.getNextQueueItem(true);
}*/ _buttonNext.visibility = if (vidNext != null) View.VISIBLE else View.GONE
_buttonPrevious.visibility = if (vidPrev != null) View.VISIBLE else View.GONE
}
private val _currentChapterUpdateInterval: Long = 1000L / Settings.instance.playback.getChapterUpdateFrames(); private val _currentChapterUpdateInterval: Long = 1000L / Settings.instance.playback.getChapterUpdateFrames();
private var _currentChapterUpdateLastPos = 0L; private var _currentChapterUpdateLastPos = 0L;