Merge pull request #3733 from Bnyro/master

Various subscription group improvements
This commit is contained in:
Bnyro 2023-05-08 18:06:25 +02:00 committed by GitHub
commit 33ccb1aa0a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 152 additions and 83 deletions

View File

@ -8,6 +8,7 @@ import com.github.libretube.databinding.SubscriptionGroupChannelRowBinding
import com.github.libretube.db.obj.SubscriptionGroup import com.github.libretube.db.obj.SubscriptionGroup
import com.github.libretube.extensions.toID import com.github.libretube.extensions.toID
import com.github.libretube.helpers.ImageHelper import com.github.libretube.helpers.ImageHelper
import com.github.libretube.helpers.NavigationHelper
import com.github.libretube.ui.viewholders.SubscriptionGroupChannelRowViewHolder import com.github.libretube.ui.viewholders.SubscriptionGroupChannelRowViewHolder
class SubscriptionGroupChannelsAdapter( class SubscriptionGroupChannelsAdapter(
@ -30,6 +31,9 @@ class SubscriptionGroupChannelsAdapter(
val channel = channels[position] val channel = channels[position]
val channelId = channel.url.toID() val channelId = channel.url.toID()
holder.binding.apply { holder.binding.apply {
root.setOnClickListener {
NavigationHelper.navigateChannel(root.context, channelId)
}
subscriptionChannelName.text = channel.name subscriptionChannelName.text = channel.name
ImageHelper.loadImage(channel.avatar, subscriptionChannelImage) ImageHelper.loadImage(channel.avatar, subscriptionChannelImage)
channelIncluded.setOnCheckedChangeListener(null) channelIncluded.setOnCheckedChangeListener(null)

View File

@ -7,7 +7,7 @@ import androidx.recyclerview.widget.RecyclerView
import com.github.libretube.databinding.SubscriptionGroupRowBinding import com.github.libretube.databinding.SubscriptionGroupRowBinding
import com.github.libretube.db.DatabaseHolder import com.github.libretube.db.DatabaseHolder
import com.github.libretube.db.obj.SubscriptionGroup import com.github.libretube.db.obj.SubscriptionGroup
import com.github.libretube.ui.dialogs.EditChannelGroupDialog import com.github.libretube.ui.sheets.EditChannelGroupSheet
import com.github.libretube.ui.viewholders.SubscriptionGroupsViewHolder import com.github.libretube.ui.viewholders.SubscriptionGroupsViewHolder
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
@ -44,7 +44,7 @@ class SubscriptionGroupsAdapter(
notifyItemRangeChanged(position, itemCount) notifyItemRangeChanged(position, itemCount)
} }
editGroup.setOnClickListener { editGroup.setOnClickListener {
EditChannelGroupDialog(subscriptionGroup) { EditChannelGroupSheet(subscriptionGroup) {
groups[position] = it groups[position] = it
runBlocking(Dispatchers.IO) { runBlocking(Dispatchers.IO) {
// delete the old one as it might have a different name // delete the old one as it might have a different name

View File

@ -1,47 +0,0 @@
package com.github.libretube.ui.dialogs
import android.app.Dialog
import android.os.Bundle
import androidx.fragment.app.DialogFragment
import androidx.recyclerview.widget.LinearLayoutManager
import com.github.libretube.R
import com.github.libretube.databinding.DialogSubscriptionGroupsBinding
import com.github.libretube.db.DatabaseHolder
import com.github.libretube.db.obj.SubscriptionGroup
import com.github.libretube.ui.adapters.SubscriptionGroupsAdapter
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
class ChannelGroupsDialog(
private val groups: MutableList<SubscriptionGroup>,
private val onGroupsChanged: (List<SubscriptionGroup>) -> Unit
) : DialogFragment() {
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val binding = DialogSubscriptionGroupsBinding.inflate(layoutInflater)
binding.groupsRV.layoutManager = LinearLayoutManager(context)
val adapter = SubscriptionGroupsAdapter(
groups.toMutableList(),
parentFragmentManager,
onGroupsChanged
)
binding.groupsRV.adapter = adapter
return MaterialAlertDialogBuilder(requireContext())
.setTitle(R.string.channel_groups)
.setView(binding.root)
.setPositiveButton(R.string.okay, null)
.setNeutralButton(R.string.new_group) { _, _ ->
EditChannelGroupDialog(SubscriptionGroup("", mutableListOf())) {
runBlocking(Dispatchers.IO) {
DatabaseHolder.Database.subscriptionGroupsDao().createGroup(it)
}
groups.add(it)
adapter.insertItem(it)
onGroupsChanged(groups)
}.show(parentFragmentManager, null)
}
.create()
}
}

View File

@ -25,9 +25,9 @@ import com.github.libretube.helpers.PreferenceHelper
import com.github.libretube.ui.adapters.LegacySubscriptionAdapter import com.github.libretube.ui.adapters.LegacySubscriptionAdapter
import com.github.libretube.ui.adapters.SubscriptionChannelAdapter import com.github.libretube.ui.adapters.SubscriptionChannelAdapter
import com.github.libretube.ui.adapters.VideosAdapter import com.github.libretube.ui.adapters.VideosAdapter
import com.github.libretube.ui.dialogs.ChannelGroupsDialog
import com.github.libretube.ui.models.SubscriptionsViewModel import com.github.libretube.ui.models.SubscriptionsViewModel
import com.github.libretube.ui.sheets.BaseBottomSheet import com.github.libretube.ui.sheets.BaseBottomSheet
import com.github.libretube.ui.sheets.ChannelGroupsSheet
import com.google.android.material.chip.Chip import com.google.android.material.chip.Chip
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -197,7 +197,7 @@ class SubscriptionsFragment : Fragment() {
} }
binding.editGroups.setOnClickListener { binding.editGroups.setOnClickListener {
ChannelGroupsDialog(channelGroups.toMutableList()) { ChannelGroupsSheet(channelGroups.toMutableList()) {
lifecycleScope.launch { initChannelGroups() } lifecycleScope.launch { initChannelGroups() }
}.show(childFragmentManager, null) }.show(childFragmentManager, null)
} }

View File

@ -0,0 +1,51 @@
package com.github.libretube.ui.sheets
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.LinearLayoutManager
import com.github.libretube.databinding.DialogSubscriptionGroupsBinding
import com.github.libretube.db.DatabaseHolder
import com.github.libretube.db.obj.SubscriptionGroup
import com.github.libretube.ui.adapters.SubscriptionGroupsAdapter
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
class ChannelGroupsSheet(
private val groups: MutableList<SubscriptionGroup>,
private val onGroupsChanged: (List<SubscriptionGroup>) -> Unit
) : ExpandedBottomSheet() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
val binding = DialogSubscriptionGroupsBinding.inflate(layoutInflater)
binding.groupsRV.layoutManager = LinearLayoutManager(context)
val adapter = SubscriptionGroupsAdapter(
groups.toMutableList(),
parentFragmentManager,
onGroupsChanged
)
binding.groupsRV.adapter = adapter
binding.newGroup.setOnClickListener {
EditChannelGroupSheet(SubscriptionGroup("", mutableListOf())) {
runBlocking(Dispatchers.IO) {
DatabaseHolder.Database.subscriptionGroupsDao().createGroup(it)
}
groups.add(it)
adapter.insertItem(it)
onGroupsChanged(groups)
}.show(parentFragmentManager, null)
}
binding.confirm.setOnClickListener {
dismiss()
}
return binding.root
}
}

View File

@ -1,34 +1,37 @@
package com.github.libretube.ui.dialogs package com.github.libretube.ui.sheets
import android.app.Dialog
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.core.widget.addTextChangedListener import androidx.core.widget.addTextChangedListener
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.github.libretube.R
import com.github.libretube.api.SubscriptionHelper import com.github.libretube.api.SubscriptionHelper
import com.github.libretube.api.obj.Subscription import com.github.libretube.api.obj.Subscription
import com.github.libretube.databinding.DialogEditChannelGroupBinding import com.github.libretube.databinding.DialogEditChannelGroupBinding
import com.github.libretube.db.obj.SubscriptionGroup import com.github.libretube.db.obj.SubscriptionGroup
import com.github.libretube.ui.adapters.SubscriptionGroupChannelsAdapter import com.github.libretube.ui.adapters.SubscriptionGroupChannelsAdapter
import com.github.libretube.ui.models.SubscriptionsViewModel import com.github.libretube.ui.models.SubscriptionsViewModel
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
class EditChannelGroupDialog( class EditChannelGroupSheet(
private var group: SubscriptionGroup, private var group: SubscriptionGroup,
private val onGroupChanged: (SubscriptionGroup) -> Unit private val onGroupChanged: (SubscriptionGroup) -> Unit
) : DialogFragment() { ) : ExpandedBottomSheet() {
private val subscriptionsModel: SubscriptionsViewModel by activityViewModels() private val subscriptionsModel: SubscriptionsViewModel by activityViewModels()
private lateinit var binding: DialogEditChannelGroupBinding private lateinit var binding: DialogEditChannelGroupBinding
private var channels: List<Subscription> = listOf() private var channels: List<Subscription> = listOf()
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = DialogEditChannelGroupBinding.inflate(layoutInflater) binding = DialogEditChannelGroupBinding.inflate(layoutInflater)
binding.groupName.setText(group.name) binding.groupName.setText(group.name)
@ -39,16 +42,18 @@ class EditChannelGroupDialog(
showChannels(channels, it?.toString()) showChannels(channels, it?.toString())
} }
return MaterialAlertDialogBuilder(requireContext()) binding.cancel.setOnClickListener {
.setTitle(R.string.edit_group) dismiss()
.setNegativeButton(R.string.cancel, null) }
.setPositiveButton(R.string.okay) { _, _ ->
group.name = binding.groupName.text.toString() binding.confirm.setOnClickListener {
if (group.name.isBlank()) return@setPositiveButton group.name = binding.groupName.text.toString()
onGroupChanged(group) if (group.name.isBlank()) return@setOnClickListener
} onGroupChanged(group)
.setView(binding.root) dismiss()
.create() }
return binding.root
} }
private fun fetchSubscriptions() { private fun fetchSubscriptions() {

View File

@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"> android:orientation="vertical">
<com.google.android.material.textfield.TextInputLayout <com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent" android:layout_width="match_parent"
@ -16,7 +16,7 @@
<com.google.android.material.textfield.TextInputEditText <com.google.android.material.textfield.TextInputEditText
android:id="@+id/group_name" android:id="@+id/group_name"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" /> android:layout_height="wrap_content"/>
</com.google.android.material.textfield.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
@ -37,7 +37,7 @@
<com.google.android.material.textfield.TextInputEditText <com.google.android.material.textfield.TextInputEditText
android:id="@+id/search_input" android:id="@+id/search_input"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" /> android:layout_height="wrap_content"/>
</com.google.android.material.textfield.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
@ -45,7 +45,30 @@
android:id="@+id/channelsRV" android:id="@+id/channelsRV"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="10dp" /> android:layout_marginTop="10dp"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_gravity="end"
android:paddingVertical="10dp"
android:layout_height="wrap_content">
<com.google.android.material.button.MaterialButton
android:id="@+id/cancel"
style="@style/Widget.Material3.Button.OutlinedButton"
android:layout_width="wrap_content"
android:text="@string/cancel"
android:layout_height="wrap_content"/>
<com.google.android.material.button.MaterialButton
android:id="@+id/confirm"
style="@style/Widget.Material3.Button.ElevatedButton"
android:layout_width="wrap_content"
android:text="@string/okay"
android:layout_marginHorizontal="16dp"
android:layout_height="wrap_content"/>
</LinearLayout>
</LinearLayout> </LinearLayout>
@ -54,6 +77,6 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
android:layout_marginVertical="200dp" /> android:layout_marginVertical="20dp"/>
</LinearLayout> </LinearLayout>

View File

@ -1,12 +1,45 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:text="@string/channel_groups"
android:textStyle="bold"
android:textSize="24sp"
android:layout_marginTop="18dp"
android:layout_marginStart="18dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/groupsRV" android:id="@+id/groupsRV"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="20dp" /> android:layout_marginTop="20dp"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_gravity="end"
android:paddingVertical="10dp"
android:layout_height="wrap_content">
<com.google.android.material.button.MaterialButton
android:id="@+id/new_group"
android:layout_width="wrap_content"
android:text="@string/new_group"
style="@style/Widget.Material3.Button.OutlinedButton"
android:layout_height="wrap_content"/>
<com.google.android.material.button.MaterialButton
android:id="@+id/confirm"
style="@style/Widget.Material3.Button.ElevatedButton"
android:layout_width="wrap_content"
android:text="@string/okay"
android:layout_marginHorizontal="16dp"
android:layout_height="wrap_content"/>
</LinearLayout>
</LinearLayout> </LinearLayout>

View File

@ -4,8 +4,8 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground" android:background="@drawable/rounded_ripple"
android:paddingHorizontal="20dp" > android:paddingHorizontal="10dp" >
<com.google.android.material.imageview.ShapeableImageView <com.google.android.material.imageview.ShapeableImageView
android:id="@+id/subscription_channel_image" android:id="@+id/subscription_channel_image"

View File

@ -3,7 +3,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal" android:orientation="horizontal"
android:paddingHorizontal="25dp" android:paddingHorizontal="5dp"
android:paddingVertical="10dp"> android:paddingVertical="10dp">
<TextView <TextView