From 8482bf9fedf930dafceaaac54adb235817d27109 Mon Sep 17 00:00:00 2001 From: Samuel Wu Date: Sun, 23 Oct 2022 23:43:52 +1100 Subject: [PATCH 01/22] Created a non-functional button in HeaderWithMenuItem.kt --- .../newpipe/local/subscription/SubscriptionFragment.kt | 1 + .../newpipe/local/subscription/item/HeaderWithMenuItem.kt | 8 +++++++- app/src/main/res/layout/header_with_menu_item.xml | 8 ++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt index 20f8a01c1..a804b0ff3 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt @@ -269,6 +269,7 @@ class SubscriptionFragment : BaseStateFragment() { feedGroupsCarousel = FeedGroupCarouselItem(requireContext(), carouselAdapter) feedGroupsSortMenuItem = HeaderWithMenuItem( getString(R.string.feed_groups_header_title), + R.drawable.ic_list, R.drawable.ic_sort, menuItemOnClickListener = ::openReorderDialog ) diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/item/HeaderWithMenuItem.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/item/HeaderWithMenuItem.kt index 79a272178..cb312b023 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/item/HeaderWithMenuItem.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/item/HeaderWithMenuItem.kt @@ -11,8 +11,10 @@ import org.schabi.newpipe.databinding.HeaderWithMenuItemBinding class HeaderWithMenuItem( val title: String, @DrawableRes val itemIcon: Int = 0, + @DrawableRes val itemIconListView: Int = 0, var showMenuItem: Boolean = true, private val onClickListener: (() -> Unit)? = null, + private val onClickListenerListView: (() -> Unit)? = null, private val menuItemOnClickListener: (() -> Unit)? = null ) : BindableItem() { companion object { @@ -32,11 +34,15 @@ class HeaderWithMenuItem( override fun bind(viewBinding: HeaderWithMenuItemBinding, position: Int) { viewBinding.headerTitle.text = title - viewBinding.headerMenuItem.setImageResource(itemIcon) + viewBinding.headerMenuItem2.setImageResource(itemIcon) + viewBinding.headerMenuItem.setImageResource(itemIconListView) val listener = onClickListener?.let { OnClickListener { onClickListener.invoke() } } viewBinding.root.setOnClickListener(listener) + val listenerListView = onClickListenerListView?.let { OnClickListener { onClickListenerListView.invoke() } } + viewBinding.root.setOnClickListener(listenerListView) + val menuItemListener = menuItemOnClickListener?.let { OnClickListener { menuItemOnClickListener.invoke() } } viewBinding.headerMenuItem.setOnClickListener(menuItemListener) updateMenuItemVisibility(viewBinding) diff --git a/app/src/main/res/layout/header_with_menu_item.xml b/app/src/main/res/layout/header_with_menu_item.xml index fcf888ed5..170c40098 100644 --- a/app/src/main/res/layout/header_with_menu_item.xml +++ b/app/src/main/res/layout/header_with_menu_item.xml @@ -22,6 +22,14 @@ android:textStyle="bold" tools:text="Header" /> + + Date: Mon, 24 Oct 2022 16:55:12 +1100 Subject: [PATCH 02/22] Created a button in SubscriptionFragment.kt that reads whether button is clicked --- .../newpipe/local/subscription/SubscriptionFragment.kt | 5 +++++ .../newpipe/local/subscription/item/HeaderWithMenuItem.kt | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt index a804b0ff3..bf4941e8e 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt @@ -221,6 +221,10 @@ class SubscriptionFragment : BaseStateFragment() { FeedGroupReorderDialog().show(parentFragmentManager, null) } + private fun temp() { + println("This button is clicked") + } + private fun requestExportResult(result: ActivityResult) { if (result.data != null && result.resultCode == Activity.RESULT_OK) { activity.startService( @@ -271,6 +275,7 @@ class SubscriptionFragment : BaseStateFragment() { getString(R.string.feed_groups_header_title), R.drawable.ic_list, R.drawable.ic_sort, + listViewOnClickListener = ::temp, menuItemOnClickListener = ::openReorderDialog ) add(Section(feedGroupsSortMenuItem, listOf(feedGroupsCarousel))) diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/item/HeaderWithMenuItem.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/item/HeaderWithMenuItem.kt index cb312b023..338083c87 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/item/HeaderWithMenuItem.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/item/HeaderWithMenuItem.kt @@ -14,7 +14,7 @@ class HeaderWithMenuItem( @DrawableRes val itemIconListView: Int = 0, var showMenuItem: Boolean = true, private val onClickListener: (() -> Unit)? = null, - private val onClickListenerListView: (() -> Unit)? = null, + private val listViewOnClickListener: (() -> Unit)? = null, private val menuItemOnClickListener: (() -> Unit)? = null ) : BindableItem() { companion object { @@ -40,8 +40,8 @@ class HeaderWithMenuItem( val listener = onClickListener?.let { OnClickListener { onClickListener.invoke() } } viewBinding.root.setOnClickListener(listener) - val listenerListView = onClickListenerListView?.let { OnClickListener { onClickListenerListView.invoke() } } - viewBinding.root.setOnClickListener(listenerListView) + val listViewListener = listViewOnClickListener?.let { OnClickListener { listViewOnClickListener.invoke() } } + viewBinding.headerMenuItem2.setOnClickListener(listViewListener) val menuItemListener = menuItemOnClickListener?.let { OnClickListener { menuItemOnClickListener.invoke() } } viewBinding.headerMenuItem.setOnClickListener(menuItemListener) From 78547b4fa464cac863e63e07f30529528703dad7 Mon Sep 17 00:00:00 2001 From: Samuel Wu Date: Mon, 24 Oct 2022 18:55:08 +1100 Subject: [PATCH 03/22] Created a list view for channel group. --- .../decoration/FeedGroupCarouselDecoration.kt | 2 +- .../subscription/item/FeedGroupCardItem.kt | 2 +- .../item/FeedGroupCarouselItem.kt | 2 +- .../main/res/layout/feed_group_list_item.xml | 43 +++++++++++++++++++ 4 files changed, 46 insertions(+), 3 deletions(-) create mode 100644 app/src/main/res/layout/feed_group_list_item.xml diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/decoration/FeedGroupCarouselDecoration.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/decoration/FeedGroupCarouselDecoration.kt index 7b7490eaa..a113a8b41 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/decoration/FeedGroupCarouselDecoration.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/decoration/FeedGroupCarouselDecoration.kt @@ -26,7 +26,7 @@ class FeedGroupCarouselDecoration(context: Context) : RecyclerView.ItemDecoratio outRect.set(marginBetweenItems, marginTopBottom, 0, marginTopBottom) - if (childAdapterPosition == 0) { + if (childAdapterPosition >= 0) { outRect.left = marginStartEnd } else if (childAdapterPosition == childAdapterCount - 1) { outRect.right = marginStartEnd diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupCardItem.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupCardItem.kt index 7b78b3d95..fd8a75da1 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupCardItem.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupCardItem.kt @@ -21,7 +21,7 @@ data class FeedGroupCardItem( } } - override fun getLayout(): Int = R.layout.feed_group_card_item + override fun getLayout(): Int = R.layout.feed_group_list_item override fun bind(viewBinding: FeedGroupCardItemBinding, position: Int) { viewBinding.title.text = name diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupCarouselItem.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupCarouselItem.kt index 44af16280..031eb9b18 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupCarouselItem.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupCarouselItem.kt @@ -36,7 +36,7 @@ class FeedGroupCarouselItem( override fun initializeViewBinding(view: View): FeedItemCarouselBinding { val viewHolder = FeedItemCarouselBinding.bind(view) - linearLayoutManager = LinearLayoutManager(view.context, RecyclerView.HORIZONTAL, false) + linearLayoutManager = LinearLayoutManager(view.context, RecyclerView.VERTICAL, false) viewHolder.recyclerView.apply { layoutManager = linearLayoutManager diff --git a/app/src/main/res/layout/feed_group_list_item.xml b/app/src/main/res/layout/feed_group_list_item.xml new file mode 100644 index 000000000..c49da1eab --- /dev/null +++ b/app/src/main/res/layout/feed_group_list_item.xml @@ -0,0 +1,43 @@ + + + + + + + + + + From f37d869ea2c2474985a1386af9fbed67abf092ef Mon Sep 17 00:00:00 2001 From: Samuel Wu Date: Mon, 24 Oct 2022 23:01:02 +1100 Subject: [PATCH 04/22] Button can be toggled but not all strings have been fed --- .../5.json | 26 +++-- .../database/feed/model/FeedGroupEntity.kt | 2 +- .../subscription/SubscriptionFragment.kt | 101 ++++++++++++++++-- .../subscription/item/FeedGroupCardItem.kt | 4 +- .../item/FeedGroupCardVerticalItem.kt | 32 ++++++ .../item/FeedGroupCarouselItem.kt | 6 +- ....xml => feed_group_card_vertical_item.xml} | 7 +- 7 files changed, 155 insertions(+), 23 deletions(-) create mode 100644 app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupCardVerticalItem.kt rename app/src/main/res/layout/{feed_group_list_item.xml => feed_group_card_vertical_item.xml} (92%) diff --git a/app/schemas/org.schabi.newpipe.database.AppDatabase/5.json b/app/schemas/org.schabi.newpipe.database.AppDatabase/5.json index 9a1c62995..eeebdeb49 100644 --- a/app/schemas/org.schabi.newpipe.database.AppDatabase/5.json +++ b/app/schemas/org.schabi.newpipe.database.AppDatabase/5.json @@ -71,6 +71,7 @@ "service_id", "url" ], + "orders": [], "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_subscriptions_service_id_url` ON `${TABLE_NAME}` (`service_id`, `url`)" } ], @@ -78,14 +79,8 @@ }, { "tableName": "search_history", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `creation_date` INTEGER, `service_id` INTEGER NOT NULL, `search` TEXT)", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`creation_date` INTEGER, `service_id` INTEGER NOT NULL, `search` TEXT, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", "fields": [ - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true - }, { "fieldPath": "creationDate", "columnName": "creation_date", @@ -103,6 +98,12 @@ "columnName": "search", "affinity": "TEXT", "notNull": false + }, + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true } ], "primaryKey": { @@ -118,6 +119,7 @@ "columnNames": [ "search" ], + "orders": [], "createSql": "CREATE INDEX IF NOT EXISTS `index_search_history_search` ON `${TABLE_NAME}` (`search`)" } ], @@ -220,6 +222,7 @@ "service_id", "url" ], + "orders": [], "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_streams_service_id_url` ON `${TABLE_NAME}` (`service_id`, `url`)" } ], @@ -262,6 +265,7 @@ "columnNames": [ "stream_id" ], + "orders": [], "createSql": "CREATE INDEX IF NOT EXISTS `index_stream_history_stream_id` ON `${TABLE_NAME}` (`stream_id`)" } ], @@ -353,6 +357,7 @@ "columnNames": [ "name" ], + "orders": [], "createSql": "CREATE INDEX IF NOT EXISTS `index_playlists_name` ON `${TABLE_NAME}` (`name`)" } ], @@ -396,6 +401,7 @@ "playlist_id", "join_index" ], + "orders": [], "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_playlist_stream_join_playlist_id_join_index` ON `${TABLE_NAME}` (`playlist_id`, `join_index`)" }, { @@ -404,6 +410,7 @@ "columnNames": [ "stream_id" ], + "orders": [], "createSql": "CREATE INDEX IF NOT EXISTS `index_playlist_stream_join_stream_id` ON `${TABLE_NAME}` (`stream_id`)" } ], @@ -492,6 +499,7 @@ "columnNames": [ "name" ], + "orders": [], "createSql": "CREATE INDEX IF NOT EXISTS `index_remote_playlists_name` ON `${TABLE_NAME}` (`name`)" }, { @@ -501,6 +509,7 @@ "service_id", "url" ], + "orders": [], "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_remote_playlists_service_id_url` ON `${TABLE_NAME}` (`service_id`, `url`)" } ], @@ -537,6 +546,7 @@ "columnNames": [ "subscription_id" ], + "orders": [], "createSql": "CREATE INDEX IF NOT EXISTS `index_feed_subscription_id` ON `${TABLE_NAME}` (`subscription_id`)" } ], @@ -607,6 +617,7 @@ "columnNames": [ "sort_order" ], + "orders": [], "createSql": "CREATE INDEX IF NOT EXISTS `index_feed_group_sort_order` ON `${TABLE_NAME}` (`sort_order`)" } ], @@ -643,6 +654,7 @@ "columnNames": [ "subscription_id" ], + "orders": [], "createSql": "CREATE INDEX IF NOT EXISTS `index_feed_group_subscription_join_subscription_id` ON `${TABLE_NAME}` (`subscription_id`)" } ], diff --git a/app/src/main/java/org/schabi/newpipe/database/feed/model/FeedGroupEntity.kt b/app/src/main/java/org/schabi/newpipe/database/feed/model/FeedGroupEntity.kt index 1dd26946a..c7415ace0 100644 --- a/app/src/main/java/org/schabi/newpipe/database/feed/model/FeedGroupEntity.kt +++ b/app/src/main/java/org/schabi/newpipe/database/feed/model/FeedGroupEntity.kt @@ -24,7 +24,7 @@ data class FeedGroupEntity( var icon: FeedGroupIcon, @ColumnInfo(name = SORT_ORDER) - var sortOrder: Long = -1 + var sortOrder: Long = -1, ) { companion object { const val FEED_GROUP_TABLE = "feed_group" diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt index bf4941e8e..659187ffa 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt @@ -20,6 +20,7 @@ import androidx.annotation.StringRes import androidx.appcompat.app.AlertDialog import androidx.lifecycle.ViewModelProvider import androidx.recyclerview.widget.GridLayoutManager +import androidx.recyclerview.widget.RecyclerView import com.xwray.groupie.Group import com.xwray.groupie.GroupAdapter import com.xwray.groupie.Item @@ -45,6 +46,7 @@ import org.schabi.newpipe.local.subscription.item.ChannelItem import org.schabi.newpipe.local.subscription.item.EmptyPlaceholderItem import org.schabi.newpipe.local.subscription.item.FeedGroupAddItem import org.schabi.newpipe.local.subscription.item.FeedGroupCardItem +import org.schabi.newpipe.local.subscription.item.FeedGroupCardVerticalItem import org.schabi.newpipe.local.subscription.item.FeedGroupCarouselItem import org.schabi.newpipe.local.subscription.item.HeaderWithMenuItem import org.schabi.newpipe.local.subscription.item.HeaderWithMenuItem.Companion.PAYLOAD_UPDATE_VISIBILITY_MENU_ITEM @@ -76,6 +78,7 @@ class SubscriptionFragment : BaseStateFragment() { private val groupAdapter = GroupAdapter>() private val feedGroupsSection = Section() private var feedGroupsCarousel: FeedGroupCarouselItem? = null + private var feedGroupsCarouselVertical: FeedGroupCarouselItem? = feedGroupsCarousel private lateinit var feedGroupsSortMenuItem: HeaderWithMenuItem private val subscriptionsSection = Section() @@ -92,6 +95,10 @@ class SubscriptionFragment : BaseStateFragment() { @JvmField var feedGroupsListState: Parcelable? = null + @State + @JvmField + var feedGroupsListVerticalState: Parcelable? = null + init { setHasOptionsMenu(true) } @@ -118,6 +125,7 @@ class SubscriptionFragment : BaseStateFragment() { super.onPause() itemsListState = binding.itemsList.layoutManager?.onSaveInstanceState() feedGroupsListState = feedGroupsCarousel?.onSaveInstanceState() + feedGroupsListVerticalState = feedGroupsCarouselVertical?.onSaveInstanceState() } override fun onDestroy() { @@ -221,10 +229,6 @@ class SubscriptionFragment : BaseStateFragment() { FeedGroupReorderDialog().show(parentFragmentManager, null) } - private fun temp() { - println("This button is clicked") - } - private fun requestExportResult(result: ActivityResult) { if (result.data != null && result.resultCode == Activity.RESULT_OK) { activity.startService( @@ -270,16 +274,16 @@ class SubscriptionFragment : BaseStateFragment() { return@setOnItemLongClickListener true } - feedGroupsCarousel = FeedGroupCarouselItem(requireContext(), carouselAdapter) + feedGroupsCarousel = FeedGroupCarouselItem(requireContext(), carouselAdapter, RecyclerView.HORIZONTAL) feedGroupsSortMenuItem = HeaderWithMenuItem( getString(R.string.feed_groups_header_title), R.drawable.ic_list, R.drawable.ic_sort, - listViewOnClickListener = ::temp, + listViewOnClickListener = ::changeLayout, menuItemOnClickListener = ::openReorderDialog ) add(Section(feedGroupsSortMenuItem, listOf(feedGroupsCarousel))) - + groupAdapter.clear() groupAdapter.add(this) } @@ -296,6 +300,62 @@ class SubscriptionFragment : BaseStateFragment() { ) } + private fun changeLayout() { + Section().apply { + val carouselAdapter = GroupAdapter>() + + carouselAdapter.add(FeedGroupCardVerticalItem(-1, getString(R.string.all), FeedGroupIcon.RSS)) + carouselAdapter.add(feedGroupsSection) + carouselAdapter.add(FeedGroupAddItem()) // change this button later + carouselAdapter.setOnItemClickListener { item, _ -> + listenerFeedVerticalGroups.selected(item) + } + carouselAdapter.setOnItemLongClickListener { item, _ -> + if (item is FeedGroupCardVerticalItem) { + if (item.groupId == FeedGroupEntity.GROUP_ALL_ID) { + return@setOnItemLongClickListener false + } + } + listenerFeedVerticalGroups.held(item) + return@setOnItemLongClickListener true + } + + feedGroupsCarouselVertical = FeedGroupCarouselItem(requireContext(), carouselAdapter, RecyclerView.VERTICAL) + feedGroupsSortMenuItem = HeaderWithMenuItem( + getString(R.string.feed_groups_header_title), + R.drawable.ic_apps, + R.drawable.ic_sort, + listViewOnClickListener = ::setupInitialLayout, + menuItemOnClickListener = ::openReorderDialog + ) + add(Section(feedGroupsSortMenuItem, listOf(feedGroupsCarouselVertical))) + groupAdapter.clear() + groupAdapter.add(this) + } + subscriptionsSection.setPlaceholder(EmptyPlaceholderItem()) + subscriptionsSection.setHideWhenEmpty(true) + + groupAdapter.add( + Section( + HeaderWithMenuItem( + getString(R.string.tab_subscriptions) + ), + listOf(subscriptionsSection) + ) + ) + + // TODO: remove this + groupAdapter.spanCount = if (shouldUseGridLayout(context)) getGridSpanCountChannels(context) else 1 + binding.itemsList.layoutManager = GridLayoutManager(requireContext(), groupAdapter.spanCount).apply { + spanSizeLookup = groupAdapter.spanSizeLookup + } + binding.itemsList.adapter = groupAdapter + + viewModel = ViewModelProvider(this).get(SubscriptionViewModel::class.java) + viewModel.stateLiveData.observe(viewLifecycleOwner) { it?.let(this::handleResult) } + viewModel.feedGroupsLiveData.observe(viewLifecycleOwner) { it?.let(this::handleFeedVerticalGroups) } + } + override fun initViews(rootView: View, savedInstanceState: Bundle?) { super.initViews(rootView, savedInstanceState) _binding = FragmentSubscriptionBinding.bind(rootView) @@ -367,6 +427,21 @@ class SubscriptionFragment : BaseStateFragment() { } } + private val listenerFeedVerticalGroups = object : OnClickGesture> { + override fun selected(selectedItem: Item<*>?) { + when (selectedItem) { + is FeedGroupCardVerticalItem -> NavigationHelper.openFeedFragment(fm, selectedItem.groupId, selectedItem.name) + is FeedGroupAddItem -> FeedGroupDialog.newInstance().show(fm, null) + } + } + + override fun held(selectedItem: Item<*>?) { + when (selectedItem) { + is FeedGroupCardVerticalItem -> FeedGroupDialog.newInstance(selectedItem.groupId).show(fm, null) + } + } + } + private val listenerChannelItem = object : OnClickGesture { override fun selected(selectedItem: ChannelInfoItem) = NavigationHelper.openChannelFragment( fm, @@ -420,6 +495,18 @@ class SubscriptionFragment : BaseStateFragment() { binding.itemsList.post { feedGroupsSortMenuItem.notifyChanged(PAYLOAD_UPDATE_VISIBILITY_MENU_ITEM) } } + private fun handleFeedVerticalGroups(groups: List) { + feedGroupsSection.update(groups) + + if (feedGroupsListState != null) { + feedGroupsCarouselVertical?.onRestoreInstanceState(feedGroupsListVerticalState) + feedGroupsListVerticalState = null + } + + feedGroupsSortMenuItem.showMenuItem = groups.size > 1 + binding.itemsList.post { feedGroupsSortMenuItem.notifyChanged(PAYLOAD_UPDATE_VISIBILITY_MENU_ITEM) } + } + // ///////////////////////////////////////////////////////////////////////// // Contract // ///////////////////////////////////////////////////////////////////////// diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupCardItem.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupCardItem.kt index fd8a75da1..a4fa84798 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupCardItem.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupCardItem.kt @@ -10,7 +10,7 @@ import org.schabi.newpipe.local.subscription.FeedGroupIcon data class FeedGroupCardItem( val groupId: Long = FeedGroupEntity.GROUP_ALL_ID, val name: String, - val icon: FeedGroupIcon + val icon: FeedGroupIcon, ) : BindableItem() { constructor (feedGroupEntity: FeedGroupEntity) : this(feedGroupEntity.uid, feedGroupEntity.name, feedGroupEntity.icon) @@ -21,7 +21,7 @@ data class FeedGroupCardItem( } } - override fun getLayout(): Int = R.layout.feed_group_list_item + override fun getLayout(): Int = R.layout.feed_group_card_item override fun bind(viewBinding: FeedGroupCardItemBinding, position: Int) { viewBinding.title.text = name diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupCardVerticalItem.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupCardVerticalItem.kt new file mode 100644 index 000000000..9750da7b4 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupCardVerticalItem.kt @@ -0,0 +1,32 @@ +package org.schabi.newpipe.local.subscription.item + +import android.view.View +import com.xwray.groupie.viewbinding.BindableItem +import org.schabi.newpipe.R +import org.schabi.newpipe.database.feed.model.FeedGroupEntity +import org.schabi.newpipe.databinding.FeedGroupCardVerticalItemBinding +import org.schabi.newpipe.local.subscription.FeedGroupIcon + +data class FeedGroupCardVerticalItem( + val groupId: Long = FeedGroupEntity.GROUP_ALL_ID, + val name: String, + val icon: FeedGroupIcon +) : BindableItem() { + constructor (feedGroupEntity: FeedGroupEntity) : this(feedGroupEntity.uid, feedGroupEntity.name, feedGroupEntity.icon) + + override fun getId(): Long { + return when (groupId) { + FeedGroupEntity.GROUP_ALL_ID -> super.getId() + else -> groupId + } + } + + override fun getLayout(): Int = R.layout.feed_group_card_vertical_item + + override fun bind(viewBinding: FeedGroupCardVerticalItemBinding, position: Int) { + viewBinding.title.text = name + viewBinding.icon.setImageResource(icon.getDrawableRes()) + } + + override fun initializeViewBinding(view: View) = FeedGroupCardVerticalItemBinding.bind(view) +} diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupCarouselItem.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupCarouselItem.kt index 031eb9b18..a574fa01b 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupCarouselItem.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupCarouselItem.kt @@ -4,7 +4,6 @@ import android.content.Context import android.os.Parcelable import android.view.View import androidx.recyclerview.widget.LinearLayoutManager -import androidx.recyclerview.widget.RecyclerView import com.xwray.groupie.GroupAdapter import com.xwray.groupie.viewbinding.BindableItem import com.xwray.groupie.viewbinding.GroupieViewHolder @@ -14,7 +13,8 @@ import org.schabi.newpipe.local.subscription.decoration.FeedGroupCarouselDecorat class FeedGroupCarouselItem( context: Context, - private val carouselAdapter: GroupAdapter> + private val carouselAdapter: GroupAdapter>, + private var listView: Int ) : BindableItem() { private val feedGroupCarouselDecoration = FeedGroupCarouselDecoration(context) @@ -36,7 +36,7 @@ class FeedGroupCarouselItem( override fun initializeViewBinding(view: View): FeedItemCarouselBinding { val viewHolder = FeedItemCarouselBinding.bind(view) - linearLayoutManager = LinearLayoutManager(view.context, RecyclerView.VERTICAL, false) + linearLayoutManager = LinearLayoutManager(view.context, listView, false) viewHolder.recyclerView.apply { layoutManager = linearLayoutManager diff --git a/app/src/main/res/layout/feed_group_list_item.xml b/app/src/main/res/layout/feed_group_card_vertical_item.xml similarity index 92% rename from app/src/main/res/layout/feed_group_list_item.xml rename to app/src/main/res/layout/feed_group_card_vertical_item.xml index c49da1eab..aadfc95a8 100644 --- a/app/src/main/res/layout/feed_group_list_item.xml +++ b/app/src/main/res/layout/feed_group_card_vertical_item.xml @@ -2,7 +2,7 @@ + From 3bfcb16f9a5929ef5ace7d34960cfe22a372bc90 Mon Sep 17 00:00:00 2001 From: Samuel Wu Date: Tue, 25 Oct 2022 00:32:21 +1100 Subject: [PATCH 05/22] Bug: SubscriptionViewModel.kt did not map values for FeedGroupCardVerticalItem in line 26 --- .../subscription/SubscriptionFragment.kt | 45 +++++-------------- 1 file changed, 12 insertions(+), 33 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt index 659187ffa..eafa9f62c 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt @@ -78,7 +78,6 @@ class SubscriptionFragment : BaseStateFragment() { private val groupAdapter = GroupAdapter>() private val feedGroupsSection = Section() private var feedGroupsCarousel: FeedGroupCarouselItem? = null - private var feedGroupsCarouselVertical: FeedGroupCarouselItem? = feedGroupsCarousel private lateinit var feedGroupsSortMenuItem: HeaderWithMenuItem private val subscriptionsSection = Section() @@ -125,7 +124,6 @@ class SubscriptionFragment : BaseStateFragment() { super.onPause() itemsListState = binding.itemsList.layoutManager?.onSaveInstanceState() feedGroupsListState = feedGroupsCarousel?.onSaveInstanceState() - feedGroupsListVerticalState = feedGroupsCarouselVertical?.onSaveInstanceState() } override fun onDestroy() { @@ -275,6 +273,7 @@ class SubscriptionFragment : BaseStateFragment() { } feedGroupsCarousel = FeedGroupCarouselItem(requireContext(), carouselAdapter, RecyclerView.HORIZONTAL) + feedGroupsSortMenuItem = HeaderWithMenuItem( getString(R.string.feed_groups_header_title), R.drawable.ic_list, @@ -282,6 +281,7 @@ class SubscriptionFragment : BaseStateFragment() { listViewOnClickListener = ::changeLayout, menuItemOnClickListener = ::openReorderDialog ) + add(Section(feedGroupsSortMenuItem, listOf(feedGroupsCarousel))) groupAdapter.clear() groupAdapter.add(this) @@ -302,15 +302,16 @@ class SubscriptionFragment : BaseStateFragment() { private fun changeLayout() { Section().apply { - val carouselAdapter = GroupAdapter>() + val carouselAdapter2 = GroupAdapter>() - carouselAdapter.add(FeedGroupCardVerticalItem(-1, getString(R.string.all), FeedGroupIcon.RSS)) - carouselAdapter.add(feedGroupsSection) - carouselAdapter.add(FeedGroupAddItem()) // change this button later - carouselAdapter.setOnItemClickListener { item, _ -> + carouselAdapter2.add(FeedGroupCardVerticalItem(-1, getString(R.string.all), FeedGroupIcon.RSS)) + carouselAdapter2.add(feedGroupsSection) + carouselAdapter2.add(FeedGroupAddItem()) + + carouselAdapter2.setOnItemClickListener { item, _ -> listenerFeedVerticalGroups.selected(item) } - carouselAdapter.setOnItemLongClickListener { item, _ -> + carouselAdapter2.setOnItemLongClickListener { item, _ -> if (item is FeedGroupCardVerticalItem) { if (item.groupId == FeedGroupEntity.GROUP_ALL_ID) { return@setOnItemLongClickListener false @@ -319,8 +320,8 @@ class SubscriptionFragment : BaseStateFragment() { listenerFeedVerticalGroups.held(item) return@setOnItemLongClickListener true } + feedGroupsCarousel = FeedGroupCarouselItem(requireContext(), carouselAdapter2, RecyclerView.VERTICAL) - feedGroupsCarouselVertical = FeedGroupCarouselItem(requireContext(), carouselAdapter, RecyclerView.VERTICAL) feedGroupsSortMenuItem = HeaderWithMenuItem( getString(R.string.feed_groups_header_title), R.drawable.ic_apps, @@ -328,7 +329,7 @@ class SubscriptionFragment : BaseStateFragment() { listViewOnClickListener = ::setupInitialLayout, menuItemOnClickListener = ::openReorderDialog ) - add(Section(feedGroupsSortMenuItem, listOf(feedGroupsCarouselVertical))) + add(Section(feedGroupsSortMenuItem, listOf(feedGroupsCarousel))) groupAdapter.clear() groupAdapter.add(this) } @@ -343,17 +344,6 @@ class SubscriptionFragment : BaseStateFragment() { listOf(subscriptionsSection) ) ) - - // TODO: remove this - groupAdapter.spanCount = if (shouldUseGridLayout(context)) getGridSpanCountChannels(context) else 1 - binding.itemsList.layoutManager = GridLayoutManager(requireContext(), groupAdapter.spanCount).apply { - spanSizeLookup = groupAdapter.spanSizeLookup - } - binding.itemsList.adapter = groupAdapter - - viewModel = ViewModelProvider(this).get(SubscriptionViewModel::class.java) - viewModel.stateLiveData.observe(viewLifecycleOwner) { it?.let(this::handleResult) } - viewModel.feedGroupsLiveData.observe(viewLifecycleOwner) { it?.let(this::handleFeedVerticalGroups) } } override fun initViews(rootView: View, savedInstanceState: Bundle?) { @@ -366,6 +356,7 @@ class SubscriptionFragment : BaseStateFragment() { } binding.itemsList.adapter = groupAdapter + //TODO: change viewModel or create another one viewModel = ViewModelProvider(this).get(SubscriptionViewModel::class.java) viewModel.stateLiveData.observe(viewLifecycleOwner) { it?.let(this::handleResult) } viewModel.feedGroupsLiveData.observe(viewLifecycleOwner) { it?.let(this::handleFeedGroups) } @@ -495,18 +486,6 @@ class SubscriptionFragment : BaseStateFragment() { binding.itemsList.post { feedGroupsSortMenuItem.notifyChanged(PAYLOAD_UPDATE_VISIBILITY_MENU_ITEM) } } - private fun handleFeedVerticalGroups(groups: List) { - feedGroupsSection.update(groups) - - if (feedGroupsListState != null) { - feedGroupsCarouselVertical?.onRestoreInstanceState(feedGroupsListVerticalState) - feedGroupsListVerticalState = null - } - - feedGroupsSortMenuItem.showMenuItem = groups.size > 1 - binding.itemsList.post { feedGroupsSortMenuItem.notifyChanged(PAYLOAD_UPDATE_VISIBILITY_MENU_ITEM) } - } - // ///////////////////////////////////////////////////////////////////////// // Contract // ///////////////////////////////////////////////////////////////////////// From 1aa1a0287e47ddddaf19bcdcafcb9c3e3f3ecc8b Mon Sep 17 00:00:00 2001 From: Samuel Wu Date: Tue, 25 Oct 2022 02:01:57 +1100 Subject: [PATCH 06/22] Could toggle between list view and grid view...once. Requires bug fixing on refreshing --- .../local/subscription/SubscriptionFragment.kt | 15 ++++++++++++++- .../local/subscription/SubscriptionViewModel.kt | 13 +++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt index eafa9f62c..d282e58c1 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt @@ -356,10 +356,11 @@ class SubscriptionFragment : BaseStateFragment() { } binding.itemsList.adapter = groupAdapter - //TODO: change viewModel or create another one + // TODO: change viewModel or create another one viewModel = ViewModelProvider(this).get(SubscriptionViewModel::class.java) viewModel.stateLiveData.observe(viewLifecycleOwner) { it?.let(this::handleResult) } viewModel.feedGroupsLiveData.observe(viewLifecycleOwner) { it?.let(this::handleFeedGroups) } + viewModel.feedGroupsVerticalLiveData.observe(viewLifecycleOwner) { it?.let(this::handleFeedGroupsVertical) } } private fun showLongTapDialog(selectedItem: ChannelInfoItem) { @@ -486,6 +487,18 @@ class SubscriptionFragment : BaseStateFragment() { binding.itemsList.post { feedGroupsSortMenuItem.notifyChanged(PAYLOAD_UPDATE_VISIBILITY_MENU_ITEM) } } + private fun handleFeedGroupsVertical(groups: List) { + feedGroupsSection.update(groups) + + if (feedGroupsListState != null) { + feedGroupsCarousel?.onRestoreInstanceState(feedGroupsListState) + feedGroupsListVerticalState = null + } + + feedGroupsSortMenuItem.showMenuItem = groups.size > 1 + binding.itemsList.post { feedGroupsSortMenuItem.notifyChanged(PAYLOAD_UPDATE_VISIBILITY_MENU_ITEM) } + } + // ///////////////////////////////////////////////////////////////////////// // Contract // ///////////////////////////////////////////////////////////////////////// diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionViewModel.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionViewModel.kt index da009e1a0..3f378929e 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionViewModel.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionViewModel.kt @@ -9,6 +9,7 @@ import io.reactivex.rxjava3.schedulers.Schedulers import org.schabi.newpipe.local.feed.FeedDatabaseManager import org.schabi.newpipe.local.subscription.item.ChannelItem import org.schabi.newpipe.local.subscription.item.FeedGroupCardItem +import org.schabi.newpipe.local.subscription.item.FeedGroupCardVerticalItem import org.schabi.newpipe.util.DEFAULT_THROTTLE_TIMEOUT import java.util.concurrent.TimeUnit @@ -18,8 +19,10 @@ class SubscriptionViewModel(application: Application) : AndroidViewModel(applica private val mutableStateLiveData = MutableLiveData() private val mutableFeedGroupsLiveData = MutableLiveData>() + private val mutableFeedGroupsVerticalLiveData = MutableLiveData>() val stateLiveData: LiveData = mutableStateLiveData val feedGroupsLiveData: LiveData> = mutableFeedGroupsLiveData + val feedGroupsVerticalLiveData: LiveData> = mutableFeedGroupsVerticalLiveData private var feedGroupItemsDisposable = feedDatabaseManager.groups() .throttleLatest(DEFAULT_THROTTLE_TIMEOUT, TimeUnit.MILLISECONDS) @@ -30,6 +33,15 @@ class SubscriptionViewModel(application: Application) : AndroidViewModel(applica { mutableStateLiveData.postValue(SubscriptionState.ErrorState(it)) } ) + private var feedGroupVerticalItemsDisposable = feedDatabaseManager.groups() + .throttleLatest(DEFAULT_THROTTLE_TIMEOUT, TimeUnit.MILLISECONDS) + .map { it.map(::FeedGroupCardVerticalItem) } + .subscribeOn(Schedulers.io()) + .subscribe( + { mutableFeedGroupsVerticalLiveData.postValue(it) }, + { mutableStateLiveData.postValue(SubscriptionState.ErrorState(it)) } + ) + private var stateItemsDisposable = subscriptionManager.subscriptions() .throttleLatest(DEFAULT_THROTTLE_TIMEOUT, TimeUnit.MILLISECONDS) .map { it.map { entity -> ChannelItem(entity.toChannelInfoItem(), entity.uid, ChannelItem.ItemVersion.MINI) } } @@ -43,6 +55,7 @@ class SubscriptionViewModel(application: Application) : AndroidViewModel(applica super.onCleared() stateItemsDisposable.dispose() feedGroupItemsDisposable.dispose() + feedGroupVerticalItemsDisposable.dispose() } sealed class SubscriptionState { From 6eddaa0d38d4c49136f3e3572e9555364884a209 Mon Sep 17 00:00:00 2001 From: Samuel Wu Date: Tue, 25 Oct 2022 02:20:14 +1100 Subject: [PATCH 07/22] Added boolean to handle feed groups. May need a better solution for this --- .../subscription/SubscriptionFragment.kt | 36 +++++++++++-------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt index d282e58c1..667243c83 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt @@ -80,6 +80,7 @@ class SubscriptionFragment : BaseStateFragment() { private var feedGroupsCarousel: FeedGroupCarouselItem? = null private lateinit var feedGroupsSortMenuItem: HeaderWithMenuItem private val subscriptionsSection = Section() + private var listView: Boolean = false private val requestExportLauncher = registerForActivityResult(StartActivityForResult(), this::requestExportResult) @@ -124,6 +125,7 @@ class SubscriptionFragment : BaseStateFragment() { super.onPause() itemsListState = binding.itemsList.layoutManager?.onSaveInstanceState() feedGroupsListState = feedGroupsCarousel?.onSaveInstanceState() + feedGroupsListVerticalState = feedGroupsCarousel?.onSaveInstanceState() } override fun onDestroy() { @@ -252,6 +254,7 @@ class SubscriptionFragment : BaseStateFragment() { // //////////////////////////////////////////////////////////////////////// private fun setupInitialLayout() { + listView = false Section().apply { val carouselAdapter = GroupAdapter>() @@ -301,6 +304,7 @@ class SubscriptionFragment : BaseStateFragment() { } private fun changeLayout() { + listView = true Section().apply { val carouselAdapter2 = GroupAdapter>() @@ -476,27 +480,31 @@ class SubscriptionFragment : BaseStateFragment() { } private fun handleFeedGroups(groups: List) { - feedGroupsSection.update(groups) + if (!listView) { + feedGroupsSection.update(groups) - if (feedGroupsListState != null) { - feedGroupsCarousel?.onRestoreInstanceState(feedGroupsListState) - feedGroupsListState = null + if (feedGroupsListState != null) { + feedGroupsCarousel?.onRestoreInstanceState(feedGroupsListState) + feedGroupsListState = null + } + + feedGroupsSortMenuItem.showMenuItem = groups.size > 1 + binding.itemsList.post { feedGroupsSortMenuItem.notifyChanged(PAYLOAD_UPDATE_VISIBILITY_MENU_ITEM) } } - - feedGroupsSortMenuItem.showMenuItem = groups.size > 1 - binding.itemsList.post { feedGroupsSortMenuItem.notifyChanged(PAYLOAD_UPDATE_VISIBILITY_MENU_ITEM) } } private fun handleFeedGroupsVertical(groups: List) { - feedGroupsSection.update(groups) + if (listView) { + feedGroupsSection.update(groups) - if (feedGroupsListState != null) { - feedGroupsCarousel?.onRestoreInstanceState(feedGroupsListState) - feedGroupsListVerticalState = null + if (feedGroupsListVerticalState != null) { + feedGroupsCarousel?.onRestoreInstanceState(feedGroupsListVerticalState) + feedGroupsListVerticalState = null + } + + feedGroupsSortMenuItem.showMenuItem = groups.size > 1 + binding.itemsList.post { feedGroupsSortMenuItem.notifyChanged(PAYLOAD_UPDATE_VISIBILITY_MENU_ITEM) } } - - feedGroupsSortMenuItem.showMenuItem = groups.size > 1 - binding.itemsList.post { feedGroupsSortMenuItem.notifyChanged(PAYLOAD_UPDATE_VISIBILITY_MENU_ITEM) } } // ///////////////////////////////////////////////////////////////////////// From 082d7a3f187c46ab5a69412701934e2b2247f782 Mon Sep 17 00:00:00 2001 From: Samuel Wu Date: Tue, 25 Oct 2022 02:38:31 +1100 Subject: [PATCH 08/22] Added working binding for a "new" button that works in the list layout. --- .../subscription/SubscriptionFragment.kt | 18 ++++---- .../item/FeedGroupAddItemVertical.kt | 12 +++++ .../feed_group_add_new_item_vertical.xml | 45 +++++++++++++++++++ 3 files changed, 66 insertions(+), 9 deletions(-) create mode 100644 app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupAddItemVertical.kt create mode 100644 app/src/main/res/layout/feed_group_add_new_item_vertical.xml diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt index 667243c83..84e63554f 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt @@ -45,6 +45,7 @@ import org.schabi.newpipe.local.subscription.dialog.FeedGroupReorderDialog import org.schabi.newpipe.local.subscription.item.ChannelItem import org.schabi.newpipe.local.subscription.item.EmptyPlaceholderItem import org.schabi.newpipe.local.subscription.item.FeedGroupAddItem +import org.schabi.newpipe.local.subscription.item.FeedGroupAddItemVertical import org.schabi.newpipe.local.subscription.item.FeedGroupCardItem import org.schabi.newpipe.local.subscription.item.FeedGroupCardVerticalItem import org.schabi.newpipe.local.subscription.item.FeedGroupCarouselItem @@ -306,16 +307,16 @@ class SubscriptionFragment : BaseStateFragment() { private fun changeLayout() { listView = true Section().apply { - val carouselAdapter2 = GroupAdapter>() + val carouselAdapter = GroupAdapter>() - carouselAdapter2.add(FeedGroupCardVerticalItem(-1, getString(R.string.all), FeedGroupIcon.RSS)) - carouselAdapter2.add(feedGroupsSection) - carouselAdapter2.add(FeedGroupAddItem()) + carouselAdapter.add(FeedGroupCardVerticalItem(-1, getString(R.string.all), FeedGroupIcon.RSS)) + carouselAdapter.add(feedGroupsSection) + carouselAdapter.add(FeedGroupAddItemVertical()) - carouselAdapter2.setOnItemClickListener { item, _ -> + carouselAdapter.setOnItemClickListener { item, _ -> listenerFeedVerticalGroups.selected(item) } - carouselAdapter2.setOnItemLongClickListener { item, _ -> + carouselAdapter.setOnItemLongClickListener { item, _ -> if (item is FeedGroupCardVerticalItem) { if (item.groupId == FeedGroupEntity.GROUP_ALL_ID) { return@setOnItemLongClickListener false @@ -324,7 +325,7 @@ class SubscriptionFragment : BaseStateFragment() { listenerFeedVerticalGroups.held(item) return@setOnItemLongClickListener true } - feedGroupsCarousel = FeedGroupCarouselItem(requireContext(), carouselAdapter2, RecyclerView.VERTICAL) + feedGroupsCarousel = FeedGroupCarouselItem(requireContext(), carouselAdapter, RecyclerView.VERTICAL) feedGroupsSortMenuItem = HeaderWithMenuItem( getString(R.string.feed_groups_header_title), @@ -360,7 +361,6 @@ class SubscriptionFragment : BaseStateFragment() { } binding.itemsList.adapter = groupAdapter - // TODO: change viewModel or create another one viewModel = ViewModelProvider(this).get(SubscriptionViewModel::class.java) viewModel.stateLiveData.observe(viewLifecycleOwner) { it?.let(this::handleResult) } viewModel.feedGroupsLiveData.observe(viewLifecycleOwner) { it?.let(this::handleFeedGroups) } @@ -427,7 +427,7 @@ class SubscriptionFragment : BaseStateFragment() { override fun selected(selectedItem: Item<*>?) { when (selectedItem) { is FeedGroupCardVerticalItem -> NavigationHelper.openFeedFragment(fm, selectedItem.groupId, selectedItem.name) - is FeedGroupAddItem -> FeedGroupDialog.newInstance().show(fm, null) + is FeedGroupAddItemVertical -> FeedGroupDialog.newInstance().show(fm, null) } } diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupAddItemVertical.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupAddItemVertical.kt new file mode 100644 index 000000000..deb126219 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupAddItemVertical.kt @@ -0,0 +1,12 @@ +package org.schabi.newpipe.local.subscription.item + +import android.view.View +import com.xwray.groupie.viewbinding.BindableItem +import org.schabi.newpipe.R +import org.schabi.newpipe.databinding.FeedGroupAddNewItemVerticalBinding + +class FeedGroupAddItemVertical : BindableItem() { + override fun getLayout(): Int = R.layout.feed_group_add_new_item_vertical + override fun bind(viewBinding: FeedGroupAddNewItemVerticalBinding, position: Int) {} + override fun initializeViewBinding(view: View) = FeedGroupAddNewItemVerticalBinding.bind(view) +} diff --git a/app/src/main/res/layout/feed_group_add_new_item_vertical.xml b/app/src/main/res/layout/feed_group_add_new_item_vertical.xml new file mode 100644 index 000000000..43427f291 --- /dev/null +++ b/app/src/main/res/layout/feed_group_add_new_item_vertical.xml @@ -0,0 +1,45 @@ + + + + + + + + + + From ed68e3bd46dafbc36952f22b776d50de5076b238 Mon Sep 17 00:00:00 2001 From: Samuel Wu Date: Tue, 25 Oct 2022 10:54:27 +1100 Subject: [PATCH 09/22] Fully working toggle button that change between vertical and horizontal view --- .../subscription/SubscriptionFragment.kt | 30 +++++++++++-------- ...ertical.kt => FeedGroupAddVerticalItem.kt} | 2 +- 2 files changed, 18 insertions(+), 14 deletions(-) rename app/src/main/java/org/schabi/newpipe/local/subscription/item/{FeedGroupAddItemVertical.kt => FeedGroupAddVerticalItem.kt} (89%) diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt index 84e63554f..89d394a4a 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt @@ -45,7 +45,7 @@ import org.schabi.newpipe.local.subscription.dialog.FeedGroupReorderDialog import org.schabi.newpipe.local.subscription.item.ChannelItem import org.schabi.newpipe.local.subscription.item.EmptyPlaceholderItem import org.schabi.newpipe.local.subscription.item.FeedGroupAddItem -import org.schabi.newpipe.local.subscription.item.FeedGroupAddItemVertical +import org.schabi.newpipe.local.subscription.item.FeedGroupAddVerticalItem import org.schabi.newpipe.local.subscription.item.FeedGroupCardItem import org.schabi.newpipe.local.subscription.item.FeedGroupCardVerticalItem import org.schabi.newpipe.local.subscription.item.FeedGroupCarouselItem @@ -78,10 +78,12 @@ class SubscriptionFragment : BaseStateFragment() { private val groupAdapter = GroupAdapter>() private val feedGroupsSection = Section() + private val feedGroupsVerticalSection = Section() private var feedGroupsCarousel: FeedGroupCarouselItem? = null + private var feedGroupsVerticalCarousel: FeedGroupCarouselItem? = null private lateinit var feedGroupsSortMenuItem: HeaderWithMenuItem private val subscriptionsSection = Section() - private var listView: Boolean = false + private var defaultListView: Boolean = true private val requestExportLauncher = registerForActivityResult(StartActivityForResult(), this::requestExportResult) @@ -255,7 +257,7 @@ class SubscriptionFragment : BaseStateFragment() { // //////////////////////////////////////////////////////////////////////// private fun setupInitialLayout() { - listView = false + defaultListView = true Section().apply { val carouselAdapter = GroupAdapter>() @@ -302,16 +304,17 @@ class SubscriptionFragment : BaseStateFragment() { listOf(subscriptionsSection) ) ) + view?.let { initViews(it, savedInstanceState = Bundle()) } } private fun changeLayout() { - listView = true + defaultListView = false Section().apply { val carouselAdapter = GroupAdapter>() carouselAdapter.add(FeedGroupCardVerticalItem(-1, getString(R.string.all), FeedGroupIcon.RSS)) - carouselAdapter.add(feedGroupsSection) - carouselAdapter.add(FeedGroupAddItemVertical()) + carouselAdapter.add(feedGroupsVerticalSection) + carouselAdapter.add(FeedGroupAddVerticalItem()) carouselAdapter.setOnItemClickListener { item, _ -> listenerFeedVerticalGroups.selected(item) @@ -325,7 +328,7 @@ class SubscriptionFragment : BaseStateFragment() { listenerFeedVerticalGroups.held(item) return@setOnItemLongClickListener true } - feedGroupsCarousel = FeedGroupCarouselItem(requireContext(), carouselAdapter, RecyclerView.VERTICAL) + feedGroupsVerticalCarousel = FeedGroupCarouselItem(requireContext(), carouselAdapter, RecyclerView.VERTICAL) feedGroupsSortMenuItem = HeaderWithMenuItem( getString(R.string.feed_groups_header_title), @@ -334,7 +337,7 @@ class SubscriptionFragment : BaseStateFragment() { listViewOnClickListener = ::setupInitialLayout, menuItemOnClickListener = ::openReorderDialog ) - add(Section(feedGroupsSortMenuItem, listOf(feedGroupsCarousel))) + add(Section(feedGroupsSortMenuItem, listOf(feedGroupsVerticalCarousel))) groupAdapter.clear() groupAdapter.add(this) } @@ -349,6 +352,7 @@ class SubscriptionFragment : BaseStateFragment() { listOf(subscriptionsSection) ) ) + view?.let { initViews(it, savedInstanceState = Bundle()) } } override fun initViews(rootView: View, savedInstanceState: Bundle?) { @@ -427,7 +431,7 @@ class SubscriptionFragment : BaseStateFragment() { override fun selected(selectedItem: Item<*>?) { when (selectedItem) { is FeedGroupCardVerticalItem -> NavigationHelper.openFeedFragment(fm, selectedItem.groupId, selectedItem.name) - is FeedGroupAddItemVertical -> FeedGroupDialog.newInstance().show(fm, null) + is FeedGroupAddVerticalItem -> FeedGroupDialog.newInstance().show(fm, null) } } @@ -480,7 +484,7 @@ class SubscriptionFragment : BaseStateFragment() { } private fun handleFeedGroups(groups: List) { - if (!listView) { + if (defaultListView) { feedGroupsSection.update(groups) if (feedGroupsListState != null) { @@ -494,11 +498,11 @@ class SubscriptionFragment : BaseStateFragment() { } private fun handleFeedGroupsVertical(groups: List) { - if (listView) { - feedGroupsSection.update(groups) + if (!defaultListView) { + feedGroupsVerticalSection.update(groups) if (feedGroupsListVerticalState != null) { - feedGroupsCarousel?.onRestoreInstanceState(feedGroupsListVerticalState) + feedGroupsVerticalCarousel?.onRestoreInstanceState(feedGroupsListVerticalState) feedGroupsListVerticalState = null } diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupAddItemVertical.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupAddVerticalItem.kt similarity index 89% rename from app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupAddItemVertical.kt rename to app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupAddVerticalItem.kt index deb126219..eae8bd5f2 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupAddItemVertical.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupAddVerticalItem.kt @@ -5,7 +5,7 @@ import com.xwray.groupie.viewbinding.BindableItem import org.schabi.newpipe.R import org.schabi.newpipe.databinding.FeedGroupAddNewItemVerticalBinding -class FeedGroupAddItemVertical : BindableItem() { +class FeedGroupAddVerticalItem : BindableItem() { override fun getLayout(): Int = R.layout.feed_group_add_new_item_vertical override fun bind(viewBinding: FeedGroupAddNewItemVerticalBinding, position: Int) {} override fun initializeViewBinding(view: View) = FeedGroupAddNewItemVerticalBinding.bind(view) From 28464344c14425ebfdc80c653c48a8a4380f6dfe Mon Sep 17 00:00:00 2001 From: Samuel Wu Date: Tue, 25 Oct 2022 11:43:25 +1100 Subject: [PATCH 10/22] Finalized design for vertical card view and removed unneeded variables in SubscriptionFragment.kt --- .../local/subscription/SubscriptionFragment.kt | 16 +++++++--------- .../item/FeedGroupAddVerticalItem.kt | 10 +++++----- ....xml => feed_group_add_new_vertical_item.xml} | 0 .../res/layout/feed_group_card_vertical_item.xml | 13 +++++++------ app/src/main/res/values/dimens.xml | 2 +- 5 files changed, 20 insertions(+), 21 deletions(-) rename app/src/main/res/layout/{feed_group_add_new_item_vertical.xml => feed_group_add_new_vertical_item.xml} (100%) diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt index 89d394a4a..348dd5897 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt @@ -78,9 +78,7 @@ class SubscriptionFragment : BaseStateFragment() { private val groupAdapter = GroupAdapter>() private val feedGroupsSection = Section() - private val feedGroupsVerticalSection = Section() private var feedGroupsCarousel: FeedGroupCarouselItem? = null - private var feedGroupsVerticalCarousel: FeedGroupCarouselItem? = null private lateinit var feedGroupsSortMenuItem: HeaderWithMenuItem private val subscriptionsSection = Section() private var defaultListView: Boolean = true @@ -284,7 +282,7 @@ class SubscriptionFragment : BaseStateFragment() { getString(R.string.feed_groups_header_title), R.drawable.ic_list, R.drawable.ic_sort, - listViewOnClickListener = ::changeLayout, + listViewOnClickListener = ::changeVerticalLayout, menuItemOnClickListener = ::openReorderDialog ) @@ -307,13 +305,13 @@ class SubscriptionFragment : BaseStateFragment() { view?.let { initViews(it, savedInstanceState = Bundle()) } } - private fun changeLayout() { + private fun changeVerticalLayout() { defaultListView = false Section().apply { val carouselAdapter = GroupAdapter>() carouselAdapter.add(FeedGroupCardVerticalItem(-1, getString(R.string.all), FeedGroupIcon.RSS)) - carouselAdapter.add(feedGroupsVerticalSection) + carouselAdapter.add(feedGroupsSection) carouselAdapter.add(FeedGroupAddVerticalItem()) carouselAdapter.setOnItemClickListener { item, _ -> @@ -328,7 +326,7 @@ class SubscriptionFragment : BaseStateFragment() { listenerFeedVerticalGroups.held(item) return@setOnItemLongClickListener true } - feedGroupsVerticalCarousel = FeedGroupCarouselItem(requireContext(), carouselAdapter, RecyclerView.VERTICAL) + feedGroupsCarousel = FeedGroupCarouselItem(requireContext(), carouselAdapter, RecyclerView.VERTICAL) feedGroupsSortMenuItem = HeaderWithMenuItem( getString(R.string.feed_groups_header_title), @@ -337,7 +335,7 @@ class SubscriptionFragment : BaseStateFragment() { listViewOnClickListener = ::setupInitialLayout, menuItemOnClickListener = ::openReorderDialog ) - add(Section(feedGroupsSortMenuItem, listOf(feedGroupsVerticalCarousel))) + add(Section(feedGroupsSortMenuItem, listOf(feedGroupsCarousel))) groupAdapter.clear() groupAdapter.add(this) } @@ -499,10 +497,10 @@ class SubscriptionFragment : BaseStateFragment() { private fun handleFeedGroupsVertical(groups: List) { if (!defaultListView) { - feedGroupsVerticalSection.update(groups) + feedGroupsSection.update(groups) if (feedGroupsListVerticalState != null) { - feedGroupsVerticalCarousel?.onRestoreInstanceState(feedGroupsListVerticalState) + feedGroupsCarousel?.onRestoreInstanceState(feedGroupsListVerticalState) feedGroupsListVerticalState = null } diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupAddVerticalItem.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupAddVerticalItem.kt index eae8bd5f2..049728591 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupAddVerticalItem.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupAddVerticalItem.kt @@ -3,10 +3,10 @@ package org.schabi.newpipe.local.subscription.item import android.view.View import com.xwray.groupie.viewbinding.BindableItem import org.schabi.newpipe.R -import org.schabi.newpipe.databinding.FeedGroupAddNewItemVerticalBinding +import org.schabi.newpipe.databinding.FeedGroupAddNewVerticalItemBinding -class FeedGroupAddVerticalItem : BindableItem() { - override fun getLayout(): Int = R.layout.feed_group_add_new_item_vertical - override fun bind(viewBinding: FeedGroupAddNewItemVerticalBinding, position: Int) {} - override fun initializeViewBinding(view: View) = FeedGroupAddNewItemVerticalBinding.bind(view) +class FeedGroupAddVerticalItem : BindableItem() { + override fun getLayout(): Int = R.layout.feed_group_add_new_vertical_item + override fun bind(viewBinding: FeedGroupAddNewVerticalItemBinding, position: Int) {} + override fun initializeViewBinding(view: View) = FeedGroupAddNewVerticalItemBinding.bind(view) } diff --git a/app/src/main/res/layout/feed_group_add_new_item_vertical.xml b/app/src/main/res/layout/feed_group_add_new_vertical_item.xml similarity index 100% rename from app/src/main/res/layout/feed_group_add_new_item_vertical.xml rename to app/src/main/res/layout/feed_group_add_new_vertical_item.xml diff --git a/app/src/main/res/layout/feed_group_card_vertical_item.xml b/app/src/main/res/layout/feed_group_card_vertical_item.xml index aadfc95a8..2924483c2 100644 --- a/app/src/main/res/layout/feed_group_card_vertical_item.xml +++ b/app/src/main/res/layout/feed_group_card_vertical_item.xml @@ -17,10 +17,10 @@ diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 419b3ca43..86bf9da5b 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -125,7 +125,7 @@ 12dp - 2dp + 4dp 4dp 16sp From c607089cbb7f2345594115875968f4bbff912cc5 Mon Sep 17 00:00:00 2001 From: Samuel Wu Date: Wed, 26 Oct 2022 00:06:48 +1100 Subject: [PATCH 11/22] Altered grid view similar to Youtube app layout --- .../local/subscription/item/FeedGroupCarouselItem.kt | 3 ++- app/src/main/res/layout/feed_group_card_item.xml | 10 ++++++---- app/src/main/res/values/dimens.xml | 2 +- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupCarouselItem.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupCarouselItem.kt index a574fa01b..01f058913 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupCarouselItem.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupCarouselItem.kt @@ -3,6 +3,7 @@ package org.schabi.newpipe.local.subscription.item import android.content.Context import android.os.Parcelable import android.view.View +import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.LinearLayoutManager import com.xwray.groupie.GroupAdapter import com.xwray.groupie.viewbinding.BindableItem @@ -43,7 +44,7 @@ class FeedGroupCarouselItem( adapter = carouselAdapter addItemDecoration(feedGroupCarouselDecoration) } - + viewHolder.recyclerView.setLayoutManager(GridLayoutManager(view.context, 3)) return viewHolder } diff --git a/app/src/main/res/layout/feed_group_card_item.xml b/app/src/main/res/layout/feed_group_card_item.xml index e57a8167f..5e87216cb 100644 --- a/app/src/main/res/layout/feed_group_card_item.xml +++ b/app/src/main/res/layout/feed_group_card_item.xml @@ -2,9 +2,9 @@ @@ -39,7 +41,7 @@ android:padding="2dp" android:textAllCaps="false" android:textColor="?attr/colorAccent" - android:textSize="10sp" + android:textSize="14sp" android:textStyle="bold" tools:ignore="SmallSp" tools:text="ALL" /> diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 86bf9da5b..ad0e029dd 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -125,7 +125,7 @@ 12dp - 4dp + 12dp 4dp 16sp From f7e10eb094c841e427638c86bff37a8200d5b146 Mon Sep 17 00:00:00 2001 From: Samuel Wu Date: Wed, 26 Oct 2022 21:05:55 +1100 Subject: [PATCH 12/22] Fully working card and list view --- .../newpipe/local/subscription/SubscriptionFragment.kt | 4 ++-- .../local/subscription/item/FeedGroupCarouselItem.kt | 6 ++++-- app/src/main/res/values/dimens.xml | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt index 348dd5897..0ee77b4ee 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt @@ -276,7 +276,7 @@ class SubscriptionFragment : BaseStateFragment() { return@setOnItemLongClickListener true } - feedGroupsCarousel = FeedGroupCarouselItem(requireContext(), carouselAdapter, RecyclerView.HORIZONTAL) + feedGroupsCarousel = FeedGroupCarouselItem(requireContext(), carouselAdapter, RecyclerView.HORIZONTAL, true) feedGroupsSortMenuItem = HeaderWithMenuItem( getString(R.string.feed_groups_header_title), @@ -326,7 +326,7 @@ class SubscriptionFragment : BaseStateFragment() { listenerFeedVerticalGroups.held(item) return@setOnItemLongClickListener true } - feedGroupsCarousel = FeedGroupCarouselItem(requireContext(), carouselAdapter, RecyclerView.VERTICAL) + feedGroupsCarousel = FeedGroupCarouselItem(requireContext(), carouselAdapter, RecyclerView.VERTICAL, false) feedGroupsSortMenuItem = HeaderWithMenuItem( getString(R.string.feed_groups_header_title), diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupCarouselItem.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupCarouselItem.kt index 01f058913..e53693cc8 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupCarouselItem.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupCarouselItem.kt @@ -15,7 +15,8 @@ import org.schabi.newpipe.local.subscription.decoration.FeedGroupCarouselDecorat class FeedGroupCarouselItem( context: Context, private val carouselAdapter: GroupAdapter>, - private var listView: Int + private var listView: Int, + private var isGridLayout: Boolean ) : BindableItem() { private val feedGroupCarouselDecoration = FeedGroupCarouselDecoration(context) @@ -44,7 +45,8 @@ class FeedGroupCarouselItem( adapter = carouselAdapter addItemDecoration(feedGroupCarouselDecoration) } - viewHolder.recyclerView.setLayoutManager(GridLayoutManager(view.context, 3)) + if (isGridLayout) + viewHolder.recyclerView.setLayoutManager(GridLayoutManager(view.context, 3)) return viewHolder } diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index ad0e029dd..9f7e50c19 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -125,7 +125,7 @@ 12dp - 12dp + 6dp 4dp 16sp From 8b9db369f6b092f4599ae7957c6378d6bff45774 Mon Sep 17 00:00:00 2001 From: Samuel Wu Date: Wed, 26 Oct 2022 21:23:50 +1100 Subject: [PATCH 13/22] Resized add new item button --- app/src/main/res/layout/feed_group_add_new_item.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/layout/feed_group_add_new_item.xml b/app/src/main/res/layout/feed_group_add_new_item.xml index 0dfe819a6..a20cf71c0 100644 --- a/app/src/main/res/layout/feed_group_add_new_item.xml +++ b/app/src/main/res/layout/feed_group_add_new_item.xml @@ -2,8 +2,8 @@ Date: Wed, 26 Oct 2022 23:20:32 +0200 Subject: [PATCH 14/22] Fix grid/list toggle implementation of feed --- .../subscription/SubscriptionFragment.kt | 278 +++++++----------- .../subscription/SubscriptionViewModel.kt | 62 +++- .../decoration/FeedGroupCarouselDecoration.kt | 35 --- .../item/FeedGroupAddNewGridItem.kt | 12 + ...GroupAddItem.kt => FeedGroupAddNewItem.kt} | 2 +- .../item/FeedGroupAddVerticalItem.kt | 12 - ...rticalItem.kt => FeedGroupCardGridItem.kt} | 14 +- .../subscription/item/FeedGroupCardItem.kt | 2 +- .../item/FeedGroupCarouselItem.kt | 64 ++-- .../local/subscription/item/GroupsHeader.kt | 50 ++++ .../newpipe/local/subscription/item/Header.kt | 17 ++ .../subscription/item/HeaderWithMenuItem.kt | 56 ---- ...m.xml => feed_group_add_new_grid_item.xml} | 16 +- .../res/layout/feed_group_add_new_item.xml | 23 +- ...item.xml => feed_group_card_grid_item.xml} | 33 ++- .../main/res/layout/feed_group_card_item.xml | 37 ++- .../main/res/layout/feed_item_carousel.xml | 1 + ...tem.xml => subscription_groups_header.xml} | 8 +- .../main/res/layout/subscription_header.xml | 15 + 19 files changed, 354 insertions(+), 383 deletions(-) delete mode 100644 app/src/main/java/org/schabi/newpipe/local/subscription/decoration/FeedGroupCarouselDecoration.kt create mode 100644 app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupAddNewGridItem.kt rename app/src/main/java/org/schabi/newpipe/local/subscription/item/{FeedGroupAddItem.kt => FeedGroupAddNewItem.kt} (86%) delete mode 100644 app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupAddVerticalItem.kt rename app/src/main/java/org/schabi/newpipe/local/subscription/item/{FeedGroupCardVerticalItem.kt => FeedGroupCardGridItem.kt} (68%) create mode 100644 app/src/main/java/org/schabi/newpipe/local/subscription/item/GroupsHeader.kt create mode 100644 app/src/main/java/org/schabi/newpipe/local/subscription/item/Header.kt delete mode 100644 app/src/main/java/org/schabi/newpipe/local/subscription/item/HeaderWithMenuItem.kt rename app/src/main/res/layout/{feed_group_add_new_vertical_item.xml => feed_group_add_new_grid_item.xml} (82%) rename app/src/main/res/layout/{feed_group_card_vertical_item.xml => feed_group_card_grid_item.xml} (65%) rename app/src/main/res/layout/{header_with_menu_item.xml => subscription_groups_header.xml} (86%) create mode 100644 app/src/main/res/layout/subscription_header.xml diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt index 0ee77b4ee..7bee7f7ee 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt @@ -20,10 +20,8 @@ import androidx.annotation.StringRes import androidx.appcompat.app.AlertDialog import androidx.lifecycle.ViewModelProvider import androidx.recyclerview.widget.GridLayoutManager -import androidx.recyclerview.widget.RecyclerView import com.xwray.groupie.Group import com.xwray.groupie.GroupAdapter -import com.xwray.groupie.Item import com.xwray.groupie.Section import com.xwray.groupie.viewbinding.GroupieViewHolder import icepick.State @@ -44,13 +42,13 @@ import org.schabi.newpipe.local.subscription.dialog.FeedGroupDialog import org.schabi.newpipe.local.subscription.dialog.FeedGroupReorderDialog import org.schabi.newpipe.local.subscription.item.ChannelItem import org.schabi.newpipe.local.subscription.item.EmptyPlaceholderItem -import org.schabi.newpipe.local.subscription.item.FeedGroupAddItem -import org.schabi.newpipe.local.subscription.item.FeedGroupAddVerticalItem +import org.schabi.newpipe.local.subscription.item.FeedGroupAddNewGridItem +import org.schabi.newpipe.local.subscription.item.FeedGroupAddNewItem +import org.schabi.newpipe.local.subscription.item.FeedGroupCardGridItem import org.schabi.newpipe.local.subscription.item.FeedGroupCardItem -import org.schabi.newpipe.local.subscription.item.FeedGroupCardVerticalItem import org.schabi.newpipe.local.subscription.item.FeedGroupCarouselItem -import org.schabi.newpipe.local.subscription.item.HeaderWithMenuItem -import org.schabi.newpipe.local.subscription.item.HeaderWithMenuItem.Companion.PAYLOAD_UPDATE_VISIBILITY_MENU_ITEM +import org.schabi.newpipe.local.subscription.item.GroupsHeader +import org.schabi.newpipe.local.subscription.item.Header import org.schabi.newpipe.local.subscription.services.SubscriptionsExportService import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.KEY_MODE @@ -77,11 +75,10 @@ class SubscriptionFragment : BaseStateFragment() { private val disposables: CompositeDisposable = CompositeDisposable() private val groupAdapter = GroupAdapter>() - private val feedGroupsSection = Section() - private var feedGroupsCarousel: FeedGroupCarouselItem? = null - private lateinit var feedGroupsSortMenuItem: HeaderWithMenuItem + private lateinit var carouselAdapter: GroupAdapter> + private lateinit var feedGroupsCarousel: FeedGroupCarouselItem + private lateinit var feedGroupsSortMenuItem: GroupsHeader private val subscriptionsSection = Section() - private var defaultListView: Boolean = true private val requestExportLauncher = registerForActivityResult(StartActivityForResult(), this::requestExportResult) @@ -94,11 +91,7 @@ class SubscriptionFragment : BaseStateFragment() { @State @JvmField - var feedGroupsListState: Parcelable? = null - - @State - @JvmField - var feedGroupsListVerticalState: Parcelable? = null + var feedGroupsCarouselState: Parcelable? = null init { setHasOptionsMenu(true) @@ -108,11 +101,6 @@ class SubscriptionFragment : BaseStateFragment() { // Fragment LifeCycle // ///////////////////////////////////////////////////////////////////////// - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setupInitialLayout() - } - override fun onAttach(context: Context) { super.onAttach(context) subscriptionManager = SubscriptionManager(requireContext()) @@ -125,8 +113,7 @@ class SubscriptionFragment : BaseStateFragment() { override fun onPause() { super.onPause() itemsListState = binding.itemsList.layoutManager?.onSaveInstanceState() - feedGroupsListState = feedGroupsCarousel?.onSaveInstanceState() - feedGroupsListVerticalState = feedGroupsCarousel?.onSaveInstanceState() + feedGroupsCarouselState = feedGroupsCarousel.onSaveInstanceState() } override fun onDestroy() { @@ -193,7 +180,7 @@ class SubscriptionFragment : BaseStateFragment() { menuItem: MenuItem, onClick: Runnable ): MenuItem { - menuItem.setOnMenuItemClickListener { _ -> + menuItem.setOnMenuItemClickListener { onClick.run() true } @@ -254,105 +241,6 @@ class SubscriptionFragment : BaseStateFragment() { // Fragment Views // //////////////////////////////////////////////////////////////////////// - private fun setupInitialLayout() { - defaultListView = true - Section().apply { - val carouselAdapter = GroupAdapter>() - - carouselAdapter.add(FeedGroupCardItem(-1, getString(R.string.all), FeedGroupIcon.RSS)) - carouselAdapter.add(feedGroupsSection) - carouselAdapter.add(FeedGroupAddItem()) - - carouselAdapter.setOnItemClickListener { item, _ -> - listenerFeedGroups.selected(item) - } - carouselAdapter.setOnItemLongClickListener { item, _ -> - if (item is FeedGroupCardItem) { - if (item.groupId == FeedGroupEntity.GROUP_ALL_ID) { - return@setOnItemLongClickListener false - } - } - listenerFeedGroups.held(item) - return@setOnItemLongClickListener true - } - - feedGroupsCarousel = FeedGroupCarouselItem(requireContext(), carouselAdapter, RecyclerView.HORIZONTAL, true) - - feedGroupsSortMenuItem = HeaderWithMenuItem( - getString(R.string.feed_groups_header_title), - R.drawable.ic_list, - R.drawable.ic_sort, - listViewOnClickListener = ::changeVerticalLayout, - menuItemOnClickListener = ::openReorderDialog - ) - - add(Section(feedGroupsSortMenuItem, listOf(feedGroupsCarousel))) - groupAdapter.clear() - groupAdapter.add(this) - } - - subscriptionsSection.setPlaceholder(EmptyPlaceholderItem()) - subscriptionsSection.setHideWhenEmpty(true) - - groupAdapter.add( - Section( - HeaderWithMenuItem( - getString(R.string.tab_subscriptions) - ), - listOf(subscriptionsSection) - ) - ) - view?.let { initViews(it, savedInstanceState = Bundle()) } - } - - private fun changeVerticalLayout() { - defaultListView = false - Section().apply { - val carouselAdapter = GroupAdapter>() - - carouselAdapter.add(FeedGroupCardVerticalItem(-1, getString(R.string.all), FeedGroupIcon.RSS)) - carouselAdapter.add(feedGroupsSection) - carouselAdapter.add(FeedGroupAddVerticalItem()) - - carouselAdapter.setOnItemClickListener { item, _ -> - listenerFeedVerticalGroups.selected(item) - } - carouselAdapter.setOnItemLongClickListener { item, _ -> - if (item is FeedGroupCardVerticalItem) { - if (item.groupId == FeedGroupEntity.GROUP_ALL_ID) { - return@setOnItemLongClickListener false - } - } - listenerFeedVerticalGroups.held(item) - return@setOnItemLongClickListener true - } - feedGroupsCarousel = FeedGroupCarouselItem(requireContext(), carouselAdapter, RecyclerView.VERTICAL, false) - - feedGroupsSortMenuItem = HeaderWithMenuItem( - getString(R.string.feed_groups_header_title), - R.drawable.ic_apps, - R.drawable.ic_sort, - listViewOnClickListener = ::setupInitialLayout, - menuItemOnClickListener = ::openReorderDialog - ) - add(Section(feedGroupsSortMenuItem, listOf(feedGroupsCarousel))) - groupAdapter.clear() - groupAdapter.add(this) - } - subscriptionsSection.setPlaceholder(EmptyPlaceholderItem()) - subscriptionsSection.setHideWhenEmpty(true) - - groupAdapter.add( - Section( - HeaderWithMenuItem( - getString(R.string.tab_subscriptions) - ), - listOf(subscriptionsSection) - ) - ) - view?.let { initViews(it, savedInstanceState = Bundle()) } - } - override fun initViews(rootView: View, savedInstanceState: Bundle?) { super.initViews(rootView, savedInstanceState) _binding = FragmentSubscriptionBinding.bind(rootView) @@ -363,10 +251,81 @@ class SubscriptionFragment : BaseStateFragment() { } binding.itemsList.adapter = groupAdapter - viewModel = ViewModelProvider(this).get(SubscriptionViewModel::class.java) + viewModel = ViewModelProvider(this)[SubscriptionViewModel::class.java] viewModel.stateLiveData.observe(viewLifecycleOwner) { it?.let(this::handleResult) } viewModel.feedGroupsLiveData.observe(viewLifecycleOwner) { it?.let(this::handleFeedGroups) } - viewModel.feedGroupsVerticalLiveData.observe(viewLifecycleOwner) { it?.let(this::handleFeedGroupsVertical) } + + setupInitialLayout() + } + + private fun setupInitialLayout() { + Section().apply { + carouselAdapter = GroupAdapter>() + + carouselAdapter.setOnItemClickListener { item, _ -> + when (item) { + is FeedGroupCardItem -> + NavigationHelper.openFeedFragment(fm, item.groupId, item.name) + is FeedGroupCardGridItem -> + NavigationHelper.openFeedFragment(fm, item.groupId, item.name) + is FeedGroupAddNewItem -> + FeedGroupDialog.newInstance().show(fm, null) + is FeedGroupAddNewGridItem -> + FeedGroupDialog.newInstance().show(fm, null) + } + } + carouselAdapter.setOnItemLongClickListener { item, _ -> + if (( + item is FeedGroupCardItem && + item.groupId == FeedGroupEntity.GROUP_ALL_ID + ) || + ( + item is FeedGroupCardGridItem && + item.groupId == FeedGroupEntity.GROUP_ALL_ID + ) + ) { + return@setOnItemLongClickListener false + } + + when (item) { + is FeedGroupCardItem -> + FeedGroupDialog.newInstance(item.groupId).show(fm, null) + is FeedGroupCardGridItem -> + FeedGroupDialog.newInstance(item.groupId).show(fm, null) + } + return@setOnItemLongClickListener true + } + + feedGroupsCarousel = FeedGroupCarouselItem( + carouselAdapter = carouselAdapter, + listViewMode = viewModel.getListViewMode() + ) + + feedGroupsSortMenuItem = GroupsHeader( + title = getString(R.string.feed_groups_header_title), + onSortClicked = ::openReorderDialog, + onToggleListViewModeClicked = ::toggleListViewMode, + listViewMode = viewModel.getListViewMode(), + ) + + add(Section(feedGroupsSortMenuItem, listOf(feedGroupsCarousel))) + groupAdapter.clear() + groupAdapter.add(this) + } + + subscriptionsSection.setPlaceholder(EmptyPlaceholderItem()) + subscriptionsSection.setHideWhenEmpty(true) + + groupAdapter.add( + Section( + Header(getString(R.string.tab_subscriptions)), + listOf(subscriptionsSection) + ) + ) + } + + private fun toggleListViewMode() { + viewModel.setListViewMode(!viewModel.getListViewMode()) } private fun showLongTapDialog(selectedItem: ChannelInfoItem) { @@ -410,36 +369,6 @@ class SubscriptionFragment : BaseStateFragment() { override fun doInitialLoadLogic() = Unit override fun startLoading(forceLoad: Boolean) = Unit - private val listenerFeedGroups = object : OnClickGesture> { - override fun selected(selectedItem: Item<*>?) { - when (selectedItem) { - is FeedGroupCardItem -> NavigationHelper.openFeedFragment(fm, selectedItem.groupId, selectedItem.name) - is FeedGroupAddItem -> FeedGroupDialog.newInstance().show(fm, null) - } - } - - override fun held(selectedItem: Item<*>?) { - when (selectedItem) { - is FeedGroupCardItem -> FeedGroupDialog.newInstance(selectedItem.groupId).show(fm, null) - } - } - } - - private val listenerFeedVerticalGroups = object : OnClickGesture> { - override fun selected(selectedItem: Item<*>?) { - when (selectedItem) { - is FeedGroupCardVerticalItem -> NavigationHelper.openFeedFragment(fm, selectedItem.groupId, selectedItem.name) - is FeedGroupAddVerticalItem -> FeedGroupDialog.newInstance().show(fm, null) - } - } - - override fun held(selectedItem: Item<*>?) { - when (selectedItem) { - is FeedGroupCardVerticalItem -> FeedGroupDialog.newInstance(selectedItem.groupId).show(fm, null) - } - } - } - private val listenerChannelItem = object : OnClickGesture { override fun selected(selectedItem: ChannelInfoItem) = NavigationHelper.openChannelFragment( fm, @@ -482,30 +411,29 @@ class SubscriptionFragment : BaseStateFragment() { } private fun handleFeedGroups(groups: List) { - if (defaultListView) { - feedGroupsSection.update(groups) + val listViewMode = viewModel.getListViewMode() - if (feedGroupsListState != null) { - feedGroupsCarousel?.onRestoreInstanceState(feedGroupsListState) - feedGroupsListState = null - } + carouselAdapter.clear() + carouselAdapter.add( + if (listViewMode) + FeedGroupCardItem(-1, getString(R.string.all), FeedGroupIcon.RSS) + else + FeedGroupCardGridItem(-1, getString(R.string.all), FeedGroupIcon.RSS) + ) + carouselAdapter.addAll(groups) + carouselAdapter.add(if (listViewMode) FeedGroupAddNewItem() else FeedGroupAddNewGridItem()) - feedGroupsSortMenuItem.showMenuItem = groups.size > 1 - binding.itemsList.post { feedGroupsSortMenuItem.notifyChanged(PAYLOAD_UPDATE_VISIBILITY_MENU_ITEM) } + if (feedGroupsCarouselState != null) { + feedGroupsCarousel.onRestoreInstanceState(feedGroupsCarouselState) + feedGroupsCarouselState = null } - } - private fun handleFeedGroupsVertical(groups: List) { - if (!defaultListView) { - feedGroupsSection.update(groups) - - if (feedGroupsListVerticalState != null) { - feedGroupsCarousel?.onRestoreInstanceState(feedGroupsListVerticalState) - feedGroupsListVerticalState = null - } - - feedGroupsSortMenuItem.showMenuItem = groups.size > 1 - binding.itemsList.post { feedGroupsSortMenuItem.notifyChanged(PAYLOAD_UPDATE_VISIBILITY_MENU_ITEM) } + feedGroupsCarousel.listViewMode = listViewMode + feedGroupsSortMenuItem.showSortButton = groups.size > 1 + feedGroupsSortMenuItem.listViewMode = listViewMode + binding.itemsList.post { + feedGroupsCarousel.notifyChanged(FeedGroupCarouselItem.PAYLOAD_UPDATE_LIST_VIEW_MODE) + feedGroupsSortMenuItem.notifyChanged(GroupsHeader.PAYLOAD_UPDATE_ICONS) } } diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionViewModel.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionViewModel.kt index 3f378929e..814e697ce 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionViewModel.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionViewModel.kt @@ -1,15 +1,20 @@ package org.schabi.newpipe.local.subscription import android.app.Application +import android.content.res.Configuration import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData +import androidx.preference.PreferenceManager import com.xwray.groupie.Group +import io.reactivex.rxjava3.core.Flowable +import io.reactivex.rxjava3.processors.BehaviorProcessor import io.reactivex.rxjava3.schedulers.Schedulers +import org.schabi.newpipe.R import org.schabi.newpipe.local.feed.FeedDatabaseManager import org.schabi.newpipe.local.subscription.item.ChannelItem +import org.schabi.newpipe.local.subscription.item.FeedGroupCardGridItem import org.schabi.newpipe.local.subscription.item.FeedGroupCardItem -import org.schabi.newpipe.local.subscription.item.FeedGroupCardVerticalItem import org.schabi.newpipe.util.DEFAULT_THROTTLE_TIMEOUT import java.util.concurrent.TimeUnit @@ -17,31 +22,31 @@ class SubscriptionViewModel(application: Application) : AndroidViewModel(applica private var feedDatabaseManager: FeedDatabaseManager = FeedDatabaseManager(application) private var subscriptionManager = SubscriptionManager(application) + // true -> list view, false -> grid view + private val listViewMode = BehaviorProcessor.createDefault(!isGridLayout(application)) + private val listViewModeFlowable = listViewMode.distinctUntilChanged() + private val mutableStateLiveData = MutableLiveData() private val mutableFeedGroupsLiveData = MutableLiveData>() - private val mutableFeedGroupsVerticalLiveData = MutableLiveData>() val stateLiveData: LiveData = mutableStateLiveData val feedGroupsLiveData: LiveData> = mutableFeedGroupsLiveData - val feedGroupsVerticalLiveData: LiveData> = mutableFeedGroupsVerticalLiveData - private var feedGroupItemsDisposable = feedDatabaseManager.groups() + private var feedGroupItemsDisposable = Flowable + .combineLatest( + feedDatabaseManager.groups(), + listViewModeFlowable, + ::Pair + ) .throttleLatest(DEFAULT_THROTTLE_TIMEOUT, TimeUnit.MILLISECONDS) - .map { it.map(::FeedGroupCardItem) } + .map { (feedGroups, listViewMode) -> + feedGroups.map(if (listViewMode) ::FeedGroupCardItem else ::FeedGroupCardGridItem) + } .subscribeOn(Schedulers.io()) .subscribe( { mutableFeedGroupsLiveData.postValue(it) }, { mutableStateLiveData.postValue(SubscriptionState.ErrorState(it)) } ) - private var feedGroupVerticalItemsDisposable = feedDatabaseManager.groups() - .throttleLatest(DEFAULT_THROTTLE_TIMEOUT, TimeUnit.MILLISECONDS) - .map { it.map(::FeedGroupCardVerticalItem) } - .subscribeOn(Schedulers.io()) - .subscribe( - { mutableFeedGroupsVerticalLiveData.postValue(it) }, - { mutableStateLiveData.postValue(SubscriptionState.ErrorState(it)) } - ) - private var stateItemsDisposable = subscriptionManager.subscriptions() .throttleLatest(DEFAULT_THROTTLE_TIMEOUT, TimeUnit.MILLISECONDS) .map { it.map { entity -> ChannelItem(entity.toChannelInfoItem(), entity.uid, ChannelItem.ItemVersion.MINI) } } @@ -55,11 +60,38 @@ class SubscriptionViewModel(application: Application) : AndroidViewModel(applica super.onCleared() stateItemsDisposable.dispose() feedGroupItemsDisposable.dispose() - feedGroupVerticalItemsDisposable.dispose() + } + + fun setListViewMode(newListViewMode: Boolean) { + listViewMode.onNext(newListViewMode) + } + + fun getListViewMode(): Boolean { + return listViewMode.value ?: true } sealed class SubscriptionState { data class LoadedState(val subscriptions: List) : SubscriptionState() data class ErrorState(val error: Throwable? = null) : SubscriptionState() } + + companion object { + private fun isGridLayout(application: Application): Boolean { + val listMode = PreferenceManager.getDefaultSharedPreferences(application) + .getString( + application.getString(R.string.list_view_mode_key), + application.getString(R.string.list_view_mode_value) + ) + + return if ("auto" == listMode) { + val configuration: Configuration = application.resources.configuration + ( + configuration.orientation == Configuration.ORIENTATION_LANDSCAPE && + configuration.isLayoutSizeAtLeast(Configuration.SCREENLAYOUT_SIZE_LARGE) + ) + } else { + "grid" == listMode + } + } + } } diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/decoration/FeedGroupCarouselDecoration.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/decoration/FeedGroupCarouselDecoration.kt deleted file mode 100644 index a113a8b41..000000000 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/decoration/FeedGroupCarouselDecoration.kt +++ /dev/null @@ -1,35 +0,0 @@ -package org.schabi.newpipe.local.subscription.decoration - -import android.content.Context -import android.graphics.Rect -import android.view.View -import androidx.recyclerview.widget.RecyclerView -import org.schabi.newpipe.R - -class FeedGroupCarouselDecoration(context: Context) : RecyclerView.ItemDecoration() { - - private val marginStartEnd: Int - private val marginTopBottom: Int - private val marginBetweenItems: Int - - init { - with(context.resources) { - marginStartEnd = getDimensionPixelOffset(R.dimen.feed_group_carousel_start_end_margin) - marginTopBottom = getDimensionPixelOffset(R.dimen.feed_group_carousel_top_bottom_margin) - marginBetweenItems = getDimensionPixelOffset(R.dimen.feed_group_carousel_between_items_margin) - } - } - - override fun getItemOffsets(outRect: Rect, child: View, parent: RecyclerView, state: RecyclerView.State) { - val childAdapterPosition = parent.getChildAdapterPosition(child) - val childAdapterCount = parent.adapter?.itemCount ?: 0 - - outRect.set(marginBetweenItems, marginTopBottom, 0, marginTopBottom) - - if (childAdapterPosition >= 0) { - outRect.left = marginStartEnd - } else if (childAdapterPosition == childAdapterCount - 1) { - outRect.right = marginStartEnd - } - } -} diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupAddNewGridItem.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupAddNewGridItem.kt new file mode 100644 index 000000000..55d1c6097 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupAddNewGridItem.kt @@ -0,0 +1,12 @@ +package org.schabi.newpipe.local.subscription.item + +import android.view.View +import com.xwray.groupie.viewbinding.BindableItem +import org.schabi.newpipe.R +import org.schabi.newpipe.databinding.FeedGroupAddNewGridItemBinding + +class FeedGroupAddNewGridItem : BindableItem() { + override fun getLayout(): Int = R.layout.feed_group_add_new_grid_item + override fun bind(viewBinding: FeedGroupAddNewGridItemBinding, position: Int) {} + override fun initializeViewBinding(view: View) = FeedGroupAddNewGridItemBinding.bind(view) +} diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupAddItem.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupAddNewItem.kt similarity index 86% rename from app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupAddItem.kt rename to app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupAddNewItem.kt index 434b4f29a..735df80df 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupAddItem.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupAddNewItem.kt @@ -5,7 +5,7 @@ import com.xwray.groupie.viewbinding.BindableItem import org.schabi.newpipe.R import org.schabi.newpipe.databinding.FeedGroupAddNewItemBinding -class FeedGroupAddItem : BindableItem() { +class FeedGroupAddNewItem : BindableItem() { override fun getLayout(): Int = R.layout.feed_group_add_new_item override fun bind(viewBinding: FeedGroupAddNewItemBinding, position: Int) {} override fun initializeViewBinding(view: View) = FeedGroupAddNewItemBinding.bind(view) diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupAddVerticalItem.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupAddVerticalItem.kt deleted file mode 100644 index 049728591..000000000 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupAddVerticalItem.kt +++ /dev/null @@ -1,12 +0,0 @@ -package org.schabi.newpipe.local.subscription.item - -import android.view.View -import com.xwray.groupie.viewbinding.BindableItem -import org.schabi.newpipe.R -import org.schabi.newpipe.databinding.FeedGroupAddNewVerticalItemBinding - -class FeedGroupAddVerticalItem : BindableItem() { - override fun getLayout(): Int = R.layout.feed_group_add_new_vertical_item - override fun bind(viewBinding: FeedGroupAddNewVerticalItemBinding, position: Int) {} - override fun initializeViewBinding(view: View) = FeedGroupAddNewVerticalItemBinding.bind(view) -} diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupCardVerticalItem.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupCardGridItem.kt similarity index 68% rename from app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupCardVerticalItem.kt rename to app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupCardGridItem.kt index 9750da7b4..5a9d6887b 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupCardVerticalItem.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupCardGridItem.kt @@ -4,14 +4,14 @@ import android.view.View import com.xwray.groupie.viewbinding.BindableItem import org.schabi.newpipe.R import org.schabi.newpipe.database.feed.model.FeedGroupEntity -import org.schabi.newpipe.databinding.FeedGroupCardVerticalItemBinding +import org.schabi.newpipe.databinding.FeedGroupCardGridItemBinding import org.schabi.newpipe.local.subscription.FeedGroupIcon -data class FeedGroupCardVerticalItem( +data class FeedGroupCardGridItem( val groupId: Long = FeedGroupEntity.GROUP_ALL_ID, val name: String, - val icon: FeedGroupIcon -) : BindableItem() { + val icon: FeedGroupIcon, +) : BindableItem() { constructor (feedGroupEntity: FeedGroupEntity) : this(feedGroupEntity.uid, feedGroupEntity.name, feedGroupEntity.icon) override fun getId(): Long { @@ -21,12 +21,12 @@ data class FeedGroupCardVerticalItem( } } - override fun getLayout(): Int = R.layout.feed_group_card_vertical_item + override fun getLayout(): Int = R.layout.feed_group_card_grid_item - override fun bind(viewBinding: FeedGroupCardVerticalItemBinding, position: Int) { + override fun bind(viewBinding: FeedGroupCardGridItemBinding, position: Int) { viewBinding.title.text = name viewBinding.icon.setImageResource(icon.getDrawableRes()) } - override fun initializeViewBinding(view: View) = FeedGroupCardVerticalItemBinding.bind(view) + override fun initializeViewBinding(view: View) = FeedGroupCardGridItemBinding.bind(view) } diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupCardItem.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupCardItem.kt index a4fa84798..7b78b3d95 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupCardItem.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupCardItem.kt @@ -10,7 +10,7 @@ import org.schabi.newpipe.local.subscription.FeedGroupIcon data class FeedGroupCardItem( val groupId: Long = FeedGroupEntity.GROUP_ALL_ID, val name: String, - val icon: FeedGroupIcon, + val icon: FeedGroupIcon ) : BindableItem() { constructor (feedGroupEntity: FeedGroupEntity) : this(feedGroupEntity.uid, feedGroupEntity.name, feedGroupEntity.icon) diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupCarouselItem.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupCarouselItem.kt index e53693cc8..ad1e7e690 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupCarouselItem.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupCarouselItem.kt @@ -1,6 +1,5 @@ package org.schabi.newpipe.local.subscription.item -import android.content.Context import android.os.Parcelable import android.view.View import androidx.recyclerview.widget.GridLayoutManager @@ -10,54 +9,77 @@ import com.xwray.groupie.viewbinding.BindableItem import com.xwray.groupie.viewbinding.GroupieViewHolder import org.schabi.newpipe.R import org.schabi.newpipe.databinding.FeedItemCarouselBinding -import org.schabi.newpipe.local.subscription.decoration.FeedGroupCarouselDecoration +import org.schabi.newpipe.util.DeviceUtils +import java.lang.Integer.max class FeedGroupCarouselItem( - context: Context, private val carouselAdapter: GroupAdapter>, - private var listView: Int, - private var isGridLayout: Boolean + var listViewMode: Boolean ) : BindableItem() { - private val feedGroupCarouselDecoration = FeedGroupCarouselDecoration(context) + companion object { + const val PAYLOAD_UPDATE_LIST_VIEW_MODE = 2 + } - private var linearLayoutManager: LinearLayoutManager? = null + private var carouselLayoutManager: LinearLayoutManager? = null private var listState: Parcelable? = null override fun getLayout() = R.layout.feed_item_carousel fun onSaveInstanceState(): Parcelable? { - listState = linearLayoutManager?.onSaveInstanceState() + listState = carouselLayoutManager?.onSaveInstanceState() return listState } fun onRestoreInstanceState(state: Parcelable?) { - linearLayoutManager?.onRestoreInstanceState(state) + carouselLayoutManager?.onRestoreInstanceState(state) listState = state } override fun initializeViewBinding(view: View): FeedItemCarouselBinding { - val viewHolder = FeedItemCarouselBinding.bind(view) + val viewBinding = FeedItemCarouselBinding.bind(view) + updateViewMode(viewBinding) + return viewBinding + } - linearLayoutManager = LinearLayoutManager(view.context, listView, false) - - viewHolder.recyclerView.apply { - layoutManager = linearLayoutManager - adapter = carouselAdapter - addItemDecoration(feedGroupCarouselDecoration) + override fun bind( + viewBinding: FeedItemCarouselBinding, + position: Int, + payloads: MutableList + ) { + if (payloads.contains(PAYLOAD_UPDATE_LIST_VIEW_MODE)) { + updateViewMode(viewBinding) + return } - if (isGridLayout) - viewHolder.recyclerView.setLayoutManager(GridLayoutManager(view.context, 3)) - return viewHolder + + super.bind(viewBinding, position, payloads) } override fun bind(viewBinding: FeedItemCarouselBinding, position: Int) { viewBinding.recyclerView.apply { adapter = carouselAdapter } - linearLayoutManager?.onRestoreInstanceState(listState) + carouselLayoutManager?.onRestoreInstanceState(listState) } override fun unbind(viewHolder: GroupieViewHolder) { super.unbind(viewHolder) + listState = carouselLayoutManager?.onSaveInstanceState() + } - listState = linearLayoutManager?.onSaveInstanceState() + private fun updateViewMode(viewBinding: FeedItemCarouselBinding) { + viewBinding.recyclerView.apply { adapter = carouselAdapter } + + val context = viewBinding.root.context + carouselLayoutManager = if (listViewMode) { + LinearLayoutManager(context) + } else { + GridLayoutManager( + context, + max(1, viewBinding.recyclerView.width / DeviceUtils.dpToPx(112, context)) + ) + } + + viewBinding.recyclerView.apply { + layoutManager = carouselLayoutManager + adapter = carouselAdapter + } } } diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/item/GroupsHeader.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/item/GroupsHeader.kt new file mode 100644 index 000000000..8d5088890 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/item/GroupsHeader.kt @@ -0,0 +1,50 @@ +package org.schabi.newpipe.local.subscription.item + +import android.view.View +import androidx.core.view.isVisible +import com.xwray.groupie.viewbinding.BindableItem +import org.schabi.newpipe.R +import org.schabi.newpipe.databinding.SubscriptionGroupsHeaderBinding + +class GroupsHeader( + private val title: String, + private val onSortClicked: () -> Unit, + private val onToggleListViewModeClicked: () -> Unit, + var showSortButton: Boolean = true, + var listViewMode: Boolean = true +) : BindableItem() { + companion object { + const val PAYLOAD_UPDATE_ICONS = 1 + } + + override fun getLayout(): Int = R.layout.subscription_groups_header + + override fun bind( + viewBinding: SubscriptionGroupsHeaderBinding, + position: Int, + payloads: MutableList + ) { + if (payloads.contains(PAYLOAD_UPDATE_ICONS)) { + updateIcons(viewBinding) + return + } + + super.bind(viewBinding, position, payloads) + } + + override fun bind(viewBinding: SubscriptionGroupsHeaderBinding, position: Int) { + viewBinding.headerTitle.text = title + viewBinding.headerSort.setOnClickListener { onSortClicked() } + viewBinding.headerToggleViewMode.setOnClickListener { onToggleListViewModeClicked() } + updateIcons(viewBinding) + } + + override fun initializeViewBinding(view: View) = SubscriptionGroupsHeaderBinding.bind(view) + + private fun updateIcons(viewBinding: SubscriptionGroupsHeaderBinding) { + viewBinding.headerToggleViewMode.setImageResource( + if (listViewMode) R.drawable.ic_apps else R.drawable.ic_list + ) + viewBinding.headerSort.isVisible = showSortButton + } +} diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/item/Header.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/item/Header.kt new file mode 100644 index 000000000..87a3ac768 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/item/Header.kt @@ -0,0 +1,17 @@ +package org.schabi.newpipe.local.subscription.item + +import android.view.View +import com.xwray.groupie.viewbinding.BindableItem +import org.schabi.newpipe.R +import org.schabi.newpipe.databinding.SubscriptionHeaderBinding + +class Header(private val title: String) : BindableItem() { + + override fun getLayout(): Int = R.layout.subscription_header + + override fun bind(viewBinding: SubscriptionHeaderBinding, position: Int) { + viewBinding.root.text = title + } + + override fun initializeViewBinding(view: View) = SubscriptionHeaderBinding.bind(view) +} diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/item/HeaderWithMenuItem.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/item/HeaderWithMenuItem.kt deleted file mode 100644 index 338083c87..000000000 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/item/HeaderWithMenuItem.kt +++ /dev/null @@ -1,56 +0,0 @@ -package org.schabi.newpipe.local.subscription.item - -import android.view.View -import android.view.View.OnClickListener -import androidx.annotation.DrawableRes -import androidx.core.view.isVisible -import com.xwray.groupie.viewbinding.BindableItem -import org.schabi.newpipe.R -import org.schabi.newpipe.databinding.HeaderWithMenuItemBinding - -class HeaderWithMenuItem( - val title: String, - @DrawableRes val itemIcon: Int = 0, - @DrawableRes val itemIconListView: Int = 0, - var showMenuItem: Boolean = true, - private val onClickListener: (() -> Unit)? = null, - private val listViewOnClickListener: (() -> Unit)? = null, - private val menuItemOnClickListener: (() -> Unit)? = null -) : BindableItem() { - companion object { - const val PAYLOAD_UPDATE_VISIBILITY_MENU_ITEM = 1 - } - - override fun getLayout(): Int = R.layout.header_with_menu_item - - override fun bind(viewBinding: HeaderWithMenuItemBinding, position: Int, payloads: MutableList) { - if (payloads.contains(PAYLOAD_UPDATE_VISIBILITY_MENU_ITEM)) { - updateMenuItemVisibility(viewBinding) - return - } - - super.bind(viewBinding, position, payloads) - } - - override fun bind(viewBinding: HeaderWithMenuItemBinding, position: Int) { - viewBinding.headerTitle.text = title - viewBinding.headerMenuItem2.setImageResource(itemIcon) - viewBinding.headerMenuItem.setImageResource(itemIconListView) - - val listener = onClickListener?.let { OnClickListener { onClickListener.invoke() } } - viewBinding.root.setOnClickListener(listener) - - val listViewListener = listViewOnClickListener?.let { OnClickListener { listViewOnClickListener.invoke() } } - viewBinding.headerMenuItem2.setOnClickListener(listViewListener) - - val menuItemListener = menuItemOnClickListener?.let { OnClickListener { menuItemOnClickListener.invoke() } } - viewBinding.headerMenuItem.setOnClickListener(menuItemListener) - updateMenuItemVisibility(viewBinding) - } - - override fun initializeViewBinding(view: View) = HeaderWithMenuItemBinding.bind(view) - - private fun updateMenuItemVisibility(viewBinding: HeaderWithMenuItemBinding) { - viewBinding.headerMenuItem.isVisible = showMenuItem - } -} diff --git a/app/src/main/res/layout/feed_group_add_new_vertical_item.xml b/app/src/main/res/layout/feed_group_add_new_grid_item.xml similarity index 82% rename from app/src/main/res/layout/feed_group_add_new_vertical_item.xml rename to app/src/main/res/layout/feed_group_add_new_grid_item.xml index 43427f291..e0c336d75 100644 --- a/app/src/main/res/layout/feed_group_add_new_vertical_item.xml +++ b/app/src/main/res/layout/feed_group_add_new_grid_item.xml @@ -2,9 +2,10 @@ @@ -31,15 +33,13 @@ android:id="@+id/title" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginTop="2dp" android:ellipsize="end" android:gravity="center" android:maxLines="1" android:text="@string/feed_create_new_group_button_title" android:textAllCaps="true" android:textColor="?attr/colorAccent" - android:textSize="10sp" - android:textStyle="bold" - tools:ignore="SmallSp" /> + android:textSize="14sp" + android:textStyle="bold" /> diff --git a/app/src/main/res/layout/feed_group_add_new_item.xml b/app/src/main/res/layout/feed_group_add_new_item.xml index a20cf71c0..b8f39542f 100644 --- a/app/src/main/res/layout/feed_group_add_new_item.xml +++ b/app/src/main/res/layout/feed_group_add_new_item.xml @@ -2,9 +2,10 @@ + android:orientation="horizontal"> @@ -31,15 +31,14 @@ android:id="@+id/title" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginTop="2dp" + android:layout_gravity="center_vertical" android:ellipsize="end" - android:gravity="center" android:maxLines="1" + android:padding="10dp" android:text="@string/feed_create_new_group_button_title" android:textAllCaps="true" android:textColor="?attr/colorAccent" - android:textSize="10sp" - android:textStyle="bold" - tools:ignore="SmallSp" /> + android:textSize="14sp" + android:textStyle="bold" /> diff --git a/app/src/main/res/layout/feed_group_card_vertical_item.xml b/app/src/main/res/layout/feed_group_card_grid_item.xml similarity index 65% rename from app/src/main/res/layout/feed_group_card_vertical_item.xml rename to app/src/main/res/layout/feed_group_card_grid_item.xml index 2924483c2..f50724ba2 100644 --- a/app/src/main/res/layout/feed_group_card_vertical_item.xml +++ b/app/src/main/res/layout/feed_group_card_grid_item.xml @@ -2,44 +2,45 @@ + android:orientation="vertical" + android:paddingTop="2dp"> - diff --git a/app/src/main/res/layout/feed_group_card_item.xml b/app/src/main/res/layout/feed_group_card_item.xml index 5e87216cb..29e553345 100644 --- a/app/src/main/res/layout/feed_group_card_item.xml +++ b/app/src/main/res/layout/feed_group_card_item.xml @@ -2,9 +2,10 @@ + android:layout_height="wrap_content" + android:orientation="horizontal"> + tools:text="All" /> + diff --git a/app/src/main/res/layout/feed_item_carousel.xml b/app/src/main/res/layout/feed_item_carousel.xml index 4e8fc2c90..22389e9fa 100644 --- a/app/src/main/res/layout/feed_item_carousel.xml +++ b/app/src/main/res/layout/feed_item_carousel.xml @@ -3,4 +3,5 @@ android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="wrap_content" + android:layout_margin="4dp" android:scrollbars="none" /> diff --git a/app/src/main/res/layout/header_with_menu_item.xml b/app/src/main/res/layout/subscription_groups_header.xml similarity index 86% rename from app/src/main/res/layout/header_with_menu_item.xml rename to app/src/main/res/layout/subscription_groups_header.xml index 170c40098..b290d9dda 100644 --- a/app/src/main/res/layout/header_with_menu_item.xml +++ b/app/src/main/res/layout/subscription_groups_header.xml @@ -23,18 +23,18 @@ tools:text="Header" /> + tools:src="@drawable/ic_apps" /> + android:src="@drawable/ic_sort" /> \ No newline at end of file diff --git a/app/src/main/res/layout/subscription_header.xml b/app/src/main/res/layout/subscription_header.xml new file mode 100644 index 000000000..c00fae036 --- /dev/null +++ b/app/src/main/res/layout/subscription_header.xml @@ -0,0 +1,15 @@ + + \ No newline at end of file From 8f157be7e016c82687d38ff0cc4379f8de6cb28e Mon Sep 17 00:00:00 2001 From: Samuel Wu Date: Thu, 27 Oct 2022 12:15:36 +1100 Subject: [PATCH 15/22] Revert changes --- .../5.json | 26 +++++-------------- .../database/feed/model/FeedGroupEntity.kt | 2 +- 2 files changed, 8 insertions(+), 20 deletions(-) diff --git a/app/schemas/org.schabi.newpipe.database.AppDatabase/5.json b/app/schemas/org.schabi.newpipe.database.AppDatabase/5.json index eeebdeb49..9a1c62995 100644 --- a/app/schemas/org.schabi.newpipe.database.AppDatabase/5.json +++ b/app/schemas/org.schabi.newpipe.database.AppDatabase/5.json @@ -71,7 +71,6 @@ "service_id", "url" ], - "orders": [], "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_subscriptions_service_id_url` ON `${TABLE_NAME}` (`service_id`, `url`)" } ], @@ -79,8 +78,14 @@ }, { "tableName": "search_history", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`creation_date` INTEGER, `service_id` INTEGER NOT NULL, `search` TEXT, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `creation_date` INTEGER, `service_id` INTEGER NOT NULL, `search` TEXT)", "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, { "fieldPath": "creationDate", "columnName": "creation_date", @@ -98,12 +103,6 @@ "columnName": "search", "affinity": "TEXT", "notNull": false - }, - { - "fieldPath": "id", - "columnName": "id", - "affinity": "INTEGER", - "notNull": true } ], "primaryKey": { @@ -119,7 +118,6 @@ "columnNames": [ "search" ], - "orders": [], "createSql": "CREATE INDEX IF NOT EXISTS `index_search_history_search` ON `${TABLE_NAME}` (`search`)" } ], @@ -222,7 +220,6 @@ "service_id", "url" ], - "orders": [], "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_streams_service_id_url` ON `${TABLE_NAME}` (`service_id`, `url`)" } ], @@ -265,7 +262,6 @@ "columnNames": [ "stream_id" ], - "orders": [], "createSql": "CREATE INDEX IF NOT EXISTS `index_stream_history_stream_id` ON `${TABLE_NAME}` (`stream_id`)" } ], @@ -357,7 +353,6 @@ "columnNames": [ "name" ], - "orders": [], "createSql": "CREATE INDEX IF NOT EXISTS `index_playlists_name` ON `${TABLE_NAME}` (`name`)" } ], @@ -401,7 +396,6 @@ "playlist_id", "join_index" ], - "orders": [], "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_playlist_stream_join_playlist_id_join_index` ON `${TABLE_NAME}` (`playlist_id`, `join_index`)" }, { @@ -410,7 +404,6 @@ "columnNames": [ "stream_id" ], - "orders": [], "createSql": "CREATE INDEX IF NOT EXISTS `index_playlist_stream_join_stream_id` ON `${TABLE_NAME}` (`stream_id`)" } ], @@ -499,7 +492,6 @@ "columnNames": [ "name" ], - "orders": [], "createSql": "CREATE INDEX IF NOT EXISTS `index_remote_playlists_name` ON `${TABLE_NAME}` (`name`)" }, { @@ -509,7 +501,6 @@ "service_id", "url" ], - "orders": [], "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_remote_playlists_service_id_url` ON `${TABLE_NAME}` (`service_id`, `url`)" } ], @@ -546,7 +537,6 @@ "columnNames": [ "subscription_id" ], - "orders": [], "createSql": "CREATE INDEX IF NOT EXISTS `index_feed_subscription_id` ON `${TABLE_NAME}` (`subscription_id`)" } ], @@ -617,7 +607,6 @@ "columnNames": [ "sort_order" ], - "orders": [], "createSql": "CREATE INDEX IF NOT EXISTS `index_feed_group_sort_order` ON `${TABLE_NAME}` (`sort_order`)" } ], @@ -654,7 +643,6 @@ "columnNames": [ "subscription_id" ], - "orders": [], "createSql": "CREATE INDEX IF NOT EXISTS `index_feed_group_subscription_join_subscription_id` ON `${TABLE_NAME}` (`subscription_id`)" } ], diff --git a/app/src/main/java/org/schabi/newpipe/database/feed/model/FeedGroupEntity.kt b/app/src/main/java/org/schabi/newpipe/database/feed/model/FeedGroupEntity.kt index c7415ace0..1dd26946a 100644 --- a/app/src/main/java/org/schabi/newpipe/database/feed/model/FeedGroupEntity.kt +++ b/app/src/main/java/org/schabi/newpipe/database/feed/model/FeedGroupEntity.kt @@ -24,7 +24,7 @@ data class FeedGroupEntity( var icon: FeedGroupIcon, @ColumnInfo(name = SORT_ORDER) - var sortOrder: Long = -1, + var sortOrder: Long = -1 ) { companion object { const val FEED_GROUP_TABLE = "feed_group" From 8ceefee1e360755321acaee494cb89d7a082ab91 Mon Sep 17 00:00:00 2001 From: Stypox Date: Thu, 27 Oct 2022 13:51:56 +0200 Subject: [PATCH 16/22] Put "New feed group" item at the top --- .../schabi/newpipe/local/subscription/SubscriptionFragment.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt index 7bee7f7ee..770da3afe 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt @@ -414,6 +414,7 @@ class SubscriptionFragment : BaseStateFragment() { val listViewMode = viewModel.getListViewMode() carouselAdapter.clear() + carouselAdapter.add(if (listViewMode) FeedGroupAddNewItem() else FeedGroupAddNewGridItem()) carouselAdapter.add( if (listViewMode) FeedGroupCardItem(-1, getString(R.string.all), FeedGroupIcon.RSS) @@ -421,7 +422,6 @@ class SubscriptionFragment : BaseStateFragment() { FeedGroupCardGridItem(-1, getString(R.string.all), FeedGroupIcon.RSS) ) carouselAdapter.addAll(groups) - carouselAdapter.add(if (listViewMode) FeedGroupAddNewItem() else FeedGroupAddNewGridItem()) if (feedGroupsCarouselState != null) { feedGroupsCarousel.onRestoreInstanceState(feedGroupsCarouselState) From 83d16dc656d913fe4bfde4a9082aa601e310a7bf Mon Sep 17 00:00:00 2001 From: Stypox Date: Thu, 27 Oct 2022 14:01:04 +0200 Subject: [PATCH 17/22] Fix flickering in channel groups list --- .../subscription/SubscriptionFragment.kt | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt index 770da3afe..151e14cab 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt @@ -413,16 +413,6 @@ class SubscriptionFragment : BaseStateFragment() { private fun handleFeedGroups(groups: List) { val listViewMode = viewModel.getListViewMode() - carouselAdapter.clear() - carouselAdapter.add(if (listViewMode) FeedGroupAddNewItem() else FeedGroupAddNewGridItem()) - carouselAdapter.add( - if (listViewMode) - FeedGroupCardItem(-1, getString(R.string.all), FeedGroupIcon.RSS) - else - FeedGroupCardGridItem(-1, getString(R.string.all), FeedGroupIcon.RSS) - ) - carouselAdapter.addAll(groups) - if (feedGroupsCarouselState != null) { feedGroupsCarousel.onRestoreInstanceState(feedGroupsCarouselState) feedGroupsCarouselState = null @@ -434,6 +424,19 @@ class SubscriptionFragment : BaseStateFragment() { binding.itemsList.post { feedGroupsCarousel.notifyChanged(FeedGroupCarouselItem.PAYLOAD_UPDATE_LIST_VIEW_MODE) feedGroupsSortMenuItem.notifyChanged(GroupsHeader.PAYLOAD_UPDATE_ICONS) + + // update items here to prevent flickering + carouselAdapter.apply { + clear() + if (listViewMode) { + add(FeedGroupAddNewItem()) + add(FeedGroupCardItem(-1, getString(R.string.all), FeedGroupIcon.RSS)) + } else { + add(FeedGroupAddNewGridItem()) + add(FeedGroupCardGridItem(-1, getString(R.string.all), FeedGroupIcon.RSS)) + } + addAll(groups) + } } } From ea875c59af7c7b9d629b9d5d9c2ae8605c1f5752 Mon Sep 17 00:00:00 2001 From: Stypox Date: Thu, 27 Oct 2022 14:10:04 +0200 Subject: [PATCH 18/22] Deduplicate isGridLayout calls --- .../fragments/list/BaseListFragment.java | 13 ++------- .../subscription/SubscriptionViewModel.kt | 28 +++---------------- .../org/schabi/newpipe/util/ThemeHelper.java | 2 +- 3 files changed, 7 insertions(+), 36 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java index 9e7cb757c..633ba5d78 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java @@ -5,7 +5,6 @@ import static org.schabi.newpipe.ktx.ViewUtils.animateHideRecyclerViewAllowingSc import android.content.Context; import android.content.SharedPreferences; -import android.content.res.Configuration; import android.content.res.Resources; import android.os.Bundle; import android.util.Log; @@ -31,6 +30,7 @@ import org.schabi.newpipe.info_list.dialog.InfoItemDialog; import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.OnClickGesture; import org.schabi.newpipe.util.StateSaver; +import org.schabi.newpipe.util.ThemeHelper; import org.schabi.newpipe.views.SuperScrollLayoutManager; import java.util.List; @@ -476,15 +476,6 @@ public abstract class BaseListFragment extends BaseStateFragment } protected boolean isGridLayout() { - final String listMode = PreferenceManager.getDefaultSharedPreferences(activity) - .getString(getString(R.string.list_view_mode_key), - getString(R.string.list_view_mode_value)); - if ("auto".equals(listMode)) { - final Configuration configuration = getResources().getConfiguration(); - return configuration.orientation == Configuration.ORIENTATION_LANDSCAPE - && configuration.isLayoutSizeAtLeast(Configuration.SCREENLAYOUT_SIZE_LARGE); - } else { - return "grid".equals(listMode); - } + return ThemeHelper.shouldUseGridLayout(activity); } } diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionViewModel.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionViewModel.kt index 814e697ce..cb14b33a6 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionViewModel.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionViewModel.kt @@ -1,21 +1,19 @@ package org.schabi.newpipe.local.subscription import android.app.Application -import android.content.res.Configuration import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData -import androidx.preference.PreferenceManager import com.xwray.groupie.Group import io.reactivex.rxjava3.core.Flowable import io.reactivex.rxjava3.processors.BehaviorProcessor import io.reactivex.rxjava3.schedulers.Schedulers -import org.schabi.newpipe.R import org.schabi.newpipe.local.feed.FeedDatabaseManager import org.schabi.newpipe.local.subscription.item.ChannelItem import org.schabi.newpipe.local.subscription.item.FeedGroupCardGridItem import org.schabi.newpipe.local.subscription.item.FeedGroupCardItem import org.schabi.newpipe.util.DEFAULT_THROTTLE_TIMEOUT +import org.schabi.newpipe.util.ThemeHelper import java.util.concurrent.TimeUnit class SubscriptionViewModel(application: Application) : AndroidViewModel(application) { @@ -23,7 +21,9 @@ class SubscriptionViewModel(application: Application) : AndroidViewModel(applica private var subscriptionManager = SubscriptionManager(application) // true -> list view, false -> grid view - private val listViewMode = BehaviorProcessor.createDefault(!isGridLayout(application)) + private val listViewMode = BehaviorProcessor.createDefault( + !ThemeHelper.shouldUseGridLayout(application) + ) private val listViewModeFlowable = listViewMode.distinctUntilChanged() private val mutableStateLiveData = MutableLiveData() @@ -74,24 +74,4 @@ class SubscriptionViewModel(application: Application) : AndroidViewModel(applica data class LoadedState(val subscriptions: List) : SubscriptionState() data class ErrorState(val error: Throwable? = null) : SubscriptionState() } - - companion object { - private fun isGridLayout(application: Application): Boolean { - val listMode = PreferenceManager.getDefaultSharedPreferences(application) - .getString( - application.getString(R.string.list_view_mode_key), - application.getString(R.string.list_view_mode_value) - ) - - return if ("auto" == listMode) { - val configuration: Configuration = application.resources.configuration - ( - configuration.orientation == Configuration.ORIENTATION_LANDSCAPE && - configuration.isLayoutSizeAtLeast(Configuration.SCREENLAYOUT_SIZE_LARGE) - ) - } else { - "grid" == listMode - } - } - } } diff --git a/app/src/main/java/org/schabi/newpipe/util/ThemeHelper.java b/app/src/main/java/org/schabi/newpipe/util/ThemeHelper.java index 389af80ee..ea22e9368 100644 --- a/app/src/main/java/org/schabi/newpipe/util/ThemeHelper.java +++ b/app/src/main/java/org/schabi/newpipe/util/ThemeHelper.java @@ -349,7 +349,7 @@ public final class ThemeHelper { return false; } else if (listMode.equals(context.getString(R.string.list_view_mode_grid_key))) { return true; - } else { + } else /* listMode.equals("auto") */ { final Configuration configuration = context.getResources().getConfiguration(); return configuration.orientation == Configuration.ORIENTATION_LANDSCAPE && configuration.isLayoutSizeAtLeast(Configuration.SCREENLAYOUT_SIZE_LARGE); From 2ed6819e2c4ade75b032bca1769b4249f5ea0941 Mon Sep 17 00:00:00 2001 From: Stypox Date: Thu, 27 Oct 2022 17:35:55 +0200 Subject: [PATCH 19/22] Make channel groups button sizes larger --- .../res/layout/subscription_groups_header.xml | 23 ++++++++++--------- app/src/main/res/values/strings.xml | 1 + 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/app/src/main/res/layout/subscription_groups_header.xml b/app/src/main/res/layout/subscription_groups_header.xml index b290d9dda..e59e63c73 100644 --- a/app/src/main/res/layout/subscription_groups_header.xml +++ b/app/src/main/res/layout/subscription_groups_header.xml @@ -2,11 +2,7 @@ + android:layout_height="wrap_content"> \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e685ca081..2bf3e0d60 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -751,4 +751,5 @@ Unknown quality Show future items Hide future items + Sort \ No newline at end of file From a41aa0146102a898093ae9a3c84a54fa505930eb Mon Sep 17 00:00:00 2001 From: Stypox Date: Thu, 27 Oct 2022 17:52:17 +0200 Subject: [PATCH 20/22] Solve two SonarCloud smells --- .../local/subscription/item/FeedGroupAddNewGridItem.kt | 4 +++- .../newpipe/local/subscription/item/FeedGroupAddNewItem.kt | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupAddNewGridItem.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupAddNewGridItem.kt index 55d1c6097..a2870b849 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupAddNewGridItem.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupAddNewGridItem.kt @@ -7,6 +7,8 @@ import org.schabi.newpipe.databinding.FeedGroupAddNewGridItemBinding class FeedGroupAddNewGridItem : BindableItem() { override fun getLayout(): Int = R.layout.feed_group_add_new_grid_item - override fun bind(viewBinding: FeedGroupAddNewGridItemBinding, position: Int) {} override fun initializeViewBinding(view: View) = FeedGroupAddNewGridItemBinding.bind(view) + override fun bind(viewBinding: FeedGroupAddNewGridItemBinding, position: Int) { + // this is a static item, nothing to do here + } } diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupAddNewItem.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupAddNewItem.kt index 735df80df..e06e578f8 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupAddNewItem.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/item/FeedGroupAddNewItem.kt @@ -7,6 +7,8 @@ import org.schabi.newpipe.databinding.FeedGroupAddNewItemBinding class FeedGroupAddNewItem : BindableItem() { override fun getLayout(): Int = R.layout.feed_group_add_new_item - override fun bind(viewBinding: FeedGroupAddNewItemBinding, position: Int) {} override fun initializeViewBinding(view: View) = FeedGroupAddNewItemBinding.bind(view) + override fun bind(viewBinding: FeedGroupAddNewItemBinding, position: Int) { + // this is a static item, nothing to do here + } } From 4b32890b5f0c3284c2efa56cf5b7ca3ca59460c3 Mon Sep 17 00:00:00 2001 From: Stypox Date: Thu, 27 Oct 2022 18:45:06 +0200 Subject: [PATCH 21/22] Fix random crash in SubscriptionFragment --- .../newpipe/local/subscription/SubscriptionFragment.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt index 151e14cab..4ef289155 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt @@ -422,6 +422,12 @@ class SubscriptionFragment : BaseStateFragment() { feedGroupsSortMenuItem.showSortButton = groups.size > 1 feedGroupsSortMenuItem.listViewMode = listViewMode binding.itemsList.post { + if (context == null) { + // since this part was posted to the next UI cycle, the fragment might have been + // removed in the meantime + return@post + } + feedGroupsCarousel.notifyChanged(FeedGroupCarouselItem.PAYLOAD_UPDATE_LIST_VIEW_MODE) feedGroupsSortMenuItem.notifyChanged(GroupsHeader.PAYLOAD_UPDATE_ICONS) From a44b7c9c9e9293d180baedde056a43c7c610d76c Mon Sep 17 00:00:00 2001 From: Samuel Wu Date: Fri, 28 Oct 2022 04:54:33 +1100 Subject: [PATCH 22/22] Disabled animations for subscription fragment --- .../schabi/newpipe/local/subscription/SubscriptionFragment.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt index 151e14cab..731d08fea 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt @@ -250,6 +250,7 @@ class SubscriptionFragment : BaseStateFragment() { spanSizeLookup = groupAdapter.spanSizeLookup } binding.itemsList.adapter = groupAdapter + binding.itemsList.itemAnimator = null viewModel = ViewModelProvider(this)[SubscriptionViewModel::class.java] viewModel.stateLiveData.observe(viewLifecycleOwner) { it?.let(this::handleResult) }