diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/ImportConfirmationDialog.java b/app/src/main/java/org/schabi/newpipe/local/subscription/ImportConfirmationDialog.java index 3db86a203..a193cc1b9 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/ImportConfirmationDialog.java +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/ImportConfirmationDialog.java @@ -11,7 +11,6 @@ import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.DialogFragment; import androidx.fragment.app.Fragment; import androidx.work.Constraints; -import androidx.work.Data; import androidx.work.ExistingWorkPolicy; import androidx.work.NetworkType; import androidx.work.OneTimeWorkRequest; @@ -22,31 +21,19 @@ import com.evernote.android.state.State; import com.livefront.bridge.Bridge; import org.schabi.newpipe.R; +import org.schabi.newpipe.local.subscription.workers.SubscriptionImportInput; import org.schabi.newpipe.local.subscription.workers.SubscriptionImportWorker; -import org.schabi.newpipe.util.Constants; public class ImportConfirmationDialog extends DialogFragment { @State - protected int mode; - @State - protected String value; - @State - protected int serviceId; + protected SubscriptionImportInput input; - public static void show(@NonNull final Fragment fragment, final int mode, - @Nullable final String value, final int serviceId) { + public static void show(@NonNull final Fragment fragment, final SubscriptionImportInput input) { final var confirmationDialog = new ImportConfirmationDialog(); - confirmationDialog.setData(mode, value, serviceId); + confirmationDialog.input = input; confirmationDialog.show(fragment.getParentFragmentManager(), null); } - @SuppressWarnings("HiddenField") - public void setData(final int mode, final String value, final int serviceId) { - this.mode = mode; - this.value = value; - this.serviceId = serviceId; - } - @NonNull @Override public Dialog onCreateDialog(@Nullable final Bundle savedInstanceState) { @@ -57,17 +44,12 @@ public class ImportConfirmationDialog extends DialogFragment { .setCancelable(true) .setNegativeButton(R.string.cancel, null) .setPositiveButton(R.string.ok, (dialogInterface, i) -> { - final var inputData = new Data.Builder() - .putString(SubscriptionImportWorker.KEY_VALUE, value) - .putInt(SubscriptionImportWorker.KEY_MODE, mode) - .putInt(Constants.KEY_SERVICE_ID, serviceId) - .build(); final var constraints = new Constraints.Builder() .setRequiredNetworkType(NetworkType.CONNECTED) .build(); final var req = new OneTimeWorkRequest.Builder(SubscriptionImportWorker.class) - .setInputData(inputData) + .setInputData(input.toData()) .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST) .setConstraints(constraints) .build(); @@ -85,10 +67,6 @@ public class ImportConfirmationDialog extends DialogFragment { public void onCreate(@Nullable final Bundle savedInstanceState) { super.onCreate(savedInstanceState); - if (mode == 0 && value == null && serviceId == 0) { - throw new IllegalStateException("Input data not provided"); - } - Bridge.restoreInstanceState(this, savedInstanceState); } 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 cdc7ae179..91ff7cd27 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 @@ -49,11 +49,10 @@ 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.SubscriptionImportWorker +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.ui.emptystate.setEmptyStateComposable -import org.schabi.newpipe.util.NO_SERVICE_ID import org.schabi.newpipe.util.NavigationHelper import org.schabi.newpipe.util.OnClickGesture import org.schabi.newpipe.util.ServiceHelper @@ -231,7 +230,7 @@ class SubscriptionFragment : BaseStateFragment() { val data = result.data?.dataString if (data != null && result.resultCode == Activity.RESULT_OK) { ImportConfirmationDialog.show( - this, SubscriptionImportWorker.PREVIOUS_EXPORT_MODE, data, NO_SERVICE_ID + this, SubscriptionImportInput.PreviousExportMode(data) ) } } diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionsImportFragment.java b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionsImportFragment.java index a1d244df8..aee7c0003 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionsImportFragment.java +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionsImportFragment.java @@ -33,7 +33,7 @@ import org.schabi.newpipe.error.UserAction; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.subscription.SubscriptionExtractor; -import org.schabi.newpipe.local.subscription.workers.SubscriptionImportWorker; +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.Constants; @@ -164,8 +164,8 @@ public class SubscriptionsImportFragment extends BaseFragment { } public void onImportUrl(final String value) { - ImportConfirmationDialog.show(this, SubscriptionImportWorker.CHANNEL_URL_MODE, value, - currentServiceId); + ImportConfirmationDialog.show(this, + new SubscriptionImportInput.ChannelUrlMode(currentServiceId, value)); } public void onImportFile() { @@ -182,8 +182,8 @@ public class SubscriptionsImportFragment extends BaseFragment { private void requestImportFileResult(final ActivityResult result) { final String data = result.getData() != null ? result.getData().getDataString() : null; if (result.getResultCode() == Activity.RESULT_OK && data != null) { - ImportConfirmationDialog.show(this, SubscriptionImportWorker.INPUT_STREAM_MODE, - data, currentServiceId); + ImportConfirmationDialog.show(this, + new SubscriptionImportInput.InputStreamMode(currentServiceId, data)); } } diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/workers/SubscriptionImportWorker.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/workers/SubscriptionImportWorker.kt index e97eb760e..4bcec5cb3 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/workers/SubscriptionImportWorker.kt +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/workers/SubscriptionImportWorker.kt @@ -3,11 +3,13 @@ package org.schabi.newpipe.local.subscription.workers import android.content.Context import android.content.pm.ServiceInfo import android.os.Build +import android.os.Parcelable import android.webkit.MimeTypeMap import android.widget.Toast import androidx.core.app.NotificationCompat import androidx.core.net.toUri import androidx.work.CoroutineWorker +import androidx.work.Data import androidx.work.ForegroundInfo import androidx.work.WorkManager import androidx.work.WorkerParameters @@ -18,12 +20,11 @@ import kotlinx.coroutines.rx3.await import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.withContext +import kotlinx.parcelize.Parcelize import org.schabi.newpipe.R import org.schabi.newpipe.extractor.NewPipe import org.schabi.newpipe.local.subscription.SubscriptionManager import org.schabi.newpipe.util.ExtractorHelper -import org.schabi.newpipe.util.KEY_SERVICE_ID -import org.schabi.newpipe.util.NO_SERVICE_ID class SubscriptionImportWorker( appContext: Context, @@ -35,27 +36,29 @@ class SubscriptionImportWorker( } override suspend fun doWork(): Result { - val mode = inputData.getInt(KEY_MODE, CHANNEL_URL_MODE) - val serviceId = inputData.getInt(KEY_SERVICE_ID, NO_SERVICE_ID) - val value = inputData.getString(KEY_VALUE)!! + val input = SubscriptionImportInput.fromData(inputData) val subscriptions = withContext(Dispatchers.IO) { - if (mode == CHANNEL_URL_MODE) { - NewPipe.getService(serviceId).subscriptionExtractor - .fromChannelUrl(value) - .map { SubscriptionItem(it.serviceId, it.url, it.name) } - } else { - applicationContext.contentResolver.openInputStream(value.toUri())?.use { - if (mode == INPUT_STREAM_MODE) { - val contentType = MimeTypeMap.getFileExtensionFromUrl(value).ifEmpty { DEFAULT_MIME } - NewPipe.getService(serviceId).subscriptionExtractor + when (input) { + is SubscriptionImportInput.ChannelUrlMode -> + NewPipe.getService(input.serviceId).subscriptionExtractor + .fromChannelUrl(input.url) + .map { SubscriptionItem(it.serviceId, it.url, it.name) } + + is SubscriptionImportInput.InputStreamMode -> + applicationContext.contentResolver.openInputStream(input.url.toUri())?.use { + val contentType = + MimeTypeMap.getFileExtensionFromUrl(input.url).ifEmpty { DEFAULT_MIME } + NewPipe.getService(input.serviceId).subscriptionExtractor .fromInputStream(it, contentType) .map { SubscriptionItem(it.serviceId, it.url, it.name) } - } else { + } + + is SubscriptionImportInput.PreviousExportMode -> + applicationContext.contentResolver.openInputStream(input.url.toUri())?.use { ImportExportJsonHelper.readFrom(it) } - } ?: emptyList() - } + } ?: emptyList() } val mutex = Mutex() @@ -146,10 +149,69 @@ class SubscriptionImportWorker( private const val BUFFER_COUNT_BEFORE_INSERT = 50 const val WORK_NAME = "SubscriptionImportWorker" - const val CHANNEL_URL_MODE = 0 - const val INPUT_STREAM_MODE = 1 - const val PREVIOUS_EXPORT_MODE = 2 - const val KEY_MODE = "key_mode" - const val KEY_VALUE = "key_value" + } +} + +sealed class SubscriptionImportInput : Parcelable { + @Parcelize + data class ChannelUrlMode(val serviceId: Int, val url: String) : SubscriptionImportInput() + @Parcelize + data class InputStreamMode(val serviceId: Int, val url: String) : SubscriptionImportInput() + @Parcelize + data class PreviousExportMode(val url: String) : SubscriptionImportInput() + + fun toData(): Data { + return when (this) { + is ChannelUrlMode -> Data.Builder() + .putInt("mode", CHANNEL_URL_MODE) + .putInt("service_id", serviceId) + .putString("url", url) + .build() + is InputStreamMode -> + Data.Builder() + .putInt("mode", INPUT_STREAM_MODE) + .putInt("service_id", serviceId) + .putString("url", url) + .build() + is PreviousExportMode -> + Data.Builder() + .putInt("mode", PREVIOUS_EXPORT_MODE) + .putString("url", url) + .build() + } + } + + companion object { + + private const val CHANNEL_URL_MODE = 0 + private const val INPUT_STREAM_MODE = 1 + private const val PREVIOUS_EXPORT_MODE = 2 + + fun fromData(data: Data): SubscriptionImportInput { + val mode = data.getInt("mode", PREVIOUS_EXPORT_MODE) + when (mode) { + CHANNEL_URL_MODE -> { + val serviceId = data.getInt("service_id", -1) + if (serviceId == -1) { + throw IllegalArgumentException("No service id provided") + } + val url = data.getString("url")!! + return ChannelUrlMode(serviceId, url) + } + INPUT_STREAM_MODE -> { + val serviceId = data.getInt("service_id", -1) + if (serviceId == -1) { + throw IllegalArgumentException("No service id provided") + } + val url = data.getString("url")!! + return InputStreamMode(serviceId, url) + } + PREVIOUS_EXPORT_MODE -> { + val url = data.getString("url")!! + return PreviousExportMode(url) + } + else -> throw IllegalArgumentException("Unknown mode: $mode") + } + } } }