Json export and import feature #5

Merged
marco merged 14 commits from json-export-feature into development 2026-01-22 18:12:01 +01:00
5 changed files with 88 additions and 43 deletions
Showing only changes of commit 06c5ca9910 - Show all commits

View File

@@ -30,8 +30,14 @@
"import": "Importieren", "import": "Importieren",
"activateJsonExport": "Immer als JSON speichern", "activateJsonExport": "Immer als JSON speichern",
"@@comment": "Info",
"exportSuccess": "Daten exportiert",
"importSuccess": "Daten importiert",
"@@comment": "Errors", "@@comment": "Errors",
"errorStoragePermisson": "Zugriff auf Speicher verwehrt", "errorStoragePermisson": "Zugriff auf Speicher verwehrt",
"errorCouldNotLaunchUrl": "Konnte Url nicht öffnen", "errorCouldNotLaunchUrl": "Konnte Url nicht öffnen",
"errorInvalidUrl": "Fehlerhafte Url" "errorInvalidUrl": "Fehlerhafte Url",
"exportFailed": "Export fehlgeschlagen",
"importFailed": "Import fehlgeschlagen"
} }

View File

@@ -30,8 +30,15 @@
"import": "Import", "import": "Import",
"activateJsonExport": "Always save to JSON", "activateJsonExport": "Always save to JSON",
"@@comment": "Info",
"exportSuccess": "Exported data",
"importSuccess": "Imported data",
"@@comment": "Errors", "@@comment": "Errors",
"errorStoragePermisson": "Storage permissions denied", "errorStoragePermisson": "Storage permissions denied",
"errorCouldNotLaunchUrl": "Could not launch Url", "errorCouldNotLaunchUrl": "Could not launch Url",
"errorInvalidUrl": "Invalid Url" "errorInvalidUrl": "Invalid Url",
"exportFailed": "Export failed",
"importFailed": "Import failed"
} }

View File

@@ -1,3 +1,5 @@
import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart'; import 'package:permission_handler/permission_handler.dart';
@@ -43,20 +45,42 @@ class _SettingsPageState extends State<SettingsPage> {
} }
void onActivateJsonExportPressed() async { void onActivateJsonExportPressed() async {
if (await checkStoragePermission) Storage.exportToJsonFile(); if (!await checkStoragePermission) return;
Storage.exportToJsonFile().then(showExportInfo);
} }
void onActivateJsonImportPressed() async { void onActivateJsonImportPressed() async {
if (await checkStoragePermission) Storage.importFromJsonFile(); if (!await checkStoragePermission) return;
Storage.importFromJsonFile().then(showImportInfo);
} }
Future<bool> get checkStoragePermission async { Future<bool> get checkStoragePermission async {
if (!(await PermissionService.requestStoragePermission).isGranted) { if (!(await PermissionService.requestStoragePermission).isGranted) {
if (mounted) { if (mounted) {
Notifying.showStoragePermissionErrorSnackbar(context); Notifying.showErrorSnackbar(
context,
AppLocalizations.of(context)!.errorStoragePermisson,
);
return false; return false;
} }
} }
return true; return true;
} }
void showExportInfo(bool success) => Notifying.showSnackbar(
context,
text: success
? AppLocalizations.of(context)!.exportSuccess
: AppLocalizations.of(context)!.exportFailed,
isError: success,
);
void showImportInfo(bool success) => Notifying.showSnackbar(
context,
text: success
? AppLocalizations.of(context)!.importSuccess
: AppLocalizations.of(context)!.importFailed,
isError: success,
);
} }

View File

@@ -13,7 +13,9 @@ class JsonFileService {
required List<Collection> collections, required List<Collection> collections,
required List<Bookmark> bookmarks, required List<Bookmark> bookmarks,
}) async { }) async {
try {
final dir = await _directoryPath; final dir = await _directoryPath;
if (dir.isEmpty) return false;
final data = { final data = {
'collections': collections.map((c) => c.toJson()).toList(), 'collections': collections.map((c) => c.toJson()).toList(),
@@ -27,12 +29,15 @@ class JsonFileService {
); );
file.saveTo('$dir/${constants.jsonFileName}'); file.saveTo('$dir/${constants.jsonFileName}');
} catch (e) {
return false;
}
return false; return false;
} }
static Future<({List<Collection> collections, List<Bookmark> bookmarks})> static Future<({List<Collection> collections, List<Bookmark> bookmarks})>
importFromJson() async { importFromJson() async {
try {
const typeGroup = XTypeGroup(label: 'json', extensions: <String>['json']); const typeGroup = XTypeGroup(label: 'json', extensions: <String>['json']);
final XFile? file = await openFile( final XFile? file = await openFile(
acceptedTypeGroups: <XTypeGroup>[typeGroup], acceptedTypeGroups: <XTypeGroup>[typeGroup],
@@ -55,6 +60,9 @@ class JsonFileService {
.toList(); .toList();
return (collections: collections, bookmarks: bookmarks); return (collections: collections, bookmarks: bookmarks);
} catch (e) {
return (collections: <Collection>[], bookmarks: <Bookmark>[]);
}
} }
static Future<String> get _directoryPath async { static Future<String> get _directoryPath async {

View File

@@ -54,11 +54,11 @@ class Notifying {
showSnackbar(context, text: errorText, isError: true); showSnackbar(context, text: errorText, isError: true);
} }
static void showStoragePermissionErrorSnackbar(BuildContext context) { static void showErrorSnackbar(BuildContext context, String message) {
showSnackbar( showSnackbar(context, text: message, isError: true);
context, }
text: AppLocalizations.of(context)!.errorStoragePermisson,
isError: true, static void showMessageSnackbar(BuildContext context, String message) {
); showSnackbar(context, text: message, isError: false);
} }
} }