Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Moved subscription import/export options to (overflow) menu #7458

Merged
merged 10 commits into from
May 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
package org.schabi.newpipe.local.subscription

import android.app.Activity
import android.content.BroadcastReceiver
import android.content.Context
import android.content.DialogInterface
import android.content.Intent
import android.content.IntentFilter
import android.os.Bundle
import android.os.Parcelable
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.SubMenu
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.activity.result.ActivityResult
import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult
import androidx.annotation.StringRes
import androidx.appcompat.app.AlertDialog
import androidx.lifecycle.ViewModelProvider
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import androidx.recyclerview.widget.GridLayoutManager
import com.xwray.groupie.Group
import com.xwray.groupie.GroupAdapter
Expand All @@ -34,6 +34,7 @@ import org.schabi.newpipe.databinding.FeedItemCarouselBinding
import org.schabi.newpipe.databinding.FragmentSubscriptionBinding
import org.schabi.newpipe.error.ErrorInfo
import org.schabi.newpipe.error.UserAction
import org.schabi.newpipe.extractor.ServiceList
import org.schabi.newpipe.extractor.channel.ChannelInfoItem
import org.schabi.newpipe.fragments.BaseStateFragment
import org.schabi.newpipe.ktx.animate
Expand All @@ -45,20 +46,18 @@ 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.FeedGroupCarouselItem
import org.schabi.newpipe.local.subscription.item.FeedImportExportItem
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.services.SubscriptionsExportService
import org.schabi.newpipe.local.subscription.services.SubscriptionsExportService.EXPORT_COMPLETE_ACTION
import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService
import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.IMPORT_COMPLETE_ACTION
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
import org.schabi.newpipe.streams.io.NoFileManagerSafeGuard
import org.schabi.newpipe.streams.io.StoredFileHelper
import org.schabi.newpipe.util.NavigationHelper
import org.schabi.newpipe.util.OnClickGesture
import org.schabi.newpipe.util.ServiceHelper
import org.schabi.newpipe.util.ThemeHelper.getGridSpanCountChannels
import org.schabi.newpipe.util.ThemeHelper.shouldUseGridLayout
import org.schabi.newpipe.util.external_communication.ShareUtils
Expand All @@ -74,12 +73,9 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
private lateinit var subscriptionManager: SubscriptionManager
private val disposables: CompositeDisposable = CompositeDisposable()

private var subscriptionBroadcastReceiver: BroadcastReceiver? = null

private val groupAdapter = GroupAdapter<GroupieViewHolder<FeedItemCarouselBinding>>()
private val feedGroupsSection = Section()
private var feedGroupsCarousel: FeedGroupCarouselItem? = null
private lateinit var importExportItem: FeedImportExportItem
private lateinit var feedGroupsSortMenuItem: HeaderWithMenuItem
private val subscriptionsSection = Section()

Expand All @@ -91,12 +87,10 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
@State
@JvmField
var itemsListState: Parcelable? = null

@State
@JvmField
var feedGroupsListState: Parcelable? = null
@State
@JvmField
var importExportItemExpandedState: Boolean? = null

init {
setHasOptionsMenu(true)
Expand All @@ -120,20 +114,10 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
return inflater.inflate(R.layout.fragment_subscription, container, false)
}

override fun onResume() {
super.onResume()
setupBroadcastReceiver()
}

override fun onPause() {
super.onPause()
itemsListState = binding.itemsList.layoutManager?.onSaveInstanceState()
feedGroupsListState = feedGroupsCarousel?.onSaveInstanceState()
importExportItemExpandedState = importExportItem.isExpanded

if (subscriptionBroadcastReceiver != null && activity != null) {
LocalBroadcastManager.getInstance(activity).unregisterReceiver(subscriptionBroadcastReceiver!!)
}
}

override fun onDestroy() {
Expand All @@ -150,28 +134,61 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {

activity.supportActionBar?.setDisplayShowTitleEnabled(true)
activity.supportActionBar?.setTitle(R.string.tab_subscriptions)

buildImportExportMenu(menu)
}

private fun setupBroadcastReceiver() {
if (activity == null) return
private fun buildImportExportMenu(menu: Menu) {
// -- Import --
val importSubMenu = menu.addSubMenu(R.string.import_from)

if (subscriptionBroadcastReceiver != null) {
LocalBroadcastManager.getInstance(activity).unregisterReceiver(subscriptionBroadcastReceiver!!)
}
addMenuItemToSubmenu(importSubMenu, R.string.previous_export) { onImportPreviousSelected() }
.setIcon(R.drawable.ic_backup)

val filters = IntentFilter()
filters.addAction(EXPORT_COMPLETE_ACTION)
filters.addAction(IMPORT_COMPLETE_ACTION)
subscriptionBroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
_binding?.itemsList?.post {
importExportItem.isExpanded = false
importExportItem.notifyChanged(FeedImportExportItem.REFRESH_EXPANDED_STATUS)
}
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)
}
.setIcon(ServiceHelper.getIcon(service.serviceId))
}

LocalBroadcastManager.getInstance(activity).registerReceiver(subscriptionBroadcastReceiver!!, filters)
// -- Export --
val exportSubMenu = menu.addSubMenu(R.string.export_to)

addMenuItemToSubmenu(exportSubMenu, R.string.file) { onExportSelected() }
.setIcon(R.drawable.ic_save)
}

private fun addMenuItemToSubmenu(
subMenu: SubMenu,
@StringRes title: Int,
onClick: Runnable
): MenuItem {
return setClickListenerToMenuItem(subMenu.add(title), onClick)
}

private fun addMenuItemToSubmenu(
subMenu: SubMenu,
title: String,
onClick: Runnable
): MenuItem {
return setClickListenerToMenuItem(subMenu.add(title), onClick)
}

private fun setClickListenerToMenuItem(
menuItem: MenuItem,
onClick: Runnable
): MenuItem {
menuItem.setOnMenuItemClickListener { _ ->
onClick.run()
true
}
return menuItem
}

private fun onImportFromServiceSelected(serviceId: Int) {
Expand Down Expand Up @@ -263,13 +280,14 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
subscriptionsSection.setPlaceholder(EmptyPlaceholderItem())
subscriptionsSection.setHideWhenEmpty(true)

importExportItem = FeedImportExportItem(
{ onImportPreviousSelected() },
{ onImportFromServiceSelected(it) },
{ onExportSelected() },
importExportItemExpandedState ?: false
groupAdapter.add(
Section(
HeaderWithMenuItem(
getString(R.string.tab_subscriptions)
),
listOf(subscriptionsSection)
)
)
groupAdapter.add(Section(importExportItem, listOf(subscriptionsSection)))
}

override fun initViews(rootView: View, savedInstanceState: Bundle?) {
Expand Down Expand Up @@ -371,13 +389,6 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
subscriptionsSection.update(result.subscriptions)
subscriptionsSection.setHideWhenEmpty(false)

if (result.subscriptions.isEmpty() && importExportItemExpandedState == null) {
binding.itemsList.post {
importExportItem.isExpanded = true
importExportItem.notifyChanged(FeedImportExportItem.REFRESH_EXPANDED_STATUS)
}
}

if (itemsListState != null) {
binding.itemsList.layoutManager?.onRestoreInstanceState(itemsListState)
itemsListState = null
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ private void showAddItemDialog(final Context c) {

new AlertDialog.Builder(c)
.setTitle(R.string.peertube_instance_add_title)
.setIcon(R.drawable.place_holder_peertube)
.setIcon(R.drawable.ic_placeholder_peertube)
.setView(dialogBinding.getRoot())
.setNegativeButton(R.string.cancel, null)
.setPositiveButton(R.string.ok, (dialog1, which) -> {
Expand Down Expand Up @@ -411,7 +411,7 @@ void bind(final int position, final TabViewHolder holder) {
lastChecked = instanceRB;
}
});
instanceIconView.setImageResource(R.drawable.place_holder_peertube);
instanceIconView.setImageResource(R.drawable.ic_placeholder_peertube);
}

@SuppressLint("ClickableViewAccessibility")
Expand Down
12 changes: 6 additions & 6 deletions app/src/main/java/org/schabi/newpipe/util/ServiceHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,17 @@ private ServiceHelper() { }
public static int getIcon(final int serviceId) {
switch (serviceId) {
case 0:
return R.drawable.place_holder_youtube;
return R.drawable.ic_smart_display;
case 1:
return R.drawable.place_holder_cloud;
return R.drawable.ic_cloud;
case 2:
return R.drawable.place_holder_gadse;
return R.drawable.ic_placeholder_media_ccc;
case 3:
return R.drawable.place_holder_peertube;
return R.drawable.ic_placeholder_peertube;
case 4:
return R.drawable.place_holder_bandcamp;
return R.drawable.ic_placeholder_bandcamp;
default:
return R.drawable.place_holder_circle;
return R.drawable.ic_circle;
}
}

Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
10 changes: 10 additions & 0 deletions app/src/main/res/drawable/ic_circle.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:width="24dp"
android:viewportHeight="24"
android:viewportWidth="24"
android:tint="@color/defaultIconTint" >
<path
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10s10,-4.49 10,-10S17.52,2 12,2L12,2z"
android:fillColor="#FF000000" />
</vector>
Loading