mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-01-15 11:18:41 +00:00
twonly Safe is now mandatory
This commit is contained in:
parent
404aee1e18
commit
d40e33b247
14 changed files with 290 additions and 274 deletions
|
|
@ -11,6 +11,7 @@ import 'package:twonly/src/views/components/app_outdated.dart';
|
|||
import 'package:twonly/src/views/home.view.dart';
|
||||
import 'package:twonly/src/views/onboarding/onboarding.view.dart';
|
||||
import 'package:twonly/src/views/onboarding/register.view.dart';
|
||||
import 'package:twonly/src/views/settings/backup/twonly_safe_backup.view.dart';
|
||||
import 'package:twonly/src/views/updates/62_database_migration.view.dart';
|
||||
|
||||
class App extends StatefulWidget {
|
||||
|
|
@ -181,9 +182,17 @@ class _AppMainWidgetState extends State<AppMainWidget> {
|
|||
if (_showDatabaseMigration) {
|
||||
child = const DatabaseMigrationView();
|
||||
} else if (_isUserCreated) {
|
||||
if (gUser.twonlySafeBackup == null) {
|
||||
child = TwonlyIdentityBackupView(
|
||||
callBack: () {
|
||||
setState(() {});
|
||||
},
|
||||
);
|
||||
} else {
|
||||
child = HomeView(
|
||||
initialPage: widget.initialPage,
|
||||
);
|
||||
}
|
||||
} else if (_showOnboarding) {
|
||||
child = OnboardingView(
|
||||
callbackOnSuccess: () => setState(() {
|
||||
|
|
|
|||
|
|
@ -311,6 +311,7 @@
|
|||
"backupLastBackupSize": "Backup-Größe",
|
||||
"backupLastBackupResult": "Ergebnis",
|
||||
"deleteBackupTitle": "Bist du sicher?",
|
||||
"backupNoPasswordRecovery": "Aufgrund des Sicherheitssystems von twonly gibt es (derzeit) keine Funktion zur Wiederherstellung des Passworts. Daher musst du dir dein Passwort merken oder, besser noch, aufschreiben.",
|
||||
"deleteBackupBody": "Ohne ein Backup kannst du dein Benutzerkonto nicht wiederherstellen.",
|
||||
"backupData": "Daten-Backup",
|
||||
"backupDataDesc": "Das Daten-Backup enthält neben deiner twonly-Identität auch alle deine Mediendateien. Dieses Backup ist ebenfalls verschlüsselt, wird jedoch lokal gespeichert. Du musst es dann manuell auf deinen Laptop oder ein Gerät deiner Wahl kopieren.",
|
||||
|
|
@ -318,18 +319,19 @@
|
|||
"backupInsecurePasswordDesc": "Das gewählte Passwort ist sehr unsicher und kann daher leicht von Angreifern erraten werden. Bitte wähle ein sicheres Passwort.",
|
||||
"backupInsecurePasswordOk": "Trotzdem fortfahren",
|
||||
"backupInsecurePasswordCancel": "Erneut versuchen",
|
||||
"backupTwonlySafeLongDesc": "twonly hat keine zentralen Benutzerkonten. Während der Installation wird ein Schlüsselpaar erstellt, das aus einem öffentlichen und einem privaten Schlüssel besteht. Der private Schlüssel wird nur auf deinem Gerät gespeichert, um ihn vor unbefugtem Zugriff zu schützen. Der öffentliche Schlüssel wird auf den Server hochgeladen und mit deinem gewählten Benutzernamen verknüpft, damit andere dich finden können.\n\ntwonly Safe erstellt regelmäßig ein verschlüsseltes, anonymes Backup deines privaten Schlüssels zusammen mit deinen Kontakten und Einstellungen. Dein Benutzername und das gewählte Passwort reichen aus, um diese Daten auf einem anderen Gerät wiederherzustellen.",
|
||||
"backupSelectStrongPassword": "Wähle ein sicheres Passwort. Dies ist erforderlich, wenn du dein twonly Safe-Backup wiederherstellen möchtest.",
|
||||
"backupTwonlySafeLongDesc": "twonly hat keine zentralen Benutzerkonten. Während der Installation wird ein Schlüsselpaar erstellt, das aus einem öffentlichen und einem privaten Schlüssel besteht. Der private Schlüssel wird nur auf deinem Gerät gespeichert, um ihn vor unbefugtem Zugriff zu schützen. Der öffentliche Schlüssel wird auf den Server hochgeladen und mit deinem gewählten Benutzernamen verknüpft, damit andere dich finden können.\n\ntwonly Backup erstellt regelmäßig ein verschlüsseltes, anonymes Backup deines privaten Schlüssels zusammen mit deinen Kontakten und Einstellungen. Dein Benutzername und das gewählte Passwort reichen aus, um diese Daten auf einem anderen Gerät wiederherzustellen.",
|
||||
"backupSelectStrongPassword": "Wähle ein sicheres Passwort. Dies ist erforderlich, wenn du dein twonly Backup wiederherstellen möchtest.",
|
||||
"password": "Passwort",
|
||||
"passwordRepeated": "Passwort wiederholen",
|
||||
"passwordRepeatedNotEqual": "Passwörter stimmen nicht überein.",
|
||||
"backupPasswordRequirement": "Das Passwort muss mindestens 8 Zeichen lang sein.",
|
||||
"backupExpertSettings": "Experteneinstellungen",
|
||||
"backupEnableBackup": "Automatische Sicherung aktivieren",
|
||||
"backupOwnServerDesc": "Speichere dein twonly Safe-Backups auf einem Server deiner Wahl.",
|
||||
"backupOwnServerDesc": "Speichere dein twonly Backup auf einem Server deiner Wahl.",
|
||||
"backupUseOwnServer": "Server verwenden",
|
||||
"backupResetServer": "Standardserver verwenden",
|
||||
"backupTwonlySaveNow": "Jetzt speichern",
|
||||
"backupChangePassword": "Password ändern",
|
||||
"inviteFriends": "Freunde einladen",
|
||||
"inviteFriendsShareBtn": "Teilen",
|
||||
"inviteFriendsShareText": "Wechseln wir zu twonly: {url}",
|
||||
|
|
|
|||
|
|
@ -457,6 +457,7 @@
|
|||
"backupFailed": "Failed",
|
||||
"backupSuccess": "Success",
|
||||
"backupTwonlySafeDesc": "Back up your twonly identity, as this is the only way to restore your account if you uninstall the app or lose your phone.",
|
||||
"backupNoPasswordRecovery": "Due to twonly's security system, there is (currently) no password recovery function. Therefore, you must remember your password or, better yet, write it down.",
|
||||
"backupServer": "Server",
|
||||
"backupMaxBackupSize": "max. backup size",
|
||||
"backupStorageRetention": "Storage retention",
|
||||
|
|
@ -471,20 +472,21 @@
|
|||
"backupInsecurePasswordDesc": "The chosen password is very insecure and can therefore easily be guessed by attackers. Please choose a secure password.",
|
||||
"backupInsecurePasswordOk": "Continue anyway",
|
||||
"backupInsecurePasswordCancel": "Try again",
|
||||
"backupTwonlySafeLongDesc": "twonly does not have any central user accounts. A key pair is created during installation, which consists of a public and a private key. The private key is only stored on your device to protect it from unauthorized access. The public key is uploaded to the server and linked to your chosen username so that others can find you.\n\ntwonly Safe regularly creates an encrypted, anonymous backup of your private key together with your contacts and settings. Your username and chosen password are enough to restore this data on another device.",
|
||||
"backupSelectStrongPassword": "Choose a secure password. This is required if you want to restore your twonly Safe backup.",
|
||||
"backupTwonlySafeLongDesc": "twonly does not have any central user accounts. A key pair is created during installation, which consists of a public and a private key. The private key is only stored on your device to protect it from unauthorized access. The public key is uploaded to the server and linked to your chosen username so that others can find you.\n\ntwonly Backup regularly creates an encrypted, anonymous backup of your private key together with your contacts and settings. Your username and chosen password are enough to restore this data on another device.",
|
||||
"backupSelectStrongPassword": "Choose a secure password. This is required if you want to restore your twonly Backup.",
|
||||
"password": "Password",
|
||||
"passwordRepeated": "Repeat password",
|
||||
"passwordRepeatedNotEqual": "Passwords do not match.",
|
||||
"backupPasswordRequirement": "Password must be at least 8 characters long.",
|
||||
"backupExpertSettings": "Expert settings",
|
||||
"backupEnableBackup": "Activate automatic backup",
|
||||
"backupOwnServerDesc": "Save your twonly safe backups at twonly or on any server of your choice.",
|
||||
"backupOwnServerDesc": "Save your twonly Backup at twonly or on any server of your choice.",
|
||||
"backupUseOwnServer": "Use server",
|
||||
"backupResetServer": "Use standard server",
|
||||
"backupTwonlySaveNow": "Save now",
|
||||
"backupChangePassword": "Change password",
|
||||
"twonlySafeRecoverTitle": "Recovery",
|
||||
"twonlySafeRecoverDesc": "If you have created a backup with twonly Safe, you can restore it here.",
|
||||
"twonlySafeRecoverDesc": "If you have created a backup with twonly Backup, you can restore it here.",
|
||||
"twonlySafeRecoverBtn": "Restore backup",
|
||||
"inviteFriends": "Invite your friends",
|
||||
"inviteFriendsShareBtn": "Share",
|
||||
|
|
|
|||
|
|
@ -1844,6 +1844,12 @@ abstract class AppLocalizations {
|
|||
/// **'Back up your twonly identity, as this is the only way to restore your account if you uninstall the app or lose your phone.'**
|
||||
String get backupTwonlySafeDesc;
|
||||
|
||||
/// No description provided for @backupNoPasswordRecovery.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Due to twonly\'s security system, there is (currently) no password recovery function. Therefore, you must remember your password or, better yet, write it down.'**
|
||||
String get backupNoPasswordRecovery;
|
||||
|
||||
/// No description provided for @backupServer.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
|
|
@ -1931,13 +1937,13 @@ abstract class AppLocalizations {
|
|||
/// No description provided for @backupTwonlySafeLongDesc.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'twonly does not have any central user accounts. A key pair is created during installation, which consists of a public and a private key. The private key is only stored on your device to protect it from unauthorized access. The public key is uploaded to the server and linked to your chosen username so that others can find you.\n\ntwonly Safe regularly creates an encrypted, anonymous backup of your private key together with your contacts and settings. Your username and chosen password are enough to restore this data on another device.'**
|
||||
/// **'twonly does not have any central user accounts. A key pair is created during installation, which consists of a public and a private key. The private key is only stored on your device to protect it from unauthorized access. The public key is uploaded to the server and linked to your chosen username so that others can find you.\n\ntwonly Backup regularly creates an encrypted, anonymous backup of your private key together with your contacts and settings. Your username and chosen password are enough to restore this data on another device.'**
|
||||
String get backupTwonlySafeLongDesc;
|
||||
|
||||
/// No description provided for @backupSelectStrongPassword.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Choose a secure password. This is required if you want to restore your twonly Safe backup.'**
|
||||
/// **'Choose a secure password. This is required if you want to restore your twonly Backup.'**
|
||||
String get backupSelectStrongPassword;
|
||||
|
||||
/// No description provided for @password.
|
||||
|
|
@ -1979,7 +1985,7 @@ abstract class AppLocalizations {
|
|||
/// No description provided for @backupOwnServerDesc.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Save your twonly safe backups at twonly or on any server of your choice.'**
|
||||
/// **'Save your twonly Backup at twonly or on any server of your choice.'**
|
||||
String get backupOwnServerDesc;
|
||||
|
||||
/// No description provided for @backupUseOwnServer.
|
||||
|
|
@ -2000,6 +2006,12 @@ abstract class AppLocalizations {
|
|||
/// **'Save now'**
|
||||
String get backupTwonlySaveNow;
|
||||
|
||||
/// No description provided for @backupChangePassword.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Change password'**
|
||||
String get backupChangePassword;
|
||||
|
||||
/// No description provided for @twonlySafeRecoverTitle.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
|
|
@ -2009,7 +2021,7 @@ abstract class AppLocalizations {
|
|||
/// No description provided for @twonlySafeRecoverDesc.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'If you have created a backup with twonly Safe, you can restore it here.'**
|
||||
/// **'If you have created a backup with twonly Backup, you can restore it here.'**
|
||||
String get twonlySafeRecoverDesc;
|
||||
|
||||
/// No description provided for @twonlySafeRecoverBtn.
|
||||
|
|
|
|||
|
|
@ -973,6 +973,10 @@ class AppLocalizationsDe extends AppLocalizations {
|
|||
String get backupTwonlySafeDesc =>
|
||||
'Sichere deine twonly-Identität, da dies die einzige Möglichkeit ist, dein Konto wiederherzustellen, wenn du die App deinstallierst oder dein Handy verlierst.';
|
||||
|
||||
@override
|
||||
String get backupNoPasswordRecovery =>
|
||||
'Aufgrund des Sicherheitssystems von twonly gibt es (derzeit) keine Funktion zur Wiederherstellung des Passworts. Daher musst du dir dein Passwort merken oder, besser noch, aufschreiben.';
|
||||
|
||||
@override
|
||||
String get backupServer => 'Server';
|
||||
|
||||
|
|
@ -1020,11 +1024,11 @@ class AppLocalizationsDe extends AppLocalizations {
|
|||
|
||||
@override
|
||||
String get backupTwonlySafeLongDesc =>
|
||||
'twonly hat keine zentralen Benutzerkonten. Während der Installation wird ein Schlüsselpaar erstellt, das aus einem öffentlichen und einem privaten Schlüssel besteht. Der private Schlüssel wird nur auf deinem Gerät gespeichert, um ihn vor unbefugtem Zugriff zu schützen. Der öffentliche Schlüssel wird auf den Server hochgeladen und mit deinem gewählten Benutzernamen verknüpft, damit andere dich finden können.\n\ntwonly Safe erstellt regelmäßig ein verschlüsseltes, anonymes Backup deines privaten Schlüssels zusammen mit deinen Kontakten und Einstellungen. Dein Benutzername und das gewählte Passwort reichen aus, um diese Daten auf einem anderen Gerät wiederherzustellen.';
|
||||
'twonly hat keine zentralen Benutzerkonten. Während der Installation wird ein Schlüsselpaar erstellt, das aus einem öffentlichen und einem privaten Schlüssel besteht. Der private Schlüssel wird nur auf deinem Gerät gespeichert, um ihn vor unbefugtem Zugriff zu schützen. Der öffentliche Schlüssel wird auf den Server hochgeladen und mit deinem gewählten Benutzernamen verknüpft, damit andere dich finden können.\n\ntwonly Backup erstellt regelmäßig ein verschlüsseltes, anonymes Backup deines privaten Schlüssels zusammen mit deinen Kontakten und Einstellungen. Dein Benutzername und das gewählte Passwort reichen aus, um diese Daten auf einem anderen Gerät wiederherzustellen.';
|
||||
|
||||
@override
|
||||
String get backupSelectStrongPassword =>
|
||||
'Wähle ein sicheres Passwort. Dies ist erforderlich, wenn du dein twonly Safe-Backup wiederherstellen möchtest.';
|
||||
'Wähle ein sicheres Passwort. Dies ist erforderlich, wenn du dein twonly Backup wiederherstellen möchtest.';
|
||||
|
||||
@override
|
||||
String get password => 'Passwort';
|
||||
|
|
@ -1047,7 +1051,7 @@ class AppLocalizationsDe extends AppLocalizations {
|
|||
|
||||
@override
|
||||
String get backupOwnServerDesc =>
|
||||
'Speichere dein twonly Safe-Backups auf einem Server deiner Wahl.';
|
||||
'Speichere dein twonly Backup auf einem Server deiner Wahl.';
|
||||
|
||||
@override
|
||||
String get backupUseOwnServer => 'Server verwenden';
|
||||
|
|
@ -1058,12 +1062,15 @@ class AppLocalizationsDe extends AppLocalizations {
|
|||
@override
|
||||
String get backupTwonlySaveNow => 'Jetzt speichern';
|
||||
|
||||
@override
|
||||
String get backupChangePassword => 'Password ändern';
|
||||
|
||||
@override
|
||||
String get twonlySafeRecoverTitle => 'Recovery';
|
||||
|
||||
@override
|
||||
String get twonlySafeRecoverDesc =>
|
||||
'If you have created a backup with twonly Safe, you can restore it here.';
|
||||
'If you have created a backup with twonly Backup, you can restore it here.';
|
||||
|
||||
@override
|
||||
String get twonlySafeRecoverBtn => 'Restore backup';
|
||||
|
|
|
|||
|
|
@ -967,6 +967,10 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||
String get backupTwonlySafeDesc =>
|
||||
'Back up your twonly identity, as this is the only way to restore your account if you uninstall the app or lose your phone.';
|
||||
|
||||
@override
|
||||
String get backupNoPasswordRecovery =>
|
||||
'Due to twonly\'s security system, there is (currently) no password recovery function. Therefore, you must remember your password or, better yet, write it down.';
|
||||
|
||||
@override
|
||||
String get backupServer => 'Server';
|
||||
|
||||
|
|
@ -1014,11 +1018,11 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||
|
||||
@override
|
||||
String get backupTwonlySafeLongDesc =>
|
||||
'twonly does not have any central user accounts. A key pair is created during installation, which consists of a public and a private key. The private key is only stored on your device to protect it from unauthorized access. The public key is uploaded to the server and linked to your chosen username so that others can find you.\n\ntwonly Safe regularly creates an encrypted, anonymous backup of your private key together with your contacts and settings. Your username and chosen password are enough to restore this data on another device.';
|
||||
'twonly does not have any central user accounts. A key pair is created during installation, which consists of a public and a private key. The private key is only stored on your device to protect it from unauthorized access. The public key is uploaded to the server and linked to your chosen username so that others can find you.\n\ntwonly Backup regularly creates an encrypted, anonymous backup of your private key together with your contacts and settings. Your username and chosen password are enough to restore this data on another device.';
|
||||
|
||||
@override
|
||||
String get backupSelectStrongPassword =>
|
||||
'Choose a secure password. This is required if you want to restore your twonly Safe backup.';
|
||||
'Choose a secure password. This is required if you want to restore your twonly Backup.';
|
||||
|
||||
@override
|
||||
String get password => 'Password';
|
||||
|
|
@ -1041,7 +1045,7 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||
|
||||
@override
|
||||
String get backupOwnServerDesc =>
|
||||
'Save your twonly safe backups at twonly or on any server of your choice.';
|
||||
'Save your twonly Backup at twonly or on any server of your choice.';
|
||||
|
||||
@override
|
||||
String get backupUseOwnServer => 'Use server';
|
||||
|
|
@ -1052,12 +1056,15 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||
@override
|
||||
String get backupTwonlySaveNow => 'Save now';
|
||||
|
||||
@override
|
||||
String get backupChangePassword => 'Change password';
|
||||
|
||||
@override
|
||||
String get twonlySafeRecoverTitle => 'Recovery';
|
||||
|
||||
@override
|
||||
String get twonlySafeRecoverDesc =>
|
||||
'If you have created a backup with twonly Safe, you can restore it here.';
|
||||
'If you have created a backup with twonly Backup, you can restore it here.';
|
||||
|
||||
@override
|
||||
String get twonlySafeRecoverBtn => 'Restore backup';
|
||||
|
|
|
|||
|
|
@ -311,7 +311,9 @@ class ApiService {
|
|||
}
|
||||
if (res.error == ErrorCode.NewDeviceRegistered) {
|
||||
globalCallbackNewDeviceRegistered();
|
||||
Log.error('Device is disabled, as a newer device restore twonly Safe.');
|
||||
Log.error(
|
||||
'Device is disabled, as a newer device restore twonly Backup.',
|
||||
);
|
||||
appIsOutdated = true;
|
||||
await close(() {});
|
||||
return Result.error(ErrorCode.InternalError);
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ Future<void> performTwonlySafeBackup({bool force = false}) async {
|
|||
}
|
||||
}
|
||||
|
||||
Log.info('Starting new twonly Safe-Backup!');
|
||||
Log.info('Starting new twonly Backup!');
|
||||
|
||||
final baseDir = (await getApplicationSupportDirectory()).path;
|
||||
|
||||
|
|
@ -161,7 +161,7 @@ Future<void> performTwonlySafeBackup({bool force = false}) async {
|
|||
await encryptedBackupBytesFile.writeAsBytes(encryptedBackupBytes);
|
||||
|
||||
Log.info(
|
||||
'Create twonly Safe backup with a size of ${encryptedBackupBytes.length} bytes.',
|
||||
'Create twonly Backup with a size of ${encryptedBackupBytes.length} bytes.',
|
||||
);
|
||||
|
||||
if (gUser.backupServer != null) {
|
||||
|
|
@ -187,7 +187,7 @@ Future<void> performTwonlySafeBackup({bool force = false}) async {
|
|||
},
|
||||
);
|
||||
if (await FileDownloader().enqueue(task)) {
|
||||
Log.info('Starting upload from twonly Safe backup.');
|
||||
Log.info('Starting upload from twonly Backup.');
|
||||
await updateUserdata((user) {
|
||||
user.twonlySafeBackup!.backupUploadState = LastBackupUploadState.pending;
|
||||
user.twonlySafeBackup!.lastBackupDone = DateTime.now();
|
||||
|
|
@ -196,7 +196,7 @@ Future<void> performTwonlySafeBackup({bool force = false}) async {
|
|||
});
|
||||
gUpdateBackupView();
|
||||
} else {
|
||||
Log.error('Error starting UploadTask for twonly Safe.');
|
||||
Log.error('Error starting UploadTask for twonly Backup.');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -204,7 +204,7 @@ Future<void> handleBackupStatusUpdate(TaskStatusUpdate update) async {
|
|||
if (update.status == TaskStatus.failed ||
|
||||
update.status == TaskStatus.canceled) {
|
||||
Log.error(
|
||||
'twonly Safe upload failed. ${update.responseStatusCode} ${update.responseBody} ${update.responseHeaders} ${update.exception}',
|
||||
'twonly Backup upload failed. ${update.responseStatusCode} ${update.responseBody} ${update.responseHeaders} ${update.exception}',
|
||||
);
|
||||
await updateUserdata((user) {
|
||||
if (user.twonlySafeBackup != null) {
|
||||
|
|
@ -214,7 +214,7 @@ Future<void> handleBackupStatusUpdate(TaskStatusUpdate update) async {
|
|||
});
|
||||
} else if (update.status == TaskStatus.complete) {
|
||||
Log.error(
|
||||
'twonly Safe uploaded with status code ${update.responseStatusCode}',
|
||||
'twonly Backup uploaded with status code ${update.responseStatusCode}',
|
||||
);
|
||||
await updateUserdata((user) {
|
||||
if (user.twonlySafeBackup != null) {
|
||||
|
|
|
|||
|
|
@ -60,13 +60,13 @@ class _BackupRecoveryViewState extends State<BackupRecoveryView> {
|
|||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('twonly Safe ${context.lang.twonlySafeRecoverTitle}'),
|
||||
title: Text('twonly Backup ${context.lang.twonlySafeRecoverTitle}'),
|
||||
actions: [
|
||||
IconButton(
|
||||
onPressed: () async {
|
||||
await showAlertDialog(
|
||||
context,
|
||||
'twonly Safe',
|
||||
'twonly Backup',
|
||||
context.lang.backupTwonlySafeLongDesc,
|
||||
);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -166,30 +166,6 @@ class _RegisterViewState extends State<RegisterView> {
|
|||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
// const SizedBox(height: 5),
|
||||
// Center(
|
||||
// child: Padding(
|
||||
// padding: EdgeInsets.only(left: 10, right: 10),
|
||||
// child: Text(
|
||||
// context.lang.registerUsernameLimits,
|
||||
// textAlign: TextAlign.center,
|
||||
// style: const TextStyle(fontSize: 9),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// const SizedBox(height: 30),
|
||||
// Center(
|
||||
// child: Text(
|
||||
// context.lang.registerTwonlyCodeText,
|
||||
// textAlign: TextAlign.center,
|
||||
// ),
|
||||
// ),
|
||||
// const SizedBox(height: 10),
|
||||
// TextField(
|
||||
// controller: inviteCodeController,
|
||||
// decoration:
|
||||
// getInputDecoration(context.lang.registerTwonlyCodeLabel),
|
||||
// ),
|
||||
const SizedBox(height: 30),
|
||||
Column(
|
||||
children: [
|
||||
|
|
|
|||
|
|
@ -3,10 +3,8 @@ import 'package:flutter/material.dart';
|
|||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:twonly/globals.dart';
|
||||
import 'package:twonly/src/model/json/userdata.dart';
|
||||
import 'package:twonly/src/services/twonly_safe/common.twonly_safe.dart';
|
||||
import 'package:twonly/src/services/twonly_safe/create_backup.twonly_safe.dart';
|
||||
import 'package:twonly/src/utils/misc.dart';
|
||||
import 'package:twonly/src/views/components/alert_dialog.dart';
|
||||
import 'package:twonly/src/views/settings/backup/twonly_safe_backup.view.dart';
|
||||
|
||||
void Function() gUpdateBackupView = () {};
|
||||
|
|
@ -25,8 +23,6 @@ BackupServer defaultBackupServer = BackupServer(
|
|||
);
|
||||
|
||||
class _BackupViewState extends State<BackupView> {
|
||||
TwonlySafeBackup? twonlySafeBackup;
|
||||
BackupServer backupServer = defaultBackupServer;
|
||||
bool isLoading = false;
|
||||
|
||||
int activePageIdx = 0;
|
||||
|
|
@ -47,11 +43,6 @@ class _BackupViewState extends State<BackupView> {
|
|||
}
|
||||
|
||||
Future<void> initAsync() async {
|
||||
twonlySafeBackup = gUser.twonlySafeBackup;
|
||||
backupServer = defaultBackupServer;
|
||||
if (gUser.backupServer != null) {
|
||||
backupServer = gUser.backupServer!;
|
||||
}
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
|
|
@ -68,8 +59,25 @@ class _BackupViewState extends State<BackupView> {
|
|||
}
|
||||
}
|
||||
|
||||
Future<void> changeTwonlySafePassword() async {
|
||||
await Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) {
|
||||
return const TwonlyIdentityBackupView(
|
||||
isPasswordChangeOnly: true,
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
setState(() {
|
||||
// gUser was updated
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final backupServer = gUser.backupServer ?? defaultBackupServer;
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(context.lang.settingsBackup),
|
||||
|
|
@ -83,10 +91,13 @@ class _BackupViewState extends State<BackupView> {
|
|||
},
|
||||
children: [
|
||||
BackupOption(
|
||||
title: 'twonly Safe',
|
||||
title: 'twonly Backup',
|
||||
description: context.lang.backupTwonlySafeDesc,
|
||||
autoBackupEnabled: twonlySafeBackup != null,
|
||||
child: (twonlySafeBackup == null)
|
||||
bottomButton: FilledButton(
|
||||
onPressed: changeTwonlySafePassword,
|
||||
child: Text(context.lang.backupChangePassword),
|
||||
),
|
||||
child: (gUser.twonlySafeBackup == null)
|
||||
? null
|
||||
: Column(
|
||||
children: [
|
||||
|
|
@ -114,16 +125,20 @@ class _BackupViewState extends State<BackupView> {
|
|||
context.lang.backupLastBackupDate,
|
||||
formatDateTime(
|
||||
context,
|
||||
twonlySafeBackup!.lastBackupDone,
|
||||
gUser.twonlySafeBackup!.lastBackupDone,
|
||||
)
|
||||
),
|
||||
(
|
||||
context.lang.backupLastBackupSize,
|
||||
formatBytes(twonlySafeBackup!.lastBackupSize)
|
||||
formatBytes(
|
||||
gUser.twonlySafeBackup!.lastBackupSize,
|
||||
)
|
||||
),
|
||||
(
|
||||
context.lang.backupLastBackupResult,
|
||||
backupStatus(twonlySafeBackup!.backupUploadState)
|
||||
backupStatus(
|
||||
gUser.twonlySafeBackup!.backupUploadState,
|
||||
)
|
||||
),
|
||||
].map((pair) {
|
||||
return TableRow(
|
||||
|
|
@ -134,8 +149,9 @@ class _BackupViewState extends State<BackupView> {
|
|||
),
|
||||
TableCell(
|
||||
child: Padding(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(vertical: 4),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 4,
|
||||
),
|
||||
child: Text(
|
||||
pair.$2,
|
||||
textAlign: TextAlign.right,
|
||||
|
|
@ -148,7 +164,7 @@ class _BackupViewState extends State<BackupView> {
|
|||
],
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
FilledButton(
|
||||
OutlinedButton(
|
||||
onPressed: isLoading
|
||||
? null
|
||||
: () async {
|
||||
|
|
@ -164,37 +180,10 @@ class _BackupViewState extends State<BackupView> {
|
|||
),
|
||||
],
|
||||
),
|
||||
onTap: () async {
|
||||
if (twonlySafeBackup != null) {
|
||||
final disable = await showAlertDialog(
|
||||
context,
|
||||
context.lang.deleteBackupTitle,
|
||||
context.lang.deleteBackupBody,
|
||||
);
|
||||
if (disable) {
|
||||
await disableTwonlySafe();
|
||||
}
|
||||
} else {
|
||||
setState(() {
|
||||
isLoading = true;
|
||||
});
|
||||
await Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) {
|
||||
return const TwonlyIdentityBackupView();
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
await initAsync();
|
||||
},
|
||||
),
|
||||
BackupOption(
|
||||
title: '${context.lang.backupData} (Coming Soon)',
|
||||
description: context.lang.backupDataDesc,
|
||||
autoBackupEnabled: false,
|
||||
onTap: null,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
@ -209,7 +198,7 @@ class _BackupViewState extends State<BackupView> {
|
|||
items: [
|
||||
const BottomNavigationBarItem(
|
||||
icon: FaIcon(FontAwesomeIcons.vault, size: 17),
|
||||
label: 'twonly Safe',
|
||||
label: 'twonly Backup',
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
icon: const FaIcon(FontAwesomeIcons.boxArchive, size: 17),
|
||||
|
|
@ -236,22 +225,18 @@ class BackupOption extends StatelessWidget {
|
|||
const BackupOption({
|
||||
required this.title,
|
||||
required this.description,
|
||||
required this.autoBackupEnabled,
|
||||
required this.onTap,
|
||||
this.bottomButton,
|
||||
super.key,
|
||||
this.child,
|
||||
});
|
||||
final String title;
|
||||
final String description;
|
||||
final Widget? child;
|
||||
final bool autoBackupEnabled;
|
||||
final void Function()? onTap;
|
||||
final Widget? bottomButton;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GestureDetector(
|
||||
onTap: autoBackupEnabled ? null : onTap,
|
||||
child: Card(
|
||||
return Card(
|
||||
margin: const EdgeInsets.all(16),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
|
|
@ -260,29 +245,17 @@ class BackupOption extends StatelessWidget {
|
|||
children: [
|
||||
Text(
|
||||
title,
|
||||
style:
|
||||
const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
||||
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(description),
|
||||
const SizedBox(height: 8),
|
||||
if (child != null) child! else Container(),
|
||||
Expanded(child: Container()),
|
||||
Center(
|
||||
child: autoBackupEnabled
|
||||
? OutlinedButton(
|
||||
onPressed: onTap,
|
||||
child: Text(context.lang.disable),
|
||||
)
|
||||
: FilledButton(
|
||||
onPressed: onTap,
|
||||
child: Text(context.lang.enable),
|
||||
),
|
||||
),
|
||||
if (bottomButton != null) Center(child: bottomButton),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,16 @@ import 'package:twonly/src/views/components/alert_dialog.dart';
|
|||
import 'package:twonly/src/views/settings/backup/twonly_safe_server.view.dart';
|
||||
|
||||
class TwonlyIdentityBackupView extends StatefulWidget {
|
||||
const TwonlyIdentityBackupView({super.key});
|
||||
const TwonlyIdentityBackupView({
|
||||
this.isPasswordChangeOnly = false,
|
||||
this.callBack,
|
||||
super.key,
|
||||
});
|
||||
|
||||
// in case a callback is defined the callback
|
||||
// is called instead of the Navigator.pop()
|
||||
final VoidCallback? callBack;
|
||||
final bool isPasswordChangeOnly;
|
||||
|
||||
@override
|
||||
State<TwonlyIdentityBackupView> createState() =>
|
||||
|
|
@ -56,20 +65,26 @@ class _TwonlyIdentityBackupViewState extends State<TwonlyIdentityBackupView> {
|
|||
isLoading = false;
|
||||
});
|
||||
|
||||
if (widget.callBack != null) {
|
||||
widget.callBack!();
|
||||
} else {
|
||||
Navigator.pop(context);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
return GestureDetector(
|
||||
onTap: () => FocusScope.of(context).unfocus(),
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('twonly Safe'),
|
||||
title: const Text('twonly Backup'),
|
||||
actions: [
|
||||
IconButton(
|
||||
onPressed: () async {
|
||||
await showAlertDialog(
|
||||
context,
|
||||
'twonly Safe',
|
||||
'twonly Backup',
|
||||
context.lang.backupTwonlySafeLongDesc,
|
||||
);
|
||||
},
|
||||
|
|
@ -178,6 +193,12 @@ class _TwonlyIdentityBackupViewState extends State<TwonlyIdentityBackupView> {
|
|||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
context.lang.backupNoPasswordRecovery,
|
||||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(fontSize: 12),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Center(
|
||||
child: FilledButton.icon(
|
||||
onPressed: (!isLoading &&
|
||||
|
|
@ -193,12 +214,17 @@ class _TwonlyIdentityBackupViewState extends State<TwonlyIdentityBackupView> {
|
|||
child: CircularProgressIndicator(strokeWidth: 1),
|
||||
)
|
||||
: const Icon(Icons.lock_clock_rounded),
|
||||
label: Text(context.lang.backupEnableBackup),
|
||||
label: Text(
|
||||
widget.isPasswordChangeOnly
|
||||
? context.lang.backupChangePassword
|
||||
: context.lang.backupEnableBackup,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ class _TwonlySafeServerViewState extends State<TwonlySafeServerView> {
|
|||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('twonly Safe Server'),
|
||||
title: const Text('twonly Backup Server'),
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(40),
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ if [ ! -f "pubspec.yaml" ]; then
|
|||
exit 1
|
||||
fi
|
||||
|
||||
# Definitions for twonly Safe
|
||||
# Definitions for twonly Backup
|
||||
GENERATED_DIR="./lib/src/model/protobuf/client/generated/"
|
||||
CLIENT_DIR="./lib/src/model/protobuf/client/"
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue