From 71cc49a30f0453d861e490b8cf8a49c6fab697e0 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Mon, 5 Aug 2024 15:53:44 -0400 Subject: [PATCH 1/6] APKPure: Filter releases by available architecture (#598) --- lib/app_sources/apkpure.dart | 132 +++++++++++++++++++++++++--------- lib/app_sources/html.dart | 136 +++++++++++++++++------------------ 2 files changed, 165 insertions(+), 103 deletions(-) diff --git a/lib/app_sources/apkpure.dart b/lib/app_sources/apkpure.dart index 715a8d3..8f53912 100644 --- a/lib/app_sources/apkpure.dart +++ b/lib/app_sources/apkpure.dart @@ -1,5 +1,7 @@ +import 'package:device_info_plus/device_info_plus.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:html/parser.dart'; +import 'package:obtainium/app_sources/html.dart'; import 'package:obtainium/custom_errors.dart'; import 'package:obtainium/providers/source_provider.dart'; @@ -58,40 +60,102 @@ class APKPure extends AppSource { ) async { String appId = (await tryInferringAppId(standardUrl))!; String host = Uri.parse(standardUrl).host; - var res = await sourceRequest('$standardUrl/download', additionalSettings); - var resChangelog = await sourceRequest(standardUrl, additionalSettings); - if (res.statusCode == 200 && resChangelog.statusCode == 200) { - var html = parse(res.body); - var htmlChangelog = parse(resChangelog.body); - String? version = html.querySelector('span.info-sdk span')?.text.trim(); - if (version == null) { - throw NoVersionError(); - } - String? dateString = - html.querySelector('span.info-other span.date')?.text.trim(); - DateTime? releaseDate = parseDateTimeMMMddCommayyyy(dateString); - String type = html.querySelector('a.info-tag')?.text.trim() ?? 'APK'; - List> apkUrls = [ - MapEntry('$appId.apk', - 'https://d.${hosts.contains(host) ? 'cdnpure.com' : host}/b/$type/$appId?version=latest') - ]; - String author = html - .querySelector('span.info-sdk') - ?.text - .trim() - .substring(version.length + 4) ?? - Uri.parse(standardUrl).pathSegments.reversed.last; - String appName = - html.querySelector('h1.info-title')?.text.trim() ?? appId; - String? changeLog = htmlChangelog - .querySelector("div.whats-new-info p:not(.date)") - ?.innerHtml - .trim() - .replaceAll("
", " \n"); - return APKDetails(version, apkUrls, AppNames(author, appName), - releaseDate: releaseDate, changeLog: changeLog); - } else { - throw getObtainiumHttpError(res); + + var res0 = await sourceRequest('$standardUrl/versions', additionalSettings); + var versionLinks = await grabLinksCommon(res0, { + 'skipSort': true, + 'customLinkFilterRegex': '$standardUrl/download/[^/]+\$' + }); + + // if (versionLinks.length > 7) { + // // Returns up to 30 which is too much - would take too long and possibly get blocked/rate-limited + // versionLinks = versionLinks.sublist(0, 7); + // } + + var supportedArchs = (await DeviceInfoPlugin().androidInfo).supportedAbis; + + if (additionalSettings['autoApkFilterByArch'] != true) { + // No need to request multiple versions when we're not going to filter them (always pick the top one) + versionLinks = versionLinks.sublist(0, 1); } + if (versionLinks.isEmpty) { + throw NoReleasesError(); + } + + List versionDetails = + (await Future.wait(versionLinks.map((link) async { + var res = await sourceRequest(link.key, additionalSettings); + if (res.statusCode == 200) { + var html = parse(res.body); + var apksDiv = + html.querySelector('#version-list div div.show-more-content'); + DateTime? topReleaseDate; + var apkUrls = apksDiv + ?.querySelectorAll('div.group-title') + .map((e) { + String? architecture = e.text.trim(); + // Only take the first APK for each architecture, ignore others for now, for simplicity + // Unclear why there can even be multiple APKs for the same version and arch + var apkInfo = e.nextElementSibling?.querySelector('div.info'); + String? versionCode = RegExp('[0-9]+') + .firstMatch(apkInfo + ?.querySelector('div.info-top span.code') + ?.text ?? + '') + ?.group(0) + ?.trim(); + String? type = apkInfo + ?.querySelector('div.info-top span.tag') + ?.text + .trim() ?? + 'APK'; + String? dateString = apkInfo + ?.querySelector('div.info-bottom span.time') + ?.text + .trim(); + DateTime? releaseDate = + parseDateTimeMMMddCommayyyy(dateString); + if (additionalSettings['autoApkFilterByArch'] == true && + !supportedArchs.contains(architecture)) { + return const MapEntry('', ''); + } + topReleaseDate ??= + releaseDate; // Just use the release date of the first APK in the list as the release date for this version + return MapEntry( + '$appId-$versionCode-$architecture.${type.toLowerCase()}', + 'https://d.${hosts.contains(host) ? 'cdnpure.com' : host}/b/$type/$appId?versionCode=$versionCode'); + }) + .where((e) => e.key.isNotEmpty) + .toList() ?? + []; + if (apkUrls.isEmpty) { + return null; + } + String version = Uri.parse(link.key).pathSegments.last; + String author = html + .querySelector('span.info-sdk') + ?.text + .trim() + .substring(version.length + 4) ?? + Uri.parse(standardUrl).pathSegments.reversed.last; + String appName = + html.querySelector('h1.info-title')?.text.trim() ?? appId; + String? changeLog = html + .querySelector('div.module.change-log') + ?.innerHtml + .trim() + .replaceAll("
", " \n"); + return APKDetails(version, apkUrls, AppNames(author, appName), + releaseDate: topReleaseDate, changeLog: changeLog); + } else { + throw getObtainiumHttpError(res); + } + }))) + .where((e) => e != null) + .toList(); + if (versionDetails.isEmpty) { + throw NoAPKError(); + } + return versionDetails[0]!; } } diff --git a/lib/app_sources/html.dart b/lib/app_sources/html.dart index e94e200..46f5a65 100644 --- a/lib/app_sources/html.dart +++ b/lib/app_sources/html.dart @@ -92,6 +92,73 @@ bool _isNumeric(String s) { return s.codeUnitAt(0) >= 48 && s.codeUnitAt(0) <= 57; } +// Given an HTTP response, grab some links according to the common additional settings +// (those that apply to intermediate and final steps) +Future>> grabLinksCommon( + Response res, Map additionalSettings) async { + if (res.statusCode != 200) { + throw getObtainiumHttpError(res); + } + var html = parse(res.body); + List> allLinks = html + .querySelectorAll('a') + .map((element) => MapEntry( + element.attributes['href'] ?? '', + element.text.isNotEmpty + ? element.text + : (element.attributes['href'] ?? '').split('/').last)) + .where((element) => element.key.isNotEmpty) + .map((e) => MapEntry(ensureAbsoluteUrl(e.key, res.request!.url), e.value)) + .toList(); + if (allLinks.isEmpty) { + allLinks = RegExp( + r'(http|ftp|https)://([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:/~+#-]*[\w@?^=%&/~+#-])?') + .allMatches(res.body) + .map((match) => + MapEntry(match.group(0)!, match.group(0)?.split('/').last ?? '')) + .toList(); + } + List> links = []; + bool skipSort = additionalSettings['skipSort'] == true; + bool filterLinkByText = additionalSettings['filterByLinkText'] == true; + if ((additionalSettings['customLinkFilterRegex'] as String?)?.isNotEmpty == + true) { + var reg = RegExp(additionalSettings['customLinkFilterRegex']); + links = allLinks.where((element) { + var link = element.key; + try { + link = Uri.decodeFull(element.key); + } catch (e) { + // Some links may not have valid encoding + } + return reg.hasMatch(filterLinkByText ? element.value : link); + }).toList(); + } else { + links = allLinks.where((element) { + var link = element.key; + try { + link = Uri.decodeFull(element.key); + } catch (e) { + // Some links may not have valid encoding + } + return Uri.parse(filterLinkByText ? element.value : link) + .path + .toLowerCase() + .endsWith('.apk'); + }).toList(); + } + if (!skipSort) { + links.sort((a, b) => additionalSettings['sortByLastLinkSegment'] == true + ? compareAlphaNumeric(a.key.split('/').where((e) => e.isNotEmpty).last, + b.key.split('/').where((e) => e.isNotEmpty).last) + : compareAlphaNumeric(a.key, b.key)); + } + if (additionalSettings['reverseSort'] == true) { + links = links.reversed.toList(); + } + return links; +} + class HTML extends AppSource { @override List> get combinedAppSpecificSettingFormItems { @@ -225,75 +292,6 @@ class HTML extends AppSource { return url; } - // Given an HTTP response, grab some links according to the common additional settings - // (those that apply to intermediate and final steps) - Future>> grabLinksCommon( - Response res, Map additionalSettings) async { - if (res.statusCode != 200) { - throw getObtainiumHttpError(res); - } - var html = parse(res.body); - List> allLinks = html - .querySelectorAll('a') - .map((element) => MapEntry( - element.attributes['href'] ?? '', - element.text.isNotEmpty - ? element.text - : (element.attributes['href'] ?? '').split('/').last)) - .where((element) => element.key.isNotEmpty) - .map((e) => - MapEntry(ensureAbsoluteUrl(e.key, res.request!.url), e.value)) - .toList(); - if (allLinks.isEmpty) { - allLinks = RegExp( - r'(http|ftp|https)://([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:/~+#-]*[\w@?^=%&/~+#-])?') - .allMatches(res.body) - .map((match) => - MapEntry(match.group(0)!, match.group(0)?.split('/').last ?? '')) - .toList(); - } - List> links = []; - bool skipSort = additionalSettings['skipSort'] == true; - bool filterLinkByText = additionalSettings['filterByLinkText'] == true; - if ((additionalSettings['customLinkFilterRegex'] as String?)?.isNotEmpty == - true) { - var reg = RegExp(additionalSettings['customLinkFilterRegex']); - links = allLinks.where((element) { - var link = element.key; - try { - link = Uri.decodeFull(element.key); - } catch (e) { - // Some links may not have valid encoding - } - return reg.hasMatch(filterLinkByText ? element.value : link); - }).toList(); - } else { - links = allLinks.where((element) { - var link = element.key; - try { - link = Uri.decodeFull(element.key); - } catch (e) { - // Some links may not have valid encoding - } - return Uri.parse(filterLinkByText ? element.value : link) - .path - .toLowerCase() - .endsWith('.apk'); - }).toList(); - } - if (!skipSort) { - links.sort((a, b) => additionalSettings['sortByLastLinkSegment'] == true - ? compareAlphaNumeric( - a.key.split('/').where((e) => e.isNotEmpty).last, - b.key.split('/').where((e) => e.isNotEmpty).last) - : compareAlphaNumeric(a.key, b.key)); - } - if (additionalSettings['reverseSort'] == true) { - links = links.reversed.toList(); - } - return links; - } - @override Future getLatestAPKDetails( String standardUrl, From fd384448368e3a9f1095e3e41a9b12c672c83555 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Mon, 5 Aug 2024 16:08:12 -0400 Subject: [PATCH 2/6] Improvement on previous commit --- lib/app_sources/apkpure.dart | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/lib/app_sources/apkpure.dart b/lib/app_sources/apkpure.dart index 8f53912..4480926 100644 --- a/lib/app_sources/apkpure.dart +++ b/lib/app_sources/apkpure.dart @@ -82,8 +82,8 @@ class APKPure extends AppSource { throw NoReleasesError(); } - List versionDetails = - (await Future.wait(versionLinks.map((link) async { + for (var i = 0; i < versionLinks.length; i++) { + var link = versionLinks[i]; var res = await sourceRequest(link.key, additionalSettings); if (res.statusCode == 200) { var html = parse(res.body); @@ -129,7 +129,7 @@ class APKPure extends AppSource { .toList() ?? []; if (apkUrls.isEmpty) { - return null; + continue; } String version = Uri.parse(link.key).pathSegments.last; String author = html @@ -150,12 +150,7 @@ class APKPure extends AppSource { } else { throw getObtainiumHttpError(res); } - }))) - .where((e) => e != null) - .toList(); - if (versionDetails.isEmpty) { - throw NoAPKError(); } - return versionDetails[0]!; + throw NoAPKError(); } } From 62dbffab521655be1cac1100aef52c0709a94810 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Mon, 5 Aug 2024 16:21:42 -0400 Subject: [PATCH 3/6] Use a more obvious icon (magnifying glass) for the "filter apps" button (#1762) --- lib/pages/apps.dart | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index 6ef26ab..d2086c9 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -1077,7 +1077,9 @@ class AppsPageState extends State { IconButton( color: Theme.of(context).colorScheme.primary, style: const ButtonStyle(visualDensity: VisualDensity.compact), - tooltip: '${tr('filter')}${isFilterOff ? '' : ' *'}', + tooltip: isFilterOff + ? tr('filterApps') + : '${tr('filter')} - ${tr('remove')}', onPressed: isFilterOff ? showFilterDialog : () { @@ -1086,8 +1088,8 @@ class AppsPageState extends State { }); }, icon: Icon(isFilterOff - ? Icons.filter_list_rounded - : Icons.filter_list_off_rounded)), + ? Icons.search_rounded + : Icons.search_off_rounded)), const SizedBox( width: 10, ), From aa00f42a23f883d437748091ac7f17684ac46065 Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Mon, 5 Aug 2024 16:24:30 -0400 Subject: [PATCH 4/6] Update packages, increment version --- pubspec.lock | 112 +++++++++++++++++++++++++-------------------------- pubspec.yaml | 6 +-- 2 files changed, 59 insertions(+), 59 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index c8f981f..31cf5a3 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,10 +5,10 @@ packages: dependency: "direct main" description: name: android_intent_plus - sha256: "2bfdbee8d65e7c26f88b66f0a91f2863da4d3596d8a658b4162c8de5cf04b074" + sha256: "007703c1b2cac7ca98add3336b98cffa4baa11d5133cc463293dba9daa39cdf6" url: "https://pub.dev" source: hosted - version: "5.0.2" + version: "5.1.0" android_package_installer: dependency: "direct main" description: @@ -71,10 +71,10 @@ packages: dependency: transitive description: name: app_links_web - sha256: "74586ed5f3c4786341e82a0fa43c39ec3f13108a550f74e80d8bf68aa11349d1" + sha256: af060ed76183f9e2b87510a9480e56a5352b6c249778d07bd2c95fc35632a555 url: "https://pub.dev" source: hosted - version: "1.0.3" + version: "1.0.4" archive: dependency: transitive description: @@ -159,26 +159,26 @@ packages: dependency: "direct main" description: name: connectivity_plus - sha256: db7a4e143dc72cc3cb2044ef9b052a7ebfe729513e6a82943bc3526f784365b8 + sha256: "3e7d1d9dbae40ae82cbe6c23c518f0c4ffe32764ee9749b9a99d32cbac8734f6" url: "https://pub.dev" source: hosted - version: "6.0.3" + version: "6.0.4" connectivity_plus_platform_interface: dependency: transitive description: name: connectivity_plus_platform_interface - sha256: b6a56efe1e6675be240de39107281d4034b64ac23438026355b4234042a35adb + sha256: "42657c1715d48b167930d5f34d00222ac100475f73d10162ddf43e714932f204" url: "https://pub.dev" source: hosted - version: "2.0.0" + version: "2.0.1" cross_file: dependency: transitive description: name: cross_file - sha256: "55d7b444feb71301ef6b8838dbc1ae02e63dd48c8773f3810ff53bb1e2945b32" + sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670" url: "https://pub.dev" source: hosted - version: "0.3.4+1" + version: "0.3.4+2" crypto: dependency: "direct main" description: @@ -215,18 +215,18 @@ packages: dependency: "direct main" description: name: device_info_plus - sha256: eead12d1a1ed83d8283ab4c2f3fca23ac4082f29f25f29dff0f758f57d06ec91 + sha256: "93429694c9253d2871b3af80cf11b3cbb5c65660d402ed7bf69854ce4a089f82" url: "https://pub.dev" source: hosted - version: "10.1.0" + version: "10.1.1" device_info_plus_platform_interface: dependency: transitive description: name: device_info_plus_platform_interface - sha256: d3b01d5868b50ae571cd1dc6e502fc94d956b665756180f7b16ead09e836fd64 + sha256: "282d3cf731045a2feb66abfe61bbc40870ae50a3ed10a4d3d217556c35c8c2ba" url: "https://pub.dev" source: hosted - version: "7.0.0" + version: "7.0.1" dynamic_color: dependency: "direct main" description: @@ -332,10 +332,10 @@ packages: dependency: "direct main" description: name: flutter_fgbg - sha256: "08c4d2fd229e3df26083d5aecc3dea9ff4f2d188f8cd57aaf2b3f047bd08a047" + sha256: "5e61a2ff2e2e83614ae7690bea3dfa74bbd91b5c083e81ce07692411ce65e3d7" url: "https://pub.dev" source: hosted - version: "0.3.0" + version: "0.4.0" flutter_keyboard_visibility: dependency: transitive description: @@ -475,10 +475,10 @@ packages: dependency: transitive description: name: fraction - sha256: "09e9504c9177bbd77df56e5d147abfbb3b43360e64bf61510059c14d6a82d524" + sha256: ac0d9904bb8211eb28606bdf623ff9f222c53240d8e9b927a07c149d356eddc2 url: "https://pub.dev" source: hosted - version: "5.0.2" + version: "5.0.3" gtk: dependency: transitive description: @@ -643,18 +643,18 @@ packages: dependency: "direct main" description: name: path_provider - sha256: c9e7d3a4cd1410877472158bee69963a4579f78b68c65a2b7d40d1a7a88bb161 + sha256: fec0d61223fba3154d87759e3cc27fe2c8dc498f6386c6d6fc80d1afdd1bf378 url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "2.1.4" path_provider_android: dependency: transitive description: name: path_provider_android - sha256: e84c8a53fe1510ef4582f118c7b4bdf15b03002b51d7c2b66983c65843d61193 + sha256: "490539678396d4c3c0b06efdaab75ae60675c3e0c66f72bc04c2e2c1e0e2abeb" url: "https://pub.dev" source: hosted - version: "2.2.8" + version: "2.2.9" path_provider_foundation: dependency: transitive description: @@ -699,10 +699,10 @@ packages: dependency: transitive description: name: permission_handler_android - sha256: b29a799ca03be9f999aa6c39f7de5209482d638e6f857f6b93b0875c618b7e54 + sha256: eaf2a1ec4472775451e88ca6a7b86559ef2f1d1ed903942ed135e38ea0097dca url: "https://pub.dev" source: hosted - version: "12.0.7" + version: "12.0.8" permission_handler_apple: dependency: transitive description: @@ -723,10 +723,10 @@ packages: dependency: transitive description: name: permission_handler_platform_interface - sha256: "48d4fcf201a1dad93ee869ab0d4101d084f49136ec82a8a06ed9cfeacab9fd20" + sha256: fe0ffe274d665be8e34f9c59705441a7d248edebbe5d9e3ec2665f88b79358ea url: "https://pub.dev" source: hosted - version: "4.2.1" + version: "4.2.2" permission_handler_windows: dependency: transitive description: @@ -763,10 +763,10 @@ packages: dependency: transitive description: name: pointer_interceptor - sha256: d0a8e660d1204eaec5bd34b34cc92174690e076d2e4f893d9d68c486a13b07c4 + sha256: "57210410680379aea8b1b7ed6ae0c3ad349bfd56fe845b8ea934a53344b9d523" url: "https://pub.dev" source: hosted - version: "0.10.1+1" + version: "0.10.1+2" pointer_interceptor_ios: dependency: transitive description: @@ -787,10 +787,10 @@ packages: dependency: transitive description: name: pointer_interceptor_web - sha256: a6237528b46c411d8d55cdfad8fcb3269fc4cbb26060b14bff94879165887d1e + sha256: "7a7087782110f8c1827170660b09f8aa893e0e9a61431dbbe2ac3fc482e8c044" url: "https://pub.dev" source: hosted - version: "0.10.2" + version: "0.10.2+1" provider: dependency: "direct main" description: @@ -803,74 +803,74 @@ packages: dependency: "direct main" description: name: share_plus - sha256: ef3489a969683c4f3d0239010cc8b7a2a46543a8d139e111c06c558875083544 + sha256: "59dfd53f497340a0c3a81909b220cfdb9b8973a91055c4e5ab9b9b9ad7c513c0" url: "https://pub.dev" source: hosted - version: "9.0.0" + version: "10.0.0" share_plus_platform_interface: dependency: transitive description: name: share_plus_platform_interface - sha256: "0f9e4418835d1b2c3ae78fdb918251959106cefdbc4dd43526e182f80e82f6d4" + sha256: "6ababf341050edff57da8b6990f11f4e99eaba837865e2e6defe16d039619db5" url: "https://pub.dev" source: hosted - version: "4.0.0" + version: "5.0.0" shared_preferences: dependency: "direct main" description: name: shared_preferences - sha256: d3bbe5553a986e83980916ded2f0b435ef2e1893dfaa29d5a7a790d0eca12180 + sha256: c272f9cabca5a81adc9b0894381e9c1def363e980f960fa903c604c471b22f68 url: "https://pub.dev" source: hosted - version: "2.2.3" + version: "2.3.1" shared_preferences_android: dependency: transitive description: name: shared_preferences_android - sha256: "3d4571b3c5eb58ce52a419d86e655493d0bc3020672da79f72fa0c16ca3a8ec1" + sha256: "041be4d9d2dc6079cf342bc8b761b03787e3b71192d658220a56cac9c04a0294" url: "https://pub.dev" source: hosted - version: "2.2.4" + version: "2.3.0" shared_preferences_foundation: dependency: transitive description: name: shared_preferences_foundation - sha256: "0a8a893bf4fd1152f93fec03a415d11c27c74454d96e2318a7ac38dd18683ab7" + sha256: "671e7a931f55a08aa45be2a13fe7247f2a41237897df434b30d2012388191833" url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.5.0" shared_preferences_linux: dependency: transitive description: name: shared_preferences_linux - sha256: "9f2cbcf46d4270ea8be39fa156d86379077c8a5228d9dfdb1164ae0bb93f1faa" + sha256: "2ba0510d3017f91655b7543e9ee46d48619de2a2af38e5c790423f7007c7ccc1" url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.4.0" shared_preferences_platform_interface: dependency: transitive description: name: shared_preferences_platform_interface - sha256: "034650b71e73629ca08a0bd789fd1d83cc63c2d1e405946f7cef7bc37432f93a" + sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80" url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.4.1" shared_preferences_web: dependency: transitive description: name: shared_preferences_web - sha256: "9aee1089b36bd2aafe06582b7d7817fd317ef05fc30e6ba14bff247d0933042a" + sha256: "59dc807b94d29d52ddbb1b3c0d3b9d0a67fc535a64e62a5542c8db0513fcb6c2" url: "https://pub.dev" source: hosted - version: "2.3.0" + version: "2.4.1" shared_preferences_windows: dependency: transitive description: name: shared_preferences_windows - sha256: "841ad54f3c8381c480d0c9b508b89a34036f512482c407e6df7a9c4aa2ef8f59" + sha256: "398084b47b7f92110683cac45c6dc4aae853db47e470e5ddcd52cab7f7196ab2" url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "2.4.0" shared_storage: dependency: "direct main" description: @@ -1001,10 +1001,10 @@ packages: dependency: transitive description: name: url_launcher_android - sha256: c24484594a8dea685610569ab0f2547de9c7a1907500a9bc5e37e4c9a3cbfb23 + sha256: "94d8ad05f44c6d4e2ffe5567ab4d741b82d62e3c8e288cc1fcea45965edf47c9" url: "https://pub.dev" source: hosted - version: "6.3.6" + version: "6.3.8" url_launcher_ios: dependency: transitive description: @@ -1041,10 +1041,10 @@ packages: dependency: transitive description: name: url_launcher_web - sha256: "8d9e750d8c9338601e709cd0885f95825086bd8b642547f26bda435aade95d8a" + sha256: a36e2d7981122fa185006b216eb6b5b97ede3f9a54b7a511bc966971ab98d049 url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.3.2" url_launcher_windows: dependency: transitive description: @@ -1097,10 +1097,10 @@ packages: dependency: transitive description: name: webview_flutter_android - sha256: "060e1a621add859dc822f3e4c59b01468e8515ea78cfc5ac4c6b28bc903b5f74" + sha256: c66651fba15f9d7ddd31daec42da8d6bce46c85610a7127e3ebcb39a4395c3c9 url: "https://pub.dev" source: hosted - version: "3.16.5" + version: "3.16.6" webview_flutter_platform_interface: dependency: transitive description: @@ -1121,10 +1121,10 @@ packages: dependency: transitive description: name: win32 - sha256: a79dbe579cb51ecd6d30b17e0cae4e0ea15e2c0e66f69ad4198f22a6789e94f4 + sha256: "015002c060f1ae9f41a818f2d5640389cc05283e368be19dc8d77cecb43c40c9" url: "https://pub.dev" source: hosted - version: "5.5.1" + version: "5.5.3" win32_registry: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 2136551..6732129 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: 1.1.15+2272 +version: 1.1.16+2273 environment: sdk: '>=3.0.0 <4.0.0' @@ -37,7 +37,7 @@ dependencies: # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.5 path_provider: ^2.0.11 - flutter_fgbg: ^0.3.0 # Try removing reliance on this + flutter_fgbg: ^0.4.0 flutter_local_notifications: ^17.0.0 provider: ^6.0.3 http: ^1.0.0 @@ -56,7 +56,7 @@ dependencies: url: https://github.com/ImranR98/android_package_installer ref: main android_package_manager: ^0.7.0 - share_plus: ^9.0.0 + share_plus: ^10.0.0 sqflite: ^2.2.0+3 easy_localization: ^3.0.1 android_intent_plus: ^5.0.1 From 325d2f48dce50d26afa2520b84ecf357f206bb6f Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Mon, 5 Aug 2024 16:25:02 -0400 Subject: [PATCH 5/6] More consistent tagline --- README.md | 2 +- pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9102a86..712520f 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Ceasefire Now](https://badge.techforpalestine.org/default)](https://techforpalestine.org/learn-more) -Get Android App Updates Directly From the Source. +Get Android app updates straight from the source. Obtainium allows you to install and update apps directly from their releases pages, and receive notifications when new releases are made available. diff --git a/pubspec.yaml b/pubspec.yaml index 6732129..a282f93 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: obtainium -description: Get Android App Updates Directly From the Source. +description: Get Android app updates straight from the source. # The following line prevents the package from being accidentally published to # pub.dev using `flutter pub publish`. This is preferred for private packages. From adc4e7c2b4f9b21a11dea674e1c918b67591628c Mon Sep 17 00:00:00 2001 From: Imran Remtulla Date: Mon, 5 Aug 2024 16:30:12 -0400 Subject: [PATCH 6/6] Fix error after fgbg package update in previous commit --- lib/providers/apps_provider.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/providers/apps_provider.dart b/lib/providers/apps_provider.dart index e3b9595..8e8dfa9 100644 --- a/lib/providers/apps_provider.dart +++ b/lib/providers/apps_provider.dart @@ -367,7 +367,7 @@ class AppsProvider with ChangeNotifier { AppsProvider({isBg = false}) { // Subscribe to changes in the app foreground status - foregroundStream = FGBGEvents.stream.asBroadcastStream(); + foregroundStream = FGBGEvents.instance.stream.asBroadcastStream(); foregroundSubscription = foregroundStream?.listen((event) async { isForeground = event == FGBGType.foreground; if (isForeground) { @@ -572,7 +572,7 @@ class AppsProvider with ChangeNotifier { if (!isForeground) { await notificationsProvider.notify(completeInstallationNotification, cancelExisting: true); - while (await FGBGEvents.stream.first != FGBGType.foreground) {} + while (await FGBGEvents.instance.stream.first != FGBGType.foreground) {} await notificationsProvider.cancel(completeInstallationNotification.id); } }