diff --git a/app/src/main/java/com/github/libretube/extensions/ToStreamItem.kt b/app/src/main/java/com/github/libretube/extensions/ToStreamItem.kt new file mode 100644 index 000000000..f58d4d298 --- /dev/null +++ b/app/src/main/java/com/github/libretube/extensions/ToStreamItem.kt @@ -0,0 +1,22 @@ +package com.github.libretube.extensions + +import com.github.libretube.api.obj.StreamItem +import com.github.libretube.api.obj.Streams + +fun Streams?.toStreamItem(videoId: String): StreamItem { + if (this == null) return StreamItem() + return StreamItem( + url = videoId, + title = title, + thumbnail = thumbnailUrl, + uploaderName = uploader, + uploaderUrl = uploaderUrl, + uploaderAvatar = uploaderAvatar, + uploadedDate = uploadDate, + uploaded = null, + duration = duration, + views = views, + uploaderVerified = uploaderVerified, + shortDescription = description + ) +} diff --git a/app/src/main/java/com/github/libretube/services/BackgroundMode.kt b/app/src/main/java/com/github/libretube/services/BackgroundMode.kt index 9cda3e3cc..f6b617682 100644 --- a/app/src/main/java/com/github/libretube/services/BackgroundMode.kt +++ b/app/src/main/java/com/github/libretube/services/BackgroundMode.kt @@ -25,6 +25,7 @@ import com.github.libretube.db.DatabaseHelper import com.github.libretube.db.DatabaseHolder import com.github.libretube.extensions.awaitQuery import com.github.libretube.extensions.toID +import com.github.libretube.extensions.toStreamItem import com.github.libretube.util.AutoPlayHelper import com.github.libretube.util.NowPlayingNotification import com.github.libretube.util.PlayerHelper @@ -146,7 +147,9 @@ class BackgroundMode : Service() { } private fun updateWatchPosition() { - player?.currentPosition?.let { DatabaseHelper.saveWatchPosition(videoId, it) } + player?.currentPosition?.let { + DatabaseHelper.saveWatchPosition(videoId, it) + } handler.postDelayed(this::updateWatchPosition, 500) } @@ -158,7 +161,7 @@ class BackgroundMode : Service() { seekToPosition: Long = 0 ) { // append the video to the playing queue - PlayingQueue.add(videoId) + PlayingQueue.add(streams.toStreamItem(videoId)) CoroutineScope(Dispatchers.IO).launch { try { streams = RetrofitInstance.api.getStreams(videoId) @@ -166,6 +169,8 @@ class BackgroundMode : Service() { return@launch } + PlayingQueue.updateCurrent(streams.toStreamItem(videoId)) + handler.post { playAudio(seekToPosition) } @@ -175,8 +180,6 @@ class BackgroundMode : Service() { private fun playAudio( seekToPosition: Long ) { - PlayingQueue.updateCurrent(videoId) - initializePlayer() setMediaItem() @@ -280,7 +283,7 @@ class BackgroundMode : Service() { if (!this::autoPlayHelper.isInitialized) autoPlayHelper = AutoPlayHelper(playlistId!!) // search for the next videoId in the playlist CoroutineScope(Dispatchers.IO).launch { - nextStreamId = autoPlayHelper.getNextVideoId(videoId, streams!!.relatedStreams!!) + nextStreamId = autoPlayHelper.getNextVideoId(videoId) } } diff --git a/app/src/main/java/com/github/libretube/ui/fragments/HomeFragment.kt b/app/src/main/java/com/github/libretube/ui/fragments/HomeFragment.kt index ca5b8a0ff..38dc23e3f 100644 --- a/app/src/main/java/com/github/libretube/ui/fragments/HomeFragment.kt +++ b/app/src/main/java/com/github/libretube/ui/fragments/HomeFragment.kt @@ -81,8 +81,6 @@ class HomeFragment : BaseFragment() { } finally { binding.homeRefresh.isRefreshing = false } - // TODO() REMOVE TESTING - PlayingQueue.streams = response runOnUiThread { binding.progressBar.visibility = View.GONE diff --git a/app/src/main/java/com/github/libretube/ui/fragments/PlayerFragment.kt b/app/src/main/java/com/github/libretube/ui/fragments/PlayerFragment.kt index 7a639500f..fa360bbb5 100644 --- a/app/src/main/java/com/github/libretube/ui/fragments/PlayerFragment.kt +++ b/app/src/main/java/com/github/libretube/ui/fragments/PlayerFragment.kt @@ -52,6 +52,7 @@ import com.github.libretube.extensions.formatShort import com.github.libretube.extensions.hideKeyboard import com.github.libretube.extensions.query import com.github.libretube.extensions.toID +import com.github.libretube.extensions.toStreamItem import com.github.libretube.models.PlayerViewModel import com.github.libretube.models.interfaces.PlayerOptionsInterface import com.github.libretube.services.BackgroundMode @@ -635,8 +636,6 @@ class PlayerFragment : BaseFragment() { private fun playVideo() { lifecycleScope.launchWhenCreated { - PlayingQueue.updateCurrent(videoId!!) - streams = try { RetrofitInstance.api.getStreams(videoId!!) } catch (e: IOException) { @@ -650,6 +649,12 @@ class PlayerFragment : BaseFragment() { return@launchWhenCreated } + PlayingQueue.updateCurrent(streams.toStreamItem(videoId!!)) + + if (PlayingQueue.size() <= 1) PlayingQueue.add( + *streams.relatedStreams.orEmpty().toTypedArray() + ) + runOnUiThread { // hide the button to skip SponsorBlock segments manually binding.sbSkipBtn.visibility = View.GONE @@ -694,7 +699,7 @@ class PlayerFragment : BaseFragment() { if (!this::autoPlayHelper.isInitialized) autoPlayHelper = AutoPlayHelper(playlistId) // search for the next videoId in the playlist lifecycleScope.launchWhenCreated { - nextStreamId = autoPlayHelper.getNextVideoId(videoId!!, streams.relatedStreams) + nextStreamId = autoPlayHelper.getNextVideoId(videoId!!) } } diff --git a/app/src/main/java/com/github/libretube/ui/sheets/PlayingQueueSheet.kt b/app/src/main/java/com/github/libretube/ui/sheets/PlayingQueueSheet.kt index e76dc62b3..87d6c8c8b 100644 --- a/app/src/main/java/com/github/libretube/ui/sheets/PlayingQueueSheet.kt +++ b/app/src/main/java/com/github/libretube/ui/sheets/PlayingQueueSheet.kt @@ -27,7 +27,7 @@ class PlayingQueueSheet : BottomSheetDialogFragment() { binding.optionsRecycler.layoutManager = LinearLayoutManager(context) binding.optionsRecycler.adapter = PlayingQueueAdapter( - PlayingQueue.streams + PlayingQueue.getStreams() ) } } diff --git a/app/src/main/java/com/github/libretube/ui/sheets/VideoOptionsBottomSheet.kt b/app/src/main/java/com/github/libretube/ui/sheets/VideoOptionsBottomSheet.kt index f174e2a33..5310b75a1 100644 --- a/app/src/main/java/com/github/libretube/ui/sheets/VideoOptionsBottomSheet.kt +++ b/app/src/main/java/com/github/libretube/ui/sheets/VideoOptionsBottomSheet.kt @@ -3,8 +3,10 @@ package com.github.libretube.ui.sheets import android.os.Bundle import android.widget.Toast import com.github.libretube.R +import com.github.libretube.api.RetrofitInstance import com.github.libretube.constants.IntentData import com.github.libretube.constants.ShareObjectType +import com.github.libretube.extensions.toStreamItem import com.github.libretube.ui.dialogs.AddToPlaylistDialog import com.github.libretube.ui.dialogs.DownloadDialog import com.github.libretube.ui.dialogs.ShareDialog @@ -12,6 +14,9 @@ import com.github.libretube.ui.views.BottomSheet import com.github.libretube.util.BackgroundHelper import com.github.libretube.util.PlayingQueue import com.github.libretube.util.PreferenceHelper +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch /** * Dialog with different options for a selected video. @@ -79,10 +84,28 @@ class VideoOptionsBottomSheet( shareDialog.show(parentFragmentManager, ShareDialog::class.java.name) } context?.getString(R.string.play_next) -> { - PlayingQueue.addAsNext(videoId) + CoroutineScope(Dispatchers.IO).launch { + try { + PlayingQueue.addAsNext( + RetrofitInstance.api.getStreams(videoId) + .toStreamItem(videoId) + ) + } catch (e: Exception) { + e.printStackTrace() + } + } } context?.getString(R.string.add_to_queue) -> { - PlayingQueue.add(videoId) + CoroutineScope(Dispatchers.IO).launch { + try { + PlayingQueue.add( + RetrofitInstance.api.getStreams(videoId) + .toStreamItem(videoId) + ) + } catch (e: Exception) { + e.printStackTrace() + } + } } } } diff --git a/app/src/main/java/com/github/libretube/util/AutoPlayHelper.kt b/app/src/main/java/com/github/libretube/util/AutoPlayHelper.kt index 1e1f17e1f..645d58fa9 100644 --- a/app/src/main/java/com/github/libretube/util/AutoPlayHelper.kt +++ b/app/src/main/java/com/github/libretube/util/AutoPlayHelper.kt @@ -16,13 +16,10 @@ class AutoPlayHelper( * get the id of the next video to be played */ suspend fun getNextVideoId( - currentVideoId: String, - relatedStreams: List? + currentVideoId: String ): String? { return if (playlistId == null) { - getNextTrendingVideoId( - relatedStreams - ) + null } else { getNextPlaylistVideoId( currentVideoId @@ -30,27 +27,6 @@ class AutoPlayHelper( } } - /** - * get the id of the next related video - */ - private fun getNextTrendingVideoId( - relatedStreams: List? - ): String? { - // don't play a video if it got played before already - if (relatedStreams == null || relatedStreams.isEmpty()) return null - var index = 0 - var nextStreamId: String? = null - while (nextStreamId == null || PlayingQueue.containsBeforeCurrent(nextStreamId)) { - nextStreamId = relatedStreams[index].url!!.toID() - if (index + 1 < relatedStreams.size) { - index += 1 - } else { - break - } - } - return nextStreamId - } - /** * get the videoId of the next video in a playlist */ diff --git a/app/src/main/java/com/github/libretube/util/PlayingQueue.kt b/app/src/main/java/com/github/libretube/util/PlayingQueue.kt index 3938eb437..cb827f89d 100644 --- a/app/src/main/java/com/github/libretube/util/PlayingQueue.kt +++ b/app/src/main/java/com/github/libretube/util/PlayingQueue.kt @@ -1,58 +1,63 @@ package com.github.libretube.util import com.github.libretube.api.obj.StreamItem +import com.github.libretube.extensions.toID object PlayingQueue { - private val queue = mutableListOf() - private var currentVideoId: String? = null - var streams: List = listOf() + private val queue = mutableListOf() + private var currentStream: StreamItem? = null - fun add(videoId: String) { - if (currentVideoId == videoId) return - if (queue.contains(videoId)) queue.remove(videoId) - queue.add(videoId) + fun add(vararg streamItem: StreamItem) { + streamItem.forEach { + if (currentStream != it) { + if (queue.contains(it)) queue.remove(it) + queue.add(it) + } + } } - fun addAsNext(videoId: String) { - if (currentVideoId == videoId) return - if (queue.contains(videoId)) queue.remove(videoId) + fun addAsNext(streamItem: StreamItem) { + if (currentStream == streamItem) return + if (queue.contains(streamItem)) queue.remove(streamItem) queue.add( - queue.indexOf(currentVideoId) + 1, - videoId + currentIndex() + 1, + streamItem ) } fun getNext(): String? { return try { - queue[currentIndex() + 1] + queue[currentIndex() + 1].url?.toID() } catch (e: Exception) { null } } fun getPrev(): String? { - val index = queue.indexOf(currentVideoId) - return if (index > 0) queue[index - 1] else null + val index = queue.indexOf(currentStream) + return if (index > 0) queue[index - 1].url?.toID() else null } fun hasPrev(): Boolean { - return queue.indexOf(currentVideoId) > 0 + return queue.indexOf(currentStream) > 0 } - fun updateCurrent(videoId: String) { - currentVideoId = videoId - queue.add(videoId) + fun updateCurrent(streamItem: StreamItem) { + currentStream = streamItem + queue.add(streamItem) } fun isNotEmpty() = queue.isNotEmpty() + fun isEmpty() = queue.isEmpty() + fun clear() = queue.clear() - fun currentIndex() = queue.indexOf(currentVideoId) + fun size() = queue.size - fun contains(videoId: String) = queue.contains(videoId) + private fun currentIndex() = queue.indexOf(currentStream) - fun containsBeforeCurrent(videoId: String): Boolean { - return queue.contains(videoId) && queue.indexOf(videoId) < currentIndex() - } + fun contains(streamItem: StreamItem) = queue.contains(streamItem) + + fun getStreams() = queue }