mirror of
https://github.com/TeamNewPipe/NewPipe
synced 2025-11-12 21:22:59 +00:00
SubscriptionImportWorker: inputs as sealed class
This commit is contained in:
@@ -11,7 +11,6 @@ import androidx.appcompat.app.AlertDialog;
|
|||||||
import androidx.fragment.app.DialogFragment;
|
import androidx.fragment.app.DialogFragment;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.work.Constraints;
|
import androidx.work.Constraints;
|
||||||
import androidx.work.Data;
|
|
||||||
import androidx.work.ExistingWorkPolicy;
|
import androidx.work.ExistingWorkPolicy;
|
||||||
import androidx.work.NetworkType;
|
import androidx.work.NetworkType;
|
||||||
import androidx.work.OneTimeWorkRequest;
|
import androidx.work.OneTimeWorkRequest;
|
||||||
@@ -22,31 +21,19 @@ import com.evernote.android.state.State;
|
|||||||
import com.livefront.bridge.Bridge;
|
import com.livefront.bridge.Bridge;
|
||||||
|
|
||||||
import org.schabi.newpipe.R;
|
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.local.subscription.workers.SubscriptionImportWorker;
|
||||||
import org.schabi.newpipe.util.Constants;
|
|
||||||
|
|
||||||
public class ImportConfirmationDialog extends DialogFragment {
|
public class ImportConfirmationDialog extends DialogFragment {
|
||||||
@State
|
@State
|
||||||
protected int mode;
|
protected SubscriptionImportInput input;
|
||||||
@State
|
|
||||||
protected String value;
|
|
||||||
@State
|
|
||||||
protected int serviceId;
|
|
||||||
|
|
||||||
public static void show(@NonNull final Fragment fragment, final int mode,
|
public static void show(@NonNull final Fragment fragment, final SubscriptionImportInput input) {
|
||||||
@Nullable final String value, final int serviceId) {
|
|
||||||
final var confirmationDialog = new ImportConfirmationDialog();
|
final var confirmationDialog = new ImportConfirmationDialog();
|
||||||
confirmationDialog.setData(mode, value, serviceId);
|
confirmationDialog.input = input;
|
||||||
confirmationDialog.show(fragment.getParentFragmentManager(), null);
|
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
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public Dialog onCreateDialog(@Nullable final Bundle savedInstanceState) {
|
public Dialog onCreateDialog(@Nullable final Bundle savedInstanceState) {
|
||||||
@@ -57,17 +44,12 @@ public class ImportConfirmationDialog extends DialogFragment {
|
|||||||
.setCancelable(true)
|
.setCancelable(true)
|
||||||
.setNegativeButton(R.string.cancel, null)
|
.setNegativeButton(R.string.cancel, null)
|
||||||
.setPositiveButton(R.string.ok, (dialogInterface, i) -> {
|
.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()
|
final var constraints = new Constraints.Builder()
|
||||||
.setRequiredNetworkType(NetworkType.CONNECTED)
|
.setRequiredNetworkType(NetworkType.CONNECTED)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
final var req = new OneTimeWorkRequest.Builder(SubscriptionImportWorker.class)
|
final var req = new OneTimeWorkRequest.Builder(SubscriptionImportWorker.class)
|
||||||
.setInputData(inputData)
|
.setInputData(input.toData())
|
||||||
.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
|
.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
|
||||||
.setConstraints(constraints)
|
.setConstraints(constraints)
|
||||||
.build();
|
.build();
|
||||||
@@ -85,10 +67,6 @@ public class ImportConfirmationDialog extends DialogFragment {
|
|||||||
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
if (mode == 0 && value == null && serviceId == 0) {
|
|
||||||
throw new IllegalStateException("Input data not provided");
|
|
||||||
}
|
|
||||||
|
|
||||||
Bridge.restoreInstanceState(this, savedInstanceState);
|
Bridge.restoreInstanceState(this, savedInstanceState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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.Header
|
||||||
import org.schabi.newpipe.local.subscription.item.ImportSubscriptionsHintPlaceholderItem
|
import org.schabi.newpipe.local.subscription.item.ImportSubscriptionsHintPlaceholderItem
|
||||||
import org.schabi.newpipe.local.subscription.workers.SubscriptionExportWorker
|
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.NoFileManagerSafeGuard
|
||||||
import org.schabi.newpipe.streams.io.StoredFileHelper
|
import org.schabi.newpipe.streams.io.StoredFileHelper
|
||||||
import org.schabi.newpipe.ui.emptystate.setEmptyStateComposable
|
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.NavigationHelper
|
||||||
import org.schabi.newpipe.util.OnClickGesture
|
import org.schabi.newpipe.util.OnClickGesture
|
||||||
import org.schabi.newpipe.util.ServiceHelper
|
import org.schabi.newpipe.util.ServiceHelper
|
||||||
@@ -231,7 +230,7 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
|
|||||||
val data = result.data?.dataString
|
val data = result.data?.dataString
|
||||||
if (data != null && result.resultCode == Activity.RESULT_OK) {
|
if (data != null && result.resultCode == Activity.RESULT_OK) {
|
||||||
ImportConfirmationDialog.show(
|
ImportConfirmationDialog.show(
|
||||||
this, SubscriptionImportWorker.PREVIOUS_EXPORT_MODE, data, NO_SERVICE_ID
|
this, SubscriptionImportInput.PreviousExportMode(data)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ import org.schabi.newpipe.error.UserAction;
|
|||||||
import org.schabi.newpipe.extractor.NewPipe;
|
import org.schabi.newpipe.extractor.NewPipe;
|
||||||
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||||
import org.schabi.newpipe.extractor.subscription.SubscriptionExtractor;
|
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.NoFileManagerSafeGuard;
|
||||||
import org.schabi.newpipe.streams.io.StoredFileHelper;
|
import org.schabi.newpipe.streams.io.StoredFileHelper;
|
||||||
import org.schabi.newpipe.util.Constants;
|
import org.schabi.newpipe.util.Constants;
|
||||||
@@ -164,8 +164,8 @@ public class SubscriptionsImportFragment extends BaseFragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void onImportUrl(final String value) {
|
public void onImportUrl(final String value) {
|
||||||
ImportConfirmationDialog.show(this, SubscriptionImportWorker.CHANNEL_URL_MODE, value,
|
ImportConfirmationDialog.show(this,
|
||||||
currentServiceId);
|
new SubscriptionImportInput.ChannelUrlMode(currentServiceId, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onImportFile() {
|
public void onImportFile() {
|
||||||
@@ -182,8 +182,8 @@ public class SubscriptionsImportFragment extends BaseFragment {
|
|||||||
private void requestImportFileResult(final ActivityResult result) {
|
private void requestImportFileResult(final ActivityResult result) {
|
||||||
final String data = result.getData() != null ? result.getData().getDataString() : null;
|
final String data = result.getData() != null ? result.getData().getDataString() : null;
|
||||||
if (result.getResultCode() == Activity.RESULT_OK && data != null) {
|
if (result.getResultCode() == Activity.RESULT_OK && data != null) {
|
||||||
ImportConfirmationDialog.show(this, SubscriptionImportWorker.INPUT_STREAM_MODE,
|
ImportConfirmationDialog.show(this,
|
||||||
data, currentServiceId);
|
new SubscriptionImportInput.InputStreamMode(currentServiceId, data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,11 +3,13 @@ package org.schabi.newpipe.local.subscription.workers
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.pm.ServiceInfo
|
import android.content.pm.ServiceInfo
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
import android.os.Parcelable
|
||||||
import android.webkit.MimeTypeMap
|
import android.webkit.MimeTypeMap
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import androidx.work.CoroutineWorker
|
import androidx.work.CoroutineWorker
|
||||||
|
import androidx.work.Data
|
||||||
import androidx.work.ForegroundInfo
|
import androidx.work.ForegroundInfo
|
||||||
import androidx.work.WorkManager
|
import androidx.work.WorkManager
|
||||||
import androidx.work.WorkerParameters
|
import androidx.work.WorkerParameters
|
||||||
@@ -18,12 +20,11 @@ import kotlinx.coroutines.rx3.await
|
|||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
import kotlinx.coroutines.sync.withLock
|
import kotlinx.coroutines.sync.withLock
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
import kotlinx.parcelize.Parcelize
|
||||||
import org.schabi.newpipe.R
|
import org.schabi.newpipe.R
|
||||||
import org.schabi.newpipe.extractor.NewPipe
|
import org.schabi.newpipe.extractor.NewPipe
|
||||||
import org.schabi.newpipe.local.subscription.SubscriptionManager
|
import org.schabi.newpipe.local.subscription.SubscriptionManager
|
||||||
import org.schabi.newpipe.util.ExtractorHelper
|
import org.schabi.newpipe.util.ExtractorHelper
|
||||||
import org.schabi.newpipe.util.KEY_SERVICE_ID
|
|
||||||
import org.schabi.newpipe.util.NO_SERVICE_ID
|
|
||||||
|
|
||||||
class SubscriptionImportWorker(
|
class SubscriptionImportWorker(
|
||||||
appContext: Context,
|
appContext: Context,
|
||||||
@@ -35,27 +36,29 @@ class SubscriptionImportWorker(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun doWork(): Result {
|
override suspend fun doWork(): Result {
|
||||||
val mode = inputData.getInt(KEY_MODE, CHANNEL_URL_MODE)
|
val input = SubscriptionImportInput.fromData(inputData)
|
||||||
val serviceId = inputData.getInt(KEY_SERVICE_ID, NO_SERVICE_ID)
|
|
||||||
val value = inputData.getString(KEY_VALUE)!!
|
|
||||||
|
|
||||||
val subscriptions = withContext(Dispatchers.IO) {
|
val subscriptions = withContext(Dispatchers.IO) {
|
||||||
if (mode == CHANNEL_URL_MODE) {
|
when (input) {
|
||||||
NewPipe.getService(serviceId).subscriptionExtractor
|
is SubscriptionImportInput.ChannelUrlMode ->
|
||||||
.fromChannelUrl(value)
|
NewPipe.getService(input.serviceId).subscriptionExtractor
|
||||||
.map { SubscriptionItem(it.serviceId, it.url, it.name) }
|
.fromChannelUrl(input.url)
|
||||||
} else {
|
.map { SubscriptionItem(it.serviceId, it.url, it.name) }
|
||||||
applicationContext.contentResolver.openInputStream(value.toUri())?.use {
|
|
||||||
if (mode == INPUT_STREAM_MODE) {
|
is SubscriptionImportInput.InputStreamMode ->
|
||||||
val contentType = MimeTypeMap.getFileExtensionFromUrl(value).ifEmpty { DEFAULT_MIME }
|
applicationContext.contentResolver.openInputStream(input.url.toUri())?.use {
|
||||||
NewPipe.getService(serviceId).subscriptionExtractor
|
val contentType =
|
||||||
|
MimeTypeMap.getFileExtensionFromUrl(input.url).ifEmpty { DEFAULT_MIME }
|
||||||
|
NewPipe.getService(input.serviceId).subscriptionExtractor
|
||||||
.fromInputStream(it, contentType)
|
.fromInputStream(it, contentType)
|
||||||
.map { SubscriptionItem(it.serviceId, it.url, it.name) }
|
.map { SubscriptionItem(it.serviceId, it.url, it.name) }
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
is SubscriptionImportInput.PreviousExportMode ->
|
||||||
|
applicationContext.contentResolver.openInputStream(input.url.toUri())?.use {
|
||||||
ImportExportJsonHelper.readFrom(it)
|
ImportExportJsonHelper.readFrom(it)
|
||||||
}
|
}
|
||||||
} ?: emptyList()
|
} ?: emptyList()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val mutex = Mutex()
|
val mutex = Mutex()
|
||||||
@@ -146,10 +149,69 @@ class SubscriptionImportWorker(
|
|||||||
private const val BUFFER_COUNT_BEFORE_INSERT = 50
|
private const val BUFFER_COUNT_BEFORE_INSERT = 50
|
||||||
|
|
||||||
const val WORK_NAME = "SubscriptionImportWorker"
|
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"
|
sealed class SubscriptionImportInput : Parcelable {
|
||||||
const val KEY_VALUE = "key_value"
|
@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")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user