Skip to content

Commit

Permalink
Merge pull request #242 from flow-mn:sadespresso/241208-compress-back…
Browse files Browse the repository at this point in the history
…ups-204

backup v2 draft
  • Loading branch information
sadespresso authored Dec 22, 2024
2 parents 4e8e469 + db325e7 commit 3b31188
Show file tree
Hide file tree
Showing 29 changed files with 985 additions and 75 deletions.
17 changes: 16 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,21 @@
# Changelog

## Beta next (0.9.0)
## 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

0 comments on commit 3b31188

Please sign in to comment.