From 9beb839bf4f029433ed4d28e6cec6d5024f23fc2 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 17 Dec 2023 14:13:26 -0500 Subject: [PATCH 1/5] Fix 'verify latest' option for GitHub (#1163) --- lib/app_sources/github.dart | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/lib/app_sources/github.dart b/lib/app_sources/github.dart index 2456335..6ed69c8 100644 --- a/lib/app_sources/github.dart +++ b/lib/app_sources/github.dart @@ -234,7 +234,7 @@ class GitHub extends AppSource { bool verifyLatestTag = additionalSettings['verifyLatestTag'] == true; bool dontSortReleasesList = additionalSettings['dontSortReleasesList'] == true; - String? latestTag; + dynamic latestRelease; if (verifyLatestTag) { var temp = requestUrl.split('?'); Response res = await sourceRequest( @@ -245,12 +245,20 @@ class GitHub extends AppSource { } throw getObtainiumHttpError(res); } - var jsres = jsonDecode(res.body); - latestTag = jsres['tag_name'] ?? jsres['name']; + latestRelease = jsonDecode(res.body); } Response res = await sourceRequest(requestUrl); if (res.statusCode == 200) { var releases = jsonDecode(res.body) as List; + if (latestRelease != null) { + var latestTag = latestRelease['tag_name'] ?? latestRelease['name']; + if (releases + .where((element) => + (element['tag_name'] ?? element['name']) == latestTag) + .isEmpty) { + releases = [latestRelease, ...releases]; + } + } List> getReleaseAPKUrls(dynamic release) => (release['assets'] as List?) @@ -299,13 +307,13 @@ class GitHub extends AppSource { } }); } - if (latestTag != null && + if (latestRelease != null && releases.isNotEmpty && - latestTag != + latestRelease != (releases[releases.length - 1]['tag_name'] ?? releases[0]['name'])) { - var ind = releases.indexWhere( - (element) => latestTag == (element['tag_name'] ?? element['name'])); + var ind = releases.indexWhere((element) => + latestRelease == (element['tag_name'] ?? element['name'])); if (ind >= 0) { releases.add(releases.removeAt(ind)); } From d1955192ed8c6ad8baf7efbe1b1be73c43d28d93 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 17 Dec 2023 14:14:46 -0500 Subject: [PATCH 2/5] Minor UI fix (#1162) --- lib/pages/import_export.dart | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/pages/import_export.dart b/lib/pages/import_export.dart index 0a624e9..635c720 100644 --- a/lib/pages/import_export.dart +++ b/lib/pages/import_export.dart @@ -347,7 +347,8 @@ class _ImportExportPageState extends State { : () { runObtainiumExport(pickOnly: true); }, - child: Text(tr('pickExportDir')), + child: Text(tr('pickExportDir'), + textAlign: TextAlign.center), )), const SizedBox( width: 16, @@ -360,7 +361,8 @@ class _ImportExportPageState extends State { snapshot.data == null ? null : runObtainiumExport, - child: Text(tr('obtainiumExport')), + child: Text(tr('obtainiumExport'), + textAlign: TextAlign.center), )), ], ), @@ -375,7 +377,8 @@ class _ImportExportPageState extends State { onPressed: importInProgress ? null : runObtainiumImport, - child: Text(tr('obtainiumImport')))), + child: Text(tr('obtainiumImport'), + textAlign: TextAlign.center))), ], ), if (snapshot.data != null) From cd316b71387a4ba254efc028f00ed17f8049d93f Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 17 Dec 2023 14:36:06 -0500 Subject: [PATCH 3/5] Always add Track-only apps with random ID (#1138) --- lib/providers/source_provider.dart | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index f8bc7a5..86ac8db 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -684,8 +684,9 @@ class SourceProvider { name = name.isNotEmpty ? name : apk.names.name; App finalApp = App( currentApp?.id ?? - ((!source.appIdInferIsOptional || - (source.appIdInferIsOptional && inferAppIdIfOptional)) + (!trackOnly && + (!source.appIdInferIsOptional || + (source.appIdInferIsOptional && inferAppIdIfOptional)) ? await source.tryInferringAppId(standardUrl, additionalSettings: additionalSettings) : null) ?? @@ -705,8 +706,9 @@ class SourceProvider { changeLog: apk.changeLog, overrideSource: overrideSource ?? currentApp?.overrideSource, allowIdChange: currentApp?.allowIdChange ?? - source.appIdInferIsOptional && - inferAppIdIfOptional // Optional ID inferring may be incorrect - allow correction on first install + trackOnly || + (source.appIdInferIsOptional && + inferAppIdIfOptional) // Optional ID inferring may be incorrect - allow correction on first install ); return source.endOfGetAppChanges(finalApp); } From fd59a93ede75dffde740b79d8a3c7ac17a922dd9 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 17 Dec 2023 14:47:22 -0500 Subject: [PATCH 4/5] Get real author name for F-Droid (#1076) --- lib/app_sources/fdroid.dart | 151 +++++++++++++++++-------------- lib/app_sources/izzyondroid.dart | 2 +- 2 files changed, 85 insertions(+), 68 deletions(-) diff --git a/lib/app_sources/fdroid.dart b/lib/app_sources/fdroid.dart index 8e33b41..2d7d7a1 100644 --- a/lib/app_sources/fdroid.dart +++ b/lib/app_sources/fdroid.dart @@ -65,7 +65,7 @@ class FDroid extends AppSource { ) async { String? appId = await tryInferringAppId(standardUrl); String host = Uri.parse(standardUrl).host; - return getAPKUrlsFromFDroidPackagesAPIResponse( + var details = getAPKUrlsFromFDroidPackagesAPIResponse( await sourceRequest('https://$host/api/v1/packages/$appId'), 'https://$host/repo/$appId', standardUrl, @@ -80,6 +80,23 @@ class FDroid extends AppSource { true ? additionalSettings['filterVersionsByRegEx'] : null); + if (!hostChanged) { + try { + var res = await sourceRequest( + 'https://gitlab.com/fdroid/fdroiddata/-/raw/master/metadata/$appId.yml'); + String author = res.body + .split('\n') + .where((l) => l.startsWith('AuthorName: ')) + .first + .split(': ') + .sublist(1) + .join(': '); + details.names.author = author; + } catch (e) { + // Fail silently + } + } + return details; } @override @@ -111,79 +128,79 @@ class FDroid extends AppSource { throw getObtainiumHttpError(res); } } -} -APKDetails getAPKUrlsFromFDroidPackagesAPIResponse( - Response res, String apkUrlPrefix, String standardUrl, String sourceName, - {bool autoSelectHighestVersionCode = false, - bool trySelectingSuggestedVersionCode = false, - String? filterVersionsByRegEx}) { - if (res.statusCode == 200) { - var response = jsonDecode(res.body); - List releases = response['packages'] ?? []; - if (releases.isEmpty) { - throw NoReleasesError(); - } - String? version; - Iterable releaseChoices = []; - // Grab the versionCode suggested if the user chose to do that - // Only do so at this stage if the user has no release filter - if (trySelectingSuggestedVersionCode && - response['suggestedVersionCode'] != null && - filterVersionsByRegEx == null) { - var suggestedReleases = releases.where((element) => - element['versionCode'] == response['suggestedVersionCode']); - if (suggestedReleases.isNotEmpty) { - releaseChoices = suggestedReleases; - version = suggestedReleases.first['versionName']; + APKDetails getAPKUrlsFromFDroidPackagesAPIResponse( + Response res, String apkUrlPrefix, String standardUrl, String sourceName, + {bool autoSelectHighestVersionCode = false, + bool trySelectingSuggestedVersionCode = false, + String? filterVersionsByRegEx}) { + if (res.statusCode == 200) { + var response = jsonDecode(res.body); + List releases = response['packages'] ?? []; + if (releases.isEmpty) { + throw NoReleasesError(); } - } - // Apply the release filter if any - if (filterVersionsByRegEx?.isNotEmpty == true) { - version = null; - releaseChoices = []; - for (var i = 0; i < releases.length; i++) { - if (RegExp(filterVersionsByRegEx!) - .hasMatch(releases[i]['versionName'])) { - version = releases[i]['versionName']; - } - } - if (version == null) { - throw NoVersionError(); - } - } - // Default to the highest version - version ??= releases[0]['versionName']; - if (version == null) { - throw NoVersionError(); - } - // If a suggested release was not already picked, pick all those with the selected version - if (releaseChoices.isEmpty) { - releaseChoices = - releases.where((element) => element['versionName'] == version); - } - // For the remaining releases, use the toggles to auto-select one if possible - if (releaseChoices.length > 1) { - if (autoSelectHighestVersionCode) { - releaseChoices = [releaseChoices.first]; - } else if (trySelectingSuggestedVersionCode && - response['suggestedVersionCode'] != null) { - var suggestedReleases = releaseChoices.where((element) => + String? version; + Iterable releaseChoices = []; + // Grab the versionCode suggested if the user chose to do that + // Only do so at this stage if the user has no release filter + if (trySelectingSuggestedVersionCode && + response['suggestedVersionCode'] != null && + filterVersionsByRegEx == null) { + var suggestedReleases = releases.where((element) => element['versionCode'] == response['suggestedVersionCode']); if (suggestedReleases.isNotEmpty) { releaseChoices = suggestedReleases; + version = suggestedReleases.first['versionName']; } } + // Apply the release filter if any + if (filterVersionsByRegEx?.isNotEmpty == true) { + version = null; + releaseChoices = []; + for (var i = 0; i < releases.length; i++) { + if (RegExp(filterVersionsByRegEx!) + .hasMatch(releases[i]['versionName'])) { + version = releases[i]['versionName']; + } + } + if (version == null) { + throw NoVersionError(); + } + } + // Default to the highest version + version ??= releases[0]['versionName']; + if (version == null) { + throw NoVersionError(); + } + // If a suggested release was not already picked, pick all those with the selected version + if (releaseChoices.isEmpty) { + releaseChoices = + releases.where((element) => element['versionName'] == version); + } + // For the remaining releases, use the toggles to auto-select one if possible + if (releaseChoices.length > 1) { + if (autoSelectHighestVersionCode) { + releaseChoices = [releaseChoices.first]; + } else if (trySelectingSuggestedVersionCode && + response['suggestedVersionCode'] != null) { + var suggestedReleases = releaseChoices.where((element) => + element['versionCode'] == response['suggestedVersionCode']); + if (suggestedReleases.isNotEmpty) { + releaseChoices = suggestedReleases; + } + } + } + if (releaseChoices.isEmpty) { + throw NoReleasesError(); + } + List apkUrls = releaseChoices + .map((e) => '${apkUrlPrefix}_${e['versionCode']}.apk') + .toList(); + return APKDetails(version, getApkUrlsFromUrls(apkUrls.toSet().toList()), + AppNames(sourceName, Uri.parse(standardUrl).pathSegments.last)); + } else { + throw getObtainiumHttpError(res); } - if (releaseChoices.isEmpty) { - throw NoReleasesError(); - } - List apkUrls = releaseChoices - .map((e) => '${apkUrlPrefix}_${e['versionCode']}.apk') - .toList(); - return APKDetails(version, getApkUrlsFromUrls(apkUrls.toSet().toList()), - AppNames(sourceName, Uri.parse(standardUrl).pathSegments.last)); - } else { - throw getObtainiumHttpError(res); } } diff --git a/lib/app_sources/izzyondroid.dart b/lib/app_sources/izzyondroid.dart index 66624bc..dd301b3 100644 --- a/lib/app_sources/izzyondroid.dart +++ b/lib/app_sources/izzyondroid.dart @@ -40,7 +40,7 @@ class IzzyOnDroid extends AppSource { Map additionalSettings, ) async { String? appId = await tryInferringAppId(standardUrl); - return getAPKUrlsFromFDroidPackagesAPIResponse( + return fd.getAPKUrlsFromFDroidPackagesAPIResponse( await sourceRequest( 'https://apt.izzysoft.de/fdroid/api/v1/packages/$appId'), 'https://android.izzysoft.de/frepo/$appId', From 5477b3f93694afad3dcf89f27ff3c51e1b46d205 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Sun, 17 Dec 2023 14:54:54 -0500 Subject: [PATCH 5/5] Update packages, increment version, run dart fix --- lib/main.dart | 2 +- lib/providers/apps_provider.dart | 2 +- pubspec.lock | 4 ++-- pubspec.yaml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 824818e..620f4bd 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -19,7 +19,7 @@ import 'package:easy_localization/src/easy_localization_controller.dart'; // ignore: implementation_imports import 'package:easy_localization/src/localization.dart'; -const String currentVersion = '0.14.37'; +const String currentVersion = '0.14.38'; const String currentReleaseTag = 'v$currentVersion-beta'; // KEEP THIS IN SYNC WITH GITHUB RELEASES diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index e76c1fd..35fbfcc 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -1230,7 +1230,7 @@ class AppsProvider with ChangeNotifier { Future> import(String appsJSON) async { var decodedJSON = jsonDecode(appsJSON); - var newFormat = !(decodedJSON is List); + var newFormat = decodedJSON is! List; List importedApps = ((newFormat ? decodedJSON['apps'] : decodedJSON) as List) .map((e) => App.fromJson(e)) diff --git a/pubspec.lock b/pubspec.lock index 72e6244..a84bba6 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -783,10 +783,10 @@ packages: dependency: transitive description: name: synchronized - sha256: "5fcbd27688af6082f5abd611af56ee575342c30e87541d0245f7ff99faa02c60" + sha256: "539ef412b170d65ecdafd780f924e5be3f60032a1128df156adad6c5b373d558" url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "3.1.0+1" term_glyph: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 79739f3..f4b095a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 0.14.37+231 # When changing this, update the tag in main() accordingly +version: 0.14.38+232 # When changing this, update the tag in main() accordingly environment: sdk: '>=3.0.0 <4.0.0'