diff --git a/lib/app_sources/apkmirror.dart b/lib/app_sources/apkmirror.dart index 1372d16..c0efb87 100644 --- a/lib/app_sources/apkmirror.dart +++ b/lib/app_sources/apkmirror.dart @@ -25,7 +25,7 @@ class APKMirror extends AppSource { @override Future getLatestAPKDetails( - String standardUrl, List additionalData, + String standardUrl, Map additionalData, {bool trackOnly = false}) async { Response res = await get(Uri.parse('$standardUrl/feed')); if (res.statusCode == 200) { diff --git a/lib/app_sources/fdroid.dart b/lib/app_sources/fdroid.dart index 8b7af89..fc4f4d1 100644 --- a/lib/app_sources/fdroid.dart +++ b/lib/app_sources/fdroid.dart @@ -32,7 +32,7 @@ class FDroid extends AppSource { @override String? tryInferringAppId(String standardUrl, - {List additionalData = const []}) { + {Map additionalData = const {}}) { return Uri.parse(standardUrl).pathSegments.last; } @@ -60,7 +60,7 @@ class FDroid extends AppSource { @override Future getLatestAPKDetails( - String standardUrl, List additionalData, + String standardUrl, Map additionalData, {bool trackOnly = false}) async { String? appId = tryInferringAppId(standardUrl); return getAPKUrlsFromFDroidPackagesAPIResponse( diff --git a/lib/app_sources/fdroidrepo.dart b/lib/app_sources/fdroidrepo.dart index c13a51d..7b537ef 100644 --- a/lib/app_sources/fdroidrepo.dart +++ b/lib/app_sources/fdroidrepo.dart @@ -11,11 +11,10 @@ class FDroidRepo extends AppSource { additionalSourceAppSpecificFormItems = [ [ - GeneratedFormItem( + GeneratedFormItem('appIdOrName', label: tr('appIdOrName'), hint: tr('reposHaveMultipleApps'), - required: true, - key: 'appIdOrName') + required: true) ] ]; } @@ -33,13 +32,9 @@ class FDroidRepo extends AppSource { @override Future getLatestAPKDetails( - String standardUrl, List additionalData, + String standardUrl, Map additionalData, {bool trackOnly = false}) async { - String? appIdOrName = findGeneratedFormValueByKey( - additionalSourceAppSpecificFormItems - .reduce((value, element) => [...value, ...element]), - additionalData, - 'appIdOrName'); + String? appIdOrName = additionalData['appIdOrName']; if (appIdOrName == null) { throw NoReleasesError(); } diff --git a/lib/app_sources/github.dart b/lib/app_sources/github.dart index 3fdbf4a..ed8f007 100644 --- a/lib/app_sources/github.dart +++ b/lib/app_sources/github.dart @@ -12,12 +12,9 @@ class GitHub extends AppSource { GitHub() { host = 'github.com'; - additionalSourceAppSpecificDefaults = ['true', 'true', '']; - additionalSourceSpecificSettingFormItems = [ - GeneratedFormItem( + GeneratedFormItem('github-creds', label: tr('githubPATLabel'), - id: 'github-creds', required: false, additionalValidators: [ (value) { @@ -52,17 +49,23 @@ class GitHub extends AppSource { ]) ]; + additionalSourceAppSpecificDefaults = { + 'includePrereleases': 'true', + 'fallbackToOlderReleases': 'true', + 'filterReleaseTitlesByRegEx': '' + }; + additionalSourceAppSpecificFormItems = [ [ - GeneratedFormItem( + GeneratedFormItem('includePrereleases', label: tr('includePrereleases'), type: FormItemType.bool) ], [ - GeneratedFormItem( + GeneratedFormItem('fallbackToOlderReleases', label: tr('fallbackToOlderReleases'), type: FormItemType.bool) ], [ - GeneratedFormItem( + GeneratedFormItem('filterReleaseTitlesByRegEx', label: tr('filterReleaseTitlesByRegEx'), type: FormItemType.string, required: false, @@ -99,7 +102,7 @@ class GitHub extends AppSource { SettingsProvider settingsProvider = SettingsProvider(); await settingsProvider.initializeSettings(); String? creds = settingsProvider - .getSettingString(additionalSourceSpecificSettingFormItems[0].id); + .getSettingString(additionalSourceSpecificSettingFormItems[0].key); return creds != null && creds.isNotEmpty ? '$creds@' : ''; } @@ -109,15 +112,15 @@ class GitHub extends AppSource { @override Future getLatestAPKDetails( - String standardUrl, List additionalData, + String standardUrl, Map additionalData, {bool trackOnly = false}) async { - var includePrereleases = - additionalData.isNotEmpty && additionalData[0] == 'true'; + var includePrereleases = additionalData['includePrereleases'] == 'true'; var fallbackToOlderReleases = - additionalData.length >= 2 && additionalData[1] == 'true'; - var regexFilter = additionalData.length >= 3 && additionalData[2].isNotEmpty - ? additionalData[2] - : null; + additionalData['fallbackToOlderReleases'] == 'true'; + var regexFilter = + additionalData['filterReleaseTitlesByRegEx']?.isNotEmpty == true + ? additionalData['filterReleaseTitlesByRegEx'] + : null; Response res = await get(Uri.parse( 'https://${await getCredentialPrefixIfAny()}api.$host/repos${standardUrl.substring('https://$host'.length)}/releases')); if (res.statusCode == 200) { diff --git a/lib/app_sources/gitlab.dart b/lib/app_sources/gitlab.dart index 6c2f5ab..efaff00 100644 --- a/lib/app_sources/gitlab.dart +++ b/lib/app_sources/gitlab.dart @@ -25,7 +25,7 @@ class GitLab extends AppSource { @override Future getLatestAPKDetails( - String standardUrl, List additionalData, + String standardUrl, Map additionalData, {bool trackOnly = false}) async { Response res = await get(Uri.parse('$standardUrl/-/tags?format=atom')); if (res.statusCode == 200) { diff --git a/lib/app_sources/izzyondroid.dart b/lib/app_sources/izzyondroid.dart index 13ea4bd..d2b08f1 100644 --- a/lib/app_sources/izzyondroid.dart +++ b/lib/app_sources/izzyondroid.dart @@ -23,13 +23,13 @@ class IzzyOnDroid extends AppSource { @override String? tryInferringAppId(String standardUrl, - {List additionalData = const []}) { + {Map additionalData = const {}}) { return FDroid().tryInferringAppId(standardUrl); } @override Future getLatestAPKDetails( - String standardUrl, List additionalData, + String standardUrl, Map additionalData, {bool trackOnly = false}) async { String? appId = tryInferringAppId(standardUrl); return FDroid().getAPKUrlsFromFDroidPackagesAPIResponse( diff --git a/lib/app_sources/mullvad.dart b/lib/app_sources/mullvad.dart index 353e460..f19ab6a 100644 --- a/lib/app_sources/mullvad.dart +++ b/lib/app_sources/mullvad.dart @@ -24,7 +24,7 @@ class Mullvad extends AppSource { @override Future getLatestAPKDetails( - String standardUrl, List additionalData, + String standardUrl, Map additionalData, {bool trackOnly = false}) async { Response res = await get(Uri.parse('$standardUrl/en/download/android')); if (res.statusCode == 200) { diff --git a/lib/app_sources/signal.dart b/lib/app_sources/signal.dart index 517a7df..dbf88fb 100644 --- a/lib/app_sources/signal.dart +++ b/lib/app_sources/signal.dart @@ -18,7 +18,7 @@ class Signal extends AppSource { @override Future getLatestAPKDetails( - String standardUrl, List additionalData, + String standardUrl, Map additionalData, {bool trackOnly = false}) async { Response res = await get(Uri.parse('https://updates.$host/android/latest.json')); diff --git a/lib/app_sources/sourceforge.dart b/lib/app_sources/sourceforge.dart index 6961ea8..8ad3e48 100644 --- a/lib/app_sources/sourceforge.dart +++ b/lib/app_sources/sourceforge.dart @@ -23,7 +23,7 @@ class SourceForge extends AppSource { @override Future getLatestAPKDetails( - String standardUrl, List additionalData, + String standardUrl, Map additionalData, {bool trackOnly = false}) async { Response res = await get(Uri.parse('$standardUrl/rss?path=/')); if (res.statusCode == 200) { diff --git a/lib/app_sources/steammobile.dart b/lib/app_sources/steammobile.dart index f202bd8..db9ec94 100644 --- a/lib/app_sources/steammobile.dart +++ b/lib/app_sources/steammobile.dart @@ -11,11 +11,8 @@ class SteamMobile extends AppSource { name = tr('steam'); additionalSourceAppSpecificFormItems = [ [ - GeneratedFormItem( - label: tr('app'), - key: 'app', - required: true, - opts: apks.entries.toList()) + GeneratedFormItem('app', + label: tr('app'), required: true, opts: apks.entries.toList()) ] ]; } @@ -32,15 +29,11 @@ class SteamMobile extends AppSource { @override Future getLatestAPKDetails( - String standardUrl, List additionalData, + String standardUrl, Map additionalData, {bool trackOnly = false}) async { Response res = await get(Uri.parse('https://$host/mobile')); if (res.statusCode == 200) { - var apkNamePrefix = findGeneratedFormValueByKey( - additionalSourceAppSpecificFormItems - .reduce((value, element) => [...value, ...element]), - additionalData, - 'app'); + var apkNamePrefix = additionalData['app']; if (apkNamePrefix == null) { throw NoReleasesError(); } diff --git a/lib/components/generated_form.dart b/lib/components/generated_form.dart index c0ae67f..9bf76ed 100644 --- a/lib/components/generated_form.dart +++ b/lib/components/generated_form.dart @@ -4,7 +4,7 @@ import 'package:flutter/material.dart'; enum FormItemType { string, bool } typedef OnValueChanges = void Function( - List values, bool valid, bool isBuilding); + Map values, bool valid, bool isBuilding); class GeneratedFormItem { late String key; @@ -13,22 +13,19 @@ class GeneratedFormItem { late bool required; late int max; late List additionalValidators; - late String id; late List belowWidgets; late String? hint; late List>? opts; - GeneratedFormItem( + GeneratedFormItem(this.key, {this.label = 'Input', this.type = FormItemType.string, this.required = true, this.max = 1, this.additionalValidators = const [], - this.id = 'input', this.belowWidgets = const [], this.hint, - this.opts, - this.key = 'default'}) { + this.opts}) { if (type != FormItemType.string) { required = false; } @@ -44,7 +41,7 @@ class GeneratedForm extends StatefulWidget { final List> items; final OnValueChanges onValueChanges; - final List defaultValues; + final Map defaultValues; @override State createState() => _GeneratedFormState(); @@ -52,17 +49,18 @@ class GeneratedForm extends StatefulWidget { class _GeneratedFormState extends State { final _formKey = GlobalKey(); - late List> values; + Map values = {}; late List> formInputs; List> rows = []; // If any value changes, call this to update the parent with value and validity void someValueChanged({bool isBuilding = false}) { - List returnValues = []; + Map returnValues = {}; var valid = true; - for (int r = 0; r < values.length; r++) { - for (int i = 0; i < values[r].length; i++) { - returnValues.add(values[r][i]); + for (int r = 0; r < widget.items.length; r++) { + for (int i = 0; i < widget.items[r].length; i++) { + returnValues[widget.items[r][i].key] = + values[widget.items[r][i].key] ?? ''; if (formInputs[r][i] is TextFormField) { valid = valid && ((formInputs[r][i].key as GlobalKey) @@ -80,16 +78,13 @@ class _GeneratedFormState extends State { super.initState(); // Initialize form values as all empty + values.clear(); int j = 0; - values = widget.items - .map((row) => row.map((e) { - return j < widget.defaultValues.length - ? widget.defaultValues[j++] - : e.opts != null - ? e.opts!.first.key - : ''; - }).toList()) - .toList(); + for (var row in widget.items) { + for (var e in row) { + values[e.key] = widget.defaultValues[e.key] ?? e.opts?.first.key ?? ''; + } + } // Dynamically create form inputs formInputs = widget.items.asMap().entries.map((row) { @@ -98,11 +93,11 @@ class _GeneratedFormState extends State { final formFieldKey = GlobalKey(); return TextFormField( key: formFieldKey, - initialValue: values[row.key][e.key], + initialValue: values[e.value.key], autovalidateMode: AutovalidateMode.onUserInteraction, onChanged: (value) { setState(() { - values[row.key][e.key] = value; + values[e.value.key] = value; someValueChanged(); }); }, @@ -131,14 +126,14 @@ class _GeneratedFormState extends State { } return DropdownButtonFormField( decoration: InputDecoration(labelText: e.value.label), - value: values[row.key][e.key], + value: values[e.value.key], items: e.value.opts! .map((e) => DropdownMenuItem(value: e.key, child: Text(e.value))) .toList(), onChanged: (value) { setState(() { - values[row.key][e.key] = value ?? e.value.opts!.first.key; + values[e.value.key] = value ?? e.value.opts!.first.key; someValueChanged(); }); }); @@ -160,10 +155,10 @@ class _GeneratedFormState extends State { children: [ Text(widget.items[r][e].label), Switch( - value: values[r][e] == 'true', + value: values[widget.items[r][e].key] == 'true', onChanged: (value) { setState(() { - values[r][e] = value ? 'true' : ''; + values[widget.items[r][e].key] = value ? 'true' : ''; someValueChanged(); }); }) @@ -217,18 +212,3 @@ class _GeneratedFormState extends State { )); } } - -String? findGeneratedFormValueByKey( - List items, List values, String key) { - var foundIndex = -1; - for (var i = 0; i < items.length; i++) { - if (items[i].key == key) { - foundIndex = i; - break; - } - } - if (foundIndex >= 0 && foundIndex < values.length) { - return values[foundIndex]; - } - return null; -} diff --git a/lib/components/generated_form_modal.dart b/lib/components/generated_form_modal.dart index 5ea70ff..66afdd8 100644 --- a/lib/components/generated_form_modal.dart +++ b/lib/components/generated_form_modal.dart @@ -15,7 +15,7 @@ class GeneratedFormModal extends StatefulWidget { final String title; final String message; final List> items; - final List defaultValues; + final Map defaultValues; final bool initValid; @override @@ -23,13 +23,15 @@ class GeneratedFormModal extends StatefulWidget { } class _GeneratedFormModalState extends State { - List values = []; + Map values = {}; bool valid = false; @override void initState() { super.initState(); - values = widget.defaultValues; + widget.defaultValues.forEach((key, value) { + values[key] = value; + }); valid = widget.initValid || widget.items.isEmpty; } diff --git a/lib/main.dart b/lib/main.dart index 2f614d9..0e17272 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -200,7 +200,7 @@ class _ObtainiumState extends State { currentReleaseTag, [], 0, - ['true'], + {}, null, false, false) diff --git a/lib/pages/add_app.dart b/lib/pages/add_app.dart index 40e1f40..a3659d4 100644 --- a/lib/pages/add_app.dart +++ b/lib/pages/add_app.dart @@ -27,9 +27,9 @@ class _AddAppPageState extends State { String userInput = ''; String searchQuery = ''; AppSource? pickedSource; - List sourceSpecificAdditionalData = []; + Map sourceSpecificAdditionalData = {}; bool sourceSpecificDataIsValid = true; - List otherAdditionalData = []; + Map otherAdditionalData = {}; bool otherAdditionalDataIsValid = true; @override @@ -44,7 +44,7 @@ class _AddAppPageState extends State { if (pickedSource.runtimeType != source.runtimeType) { pickedSource = source; sourceSpecificAdditionalData = - source != null ? source.additionalSourceAppSpecificDefaults : []; + source != null ? source.additionalSourceAppSpecificDefaults : {}; sourceSpecificDataIsValid = source != null ? !sourceProvider.ifSourceAppsRequireAdditionalData(source) : true; @@ -66,16 +66,10 @@ class _AddAppPageState extends State { }); var settingsProvider = context.read(); () async { - var userPickedTrackOnly = findGeneratedFormValueByKey( - pickedSource!.additionalAppSpecificSourceAgnosticFormItems, - otherAdditionalData, - 'trackOnlyFormItemKey') == - 'true'; - var userPickedNoVersionDetection = findGeneratedFormValueByKey( - pickedSource!.additionalAppSpecificSourceAgnosticFormItems, - otherAdditionalData, - 'noVersionDetectionKey') == - 'true'; + var userPickedTrackOnly = + otherAdditionalData['trackOnlyFormItemKey'] == 'true'; + var userPickedNoVersionDetection = + otherAdditionalData['noVersionDetectionKey'] == 'true'; var cont = true; if ((userPickedTrackOnly || pickedSource!.enforceTrackOnly) && await showDialog( @@ -88,7 +82,7 @@ class _AddAppPageState extends State { : tr('app') ]), items: const [], - defaultValues: const [], + defaultValues: const {}, message: '${pickedSource!.enforceTrackOnly ? tr('appsFromSourceAreTrackOnly') : tr('youPickedTrackOnly')}\n\n${tr('trackOnlyAppDescription')}', ); @@ -100,10 +94,10 @@ class _AddAppPageState extends State { await showDialog( context: context, builder: (BuildContext ctx) { - return GeneratedFormModal( + return const GeneratedFormModal( title: 'Disable Version Detection', // TODO - items: const [], - defaultValues: const [], + items: [], + defaultValues: {}, message: 'TODO', ); }) == @@ -177,7 +171,7 @@ class _AddAppPageState extends State { child: GeneratedForm( items: [ [ - GeneratedFormItem( + GeneratedFormItem('appSourceURL', label: tr('appSourceURL'), additionalValidators: [ (value) { @@ -200,10 +194,10 @@ class _AddAppPageState extends State { ] ], onValueChanges: (values, valid, isBuilding) { - changeUserInput( - values[0], valid, isBuilding); + changeUserInput(values['appSourceURL']!, + valid, isBuilding); }, - defaultValues: const [])), + defaultValues: const {'appSourceURL': ''})), const SizedBox( width: 16, ), @@ -244,7 +238,7 @@ class _AddAppPageState extends State { child: GeneratedForm( items: [ [ - GeneratedFormItem( + GeneratedFormItem('searchSomeSources', label: tr('searchSomeSourcesLabel'), required: false), ] @@ -252,11 +246,14 @@ class _AddAppPageState extends State { onValueChanges: (values, valid, isBuilding) { if (values.isNotEmpty && valid) { setState(() { - searchQuery = values[0].trim(); + searchQuery = + values['searchSomeSources']!.trim(); }); } }, - defaultValues: const ['']), + defaultValues: const { + 'searchSomeSources': '' + }), ), const SizedBox( width: 16, diff --git a/lib/pages/app.dart b/lib/pages/app.dart index ed8415d..f5581c2 100644 --- a/lib/pages/app.dart +++ b/lib/pages/app.dart @@ -208,7 +208,7 @@ class _AppPageState extends State { onPressed: app?.downloadProgress != null ? null : () { - showDialog>( + showDialog>( context: context, builder: (BuildContext ctx) { return GeneratedFormModal( diff --git a/lib/pages/apps.dart b/lib/pages/apps.dart index 4c34dd8..ba99ca5 100644 --- a/lib/pages/apps.dart +++ b/lib/pages/apps.dart @@ -349,7 +349,7 @@ class AppsPageState extends State { return GeneratedFormModal( title: tr('removeSelectedAppsQuestion'), items: const [], - defaultValues: const [], + defaultValues: const {}, initValid: true, message: tr( 'xWillBeRemovedButRemainInstalled', @@ -377,40 +377,37 @@ class AppsPageState extends State { : () { HapticFeedback.heavyImpact(); List formInputs = []; - List defaultValues = []; + Map defaultValues = {}; if (existingUpdateIdsAllOrSelected.isNotEmpty) { - formInputs.add(GeneratedFormItem( + formInputs.add(GeneratedFormItem('updates', label: tr('updateX', args: [ plural('apps', existingUpdateIdsAllOrSelected.length) ]), - type: FormItemType.bool, - key: 'updates')); - defaultValues.add('true'); + type: FormItemType.bool)); + defaultValues['updates'] = 'true'; } if (newInstallIdsAllOrSelected.isNotEmpty) { - formInputs.add(GeneratedFormItem( + formInputs.add(GeneratedFormItem('installs', label: tr('installX', args: [ plural('apps', newInstallIdsAllOrSelected.length) ]), - type: FormItemType.bool, - key: 'installs')); - defaultValues - .add(defaultValues.isEmpty ? 'true' : ''); + type: FormItemType.bool)); + defaultValues['installs'] = + defaultValues.isEmpty ? 'true' : ''; } if (trackOnlyUpdateIdsAllOrSelected.isNotEmpty) { - formInputs.add(GeneratedFormItem( + formInputs.add(GeneratedFormItem('trackonlies', label: tr('markXTrackOnlyAsUpdated', args: [ plural('apps', trackOnlyUpdateIdsAllOrSelected.length) ]), - type: FormItemType.bool, - key: 'trackonlies')); - defaultValues - .add(defaultValues.isEmpty ? 'true' : ''); + type: FormItemType.bool)); + defaultValues['trackonlies'] = + defaultValues.isEmpty ? 'true' : ''; } - showDialog?>( + showDialog?>( context: context, builder: (BuildContext ctx) { var totalApps = existingUpdateIdsAllOrSelected @@ -430,17 +427,11 @@ class AppsPageState extends State { values = defaultValues; } bool shouldInstallUpdates = - findGeneratedFormValueByKey( - formInputs, values, 'updates') == - 'true'; + values['updates'] == 'true'; bool shouldInstallNew = - findGeneratedFormValueByKey( - formInputs, values, 'installs') == - 'true'; + values['installs'] == 'true'; bool shouldMarkTrackOnlies = - findGeneratedFormValueByKey(formInputs, - values, 'trackonlies') == - 'true'; + values['trackonlies'] == 'true'; (() async { if (shouldInstallNew || shouldInstallUpdates) { @@ -613,7 +604,7 @@ class AppsPageState extends State { title: tr( 'resetInstallStatusForSelectedAppsQuestion'), items: const [], - defaultValues: const [], + defaultValues: const {}, initValid: true, message: tr( 'installStatusOfXWillBeResetExplanation', @@ -683,36 +674,36 @@ class AppsPageState extends State { : FontWeight.bold), ), onPressed: () { - showDialog?>( + showDialog?>( context: context, builder: (BuildContext ctx) { return GeneratedFormModal( title: tr('filterApps'), items: [ [ - GeneratedFormItem( + GeneratedFormItem('appName', label: tr('appName'), required: false), - GeneratedFormItem( + GeneratedFormItem('author', label: tr('author'), required: false) ], [ - GeneratedFormItem( + GeneratedFormItem('upToDateApps', label: tr('upToDateApps'), type: FormItemType.bool) ], [ - GeneratedFormItem( + GeneratedFormItem('nonInstalledApps', label: tr('nonInstalledApps'), type: FormItemType.bool) ] ], defaultValues: filter == null - ? AppsFilter().toValuesArray() - : filter!.toValuesArray()); + ? AppsFilter().toValuesMap() + : filter!.toValuesMap()); }).then((values) { if (values != null) { setState(() { - filter = AppsFilter.fromValuesArray(values); + filter = AppsFilter.fromValuesMap(values); if (AppsFilter().isIdenticalTo(filter!)) { filter = null; } @@ -740,20 +731,20 @@ class AppsFilter { this.includeUptodate = true, this.includeNonInstalled = true}); - List toValuesArray() { - return [ - nameFilter, - authorFilter, - includeUptodate ? 'true' : '', - includeNonInstalled ? 'true' : '' - ]; + Map toValuesMap() { + return { + 'appName': nameFilter, + 'author': authorFilter, + 'upToDateApps': includeUptodate ? 'true' : '', + 'nonInstalledApps': includeNonInstalled ? 'true' : '' + }; } - AppsFilter.fromValuesArray(List values) { - nameFilter = values[0]; - authorFilter = values[1]; - includeUptodate = values[2] == 'true'; - includeNonInstalled = values[3] == 'true'; + AppsFilter.fromValuesMap(Map values) { + nameFilter = values['appName']!; + authorFilter = values['author']!; + includeUptodate = values['upToDateApps'] == 'true'; + includeNonInstalled = values['nonInstalledApps'] == 'true'; } bool isIdenticalTo(AppsFilter other) => diff --git a/lib/pages/import_export.dart b/lib/pages/import_export.dart index 889969b..d6aede6 100644 --- a/lib/pages/import_export.dart +++ b/lib/pages/import_export.dart @@ -145,7 +145,7 @@ class _ImportExportPageState extends State { title: tr('importFromURLList'), items: [ [ - GeneratedFormItem( + GeneratedFormItem('appURLList', label: tr('appURLList'), max: 7, additionalValidators: [ @@ -172,7 +172,7 @@ class _ImportExportPageState extends State { ]) ] ], - defaultValues: const [], + defaultValues: const {}, ); }).then((values) { if (values != null) { @@ -237,11 +237,12 @@ class _ImportExportPageState extends State { items: [ [ GeneratedFormItem( + 'searchQuery', label: tr( 'searchQuery')) ] ], - defaultValues: const [], + defaultValues: const {}, ); }); if (values != null && @@ -346,10 +347,11 @@ class _ImportExportPageState extends State { .requiredArgs .map( (e) => [ - GeneratedFormItem(label: e) + GeneratedFormItem(e, + label: e) ]) .toList(), - defaultValues: const [], + defaultValues: const {}, ); }); if (values != null) { diff --git a/lib/pages/settings.dart b/lib/pages/settings.dart index 8f8befb..cffb56c 100644 --- a/lib/pages/settings.dart +++ b/lib/pages/settings.dart @@ -143,16 +143,16 @@ class _SettingsPageState extends State { .toList(), onValueChanges: (values, valid, isBuilding) { if (valid) { - for (var i = 0; i < values.length; i++) { - settingsProvider.setSettingString( - e.additionalSourceSpecificSettingFormItems[i].id, - values[i]); - } + values.forEach((key, value) { + settingsProvider.setSettingString(key, value); + }); } }, - defaultValues: e.additionalSourceSpecificSettingFormItems.map((e) { - return settingsProvider.getSettingString(e.id) ?? ''; - }).toList()); + defaultValues: Map.fromEntries( + e.additionalSourceSpecificSettingFormItems.map((e) { + return MapEntry( + e.key, settingsProvider.getSettingString(e.key) ?? ''); + }))); } else { return Container(); } diff --git a/lib/providers/source_provider.dart b/lib/providers/source_provider.dart index 28a203f..f6be78e 100644 --- a/lib/providers/source_provider.dart +++ b/lib/providers/source_provider.dart @@ -44,7 +44,7 @@ class App { late String latestVersion; List apkUrls = []; late int preferredApkIndex; - late List additionalData; + late Map additionalData; late DateTime? lastUpdateCheck; bool pinned = false; bool trackOnly = false; @@ -86,7 +86,7 @@ class App { ? SourceProvider() .getSource(json['url']) .additionalSourceAppSpecificDefaults - : List.from(jsonDecode(json['additionalData'])), + : Map.from(jsonDecode(json['additionalData'])), json['lastUpdateCheck'] == null ? null : DateTime.fromMicrosecondsSinceEpoch(json['lastUpdateCheck']), @@ -155,27 +155,30 @@ class AppSource { } Future getLatestAPKDetails( - String standardUrl, List additionalData, + String standardUrl, Map additionalData, {bool trackOnly = false}) { throw NotImplementedError(); } // Different Sources may need different kinds of additional data for Apps List> additionalSourceAppSpecificFormItems = []; - List additionalSourceAppSpecificDefaults = []; + Map additionalSourceAppSpecificDefaults = {}; // Some additional data may be needed for Apps regardless of Source final List additionalAppSpecificSourceAgnosticFormItems = [ GeneratedFormItem( - label: tr('trackOnly'), - type: FormItemType.bool, - key: 'trackOnlyFormItemKey'), - GeneratedFormItem( + 'trackOnlyFormItemKey', + label: tr('trackOnly'), + type: FormItemType.bool, + ), + GeneratedFormItem('noVersionDetectionKey', label: 'Do not attempt version detection', // TODO - type: FormItemType.bool, - key: 'noVersionDetectionKey') + type: FormItemType.bool) ]; - final List additionalAppSpecificSourceAgnosticDefaults = ['', '']; + final Map additionalAppSpecificSourceAgnosticDefaults = { + 'trackOnlyFormItemKey': '', + 'noVersionDetectionKey': '' + }; // Some Sources may have additional settings at the Source level (not specific to Apps) - these use SettingsProvider List additionalSourceSpecificSettingFormItems = []; @@ -194,7 +197,7 @@ class AppSource { } String? tryInferringAppId(String standardUrl, - {List additionalData = const []}) { + {Map additionalData = const {}}) { return null; } } @@ -282,7 +285,8 @@ class SourceProvider { return true; } - Future getApp(AppSource source, String url, List additionalData, + Future getApp( + AppSource source, String url, Map additionalData, {App? currentApp, bool trackOnlyOverride = false, noVersionDetectionOverride = false}) async {