revanced-manager
revanced-manager copied to clipboard
fix: Update dialog shows dev version & loading gets stuck in certain circumstances
This PR fix these ~~two~~ three issues related to the Manager update dialog.
Issue 1
Dev version is shown in the "Show update" or "Show changelog" dialog when the current latest version is dev.
completes #1774
Cause
add49e1 only checks the past releases, so the latest dev version is still shown
Solution
Make GitHubAPI.getLatestManagerVersion()
find the latest non-dev release and return it.
Issue 2
If the Manager version is too old (more than 30 releases), the update dialog gets stuck loading.
Cause
The api (https://api.github.com/repos/ReVanced/revanced-manager/releases) returns only recent 30 releases.
However, the current implementation doesn't consider it.
If the api response doesn't include the current Manager version, a while statement in GitHubAPI.getLatestManagerVersion()
( that searches current version) accesses out of range index and causes error.
Solution
Check the list range
As of today, this issue affects all versions prior to 1.18.0. ~~Discord supporters should know this issue 😕~~
Issue 3 (Added 2024/03/31)
In changelogs, version name line is duplicated
Cause
d414a91f40bb4bce6c37944f63635348d1f05aaa changed changelog format to contain version name
Solution
Not to append version name when output changelogs
I think this PR needs a review by @TheAabedKhan. Would you review please?
Thank you. I checked that it fixes the issues.
However, ?per_page=100 caused bad performance when the changelogs are long. (even on release build, Snapdragon 845 phone) It took 1.5 seconds to open the changelog and scroll is very laggy. Therefore, I think it would be reasonable to limit it to default 30 releases.
Also, I want to a question. I'm interested in this.
- Linear iteration
- Early termination
- Reduced loop iterations
I think this code will also work:
int updates = 0;
while (releases[updates]['tag_name'] != currentVersion) {
updates++;
if (updates == releases.length) {
break;
}
releases[0].update(
'body',
(value) =>
value +
'\n' +
'# ' +
releases[updates]['tag_name'] +
'\n' +
releases[updates]['body'],
);
}
Is it really more efficient to first count the number with a while loop and then do a for loop rather than processing it in one iteration? (Sorry for the off-topic general computer science question.)
It took 1.5 seconds to open the changelog and scroll is very laggy.
Couldn't feel any difference on my device. However, you can try reducing the number until you are satisfied with the performance or remove the parameter if you like.
Is it really more efficient to first count the number with a while loop and then do a for loop rather than processing it in one iteration?
You're correct that in terms of pure iteration, it would be more efficient to process everything in one iteration rather than counting first and then iterating again. Also, while we are on it, how about accumulating release notes separately before updating the body of the first release? This will reduce the number of update operations on the body of the first release.
final StringBuffer releaseNotes = StringBuffer();
while (releases[updates]['tag_name'] != currentVersion) {
updates++;
if (updates == releases.length) {
break;
}
releaseNotes.writeln('# ${releases[updates]['tag_name']}');
releaseNotes.writeln(releases[updates]['body']);
}
releases[0].update(
'body',
(value) => value + '\n' + releaseNotes.toString(),
);
return releases[0];
It's more readable than two loops! Thank you for the advice.
I just came up with an idea.
This version string in UpdateConfirmationSheet
can be obtained from a field HomeViewModel.latestManagerVersion
instead of GitHubAPI.getLatestManagerReleases()
.
This value is more accurate than get from https://api.github.com/repos/ReVanced/revanced-manager/releases?per_page=XXX, because the possibility exists that all releases from this API are pre-release.
(lack of my test cases before making a PR)
Then, the method Future<Map<String, dynamic>?> getLatestManagerRelease(String repoName)
don't have to provide the latest version string, so it can be more simple and less-responsibility method like Future<String?> getManagerChangelogs()
I will do this tomorrow.
Changes
update_confirmation_sheet.dart:
- Change version string reference from
snapshot.data!['tag_name']
tomodel.latestPatchesVersion
- Use FutureBuilder only for the changelog part
- This allows users to update manager even when failed to connect GitHub API
home_viewmodel.dart:
- Make
String? _latestManagerVersion
andString? _latestPatchesVersion
instance variables public in order to be used in update_confirmation_sheet - Remove initializing with empty strings because I want to guarantee that the variable holds the latest version string
- Change methods which used in update_confirmation_sheet
github_api.dart:
-
Future<Map<String, dynamic>?> getLatestManagerRelease(String repoName)
now returns the changelogs only and renamed toFuture<String?> getManagerChangelogs()
- Set to
?per_page=50
- Don't append the version name header while generating changelogs (Refer to the added issue 3)