Json export and import feature #5
@@ -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"
|
||||||
}
|
}
|
||||||
@@ -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"
|
||||||
}
|
}
|
||||||
@@ -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,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,48 +13,56 @@ class JsonFileService {
|
|||||||
required List<Collection> collections,
|
required List<Collection> collections,
|
||||||
required List<Bookmark> bookmarks,
|
required List<Bookmark> bookmarks,
|
||||||
}) async {
|
}) async {
|
||||||
final dir = await _directoryPath;
|
try {
|
||||||
|
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(),
|
||||||
'bookmarks': bookmarks.map((b) => b.toJson()).toList(),
|
'bookmarks': bookmarks.map((b) => b.toJson()).toList(),
|
||||||
};
|
};
|
||||||
final json = jsonEncode(data).codeUnits;
|
final json = jsonEncode(data).codeUnits;
|
||||||
final file = XFile.fromData(
|
final file = XFile.fromData(
|
||||||
Uint8List.fromList(json),
|
Uint8List.fromList(json),
|
||||||
mimeType: 'application/json',
|
mimeType: 'application/json',
|
||||||
name: constants.jsonFileName,
|
name: constants.jsonFileName,
|
||||||
);
|
);
|
||||||
|
|
||||||
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 {
|
||||||
const typeGroup = XTypeGroup(label: 'json', extensions: <String>['json']);
|
try {
|
||||||
final XFile? file = await openFile(
|
const typeGroup = XTypeGroup(label: 'json', extensions: <String>['json']);
|
||||||
acceptedTypeGroups: <XTypeGroup>[typeGroup],
|
final XFile? file = await openFile(
|
||||||
);
|
acceptedTypeGroups: <XTypeGroup>[typeGroup],
|
||||||
|
);
|
||||||
|
|
||||||
if (file == null) {
|
if (file == null) {
|
||||||
|
return (collections: <Collection>[], bookmarks: <Bookmark>[]);
|
||||||
|
}
|
||||||
|
|
||||||
|
final jsonString = await file.readAsString();
|
||||||
|
|
||||||
|
final data = jsonDecode(jsonString) as Map<String, dynamic>;
|
||||||
|
|
||||||
|
final collections = (data['collections'] as List<dynamic>? ?? [])
|
||||||
|
.map((json) => Collection.fromJson(json as Map<String, dynamic>))
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
final bookmarks = (data['bookmarks'] as List<dynamic>? ?? [])
|
||||||
|
.map((json) => Bookmark.fromJson(json as Map<String, dynamic>))
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
return (collections: collections, bookmarks: bookmarks);
|
||||||
|
} catch (e) {
|
||||||
return (collections: <Collection>[], bookmarks: <Bookmark>[]);
|
return (collections: <Collection>[], bookmarks: <Bookmark>[]);
|
||||||
}
|
}
|
||||||
|
|
||||||
final jsonString = await file.readAsString();
|
|
||||||
|
|
||||||
final data = jsonDecode(jsonString) as Map<String, dynamic>;
|
|
||||||
|
|
||||||
final collections = (data['collections'] as List<dynamic>? ?? [])
|
|
||||||
.map((json) => Collection.fromJson(json as Map<String, dynamic>))
|
|
||||||
.toList();
|
|
||||||
|
|
||||||
final bookmarks = (data['bookmarks'] as List<dynamic>? ?? [])
|
|
||||||
.map((json) => Bookmark.fromJson(json as Map<String, dynamic>))
|
|
||||||
.toList();
|
|
||||||
|
|
||||||
return (collections: collections, bookmarks: bookmarks);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<String> get _directoryPath async {
|
static Future<String> get _directoryPath async {
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user