Finished import/export changes

This commit is contained in:
Imran Remtulla
2022-09-17 00:39:56 -04:00
parent 02a5749ba7
commit f966a9e626

View File

@@ -19,41 +19,36 @@ class ImportExportPage extends StatefulWidget {
class _ImportExportPageState extends State<ImportExportPage> { class _ImportExportPageState extends State<ImportExportPage> {
bool gettingAppInfo = false; bool gettingAppInfo = false;
Future<List<List<String>>> addApps(
MassAppSource source,
List<String> args,
SourceProvider sourceProvider,
SettingsProvider settingsProvider,
AppsProvider appsProvider) async {
var urls = await source.getUrls(args);
await settingsProvider.getInstallPermission();
List<dynamic> results = await sourceProvider.getApps(urls);
List<App> apps = results[0];
Map<String, dynamic> errorsMap = results[1];
for (var app in apps) {
if (appsProvider.apps.containsKey(app.id)) {
errorsMap.addAll({app.id: 'App already added'});
} else {
await appsProvider.saveApp(app);
}
}
List<List<String>> errors =
errorsMap.keys.map((e) => [e, errorsMap[e].toString()]).toList();
return errors;
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
SourceProvider sourceProvider = SourceProvider(); SourceProvider sourceProvider = SourceProvider();
var settingsProvider = context.read<SettingsProvider>(); var settingsProvider = context.read<SettingsProvider>();
var appsProvider = context.read<AppsProvider>(); var appsProvider = context.read<AppsProvider>();
Future<List<List<String>>> addApps(List<String> urls) async {
await settingsProvider.getInstallPermission();
List<dynamic> results = await sourceProvider.getApps(urls);
List<App> apps = results[0];
Map<String, dynamic> errorsMap = results[1];
for (var app in apps) {
if (appsProvider.apps.containsKey(app.id)) {
errorsMap.addAll({app.id: 'App already added'});
} else {
await appsProvider.saveApp(app);
}
}
List<List<String>> errors =
errorsMap.keys.map((e) => [e, errorsMap[e].toString()]).toList();
return errors;
}
return Padding( return Padding(
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16), padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
children: [ children: [
ElevatedButton( ElevatedButton(
onPressed: appsProvider.apps.isEmpty onPressed: appsProvider.apps.isEmpty || gettingAppInfo
? null ? null
: () { : () {
HapticFeedback.lightImpact(); HapticFeedback.lightImpact();
@@ -68,59 +63,77 @@ class _ImportExportPageState extends State<ImportExportPage> {
height: 8, height: 8,
), ),
ElevatedButton( ElevatedButton(
onPressed: () { onPressed: gettingAppInfo
HapticFeedback.lightImpact(); ? null
showDialog( : () {
context: context, HapticFeedback.lightImpact();
builder: (BuildContext ctx) { showDialog(
return GeneratedFormModal( context: context,
title: 'Obtainium Import', builder: (BuildContext ctx) {
items: [ return GeneratedFormModal(
GeneratedFormItem( title: 'Obtainium Import',
'Obtainium Export JSON Data', true, 7) items: [
]); GeneratedFormItem(
}).then((values) { 'Obtainium Export JSON Data', true, 7)
if (values != null) { ]);
try { }).then((values) {
jsonDecode(values[0]); if (values != null) {
} catch (e) { try {
throw 'Invalid input'; jsonDecode(values[0]);
} } catch (e) {
appsProvider.importApps(values[0]).then((value) { throw 'Invalid input';
ScaffoldMessenger.of(context).showSnackBar( }
SnackBar( appsProvider.importApps(values[0]).then((value) {
content: Text( ScaffoldMessenger.of(context).showSnackBar(
'$value App${value == 1 ? '' : 's'} Imported')), SnackBar(
); content: Text(
}); '$value App${value == 1 ? '' : 's'} Imported')),
} );
}).catchError((e) { });
ScaffoldMessenger.of(context).showSnackBar( }
SnackBar(content: Text(e.toString())), }).catchError((e) {
); ScaffoldMessenger.of(context).showSnackBar(
}); SnackBar(content: Text(e.toString())),
}, );
});
},
child: const Text('Obtainium Import')), child: const Text('Obtainium Import')),
const Divider( if (gettingAppInfo)
height: 32, Column(
), children: const [
...sourceProvider.massSources SizedBox(
.map((source) => TextButton( height: 14,
onPressed: () { ),
showDialog( LinearProgressIndicator(),
context: context, SizedBox(
builder: (BuildContext ctx) { height: 14,
return GeneratedFormModal( ),
title: 'Import ${source.name}', ],
items: source.requiredArgs )
.map((e) => GeneratedFormItem(e, true, 1)) else
.toList()); const Divider(
}).then((values) { height: 32,
if (values != null) { ),
source.getUrls(values).then((urls) { TextButton(
addApps(source, values, sourceProvider, onPressed: gettingAppInfo
settingsProvider, appsProvider) ? null
.then((errors) { : () {
showDialog(
context: context,
builder: (BuildContext ctx) {
return GeneratedFormModal(
title: 'Import from URL List',
items: [
GeneratedFormItem('App URL List', true, 7)
],
);
}).then((values) {
if (values != null) {
var urls = (values[0] as String).split('\n');
setState(() {
gettingAppInfo = true;
});
addApps(urls).then((errors) {
if (errors.isEmpty) { if (errors.isEmpty) {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar( SnackBar(
@@ -131,68 +144,142 @@ class _ImportExportPageState extends State<ImportExportPage> {
showDialog( showDialog(
context: context, context: context,
builder: (BuildContext ctx) { builder: (BuildContext ctx) {
return AlertDialog( return ImportErrorDialog(
scrollable: true, urlsLength: urls.length,
title: const Text('Import Errors'), errors: errors);
content: Column(
crossAxisAlignment:
CrossAxisAlignment.stretch,
children: [
Text(
'${urls.length - errors.length} of ${urls.length} Apps imported.',
style: Theme.of(context)
.textTheme
.bodyLarge,
),
const SizedBox(height: 16),
Text(
'The following Apps had errors:',
style: Theme.of(context)
.textTheme
.bodyLarge,
),
...errors.map((e) {
return Column(
crossAxisAlignment:
CrossAxisAlignment
.stretch,
children: [
const SizedBox(
height: 16,
),
Text(e[0]),
Text(
e[1],
style: const TextStyle(
fontStyle: FontStyle
.italic),
)
]);
}).toList()
]),
actions: [
TextButton(
onPressed: () {
HapticFeedback.lightImpact();
Navigator.of(context).pop(null);
},
child: const Text('Okay'))
],
);
}); });
} }
}).catchError((e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(e.toString())),
);
}).whenComplete(() {
setState(() {
gettingAppInfo = false;
});
}); });
}).catchError((e) { }
ScaffoldMessenger.of(context).showSnackBar( });
SnackBar(content: Text(e.toString())), },
); child: const Text('Import from URL List')),
}); ...sourceProvider.massSources
} .map((source) => Column(
}); crossAxisAlignment: CrossAxisAlignment.stretch,
}, children: [
child: Text('Import ${source.name}'))) const SizedBox(height: 8),
TextButton(
onPressed: gettingAppInfo
? null
: () {
showDialog(
context: context,
builder: (BuildContext ctx) {
return GeneratedFormModal(
title: 'Import ${source.name}',
items: source.requiredArgs
.map((e) =>
GeneratedFormItem(
e, true, 1))
.toList());
}).then((values) {
if (values != null) {
source.getUrls(values).then((urls) {
setState(() {
gettingAppInfo = true;
});
addApps(urls).then((errors) {
if (errors.isEmpty) {
ScaffoldMessenger.of(context)
.showSnackBar(
SnackBar(
content: Text(
'Imported ${urls.length} Apps')),
);
} else {
showDialog(
context: context,
builder:
(BuildContext ctx) {
return ImportErrorDialog(
urlsLength:
urls.length,
errors: errors);
});
}
}).whenComplete(() {
setState(() {
gettingAppInfo = false;
});
});
}).catchError((e) {
ScaffoldMessenger.of(context)
.showSnackBar(
SnackBar(
content: Text(e.toString())),
);
});
}
});
},
child: Text('Import ${source.name}'))
]))
.toList() .toList()
], ],
)); ));
} }
} }
class ImportErrorDialog extends StatefulWidget {
const ImportErrorDialog(
{super.key, required this.urlsLength, required this.errors});
final int urlsLength;
final List<List<String>> errors;
@override
State<ImportErrorDialog> createState() => _ImportErrorDialogState();
}
class _ImportErrorDialogState extends State<ImportErrorDialog> {
@override
Widget build(BuildContext context) {
return AlertDialog(
scrollable: true,
title: const Text('Import Errors'),
content:
Column(crossAxisAlignment: CrossAxisAlignment.stretch, children: [
Text(
'${widget.urlsLength - widget.errors.length} of ${widget.urlsLength} Apps imported.',
style: Theme.of(context).textTheme.bodyLarge,
),
const SizedBox(height: 16),
Text(
'The following URLs had errors:',
style: Theme.of(context).textTheme.bodyLarge,
),
...widget.errors.map((e) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const SizedBox(
height: 16,
),
Text(e[0]),
Text(
e[1],
style: const TextStyle(fontStyle: FontStyle.italic),
)
]);
}).toList()
]),
actions: [
TextButton(
onPressed: () {
HapticFeedback.lightImpact();
Navigator.of(context).pop(null);
},
child: const Text('Okay'))
],
);
}
}