From 98991a3d0252ccf227e31498a3fcae7c46ad0b8c Mon Sep 17 00:00:00 2001 From: Brandon Presley Date: Wed, 29 Nov 2023 16:57:19 +1300 Subject: [PATCH] Replace database import with CSV import --- lib/database.dart | 38 ++--------------------- lib/delete_all_sets.dart | 51 ++++++++++++++++++++++++++++++ lib/settings_page.dart | 67 +++++++++++++++++++++++++--------------- pubspec.lock | 8 +++++ pubspec.yaml | 1 + 5 files changed, 104 insertions(+), 61 deletions(-) create mode 100644 lib/delete_all_sets.dart diff --git a/lib/database.dart b/lib/database.dart index c575b8d..b348ab9 100644 --- a/lib/database.dart +++ b/lib/database.dart @@ -17,7 +17,7 @@ class MyDatabase extends _$MyDatabase { MyDatabase() : super(_openConnection()); @override - int get schemaVersion => 3; + int get schemaVersion => 1; @override MigrationStrategy get migration => MigrationStrategy( @@ -27,41 +27,7 @@ class MyDatabase extends _$MyDatabase { var data = await (db.select(db.settings)..limit(1)).get(); if (data.isEmpty) await db.into(db.settings).insert(defaultSettings); }, - onUpgrade: (Migrator m, int from, int to) async { - if (from == 1) { - await m.create(db.gymSets); - await db.customInsert(''' - INSERT INTO gym_sets(id, name, reps, weight, created, unit, hidden, image, sets, minutes, seconds, steps) - SELECT id, name, reps, weight, created, unit, hidden, image, sets, minutes, seconds, steps FROM sets - '''); - await m.addColumn(settings, settings.darkColor); - await db.customStatement(''' - UPDATE settings SET dark_color = darkColor - '''); - await m.addColumn(settings, settings.lightColor); - await db.customStatement(''' - UPDATE settings SET light_color = lightColor - '''); - await m.addColumn(settings, settings.showDate); - await db.customStatement(''' - UPDATE settings SET show_date = showDate - '''); - await m.addColumn(settings, settings.showSets); - await db.customStatement(''' - UPDATE settings SET show_sets = showSets - '''); - await m.addColumn(settings, settings.showUnit); - await db.customStatement(''' - UPDATE settings SET show_unit = showUnit - '''); - } - if (from == 2) { - await m.addColumn(settings, settings.noSound); - await db.customStatement(''' - UPDATE settings SET no_sound = noSound - '''); - } - }, + onUpgrade: (Migrator m, int from, int to) async {}, ); } diff --git a/lib/delete_all_sets.dart b/lib/delete_all_sets.dart new file mode 100644 index 0000000..8e240ad --- /dev/null +++ b/lib/delete_all_sets.dart @@ -0,0 +1,51 @@ +import 'package:flutter/material.dart'; +import 'package:fmassive/main.dart'; +import 'package:moor/moor.dart'; + +class DeleteAllSets extends StatelessWidget { + const DeleteAllSets({ + super.key, + required this.mounted, + }); + + final bool mounted; + + @override + Widget build(BuildContext context) { + return Center( + child: ElevatedButton( + child: const Text("Delete all sets"), + onPressed: () async { + showDialog( + context: context, + builder: (context) { + return AlertDialog( + title: const Text("Delete all sets"), + content: const Text( + "This will irreversibly destroy all your gym set data. Are you sure?"), + actions: [ + ElevatedButton( + child: const Text('Cancel'), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ElevatedButton( + child: const Text('Delete'), + onPressed: () async { + await db.gymSets.delete().go(); + if (!mounted) return; + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('Deleted all sets'))); + final navigator = Navigator.of(context); + navigator.pop(); + }, + ), + ], + ); + }); + }, + ), + ); + } +} diff --git a/lib/settings_page.dart b/lib/settings_page.dart index 2b9d7e7..fff7a19 100644 --- a/lib/settings_page.dart +++ b/lib/settings_page.dart @@ -1,14 +1,15 @@ +import 'dart:convert'; import 'dart:io'; +import 'package:csv/csv.dart'; import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; import 'package:flutter/material.dart' as material; import 'package:fmassive/database.dart'; +import 'package:fmassive/delete_all_sets.dart'; import 'package:fmassive/main.dart'; import 'package:fmassive/sound_picker.dart'; import 'package:moor/moor.dart'; -import 'package:path/path.dart'; -import 'package:sqflite/sqflite.dart'; class SettingsPage extends StatelessWidget { const SettingsPage({super.key, required this.search}); @@ -63,7 +64,8 @@ class _SettingsPageState extends State<_SettingsPage> { {'title': 'Show Unit', 'value': settings.showUnit}, {'title': 'Steps', 'value': settings.steps}, {'title': 'Sound', 'value': settings.sound}, - {'title': 'Import', 'value': settings.sound}, + {'title': 'Import', 'value': null}, + {'title': 'Delete all sets', 'value': null}, ] .where((item) => (item['title'] as String) .toLowerCase() @@ -78,32 +80,47 @@ class _SettingsPageState extends State<_SettingsPage> { itemBuilder: (context, index) { final item = filteredItems[index]; + if (item['title'] == 'Delete all sets') + return DeleteAllSets(mounted: mounted); + if (item['title'] == 'Import') return Center( child: ElevatedButton( - onPressed: () async { - final result = - await FilePicker.platform.pickFiles( - type: FileType.any, - ); - if (result == null) return; + child: const Text("Import"), + onPressed: () async { + final result = await FilePicker.platform.pickFiles( + type: FileType.custom, + allowedExtensions: ['csv']); + if (result == null) return; - final file = File(result.files.single.path!); - final path = await getDatabasesPath(); - final to = join(path, 'massive.db'); - await db.close(); - await file.copy(to); - print('Migrating...'); - db = MyDatabase(); - // ignore: invalid_use_of_protected_member, invalid_use_of_visible_for_testing_member - final migrator = db.createMigrator(); - await migrator.createAll(); - await db.update(db.settings).write( - const SettingsCompanion( - sound: Value(null))); - print('Migrated.'); - }, - child: const Text("Import"))); + final file = File(result.files.single.path!); + final input = file.openRead(); + final fields = await input + .transform(utf8.decoder) + .transform(const CsvToListConverter(eol: "\n")) + .skip(1) + .toList(); + final gymSets = fields.map((row) => GymSetsCompanion( + id: Value(int.tryParse(row[0]) ?? 0), + name: Value(row[1]), + reps: Value(int.tryParse(row[2]) ?? 0), + weight: Value(double.tryParse(row[3]) ?? 0), + created: Value(row[4]), + unit: Value(row[5]), + hidden: Value(row[6] == 'true'), + image: Value(row[7]), + sets: Value(int.tryParse(row[8]) ?? 0), + minutes: Value(int.tryParse(row[9]) ?? 0), + seconds: Value(int.tryParse(row[10]) ?? 0), + steps: Value(row[11]), + )); + await db.batch( + (batch) => batch.insertAll(db.gymSets, gymSets)); + if (!mounted) return; + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('Imported data'))); + }, + )); if (item['title'] == 'Sound') { return Center( diff --git a/pubspec.lock b/pubspec.lock index c930cbe..59fbcf5 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -241,6 +241,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.3" + csv: + dependency: "direct main" + description: + name: csv + sha256: "63ed2871dd6471193dffc52c0e6c76fb86269c00244d244297abbb355c84a86e" + url: "https://pub.dev" + source: hosted + version: "5.1.1" cupertino_icons: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 206d049..ed62233 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -47,6 +47,7 @@ dependencies: intl: ^0.18.0 permission_handler: ^11.0.1 infinite_scroll_pagination: ^4.0.0 + csv: ^5.1.1 dev_dependencies: flutter_test: