mirror of
https://github.com/libre-tube/LibreTube.git
synced 2025-04-27 23:40:33 +05:30
Merge pull request #2180 from Bnyro/channel-share
Option to shar channels and play their latest videos
This commit is contained in:
commit
974ecb04a4
@ -22,7 +22,6 @@ import com.github.libretube.constants.PLAYER_NOTIFICATION_ID
|
|||||||
import com.github.libretube.constants.PreferenceKeys
|
import com.github.libretube.constants.PreferenceKeys
|
||||||
import com.github.libretube.db.DatabaseHolder.Companion.Database
|
import com.github.libretube.db.DatabaseHolder.Companion.Database
|
||||||
import com.github.libretube.db.obj.WatchPosition
|
import com.github.libretube.db.obj.WatchPosition
|
||||||
import com.github.libretube.enums.PlaylistType
|
|
||||||
import com.github.libretube.extensions.awaitQuery
|
import com.github.libretube.extensions.awaitQuery
|
||||||
import com.github.libretube.extensions.query
|
import com.github.libretube.extensions.query
|
||||||
import com.github.libretube.extensions.toID
|
import com.github.libretube.extensions.toID
|
||||||
@ -51,10 +50,10 @@ class BackgroundMode : Service() {
|
|||||||
private lateinit var videoId: String
|
private lateinit var videoId: String
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*PlaylistId for autoplay
|
* PlaylistId/ChannelId for autoplay
|
||||||
*/
|
*/
|
||||||
private var playlistId: String? = null
|
private var playlistId: String? = null
|
||||||
private var playlistType: PlaylistType? = null
|
private var channelId: String? = null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The response that gets when called the Api.
|
* The response that gets when called the Api.
|
||||||
@ -162,11 +161,14 @@ class BackgroundMode : Service() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add the playlist video to the queue
|
// add the playlist video to the queue
|
||||||
if (playlistId != null && PlayingQueue.isEmpty()) {
|
if (PlayingQueue.isEmpty() && playlistId != null) {
|
||||||
streams?.toStreamItem(videoId)
|
streams?.toStreamItem(videoId)?.let {
|
||||||
?.let {
|
PlayingQueue.insertPlaylist(playlistId!!, it)
|
||||||
PlayingQueue.insertPlaylist(playlistId!!, it)
|
}
|
||||||
}
|
} else if (PlayingQueue.isEmpty() && channelId != null) {
|
||||||
|
streams?.toStreamItem(videoId)?.let {
|
||||||
|
PlayingQueue.insertChannel(channelId!!, it)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
streams?.toStreamItem(videoId)?.let {
|
streams?.toStreamItem(videoId)?.let {
|
||||||
PlayingQueue.updateCurrent(it)
|
PlayingQueue.updateCurrent(it)
|
||||||
|
@ -5,6 +5,8 @@ import android.view.ViewGroup
|
|||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.github.libretube.databinding.LegacySubscriptionChannelBinding
|
import com.github.libretube.databinding.LegacySubscriptionChannelBinding
|
||||||
import com.github.libretube.extensions.toID
|
import com.github.libretube.extensions.toID
|
||||||
|
import com.github.libretube.ui.base.BaseActivity
|
||||||
|
import com.github.libretube.ui.sheets.ChannelOptionsBottomSheet
|
||||||
import com.github.libretube.ui.viewholders.LegacySubscriptionViewHolder
|
import com.github.libretube.ui.viewholders.LegacySubscriptionViewHolder
|
||||||
import com.github.libretube.util.ImageHelper
|
import com.github.libretube.util.ImageHelper
|
||||||
import com.github.libretube.util.NavigationHelper
|
import com.github.libretube.util.NavigationHelper
|
||||||
@ -36,6 +38,12 @@ class LegacySubscriptionAdapter(
|
|||||||
subscription.url!!.toID()
|
subscription.url!!.toID()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
root.setOnLongClickListener {
|
||||||
|
ChannelOptionsBottomSheet(subscription.url!!.toID(), subscription.name)
|
||||||
|
.show((root.context as BaseActivity).supportFragmentManager)
|
||||||
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ import com.github.libretube.ui.base.BaseActivity
|
|||||||
import com.github.libretube.ui.extensions.setFormattedDuration
|
import com.github.libretube.ui.extensions.setFormattedDuration
|
||||||
import com.github.libretube.ui.extensions.setWatchProgressLength
|
import com.github.libretube.ui.extensions.setWatchProgressLength
|
||||||
import com.github.libretube.ui.extensions.setupSubscriptionButton
|
import com.github.libretube.ui.extensions.setupSubscriptionButton
|
||||||
|
import com.github.libretube.ui.sheets.ChannelOptionsBottomSheet
|
||||||
import com.github.libretube.ui.sheets.PlaylistOptionsBottomSheet
|
import com.github.libretube.ui.sheets.PlaylistOptionsBottomSheet
|
||||||
import com.github.libretube.ui.sheets.VideoOptionsBottomSheet
|
import com.github.libretube.ui.sheets.VideoOptionsBottomSheet
|
||||||
import com.github.libretube.ui.viewholders.SearchViewHolder
|
import com.github.libretube.ui.viewholders.SearchViewHolder
|
||||||
@ -127,6 +128,12 @@ class SearchAdapter(
|
|||||||
NavigationHelper.navigateChannel(root.context, item.url)
|
NavigationHelper.navigateChannel(root.context, item.url)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
root.setOnLongClickListener {
|
||||||
|
ChannelOptionsBottomSheet(item.url!!.toID(), item.name)
|
||||||
|
.show((root.context as BaseActivity).supportFragmentManager)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
binding.searchSubButton.setupSubscriptionButton(item.url?.toID(), item.name?.toID())
|
binding.searchSubButton.setupSubscriptionButton(item.url?.toID(), item.name?.toID())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,9 @@ import androidx.recyclerview.widget.RecyclerView
|
|||||||
import com.github.libretube.api.obj.Subscription
|
import com.github.libretube.api.obj.Subscription
|
||||||
import com.github.libretube.databinding.ChannelSubscriptionRowBinding
|
import com.github.libretube.databinding.ChannelSubscriptionRowBinding
|
||||||
import com.github.libretube.extensions.toID
|
import com.github.libretube.extensions.toID
|
||||||
|
import com.github.libretube.ui.base.BaseActivity
|
||||||
import com.github.libretube.ui.extensions.setupSubscriptionButton
|
import com.github.libretube.ui.extensions.setupSubscriptionButton
|
||||||
|
import com.github.libretube.ui.sheets.ChannelOptionsBottomSheet
|
||||||
import com.github.libretube.ui.viewholders.SubscriptionChannelViewHolder
|
import com.github.libretube.ui.viewholders.SubscriptionChannelViewHolder
|
||||||
import com.github.libretube.util.ImageHelper
|
import com.github.libretube.util.ImageHelper
|
||||||
import com.github.libretube.util.NavigationHelper
|
import com.github.libretube.util.NavigationHelper
|
||||||
@ -36,6 +38,12 @@ class SubscriptionChannelAdapter(
|
|||||||
root.setOnClickListener {
|
root.setOnClickListener {
|
||||||
NavigationHelper.navigateChannel(root.context, subscription.url)
|
NavigationHelper.navigateChannel(root.context, subscription.url)
|
||||||
}
|
}
|
||||||
|
root.setOnLongClickListener {
|
||||||
|
ChannelOptionsBottomSheet(subscription.url!!.toID(), subscription.name)
|
||||||
|
.show((root.context as BaseActivity).supportFragmentManager)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
subscriptionSubscribe.setupSubscriptionButton(
|
subscriptionSubscribe.setupSubscriptionButton(
|
||||||
subscription.url?.toID(),
|
subscription.url?.toID(),
|
||||||
subscription.name,
|
subscription.name,
|
||||||
|
@ -127,6 +127,7 @@ class PlayerFragment : BaseFragment(), OnlinePlayerOptions {
|
|||||||
*/
|
*/
|
||||||
private var videoId: String? = null
|
private var videoId: String? = null
|
||||||
private var playlistId: String? = null
|
private var playlistId: String? = null
|
||||||
|
private var channelId: String? = null
|
||||||
private var isLive = false
|
private var isLive = false
|
||||||
private lateinit var streams: Streams
|
private lateinit var streams: Streams
|
||||||
|
|
||||||
@ -172,6 +173,7 @@ class PlayerFragment : BaseFragment(), OnlinePlayerOptions {
|
|||||||
arguments?.let {
|
arguments?.let {
|
||||||
videoId = it.getString(IntentData.videoId)!!.toID()
|
videoId = it.getString(IntentData.videoId)!!.toID()
|
||||||
playlistId = it.getString(IntentData.playlistId)
|
playlistId = it.getString(IntentData.playlistId)
|
||||||
|
channelId = it.getString(IntentData.channelId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -399,7 +401,8 @@ class PlayerFragment : BaseFragment(), OnlinePlayerOptions {
|
|||||||
requireContext(),
|
requireContext(),
|
||||||
videoId!!,
|
videoId!!,
|
||||||
exoPlayer.currentPosition,
|
exoPlayer.currentPosition,
|
||||||
playlistId
|
playlistId,
|
||||||
|
channelId
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -593,6 +596,8 @@ class PlayerFragment : BaseFragment(), OnlinePlayerOptions {
|
|||||||
CoroutineScope(Dispatchers.IO).launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
if (playlistId != null) {
|
if (playlistId != null) {
|
||||||
PlayingQueue.insertPlaylist(playlistId!!, streams.toStreamItem(videoId!!))
|
PlayingQueue.insertPlaylist(playlistId!!, streams.toStreamItem(videoId!!))
|
||||||
|
} else if (channelId != null) {
|
||||||
|
PlayingQueue.insertChannel(channelId!!, streams.toStreamItem(videoId!!))
|
||||||
} else {
|
} else {
|
||||||
PlayingQueue.updateCurrent(streams.toStreamItem(videoId!!))
|
PlayingQueue.updateCurrent(streams.toStreamItem(videoId!!))
|
||||||
if (PlayerHelper.autoInsertRelatedVideos) {
|
if (PlayerHelper.autoInsertRelatedVideos) {
|
||||||
|
@ -0,0 +1,77 @@
|
|||||||
|
package com.github.libretube.ui.sheets
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.util.Log
|
||||||
|
import com.github.libretube.R
|
||||||
|
import com.github.libretube.api.RetrofitInstance
|
||||||
|
import com.github.libretube.enums.ShareObjectType
|
||||||
|
import com.github.libretube.extensions.TAG
|
||||||
|
import com.github.libretube.extensions.toID
|
||||||
|
import com.github.libretube.obj.ShareData
|
||||||
|
import com.github.libretube.ui.dialogs.ShareDialog
|
||||||
|
import com.github.libretube.util.BackgroundHelper
|
||||||
|
import com.github.libretube.util.NavigationHelper
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dialog with different options for a selected video.
|
||||||
|
*
|
||||||
|
* Needs the [videoId] to load the content from the right video.
|
||||||
|
*/
|
||||||
|
class ChannelOptionsBottomSheet(
|
||||||
|
private val channelId: String,
|
||||||
|
private val channelName: String?
|
||||||
|
) : BaseBottomSheet() {
|
||||||
|
private val shareData = ShareData(currentChannel = channelName)
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
// List that stores the different menu options. In the future could be add more options here.
|
||||||
|
val optionsList = mutableListOf(
|
||||||
|
getString(R.string.share),
|
||||||
|
getString(R.string.play_latest_videos),
|
||||||
|
getString(R.string.playOnBackground)
|
||||||
|
)
|
||||||
|
|
||||||
|
setSimpleItems(optionsList) { which ->
|
||||||
|
when (optionsList[which]) {
|
||||||
|
getString(R.string.share) -> {
|
||||||
|
ShareDialog(channelId, ShareObjectType.CHANNEL, shareData)
|
||||||
|
.show(parentFragmentManager, null)
|
||||||
|
}
|
||||||
|
getString(R.string.play_latest_videos) -> {
|
||||||
|
try {
|
||||||
|
val channel = runBlocking {
|
||||||
|
RetrofitInstance.api.getChannel(channelId)
|
||||||
|
}
|
||||||
|
channel.relatedStreams?.firstOrNull()?.url?.toID()?.let {
|
||||||
|
NavigationHelper.navigateVideo(
|
||||||
|
requireContext(),
|
||||||
|
it,
|
||||||
|
channelId = channelId
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e(TAG(), e.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getString(R.string.playOnBackground) -> {
|
||||||
|
try {
|
||||||
|
val channel = runBlocking {
|
||||||
|
RetrofitInstance.api.getChannel(channelId)
|
||||||
|
}
|
||||||
|
channel.relatedStreams?.firstOrNull()?.url?.toID()?.let {
|
||||||
|
BackgroundHelper.playOnBackground(
|
||||||
|
requireContext(),
|
||||||
|
videoId = it,
|
||||||
|
channelId = channelId
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e(TAG(), e.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -20,13 +20,15 @@ object BackgroundHelper {
|
|||||||
context: Context,
|
context: Context,
|
||||||
videoId: String,
|
videoId: String,
|
||||||
position: Long? = null,
|
position: Long? = null,
|
||||||
playlistId: String? = null
|
playlistId: String? = null,
|
||||||
|
channelId: String? = null
|
||||||
) {
|
) {
|
||||||
// create an intent for the background mode service
|
// create an intent for the background mode service
|
||||||
val intent = Intent(context, BackgroundMode::class.java)
|
val intent = Intent(context, BackgroundMode::class.java)
|
||||||
intent.putExtra(IntentData.videoId, videoId)
|
intent.putExtra(IntentData.videoId, videoId)
|
||||||
if (playlistId != null) intent.putExtra(IntentData.playlistId, playlistId)
|
intent.putExtra(IntentData.playlistId, playlistId)
|
||||||
if (position != null) intent.putExtra("position", position)
|
intent.putExtra(IntentData.channelId, channelId)
|
||||||
|
intent.putExtra("position", position)
|
||||||
|
|
||||||
// start the background mode as foreground service
|
// start the background mode as foreground service
|
||||||
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) {
|
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) {
|
||||||
|
@ -48,13 +48,16 @@ object NavigationHelper {
|
|||||||
fun navigateVideo(
|
fun navigateVideo(
|
||||||
context: Context,
|
context: Context,
|
||||||
videoId: String?,
|
videoId: String?,
|
||||||
playlistId: String? = null
|
playlistId: String? = null,
|
||||||
|
channelId: String? = null
|
||||||
) {
|
) {
|
||||||
if (videoId == null) return
|
if (videoId == null) return
|
||||||
|
|
||||||
val bundle = Bundle()
|
val bundle = Bundle()
|
||||||
bundle.putString(IntentData.videoId, videoId.toID())
|
bundle.putString(IntentData.videoId, videoId.toID())
|
||||||
if (playlistId != null) bundle.putString(IntentData.playlistId, playlistId)
|
bundle.putString(IntentData.playlistId, playlistId)
|
||||||
|
bundle.putString(IntentData.channelId, channelId)
|
||||||
|
|
||||||
val frag = PlayerFragment()
|
val frag = PlayerFragment()
|
||||||
frag.arguments = bundle
|
frag.arguments = bundle
|
||||||
val activity = context as AppCompatActivity
|
val activity = context as AppCompatActivity
|
||||||
|
@ -110,13 +110,8 @@ object PlayingQueue {
|
|||||||
fun insertPlaylist(playlistId: String, newCurrentStream: StreamItem) {
|
fun insertPlaylist(playlistId: String, newCurrentStream: StreamItem) {
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
try {
|
try {
|
||||||
val playlistType = PlaylistsHelper.getPrivatePlaylistType(playlistId)
|
|
||||||
val playlist = PlaylistsHelper.getPlaylist(playlistId)
|
val playlist = PlaylistsHelper.getPlaylist(playlistId)
|
||||||
add(
|
add(*playlist.relatedStreams.orEmpty().toTypedArray())
|
||||||
*playlist.relatedStreams
|
|
||||||
.orEmpty()
|
|
||||||
.toTypedArray()
|
|
||||||
)
|
|
||||||
updateCurrent(newCurrentStream)
|
updateCurrent(newCurrentStream)
|
||||||
if (playlist.nextpage == null) return@launch
|
if (playlist.nextpage == null) return@launch
|
||||||
fetchMoreFromPlaylist(playlistId, playlist.nextpage)
|
fetchMoreFromPlaylist(playlistId, playlist.nextpage)
|
||||||
@ -126,6 +121,32 @@ object PlayingQueue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun fetchMoreFromChannel(channelId: String, nextPage: String?) {
|
||||||
|
var channelNextPage: String? = nextPage
|
||||||
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
while (channelNextPage != null) {
|
||||||
|
RetrofitInstance.api.getChannelNextPage(channelId, nextPage!!).apply {
|
||||||
|
add(*relatedStreams.orEmpty().toTypedArray())
|
||||||
|
channelNextPage = this.nextpage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun insertChannel(channelId: String, newCurrentStream: StreamItem) {
|
||||||
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
try {
|
||||||
|
val channel = RetrofitInstance.api.getChannel(channelId)
|
||||||
|
add(*channel.relatedStreams.orEmpty().toTypedArray())
|
||||||
|
updateCurrent(newCurrentStream)
|
||||||
|
if (channel.nextpage == null) return@launch
|
||||||
|
fetchMoreFromChannel(channelId, channel.nextpage)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun onQueueItemSelected(index: Int) {
|
fun onQueueItemSelected(index: Int) {
|
||||||
try {
|
try {
|
||||||
val streamItem = queue[index]
|
val streamItem = queue[index]
|
||||||
|
@ -414,6 +414,7 @@
|
|||||||
<string name="privacy_alert">Privacy alert</string>
|
<string name="privacy_alert">Privacy alert</string>
|
||||||
<string name="username_email">Proceed with an e-mail address that isn\'t recommended\?</string>
|
<string name="username_email">Proceed with an e-mail address that isn\'t recommended\?</string>
|
||||||
<string name="proceed">Proceed</string>
|
<string name="proceed">Proceed</string>
|
||||||
|
<string name="play_latest_videos">Play latest videos</string>
|
||||||
|
|
||||||
<!-- Notification channel strings -->
|
<!-- Notification channel strings -->
|
||||||
<string name="download_channel_name">Download Service</string>
|
<string name="download_channel_name">Download Service</string>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user