mirror of
https://github.com/ImranR98/Obtainium.git
synced 2025-07-24 18:09:42 +02:00
Compare commits
6 Commits
v0.14.37-b
...
v0.14.38-b
Author | SHA1 | Date | |
---|---|---|---|
|
cbaaec961c | ||
|
5477b3f936 | ||
|
fd59a93ede | ||
|
cd316b7138 | ||
|
d1955192ed | ||
|
9beb839bf4 |
@@ -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<dynamic> releases = response['packages'] ?? [];
|
||||
if (releases.isEmpty) {
|
||||
throw NoReleasesError();
|
||||
}
|
||||
String? version;
|
||||
Iterable<dynamic> 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<dynamic> 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<dynamic> 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<String> 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<String> 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);
|
||||
}
|
||||
}
|
||||
|
@@ -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<dynamic>;
|
||||
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<MapEntry<String, String>> getReleaseAPKUrls(dynamic release) =>
|
||||
(release['assets'] as List<dynamic>?)
|
||||
@@ -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));
|
||||
}
|
||||
|
@@ -40,7 +40,7 @@ class IzzyOnDroid extends AppSource {
|
||||
Map<String, dynamic> 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',
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -347,7 +347,8 @@ class _ImportExportPageState extends State<ImportExportPage> {
|
||||
: () {
|
||||
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<ImportExportPage> {
|
||||
snapshot.data == null
|
||||
? null
|
||||
: runObtainiumExport,
|
||||
child: Text(tr('obtainiumExport')),
|
||||
child: Text(tr('obtainiumExport'),
|
||||
textAlign: TextAlign.center),
|
||||
)),
|
||||
],
|
||||
),
|
||||
@@ -375,7 +377,8 @@ class _ImportExportPageState extends State<ImportExportPage> {
|
||||
onPressed: importInProgress
|
||||
? null
|
||||
: runObtainiumImport,
|
||||
child: Text(tr('obtainiumImport')))),
|
||||
child: Text(tr('obtainiumImport'),
|
||||
textAlign: TextAlign.center))),
|
||||
],
|
||||
),
|
||||
if (snapshot.data != null)
|
||||
|
@@ -1230,7 +1230,7 @@ class AppsProvider with ChangeNotifier {
|
||||
|
||||
Future<MapEntry<int, bool>> import(String appsJSON) async {
|
||||
var decodedJSON = jsonDecode(appsJSON);
|
||||
var newFormat = !(decodedJSON is List);
|
||||
var newFormat = decodedJSON is! List;
|
||||
List<App> importedApps =
|
||||
((newFormat ? decodedJSON['apps'] : decodedJSON) as List<dynamic>)
|
||||
.map((e) => App.fromJson(e))
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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:
|
||||
|
@@ -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'
|
||||
|
Reference in New Issue
Block a user