aboutsummaryrefslogtreecommitdiff
path: root/lib/util
diff options
context:
space:
mode:
Diffstat (limited to 'lib/util')
-rw-r--r--lib/util/file_handler.dart109
-rw-r--r--lib/util/notifications.dart32
-rw-r--r--lib/util/storage_handler.dart20
3 files changed, 161 insertions, 0 deletions
diff --git a/lib/util/file_handler.dart b/lib/util/file_handler.dart
new file mode 100644
index 0000000..0344c60
--- /dev/null
+++ b/lib/util/file_handler.dart
@@ -0,0 +1,109 @@
+import 'dart:convert';
+import 'dart:io';
+
+import 'package:flutter/material.dart';
+
+import 'package:kulinar_app/constants.dart';
+import 'package:kulinar_app/util/notifications.dart';
+import 'package:kulinar_app/widgets/toastbar_widget.dart';
+import 'package:kulinar_app/models/data/recipe_data_class.dart';
+import 'package:kulinar_app/models/data/settings_data_class.dart';
+
+import 'package:file_picker/file_picker.dart';
+import 'package:external_path/external_path.dart';
+import 'package:permission_handler/permission_handler.dart';
+import 'package:flutter_gen/gen_l10n/app_localizations.dart';
+
+enum ExportType {
+ settings,
+ recipes,
+ recipe,
+ full,
+}
+
+/// Handles all the things related to file serialization / deserialization and other file interaction.
+class FileHandler {
+ /// Serializes the given `data` into a json style File. Sends a confirmation Toast to the given `context` afterwards.
+ static Future<void> serializeFile(BuildContext context, Map<String, dynamic> data) async {
+ if (await Permission.storage.request().isGranted) {
+ try {
+ final _directory = await ExternalPath.getExternalStoragePublicDirectory(ExternalPath.DIRECTORY_DOWNLOADS);
+ final _file = File("$_directory/Export-${DateTime.now().toUtc().toString().split(" ")[0]}.kulinar");
+
+ await _file.writeAsString(jsonEncode(await encodeDataAsMap(ExportType.full, data)));
+
+ ToastBar.showToastBar(context, AppLocalizations.of(context)!.exportSuccess);
+ Notifications.notify(AppLocalizations.of(context)!.exportSuccess, AppLocalizations.of(context)!.tapHint, _file.path);
+ } catch (e) {
+ print(e);
+ ToastBar.showToastBar(context, AppLocalizations.of(context)!.exportError);
+ }
+ }
+ }
+
+ /// Deserializes the given `file` into the returned Map. Sends a confirmation Toast to the given `context` afterwards.
+ static Future<Map<String, String>> deserializeFile(BuildContext context, File file) async {
+ final dynamic _content = jsonDecode(await file.readAsString());
+
+ SettingsData.decode(_content["settings"]);
+ RecipeData.decode(_content["recipes"]);
+
+ ToastBar.showToastBar(context, AppLocalizations.of(context)!.importSuccess);
+
+ return _content;
+ }
+
+ /// Parses a given possible deserializable `file` for useful information and returns a map of it.
+ static Future<Map<String, String>> deserializeFileInformation(File file) async {
+ final Map<dynamic, dynamic> _content = jsonDecode(await file.readAsString());
+ Map<String, String> _map = Map<String, String>();
+
+ _map["version"] = _content["version"];
+ _map["type"] = _content["type"].split(".")[1];
+ _map["size"] = "${await file.length()} Bytes";
+
+ if (_content["type"] == ExportType.full.toString()) {
+ int a = jsonDecode(_content["recipes"]).length;
+ int b = jsonDecode(_content["settings"]).length;
+
+ _map["entries"] = (a + b).toString();
+ }
+
+ return _map;
+ }
+
+ /// Opens the native file picker and returns the picked `.kulinar` file.
+ static Future<File?> pickDeserializableFile(BuildContext context) async {
+ if (await Permission.storage.request().isGranted) {
+ try {
+ FilePickerResult? result = await FilePicker.platform.pickFiles(type: FileType.custom, allowedExtensions: ["kulinar"]);
+
+ if (result != null) {
+ return File(result.files.single.path!);
+ }
+ } catch (e) {
+ print(e);
+ ToastBar.showToastBar(context, AppLocalizations.of(context)!.importError);
+ }
+ }
+
+ return null;
+ }
+
+ /// Encodes the given `data` together with some additional information into a serializable map.
+ static Future<Map<String, String>> encodeDataAsMap(ExportType type, Map<String, dynamic> data) async {
+ Map<String, String> _map = Map<String, String>();
+
+ _map["version"] = cVersion;
+ _map["type"] = type.toString();
+ // TODO: IMPLEMENT: Base64 Images and image count on export
+ // map["imageCount"] = getImageCount;
+ _map.addAll(data as Map<String, String>);
+
+ return _map;
+ }
+
+ /// Decodes the given `map` into
+ /// TODO: IMPLEMENT: decodeExportMap
+ // static Future<Map<String, String>> decodeMapToData(ExportType type) async {}
+}
diff --git a/lib/util/notifications.dart b/lib/util/notifications.dart
new file mode 100644
index 0000000..91280da
--- /dev/null
+++ b/lib/util/notifications.dart
@@ -0,0 +1,32 @@
+import 'package:open_file/open_file.dart';
+import 'package:flutter_local_notifications/flutter_local_notifications.dart';
+
+/// Handles all the notification related things.
+class Notifications {
+ static FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
+
+ /// Specifies the exact notification behavior on android.
+ static const AndroidNotificationDetails _androidSpecifics = AndroidNotificationDetails(
+ 'com.davidpenkowoj.kulinar',
+ 'Kulinar',
+ importance: Importance.defaultImportance,
+ priority: Priority.defaultPriority,
+ autoCancel: true,
+ playSound: false,
+ showWhen: false,
+ );
+
+ /// Is called when the notification is pressed.
+ static Future<dynamic> selectNotification(String? payload) async {
+ if (payload != null) {
+ OpenFile.open(payload, type: "*/*"); // TODO: FIXME: Still doesnt work (sometimes)
+ }
+ }
+
+ /// Launches the notification
+ static Future<void> notify(String title, String description, String payload) async {
+ const NotificationDetails _platformChannelSpecifics = NotificationDetails(android: _androidSpecifics);
+
+ await flutterLocalNotificationsPlugin.show(0, title, description, _platformChannelSpecifics, payload: payload);
+ }
+}
diff --git a/lib/util/storage_handler.dart b/lib/util/storage_handler.dart
new file mode 100644
index 0000000..1e12ed7
--- /dev/null
+++ b/lib/util/storage_handler.dart
@@ -0,0 +1,20 @@
+import 'package:shared_preferences/shared_preferences.dart';
+
+/// Handles all persistance related app storage
+class StorageHandler {
+ /// Stores the given `data` as a string with the `key`.
+ static Future<String> store(String key, String data) async {
+ final _prefs = await SharedPreferences.getInstance();
+
+ _prefs.setString(key, data);
+
+ return data;
+ }
+
+ /// Fetches the string related to the given `key`.
+ static Future<String?> fetch(String key) async {
+ final _prefs = await SharedPreferences.getInstance();
+
+ return _prefs.getString(key);
+ }
+}