mirror of
https://github.com/libre-tube/LibreTube.git
synced 2024-12-14 14:20:30 +05:30
Add functionality
This commit is contained in:
parent
afe25fc67a
commit
41162fafac
@ -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
|
||||||
|
)
|
||||||
|
}
|
@ -25,6 +25,7 @@ import com.github.libretube.db.DatabaseHelper
|
|||||||
import com.github.libretube.db.DatabaseHolder
|
import com.github.libretube.db.DatabaseHolder
|
||||||
import com.github.libretube.extensions.awaitQuery
|
import com.github.libretube.extensions.awaitQuery
|
||||||
import com.github.libretube.extensions.toID
|
import com.github.libretube.extensions.toID
|
||||||
|
import com.github.libretube.extensions.toStreamItem
|
||||||
import com.github.libretube.util.AutoPlayHelper
|
import com.github.libretube.util.AutoPlayHelper
|
||||||
import com.github.libretube.util.NowPlayingNotification
|
import com.github.libretube.util.NowPlayingNotification
|
||||||
import com.github.libretube.util.PlayerHelper
|
import com.github.libretube.util.PlayerHelper
|
||||||
@ -146,7 +147,9 @@ class BackgroundMode : Service() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun updateWatchPosition() {
|
private fun updateWatchPosition() {
|
||||||
player?.currentPosition?.let { DatabaseHelper.saveWatchPosition(videoId, it) }
|
player?.currentPosition?.let {
|
||||||
|
DatabaseHelper.saveWatchPosition(videoId, it)
|
||||||
|
}
|
||||||
handler.postDelayed(this::updateWatchPosition, 500)
|
handler.postDelayed(this::updateWatchPosition, 500)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,7 +161,7 @@ class BackgroundMode : Service() {
|
|||||||
seekToPosition: Long = 0
|
seekToPosition: Long = 0
|
||||||
) {
|
) {
|
||||||
// append the video to the playing queue
|
// append the video to the playing queue
|
||||||
PlayingQueue.add(videoId)
|
PlayingQueue.add(streams.toStreamItem(videoId))
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
try {
|
try {
|
||||||
streams = RetrofitInstance.api.getStreams(videoId)
|
streams = RetrofitInstance.api.getStreams(videoId)
|
||||||
@ -166,6 +169,8 @@ class BackgroundMode : Service() {
|
|||||||
return@launch
|
return@launch
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PlayingQueue.updateCurrent(streams.toStreamItem(videoId))
|
||||||
|
|
||||||
handler.post {
|
handler.post {
|
||||||
playAudio(seekToPosition)
|
playAudio(seekToPosition)
|
||||||
}
|
}
|
||||||
@ -175,8 +180,6 @@ class BackgroundMode : Service() {
|
|||||||
private fun playAudio(
|
private fun playAudio(
|
||||||
seekToPosition: Long
|
seekToPosition: Long
|
||||||
) {
|
) {
|
||||||
PlayingQueue.updateCurrent(videoId)
|
|
||||||
|
|
||||||
initializePlayer()
|
initializePlayer()
|
||||||
setMediaItem()
|
setMediaItem()
|
||||||
|
|
||||||
@ -280,7 +283,7 @@ class BackgroundMode : Service() {
|
|||||||
if (!this::autoPlayHelper.isInitialized) autoPlayHelper = AutoPlayHelper(playlistId!!)
|
if (!this::autoPlayHelper.isInitialized) autoPlayHelper = AutoPlayHelper(playlistId!!)
|
||||||
// search for the next videoId in the playlist
|
// search for the next videoId in the playlist
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
nextStreamId = autoPlayHelper.getNextVideoId(videoId, streams!!.relatedStreams!!)
|
nextStreamId = autoPlayHelper.getNextVideoId(videoId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,8 +81,6 @@ class HomeFragment : BaseFragment() {
|
|||||||
} finally {
|
} finally {
|
||||||
binding.homeRefresh.isRefreshing = false
|
binding.homeRefresh.isRefreshing = false
|
||||||
}
|
}
|
||||||
// TODO() REMOVE TESTING
|
|
||||||
PlayingQueue.streams = response
|
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
binding.progressBar.visibility = View.GONE
|
binding.progressBar.visibility = View.GONE
|
||||||
|
|
||||||
|
@ -52,6 +52,7 @@ import com.github.libretube.extensions.formatShort
|
|||||||
import com.github.libretube.extensions.hideKeyboard
|
import com.github.libretube.extensions.hideKeyboard
|
||||||
import com.github.libretube.extensions.query
|
import com.github.libretube.extensions.query
|
||||||
import com.github.libretube.extensions.toID
|
import com.github.libretube.extensions.toID
|
||||||
|
import com.github.libretube.extensions.toStreamItem
|
||||||
import com.github.libretube.models.PlayerViewModel
|
import com.github.libretube.models.PlayerViewModel
|
||||||
import com.github.libretube.models.interfaces.PlayerOptionsInterface
|
import com.github.libretube.models.interfaces.PlayerOptionsInterface
|
||||||
import com.github.libretube.services.BackgroundMode
|
import com.github.libretube.services.BackgroundMode
|
||||||
@ -635,8 +636,6 @@ class PlayerFragment : BaseFragment() {
|
|||||||
|
|
||||||
private fun playVideo() {
|
private fun playVideo() {
|
||||||
lifecycleScope.launchWhenCreated {
|
lifecycleScope.launchWhenCreated {
|
||||||
PlayingQueue.updateCurrent(videoId!!)
|
|
||||||
|
|
||||||
streams = try {
|
streams = try {
|
||||||
RetrofitInstance.api.getStreams(videoId!!)
|
RetrofitInstance.api.getStreams(videoId!!)
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
@ -650,6 +649,12 @@ class PlayerFragment : BaseFragment() {
|
|||||||
return@launchWhenCreated
|
return@launchWhenCreated
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PlayingQueue.updateCurrent(streams.toStreamItem(videoId!!))
|
||||||
|
|
||||||
|
if (PlayingQueue.size() <= 1) PlayingQueue.add(
|
||||||
|
*streams.relatedStreams.orEmpty().toTypedArray()
|
||||||
|
)
|
||||||
|
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
// hide the button to skip SponsorBlock segments manually
|
// hide the button to skip SponsorBlock segments manually
|
||||||
binding.sbSkipBtn.visibility = View.GONE
|
binding.sbSkipBtn.visibility = View.GONE
|
||||||
@ -694,7 +699,7 @@ class PlayerFragment : BaseFragment() {
|
|||||||
if (!this::autoPlayHelper.isInitialized) autoPlayHelper = AutoPlayHelper(playlistId)
|
if (!this::autoPlayHelper.isInitialized) autoPlayHelper = AutoPlayHelper(playlistId)
|
||||||
// search for the next videoId in the playlist
|
// search for the next videoId in the playlist
|
||||||
lifecycleScope.launchWhenCreated {
|
lifecycleScope.launchWhenCreated {
|
||||||
nextStreamId = autoPlayHelper.getNextVideoId(videoId!!, streams.relatedStreams)
|
nextStreamId = autoPlayHelper.getNextVideoId(videoId!!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ class PlayingQueueSheet : BottomSheetDialogFragment() {
|
|||||||
|
|
||||||
binding.optionsRecycler.layoutManager = LinearLayoutManager(context)
|
binding.optionsRecycler.layoutManager = LinearLayoutManager(context)
|
||||||
binding.optionsRecycler.adapter = PlayingQueueAdapter(
|
binding.optionsRecycler.adapter = PlayingQueueAdapter(
|
||||||
PlayingQueue.streams
|
PlayingQueue.getStreams()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,10 @@ package com.github.libretube.ui.sheets
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import com.github.libretube.R
|
import com.github.libretube.R
|
||||||
|
import com.github.libretube.api.RetrofitInstance
|
||||||
import com.github.libretube.constants.IntentData
|
import com.github.libretube.constants.IntentData
|
||||||
import com.github.libretube.constants.ShareObjectType
|
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.AddToPlaylistDialog
|
||||||
import com.github.libretube.ui.dialogs.DownloadDialog
|
import com.github.libretube.ui.dialogs.DownloadDialog
|
||||||
import com.github.libretube.ui.dialogs.ShareDialog
|
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.BackgroundHelper
|
||||||
import com.github.libretube.util.PlayingQueue
|
import com.github.libretube.util.PlayingQueue
|
||||||
import com.github.libretube.util.PreferenceHelper
|
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.
|
* Dialog with different options for a selected video.
|
||||||
@ -79,10 +84,28 @@ class VideoOptionsBottomSheet(
|
|||||||
shareDialog.show(parentFragmentManager, ShareDialog::class.java.name)
|
shareDialog.show(parentFragmentManager, ShareDialog::class.java.name)
|
||||||
}
|
}
|
||||||
context?.getString(R.string.play_next) -> {
|
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) -> {
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,13 +16,10 @@ class AutoPlayHelper(
|
|||||||
* get the id of the next video to be played
|
* get the id of the next video to be played
|
||||||
*/
|
*/
|
||||||
suspend fun getNextVideoId(
|
suspend fun getNextVideoId(
|
||||||
currentVideoId: String,
|
currentVideoId: String
|
||||||
relatedStreams: List<com.github.libretube.api.obj.StreamItem>?
|
|
||||||
): String? {
|
): String? {
|
||||||
return if (playlistId == null) {
|
return if (playlistId == null) {
|
||||||
getNextTrendingVideoId(
|
null
|
||||||
relatedStreams
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
getNextPlaylistVideoId(
|
getNextPlaylistVideoId(
|
||||||
currentVideoId
|
currentVideoId
|
||||||
@ -30,27 +27,6 @@ class AutoPlayHelper(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* get the id of the next related video
|
|
||||||
*/
|
|
||||||
private fun getNextTrendingVideoId(
|
|
||||||
relatedStreams: List<com.github.libretube.api.obj.StreamItem>?
|
|
||||||
): 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
|
* get the videoId of the next video in a playlist
|
||||||
*/
|
*/
|
||||||
|
@ -1,58 +1,63 @@
|
|||||||
package com.github.libretube.util
|
package com.github.libretube.util
|
||||||
|
|
||||||
import com.github.libretube.api.obj.StreamItem
|
import com.github.libretube.api.obj.StreamItem
|
||||||
|
import com.github.libretube.extensions.toID
|
||||||
|
|
||||||
object PlayingQueue {
|
object PlayingQueue {
|
||||||
private val queue = mutableListOf<String>()
|
private val queue = mutableListOf<StreamItem>()
|
||||||
private var currentVideoId: String? = null
|
private var currentStream: StreamItem? = null
|
||||||
var streams: List<StreamItem> = listOf()
|
|
||||||
|
|
||||||
fun add(videoId: String) {
|
fun add(vararg streamItem: StreamItem) {
|
||||||
if (currentVideoId == videoId) return
|
streamItem.forEach {
|
||||||
if (queue.contains(videoId)) queue.remove(videoId)
|
if (currentStream != it) {
|
||||||
queue.add(videoId)
|
if (queue.contains(it)) queue.remove(it)
|
||||||
|
queue.add(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addAsNext(videoId: String) {
|
fun addAsNext(streamItem: StreamItem) {
|
||||||
if (currentVideoId == videoId) return
|
if (currentStream == streamItem) return
|
||||||
if (queue.contains(videoId)) queue.remove(videoId)
|
if (queue.contains(streamItem)) queue.remove(streamItem)
|
||||||
queue.add(
|
queue.add(
|
||||||
queue.indexOf(currentVideoId) + 1,
|
currentIndex() + 1,
|
||||||
videoId
|
streamItem
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getNext(): String? {
|
fun getNext(): String? {
|
||||||
return try {
|
return try {
|
||||||
queue[currentIndex() + 1]
|
queue[currentIndex() + 1].url?.toID()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getPrev(): String? {
|
fun getPrev(): String? {
|
||||||
val index = queue.indexOf(currentVideoId)
|
val index = queue.indexOf(currentStream)
|
||||||
return if (index > 0) queue[index - 1] else null
|
return if (index > 0) queue[index - 1].url?.toID() else null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun hasPrev(): Boolean {
|
fun hasPrev(): Boolean {
|
||||||
return queue.indexOf(currentVideoId) > 0
|
return queue.indexOf(currentStream) > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateCurrent(videoId: String) {
|
fun updateCurrent(streamItem: StreamItem) {
|
||||||
currentVideoId = videoId
|
currentStream = streamItem
|
||||||
queue.add(videoId)
|
queue.add(streamItem)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isNotEmpty() = queue.isNotEmpty()
|
fun isNotEmpty() = queue.isNotEmpty()
|
||||||
|
|
||||||
|
fun isEmpty() = queue.isEmpty()
|
||||||
|
|
||||||
fun clear() = queue.clear()
|
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 {
|
fun contains(streamItem: StreamItem) = queue.contains(streamItem)
|
||||||
return queue.contains(videoId) && queue.indexOf(videoId) < currentIndex()
|
|
||||||
}
|
fun getStreams() = queue
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user