Merge pull request #1770 from ImranR98/dev

- APKPure: Filter releases by available architecture (#598)
- Use a more obvious icon (magnifying glass) for the "filter apps" button (#1762)
This commit is contained in:
Imran
2024-08-05 16:33:29 -04:00
committed by GitHub
7 changed files with 228 additions and 169 deletions

View File

@@ -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.

View File

@@ -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,97 @@ 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<MapEntry<String, String>> 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("<br>", " \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();
}
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);
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) {
continue;
}
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("<br>", " \n");
return APKDetails(version, apkUrls, AppNames(author, appName),
releaseDate: topReleaseDate, changeLog: changeLog);
} else {
throw getObtainiumHttpError(res);
}
}
throw NoAPKError();
}
}

View File

@@ -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<List<MapEntry<String, String>>> grabLinksCommon(
Response res, Map<String, dynamic> additionalSettings) async {
if (res.statusCode != 200) {
throw getObtainiumHttpError(res);
}
var html = parse(res.body);
List<MapEntry<String, String>> 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<MapEntry<String, String>> 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<List<GeneratedFormItem>> 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<List<MapEntry<String, String>>> grabLinksCommon(
Response res, Map<String, dynamic> additionalSettings) async {
if (res.statusCode != 200) {
throw getObtainiumHttpError(res);
}
var html = parse(res.body);
List<MapEntry<String, String>> 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<MapEntry<String, String>> 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<APKDetails> getLatestAPKDetails(
String standardUrl,

View File

@@ -1077,7 +1077,9 @@ class AppsPageState extends State<AppsPage> {
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<AppsPage> {
});
},
icon: Icon(isFilterOff
? Icons.filter_list_rounded
: Icons.filter_list_off_rounded)),
? Icons.search_rounded
: Icons.search_off_rounded)),
const SizedBox(
width: 10,
),

View File

@@ -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);
}
}

View File

@@ -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:

View File

@@ -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.
@@ -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