UI for channel tabs

This commit is contained in:
Bnyro 2022-10-29 12:06:25 +02:00
parent 36e2da52fb
commit 18eebe663b
4 changed files with 130 additions and 10 deletions

View File

@ -6,11 +6,13 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.core.view.children
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import com.github.libretube.R
import com.github.libretube.api.RetrofitInstance
import com.github.libretube.api.SubscriptionHelper
import com.github.libretube.api.obj.ChannelTab
import com.github.libretube.constants.IntentData
import com.github.libretube.constants.ShareObjectType
import com.github.libretube.databinding.FragmentChannelBinding
@ -18,9 +20,14 @@ import com.github.libretube.extensions.TAG
import com.github.libretube.extensions.formatShort
import com.github.libretube.extensions.toID
import com.github.libretube.ui.adapters.ChannelAdapter
import com.github.libretube.ui.adapters.SearchAdapter
import com.github.libretube.ui.base.BaseFragment
import com.github.libretube.ui.dialogs.ShareDialog
import com.github.libretube.util.ImageHelper
import com.google.android.material.chip.Chip
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import retrofit2.HttpException
import java.io.IOException
@ -35,6 +42,10 @@ class ChannelFragment : BaseFragment() {
private var isLoading = true
private var isSubscribed: Boolean? = false
private var onScrollEnd: () -> Unit = {}
val scope = CoroutineScope(Dispatchers.IO)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
@ -73,11 +84,10 @@ class ChannelFragment : BaseFragment() {
if (binding.channelScrollView.getChildAt(0).bottom
== (binding.channelScrollView.height + binding.channelScrollView.scrollY)
) {
// scroll view is at bottom
if (nextPage != null && !isLoading) {
isLoading = true
binding.channelRefresh.isRefreshing = true
fetchChannelNextPage()
try {
onScrollEnd.invoke()
} catch (e: Exception) {
Log.e("tabs failed", e.toString())
}
}
}
@ -103,6 +113,14 @@ class ChannelFragment : BaseFragment() {
// needed if the channel gets loaded by the ID
channelId = response.id
onScrollEnd = {
if (nextPage != null && !isLoading) {
isLoading = true
binding.channelRefresh.isRefreshing = true
fetchChannelNextPage()
}
}
// fetch and update the subscription status
isSubscribed = SubscriptionHelper.isSubscribed(channelId!!)
if (isSubscribed == null) return@launchWhenCreated
@ -166,17 +184,68 @@ class ChannelFragment : BaseFragment() {
// recyclerview of the videos by the channel
channelAdapter = ChannelAdapter(
response.relatedStreams!!.toMutableList(),
response.relatedStreams.orEmpty().toMutableList(),
childFragmentManager
)
binding.channelRecView.adapter = channelAdapter
}
response.tabs?.forEach {
try {
RetrofitInstance.api.getChannelTab(it.data!!).toString()
binding.videos.setOnClickListener {
binding.channelRecView.adapter = channelAdapter
}
response.tabs?.firstOrNull { it.name == "Playlists" }?.let {
setupTab(binding.playlists, it)
}
response.tabs?.firstOrNull { it.name == "Channels" }?.let {
setupTab(binding.channels, it)
}
response.tabs?.firstOrNull { it.name == "Livestreams" }?.let {
setupTab(binding.livestreams, it)
}
response.tabs?.firstOrNull { it.name == "Shorts" }?.let {
setupTab(binding.shorts, it)
}
}
}
private fun setupTab(chip: Chip, tab: ChannelTab) {
chip.visibility = View.VISIBLE
chip.setOnClickListener {
binding.tabChips.children.forEach {
if (it != chip) it.isSelected = false
}
scope.launch {
val response = try {
RetrofitInstance.api.getChannelTab(tab.data!!)
} catch (e: Exception) {
Log.e("error", e.toString())
return@launch
}
val adapter = SearchAdapter(
response.content.toMutableList(),
childFragmentManager
)
runOnUiThread {
binding.channelRecView.adapter = adapter
}
onScrollEnd = {
if (response.nextpage != null) {
scope.launch {
val newContent = try {
RetrofitInstance.api.getChannelTab(tab.data, response.nextpage)
} catch (e: Exception) {
e.printStackTrace()
null
}
newContent?.content?.let { adapter.updateItems(it) }
}
}
}
}
}

View File

@ -115,6 +115,47 @@
android:maxLines="2"
android:padding="10dp" />
<HorizontalScrollView
android:id="@+id/tab_chips"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="10dp"
android:scrollbars="none">
<com.google.android.material.chip.ChipGroup
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<com.google.android.material.chip.Chip
android:id="@+id/videos"
style="@style/channelChip"
android:text="@string/videos"
android:visibility="visible" />
<com.google.android.material.chip.Chip
android:id="@+id/playlists"
style="@style/channelChip"
android:text="@string/playlists" />
<com.google.android.material.chip.Chip
android:id="@+id/shorts"
style="@style/channelChip"
android:text="@string/yt_shorts" />
<com.google.android.material.chip.Chip
android:id="@+id/channels"
style="@style/channelChip"
android:text="@string/channels" />
<com.google.android.material.chip.Chip
android:id="@+id/livestreams"
style="@style/channelChip"
android:text="@string/livestreams" />
</com.google.android.material.chip.ChipGroup>
</HorizontalScrollView>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"

View File

@ -352,6 +352,7 @@
<string name="queue">Queue</string>
<string name="sb_markers">Markers</string>
<string name="sb_markers_summary">Mark the segments on the time bar.</string>
<string name="livestreams">Livestreams</string>
<!-- Notification channel strings -->
<string name="download_channel_name">Download Service</string>

View File

@ -179,4 +179,13 @@
<item name="animationMode">slide</item>
</style>
<style name="channelChip" parent="@style/Widget.Material3.Chip.Filter.Elevated">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:padding">10dp</item>
<item name="android:visibility">gone</item>
</style>
</resources>