Skip to content

Commit

Permalink
Add more backup options
Browse files Browse the repository at this point in the history
  • Loading branch information
AhsanSarwar45 committed Aug 26, 2024
1 parent 5044ce9 commit 2ded544
Show file tree
Hide file tree
Showing 7 changed files with 370 additions and 199 deletions.
11 changes: 8 additions & 3 deletions lib/common/utils/snackbar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@ import 'package:clock_app/settings/data/settings_schema.dart';
import 'package:flutter/material.dart';

void showSnackBar(BuildContext context, String text,
{bool fab = false, bool navBar = false}) {
{bool fab = false, bool navBar = false, bool error = false}) {
ThemeData theme = Theme.of(context);
ColorScheme colorScheme = theme.colorScheme;
Color? color = error ? colorScheme.error : null;
ScaffoldMessenger.of(context).removeCurrentSnackBar();
ScaffoldMessenger.of(context)
.showSnackBar(getSnackbar(text, fab: fab, navBar: navBar));
.showSnackBar(getSnackbar(text, fab: fab, navBar: navBar, color:color));
}

SnackBar getSnackbar(String text, {bool fab = false, bool navBar = false}) {
SnackBar getSnackbar(String text, {bool fab = false, bool navBar = false, Color? color}) {
double left = 20;
double right = 20;
double bottom = 12;
Expand Down Expand Up @@ -44,6 +47,7 @@ SnackBar getSnackbar(String text, {bool fab = false, bool navBar = false}) {
constraints: const BoxConstraints(minHeight: 28),
child: Container(
alignment: Alignment.centerLeft,
color: color,
// height: 28,
child: Text(text),
),
Expand All @@ -53,6 +57,7 @@ SnackBar getSnackbar(String text, {bool fab = false, bool navBar = false}) {
right: right,
bottom: bottom,
),

elevation: 2,
dismissDirection: DismissDirection.none,
);
Expand Down
157 changes: 157 additions & 0 deletions lib/settings/data/backup_options.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
import 'dart:convert';

import 'package:clock_app/alarm/logic/update_alarms.dart';
import 'package:clock_app/alarm/types/alarm.dart';
import 'package:clock_app/app.dart';
import 'package:clock_app/clock/types/city.dart';
import 'package:clock_app/common/utils/json_serialize.dart';
import 'package:clock_app/common/utils/list_storage.dart';
import 'package:clock_app/settings/data/settings_schema.dart';
import 'package:clock_app/settings/types/backup_option.dart';
import 'package:clock_app/theme/types/color_scheme.dart';
import 'package:clock_app/theme/types/style_theme.dart';
import 'package:clock_app/timer/logic/update_timers.dart';
import 'package:clock_app/timer/types/timer.dart';
import 'package:clock_app/timer/types/timer_preset.dart';
import 'package:clock_app/widgets/logic/update_widgets.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

// Order of BackupOption matters
// tags should be before alarms and timers
// color_schemes and style_themes should be before settings
final backupOptions = [
BackupOption(
"tags",
(context) => AppLocalizations.of(context)!.presetsSetting,
encode: () async {
return await loadTextFile("tags");
},
decode: (context, value) async {
await saveList<TimerPreset>("tags", [
...listFromString<TimerPreset>(value),
...await loadList<TimerPreset>("tags")
]);
},
),
BackupOption(
"color_schemes",
(context) => AppLocalizations.of(context)!.colorSchemeSetting,
encode: () async {
List<ColorSchemeData> colorSchemes =
await loadList<ColorSchemeData>("color_schemes");
List<ColorSchemeData> customColorSchemes =
colorSchemes.where((scheme) => !scheme.isDefault).toList();
return listToString(customColorSchemes);
},
decode: (context, value) async {
await saveList<ColorSchemeData>("color_schemes", [
...listFromString<ColorSchemeData>(value),
...await loadList<ColorSchemeData>("color_schemes")
]);
if (context.mounted) App.refreshTheme(context);
},
),
BackupOption(
"style_themes",
(context) => AppLocalizations.of(context)!.styleThemeSetting,
encode: () async {
List<StyleTheme> styleThemes = await loadList<StyleTheme>("style_themes");
List<StyleTheme> customThemes =
styleThemes.where((scheme) => !scheme.isDefault).toList();
return listToString(customThemes);
},
decode: (context, value) async {
await saveList<StyleTheme>("style_themes", [
...listFromString<StyleTheme>(value),
...await loadList<StyleTheme>("style_themes")
]);
if (context.mounted) App.refreshTheme(context);
},
),
BackupOption(
"settings",
(context) => AppLocalizations.of(context)!.settings,
encode: () async {
return json.encode(appSettings.valueToJson());
},
decode: (context, value) async {
appSettings.loadValueFromJson(json.decode(value));
appSettings.callAllListeners();
App.refreshTheme(context);
await appSettings.save();
if (context.mounted) {
setDigitalClockWidgetData(context);
}
},
),
BackupOption(
"alarms",
(context) => AppLocalizations.of(context)!.alarmTitle,
encode: () async {
return await loadTextFile("alarms");
},
decode: (context, value) async {
await saveList<Alarm>("alarms", [
...listFromString<Alarm>(value),
...await loadList<Alarm>("alarms")
]);
await updateAlarms("Updated alarms on importing backup");
},
),
BackupOption(
"timers",
(context) => AppLocalizations.of(context)!.timerTitle,
encode: () async {
return await loadTextFile("timers");
},
decode: (context, value) async {
await saveList<ClockTimer>("timers", [
...listFromString<ClockTimer>(value),
...await loadList<ClockTimer>("timers")
]);
await updateTimers("Updated timers on importing backup");
},
),
BackupOption(
"favorite_cities",
(context) => AppLocalizations.of(context)!.clockTitle,
encode: () async {
return await loadTextFile("favorite_cities");
},
decode: (context, value) async {
await saveList<City>("favorite_cities", [
...listFromString<City>(value),
// ...await loadList<City>("favorite_cities")
]);
// await updateTimers("Updated timers on importing backup");
},
),

// BackupOption(
// "stopwatches",
// (context) => AppLocalizations.of(context)!.stopwatchTitle,
// encode: () async {
// return await loadTextFile("stopwatches");
// },
// decode: (context, value) async {
// await saveList<ClockTimer>("stopwatches", [
// ...listFromString<ClockTimer>(value),
// ]);
// },
// ),

BackupOption(
"timer_presets",
(context) => AppLocalizations.of(context)!.presetsSetting,
encode: () async {
return await loadTextFile("timer_presets");
},
decode: (context, value) async {
await saveList<TimerPreset>("timer_presets", [
...listFromString<TimerPreset>(value),
...await loadList<TimerPreset>("timer_presets")
]);
},
),

];
93 changes: 38 additions & 55 deletions lib/settings/data/backup_settings_schema.dart
Original file line number Diff line number Diff line change
@@ -1,84 +1,67 @@
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';

import 'package:clock_app/app.dart';
import 'package:clock_app/settings/data/settings_schema.dart';
import 'package:clock_app/settings/logic/backup.dart';
import 'package:clock_app/settings/screens/backup_screen.dart';
import 'package:clock_app/settings/types/setting_action.dart';
import 'package:clock_app/settings/types/setting_group.dart';
import 'package:clock_app/settings/types/setting_link.dart';
import 'package:clock_app/widgets/logic/update_widgets.dart';
import 'package:flutter/material.dart';
import 'package:pick_or_save/pick_or_save.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

SettingGroup backupSettingsSchema = SettingGroup(
"Backup",
(context) => AppLocalizations.of(context)!.backupSettingGroup,
getDescription: (context) =>
AppLocalizations.of(context)!.backupSettingGroupDescription,
showExpandedView: false,
icon: Icons.restore_rounded,
[
SettingGroup(
"Settings",
(context) => AppLocalizations.of(context)!.settingsTitle,
[
// SettingPageLink("Export", (context) => AppLocalizations.of(context)!.exportSettingsSetting, BackupScreen()),
// SettingPageLink("Import", (context) => AppLocalizations.of(context)!.importSettingsSetting, BackupScreen()),
SettingAction(
SettingPageLink(
"Export",
(context) => AppLocalizations.of(context)!.exportSettingsSetting,
(context) async {
saveBackupFile(json.encode(appSettings.valueToJson()), "settings");
},
searchTags: ["settings", "export", "backup", "save"],
const BackupExportScreen(),
getDescription: (context) =>
AppLocalizations.of(context)!.exportSettingsSettingDescription,
),
SettingAction(
"Import",
(context) => AppLocalizations.of(context)!.importSettingsSetting,
(context) async {
loadBackupFile(
(data) async {
appSettings.loadValueFromJson(json.decode(data));
appSettings.callAllListeners();
App.refreshTheme(context);
await appSettings.save();
if (context.mounted) setDigitalClockWidgetData(context);
},
);
final data = await loadBackupFile();
if(data == null) return;
if (context.mounted) {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => BackupImportScreen(data: data)));
}
},
searchTags: ["settings", "import", "backup", "load"],
getDescription: (context) =>
AppLocalizations.of(context)!.importSettingsSettingDescription,
),
],
),
// SettingAction(
// "Export",
// (context) => AppLocalizations.of(context)!.exportSettingsSetting,
// (context) async {
// saveBackupFile(json.encode(appSettings.valueToJson()), "settings");
// },
// searchTags: ["settings", "export", "backup", "save"],
// getDescription: (context) =>
// AppLocalizations.of(context)!.exportSettingsSettingDescription,
// ),
// SettingAction(
// "Import",
// (context) => AppLocalizations.of(context)!.importSettingsSetting,
// (context) async {
// loadBackupFile(
// (data) async {
// appSettings.loadValueFromJson(json.decode(data));
// appSettings.callAllListeners();
// App.refreshTheme(context);
// await appSettings.save();
// if (context.mounted) setDigitalClockWidgetData(context);
// },
// );
// },
// searchTags: ["settings", "import", "backup", "load"],
// getDescription: (context) =>
// AppLocalizations.of(context)!.importSettingsSettingDescription,
// ),
],
);

saveBackupFile(String data, String label) async {
await PickOrSave().fileSaver(
params: FileSaverParams(
saveFiles: [
SaveFileInfo(
fileData: Uint8List.fromList(utf8.encode(data)),
fileName: "chrono_${label}_backup_${DateTime.now().toIso8601String()}",
)
],
));
}

loadBackupFile(Function(String) onSuccess) async {
List<String>? result = await PickOrSave().filePicker(
params: FilePickerParams(
getCachedFilePath: true,
),
);
if (result != null && result.isNotEmpty) {
File file = File(result[0]);
onSuccess(utf8.decode(file.readAsBytesSync()));
}
}
30 changes: 30 additions & 0 deletions lib/settings/logic/backup.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';

import 'package:pick_or_save/pick_or_save.dart';

void saveBackupFile(String data) async {
await PickOrSave().fileSaver(
params: FileSaverParams(
saveFiles: [
SaveFileInfo(
fileData: Uint8List.fromList(utf8.encode(data)),
fileName: "chrono_backup_${DateTime.now().toIso8601String().split(".")[0]}.json",
)
],
));
}

Future<String?> loadBackupFile() async {
List<String>? result = await PickOrSave().filePicker(
params: FilePickerParams(
getCachedFilePath: true,
),
);
if (result != null && result.isNotEmpty) {
File file = File(result[0]);
return utf8.decode(file.readAsBytesSync());
}
return null;
}
Loading

0 comments on commit 2ded544

Please sign in to comment.