Merge pull request #2180 from Bnyro/channel-share

Option to shar channels and play their latest videos
This commit is contained in:
Bnyro 2022-12-02 14:46:43 +01:00 committed by GitHub
commit 974ecb04a4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 154 additions and 20 deletions

View File

@ -22,7 +22,6 @@ import com.github.libretube.constants.PLAYER_NOTIFICATION_ID
import com.github.libretube.constants.PreferenceKeys
import com.github.libretube.db.DatabaseHolder.Companion.Database
import com.github.libretube.db.obj.WatchPosition
import com.github.libretube.enums.PlaylistType
import com.github.libretube.extensions.awaitQuery
import com.github.libretube.extensions.query
import com.github.libretube.extensions.toID
@ -51,10 +50,10 @@ class BackgroundMode : Service() {
private lateinit var videoId: String
/**
*PlaylistId for autoplay
* PlaylistId/ChannelId for autoplay
*/
private var playlistId: String? = null
private var playlistType: PlaylistType? = null
private var channelId: String? = null
/**
* The response that gets when called the Api.
@ -162,11 +161,14 @@ class BackgroundMode : Service() {
}
// add the playlist video to the queue
if (playlistId != null && PlayingQueue.isEmpty()) {
streams?.toStreamItem(videoId)
?.let {
PlayingQueue.insertPlaylist(playlistId!!, it)
}
if (PlayingQueue.isEmpty() && playlistId != null) {
streams?.toStreamItem(videoId)?.let {
PlayingQueue.insertPlaylist(playlistId!!, it)
}
} else if (PlayingQueue.isEmpty() && channelId != null) {
streams?.toStreamItem(videoId)?.let {
PlayingQueue.insertChannel(channelId!!, it)
}
} else {
streams?.toStreamItem(videoId)?.let {
PlayingQueue.updateCurrent(it)

View File

@ -5,6 +5,8 @@ import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.github.libretube.databinding.LegacySubscriptionChannelBinding
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.util.ImageHelper
import com.github.libretube.util.NavigationHelper
@ -36,6 +38,12 @@ class LegacySubscriptionAdapter(
subscription.url!!.toID()
)
}
root.setOnLongClickListener {
ChannelOptionsBottomSheet(subscription.url!!.toID(), subscription.name)
.show((root.context as BaseActivity).supportFragmentManager)
true
}
}
}

View File

@ -17,6 +17,7 @@ import com.github.libretube.ui.base.BaseActivity
import com.github.libretube.ui.extensions.setFormattedDuration
import com.github.libretube.ui.extensions.setWatchProgressLength
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.VideoOptionsBottomSheet
import com.github.libretube.ui.viewholders.SearchViewHolder
@ -127,6 +128,12 @@ class SearchAdapter(
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())
}
}

View File

@ -6,7 +6,9 @@ import androidx.recyclerview.widget.RecyclerView
import com.github.libretube.api.obj.Subscription
import com.github.libretube.databinding.ChannelSubscriptionRowBinding
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.sheets.ChannelOptionsBottomSheet
import com.github.libretube.ui.viewholders.SubscriptionChannelViewHolder
import com.github.libretube.util.ImageHelper
import com.github.libretube.util.NavigationHelper
@ -36,6 +38,12 @@ class SubscriptionChannelAdapter(
root.setOnClickListener {
NavigationHelper.navigateChannel(root.context, subscription.url)
}
root.setOnLongClickListener {
ChannelOptionsBottomSheet(subscription.url!!.toID(), subscription.name)
.show((root.context as BaseActivity).supportFragmentManager)
true
}
subscriptionSubscribe.setupSubscriptionButton(
subscription.url?.toID(),
subscription.name,

View File

@ -127,6 +127,7 @@ class PlayerFragment : BaseFragment(), OnlinePlayerOptions {
*/
private var videoId: String? = null
private var playlistId: String? = null
private var channelId: String? = null
private var isLive = false
private lateinit var streams: Streams
@ -172,6 +173,7 @@ class PlayerFragment : BaseFragment(), OnlinePlayerOptions {
arguments?.let {
videoId = it.getString(IntentData.videoId)!!.toID()
playlistId = it.getString(IntentData.playlistId)
channelId = it.getString(IntentData.channelId)
}
}
@ -399,7 +401,8 @@ class PlayerFragment : BaseFragment(), OnlinePlayerOptions {
requireContext(),
videoId!!,
exoPlayer.currentPosition,
playlistId
playlistId,
channelId
)
}
@ -593,6 +596,8 @@ class PlayerFragment : BaseFragment(), OnlinePlayerOptions {
CoroutineScope(Dispatchers.IO).launch {
if (playlistId != null) {
PlayingQueue.insertPlaylist(playlistId!!, streams.toStreamItem(videoId!!))
} else if (channelId != null) {
PlayingQueue.insertChannel(channelId!!, streams.toStreamItem(videoId!!))
} else {
PlayingQueue.updateCurrent(streams.toStreamItem(videoId!!))
if (PlayerHelper.autoInsertRelatedVideos) {

View File

@ -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())
}
}
}
}
}
}

View File

@ -20,13 +20,15 @@ object BackgroundHelper {
context: Context,
videoId: String,
position: Long? = null,
playlistId: String? = null
playlistId: String? = null,
channelId: String? = null
) {
// create an intent for the background mode service
val intent = Intent(context, BackgroundMode::class.java)
intent.putExtra(IntentData.videoId, videoId)
if (playlistId != null) intent.putExtra(IntentData.playlistId, playlistId)
if (position != null) intent.putExtra("position", position)
intent.putExtra(IntentData.playlistId, playlistId)
intent.putExtra(IntentData.channelId, channelId)
intent.putExtra("position", position)
// start the background mode as foreground service
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) {

View File

@ -48,13 +48,16 @@ object NavigationHelper {
fun navigateVideo(
context: Context,
videoId: String?,
playlistId: String? = null
playlistId: String? = null,
channelId: String? = null
) {
if (videoId == null) return
val bundle = Bundle()
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()
frag.arguments = bundle
val activity = context as AppCompatActivity

View File

@ -110,13 +110,8 @@ object PlayingQueue {
fun insertPlaylist(playlistId: String, newCurrentStream: StreamItem) {
CoroutineScope(Dispatchers.IO).launch {
try {
val playlistType = PlaylistsHelper.getPrivatePlaylistType(playlistId)
val playlist = PlaylistsHelper.getPlaylist(playlistId)
add(
*playlist.relatedStreams
.orEmpty()
.toTypedArray()
)
add(*playlist.relatedStreams.orEmpty().toTypedArray())
updateCurrent(newCurrentStream)
if (playlist.nextpage == null) return@launch
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) {
try {
val streamItem = queue[index]

View File

@ -414,6 +414,7 @@
<string name="privacy_alert">Privacy alert</string>
<string name="username_email">Proceed with an e-mail address that isn\'t recommended\?</string>
<string name="proceed">Proceed</string>
<string name="play_latest_videos">Play latest videos</string>
<!-- Notification channel strings -->
<string name="download_channel_name">Download Service</string>