Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backup v2, zp files #243

Merged
merged 5 commits into from
Dec 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
# Changelog

## Beta 0.10.0

### New features

* N/A

### Changes

* N/A

### Fixes and enhancements

* Now you can do ZIP backups that include account/profile photos, fixes [#173](https://github.com/flow-mn/flow/issues/173)
and [#204](https://github.com/flow-mn/flow/issues/204)

## Beta 0.9.0

### New features
Expand Down
18 changes: 17 additions & 1 deletion assets/l10n/en_IN.json
Original file line number Diff line number Diff line change
Expand Up @@ -279,14 +279,17 @@
"sync.import.emergencyBackup": "As a precaution, Flow will try to backup current data to your device before proceeding",
"sync.import.emergencyBackup.successful": "Previous data was backed up. You can save the backup file from Backup > Backup history",
"sync.import.start": "Start importing",
"sync.import.zipWarning": "Make sure to import ZIP file produced by Flow app!",
"sync.import.success": "Import successful!",

"sync.export": "Export",
"sync.export.type": "Export ({type})",
"sync.export.asCSV": "As CSV",
"sync.export.asCSV.description": "Cannot be used for restore/import! Ideal for opening in software like Google Sheets",
"sync.export.asZIP": "As backup (zip)",
"sync.export.asZIP.description": "Can be fully restored later",
"sync.export.asJSON": "As backup (json)",
"sync.export.asJSON.description": "Can be restored later",
"sync.export.asJSON.description": "Can be partially restored. Omits non-essential data (e.g., account image)",
"sync.export.autoBackup": "Auto-backup",
"sync.export.autoBackup.iCloudAlreadySyncs": "If you're using Flow on iOS or macOS, your data will be synced to your iCloud",
"sync.export.onDeviceWarning": "All backups are stored on-device, meaning when you uninstall Flow or reset your device, all the backups will be gone!",
Expand Down Expand Up @@ -338,6 +341,18 @@
"enum.ImportV1Progress@success": "Success",
"enum.ImportV1Progress@error": "Something went wrong ({error})",

"enum.ImportV2Progress@waitingConfirmation": "Waiting for confirmation",
"enum.ImportV2Progress@erasing": "Erasing current data",
"enum.ImportV2Progress@writingCategories": "Writing categories",
"enum.ImportV2Progress@writingAccounts": "Writing accounts",
"enum.ImportV2Progress@resolvingTransactions": "Sorting out transactions",
"enum.ImportV2Progress@writingTransactions": "Writing transactions",
"enum.ImportV2Progress@writingProfile": "Writing profile data",
"enum.ImportV2Progress@settingPrimaryCurrency": "Setting primary currency",
"enum.ImportV2Progress@copyingImages": "Copying images",
"enum.ImportV2Progress@success": "Success",
"enum.ImportV2Progress@error": "Something went wrong ({error})",

"enum.BackupEntryType@manual": "Manual",
"enum.BackupEntryType@manual.description": "Backup created by user",
"enum.BackupEntryType@automated": "Auto-backup",
Expand All @@ -357,6 +372,7 @@
"error.input.noImagePicked": "No image was selected",
"error.input.cropFailed": "An error occured during cropping the picture",
"error.input.wrongFileType": "Please choose a {type} file",
"error.input.invalidZip": "Not a valid Flow zip file",
"error.input.pasteFormatMismatch": "Unable to parse",
"error.sync.invalidBackupFile": "Invalid backup file",
"error.sync.safetyBackupFailed": "Unable to start import",
Expand Down
20 changes: 18 additions & 2 deletions assets/l10n/en_US.json
Original file line number Diff line number Diff line change
Expand Up @@ -279,14 +279,17 @@
"sync.import.emergencyBackup": "As a precaution, Flow will try to backup current data to your device before proceeding",
"sync.import.emergencyBackup.successful": "Previous data was backed up. You can save the backup file from Backup > Backup history",
"sync.import.start": "Start importing",
"sync.import.zipWarning": "Make sure to import ZIP file produced by Flow app!",
"sync.import.success": "Import successful!",

"sync.export": "Export",
"sync.export.type": "Export ({type})",
"sync.export.asCSV": "As CSV",
"sync.export.asCSV.description": "Cannot be used for restore/import! Ideal for opening in software like Google Sheets",
"sync.export.asZIP": "As backup (zip)",
"sync.export.asZIP.description": "Can be fully restored later",
"sync.export.asJSON": "As backup (json)",
"sync.export.asJSON.description": "Can be restored later",
"sync.export.asJSON.description": "Can be partially restored. Omits non-essential data (e.g., account image)",
"sync.export.autoBackup": "Auto-backup",
"sync.export.autoBackup.iCloudAlreadySyncs": "If you're using Flow on iOS or macOS, your data will be synced to your iCloud",
"sync.export.onDeviceWarning": "All backups are stored on-device, meaning when you uninstall Flow or reset your device, all the backups will be gone!",
Expand Down Expand Up @@ -333,11 +336,23 @@
"enum.ImportV1Progress@erasing": "Erasing current data",
"enum.ImportV1Progress@writingCategories": "Writing categories",
"enum.ImportV1Progress@writingAccounts": "Writing accounts",
"enum.ImportV1Progress@resolvingTransactions": "Soring out transactions",
"enum.ImportV1Progress@resolvingTransactions": "Sorting out transactions",
"enum.ImportV1Progress@writingTransactions": "Writing transactions",
"enum.ImportV1Progress@success": "Success",
"enum.ImportV1Progress@error": "Something went wrong ({error})",

"enum.ImportV2Progress@waitingConfirmation": "Waiting for confirmation",
"enum.ImportV2Progress@erasing": "Erasing current data",
"enum.ImportV2Progress@writingCategories": "Writing categories",
"enum.ImportV2Progress@writingAccounts": "Writing accounts",
"enum.ImportV2Progress@resolvingTransactions": "Sorting out transactions",
"enum.ImportV2Progress@writingTransactions": "Writing transactions",
"enum.ImportV2Progress@writingProfile": "Writing profile data",
"enum.ImportV2Progress@settingPrimaryCurrency": "Setting primary currency",
"enum.ImportV2Progress@copyingImages": "Copying images",
"enum.ImportV2Progress@success": "Success",
"enum.ImportV2Progress@error": "Something went wrong ({error})",

"enum.BackupEntryType@manual": "Manual",
"enum.BackupEntryType@manual.description": "Backup created by user",
"enum.BackupEntryType@automated": "Auto-backup",
Expand All @@ -357,6 +372,7 @@
"error.input.noImagePicked": "No image was selected",
"error.input.cropFailed": "An error occured during cropping the picture",
"error.input.wrongFileType": "Please choose a {type} file",
"error.input.invalidZip": "Not a valid Flow zip file",
"error.sync.invalidBackupFile": "Invalid backup file",
"error.input.pasteFormatMismatch": "Unable to parse",
"error.sync.safetyBackupFailed": "Unable to start import",
Expand Down
20 changes: 18 additions & 2 deletions assets/l10n/it_IT.json
Original file line number Diff line number Diff line change
Expand Up @@ -279,14 +279,17 @@
"sync.import.emergencyBackup": "Come precauzione, Flow tenterà di eseguire il backup dei dati attuali sul tuo dispositivo prima di procedere",
"sync.import.emergencyBackup.successful": "I dati precedenti sono stati eseguiti in backup. Puoi salvare il file di backup da Backup > Cronologia backup",
"sync.import.start": "Inizia l'importazione",
"sync.import.zipWarning": "Assicurarsi di importare il file ZIP prodotto dall'app Flow!",
"sync.import.success": "Importazione riuscita!",

"sync.export": "Esporta",
"sync.export.type": "Esporta ({type})",
"sync.export.asCSV": "Come CSV",
"sync.export.asCSV.description": "Non può essere utilizzato per il ripristino/importazione! Ideale per l'apertura in software come Google Sheets",
"sync.export.asZIP": "Come backup (zip)",
"sync.export.asZIP.description": "Può essere completamente ripristinato in seguito",
"sync.export.asJSON": "Come backup (json)",
"sync.export.asJSON.description": "Può essere ripristinato in seguito",
"sync.export.asJSON.description": "Può essere parzialmente ripristinato. Omette dati non essenziali (ad esempio, immagine dell'account)",
"sync.export.autoBackup": "Backup automatico",
"sync.export.autoBackup.iCloudAlreadySyncs": "Se usi Flow su iOS o macOS, i tuoi dati saranno sincronizzati con il tuo iCloud",
"sync.export.onDeviceWarning": "Tutti i backup sono memorizzati sul dispositivo, il che significa che quando disinstalli Flow o reimposti il tuo dispositivo, tutti i backup saranno persi!",
Expand Down Expand Up @@ -335,9 +338,21 @@
"enum.ImportV1Progress@writingAccounts": "Scrittura dei conti",
"enum.ImportV1Progress@resolvingTransactions": "Risoluzione delle transazioni",
"enum.ImportV1Progress@writingTransactions": "Scrittura delle transazioni",
"enum.ImportV1Progress@success": "Successo",
"enum.ImportV1Progress@success": "Operazione completata",
"enum.ImportV1Progress@error": "Qualcosa è andato storto ({error})",

"enum.ImportV2Progress@waitingConfirmation": "In attesa di conferma",
"enum.ImportV2Progress@erasing": "Cancellazione dei dati correnti",
"enum.ImportV2Progress@writingCategories": "Scrittura delle categorie",
"enum.ImportV2Progress@writingAccounts": "Scrittura dei conti",
"enum.ImportV2Progress@resolvingTransactions": "Risoluzione delle transazioni",
"enum.ImportV2Progress@writingTransactions": "Scrittura delle transazioni",
"enum.ImportV2Progress@writingProfile": "Scrittura dei dati del profilo",
"enum.ImportV2Progress@settingPrimaryCurrency": "Impostazione della valuta principale",
"enum.ImportV2Progress@copyingImages": "Copia delle immagini",
"enum.ImportV2Progress@success": "Operazione completata",
"enum.ImportV2Progress@error": "Qualcosa è andato storto ({error})",

"enum.BackupEntryType@manual": "Manuale",
"enum.BackupEntryType@manual.description": "Backup creato dall'utente",
"enum.BackupEntryType@automated": "Backup automatico",
Expand All @@ -357,6 +372,7 @@
"error.input.noImagePicked": "Nessuna immagine selezionata",
"error.input.cropFailed": "Si è verificato un errore durante il ritaglio dell'immagine",
"error.input.wrongFileType": "Si prega di scegliere un file {type}",
"error.input.invalidZip": "File non valido",
"error.input.pasteFormatMismatch": "Impossibile analizzare",
"error.sync.invalidBackupFile": "File di backup non valido",
"error.sync.safetyBackupFailed": "Impossibile avviare l'importazione",
Expand Down
18 changes: 17 additions & 1 deletion assets/l10n/mn_MN.json
Original file line number Diff line number Diff line change
Expand Up @@ -279,14 +279,17 @@
"sync.import.emergencyBackup": "Аливаа эсрдлээс сэрэмжилж Flow таны одоо байгаа файлыг төхөөрөмж дээр тань нөөцлөхийг оролдох болно",
"sync.import.emergencyBackup.successful": "Таны өмнөх өгөгдлүүдийг автоматаар нөөцөллөө. Файлыг Нөөцлөх > Нөөцийн түүх цэсрүү орж хадгалж аваарай",
"sync.import.start": "Эхлүүлэх",
"sync.import.zipWarning": "Зөвхөн Flow аппаас нөөцөлж авсан ZIP файлыг сонгоно уу",
"sync.import.success": "Өгөгдлийг амжилттай сэргээлээ!",

"sync.export": "Нөөцлөх",
"sync.export.type": "Нөөцлөх ({type})",
"sync.export.asCSV": "CSV хүснэгтээр",
"sync.export.asCSV.description": "Буцааж сэргээх боломжгүй! Google Sheets гэх мэт программуудад нээж харахад тохиромжтой",
"sync.export.asZIP": "Нөөц файл (ZIP)",
"sync.export.asZIP.description": "Дараа сэргээхэд зориулсан формат",
"sync.export.asJSON": "Нөөц файл (JSON)",
"sync.export.asJSON.description": "Дараа сэргээхэд зориулсан формат",
"sync.export.asJSON.description": "Сэргээх боломжтой. Нэмэлт мэдээллүүд сэргэхгүй (дансны зураг гэх мэт)",
"sync.export.autoBackup": "Автоматаар хадгалах",
"sync.export.autoBackup.iCloudAlreadySyncs": "Хэрэв та iOS эсвэл macOS систем дээр Flow-г ашиглаж байгаа бол таны iCloud-д автоматаар хадгалагдах болно",
"sync.export.onDeviceWarning": "Таны нөөцөлсөн өгөгдөл аппыг устгах болон утасны өгөгдлийг шинэчлэх үед хамт устахыг анхаарна уу!",
Expand Down Expand Up @@ -338,6 +341,18 @@
"enum.ImportV1Progress@success": "Амжилттай",
"enum.ImportV1Progress@error": "Алдаа гарлаа ({error})",

"enum.ImportV2Progress@waitingConfirmation": "Баталгаажуулалт хүлээж байна",
"enum.ImportV2Progress@erasing": "Хуучин өгөгдлийг цэвэрлэж байна",
"enum.ImportV2Progress@writingCategories": "Ангиллуудыг бичиж байна",
"enum.ImportV2Progress@writingAccounts": "Данснуудыг бичиж байна",
"enum.ImportV2Progress@resolvingTransactions": "Гүйлгээнүүдийг хуваарилж байна",
"enum.ImportV2Progress@writingTransactions": "Гүйлгээнүүдийг бичиж байна",
"enum.ImportV2Progress@writingProfile": "Бүртгэлийг бичиж байна",
"enum.ImportV2Progress@settingPrimaryCurrency": "Үндсэн валют тохируулж байна",
"enum.ImportV2Progress@copyingImages": "Зургуудыг хуулж байна",
"enum.ImportV2Progress@success": "Амжилттай",
"enum.ImportV2Progress@error": "Алдаа гарлаа ({error})",

"enum.BackupEntryType@manual": "Хэрэглэгч үүсгэсэн",
"enum.BackupEntryType@manual.description": "Хэрэглэгч өөрөө үүсгэсэн нөөц",
"enum.BackupEntryType@automated": "Автомат",
Expand All @@ -357,6 +372,7 @@
"error.input.noImagePicked": "Та зураг сонгоогүй байна",
"error.input.cropFailed": "Зураг хайчлах үед алдаа гарлаа",
"error.input.wrongFileType": "Зөвхөн {} төрлийн файл сонгох боломжтой",
"error.input.invalidZip": "Flow zip файлыг таньж чадсангүй",
"error.input.pasteFormatMismatch": "Өгөгдлийг таньж чадсангүй",
"error.sync.invalidBackupFile": "Нөөц файл алдаатай байна",
"error.sync.safetyBackupFailed": "Сэргээх үйлдэл эхлэх боломжгүй",
Expand Down
2 changes: 2 additions & 0 deletions lib/objectbox.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ class ObjectBox {

static late String appDataDirectory;

static String get imagesDirectory => path.join(appDataDirectory, "images");

/// A subdirectory to store app data.
///
/// This is useful if you want to separate multiple user data or just
Expand Down
19 changes: 16 additions & 3 deletions lib/routes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import "package:flow/routes/export_page.dart";
import "package:flow/routes/home_page.dart";
import "package:flow/routes/import_page.dart";
import "package:flow/routes/import_wizard/v1.dart";
import "package:flow/routes/import_wizard/v2.dart";
import "package:flow/routes/preferences/button_order_preferences_page.dart";
import "package:flow/routes/preferences/haptics_preferences_page.dart";
import "package:flow/routes/preferences/money_formatting_preferences_page.dart";
Expand All @@ -36,6 +37,7 @@ import "package:flow/routes/utils/crop_square_image_page.dart";
import "package:flow/routes/utils/edit_markdown_page.dart";
import "package:flow/sync/export/mode.dart";
import "package:flow/sync/import/import_v1.dart";
import "package:flow/sync/import/import_v2.dart";
import "package:flow/utils/utils.dart";
import "package:flutter/material.dart";
import "package:go_router/go_router.dart";
Expand Down Expand Up @@ -253,16 +255,27 @@ final router = GoRouter(
);
},
),
GoRoute(
path: "/import/wizard/v2",
builder: (context, state) {
if (state.extra case ImportV2 importV2) {
return ImportWizardV2Page(importer: importV2);
}

return ErrorPage(
error: "error.sync.invalidBackupFile".t(context),
);
},
),
GoRoute(
path: "/export/history",
builder: (context, state) => const ExportHistoryPage(),
),
GoRoute(
path: "/export/:type",
builder: (context, state) => ExportPage(
state.pathParameters["type"] == "csv"
? ExportMode.csv
: ExportMode.json,
ExportMode.tryParse(state.pathParameters["type"] ?? "zip") ??
ExportMode.zip,
),
),
GoRoute(
Expand Down
2 changes: 1 addition & 1 deletion lib/routes/export/export_history_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import "package:flow/entity/backup_entry.dart";
import "package:flow/l10n/extensions.dart";
import "package:flow/objectbox.dart";
import "package:flow/objectbox/objectbox.g.dart";
import "package:flow/sync/export/history/backup_entry_card.dart";
import "package:flow/widgets/export/export_history/backup_entry_card.dart";
import "package:flow/widgets/export/export_history/no_backups.dart";
import "package:flow/widgets/general/spinner.dart";
import "package:flutter/material.dart";
Expand Down
31 changes: 31 additions & 0 deletions lib/routes/export_options_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,37 @@ class _ExportOptionsPageState extends State<ExportOptionsPage> {
),
),
const SizedBox(height: 16.0),
ActionCard(
onTap: () => context.push("/export/zip"),
builder: (context) => Padding(
padding: const EdgeInsets.symmetric(
horizontal: 24.0,
vertical: 16.0,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
FlowIcon(
FlowIconData.icon(Symbols.folder_zip_rounded),
size: 80.0,
plated: true,
),
const SizedBox(height: 8.0),
Text(
"sync.export.asZIP".t(context),
style: context.textTheme.headlineSmall,
),
const SizedBox(height: 8.0),
Text(
"sync.export.asZIP.description".t(context),
style: context.textTheme.bodySmall,
),
],
),
),
),
const SizedBox(height: 16.0),
ActionCard(
onTap: () => context.push("/export/json"),
builder: (context) => Padding(
Expand Down
16 changes: 0 additions & 16 deletions lib/routes/home/profile_tab.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import "package:flow/l10n/extensions.dart";
import "package:flow/objectbox.dart";
import "package:flow/prefs.dart";
import "package:flow/services/exchange_rates.dart";
import "package:flow/sync/import.dart";
import "package:flow/theme/color_themes/registry.dart";
import "package:flow/theme/theme.dart";
import "package:flow/utils/utils.dart";
Expand Down Expand Up @@ -246,19 +245,4 @@ class _ProfileTabState extends State<ProfileTab> {
void clearExchangeRatesCache() {
ExchangeRatesService().debugClearCache();
}

void import() async {
try {
await importBackupV1();
if (mounted) {
context.showToast(
text: "sync.import.successful".t(context),
);
}
} catch (e) {
if (mounted) {
context.showErrorToast(error: e);
}
}
}
}
6 changes: 5 additions & 1 deletion lib/routes/import_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import "dart:io";
import "package:flow/l10n/extensions.dart";
import "package:flow/sync/import.dart";
import "package:flow/sync/import/base.dart";
import "package:flow/sync/import/import_v2.dart";
import "package:flow/utils/extensions/toast.dart";
import "package:flow/widgets/general/spinner.dart";
import "package:flow/widgets/import/file_select_area.dart";
Expand Down Expand Up @@ -50,7 +51,7 @@ class _ImportPageState extends State<ImportPage> {
});

try {
importer = await importBackupV1(
importer = await importBackup(
backupFile: backupFile,
);

Expand All @@ -59,6 +60,9 @@ class _ImportPageState extends State<ImportPage> {
case ImportV1 importV1:
context.pushReplacement("/import/wizard/v1", extra: importV1);
break;
case ImportV2 importV2:
context.pushReplacement("/import/wizard/v2", extra: importV2);
break;
case null:
context.showErrorToast(
error: "error.input.noFilePicked".t(context),
Expand Down
Loading
Loading