11package org.schabi.newpipe.local.subscription
22
33import android.app.Activity
4- import android.content.BroadcastReceiver
54import android.content.Context
65import android.content.DialogInterface
76import android.content.Intent
8- import android.content.IntentFilter
97import android.os.Bundle
108import android.os.Parcelable
119import android.view.LayoutInflater
1210import android.view.Menu
1311import android.view.MenuInflater
12+ import android.view.MenuItem
13+ import android.view.SubMenu
1414import android.view.View
1515import android.view.ViewGroup
1616import android.widget.Toast
1717import androidx.activity.result.ActivityResult
1818import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult
19+ import androidx.annotation.StringRes
1920import androidx.appcompat.app.AlertDialog
2021import androidx.lifecycle.ViewModelProvider
21- import androidx.localbroadcastmanager.content.LocalBroadcastManager
2222import androidx.recyclerview.widget.GridLayoutManager
2323import com.xwray.groupie.Group
2424import com.xwray.groupie.GroupAdapter
@@ -34,7 +34,9 @@ import org.schabi.newpipe.databinding.FeedItemCarouselBinding
3434import org.schabi.newpipe.databinding.FragmentSubscriptionBinding
3535import org.schabi.newpipe.error.ErrorInfo
3636import org.schabi.newpipe.error.UserAction
37+ import org.schabi.newpipe.extractor.NewPipe
3738import org.schabi.newpipe.extractor.channel.ChannelInfoItem
39+ import org.schabi.newpipe.extractor.exceptions.ExtractionException
3840import org.schabi.newpipe.fragments.BaseStateFragment
3941import org.schabi.newpipe.ktx.animate
4042import org.schabi.newpipe.local.subscription.SubscriptionViewModel.SubscriptionState
@@ -45,13 +47,10 @@ import org.schabi.newpipe.local.subscription.item.EmptyPlaceholderItem
4547import org.schabi.newpipe.local.subscription.item.FeedGroupAddItem
4648import org.schabi.newpipe.local.subscription.item.FeedGroupCardItem
4749import org.schabi.newpipe.local.subscription.item.FeedGroupCarouselItem
48- import org.schabi.newpipe.local.subscription.item.FeedImportExportItem
4950import org.schabi.newpipe.local.subscription.item.HeaderWithMenuItem
5051import org.schabi.newpipe.local.subscription.item.HeaderWithMenuItem.Companion.PAYLOAD_UPDATE_VISIBILITY_MENU_ITEM
5152import org.schabi.newpipe.local.subscription.services.SubscriptionsExportService
52- import org.schabi.newpipe.local.subscription.services.SubscriptionsExportService.EXPORT_COMPLETE_ACTION
5353import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService
54- import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.IMPORT_COMPLETE_ACTION
5554import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.KEY_MODE
5655import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.KEY_VALUE
5756import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.PREVIOUS_EXPORT_MODE
@@ -65,6 +64,7 @@ import org.schabi.newpipe.util.external_communication.ShareUtils
6564import java.text.SimpleDateFormat
6665import java.util.Date
6766import java.util.Locale
67+ import java.util.function.Supplier
6868
6969class SubscriptionFragment : BaseStateFragment <SubscriptionState >() {
7070 private var _binding : FragmentSubscriptionBinding ? = null
@@ -74,12 +74,9 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
7474 private lateinit var subscriptionManager: SubscriptionManager
7575 private val disposables: CompositeDisposable = CompositeDisposable ()
7676
77- private var subscriptionBroadcastReceiver: BroadcastReceiver ? = null
78-
7977 private val groupAdapter = GroupAdapter <GroupieViewHolder <FeedItemCarouselBinding >>()
8078 private val feedGroupsSection = Section ()
8179 private var feedGroupsCarousel: FeedGroupCarouselItem ? = null
82- private lateinit var importExportItem: FeedImportExportItem
8380 private lateinit var feedGroupsSortMenuItem: HeaderWithMenuItem
8481 private val subscriptionsSection = Section ()
8582
@@ -94,9 +91,6 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
9491 @State
9592 @JvmField
9693 var feedGroupsListState: Parcelable ? = null
97- @State
98- @JvmField
99- var importExportItemExpandedState: Boolean? = null
10094
10195 init {
10296 setHasOptionsMenu(true )
@@ -120,20 +114,10 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
120114 return inflater.inflate(R .layout.fragment_subscription, container, false )
121115 }
122116
123- override fun onResume () {
124- super .onResume()
125- setupBroadcastReceiver()
126- }
127-
128117 override fun onPause () {
129118 super .onPause()
130119 itemsListState = binding.itemsList.layoutManager?.onSaveInstanceState()
131120 feedGroupsListState = feedGroupsCarousel?.onSaveInstanceState()
132- importExportItemExpandedState = importExportItem.isExpanded
133-
134- if (subscriptionBroadcastReceiver != null && activity != null ) {
135- LocalBroadcastManager .getInstance(activity).unregisterReceiver(subscriptionBroadcastReceiver!! )
136- }
137121 }
138122
139123 override fun onDestroy () {
@@ -150,28 +134,75 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
150134
151135 activity.supportActionBar?.setDisplayShowTitleEnabled(true )
152136 activity.supportActionBar?.setTitle(R .string.tab_subscriptions)
137+
138+ buildImportExportMenu(menu)
153139 }
154140
155- private fun setupBroadcastReceiver () {
156- if (activity == null ) return
141+ private fun buildImportExportMenu (menu : Menu ) {
142+ // -- Import --
143+
144+ val importSubMenu = menu.addSubMenu(R .string.import_from)
157145
158- if (subscriptionBroadcastReceiver != null ) {
159- LocalBroadcastManager .getInstance(activity).unregisterReceiver(subscriptionBroadcastReceiver !! )
146+ addMenuItem(importSubMenu, R .string.previous_export ) {
147+ onImportPreviousSelected( )
160148 }
161149
162- val filters = IntentFilter ()
163- filters.addAction(EXPORT_COMPLETE_ACTION )
164- filters.addAction(IMPORT_COMPLETE_ACTION )
165- subscriptionBroadcastReceiver = object : BroadcastReceiver () {
166- override fun onReceive (context : Context , intent : Intent ) {
167- _binding ?.itemsList?.post {
168- importExportItem.isExpanded = false
169- importExportItem.notifyChanged(FeedImportExportItem .REFRESH_EXPANDED_STATUS )
150+ val services = requireContext().resources.getStringArray(R .array.service_list)
151+ for (serviceName in services) {
152+ try {
153+ val service = NewPipe .getService(serviceName)
154+
155+ val subscriptionExtractor = service.subscriptionExtractor ? : continue
156+
157+ val supportedSources = subscriptionExtractor.supportedSources
158+ if (supportedSources.isEmpty()) continue
159+
160+ addMenuItem(importSubMenu, serviceName) {
161+ onImportFromServiceSelected(service.serviceId)
170162 }
163+ } catch (e: ExtractionException ) {
164+ throw RuntimeException (
165+ " Services array contains an entry that it's not a valid service name ($serviceName )" ,
166+ e
167+ )
171168 }
172169 }
173170
174- LocalBroadcastManager .getInstance(activity).registerReceiver(subscriptionBroadcastReceiver!! , filters)
171+ // -- Export --
172+
173+ val exportSubMenu = menu.addSubMenu(R .string.export_to)
174+
175+ addMenuItem(exportSubMenu, R .string.file) { onExportSelected() }
176+ }
177+
178+ private fun addMenuItem (
179+ subMenu : SubMenu ,
180+ @StringRes title : Int ,
181+ onClick : Runnable
182+ ): MenuItem {
183+ return addMenuItem({ subMenu.add(title) }, onClick)
184+ }
185+
186+ private fun addMenuItem (
187+ subMenu : SubMenu ,
188+ title : String ,
189+ onClick : Runnable
190+ ): MenuItem {
191+ return addMenuItem({ subMenu.add(title) }, onClick)
192+ }
193+
194+ private fun addMenuItem (
195+ menuItemSupplier : Supplier <MenuItem >,
196+ onClick : Runnable
197+ ): MenuItem {
198+ val item = menuItemSupplier.get()
199+
200+ item.setOnMenuItemClickListener { _ ->
201+ onClick.run ()
202+ true
203+ }
204+
205+ return item
175206 }
176207
177208 private fun onImportFromServiceSelected (serviceId : Int ) {
@@ -263,13 +294,14 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
263294 subscriptionsSection.setPlaceholder(EmptyPlaceholderItem ())
264295 subscriptionsSection.setHideWhenEmpty(true )
265296
266- importExportItem = FeedImportExportItem (
267- { onImportPreviousSelected() },
268- { onImportFromServiceSelected(it) },
269- { onExportSelected() },
270- importExportItemExpandedState ? : false
297+ groupAdapter.add(
298+ Section (
299+ HeaderWithMenuItem (
300+ getString(R .string.tab_subscriptions)
301+ ),
302+ listOf (subscriptionsSection)
303+ )
271304 )
272- groupAdapter.add(Section (importExportItem, listOf (subscriptionsSection)))
273305 }
274306
275307 override fun initViews (rootView : View , savedInstanceState : Bundle ? ) {
@@ -371,13 +403,6 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
371403 subscriptionsSection.update(result.subscriptions)
372404 subscriptionsSection.setHideWhenEmpty(false )
373405
374- if (result.subscriptions.isEmpty() && importExportItemExpandedState == null ) {
375- binding.itemsList.post {
376- importExportItem.isExpanded = true
377- importExportItem.notifyChanged(FeedImportExportItem .REFRESH_EXPANDED_STATUS )
378- }
379- }
380-
381406 if (itemsListState != null ) {
382407 binding.itemsList.layoutManager?.onRestoreInstanceState(itemsListState)
383408 itemsListState = null
0 commit comments