mirror of
https://gitlab.futo.org/videostreaming/grayjay.git
synced 2025-08-22 18:31:23 +00:00
Add functionality to open channel shorts in shorts fragment
Changelog: changed
This commit is contained in:
parent
1f5a069877
commit
cf96bd1ec0
6 changed files with 136 additions and 58 deletions
|
@ -25,6 +25,7 @@ import com.futo.platformplayer.api.media.structures.IReplacerPager
|
|||
import com.futo.platformplayer.api.media.structures.MultiPager
|
||||
import com.futo.platformplayer.constructs.Event1
|
||||
import com.futo.platformplayer.constructs.Event2
|
||||
import com.futo.platformplayer.constructs.Event3
|
||||
import com.futo.platformplayer.constructs.TaskHandler
|
||||
import com.futo.platformplayer.dp
|
||||
import com.futo.platformplayer.engine.exceptions.PluginException
|
||||
|
@ -61,7 +62,7 @@ class ChannelContentsFragment(private val subType: String? = null) : Fragment(),
|
|||
private var _query: String? = null
|
||||
private var _searchView: SearchView? = null
|
||||
|
||||
val onContentClicked = Event2<IPlatformContent, Long>();
|
||||
val onContentClicked = Event3<IPlatformContent, Long, Pair<IPager<IPlatformContent>, ArrayList<IPlatformContent>>?>();
|
||||
val onContentUrlClicked = Event2<String, ContentType>();
|
||||
val onUrlClicked = Event1<String>();
|
||||
val onChannelClicked = Event1<PlatformAuthorLink>();
|
||||
|
@ -211,7 +212,10 @@ class ChannelContentsFragment(private val subType: String? = null) : Fragment(),
|
|||
_adapterResults = PreviewContentListAdapter(view.context, FeedStyle.THUMBNAIL, _results, null, Settings.instance.channel.progressBar, viewsToPrepend = arrayListOf(searchView)).apply {
|
||||
this.onContentUrlClicked.subscribe(this@ChannelContentsFragment.onContentUrlClicked::emit);
|
||||
this.onUrlClicked.subscribe(this@ChannelContentsFragment.onUrlClicked::emit);
|
||||
this.onContentClicked.subscribe(this@ChannelContentsFragment.onContentClicked::emit);
|
||||
this.onContentClicked.subscribe { content, num ->
|
||||
val results = ArrayList(_results)
|
||||
this@ChannelContentsFragment.onContentClicked.emit(content, num, Pair(_pager!!, results))
|
||||
}
|
||||
this.onChannelClicked.subscribe(this@ChannelContentsFragment.onChannelClicked::emit);
|
||||
this.onAddToClicked.subscribe(this@ChannelContentsFragment.onAddToClicked::emit);
|
||||
this.onAddToQueueClicked.subscribe(this@ChannelContentsFragment.onAddToQueueClicked::emit);
|
||||
|
|
|
@ -392,7 +392,7 @@ class MenuBottomBarFragment : MainActivityFragment() {
|
|||
ButtonDefinition(2, R.drawable.ic_creators, R.drawable.ic_creators_filled, R.string.creators, canToggle = false, { it.currentMain is CreatorsFragment }, { it.navigate<CreatorsFragment>(withHistory = false) }),
|
||||
ButtonDefinition(3, R.drawable.ic_sources, R.drawable.ic_sources_filled, R.string.sources, canToggle = false, { it.currentMain is SourcesFragment }, { it.navigate<SourcesFragment>(withHistory = false) }),
|
||||
ButtonDefinition(4, R.drawable.ic_playlist, R.drawable.ic_playlist_filled, R.string.playlists, canToggle = false, { it.currentMain is PlaylistsFragment }, { it.navigate<PlaylistsFragment>(withHistory = false) }),
|
||||
ButtonDefinition(5, R.drawable.ic_smart_display, R.drawable.ic_smart_display_filled, R.string.shorts, canToggle = true, { it.currentMain is ShortsFragment }, { it.navigate<ShortsFragment>(withHistory = false) }),
|
||||
ButtonDefinition(5, R.drawable.ic_smart_display, R.drawable.ic_smart_display_filled, R.string.shorts, canToggle = true, { it.currentMain is ShortsFragment && !(it.currentMain as ShortsFragment).isChannelShortsMode }, { it.navigate<ShortsFragment>(withHistory = false) }),
|
||||
ButtonDefinition(6, R.drawable.ic_history, R.drawable.ic_history, R.string.history, canToggle = false, { it.currentMain is HistoryFragment }, { it.navigate<HistoryFragment>(withHistory = false) }),
|
||||
ButtonDefinition(7, R.drawable.ic_download, R.drawable.ic_download, R.string.downloads, canToggle = false, { it.currentMain is DownloadsFragment }, { it.navigate<DownloadsFragment>(withHistory = false) }),
|
||||
ButtonDefinition(8, R.drawable.ic_chat, R.drawable.ic_chat_filled, R.string.comments, canToggle = true, { it.currentMain is CommentsFragment }, { it.navigate<CommentsFragment>(withHistory = false) }),
|
||||
|
|
|
@ -211,6 +211,14 @@ class ChannelFragment : MainFragment() {
|
|||
}
|
||||
}
|
||||
}
|
||||
adapter.onShortClicked.subscribe { v, _, pagerPair ->
|
||||
when (v) {
|
||||
is IPlatformVideo -> {
|
||||
StatePlayer.instance.clearQueue()
|
||||
fragment.navigate<ShortsFragment>(Triple(v, pagerPair!!.first, pagerPair.second))
|
||||
}
|
||||
}
|
||||
}
|
||||
adapter.onAddToClicked.subscribe { content ->
|
||||
_overlayContainer.let {
|
||||
if (content is IPlatformVideo) _slideUpOverlay =
|
||||
|
|
|
@ -160,10 +160,10 @@ class ShortView : FrameLayout {
|
|||
null
|
||||
|
||||
val onResetTriggered = Event0()
|
||||
val onPlayingToggled = Event1<Boolean>()
|
||||
val onLikesLoaded = Event3<RatingLikeDislikes, Boolean, Boolean>()
|
||||
val onLikeDislikeUpdated = Event1<OnLikeDislikeUpdatedArgs>()
|
||||
val onVideoUpdated = Event1<IPlatformVideo?>()
|
||||
private val onPlayingToggled = Event1<Boolean>()
|
||||
private val onLikesLoaded = Event3<RatingLikeDislikes, Boolean, Boolean>()
|
||||
private val onLikeDislikeUpdated = Event1<OnLikeDislikeUpdatedArgs>()
|
||||
private val onVideoUpdated = Event1<IPlatformVideo?>()
|
||||
|
||||
private val bottomSheet: CommentsModalBottomSheet = CommentsModalBottomSheet()
|
||||
|
||||
|
@ -447,8 +447,7 @@ class ShortView : FrameLayout {
|
|||
overlay.visibility = VISIBLE
|
||||
|
||||
overlay.animate().alpha(1f).scaleX(1f).scaleY(1f).setDuration(400)
|
||||
.setInterpolator(OvershootInterpolator(1.2f))
|
||||
.start()
|
||||
.setInterpolator(OvershootInterpolator(1.2f)).start()
|
||||
|
||||
overlay.postDelayed({
|
||||
hidePlayPauseIcon()
|
||||
|
@ -783,11 +782,11 @@ class ShortView : FrameLayout {
|
|||
|
||||
mainFragment.lifecycleScope.launch(Dispatchers.IO) {
|
||||
try {
|
||||
Logger.i(CommentsModalBottomSheet.Companion.TAG, "Started backfill")
|
||||
Logger.i(CommentsModalBottomSheet.TAG, "Started backfill")
|
||||
args.processHandle.fullyBackfillServersAnnounceExceptions()
|
||||
Logger.i(CommentsModalBottomSheet.Companion.TAG, "Finished backfill")
|
||||
Logger.i(CommentsModalBottomSheet.TAG, "Finished backfill")
|
||||
} catch (e: Throwable) {
|
||||
Logger.e(CommentsModalBottomSheet.Companion.TAG, "Failed to backfill servers", e)
|
||||
Logger.e(CommentsModalBottomSheet.TAG, "Failed to backfill servers", e)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -924,7 +923,7 @@ class ShortView : FrameLayout {
|
|||
const val TAG = "VideoDetailView"
|
||||
}
|
||||
|
||||
class CommentsModalBottomSheet() : BottomSheetDialogFragment() {
|
||||
class CommentsModalBottomSheet : BottomSheetDialogFragment() {
|
||||
var mainFragment: MainFragment? = null
|
||||
|
||||
private lateinit var containerContent: FrameLayout
|
||||
|
@ -968,7 +967,7 @@ class ShortView : FrameLayout {
|
|||
private lateinit var behavior: BottomSheetBehavior<FrameLayout>
|
||||
|
||||
private val _taskLoadPolycentricProfile =
|
||||
TaskHandler<PlatformID, PolycentricProfile?>(StateApp.instance.scopeGetter, { ApiMethods.getPolycentricProfileByClaim(ApiMethods.SERVER, ApiMethods.FUTO_TRUST_ROOT, it.claimFieldType.toLong(), it.claimType.toLong(), it.value!!) }).success { it -> setPolycentricProfile(it, animate = true) }
|
||||
TaskHandler<PlatformID, PolycentricProfile?>(StateApp.instance.scopeGetter, { ApiMethods.getPolycentricProfileByClaim(ApiMethods.SERVER, ApiMethods.FUTO_TRUST_ROOT, it.claimFieldType.toLong(), it.claimType.toLong(), it.value!!) }).success { setPolycentricProfile(it, animate = true) }
|
||||
.exception<Throwable> {
|
||||
Logger.w(TAG, "Failed to load claims.", it)
|
||||
}
|
||||
|
@ -1024,7 +1023,7 @@ class ShortView : FrameLayout {
|
|||
val id = c.author.id.value
|
||||
|
||||
Logger.i(TAG, "onAuthorClick: $id")
|
||||
if (id != null && id.startsWith("polycentric://") == true) {
|
||||
if (id != null && id.startsWith("polycentric://")) {
|
||||
val navUrl = "https://harbor.social/" + id.substring("polycentric://".length)
|
||||
mainFragment!!.startActivity(Intent(Intent.ACTION_VIEW, navUrl.toUri()))
|
||||
}
|
||||
|
@ -1229,17 +1228,23 @@ class ShortView : FrameLayout {
|
|||
buttonPlatform.setTextColor(resources.getColor(if (index == 1) R.color.white else R.color.gray_ac, null))
|
||||
buttonPolycentric.setTextColor(resources.getColor(if (index == 0) R.color.white else R.color.gray_ac, null))
|
||||
|
||||
if (index == null) {
|
||||
when (index) {
|
||||
null -> {
|
||||
addCommentView.visibility = GONE
|
||||
commentsList.clear()
|
||||
} else if (index == 0) {
|
||||
}
|
||||
|
||||
0 -> {
|
||||
addCommentView.visibility = VISIBLE
|
||||
fetchPolycentricComments()
|
||||
} else if (index == 1) {
|
||||
}
|
||||
|
||||
1 -> {
|
||||
addCommentView.visibility = GONE
|
||||
fetchComments()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun fetchComments() {
|
||||
Logger.i(TAG, "fetchComments")
|
||||
|
@ -1252,7 +1257,7 @@ class ShortView : FrameLayout {
|
|||
Logger.i(TAG, "fetchPolycentricComments")
|
||||
val video = video
|
||||
val idValue = video.id.value
|
||||
if (video.url.isEmpty() != false) {
|
||||
if (video.url.isEmpty()) {
|
||||
Logger.w(TAG, "Failed to fetch polycentric comments because url was null")
|
||||
commentsList.clear()
|
||||
return
|
||||
|
|
|
@ -31,8 +31,19 @@ class ShortsFragment : MainFragment() {
|
|||
private var loadPagerTask: TaskHandler<ShortsFragment, IPager<IPlatformVideo>>? = null
|
||||
private var nextPageTask: TaskHandler<ShortsFragment, List<IPlatformVideo>>? = null
|
||||
|
||||
private var shortsPager: IPager<IPlatformVideo>? = null
|
||||
private val videos: MutableList<IPlatformVideo> = mutableListOf()
|
||||
private var mainShortsPager: IPager<IPlatformVideo>? = null
|
||||
private val mainShorts: MutableList<IPlatformVideo> = mutableListOf()
|
||||
|
||||
// the pager to call next on
|
||||
private var currentShortsPager: IPager<IPlatformVideo>? = null
|
||||
|
||||
// the shorts array bound to the ViewPager2 adapter
|
||||
private val currentShorts: MutableList<IPlatformVideo> = mutableListOf()
|
||||
|
||||
private var channelShortsPager: IPager<IPlatformVideo>? = null
|
||||
private val channelShorts: MutableList<IPlatformVideo> = mutableListOf()
|
||||
val isChannelShortsMode: Boolean
|
||||
get() = channelShortsPager != null
|
||||
|
||||
private var viewPager: ViewPager2? = null
|
||||
private lateinit var overlayLoading: FrameLayout
|
||||
|
@ -44,6 +55,47 @@ class ShortsFragment : MainFragment() {
|
|||
loadPager()
|
||||
}
|
||||
|
||||
// we just completely reset the data structure so we want to tell the adapter that
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
override fun onShown(parameter: Any?, isBack: Boolean) {
|
||||
super.onShown(parameter, isBack)
|
||||
|
||||
if (parameter is Triple<*, *, *>) {
|
||||
setLoading(false)
|
||||
channelShorts.clear()
|
||||
@Suppress("UNCHECKED_CAST") // TODO replace with a strongly typed parameter
|
||||
channelShorts.addAll(parameter.third as ArrayList<IPlatformVideo>)
|
||||
@Suppress("UNCHECKED_CAST") // TODO replace with a strongly typed parameter
|
||||
channelShortsPager = parameter.second as IPager<IPlatformVideo>
|
||||
|
||||
currentShorts.clear()
|
||||
currentShorts.addAll(channelShorts)
|
||||
currentShortsPager = channelShortsPager
|
||||
|
||||
viewPager?.adapter?.notifyDataSetChanged()
|
||||
|
||||
viewPager?.post {
|
||||
viewPager?.currentItem = channelShorts.indexOfFirst {
|
||||
return@indexOfFirst (parameter.first as IPlatformVideo).id == it.id
|
||||
}
|
||||
}
|
||||
} else if (isChannelShortsMode) {
|
||||
channelShortsPager = null
|
||||
channelShorts.clear()
|
||||
currentShorts.clear()
|
||||
|
||||
if (loadPagerTask == null) {
|
||||
currentShorts.addAll(mainShorts)
|
||||
currentShortsPager = mainShortsPager
|
||||
} else {
|
||||
setLoading(true)
|
||||
}
|
||||
|
||||
viewPager?.adapter?.notifyDataSetChanged()
|
||||
viewPager?.currentItem = 0
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateMainView(
|
||||
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
|
||||
): View {
|
||||
|
@ -62,8 +114,8 @@ class ShortsFragment : MainFragment() {
|
|||
|
||||
Logger.i(TAG, "Creating adapter")
|
||||
val customViewAdapter =
|
||||
CustomViewAdapter(videos, layoutInflater, this@ShortsFragment, overlayQualityContainer) {
|
||||
if (!shortsPager!!.hasMorePages()) {
|
||||
CustomViewAdapter(currentShorts, layoutInflater, this@ShortsFragment, overlayQualityContainer) {
|
||||
if (!currentShortsPager!!.hasMorePages()) {
|
||||
return@CustomViewAdapter
|
||||
}
|
||||
nextPage()
|
||||
|
@ -81,19 +133,16 @@ class ShortsFragment : MainFragment() {
|
|||
|
||||
this.customViewAdapter = customViewAdapter
|
||||
|
||||
if (loadPagerTask == null && videos.isEmpty()) {
|
||||
if (loadPagerTask == null && currentShorts.isEmpty()) {
|
||||
loadPager()
|
||||
|
||||
loadPagerTask!!.success {
|
||||
applyData()
|
||||
setLoading(false)
|
||||
}
|
||||
} else {
|
||||
applyData()
|
||||
}
|
||||
setLoading(false)
|
||||
}
|
||||
|
||||
private fun applyData() {
|
||||
val viewPager = viewPager!!
|
||||
viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
|
||||
fun play(adapter: CustomViewAdapter, position: Int) {
|
||||
val recycler = (viewPager.getChildAt(0) as RecyclerView)
|
||||
|
@ -126,17 +175,13 @@ class ShortsFragment : MainFragment() {
|
|||
super.onPageScrollStateChanged(state)
|
||||
if (state == ViewPager2.SCROLL_STATE_IDLE) {
|
||||
val adapter = (viewPager.adapter as CustomViewAdapter)
|
||||
val position = adapter.newPosition
|
||||
if (position == null) {
|
||||
return
|
||||
}
|
||||
val position = adapter.newPosition ?: return
|
||||
adapter.newPosition = null
|
||||
|
||||
play(adapter, position)
|
||||
}
|
||||
}
|
||||
})
|
||||
setLoading(false)
|
||||
}
|
||||
|
||||
private fun nextPage() {
|
||||
|
@ -144,12 +189,17 @@ class ShortsFragment : MainFragment() {
|
|||
|
||||
val nextPageTask =
|
||||
TaskHandler<ShortsFragment, List<IPlatformVideo>>(StateApp.instance.scopeGetter, {
|
||||
shortsPager!!.nextPage()
|
||||
currentShortsPager!!.nextPage()
|
||||
|
||||
return@TaskHandler shortsPager!!.getResults()
|
||||
return@TaskHandler currentShortsPager!!.getResults()
|
||||
}).success { newVideos ->
|
||||
val prevCount = customViewAdapter!!.itemCount
|
||||
videos.addAll(newVideos)
|
||||
currentShorts.addAll(newVideos)
|
||||
if (isChannelShortsMode) {
|
||||
channelShorts.addAll(newVideos)
|
||||
} else {
|
||||
mainShorts.addAll(newVideos)
|
||||
}
|
||||
customViewAdapter!!.notifyItemRangeInserted(prevCount, newVideos.size)
|
||||
nextPageTask = null
|
||||
}
|
||||
|
@ -170,13 +220,19 @@ class ShortsFragment : MainFragment() {
|
|||
|
||||
return@TaskHandler pager
|
||||
}).success { pager ->
|
||||
videos.clear()
|
||||
videos.addAll(pager.getResults())
|
||||
shortsPager = pager
|
||||
mainShorts.clear()
|
||||
mainShorts.addAll(pager.getResults())
|
||||
mainShortsPager = pager
|
||||
|
||||
if (!isChannelShortsMode) {
|
||||
currentShorts.clear()
|
||||
currentShorts.addAll(mainShorts)
|
||||
currentShortsPager = pager
|
||||
|
||||
// if the view pager exists go back to the beginning
|
||||
viewPager?.adapter?.notifyDataSetChanged()
|
||||
viewPager?.currentItem = 0
|
||||
}
|
||||
|
||||
loadPagerTask = null
|
||||
}.exception<Throwable> { err ->
|
||||
|
|
|
@ -9,8 +9,10 @@ import com.futo.platformplayer.api.media.models.ResultCapabilities
|
|||
import com.futo.platformplayer.api.media.models.channels.IPlatformChannel
|
||||
import com.futo.platformplayer.api.media.models.contents.ContentType
|
||||
import com.futo.platformplayer.api.media.models.contents.IPlatformContent
|
||||
import com.futo.platformplayer.api.media.structures.IPager
|
||||
import com.futo.platformplayer.constructs.Event1
|
||||
import com.futo.platformplayer.constructs.Event2
|
||||
import com.futo.platformplayer.constructs.Event3
|
||||
import com.futo.platformplayer.fragment.channel.tab.ChannelAboutFragment
|
||||
import com.futo.platformplayer.fragment.channel.tab.ChannelContentsFragment
|
||||
import com.futo.platformplayer.fragment.channel.tab.ChannelListFragment
|
||||
|
@ -38,6 +40,7 @@ class ChannelViewPagerAdapter(fragmentManager: FragmentManager, lifecycle: Lifec
|
|||
val onContentUrlClicked = Event2<String, ContentType>()
|
||||
val onUrlClicked = Event1<String>()
|
||||
val onContentClicked = Event2<IPlatformContent, Long>()
|
||||
val onShortClicked = Event3<IPlatformContent, Long, Pair<IPager<IPlatformContent>, ArrayList<IPlatformContent>>?>()
|
||||
val onChannelClicked = Event1<PlatformAuthorLink>()
|
||||
val onAddToClicked = Event1<IPlatformContent>()
|
||||
val onAddToQueueClicked = Event1<IPlatformContent>()
|
||||
|
@ -81,7 +84,9 @@ class ChannelViewPagerAdapter(fragmentManager: FragmentManager, lifecycle: Lifec
|
|||
when (_tabs[position]) {
|
||||
ChannelTab.VIDEOS -> {
|
||||
fragment = ChannelContentsFragment.newInstance().apply {
|
||||
onContentClicked.subscribe(this@ChannelViewPagerAdapter.onContentClicked::emit)
|
||||
onContentClicked.subscribe { video, num, _ ->
|
||||
this@ChannelViewPagerAdapter.onContentClicked.emit(video, num)
|
||||
}
|
||||
onContentUrlClicked.subscribe(this@ChannelViewPagerAdapter.onContentUrlClicked::emit)
|
||||
onUrlClicked.subscribe(this@ChannelViewPagerAdapter.onUrlClicked::emit)
|
||||
onChannelClicked.subscribe(this@ChannelViewPagerAdapter.onChannelClicked::emit)
|
||||
|
@ -94,7 +99,7 @@ class ChannelViewPagerAdapter(fragmentManager: FragmentManager, lifecycle: Lifec
|
|||
|
||||
ChannelTab.SHORTS -> {
|
||||
fragment = ChannelContentsFragment.newInstance(ResultCapabilities.TYPE_SHORTS).apply {
|
||||
onContentClicked.subscribe(this@ChannelViewPagerAdapter.onContentClicked::emit)
|
||||
onContentClicked.subscribe(this@ChannelViewPagerAdapter.onShortClicked::emit)
|
||||
onContentUrlClicked.subscribe(this@ChannelViewPagerAdapter.onContentUrlClicked::emit)
|
||||
onUrlClicked.subscribe(this@ChannelViewPagerAdapter.onUrlClicked::emit)
|
||||
onChannelClicked.subscribe(this@ChannelViewPagerAdapter.onChannelClicked::emit)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue