From 27d91cbbcb23d2a39b175142f0b04f6bf86420d1 Mon Sep 17 00:00:00 2001 From: Prasanna Anbazhagan Date: Sat, 6 Jan 2024 09:59:28 +0530 Subject: [PATCH] import file code --- lib/api/apis/backup_api.dart | 51 ++++++++++++++++++++++++---- lib/api/db/app_database.dart | 22 ++++++++++++ lib/presentation/main_presenter.dart | 28 +++++++++++++++ lib/ui/pages/main_page.dart | 18 +++++++--- 4 files changed, 108 insertions(+), 11 deletions(-) create mode 100644 lib/presentation/main_presenter.dart diff --git a/lib/api/apis/backup_api.dart b/lib/api/apis/backup_api.dart index 4795dc9..176724d 100644 --- a/lib/api/apis/backup_api.dart +++ b/lib/api/apis/backup_api.dart @@ -1,9 +1,9 @@ import 'dart:convert'; // ignore: avoid_web_libraries_in_flutter -import 'dart:html' as html; - +import 'dart:html'; import 'package:flutter/services.dart'; +import 'package:logger/logger.dart'; import 'package:wealth_wave/api/db/app_database.dart'; class BackupApi { @@ -11,21 +11,60 @@ class BackupApi { BackupApi({final AppDatabase? db}) : _db = db ?? AppDatabase.instance; + Future importDatabase() async { + final file = await _pickFile(); + if (file == null) { + return Future.error('No file selected'); + } + + final json = await _readJsonFromFile(file); + + if (json == null) { + return Future.error('Not a json file'); + } + + await _db.loadBackup(json); + } + Future exportDatabase() async { final result = await _db.getBackup(); final jsonString = json.encode(result); - final blob = html.Blob([Uint8List.fromList(utf8.encode(jsonString))]); + final blob = Blob([Uint8List.fromList(utf8.encode(jsonString))]); - final anchor = html.AnchorElement(href: html.Url.createObjectUrlFromBlob(blob)) + final anchor = AnchorElement(href: Url.createObjectUrlFromBlob(blob)) ..target = 'blank' ..download = 'wealth_app_data.json'; // Trigger a click event to prompt the user to download the file - html.document.body?.append(anchor); + document.body?.append(anchor); anchor.click(); // Clean up - html.Url.revokeObjectUrl(anchor.href!); + Url.revokeObjectUrl(anchor.href!); + } + + Future _pickFile() async { + final input = FileUploadInputElement()..accept = 'application/json'; + input.click(); + + await input.onChange.first; + return input.files?.isNotEmpty == true ? input.files![0] : null; + } + + Future>>?> _readJsonFromFile( + File file) async { + try { + final reader = FileReader(); + reader.readAsText(file); + + await reader.onLoad.first; + + final jsonString = reader.result as String; + return json.decode(jsonString) as Map>>; + } catch (e) { + Logger().e(e.toString()); + return null; + } } } diff --git a/lib/api/db/app_database.dart b/lib/api/db/app_database.dart index b290e96..f136638 100644 --- a/lib/api/db/app_database.dart +++ b/lib/api/db/app_database.dart @@ -169,6 +169,28 @@ class AppDatabase extends _$AppDatabase { 'goal_investment_table': goalInvestmentBackup, }; } + + Future loadBackup( + Map>> backup) async { + await transaction(() async { + for (var entry in backup.entries) { + var tableName = entry.key; + var tableDatas = entry.value; + + for (var tableData in tableDatas) { + var columns = tableData.keys.join(', '); + var values = tableData.keys.map((key) => '?').join(', '); + + await customInsert( + 'INSERT INTO $tableName ($columns) VALUES ($values)', + variables: tableData.values + .map((value) => Variable.withString('$value')) + .toList(), + ); + } + } + }); + } } DatabaseConnection connectOnWeb() { diff --git a/lib/presentation/main_presenter.dart b/lib/presentation/main_presenter.dart new file mode 100644 index 0000000..6d938c6 --- /dev/null +++ b/lib/presentation/main_presenter.dart @@ -0,0 +1,28 @@ +import 'package:wealth_wave/api/apis/backup_api.dart'; +import 'package:wealth_wave/core/presenter.dart'; +import 'package:wealth_wave/core/single_event.dart'; + +class MainPresenter extends Presenter { + final BackupApi _backupApi; + + MainPresenter({final BackupApi? backupApi}) + : _backupApi = backupApi ?? BackupApi(), + super(MainViewState()); + + void performImportFile() { + _backupApi.importDatabase().then((value) => updateViewState((viewState) { + viewState.onImportCompleted = SingleEvent(null); + })); + } + + void performBackup() { + _backupApi.exportDatabase().then((value) => updateViewState((viewState) { + viewState.onBackupCompleted = SingleEvent(null); + })); + } +} + +class MainViewState { + SingleEvent? onBackupCompleted; + SingleEvent? onImportCompleted; +} diff --git a/lib/ui/pages/main_page.dart b/lib/ui/pages/main_page.dart index 72710c9..fd32bae 100644 --- a/lib/ui/pages/main_page.dart +++ b/lib/ui/pages/main_page.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:wealth_wave/api/apis/backup_api.dart'; +import 'package:wealth_wave/core/page_state.dart'; +import 'package:wealth_wave/presentation/main_presenter.dart'; import 'package:wealth_wave/ui/pages/baskets_page.dart'; import 'package:wealth_wave/ui/pages/goals_page.dart'; import 'package:wealth_wave/ui/pages/investments_page.dart'; @@ -13,12 +14,12 @@ class MainPage extends StatefulWidget { State createState() => _MainPageState(); } -class _MainPageState extends State { +class _MainPageState extends PageState { var _selectedIndex = 0; var _isExtended = true; @override - Widget build(BuildContext context) { + Widget buildWidget(BuildContext context, MainViewState snapshot) { return Scaffold( appBar: AppBar( backgroundColor: Theme.of(context).colorScheme.inversePrimary, @@ -27,8 +28,10 @@ class _MainPageState extends State { PopupMenuButton( onSelected: (value) { if (value == 1) { - BackupApi().exportDatabase(); - } else if (value == 2) {} + presenter.performBackup(); + } else if (value == 2) { + presenter.performImportFile(); + } }, itemBuilder: (context) => [ const PopupMenuItem( @@ -91,6 +94,11 @@ class _MainPageState extends State { ), )); } + + @override + MainPresenter initializePresenter() { + return MainPresenter(); + } } class SideNav extends StatelessWidget {