mirror of
https://github.com/TeamNewPipe/NewPipe
synced 2026-03-18 05:39:44 +00:00
BackupRestoreSettingsFragment: add UI options to import/export subscriptions
* create SubscriptionsImportExportHelper to share common code used in SubscriptionFragment and BackupRestoreSettingsFragment * Add UI options for import/export in BackupRestoreSettingsFragment
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
package org.schabi.newpipe.local.subscription
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.DialogInterface
|
||||
import android.os.Bundle
|
||||
@@ -14,8 +13,6 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.webkit.MimeTypeMap
|
||||
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
|
||||
@@ -26,9 +23,6 @@ import com.xwray.groupie.GroupAdapter
|
||||
import com.xwray.groupie.Section
|
||||
import com.xwray.groupie.viewbinding.GroupieViewHolder
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
import org.schabi.newpipe.R
|
||||
import org.schabi.newpipe.database.feed.model.FeedGroupEntity.Companion.GROUP_ALL_ID
|
||||
import org.schabi.newpipe.databinding.DialogTitleBinding
|
||||
@@ -52,10 +46,6 @@ import org.schabi.newpipe.local.subscription.item.FeedGroupCarouselItem
|
||||
import org.schabi.newpipe.local.subscription.item.GroupsHeader
|
||||
import org.schabi.newpipe.local.subscription.item.Header
|
||||
import org.schabi.newpipe.local.subscription.item.ImportSubscriptionsHintPlaceholderItem
|
||||
import org.schabi.newpipe.local.subscription.workers.SubscriptionExportWorker
|
||||
import org.schabi.newpipe.local.subscription.workers.SubscriptionImportInput
|
||||
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
|
||||
@@ -68,6 +58,7 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
|
||||
|
||||
private lateinit var viewModel: SubscriptionViewModel
|
||||
private lateinit var subscriptionManager: SubscriptionManager
|
||||
private lateinit var importExportHelper: SubscriptionsImportExportHelper
|
||||
private val disposables: CompositeDisposable = CompositeDisposable()
|
||||
|
||||
private val groupAdapter = GroupAdapter<GroupieViewHolder<FeedItemCarouselBinding>>()
|
||||
@@ -76,11 +67,6 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
|
||||
private lateinit var feedGroupsSortMenuItem: GroupsHeader
|
||||
private val subscriptionsSection = Section()
|
||||
|
||||
private val requestExportLauncher =
|
||||
registerForActivityResult(StartActivityForResult(), this::requestExportResult)
|
||||
private val requestImportLauncher =
|
||||
registerForActivityResult(StartActivityForResult(), this::requestImportResult)
|
||||
|
||||
@State
|
||||
@JvmField
|
||||
var itemsListState: Parcelable? = null
|
||||
@@ -100,6 +86,7 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
|
||||
override fun onAttach(context: Context) {
|
||||
super.onAttach(context)
|
||||
subscriptionManager = SubscriptionManager(requireContext())
|
||||
importExportHelper = SubscriptionsImportExportHelper(this)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
@@ -139,7 +126,7 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
|
||||
// -- Import --
|
||||
val importSubMenu = menu.addSubMenu(R.string.import_from)
|
||||
|
||||
addMenuItemToSubmenu(importSubMenu, R.string.previous_export) { onImportPreviousSelected() }
|
||||
addMenuItemToSubmenu(importSubMenu, R.string.previous_export) { importExportHelper.onImportPreviousSelected() }
|
||||
.setIcon(R.drawable.ic_backup)
|
||||
|
||||
for (service in ServiceList.all()) {
|
||||
@@ -157,7 +144,7 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
|
||||
// -- Export --
|
||||
val exportSubMenu = menu.addSubMenu(R.string.export_to)
|
||||
|
||||
addMenuItemToSubmenu(exportSubMenu, R.string.file) { onExportSelected() }
|
||||
addMenuItemToSubmenu(exportSubMenu, R.string.file) { importExportHelper.onExportSelected() }
|
||||
.setIcon(R.drawable.ic_save)
|
||||
}
|
||||
|
||||
@@ -193,48 +180,10 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
|
||||
NavigationHelper.openSubscriptionsImportFragment(fragmentManager, serviceId)
|
||||
}
|
||||
|
||||
private fun onImportPreviousSelected() {
|
||||
NoFileManagerSafeGuard.launchSafe(
|
||||
requestImportLauncher,
|
||||
StoredFileHelper.getPicker(activity, JSON_MIME_TYPE),
|
||||
TAG,
|
||||
requireContext()
|
||||
)
|
||||
}
|
||||
|
||||
private fun onExportSelected() {
|
||||
val date = SimpleDateFormat("yyyyMMddHHmm", Locale.ENGLISH).format(Date())
|
||||
val exportName = "newpipe_subscriptions_$date.json"
|
||||
|
||||
NoFileManagerSafeGuard.launchSafe(
|
||||
requestExportLauncher,
|
||||
StoredFileHelper.getNewPicker(activity, exportName, JSON_MIME_TYPE, null),
|
||||
TAG,
|
||||
requireContext()
|
||||
)
|
||||
}
|
||||
|
||||
private fun openReorderDialog() {
|
||||
FeedGroupReorderDialog().show(parentFragmentManager, null)
|
||||
}
|
||||
|
||||
private fun requestExportResult(result: ActivityResult) {
|
||||
val data = result.data?.data
|
||||
if (data != null && result.resultCode == Activity.RESULT_OK) {
|
||||
SubscriptionExportWorker.schedule(activity, data)
|
||||
}
|
||||
}
|
||||
|
||||
private fun requestImportResult(result: ActivityResult) {
|
||||
val data = result.data?.dataString
|
||||
if (data != null && result.resultCode == Activity.RESULT_OK) {
|
||||
ImportConfirmationDialog.show(
|
||||
this,
|
||||
SubscriptionImportInput.PreviousExportMode(data)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// ////////////////////////////////////////////////////////////////////////
|
||||
// Fragment Views
|
||||
// ////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
package org.schabi.newpipe.local.subscription
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import androidx.activity.result.ActivityResult
|
||||
import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult
|
||||
import androidx.fragment.app.Fragment
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
import org.schabi.newpipe.local.subscription.SubscriptionFragment.Companion.JSON_MIME_TYPE
|
||||
import org.schabi.newpipe.local.subscription.workers.SubscriptionExportWorker
|
||||
import org.schabi.newpipe.local.subscription.workers.SubscriptionImportInput
|
||||
import org.schabi.newpipe.streams.io.NoFileManagerSafeGuard
|
||||
import org.schabi.newpipe.streams.io.StoredFileHelper
|
||||
|
||||
/**
|
||||
* This class has to be created in onAttach() or onCreate().
|
||||
*
|
||||
* It contains registerForActivityResult calls and those
|
||||
* calls are only allowed before a fragment/activity is created.
|
||||
*/
|
||||
class SubscriptionsImportExportHelper(
|
||||
val fragment: Fragment
|
||||
) {
|
||||
val context: Context = fragment.requireContext()
|
||||
|
||||
companion object {
|
||||
val TAG: String =
|
||||
SubscriptionsImportExportHelper::class.java.simpleName + "@" + Integer.toHexString(
|
||||
hashCode()
|
||||
)
|
||||
}
|
||||
|
||||
private val requestExportLauncher =
|
||||
fragment.registerForActivityResult(StartActivityForResult(), this::requestExportResult)
|
||||
private val requestImportLauncher =
|
||||
fragment.registerForActivityResult(StartActivityForResult(), this::requestImportResult)
|
||||
|
||||
private fun requestExportResult(result: ActivityResult) {
|
||||
val data = result.data?.data
|
||||
if (data != null && result.resultCode == Activity.RESULT_OK) {
|
||||
SubscriptionExportWorker.schedule(context, data)
|
||||
}
|
||||
}
|
||||
|
||||
private fun requestImportResult(result: ActivityResult) {
|
||||
val data = result.data?.dataString
|
||||
if (data != null && result.resultCode == Activity.RESULT_OK) {
|
||||
ImportConfirmationDialog.show(
|
||||
fragment,
|
||||
SubscriptionImportInput.PreviousExportMode(data)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun onExportSelected() {
|
||||
val date = SimpleDateFormat("yyyyMMddHHmm", Locale.ENGLISH).format(Date())
|
||||
val exportName = "newpipe_subscriptions_$date.json"
|
||||
|
||||
NoFileManagerSafeGuard.launchSafe(
|
||||
requestExportLauncher,
|
||||
StoredFileHelper.getNewPicker(
|
||||
context,
|
||||
exportName,
|
||||
JSON_MIME_TYPE,
|
||||
null
|
||||
),
|
||||
TAG,
|
||||
context
|
||||
)
|
||||
}
|
||||
|
||||
fun onImportPreviousSelected() {
|
||||
NoFileManagerSafeGuard.launchSafe(
|
||||
requestImportLauncher,
|
||||
StoredFileHelper.getPicker(context, JSON_MIME_TYPE),
|
||||
TAG,
|
||||
context
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,7 @@ import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.error.ErrorInfo;
|
||||
import org.schabi.newpipe.error.ErrorUtil;
|
||||
import org.schabi.newpipe.error.UserAction;
|
||||
import org.schabi.newpipe.local.subscription.SubscriptionsImportExportHelper;
|
||||
import org.schabi.newpipe.settings.export.BackupFileLocator;
|
||||
import org.schabi.newpipe.settings.export.ImportExportManager;
|
||||
import org.schabi.newpipe.streams.io.NoFileManagerSafeGuard;
|
||||
@@ -57,8 +58,15 @@ public class BackupRestoreSettingsFragment extends BasePreferenceFragment {
|
||||
private final ActivityResultLauncher<Intent> requestExportPathLauncher =
|
||||
registerForActivityResult(new ActivityResultContracts.StartActivityForResult(),
|
||||
this::requestExportPathResult);
|
||||
private SubscriptionsImportExportHelper importExportHelper;
|
||||
|
||||
|
||||
@Override
|
||||
public void onAttach(@NonNull final Context context) {
|
||||
super.onAttach(context);
|
||||
importExportHelper = new SubscriptionsImportExportHelper(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreatePreferences(@Nullable final Bundle savedInstanceState,
|
||||
@Nullable final String rootKey) {
|
||||
@@ -123,6 +131,21 @@ public class BackupRestoreSettingsFragment extends BasePreferenceFragment {
|
||||
alertDialog.show();
|
||||
return true;
|
||||
});
|
||||
|
||||
final Preference exportSubsPreference =
|
||||
requirePreference(R.string.export_subscriptions_key);
|
||||
exportSubsPreference.setOnPreferenceClickListener(reference -> {
|
||||
importExportHelper.onExportSelected();
|
||||
return true;
|
||||
});
|
||||
|
||||
final Preference importSubsPreference =
|
||||
requirePreference(R.string.import_subscriptions_key);
|
||||
importSubsPreference.setOnPreferenceClickListener(preference -> {
|
||||
importExportHelper.onImportPreviousSelected();
|
||||
return true;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private void requestExportPathResult(final ActivityResult result) {
|
||||
|
||||
@@ -413,6 +413,8 @@
|
||||
<string name="import_export_data_path">import_export_data_path</string>
|
||||
<string name="import_data">import_data</string>
|
||||
<string name="export_data">export_data</string>
|
||||
<string name="import_subscriptions_key">import_subscriptions_key</string>
|
||||
<string name="export_subscriptions_key">export_subscriptions_key</string>
|
||||
|
||||
<string name="clear_cookie_key">clear_cookie</string>
|
||||
|
||||
|
||||
@@ -520,6 +520,11 @@
|
||||
<string name="export_ongoing">Exporting…</string>
|
||||
<string name="import_file_title">Import file</string>
|
||||
<string name="previous_export">Previous export</string>
|
||||
<string name="import_subscriptions_title">Import subscriptions"</string>
|
||||
<string name="export_subscriptions_title">Export subscriptions</string>
|
||||
<string name="import_subscriptions_summary">Import subscriptions from a previous .json export"</string>
|
||||
<string name="export_subscriptions_summary">Export your subscriptions to a .json file</string>
|
||||
<string name="import_from_previous_export">Import from previous export</string>
|
||||
<string name="subscriptions_import_unsuccessful">Could not import subscriptions</string>
|
||||
<string name="subscriptions_export_unsuccessful">Could not export subscriptions</string>
|
||||
<string name="import_youtube_instructions">Import YouTube subscriptions from Google takeout:
|
||||
|
||||
@@ -22,4 +22,18 @@
|
||||
android:summary="@string/reset_settings_summary"
|
||||
app:singleLineTitle="false"
|
||||
app:iconSpaceReserved="false" />
|
||||
|
||||
<Preference
|
||||
android:key="@string/export_subscriptions_key"
|
||||
android:title="@string/export_subscriptions_title"
|
||||
android:summary="@string/export_subscriptions_summary"
|
||||
app:singleLineTitle="false"
|
||||
app:iconSpaceReserved="false" />
|
||||
|
||||
<Preference
|
||||
android:key="@string/import_subscriptions_key"
|
||||
android:title="@string/import_subscriptions_title"
|
||||
android:summary="@string/import_subscriptions_summary"
|
||||
app:singleLineTitle="false"
|
||||
app:iconSpaceReserved="false" />
|
||||
</PreferenceScreen>
|
||||
Reference in New Issue
Block a user