mirror of
https://github.com/ImranR98/Obtainium.git
synced 2025-07-16 14:46:44 +02:00
Progress
This commit is contained in:
@ -25,8 +25,9 @@ class APKMirror extends AppSource {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<APKDetails> getLatestAPKDetails(
|
Future<APKDetails> getLatestAPKDetails(
|
||||||
String standardUrl, Map<String, String> additionalData,
|
String standardUrl,
|
||||||
{bool trackOnly = false}) async {
|
Map<String, String> additionalSettings,
|
||||||
|
) async {
|
||||||
Response res = await get(Uri.parse('$standardUrl/feed'));
|
Response res = await get(Uri.parse('$standardUrl/feed'));
|
||||||
if (res.statusCode == 200) {
|
if (res.statusCode == 200) {
|
||||||
String? titleString = parse(res.body)
|
String? titleString = parse(res.body)
|
||||||
|
@ -32,7 +32,7 @@ class FDroid extends AppSource {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String? tryInferringAppId(String standardUrl,
|
String? tryInferringAppId(String standardUrl,
|
||||||
{Map<String, String> additionalData = const {}}) {
|
{Map<String, String> additionalSettings = const {}}) {
|
||||||
return Uri.parse(standardUrl).pathSegments.last;
|
return Uri.parse(standardUrl).pathSegments.last;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,8 +60,9 @@ class FDroid extends AppSource {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<APKDetails> getLatestAPKDetails(
|
Future<APKDetails> getLatestAPKDetails(
|
||||||
String standardUrl, Map<String, String> additionalData,
|
String standardUrl,
|
||||||
{bool trackOnly = false}) async {
|
Map<String, String> additionalSettings,
|
||||||
|
) async {
|
||||||
String? appId = tryInferringAppId(standardUrl);
|
String? appId = tryInferringAppId(standardUrl);
|
||||||
return getAPKUrlsFromFDroidPackagesAPIResponse(
|
return getAPKUrlsFromFDroidPackagesAPIResponse(
|
||||||
await get(Uri.parse('https://f-droid.org/api/v1/packages/$appId')),
|
await get(Uri.parse('https://f-droid.org/api/v1/packages/$appId')),
|
||||||
|
@ -9,7 +9,7 @@ class FDroidRepo extends AppSource {
|
|||||||
FDroidRepo() {
|
FDroidRepo() {
|
||||||
name = tr('fdroidThirdPartyRepo');
|
name = tr('fdroidThirdPartyRepo');
|
||||||
|
|
||||||
additionalSourceAppSpecificFormItems = [
|
additionalSourceAppSpecificSettingFormItems = [
|
||||||
[
|
[
|
||||||
GeneratedFormItem('appIdOrName',
|
GeneratedFormItem('appIdOrName',
|
||||||
label: tr('appIdOrName'),
|
label: tr('appIdOrName'),
|
||||||
@ -32,9 +32,10 @@ class FDroidRepo extends AppSource {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<APKDetails> getLatestAPKDetails(
|
Future<APKDetails> getLatestAPKDetails(
|
||||||
String standardUrl, Map<String, String> additionalData,
|
String standardUrl,
|
||||||
{bool trackOnly = false}) async {
|
Map<String, String> additionalSettings,
|
||||||
String? appIdOrName = additionalData['appIdOrName'];
|
) async {
|
||||||
|
String? appIdOrName = additionalSettings['appIdOrName'];
|
||||||
if (appIdOrName == null) {
|
if (appIdOrName == null) {
|
||||||
throw NoReleasesError();
|
throw NoReleasesError();
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,7 @@ class GitHub extends AppSource {
|
|||||||
])
|
])
|
||||||
];
|
];
|
||||||
|
|
||||||
additionalSourceAppSpecificFormItems = [
|
additionalSourceAppSpecificSettingFormItems = [
|
||||||
[
|
[
|
||||||
GeneratedFormItem('includePrereleases',
|
GeneratedFormItem('includePrereleases',
|
||||||
label: tr('includePrereleases'),
|
label: tr('includePrereleases'),
|
||||||
@ -110,14 +110,15 @@ class GitHub extends AppSource {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<APKDetails> getLatestAPKDetails(
|
Future<APKDetails> getLatestAPKDetails(
|
||||||
String standardUrl, Map<String, String> additionalData,
|
String standardUrl,
|
||||||
{bool trackOnly = false}) async {
|
Map<String, String> additionalSettings,
|
||||||
var includePrereleases = additionalData['includePrereleases'] == 'true';
|
) async {
|
||||||
|
var includePrereleases = additionalSettings['includePrereleases'] == 'true';
|
||||||
var fallbackToOlderReleases =
|
var fallbackToOlderReleases =
|
||||||
additionalData['fallbackToOlderReleases'] == 'true';
|
additionalSettings['fallbackToOlderReleases'] == 'true';
|
||||||
var regexFilter =
|
var regexFilter =
|
||||||
additionalData['filterReleaseTitlesByRegEx']?.isNotEmpty == true
|
additionalSettings['filterReleaseTitlesByRegEx']?.isNotEmpty == true
|
||||||
? additionalData['filterReleaseTitlesByRegEx']
|
? additionalSettings['filterReleaseTitlesByRegEx']
|
||||||
: null;
|
: null;
|
||||||
Response res = await get(Uri.parse(
|
Response res = await get(Uri.parse(
|
||||||
'https://${await getCredentialPrefixIfAny()}api.$host/repos${standardUrl.substring('https://$host'.length)}/releases'));
|
'https://${await getCredentialPrefixIfAny()}api.$host/repos${standardUrl.substring('https://$host'.length)}/releases'));
|
||||||
@ -149,7 +150,7 @@ class GitHub extends AppSource {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var apkUrls = getReleaseAPKUrls(releases[i]);
|
var apkUrls = getReleaseAPKUrls(releases[i]);
|
||||||
if (apkUrls.isEmpty && !trackOnly) {
|
if (apkUrls.isEmpty && additionalSettings['trackOnly'] != 'true') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
targetRelease = releases[i];
|
targetRelease = releases[i];
|
||||||
|
@ -25,8 +25,9 @@ class GitLab extends AppSource {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<APKDetails> getLatestAPKDetails(
|
Future<APKDetails> getLatestAPKDetails(
|
||||||
String standardUrl, Map<String, String> additionalData,
|
String standardUrl,
|
||||||
{bool trackOnly = false}) async {
|
Map<String, String> additionalSettings,
|
||||||
|
) async {
|
||||||
Response res = await get(Uri.parse('$standardUrl/-/tags?format=atom'));
|
Response res = await get(Uri.parse('$standardUrl/-/tags?format=atom'));
|
||||||
if (res.statusCode == 200) {
|
if (res.statusCode == 200) {
|
||||||
var standardUri = Uri.parse(standardUrl);
|
var standardUri = Uri.parse(standardUrl);
|
||||||
|
@ -23,14 +23,15 @@ class IzzyOnDroid extends AppSource {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String? tryInferringAppId(String standardUrl,
|
String? tryInferringAppId(String standardUrl,
|
||||||
{Map<String, String> additionalData = const {}}) {
|
{Map<String, String> additionalSettings = const {}}) {
|
||||||
return FDroid().tryInferringAppId(standardUrl);
|
return FDroid().tryInferringAppId(standardUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<APKDetails> getLatestAPKDetails(
|
Future<APKDetails> getLatestAPKDetails(
|
||||||
String standardUrl, Map<String, String> additionalData,
|
String standardUrl,
|
||||||
{bool trackOnly = false}) async {
|
Map<String, String> additionalSettings,
|
||||||
|
) async {
|
||||||
String? appId = tryInferringAppId(standardUrl);
|
String? appId = tryInferringAppId(standardUrl);
|
||||||
return FDroid().getAPKUrlsFromFDroidPackagesAPIResponse(
|
return FDroid().getAPKUrlsFromFDroidPackagesAPIResponse(
|
||||||
await get(
|
await get(
|
||||||
|
@ -24,8 +24,9 @@ class Mullvad extends AppSource {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<APKDetails> getLatestAPKDetails(
|
Future<APKDetails> getLatestAPKDetails(
|
||||||
String standardUrl, Map<String, String> additionalData,
|
String standardUrl,
|
||||||
{bool trackOnly = false}) async {
|
Map<String, String> additionalSettings,
|
||||||
|
) async {
|
||||||
Response res = await get(Uri.parse('$standardUrl/en/download/android'));
|
Response res = await get(Uri.parse('$standardUrl/en/download/android'));
|
||||||
if (res.statusCode == 200) {
|
if (res.statusCode == 200) {
|
||||||
var version = parse(res.body)
|
var version = parse(res.body)
|
||||||
|
@ -18,8 +18,9 @@ class Signal extends AppSource {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<APKDetails> getLatestAPKDetails(
|
Future<APKDetails> getLatestAPKDetails(
|
||||||
String standardUrl, Map<String, String> additionalData,
|
String standardUrl,
|
||||||
{bool trackOnly = false}) async {
|
Map<String, String> additionalSettings,
|
||||||
|
) async {
|
||||||
Response res =
|
Response res =
|
||||||
await get(Uri.parse('https://updates.$host/android/latest.json'));
|
await get(Uri.parse('https://updates.$host/android/latest.json'));
|
||||||
if (res.statusCode == 200) {
|
if (res.statusCode == 200) {
|
||||||
|
@ -23,8 +23,9 @@ class SourceForge extends AppSource {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<APKDetails> getLatestAPKDetails(
|
Future<APKDetails> getLatestAPKDetails(
|
||||||
String standardUrl, Map<String, String> additionalData,
|
String standardUrl,
|
||||||
{bool trackOnly = false}) async {
|
Map<String, String> additionalSettings,
|
||||||
|
) async {
|
||||||
Response res = await get(Uri.parse('$standardUrl/rss?path=/'));
|
Response res = await get(Uri.parse('$standardUrl/rss?path=/'));
|
||||||
if (res.statusCode == 200) {
|
if (res.statusCode == 200) {
|
||||||
var parsedHtml = parse(res.body);
|
var parsedHtml = parse(res.body);
|
||||||
|
@ -9,7 +9,7 @@ class SteamMobile extends AppSource {
|
|||||||
SteamMobile() {
|
SteamMobile() {
|
||||||
host = 'store.steampowered.com';
|
host = 'store.steampowered.com';
|
||||||
name = tr('steam');
|
name = tr('steam');
|
||||||
additionalSourceAppSpecificFormItems = [
|
additionalSourceAppSpecificSettingFormItems = [
|
||||||
[
|
[
|
||||||
GeneratedFormItem('app',
|
GeneratedFormItem('app',
|
||||||
label: tr('app'), required: true, opts: apks.entries.toList())
|
label: tr('app'), required: true, opts: apks.entries.toList())
|
||||||
@ -29,11 +29,12 @@ class SteamMobile extends AppSource {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<APKDetails> getLatestAPKDetails(
|
Future<APKDetails> getLatestAPKDetails(
|
||||||
String standardUrl, Map<String, String> additionalData,
|
String standardUrl,
|
||||||
{bool trackOnly = false}) async {
|
Map<String, String> additionalSettings,
|
||||||
|
) async {
|
||||||
Response res = await get(Uri.parse('https://$host/mobile'));
|
Response res = await get(Uri.parse('https://$host/mobile'));
|
||||||
if (res.statusCode == 200) {
|
if (res.statusCode == 200) {
|
||||||
var apkNamePrefix = additionalData['app'];
|
var apkNamePrefix = additionalSettings['app'];
|
||||||
if (apkNamePrefix == null) {
|
if (apkNamePrefix == null) {
|
||||||
throw NoReleasesError();
|
throw NoReleasesError();
|
||||||
}
|
}
|
||||||
|
@ -202,7 +202,6 @@ class _ObtainiumState extends State<Obtainium> {
|
|||||||
0,
|
0,
|
||||||
{},
|
{},
|
||||||
null,
|
null,
|
||||||
false,
|
|
||||||
false)
|
false)
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
@ -27,10 +27,8 @@ class _AddAppPageState extends State<AddAppPage> {
|
|||||||
String userInput = '';
|
String userInput = '';
|
||||||
String searchQuery = '';
|
String searchQuery = '';
|
||||||
AppSource? pickedSource;
|
AppSource? pickedSource;
|
||||||
Map<String, String> sourceSpecificAdditionalData = {};
|
Map<String, String> additionalSettings = {};
|
||||||
bool sourceSpecificDataIsValid = true;
|
bool additionalSettingsValid = true;
|
||||||
Map<String, String> otherAdditionalData = {};
|
|
||||||
bool otherAdditionalDataIsValid = true;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -43,12 +41,12 @@ class _AddAppPageState extends State<AddAppPage> {
|
|||||||
var source = valid ? sourceProvider.getSource(userInput) : null;
|
var source = valid ? sourceProvider.getSource(userInput) : null;
|
||||||
if (pickedSource.runtimeType != source.runtimeType) {
|
if (pickedSource.runtimeType != source.runtimeType) {
|
||||||
pickedSource = source;
|
pickedSource = source;
|
||||||
sourceSpecificAdditionalData = source != null
|
additionalSettings = source != null
|
||||||
? getDefaultValuesFromFormItems(
|
? getDefaultValuesFromFormItems(
|
||||||
source.additionalSourceAppSpecificFormItems)
|
source.combinedAppSpecificSettingFormItems)
|
||||||
: {};
|
: {};
|
||||||
sourceSpecificDataIsValid = source != null
|
additionalSettingsValid = source != null
|
||||||
? !sourceProvider.ifSourceAppsRequireAdditionalData(source)
|
? !sourceProvider.ifRequiredAppSpecificSettingsExist(source)
|
||||||
: true;
|
: true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -68,10 +66,9 @@ class _AddAppPageState extends State<AddAppPage> {
|
|||||||
});
|
});
|
||||||
var settingsProvider = context.read<SettingsProvider>();
|
var settingsProvider = context.read<SettingsProvider>();
|
||||||
() async {
|
() async {
|
||||||
var userPickedTrackOnly =
|
var userPickedTrackOnly = additionalSettings['trackOnly'] == 'true';
|
||||||
otherAdditionalData['trackOnlyFormItemKey'] == 'true';
|
|
||||||
var userPickedNoVersionDetection =
|
var userPickedNoVersionDetection =
|
||||||
otherAdditionalData['noVersionDetectionKey'] == 'true';
|
additionalSettings['noVersionDetection'] == 'true';
|
||||||
var cont = true;
|
var cont = true;
|
||||||
if ((userPickedTrackOnly || pickedSource!.enforceTrackOnly) &&
|
if ((userPickedTrackOnly || pickedSource!.enforceTrackOnly) &&
|
||||||
await showDialog(
|
await showDialog(
|
||||||
@ -108,14 +105,15 @@ class _AddAppPageState extends State<AddAppPage> {
|
|||||||
HapticFeedback.selectionClick();
|
HapticFeedback.selectionClick();
|
||||||
var trackOnly = pickedSource!.enforceTrackOnly || userPickedTrackOnly;
|
var trackOnly = pickedSource!.enforceTrackOnly || userPickedTrackOnly;
|
||||||
App app = await sourceProvider.getApp(
|
App app = await sourceProvider.getApp(
|
||||||
pickedSource!, userInput, sourceSpecificAdditionalData,
|
pickedSource!, userInput, additionalSettings,
|
||||||
trackOnlyOverride: trackOnly,
|
trackOnlyOverride: trackOnly,
|
||||||
noVersionDetectionOverride: userPickedNoVersionDetection);
|
noVersionDetectionOverride: userPickedNoVersionDetection);
|
||||||
if (!trackOnly) {
|
if (!trackOnly) {
|
||||||
await settingsProvider.getInstallPermission();
|
await settingsProvider.getInstallPermission();
|
||||||
}
|
}
|
||||||
// Only download the APK here if you need to for the package ID
|
// Only download the APK here if you need to for the package ID
|
||||||
if (sourceProvider.isTempId(app.id) && !app.trackOnly) {
|
if (sourceProvider.isTempId(app.id) &&
|
||||||
|
app.additionalSettings['trackOnly'] != 'true') {
|
||||||
// ignore: use_build_context_synchronously
|
// ignore: use_build_context_synchronously
|
||||||
var apkUrl = await appsProvider.confirmApkUrl(app, context);
|
var apkUrl = await appsProvider.confirmApkUrl(app, context);
|
||||||
if (apkUrl == null) {
|
if (apkUrl == null) {
|
||||||
@ -130,7 +128,7 @@ class _AddAppPageState extends State<AddAppPage> {
|
|||||||
if (appsProvider.apps.containsKey(app.id)) {
|
if (appsProvider.apps.containsKey(app.id)) {
|
||||||
throw ObtainiumError(tr('appAlreadyAdded'));
|
throw ObtainiumError(tr('appAlreadyAdded'));
|
||||||
}
|
}
|
||||||
if (app.trackOnly) {
|
if (app.additionalSettings['trackOnly'] == 'true') {
|
||||||
app.installedVersion = app.latestVersion;
|
app.installedVersion = app.latestVersion;
|
||||||
}
|
}
|
||||||
await appsProvider.saveApps([app]);
|
await appsProvider.saveApps([app]);
|
||||||
@ -206,13 +204,9 @@ class _AddAppPageState extends State<AddAppPage> {
|
|||||||
onPressed: gettingAppInfo ||
|
onPressed: gettingAppInfo ||
|
||||||
pickedSource == null ||
|
pickedSource == null ||
|
||||||
(pickedSource!
|
(pickedSource!
|
||||||
.additionalSourceAppSpecificFormItems
|
.combinedAppSpecificSettingFormItems
|
||||||
.isNotEmpty &&
|
.isNotEmpty &&
|
||||||
!sourceSpecificDataIsValid) ||
|
!additionalSettingsValid)
|
||||||
(pickedSource!
|
|
||||||
.additionalAppSpecificSourceAgnosticFormItems
|
|
||||||
.isNotEmpty &&
|
|
||||||
!otherAdditionalDataIsValid)
|
|
||||||
? null
|
? null
|
||||||
: addApp,
|
: addApp,
|
||||||
child: Text(tr('add')))
|
child: Text(tr('add')))
|
||||||
@ -305,15 +299,8 @@ class _AddAppPageState extends State<AddAppPage> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (pickedSource != null &&
|
if (pickedSource != null &&
|
||||||
(pickedSource!.additionalSourceAppSpecificFormItems
|
(pickedSource!
|
||||||
.isNotEmpty ||
|
.combinedAppSpecificSettingFormItems.isNotEmpty))
|
||||||
pickedSource!
|
|
||||||
.additionalAppSpecificSourceAgnosticFormItems
|
|
||||||
.where((e) => pickedSource!.enforceTrackOnly
|
|
||||||
? e.key != 'trackOnlyFormItemKey'
|
|
||||||
: true)
|
|
||||||
.map((e) => [e])
|
|
||||||
.isNotEmpty))
|
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
children: [
|
children: [
|
||||||
@ -329,39 +316,14 @@ class _AddAppPageState extends State<AddAppPage> {
|
|||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 16,
|
height: 16,
|
||||||
),
|
),
|
||||||
if (pickedSource!
|
|
||||||
.additionalSourceAppSpecificFormItems
|
|
||||||
.isNotEmpty)
|
|
||||||
GeneratedForm(
|
|
||||||
items: pickedSource!
|
|
||||||
.additionalSourceAppSpecificFormItems,
|
|
||||||
onValueChanges: (values, valid, isBuilding) {
|
|
||||||
if (!isBuilding) {
|
|
||||||
setState(() {
|
|
||||||
sourceSpecificAdditionalData = values;
|
|
||||||
sourceSpecificDataIsValid = valid;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
if (pickedSource!
|
|
||||||
.additionalAppSpecificSourceAgnosticFormItems
|
|
||||||
.isNotEmpty)
|
|
||||||
const SizedBox(
|
|
||||||
height: 8,
|
|
||||||
),
|
|
||||||
GeneratedForm(
|
GeneratedForm(
|
||||||
items: pickedSource!
|
items: pickedSource!
|
||||||
.additionalAppSpecificSourceAgnosticFormItems
|
.combinedAppSpecificSettingFormItems,
|
||||||
.where((e) => pickedSource!.enforceTrackOnly
|
|
||||||
? e.key != 'trackOnlyFormItemKey'
|
|
||||||
: true)
|
|
||||||
.map((e) => [e])
|
|
||||||
.toList(),
|
|
||||||
onValueChanges: (values, valid, isBuilding) {
|
onValueChanges: (values, valid, isBuilding) {
|
||||||
if (!isBuilding) {
|
if (!isBuilding) {
|
||||||
setState(() {
|
setState(() {
|
||||||
otherAdditionalData = values;
|
additionalSettings = values;
|
||||||
otherAdditionalDataIsValid = valid;
|
additionalSettingsValid = valid;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
@ -40,6 +40,7 @@ class _AppPageState extends State<AppPage> {
|
|||||||
prevApp = app;
|
prevApp = app;
|
||||||
getUpdate(app.app.id);
|
getUpdate(app.app.id);
|
||||||
}
|
}
|
||||||
|
var trackOnly = app?.app.additionalSettings['trackOnly'] == 'true';
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: settingsProvider.showAppWebpage ? AppBar() : null,
|
appBar: settingsProvider.showAppWebpage ? AppBar() : null,
|
||||||
backgroundColor: Theme.of(context).colorScheme.surface,
|
backgroundColor: Theme.of(context).colorScheme.surface,
|
||||||
@ -111,7 +112,7 @@ class _AppPageState extends State<AppPage> {
|
|||||||
Text(
|
Text(
|
||||||
'${tr('installedVersionX', args: [
|
'${tr('installedVersionX', args: [
|
||||||
app?.app.installedVersion ?? tr('none')
|
app?.app.installedVersion ?? tr('none')
|
||||||
])}${app?.app.trackOnly == true ? ' ${tr('estimateInBrackets')}\n\n${tr('xIsTrackOnly', args: [
|
])}${trackOnly ? ' ${tr('estimateInBrackets')}\n\n${tr('xIsTrackOnly', args: [
|
||||||
tr('app')
|
tr('app')
|
||||||
])}' : ''}',
|
])}' : ''}',
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
@ -151,7 +152,7 @@ class _AppPageState extends State<AppPage> {
|
|||||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||||
children: [
|
children: [
|
||||||
if (app?.app.installedVersion != null &&
|
if (app?.app.installedVersion != null &&
|
||||||
app?.app.trackOnly == false &&
|
!trackOnly &&
|
||||||
app?.app.installedVersion != app?.app.latestVersion)
|
app?.app.installedVersion != app?.app.latestVersion)
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: app?.downloadProgress != null
|
onPressed: app?.downloadProgress != null
|
||||||
@ -202,8 +203,8 @@ class _AppPageState extends State<AppPage> {
|
|||||||
tooltip: 'Mark as Updated',
|
tooltip: 'Mark as Updated',
|
||||||
icon: const Icon(Icons.done)),
|
icon: const Icon(Icons.done)),
|
||||||
if (source != null &&
|
if (source != null &&
|
||||||
source.additionalSourceAppSpecificFormItems
|
source
|
||||||
.isNotEmpty)
|
.combinedAppSpecificSettingFormItems.isNotEmpty)
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: app?.downloadProgress != null
|
onPressed: app?.downloadProgress != null
|
||||||
? null
|
? null
|
||||||
@ -211,14 +212,36 @@ class _AppPageState extends State<AppPage> {
|
|||||||
showDialog<Map<String, String>>(
|
showDialog<Map<String, String>>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (BuildContext ctx) {
|
builder: (BuildContext ctx) {
|
||||||
|
var items = source
|
||||||
|
.combinedAppSpecificSettingFormItems
|
||||||
|
.map((row) {
|
||||||
|
row.map((e) {
|
||||||
|
if (app?.app.additionalSettings[
|
||||||
|
e.key] !=
|
||||||
|
null) {
|
||||||
|
e.defaultValue = app?.app
|
||||||
|
.additionalSettings[
|
||||||
|
e.key];
|
||||||
|
}
|
||||||
|
return e;
|
||||||
|
}).toList();
|
||||||
|
return row;
|
||||||
|
}).toList();
|
||||||
return GeneratedFormModal(
|
return GeneratedFormModal(
|
||||||
title: 'Additional Options',
|
title: 'Additional Options',
|
||||||
items: source
|
items: items);
|
||||||
.additionalSourceAppSpecificFormItems);
|
|
||||||
}).then((values) {
|
}).then((values) {
|
||||||
if (app != null && values != null) {
|
if (app != null && values != null) {
|
||||||
var changedApp = app.app;
|
var changedApp = app.app;
|
||||||
changedApp.additionalData = values;
|
changedApp.additionalSettings =
|
||||||
|
values;
|
||||||
|
if (source.enforceTrackOnly) {
|
||||||
|
changedApp.additionalSettings[
|
||||||
|
'trackOnly'] = 'true';
|
||||||
|
showError(
|
||||||
|
tr('appsFromSourceAreTrackOnly'),
|
||||||
|
context);
|
||||||
|
}
|
||||||
appsProvider.saveApps(
|
appsProvider.saveApps(
|
||||||
[changedApp]).then((value) {
|
[changedApp]).then((value) {
|
||||||
getUpdate(changedApp.id);
|
getUpdate(changedApp.id);
|
||||||
@ -238,7 +261,9 @@ class _AppPageState extends State<AppPage> {
|
|||||||
? () {
|
? () {
|
||||||
HapticFeedback.heavyImpact();
|
HapticFeedback.heavyImpact();
|
||||||
() async {
|
() async {
|
||||||
if (app?.app.trackOnly != true) {
|
if (app?.app.additionalSettings[
|
||||||
|
'trackOnly'] !=
|
||||||
|
'true') {
|
||||||
await settingsProvider
|
await settingsProvider
|
||||||
.getInstallPermission();
|
.getInstallPermission();
|
||||||
}
|
}
|
||||||
@ -260,10 +285,10 @@ class _AppPageState extends State<AppPage> {
|
|||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
child: Text(app?.app.installedVersion == null
|
child: Text(app?.app.installedVersion == null
|
||||||
? app?.app.trackOnly == false
|
? !trackOnly
|
||||||
? 'Install'
|
? 'Install'
|
||||||
: 'Mark Installed'
|
: 'Mark Installed'
|
||||||
: app?.app.trackOnly == false
|
: !trackOnly
|
||||||
? 'Update'
|
? 'Update'
|
||||||
: 'Mark Updated'))),
|
: 'Mark Updated'))),
|
||||||
const SizedBox(width: 16.0),
|
const SizedBox(width: 16.0),
|
||||||
|
@ -139,14 +139,16 @@ class AppsPageState extends State<AppsPage> {
|
|||||||
|
|
||||||
List<String> trackOnlyUpdateIdsAllOrSelected = [];
|
List<String> trackOnlyUpdateIdsAllOrSelected = [];
|
||||||
existingUpdateIdsAllOrSelected = existingUpdateIdsAllOrSelected.where((id) {
|
existingUpdateIdsAllOrSelected = existingUpdateIdsAllOrSelected.where((id) {
|
||||||
if (appsProvider.apps[id]!.app.trackOnly) {
|
if (appsProvider.apps[id]!.app.additionalSettings['trackOnly'] ==
|
||||||
|
'true') {
|
||||||
trackOnlyUpdateIdsAllOrSelected.add(id);
|
trackOnlyUpdateIdsAllOrSelected.add(id);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}).toList();
|
}).toList();
|
||||||
newInstallIdsAllOrSelected = newInstallIdsAllOrSelected.where((id) {
|
newInstallIdsAllOrSelected = newInstallIdsAllOrSelected.where((id) {
|
||||||
if (appsProvider.apps[id]!.app.trackOnly) {
|
if (appsProvider.apps[id]!.app.additionalSettings['trackOnly'] ==
|
||||||
|
'true') {
|
||||||
trackOnlyUpdateIdsAllOrSelected.add(id);
|
trackOnlyUpdateIdsAllOrSelected.add(id);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -271,7 +273,7 @@ class AppsPageState extends State<AppsPage> {
|
|||||||
SizedBox(
|
SizedBox(
|
||||||
width: 100,
|
width: 100,
|
||||||
child: Text(
|
child: Text(
|
||||||
'${sortedApps[index].app.installedVersion ?? tr('notInstalled')}${sortedApps[index].app.trackOnly == true ? ' ${tr('estimateInBrackets')}' : ''}',
|
'${sortedApps[index].app.installedVersion ?? tr('notInstalled')}${sortedApps[index].app.additionalSettings['trackOnly'] == 'true' ? ' ${tr('estimateInBrackets')}' : ''}',
|
||||||
overflow: TextOverflow.fade,
|
overflow: TextOverflow.fade,
|
||||||
textAlign: TextAlign.end,
|
textAlign: TextAlign.end,
|
||||||
)),
|
)),
|
||||||
@ -289,7 +291,7 @@ class AppsPageState extends State<AppsPage> {
|
|||||||
child: appsProvider.areDownloadsRunning()
|
child: appsProvider.areDownloadsRunning()
|
||||||
? Text(tr('pleaseWait'))
|
? Text(tr('pleaseWait'))
|
||||||
: Text(
|
: Text(
|
||||||
'${tr('updateAvailable')}${sortedApps[index].app.trackOnly ? ' ${tr('estimateInBracketsShort')}' : ''}',
|
'${tr('updateAvailable')}${sortedApps[index].app.additionalSettings['trackOnly'] == 'true' ? ' ${tr('estimateInBracketsShort')}' : ''}',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontStyle: FontStyle.italic,
|
fontStyle: FontStyle.italic,
|
||||||
decoration: changesUrl == null
|
decoration: changesUrl == null
|
||||||
@ -343,7 +345,7 @@ class AppsPageState extends State<AppsPage> {
|
|||||||
: IconButton(
|
: IconButton(
|
||||||
visualDensity: VisualDensity.compact,
|
visualDensity: VisualDensity.compact,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
showDialog<List<String>?>(
|
showDialog<Map<String, String>?>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (BuildContext ctx) {
|
builder: (BuildContext ctx) {
|
||||||
return GeneratedFormModal(
|
return GeneratedFormModal(
|
||||||
|
@ -313,7 +313,8 @@ class AppsProvider with ChangeNotifier {
|
|||||||
throw ObtainiumError(tr('appNotFound'));
|
throw ObtainiumError(tr('appNotFound'));
|
||||||
}
|
}
|
||||||
String? apkUrl;
|
String? apkUrl;
|
||||||
if (!apps[id]!.app.trackOnly) {
|
var trackOnly = apps[id]!.app.additionalSettings['trackOnly'] == 'true';
|
||||||
|
if (!trackOnly) {
|
||||||
apkUrl = await confirmApkUrl(apps[id]!.app, context);
|
apkUrl = await confirmApkUrl(apps[id]!.app, context);
|
||||||
}
|
}
|
||||||
if (apkUrl != null) {
|
if (apkUrl != null) {
|
||||||
@ -326,7 +327,7 @@ class AppsProvider with ChangeNotifier {
|
|||||||
appsToInstall.add(id);
|
appsToInstall.add(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (apps[id]!.app.trackOnly) {
|
if (trackOnly) {
|
||||||
trackOnlyAppsToUpdate.add(id);
|
trackOnlyAppsToUpdate.add(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -451,9 +452,10 @@ class AppsProvider with ChangeNotifier {
|
|||||||
// Don't save changes, just return the object if changes were made (else null)
|
// Don't save changes, just return the object if changes were made (else null)
|
||||||
App? getCorrectedInstallStatusAppIfPossible(App app, AppInfo? installedInfo) {
|
App? getCorrectedInstallStatusAppIfPossible(App app, AppInfo? installedInfo) {
|
||||||
var modded = false;
|
var modded = false;
|
||||||
if (installedInfo == null &&
|
var trackOnly = app.additionalSettings['trackOnly'] == 'true';
|
||||||
app.installedVersion != null &&
|
var noVersionDetection =
|
||||||
!app.trackOnly) {
|
app.additionalSettings['noVersionDetection'] == 'true';
|
||||||
|
if (installedInfo == null && app.installedVersion != null && !trackOnly) {
|
||||||
app.installedVersion = null;
|
app.installedVersion = null;
|
||||||
modded = true;
|
modded = true;
|
||||||
} else if (installedInfo?.versionName != null &&
|
} else if (installedInfo?.versionName != null &&
|
||||||
@ -462,7 +464,7 @@ class AppsProvider with ChangeNotifier {
|
|||||||
modded = true;
|
modded = true;
|
||||||
} else if (installedInfo?.versionName != null &&
|
} else if (installedInfo?.versionName != null &&
|
||||||
installedInfo!.versionName != app.installedVersion &&
|
installedInfo!.versionName != app.installedVersion &&
|
||||||
!app.noVersionDetection) {
|
!noVersionDetection) {
|
||||||
String? correctedInstalledVersion = reconcileRealAndInternalVersions(
|
String? correctedInstalledVersion = reconcileRealAndInternalVersions(
|
||||||
installedInfo.versionName!, app.installedVersion!);
|
installedInfo.versionName!, app.installedVersion!);
|
||||||
if (correctedInstalledVersion != null) {
|
if (correctedInstalledVersion != null) {
|
||||||
@ -472,7 +474,7 @@ class AppsProvider with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
if (app.installedVersion != null &&
|
if (app.installedVersion != null &&
|
||||||
app.installedVersion != app.latestVersion &&
|
app.installedVersion != app.latestVersion &&
|
||||||
!app.noVersionDetection) {
|
!noVersionDetection) {
|
||||||
app.installedVersion = reconcileRealAndInternalVersions(
|
app.installedVersion = reconcileRealAndInternalVersions(
|
||||||
app.installedVersion!, app.latestVersion,
|
app.installedVersion!, app.latestVersion,
|
||||||
matchMode: true) ??
|
matchMode: true) ??
|
||||||
@ -625,7 +627,7 @@ class AppsProvider with ChangeNotifier {
|
|||||||
App newApp = await sourceProvider.getApp(
|
App newApp = await sourceProvider.getApp(
|
||||||
sourceProvider.getSource(currentApp.url),
|
sourceProvider.getSource(currentApp.url),
|
||||||
currentApp.url,
|
currentApp.url,
|
||||||
currentApp.additionalData,
|
currentApp.additionalSettings,
|
||||||
currentApp: currentApp);
|
currentApp: currentApp);
|
||||||
if (currentApp.preferredApkIndex < newApp.apkUrls.length) {
|
if (currentApp.preferredApkIndex < newApp.apkUrls.length) {
|
||||||
newApp.preferredApkIndex = currentApp.preferredApkIndex;
|
newApp.preferredApkIndex = currentApp.preferredApkIndex;
|
||||||
|
@ -44,11 +44,9 @@ class App {
|
|||||||
late String latestVersion;
|
late String latestVersion;
|
||||||
List<String> apkUrls = [];
|
List<String> apkUrls = [];
|
||||||
late int preferredApkIndex;
|
late int preferredApkIndex;
|
||||||
late Map<String, String> additionalData;
|
late Map<String, String> additionalSettings;
|
||||||
late DateTime? lastUpdateCheck;
|
late DateTime? lastUpdateCheck;
|
||||||
bool pinned = false;
|
bool pinned = false;
|
||||||
bool trackOnly = false;
|
|
||||||
bool noVersionDetection = false;
|
|
||||||
App(
|
App(
|
||||||
this.id,
|
this.id,
|
||||||
this.url,
|
this.url,
|
||||||
@ -58,38 +56,37 @@ class App {
|
|||||||
this.latestVersion,
|
this.latestVersion,
|
||||||
this.apkUrls,
|
this.apkUrls,
|
||||||
this.preferredApkIndex,
|
this.preferredApkIndex,
|
||||||
this.additionalData,
|
this.additionalSettings,
|
||||||
this.lastUpdateCheck,
|
this.lastUpdateCheck,
|
||||||
this.pinned,
|
this.pinned);
|
||||||
this.trackOnly,
|
|
||||||
{this.noVersionDetection = false});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'ID: $id URL: $url INSTALLED: $installedVersion LATEST: $latestVersion APK: $apkUrls PREFERREDAPK: $preferredApkIndex ADDITIONALDATA: ${additionalData.toString()} LASTCHECK: ${lastUpdateCheck.toString()} PINNED $pinned';
|
return 'ID: $id URL: $url INSTALLED: $installedVersion LATEST: $latestVersion APK: $apkUrls PREFERREDAPK: $preferredApkIndex ADDITIONALSETTINGS: ${additionalSettings.toString()} LASTCHECK: ${lastUpdateCheck.toString()} PINNED $pinned';
|
||||||
}
|
}
|
||||||
|
|
||||||
factory App.fromJson(Map<String, dynamic> json) {
|
factory App.fromJson(Map<String, dynamic> json) {
|
||||||
var formItems = SourceProvider()
|
var source = SourceProvider().getSource(json['url']);
|
||||||
.getSource(json['url'])
|
var formItems = source.combinedAppSpecificSettingFormItems
|
||||||
.additionalSourceAppSpecificFormItems
|
|
||||||
.reduce((value, element) => [...value, ...element]);
|
.reduce((value, element) => [...value, ...element]);
|
||||||
Map<String, String> additionalData =
|
Map<String, String> additionalSettings =
|
||||||
getDefaultValuesFromFormItems([formItems]);
|
getDefaultValuesFromFormItems([formItems]);
|
||||||
|
if (json['additionalSettings'] != null) {
|
||||||
|
additionalSettings.addEntries(
|
||||||
|
Map<String, String>.from(jsonDecode(json['additionalSettings']))
|
||||||
|
.entries);
|
||||||
|
}
|
||||||
|
// If needed, migrate old-style additionalData to new-style additionalSettings
|
||||||
if (json['additionalData'] != null) {
|
if (json['additionalData'] != null) {
|
||||||
try {
|
List<String> temp = List<String>.from(jsonDecode(json['additionalData']));
|
||||||
additionalData =
|
temp.asMap().forEach((i, value) {
|
||||||
Map<String, String>.from(jsonDecode(json['additionalData']));
|
if (i < formItems.length) {
|
||||||
} catch (e) {
|
additionalSettings[formItems[i].key] = value;
|
||||||
// Migrate old-style additionalData List to new-style Map
|
}
|
||||||
List<String> temp =
|
});
|
||||||
List<String>.from(jsonDecode(json['additionalData']));
|
additionalSettings['trackOnly'] = (json['trackOnly'] ?? false).toString();
|
||||||
temp.asMap().forEach((i, value) {
|
additionalSettings['noVersionDetection'] =
|
||||||
if (i < formItems.length) {
|
(json['noVersionDetection'] ?? false).toString();
|
||||||
additionalData[formItems[i].key] = value;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return App(
|
return App(
|
||||||
json['id'] as String,
|
json['id'] as String,
|
||||||
@ -106,13 +103,11 @@ class App {
|
|||||||
json['preferredApkIndex'] == null
|
json['preferredApkIndex'] == null
|
||||||
? 0
|
? 0
|
||||||
: json['preferredApkIndex'] as int,
|
: json['preferredApkIndex'] as int,
|
||||||
additionalData,
|
additionalSettings,
|
||||||
json['lastUpdateCheck'] == null
|
json['lastUpdateCheck'] == null
|
||||||
? null
|
? null
|
||||||
: DateTime.fromMicrosecondsSinceEpoch(json['lastUpdateCheck']),
|
: DateTime.fromMicrosecondsSinceEpoch(json['lastUpdateCheck']),
|
||||||
json['pinned'] ?? false,
|
json['pinned'] ?? false);
|
||||||
json['trackOnly'] ?? false,
|
|
||||||
noVersionDetection: json['noVersionDetection'] ?? false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => {
|
Map<String, dynamic> toJson() => {
|
||||||
@ -124,11 +119,9 @@ class App {
|
|||||||
'latestVersion': latestVersion,
|
'latestVersion': latestVersion,
|
||||||
'apkUrls': jsonEncode(apkUrls),
|
'apkUrls': jsonEncode(apkUrls),
|
||||||
'preferredApkIndex': preferredApkIndex,
|
'preferredApkIndex': preferredApkIndex,
|
||||||
'additionalData': jsonEncode(additionalData),
|
'additionalSettings': jsonEncode(additionalSettings),
|
||||||
'lastUpdateCheck': lastUpdateCheck?.microsecondsSinceEpoch,
|
'lastUpdateCheck': lastUpdateCheck?.microsecondsSinceEpoch,
|
||||||
'pinned': pinned,
|
'pinned': pinned
|
||||||
'trackOnly': trackOnly,
|
|
||||||
'noVersionDetection': noVersionDetection
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,26 +176,39 @@ class AppSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<APKDetails> getLatestAPKDetails(
|
Future<APKDetails> getLatestAPKDetails(
|
||||||
String standardUrl, Map<String, String> additionalData,
|
String standardUrl, Map<String, String> additionalSettings) {
|
||||||
{bool trackOnly = false}) {
|
|
||||||
throw NotImplementedError();
|
throw NotImplementedError();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Different Sources may need different kinds of additional data for Apps
|
// Different Sources may need different kinds of additional data for Apps
|
||||||
List<List<GeneratedFormItem>> additionalSourceAppSpecificFormItems = [];
|
List<List<GeneratedFormItem>> additionalSourceAppSpecificSettingFormItems =
|
||||||
|
[];
|
||||||
|
|
||||||
// Some additional data may be needed for Apps regardless of Source
|
// Some additional data may be needed for Apps regardless of Source
|
||||||
final List<GeneratedFormItem> additionalAppSpecificSourceAgnosticFormItems = [
|
final List<List<GeneratedFormItem>>
|
||||||
GeneratedFormItem(
|
additionalAppSpecificSourceAgnosticSettingFormItems = [
|
||||||
'trackOnlyFormItemKey',
|
[
|
||||||
label: tr('trackOnly'),
|
GeneratedFormItem(
|
||||||
type: FormItemType.bool,
|
'trackOnly',
|
||||||
),
|
label: tr('trackOnly'),
|
||||||
GeneratedFormItem('noVersionDetectionKey',
|
type: FormItemType.bool,
|
||||||
label: 'Do not attempt version detection', // TODO
|
)
|
||||||
type: FormItemType.bool)
|
],
|
||||||
|
[
|
||||||
|
GeneratedFormItem('noVersionDetection',
|
||||||
|
label: 'Do not attempt version detection', // TODO
|
||||||
|
type: FormItemType.bool)
|
||||||
|
]
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// Previous 2 variables combined into one at runtime for convenient usage
|
||||||
|
List<List<GeneratedFormItem>> get combinedAppSpecificSettingFormItems {
|
||||||
|
return [
|
||||||
|
...additionalSourceAppSpecificSettingFormItems,
|
||||||
|
...additionalAppSpecificSourceAgnosticSettingFormItems
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
// Some Sources may have additional settings at the Source level (not specific to Apps) - these use SettingsProvider
|
// Some Sources may have additional settings at the Source level (not specific to Apps) - these use SettingsProvider
|
||||||
List<GeneratedFormItem> additionalSourceSpecificSettingFormItems = [];
|
List<GeneratedFormItem> additionalSourceSpecificSettingFormItems = [];
|
||||||
|
|
||||||
@ -220,7 +226,7 @@ class AppSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String? tryInferringAppId(String standardUrl,
|
String? tryInferringAppId(String standardUrl,
|
||||||
{Map<String, String> additionalData = const {}}) {
|
{Map<String, String> additionalSettings = const {}}) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -280,8 +286,8 @@ class SourceProvider {
|
|||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ifSourceAppsRequireAdditionalData(AppSource source) {
|
bool ifRequiredAppSpecificSettingsExist(AppSource source) {
|
||||||
for (var row in source.additionalSourceAppSpecificFormItems) {
|
for (var row in source.combinedAppSpecificSettingFormItems) {
|
||||||
for (var element in row) {
|
for (var element in row) {
|
||||||
if (element.required && element.opts == null) {
|
if (element.required && element.opts == null) {
|
||||||
return true;
|
return true;
|
||||||
@ -309,15 +315,20 @@ class SourceProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<App> getApp(
|
Future<App> getApp(
|
||||||
AppSource source, String url, Map<String, String> additionalData,
|
AppSource source, String url, Map<String, String> additionalSettings,
|
||||||
{App? currentApp,
|
{App? currentApp,
|
||||||
bool trackOnlyOverride = false,
|
bool trackOnlyOverride = false,
|
||||||
noVersionDetectionOverride = false}) async {
|
noVersionDetectionOverride = false}) async {
|
||||||
var trackOnly = trackOnlyOverride || (currentApp?.trackOnly ?? false);
|
if (trackOnlyOverride) {
|
||||||
|
additionalSettings['trackOnly'] = 'true';
|
||||||
|
}
|
||||||
|
if (noVersionDetectionOverride) {
|
||||||
|
additionalSettings['noVersionDetection'] = 'true';
|
||||||
|
}
|
||||||
|
var trackOnly = currentApp?.additionalSettings['trackOnly'] == 'true';
|
||||||
String standardUrl = source.standardizeURL(preStandardizeUrl(url));
|
String standardUrl = source.standardizeURL(preStandardizeUrl(url));
|
||||||
APKDetails apk = await source
|
APKDetails apk =
|
||||||
.getLatestAPKDetails(standardUrl, additionalData, trackOnly: trackOnly);
|
await source.getLatestAPKDetails(standardUrl, additionalSettings);
|
||||||
if (apk.apkUrls.isEmpty && !trackOnly) {
|
if (apk.apkUrls.isEmpty && !trackOnly) {
|
||||||
throw NoAPKError();
|
throw NoAPKError();
|
||||||
}
|
}
|
||||||
@ -327,7 +338,7 @@ class SourceProvider {
|
|||||||
return App(
|
return App(
|
||||||
currentApp?.id ??
|
currentApp?.id ??
|
||||||
source.tryInferringAppId(standardUrl,
|
source.tryInferringAppId(standardUrl,
|
||||||
additionalData: additionalData) ??
|
additionalSettings: additionalSettings) ??
|
||||||
generateTempID(apk.names, source),
|
generateTempID(apk.names, source),
|
||||||
standardUrl,
|
standardUrl,
|
||||||
apk.names.author[0].toUpperCase() + apk.names.author.substring(1),
|
apk.names.author[0].toUpperCase() + apk.names.author.substring(1),
|
||||||
@ -338,12 +349,9 @@ class SourceProvider {
|
|||||||
apkVersion,
|
apkVersion,
|
||||||
apk.apkUrls,
|
apk.apkUrls,
|
||||||
apk.apkUrls.length - 1,
|
apk.apkUrls.length - 1,
|
||||||
additionalData,
|
additionalSettings,
|
||||||
DateTime.now(),
|
DateTime.now(),
|
||||||
currentApp?.pinned ?? false,
|
currentApp?.pinned ?? false);
|
||||||
trackOnly,
|
|
||||||
noVersionDetection: noVersionDetectionOverride ||
|
|
||||||
(currentApp?.noVersionDetection ?? false));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns errors in [results, errors] instead of throwing them
|
// Returns errors in [results, errors] instead of throwing them
|
||||||
@ -358,7 +366,7 @@ class SourceProvider {
|
|||||||
source,
|
source,
|
||||||
url,
|
url,
|
||||||
getDefaultValuesFromFormItems(
|
getDefaultValuesFromFormItems(
|
||||||
source.additionalSourceAppSpecificFormItems)));
|
source.combinedAppSpecificSettingFormItems)));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
errors.addAll(<String, dynamic>{url: e});
|
errors.addAll(<String, dynamic>{url: e});
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user