2019-04-28 22:43:54 +02:00
|
|
|
package org.schabi.newpipe.local.subscription
|
|
|
|
|
|
|
|
import android.app.Activity
|
2020-05-01 20:13:01 +02:00
|
|
|
import android.content.Context
|
|
|
|
import android.content.DialogInterface
|
|
|
|
import android.content.Intent
|
2019-04-28 22:43:54 +02:00
|
|
|
import android.os.Bundle
|
|
|
|
import android.os.Parcelable
|
2020-05-01 20:13:01 +02:00
|
|
|
import android.view.LayoutInflater
|
|
|
|
import android.view.Menu
|
|
|
|
import android.view.MenuInflater
|
2021-11-28 16:13:14 +01:00
|
|
|
import android.view.MenuItem
|
|
|
|
import android.view.SubMenu
|
2020-05-01 20:13:01 +02:00
|
|
|
import android.view.View
|
|
|
|
import android.view.ViewGroup
|
2019-04-28 22:43:54 +02:00
|
|
|
import android.widget.Toast
|
2021-06-16 04:09:19 +02:00
|
|
|
import androidx.activity.result.ActivityResult
|
|
|
|
import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult
|
2021-11-28 16:13:14 +01:00
|
|
|
import androidx.annotation.StringRes
|
2021-04-01 21:46:29 +02:00
|
|
|
import androidx.appcompat.app.AlertDialog
|
2020-08-27 22:56:12 +02:00
|
|
|
import androidx.lifecycle.ViewModelProvider
|
2020-03-06 01:26:00 +01:00
|
|
|
import androidx.recyclerview.widget.GridLayoutManager
|
2022-10-24 14:01:02 +02:00
|
|
|
import androidx.recyclerview.widget.RecyclerView
|
2019-04-28 22:43:54 +02:00
|
|
|
import com.xwray.groupie.Group
|
|
|
|
import com.xwray.groupie.GroupAdapter
|
|
|
|
import com.xwray.groupie.Item
|
|
|
|
import com.xwray.groupie.Section
|
2020-11-28 09:02:39 +01:00
|
|
|
import com.xwray.groupie.viewbinding.GroupieViewHolder
|
2019-04-28 22:43:54 +02:00
|
|
|
import icepick.State
|
2020-10-31 21:55:45 +01:00
|
|
|
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
2019-04-28 22:43:54 +02:00
|
|
|
import org.schabi.newpipe.R
|
2020-01-28 06:59:49 +01:00
|
|
|
import org.schabi.newpipe.database.feed.model.FeedGroupEntity
|
2020-11-03 09:31:36 +01:00
|
|
|
import org.schabi.newpipe.databinding.DialogTitleBinding
|
2020-11-28 09:02:39 +01:00
|
|
|
import org.schabi.newpipe.databinding.FeedItemCarouselBinding
|
2020-11-03 09:31:36 +01:00
|
|
|
import org.schabi.newpipe.databinding.FragmentSubscriptionBinding
|
2020-12-11 14:55:47 +01:00
|
|
|
import org.schabi.newpipe.error.ErrorInfo
|
2020-12-09 12:42:01 +01:00
|
|
|
import org.schabi.newpipe.error.UserAction
|
2022-05-09 20:58:10 +02:00
|
|
|
import org.schabi.newpipe.extractor.ServiceList
|
2019-04-28 22:43:54 +02:00
|
|
|
import org.schabi.newpipe.extractor.channel.ChannelInfoItem
|
|
|
|
import org.schabi.newpipe.fragments.BaseStateFragment
|
2021-01-16 04:32:01 +01:00
|
|
|
import org.schabi.newpipe.ktx.animate
|
2020-02-26 03:01:23 +01:00
|
|
|
import org.schabi.newpipe.local.subscription.SubscriptionViewModel.SubscriptionState
|
2019-04-28 22:43:54 +02:00
|
|
|
import org.schabi.newpipe.local.subscription.dialog.FeedGroupDialog
|
2020-02-26 03:01:23 +01:00
|
|
|
import org.schabi.newpipe.local.subscription.dialog.FeedGroupReorderDialog
|
2020-05-01 20:13:01 +02:00
|
|
|
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
|
2022-10-24 14:01:02 +02:00
|
|
|
import org.schabi.newpipe.local.subscription.item.FeedGroupCardVerticalItem
|
2020-05-01 20:13:01 +02:00
|
|
|
import org.schabi.newpipe.local.subscription.item.FeedGroupCarouselItem
|
|
|
|
import org.schabi.newpipe.local.subscription.item.HeaderWithMenuItem
|
2020-04-05 21:57:28 +02:00
|
|
|
import org.schabi.newpipe.local.subscription.item.HeaderWithMenuItem.Companion.PAYLOAD_UPDATE_VISIBILITY_MENU_ITEM
|
2019-04-28 22:43:54 +02:00
|
|
|
import org.schabi.newpipe.local.subscription.services.SubscriptionsExportService
|
|
|
|
import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService
|
2020-05-01 20:13:01 +02:00
|
|
|
import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.KEY_MODE
|
|
|
|
import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.KEY_VALUE
|
|
|
|
import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.PREVIOUS_EXPORT_MODE
|
2021-11-28 14:07:45 +01:00
|
|
|
import org.schabi.newpipe.streams.io.NoFileManagerSafeGuard
|
2020-06-14 19:37:45 +02:00
|
|
|
import org.schabi.newpipe.streams.io.StoredFileHelper
|
2020-05-01 20:13:01 +02:00
|
|
|
import org.schabi.newpipe.util.NavigationHelper
|
|
|
|
import org.schabi.newpipe.util.OnClickGesture
|
2022-03-20 17:22:48 +01:00
|
|
|
import org.schabi.newpipe.util.ServiceHelper
|
2021-07-31 10:51:59 +02:00
|
|
|
import org.schabi.newpipe.util.ThemeHelper.getGridSpanCountChannels
|
2021-07-19 20:47:50 +02:00
|
|
|
import org.schabi.newpipe.util.ThemeHelper.shouldUseGridLayout
|
2021-06-23 14:29:57 +02:00
|
|
|
import org.schabi.newpipe.util.external_communication.ShareUtils
|
2020-10-31 21:55:45 +01:00
|
|
|
import java.text.SimpleDateFormat
|
|
|
|
import java.util.Date
|
|
|
|
import java.util.Locale
|
2019-04-28 22:43:54 +02:00
|
|
|
|
|
|
|
class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
|
2020-11-03 09:31:36 +01:00
|
|
|
private var _binding: FragmentSubscriptionBinding? = null
|
|
|
|
private val binding get() = _binding!!
|
|
|
|
|
2019-04-28 22:43:54 +02:00
|
|
|
private lateinit var viewModel: SubscriptionViewModel
|
|
|
|
private lateinit var subscriptionManager: SubscriptionManager
|
|
|
|
private val disposables: CompositeDisposable = CompositeDisposable()
|
|
|
|
|
2020-11-28 09:02:39 +01:00
|
|
|
private val groupAdapter = GroupAdapter<GroupieViewHolder<FeedItemCarouselBinding>>()
|
2019-04-28 22:43:54 +02:00
|
|
|
private val feedGroupsSection = Section()
|
|
|
|
private var feedGroupsCarousel: FeedGroupCarouselItem? = null
|
2020-02-26 03:01:23 +01:00
|
|
|
private lateinit var feedGroupsSortMenuItem: HeaderWithMenuItem
|
2019-04-28 22:43:54 +02:00
|
|
|
private val subscriptionsSection = Section()
|
2022-10-24 17:20:14 +02:00
|
|
|
private var listView: Boolean = false
|
2019-04-28 22:43:54 +02:00
|
|
|
|
2021-06-16 04:09:19 +02:00
|
|
|
private val requestExportLauncher =
|
|
|
|
registerForActivityResult(StartActivityForResult(), this::requestExportResult)
|
|
|
|
private val requestImportLauncher =
|
|
|
|
registerForActivityResult(StartActivityForResult(), this::requestImportResult)
|
|
|
|
|
2020-03-31 19:20:15 +02:00
|
|
|
@State
|
|
|
|
@JvmField
|
|
|
|
var itemsListState: Parcelable? = null
|
2022-05-07 15:08:23 +02:00
|
|
|
|
2020-03-31 19:20:15 +02:00
|
|
|
@State
|
|
|
|
@JvmField
|
|
|
|
var feedGroupsListState: Parcelable? = null
|
2019-04-28 22:43:54 +02:00
|
|
|
|
2022-10-24 14:01:02 +02:00
|
|
|
@State
|
|
|
|
@JvmField
|
|
|
|
var feedGroupsListVerticalState: Parcelable? = null
|
|
|
|
|
2019-04-28 22:43:54 +02:00
|
|
|
init {
|
|
|
|
setHasOptionsMenu(true)
|
|
|
|
}
|
|
|
|
|
2020-05-01 20:13:21 +02:00
|
|
|
// /////////////////////////////////////////////////////////////////////////
|
2019-04-28 22:43:54 +02:00
|
|
|
// Fragment LifeCycle
|
2020-05-01 20:13:21 +02:00
|
|
|
// /////////////////////////////////////////////////////////////////////////
|
2019-04-28 22:43:54 +02:00
|
|
|
|
|
|
|
override fun onCreate(savedInstanceState: Bundle?) {
|
|
|
|
super.onCreate(savedInstanceState)
|
|
|
|
setupInitialLayout()
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun onAttach(context: Context) {
|
|
|
|
super.onAttach(context)
|
|
|
|
subscriptionManager = SubscriptionManager(requireContext())
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
|
|
|
return inflater.inflate(R.layout.fragment_subscription, container, false)
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun onPause() {
|
|
|
|
super.onPause()
|
2020-11-03 09:31:36 +01:00
|
|
|
itemsListState = binding.itemsList.layoutManager?.onSaveInstanceState()
|
2019-04-28 22:43:54 +02:00
|
|
|
feedGroupsListState = feedGroupsCarousel?.onSaveInstanceState()
|
2022-10-24 17:20:14 +02:00
|
|
|
feedGroupsListVerticalState = feedGroupsCarousel?.onSaveInstanceState()
|
2019-04-28 22:43:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
override fun onDestroy() {
|
|
|
|
super.onDestroy()
|
|
|
|
disposables.dispose()
|
|
|
|
}
|
|
|
|
|
2020-05-01 20:13:21 +02:00
|
|
|
// ////////////////////////////////////////////////////////////////////////
|
2019-04-28 22:43:54 +02:00
|
|
|
// Menu
|
2020-05-01 20:13:21 +02:00
|
|
|
// ////////////////////////////////////////////////////////////////////////
|
2019-04-28 22:43:54 +02:00
|
|
|
|
|
|
|
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
|
|
|
super.onCreateOptionsMenu(menu, inflater)
|
|
|
|
|
2021-07-16 21:21:10 +02:00
|
|
|
activity.supportActionBar?.setDisplayShowTitleEnabled(true)
|
|
|
|
activity.supportActionBar?.setTitle(R.string.tab_subscriptions)
|
2021-11-28 16:13:14 +01:00
|
|
|
|
|
|
|
buildImportExportMenu(menu)
|
2019-04-28 22:43:54 +02:00
|
|
|
}
|
|
|
|
|
2021-11-28 16:13:14 +01:00
|
|
|
private fun buildImportExportMenu(menu: Menu) {
|
|
|
|
// -- Import --
|
|
|
|
val importSubMenu = menu.addSubMenu(R.string.import_from)
|
2019-04-28 22:43:54 +02:00
|
|
|
|
2022-05-07 15:08:23 +02:00
|
|
|
addMenuItemToSubmenu(importSubMenu, R.string.previous_export) { onImportPreviousSelected() }
|
2022-03-20 17:32:41 +01:00
|
|
|
.setIcon(R.drawable.ic_backup)
|
2019-04-28 22:43:54 +02:00
|
|
|
|
2022-05-09 20:58:10 +02:00
|
|
|
for (service in ServiceList.all()) {
|
|
|
|
val subscriptionExtractor = service.subscriptionExtractor ?: continue
|
|
|
|
|
|
|
|
val supportedSources = subscriptionExtractor.supportedSources
|
|
|
|
if (supportedSources.isEmpty()) continue
|
|
|
|
|
|
|
|
addMenuItemToSubmenu(importSubMenu, service.serviceInfo.name) {
|
|
|
|
onImportFromServiceSelected(service.serviceId)
|
2019-04-28 22:43:54 +02:00
|
|
|
}
|
2022-05-09 20:58:10 +02:00
|
|
|
.setIcon(ServiceHelper.getIcon(service.serviceId))
|
2019-04-28 22:43:54 +02:00
|
|
|
}
|
|
|
|
|
2021-11-28 16:13:14 +01:00
|
|
|
// -- Export --
|
|
|
|
val exportSubMenu = menu.addSubMenu(R.string.export_to)
|
|
|
|
|
2022-05-07 15:08:23 +02:00
|
|
|
addMenuItemToSubmenu(exportSubMenu, R.string.file) { onExportSelected() }
|
2022-03-20 17:32:41 +01:00
|
|
|
.setIcon(R.drawable.ic_save)
|
2021-11-28 16:13:14 +01:00
|
|
|
}
|
|
|
|
|
2022-05-07 15:08:23 +02:00
|
|
|
private fun addMenuItemToSubmenu(
|
2021-11-28 16:13:14 +01:00
|
|
|
subMenu: SubMenu,
|
|
|
|
@StringRes title: Int,
|
|
|
|
onClick: Runnable
|
|
|
|
): MenuItem {
|
2022-05-07 15:08:23 +02:00
|
|
|
return setClickListenerToMenuItem(subMenu.add(title), onClick)
|
2021-11-28 16:13:14 +01:00
|
|
|
}
|
|
|
|
|
2022-05-07 15:08:23 +02:00
|
|
|
private fun addMenuItemToSubmenu(
|
2021-11-28 16:13:14 +01:00
|
|
|
subMenu: SubMenu,
|
|
|
|
title: String,
|
|
|
|
onClick: Runnable
|
|
|
|
): MenuItem {
|
2022-05-07 15:08:23 +02:00
|
|
|
return setClickListenerToMenuItem(subMenu.add(title), onClick)
|
2021-11-28 16:13:14 +01:00
|
|
|
}
|
|
|
|
|
2022-05-07 15:08:23 +02:00
|
|
|
private fun setClickListenerToMenuItem(
|
|
|
|
menuItem: MenuItem,
|
2021-11-28 16:13:14 +01:00
|
|
|
onClick: Runnable
|
|
|
|
): MenuItem {
|
2022-05-07 15:08:23 +02:00
|
|
|
menuItem.setOnMenuItemClickListener { _ ->
|
2021-11-28 16:13:14 +01:00
|
|
|
onClick.run()
|
|
|
|
true
|
|
|
|
}
|
2022-05-07 15:08:23 +02:00
|
|
|
return menuItem
|
2019-04-28 22:43:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private fun onImportFromServiceSelected(serviceId: Int) {
|
|
|
|
val fragmentManager = fm
|
|
|
|
NavigationHelper.openSubscriptionsImportFragment(fragmentManager, serviceId)
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun onImportPreviousSelected() {
|
2021-11-28 14:07:45 +01:00
|
|
|
NoFileManagerSafeGuard.launchSafe(
|
|
|
|
requestImportLauncher,
|
|
|
|
StoredFileHelper.getPicker(activity, JSON_MIME_TYPE),
|
|
|
|
TAG,
|
|
|
|
requireContext()
|
|
|
|
)
|
2019-04-28 22:43:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private fun onExportSelected() {
|
|
|
|
val date = SimpleDateFormat("yyyyMMddHHmm", Locale.ENGLISH).format(Date())
|
|
|
|
val exportName = "newpipe_subscriptions_$date.json"
|
|
|
|
|
2021-11-28 14:07:45 +01:00
|
|
|
NoFileManagerSafeGuard.launchSafe(
|
|
|
|
requestExportLauncher,
|
|
|
|
StoredFileHelper.getNewPicker(activity, exportName, JSON_MIME_TYPE, null),
|
|
|
|
TAG,
|
|
|
|
requireContext()
|
|
|
|
)
|
2019-04-28 22:43:54 +02:00
|
|
|
}
|
|
|
|
|
2020-02-26 03:01:23 +01:00
|
|
|
private fun openReorderDialog() {
|
2021-06-16 04:08:25 +02:00
|
|
|
FeedGroupReorderDialog().show(parentFragmentManager, null)
|
2020-02-26 03:01:23 +01:00
|
|
|
}
|
|
|
|
|
2021-08-01 13:52:32 +02:00
|
|
|
private fun requestExportResult(result: ActivityResult) {
|
2021-06-16 04:09:19 +02:00
|
|
|
if (result.data != null && result.resultCode == Activity.RESULT_OK) {
|
|
|
|
activity.startService(
|
|
|
|
Intent(activity, SubscriptionsExportService::class.java)
|
|
|
|
.putExtra(SubscriptionsExportService.KEY_FILE_PATH, result.data?.data)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-01 13:52:32 +02:00
|
|
|
private fun requestImportResult(result: ActivityResult) {
|
2021-06-16 04:09:19 +02:00
|
|
|
if (result.data != null && result.resultCode == Activity.RESULT_OK) {
|
|
|
|
ImportConfirmationDialog.show(
|
|
|
|
this,
|
|
|
|
Intent(activity, SubscriptionsImportService::class.java)
|
|
|
|
.putExtra(KEY_MODE, PREVIOUS_EXPORT_MODE)
|
|
|
|
.putExtra(KEY_VALUE, result.data?.data)
|
|
|
|
)
|
2019-04-28 22:43:54 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-01 20:13:21 +02:00
|
|
|
// ////////////////////////////////////////////////////////////////////////
|
2019-04-28 22:43:54 +02:00
|
|
|
// Fragment Views
|
2020-05-01 20:13:21 +02:00
|
|
|
// ////////////////////////////////////////////////////////////////////////
|
2019-04-28 22:43:54 +02:00
|
|
|
|
|
|
|
private fun setupInitialLayout() {
|
2022-10-24 17:20:14 +02:00
|
|
|
listView = false
|
2019-04-28 22:43:54 +02:00
|
|
|
Section().apply {
|
2020-11-28 09:02:39 +01:00
|
|
|
val carouselAdapter = GroupAdapter<GroupieViewHolder<FeedItemCarouselBinding>>()
|
2019-04-28 22:43:54 +02:00
|
|
|
|
2019-10-11 06:09:28 +02:00
|
|
|
carouselAdapter.add(FeedGroupCardItem(-1, getString(R.string.all), FeedGroupIcon.RSS))
|
2019-04-28 22:43:54 +02:00
|
|
|
carouselAdapter.add(feedGroupsSection)
|
|
|
|
carouselAdapter.add(FeedGroupAddItem())
|
|
|
|
|
|
|
|
carouselAdapter.setOnItemClickListener { item, _ ->
|
|
|
|
listenerFeedGroups.selected(item)
|
|
|
|
}
|
|
|
|
carouselAdapter.setOnItemLongClickListener { item, _ ->
|
|
|
|
if (item is FeedGroupCardItem) {
|
2020-01-28 06:59:49 +01:00
|
|
|
if (item.groupId == FeedGroupEntity.GROUP_ALL_ID) {
|
2019-04-28 22:43:54 +02:00
|
|
|
return@setOnItemLongClickListener false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
listenerFeedGroups.held(item)
|
|
|
|
return@setOnItemLongClickListener true
|
|
|
|
}
|
|
|
|
|
2022-10-24 14:01:02 +02:00
|
|
|
feedGroupsCarousel = FeedGroupCarouselItem(requireContext(), carouselAdapter, RecyclerView.HORIZONTAL)
|
2022-10-24 15:32:21 +02:00
|
|
|
|
2020-02-26 03:01:23 +01:00
|
|
|
feedGroupsSortMenuItem = HeaderWithMenuItem(
|
2020-10-31 21:55:45 +01:00
|
|
|
getString(R.string.feed_groups_header_title),
|
2022-10-23 14:43:52 +02:00
|
|
|
R.drawable.ic_list,
|
2021-03-27 15:45:49 +01:00
|
|
|
R.drawable.ic_sort,
|
2022-10-24 14:01:02 +02:00
|
|
|
listViewOnClickListener = ::changeLayout,
|
2020-10-31 21:55:45 +01:00
|
|
|
menuItemOnClickListener = ::openReorderDialog
|
2020-02-26 03:01:23 +01:00
|
|
|
)
|
2022-10-24 15:32:21 +02:00
|
|
|
|
2020-02-26 03:01:23 +01:00
|
|
|
add(Section(feedGroupsSortMenuItem, listOf(feedGroupsCarousel)))
|
2022-10-24 14:01:02 +02:00
|
|
|
groupAdapter.clear()
|
2019-04-28 22:43:54 +02:00
|
|
|
groupAdapter.add(this)
|
|
|
|
}
|
|
|
|
|
|
|
|
subscriptionsSection.setPlaceholder(EmptyPlaceholderItem())
|
|
|
|
subscriptionsSection.setHideWhenEmpty(true)
|
|
|
|
|
2021-11-28 16:13:14 +01:00
|
|
|
groupAdapter.add(
|
|
|
|
Section(
|
|
|
|
HeaderWithMenuItem(
|
|
|
|
getString(R.string.tab_subscriptions)
|
|
|
|
),
|
|
|
|
listOf(subscriptionsSection)
|
|
|
|
)
|
2020-10-31 21:55:45 +01:00
|
|
|
)
|
2019-04-28 22:43:54 +02:00
|
|
|
}
|
|
|
|
|
2022-10-24 14:01:02 +02:00
|
|
|
private fun changeLayout() {
|
2022-10-24 17:20:14 +02:00
|
|
|
listView = true
|
2022-10-24 14:01:02 +02:00
|
|
|
Section().apply {
|
2022-10-24 15:32:21 +02:00
|
|
|
val carouselAdapter2 = GroupAdapter<GroupieViewHolder<FeedItemCarouselBinding>>()
|
2022-10-24 14:01:02 +02:00
|
|
|
|
2022-10-24 15:32:21 +02:00
|
|
|
carouselAdapter2.add(FeedGroupCardVerticalItem(-1, getString(R.string.all), FeedGroupIcon.RSS))
|
|
|
|
carouselAdapter2.add(feedGroupsSection)
|
|
|
|
carouselAdapter2.add(FeedGroupAddItem())
|
|
|
|
|
|
|
|
carouselAdapter2.setOnItemClickListener { item, _ ->
|
2022-10-24 14:01:02 +02:00
|
|
|
listenerFeedVerticalGroups.selected(item)
|
|
|
|
}
|
2022-10-24 15:32:21 +02:00
|
|
|
carouselAdapter2.setOnItemLongClickListener { item, _ ->
|
2022-10-24 14:01:02 +02:00
|
|
|
if (item is FeedGroupCardVerticalItem) {
|
|
|
|
if (item.groupId == FeedGroupEntity.GROUP_ALL_ID) {
|
|
|
|
return@setOnItemLongClickListener false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
listenerFeedVerticalGroups.held(item)
|
|
|
|
return@setOnItemLongClickListener true
|
|
|
|
}
|
2022-10-24 15:32:21 +02:00
|
|
|
feedGroupsCarousel = FeedGroupCarouselItem(requireContext(), carouselAdapter2, RecyclerView.VERTICAL)
|
2022-10-24 14:01:02 +02:00
|
|
|
|
|
|
|
feedGroupsSortMenuItem = HeaderWithMenuItem(
|
|
|
|
getString(R.string.feed_groups_header_title),
|
|
|
|
R.drawable.ic_apps,
|
|
|
|
R.drawable.ic_sort,
|
|
|
|
listViewOnClickListener = ::setupInitialLayout,
|
|
|
|
menuItemOnClickListener = ::openReorderDialog
|
|
|
|
)
|
2022-10-24 15:32:21 +02:00
|
|
|
add(Section(feedGroupsSortMenuItem, listOf(feedGroupsCarousel)))
|
2022-10-24 14:01:02 +02:00
|
|
|
groupAdapter.clear()
|
|
|
|
groupAdapter.add(this)
|
|
|
|
}
|
|
|
|
subscriptionsSection.setPlaceholder(EmptyPlaceholderItem())
|
|
|
|
subscriptionsSection.setHideWhenEmpty(true)
|
|
|
|
|
|
|
|
groupAdapter.add(
|
|
|
|
Section(
|
|
|
|
HeaderWithMenuItem(
|
|
|
|
getString(R.string.tab_subscriptions)
|
|
|
|
),
|
|
|
|
listOf(subscriptionsSection)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2019-04-28 22:43:54 +02:00
|
|
|
override fun initViews(rootView: View, savedInstanceState: Bundle?) {
|
|
|
|
super.initViews(rootView, savedInstanceState)
|
2020-11-03 09:31:36 +01:00
|
|
|
_binding = FragmentSubscriptionBinding.bind(rootView)
|
2019-04-28 22:43:54 +02:00
|
|
|
|
2021-07-31 10:51:59 +02:00
|
|
|
groupAdapter.spanCount = if (shouldUseGridLayout(context)) getGridSpanCountChannels(context) else 1
|
2020-11-03 09:31:36 +01:00
|
|
|
binding.itemsList.layoutManager = GridLayoutManager(requireContext(), groupAdapter.spanCount).apply {
|
2020-03-06 01:26:00 +01:00
|
|
|
spanSizeLookup = groupAdapter.spanSizeLookup
|
|
|
|
}
|
2020-11-03 09:31:36 +01:00
|
|
|
binding.itemsList.adapter = groupAdapter
|
2019-04-28 22:43:54 +02:00
|
|
|
|
2022-10-24 17:01:57 +02:00
|
|
|
// TODO: change viewModel or create another one
|
2020-08-27 22:56:12 +02:00
|
|
|
viewModel = ViewModelProvider(this).get(SubscriptionViewModel::class.java)
|
2020-12-11 14:55:47 +01:00
|
|
|
viewModel.stateLiveData.observe(viewLifecycleOwner) { it?.let(this::handleResult) }
|
|
|
|
viewModel.feedGroupsLiveData.observe(viewLifecycleOwner) { it?.let(this::handleFeedGroups) }
|
2022-10-24 17:01:57 +02:00
|
|
|
viewModel.feedGroupsVerticalLiveData.observe(viewLifecycleOwner) { it?.let(this::handleFeedGroupsVertical) }
|
2019-04-28 22:43:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private fun showLongTapDialog(selectedItem: ChannelInfoItem) {
|
2021-06-06 11:56:38 +02:00
|
|
|
val commands = arrayOf(
|
2021-06-06 22:15:32 +02:00
|
|
|
getString(R.string.share),
|
|
|
|
getString(R.string.open_in_browser),
|
2021-06-06 11:56:38 +02:00
|
|
|
getString(R.string.unsubscribe)
|
|
|
|
)
|
2019-04-28 22:43:54 +02:00
|
|
|
|
|
|
|
val actions = DialogInterface.OnClickListener { _, i ->
|
|
|
|
when (i) {
|
2021-06-23 14:29:57 +02:00
|
|
|
0 -> ShareUtils.shareText(
|
|
|
|
requireContext(), selectedItem.name, selectedItem.url,
|
|
|
|
selectedItem.thumbnailUrl
|
|
|
|
)
|
2021-05-13 12:49:34 +02:00
|
|
|
1 -> ShareUtils.openUrlInBrowser(requireContext(), selectedItem.url)
|
|
|
|
2 -> deleteChannel(selectedItem)
|
2019-04-28 22:43:54 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-03 09:31:36 +01:00
|
|
|
val dialogTitleBinding = DialogTitleBinding.inflate(LayoutInflater.from(requireContext()))
|
|
|
|
dialogTitleBinding.root.isSelected = true
|
|
|
|
dialogTitleBinding.itemTitleView.text = selectedItem.name
|
|
|
|
dialogTitleBinding.itemAdditionalDetails.visibility = View.GONE
|
2019-04-28 22:43:54 +02:00
|
|
|
|
|
|
|
AlertDialog.Builder(requireContext())
|
2021-01-15 02:15:07 +01:00
|
|
|
.setCustomTitle(dialogTitleBinding.root)
|
|
|
|
.setItems(commands, actions)
|
|
|
|
.create()
|
|
|
|
.show()
|
2019-04-28 22:43:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private fun deleteChannel(selectedItem: ChannelInfoItem) {
|
2020-10-31 21:55:45 +01:00
|
|
|
disposables.add(
|
|
|
|
subscriptionManager.deleteSubscription(selectedItem.serviceId, selectedItem.url).subscribe {
|
|
|
|
Toast.makeText(requireContext(), getString(R.string.channel_unsubscribed), Toast.LENGTH_SHORT).show()
|
|
|
|
}
|
|
|
|
)
|
2019-04-28 22:43:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
override fun doInitialLoadLogic() = Unit
|
|
|
|
override fun startLoading(forceLoad: Boolean) = Unit
|
|
|
|
|
2022-07-31 10:08:24 +02:00
|
|
|
private val listenerFeedGroups = object : OnClickGesture<Item<*>> {
|
2019-04-28 22:43:54 +02:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-24 14:01:02 +02:00
|
|
|
private val listenerFeedVerticalGroups = object : OnClickGesture<Item<*>> {
|
|
|
|
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)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-31 10:08:24 +02:00
|
|
|
private val listenerChannelItem = object : OnClickGesture<ChannelInfoItem> {
|
2020-10-31 21:55:45 +01:00
|
|
|
override fun selected(selectedItem: ChannelInfoItem) = NavigationHelper.openChannelFragment(
|
|
|
|
fm,
|
|
|
|
selectedItem.serviceId, selectedItem.url, selectedItem.name
|
|
|
|
)
|
2019-04-28 22:43:54 +02:00
|
|
|
|
|
|
|
override fun held(selectedItem: ChannelInfoItem) = showLongTapDialog(selectedItem)
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun handleResult(result: SubscriptionState) {
|
|
|
|
super.handleResult(result)
|
|
|
|
|
2021-07-19 20:47:50 +02:00
|
|
|
val shouldUseGridLayout = shouldUseGridLayout(context)
|
2019-04-28 22:43:54 +02:00
|
|
|
when (result) {
|
|
|
|
is SubscriptionState.LoadedState -> {
|
|
|
|
result.subscriptions.forEach {
|
|
|
|
if (it is ChannelItem) {
|
|
|
|
it.gesturesListener = listenerChannelItem
|
2020-03-06 01:26:00 +01:00
|
|
|
it.itemVersion = when {
|
|
|
|
shouldUseGridLayout -> ChannelItem.ItemVersion.GRID
|
|
|
|
else -> ChannelItem.ItemVersion.MINI
|
|
|
|
}
|
2019-04-28 22:43:54 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
subscriptionsSection.update(result.subscriptions)
|
|
|
|
subscriptionsSection.setHideWhenEmpty(false)
|
|
|
|
|
|
|
|
if (itemsListState != null) {
|
2020-11-03 09:31:36 +01:00
|
|
|
binding.itemsList.layoutManager?.onRestoreInstanceState(itemsListState)
|
2019-04-28 22:43:54 +02:00
|
|
|
itemsListState = null
|
|
|
|
}
|
|
|
|
}
|
|
|
|
is SubscriptionState.ErrorState -> {
|
2020-12-11 14:55:47 +01:00
|
|
|
result.error?.let {
|
|
|
|
showError(ErrorInfo(result.error, UserAction.SOMETHING_ELSE, "Subscriptions"))
|
|
|
|
}
|
2019-04-28 22:43:54 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun handleFeedGroups(groups: List<Group>) {
|
2022-10-24 17:20:14 +02:00
|
|
|
if (!listView) {
|
|
|
|
feedGroupsSection.update(groups)
|
2019-04-28 22:43:54 +02:00
|
|
|
|
2022-10-24 17:20:14 +02:00
|
|
|
if (feedGroupsListState != null) {
|
|
|
|
feedGroupsCarousel?.onRestoreInstanceState(feedGroupsListState)
|
|
|
|
feedGroupsListState = null
|
|
|
|
}
|
2020-02-26 03:01:23 +01:00
|
|
|
|
2022-10-24 17:20:14 +02:00
|
|
|
feedGroupsSortMenuItem.showMenuItem = groups.size > 1
|
|
|
|
binding.itemsList.post { feedGroupsSortMenuItem.notifyChanged(PAYLOAD_UPDATE_VISIBILITY_MENU_ITEM) }
|
|
|
|
}
|
2019-04-28 22:43:54 +02:00
|
|
|
}
|
|
|
|
|
2022-10-24 17:01:57 +02:00
|
|
|
private fun handleFeedGroupsVertical(groups: List<Group>) {
|
2022-10-24 17:20:14 +02:00
|
|
|
if (listView) {
|
|
|
|
feedGroupsSection.update(groups)
|
2022-10-24 17:01:57 +02:00
|
|
|
|
2022-10-24 17:20:14 +02:00
|
|
|
if (feedGroupsListVerticalState != null) {
|
|
|
|
feedGroupsCarousel?.onRestoreInstanceState(feedGroupsListVerticalState)
|
|
|
|
feedGroupsListVerticalState = null
|
|
|
|
}
|
2022-10-24 17:01:57 +02:00
|
|
|
|
2022-10-24 17:20:14 +02:00
|
|
|
feedGroupsSortMenuItem.showMenuItem = groups.size > 1
|
|
|
|
binding.itemsList.post { feedGroupsSortMenuItem.notifyChanged(PAYLOAD_UPDATE_VISIBILITY_MENU_ITEM) }
|
|
|
|
}
|
2022-10-24 17:01:57 +02:00
|
|
|
}
|
|
|
|
|
2020-05-01 20:13:21 +02:00
|
|
|
// /////////////////////////////////////////////////////////////////////////
|
2019-04-28 22:43:54 +02:00
|
|
|
// Contract
|
2020-05-01 20:13:21 +02:00
|
|
|
// /////////////////////////////////////////////////////////////////////////
|
2019-04-28 22:43:54 +02:00
|
|
|
|
|
|
|
override fun showLoading() {
|
|
|
|
super.showLoading()
|
2021-01-16 04:32:01 +01:00
|
|
|
binding.itemsList.animate(false, 100)
|
2019-04-28 22:43:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
override fun hideLoading() {
|
|
|
|
super.hideLoading()
|
2021-01-16 04:32:01 +01:00
|
|
|
binding.itemsList.animate(true, 200)
|
2019-04-28 22:43:54 +02:00
|
|
|
}
|
2021-08-01 13:52:32 +02:00
|
|
|
|
|
|
|
companion object {
|
|
|
|
const val JSON_MIME_TYPE = "application/json"
|
|
|
|
}
|
2019-04-28 22:43:54 +02:00
|
|
|
}
|