started with #121

This commit is contained in:
otsmr 2025-06-03 21:30:33 +02:00
parent 8ca017f5d8
commit 01c3e8ebbd
7 changed files with 186 additions and 1 deletions

View file

@ -418,5 +418,6 @@
"tutorialChatMessagesReopenMessageDesc": "If your friend has sent you a picture or video with infinite display time, you can open it again at any time until you restart the app. To do this, simply double-click on the message. Your friend will then receive a notification that you have viewed the picture again.", "tutorialChatMessagesReopenMessageDesc": "If your friend has sent you a picture or video with infinite display time, you can open it again at any time until you restart the app. To do this, simply double-click on the message. Your friend will then receive a notification that you have viewed the picture again.",
"memoriesEmpty": "As soon as you save pictures or videos, they end up here in your memories.", "memoriesEmpty": "As soon as you save pictures or videos, they end up here in your memories.",
"deleteImageTitle": "Are you sure?", "deleteImageTitle": "Are you sure?",
"deleteImageBody": "The image will be irrevocably deleted." "deleteImageBody": "The image will be irrevocably deleted.",
"settingsBackup": "Backup"
} }

View file

@ -1573,6 +1573,12 @@ abstract class AppLocalizations {
/// In en, this message translates to: /// In en, this message translates to:
/// **'The image will be irrevocably deleted.'** /// **'The image will be irrevocably deleted.'**
String get deleteImageBody; String get deleteImageBody;
/// No description provided for @settingsBackup.
///
/// In en, this message translates to:
/// **'Backup'**
String get settingsBackup;
} }
class _AppLocalizationsDelegate class _AppLocalizationsDelegate

View file

@ -833,4 +833,7 @@ class AppLocalizationsDe extends AppLocalizations {
@override @override
String get deleteImageBody => 'Das Bild wird unwiderruflich gelöscht.'; String get deleteImageBody => 'Das Bild wird unwiderruflich gelöscht.';
@override
String get settingsBackup => 'Backup';
} }

View file

@ -827,4 +827,7 @@ class AppLocalizationsEn extends AppLocalizations {
@override @override
String get deleteImageBody => 'The image will be irrevocably deleted.'; String get deleteImageBody => 'The image will be irrevocably deleted.';
@override
String get settingsBackup => 'Backup';
} }

View file

@ -0,0 +1,138 @@
import 'package:flutter/material.dart';
import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/views/settings/backup/twonly_identity_backup.view.dart';
class BackupView extends StatefulWidget {
const BackupView({super.key});
@override
State<BackupView> createState() => _BackupViewState();
}
class _BackupViewState extends State<BackupView> {
bool _twonlyIdBackupEnabled = false;
DateTime? _twonlyIdLastBackup;
bool _dataBackupEnabled = false;
DateTime? _dataBackupLastBackup;
@override
void initState() {
initAsync();
super.initState();
}
Future initAsync() async {
setState(() {
_twonlyIdBackupEnabled = true;
_dataBackupEnabled = false;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(context.lang.settingsBackup),
),
body: ListView(
children: [
BackupOption(
title: 'twonly-Identity Backup',
description:
'Back up your twonly identity, as this is the only way to restore your account if you uninstall or lose your phone.',
lastBackup: _twonlyIdLastBackup,
autoBackupEnabled: _twonlyIdBackupEnabled,
onTap: () async {
await Navigator.push(context,
MaterialPageRoute(builder: (context) {
return TwonlyIdentityBackupView();
}));
initAsync();
},
),
BackupOption(
title: 'Daten-Backup',
description:
'This backup contains besides of your twonly-Identity also all of your media files. This backup will also be encrypted using a password chosen by the user but stored locally on the smartphone. You then have to ensure to manually copy it onto your laptop or device of your choice.',
autoBackupEnabled: _dataBackupEnabled,
onTap: () {},
lastBackup: _dataBackupLastBackup,
),
],
),
);
}
}
class BackupOption extends StatelessWidget {
final String title;
final String description;
final bool autoBackupEnabled;
final DateTime? lastBackup;
final Function() onTap;
const BackupOption({
super.key,
required this.title,
required this.description,
required this.autoBackupEnabled,
required this.lastBackup,
required this.onTap,
});
String formatDateTime(DateTime? dateTime) {
if (dateTime == null) {
return "Never";
}
final now = DateTime.now();
final difference = now.difference(dateTime);
if (difference.inDays == 0) {
return 'Today';
} else if (difference.inDays == 1) {
return 'Yesterday';
} else {
return '${difference.inDays} Days ago';
}
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: onTap,
child: Card(
margin: EdgeInsets.all(8.0),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
SizedBox(height: 8.0),
Text(description),
SizedBox(height: 8.0),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('Last backup: ${formatDateTime(lastBackup)}'),
(autoBackupEnabled)
? OutlinedButton(
onPressed: onTap,
child: Text("Disable"),
)
: FilledButton(
onPressed: onTap,
child: Text("Enable"),
)
],
),
],
),
),
),
);
}
}

View file

@ -0,0 +1,24 @@
import 'package:flutter/material.dart';
class TwonlyIdentityBackupView extends StatefulWidget {
const TwonlyIdentityBackupView({super.key});
@override
State<TwonlyIdentityBackupView> createState() =>
_TwonlyIdentityBackupViewState();
}
class _TwonlyIdentityBackupViewState extends State<TwonlyIdentityBackupView> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("twonly-Identity Backup"),
),
body: ListView(children: [
Text(
'Backup of your twonly-Identity. As twonly does not have any second factor like your phone number or email, this backup contains your twonly-Identity. If you lose your device, the only option to recover is with the twonly-ID Backup. This backup will be protected by a password chosen by you in the next step and anonymously uploaded to the twonly servers. Read more [here](https://twonly.eu/s/backup).'),
]),
);
}
}

View file

@ -120,6 +120,16 @@ class _SettingsMainViewState extends State<SettingsMainView> {
})); }));
}, },
), ),
// BetterListTile(
// icon: Icons.lock_clock_rounded,
// text: context.lang.settingsBackup,
// onTap: () {
// Navigator.push(context,
// MaterialPageRoute(builder: (context) {
// return BackupView();
// }));
// },
// ),
const Divider(), const Divider(),
BetterListTile( BetterListTile(
icon: FontAwesomeIcons.sun, icon: FontAwesomeIcons.sun,