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

Rewrite import and export subscriptions functionality using coroutines #11759

Open
wants to merge 12 commits into
base: refactor
Choose a base branch
from

Conversation

Isira-Seneviratne
Copy link
Member

What is it?

  • Bugfix (user facing)
  • Feature (user facing)
  • Codebase improvement (dev facing)
  • Meta improvement to the project (dev facing)

Description of the changes in your PR

  • Implement the subscription import/export functionality using CoroutineWorker for better performance and readability of the code.
  • Make the import process cancellable (exporting usually completes too quickly to show a notification).
  • Read/write subscription data using the Kotlinx Serialization library and plugin.
  • Update WorkManager from 2.8.1 to 2.10.0 (changelog)
  • Update the compile SDK to 35 (required by WorkManager).

Before/After Screenshots/Screen Record

Export

  • Before:
Screen_recording_20241129_071419.webm

Android 6.0

  • After:
Screen_recording_20241129_064527.webm

Android 6.0

Screen_recording_20241129_064829.mp4

Android 15

Fixes the following issue(s)

  • Fixes #

APK testing

The APK can be found by going to the "Checks" tab below the title. On the left pane, click on "CI", scroll down to "artifacts" and click "app" to download the zip file which contains the debug APK of this PR. You can find more info and a video demonstration on this wiki page.

Due diligence

@github-actions github-actions bot added the size/giant PRs with more than 750 changed lines label Nov 29, 2024
@ShareASmile ShareASmile added dependency Issues and PRs related to dependencies rewrite Issues and PRs related to rewrite import/export feature request Issue is related to a feature in the app labels Nov 29, 2024
Comment on lines +50 to +56
try {
@OptIn(ExperimentalSerializationApi::class)
return json.decodeFromStream<SubscriptionData>(`in`).subscriptions
} catch (e: Throwable) {
throw InvalidSourceException("Couldn't parse json", e)
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From a cursory look, this seems to be a lot stricter than the previous json parser.

e.g. the serviceId would default to 0, and items in the list would simply be skipped if they don’t conform to the schema.

Do we want to change that behavior?

Comment on lines 88 to 90
if (mode == 0 && value == null && serviceId == 0) {
throw new IllegalStateException("Input data not provided");
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to crash when rotating the screen while the confirmation dialog is visible

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At that point the module is not yet restored, I don’t know what this is supposed to do?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be fixed in the commit I added, I left out the check since it will always use the @Parcelize decoders from the SubscriptionImportInput subclasses.

@Profpatsch Profpatsch force-pushed the Import-export-worker branch from e99c0bc to dbd11a6 Compare January 22, 2025 14:41
@Profpatsch
Copy link
Contributor

I rebased on current refactor, and added a commit which kotlin-ifies the SubscriptionImportWorker input data a little, turning them into a sealed class that auto-parcelizes.

Unfortunately, there is no Data.Builder().fromParcelable() or similar, so the Data conversion has to be done manually still, but I centralized it in the sealed class so it should be straightforward as well.

Comment on lines +41 to +60
val subscriptions = withContext(Dispatchers.IO) {
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) }
}

is SubscriptionImportInput.PreviousExportMode ->
applicationContext.contentResolver.openInputStream(input.url.toUri())?.use {
ImportExportJsonHelper.readFrom(it)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is missing a bunch of error handling, for example:

  • File that was selected might not exist
  • File might not be able to be parsed as json, or have the wrong contents
  • Channel might not exist
  • ServiceId might not exist

All of these should probably be shown to the user, right now the worker crashes silently in the background and nothing happens.

@Profpatsch
Copy link
Contributor

Once the missing error handling is added on import & the question about how leniently to parse the json is resolved, I’d say LGTM!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
dependency Issues and PRs related to dependencies feature request Issue is related to a feature in the app import/export rewrite Issues and PRs related to rewrite size/giant PRs with more than 750 changed lines
Projects
Status: Todo
Development

Successfully merging this pull request may close these issues.

3 participants