mirror of
https://github.com/lollipopkit/flutter_server_box.git
synced 2025-12-17 07:14:28 +01:00
feat: custom pwd of bak (#827)
This commit is contained in:
@@ -2,7 +2,6 @@ import 'dart:async';
|
||||
|
||||
import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:server_box/core/extension/context/locale.dart';
|
||||
import 'package:server_box/data/model/server/server_private_info.dart';
|
||||
import 'package:server_box/data/provider/app.dart';
|
||||
|
||||
@@ -13,7 +12,7 @@ abstract final class KeybordInteractive {
|
||||
}) async {
|
||||
try {
|
||||
final res = await (ctx ?? AppProvider.ctx)?.showPwdDialog(
|
||||
title: l10n.pwd,
|
||||
title: libL10n.pwd,
|
||||
id: spi.id,
|
||||
label: spi.id,
|
||||
);
|
||||
|
||||
@@ -74,15 +74,27 @@ abstract class BackupV2 with _$BackupV2 implements Mergeable {
|
||||
);
|
||||
}
|
||||
|
||||
static Future<String> backup([String? name]) async {
|
||||
static Future<String> backup([String? name, String? password]) async {
|
||||
final bak = await BackupV2.loadFromStore();
|
||||
final result = json.encode(bak.toJson());
|
||||
var result = json.encode(bak.toJson());
|
||||
|
||||
if (password != null && password.isNotEmpty) {
|
||||
result = Cryptor.encrypt(result, password);
|
||||
}
|
||||
|
||||
final path = Paths.doc.joinPath(name ?? Miscs.bakFileName);
|
||||
await File(path).writeAsString(result);
|
||||
return path;
|
||||
}
|
||||
|
||||
factory BackupV2.fromJsonString(String jsonString) {
|
||||
factory BackupV2.fromJsonString(String jsonString, [String? password]) {
|
||||
if (Cryptor.isEncrypted(jsonString)) {
|
||||
if (password == null || password.isEmpty) {
|
||||
throw Exception('Backup is encrypted but no password provided');
|
||||
}
|
||||
jsonString = Cryptor.decrypt(jsonString, password);
|
||||
}
|
||||
|
||||
final map = json.decode(jsonString) as Map<String, dynamic>;
|
||||
return BackupV2.fromJson(map);
|
||||
}
|
||||
|
||||
198
lib/data/model/app/bak/backup_service.dart
Normal file
198
lib/data/model/app/bak/backup_service.dart
Normal file
@@ -0,0 +1,198 @@
|
||||
import 'package:computer/computer.dart';
|
||||
import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:server_box/core/extension/context/locale.dart';
|
||||
import 'package:server_box/data/model/app/bak/backup2.dart';
|
||||
import 'package:server_box/data/model/app/bak/backup_source.dart';
|
||||
import 'package:server_box/data/model/app/bak/utils.dart';
|
||||
import 'package:server_box/data/res/store.dart';
|
||||
|
||||
/// Service class for handling backup operations
|
||||
class BackupService {
|
||||
/// Perform backup operation with the given source
|
||||
static Future<void> backup(BuildContext context, BackupSource source) async {
|
||||
final password = await _getBackupPassword(context);
|
||||
if (password == null) return;
|
||||
|
||||
try {
|
||||
final path = await BackupV2.backup(null, password.isEmpty ? null : password);
|
||||
await source.saveContent(path);
|
||||
|
||||
// Show success message for clipboard source
|
||||
if (source is ClipboardBackupSource) {
|
||||
context.showSnackBar(libL10n.success);
|
||||
}
|
||||
} catch (e, s) {
|
||||
context.showErrDialog(e, s, libL10n.backup);
|
||||
}
|
||||
}
|
||||
|
||||
/// Perform restore operation with the given source
|
||||
static Future<void> restore(BuildContext context, BackupSource source) async {
|
||||
final text = await source.getContent();
|
||||
if (text == null) {
|
||||
// Show empty message for clipboard source
|
||||
if (source is ClipboardBackupSource) {
|
||||
context.showSnackBar(libL10n.empty);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
await restoreFromText(context, text);
|
||||
}
|
||||
|
||||
/// Handle password dialog for backup operations
|
||||
static Future<String?> _getBackupPassword(BuildContext context) async {
|
||||
final savedPassword = await Stores.setting.backupasswd.read();
|
||||
String? password;
|
||||
|
||||
if (savedPassword != null && savedPassword.isNotEmpty) {
|
||||
// Use saved password or ask for custom password
|
||||
final useCustom = await context.showRoundDialog<bool>(
|
||||
title: l10n.backupPassword,
|
||||
child: Text(l10n.backupPasswordTip),
|
||||
actions: [
|
||||
Btn.cancel(),
|
||||
TextButton(onPressed: () => context.pop(false), child: Text(l10n.backupPasswordSet)),
|
||||
TextButton(onPressed: () => context.pop(true), child: Text(libL10n.custom)),
|
||||
],
|
||||
);
|
||||
|
||||
if (useCustom == null) return null;
|
||||
|
||||
if (useCustom) {
|
||||
password = await _showPasswordDialog(context, initial: savedPassword);
|
||||
} else {
|
||||
password = savedPassword;
|
||||
}
|
||||
} else {
|
||||
// No saved password, ask if user wants to set one
|
||||
password = await _showPasswordDialog(context);
|
||||
}
|
||||
|
||||
return password;
|
||||
}
|
||||
|
||||
/// Handle restore from text with decryption support
|
||||
static Future<void> restoreFromText(BuildContext context, String text) async {
|
||||
// Check if backup is encrypted
|
||||
final isEncrypted = Cryptor.isEncrypted(text);
|
||||
String? password;
|
||||
|
||||
if (!isEncrypted) {
|
||||
try {
|
||||
final (backup, err) = await context.showLoadingDialog(
|
||||
fn: () => Computer.shared.start(MergeableUtils.fromJsonString, text),
|
||||
);
|
||||
if (err != null || backup == null) return;
|
||||
|
||||
await _confirmAndRestore(context, backup);
|
||||
} catch (e, s) {
|
||||
Loggers.app.warning('Import backup failed', e, s);
|
||||
context.showErrDialog(e, s, libL10n.restore);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Try with saved password first
|
||||
final savedPassword = await Stores.setting.backupasswd.read();
|
||||
if (savedPassword != null && savedPassword.isNotEmpty) {
|
||||
try {
|
||||
final (backup, err) = await context.showLoadingDialog(
|
||||
fn: () => Computer.shared.start((args) => MergeableUtils.fromJsonString(args.$1, args.$2), (
|
||||
text,
|
||||
savedPassword,
|
||||
)),
|
||||
);
|
||||
if (err == null && backup != null) {
|
||||
await _confirmAndRestore(context, backup);
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
// Saved password failed, will prompt for manual input
|
||||
}
|
||||
}
|
||||
|
||||
// Prompt for password with retry logic
|
||||
while (true) {
|
||||
password = await _showPasswordDialog(context, title: libL10n.pwd, hint: l10n.backupEncrypted);
|
||||
if (password == null) return; // User cancelled
|
||||
|
||||
try {
|
||||
final (backup, err) = await context.showLoadingDialog(
|
||||
fn: () => Computer.shared.start((args) => MergeableUtils.fromJsonString(args.$1, args.$2), (
|
||||
text,
|
||||
password,
|
||||
)),
|
||||
);
|
||||
if (err != null || backup == null) continue;
|
||||
|
||||
await _confirmAndRestore(context, backup);
|
||||
return;
|
||||
} catch (e) {
|
||||
if (e.toString().contains('incorrect password') || e.toString().contains('Failed to decrypt')) {
|
||||
final retry = await context.showRoundDialog<bool>(
|
||||
title: l10n.backupPasswordWrong,
|
||||
child: Text(l10n.backupPasswordWrong),
|
||||
actions: [
|
||||
TextButton(onPressed: () => context.pop(false), child: Text(libL10n.cancel)),
|
||||
TextButton(onPressed: () => context.pop(true), child: Text(libL10n.retry)),
|
||||
],
|
||||
);
|
||||
if (retry != true) return;
|
||||
continue; // Try again
|
||||
} else {
|
||||
// Other error, show and exit
|
||||
context.showErrDialog(e, null, libL10n.restore);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Confirm and execute restore operation
|
||||
static Future<void> _confirmAndRestore(BuildContext context, (dynamic, String) backup) async {
|
||||
await context.showRoundDialog(
|
||||
title: libL10n.restore,
|
||||
child: Text(libL10n.askContinue('${libL10n.restore} ${libL10n.backup}(${backup.$2})')),
|
||||
actions: Btn.ok(
|
||||
onTap: () async {
|
||||
await backup.$1.merge(force: true);
|
||||
context.pop();
|
||||
},
|
||||
).toList,
|
||||
);
|
||||
}
|
||||
|
||||
/// Show password input dialog
|
||||
static Future<String?> _showPasswordDialog(
|
||||
BuildContext context, {
|
||||
String? initial,
|
||||
String? title,
|
||||
String? hint,
|
||||
}) async {
|
||||
final controller = TextEditingController(text: initial ?? '');
|
||||
final result = await context.showRoundDialog<String>(
|
||||
title: title ?? libL10n.pwd,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(hint ?? l10n.backupPasswordTip, style: UIs.textGrey),
|
||||
UIs.height13,
|
||||
Input(
|
||||
label: l10n.backupPassword,
|
||||
controller: controller,
|
||||
obscureText: true,
|
||||
onSubmitted: (_) => context.pop(controller.text),
|
||||
),
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
Btn.cancel(),
|
||||
TextButton(onPressed: () => context.pop(controller.text), child: Text(libL10n.ok)),
|
||||
],
|
||||
);
|
||||
controller.dispose();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
62
lib/data/model/app/bak/backup_source.dart
Normal file
62
lib/data/model/app/bak/backup_source.dart
Normal file
@@ -0,0 +1,62 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:fl_lib/fl_lib.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// Abstract interface for backup content sources
|
||||
abstract class BackupSource {
|
||||
/// Get content from this source for restore
|
||||
Future<String?> getContent();
|
||||
|
||||
/// Save content to this source for backup
|
||||
Future<void> saveContent(String filePath);
|
||||
|
||||
/// Display name for this source
|
||||
String get displayName;
|
||||
|
||||
/// Icon for this source
|
||||
IconData get icon;
|
||||
}
|
||||
|
||||
/// File-based backup source
|
||||
class FileBackupSource implements BackupSource {
|
||||
@override
|
||||
Future<String?> getContent() async {
|
||||
return await Pfs.pickFileString();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> saveContent(String filePath) async {
|
||||
await Pfs.sharePaths(paths: [filePath]);
|
||||
}
|
||||
|
||||
@override
|
||||
String get displayName => libL10n.file;
|
||||
|
||||
@override
|
||||
IconData get icon => Icons.file_open;
|
||||
}
|
||||
|
||||
/// Clipboard-based backup source
|
||||
class ClipboardBackupSource implements BackupSource {
|
||||
@override
|
||||
Future<String?> getContent() async {
|
||||
final text = await Pfs.paste();
|
||||
if (text == null || text.isEmpty) {
|
||||
return null;
|
||||
}
|
||||
return text.trim();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> saveContent(String filePath) async {
|
||||
final content = await File(filePath).readAsString();
|
||||
Pfs.copy(content);
|
||||
}
|
||||
|
||||
@override
|
||||
String get displayName => libL10n.clipboard;
|
||||
|
||||
@override
|
||||
IconData get icon => Icons.content_paste;
|
||||
}
|
||||
@@ -3,9 +3,9 @@ import 'package:server_box/data/model/app/bak/backup.dart';
|
||||
import 'package:server_box/data/model/app/bak/backup2.dart';
|
||||
|
||||
abstract final class MergeableUtils {
|
||||
static (Mergeable, String) fromJsonString(String json) {
|
||||
static (Mergeable, String) fromJsonString(String json, [String? password]) {
|
||||
try {
|
||||
final bak = BackupV2.fromJsonString(json);
|
||||
final bak = BackupV2.fromJsonString(json, password);
|
||||
return (bak, DateTime.fromMillisecondsSinceEpoch(bak.date).hms());
|
||||
} catch (e) {
|
||||
final bak = Backup.fromJsonString(json);
|
||||
|
||||
@@ -270,4 +270,7 @@ class SettingStore extends HiveStore {
|
||||
|
||||
/// Have notified user for notificaiton permission or not
|
||||
late final noNotiPerm = propertyDefault('noNotiPerm', false);
|
||||
|
||||
/// The backup password
|
||||
late final backupasswd = SecureProp('bakPasswd');
|
||||
}
|
||||
|
||||
@@ -188,7 +188,7 @@ abstract class AppLocalizations {
|
||||
/// No description provided for @backupTip.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'The exported data is weakly encrypted. \nPlease keep it safe.'**
|
||||
/// **'The exported data can be encrypted with password. \nPlease keep it safe.'**
|
||||
String get backupTip;
|
||||
|
||||
/// No description provided for @backupVersionNotMatch.
|
||||
@@ -197,6 +197,48 @@ abstract class AppLocalizations {
|
||||
/// **'Backup version is not match.'**
|
||||
String get backupVersionNotMatch;
|
||||
|
||||
/// No description provided for @backupPassword.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Backup password'**
|
||||
String get backupPassword;
|
||||
|
||||
/// No description provided for @backupPasswordTip.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Set a password to encrypt backup files. Leave empty to disable encryption.'**
|
||||
String get backupPasswordTip;
|
||||
|
||||
/// No description provided for @backupPasswordWrong.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Incorrect backup password'**
|
||||
String get backupPasswordWrong;
|
||||
|
||||
/// No description provided for @backupEncrypted.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Backup is encrypted'**
|
||||
String get backupEncrypted;
|
||||
|
||||
/// No description provided for @backupNotEncrypted.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Backup is not encrypted'**
|
||||
String get backupNotEncrypted;
|
||||
|
||||
/// No description provided for @backupPasswordSet.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Backup password set'**
|
||||
String get backupPasswordSet;
|
||||
|
||||
/// No description provided for @backupPasswordRemoved.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Backup password removed'**
|
||||
String get backupPasswordRemoved;
|
||||
|
||||
/// No description provided for @battery.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
@@ -944,12 +986,6 @@ abstract class AppLocalizations {
|
||||
/// **'This feature is currently in the testing phase and has only been tested on PVE 8+. Please use it with caution.'**
|
||||
String get pveVersionLow;
|
||||
|
||||
/// No description provided for @pwd.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Password'**
|
||||
String get pwd;
|
||||
|
||||
/// No description provided for @read.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
|
||||
@@ -47,12 +47,34 @@ class AppLocalizationsDe extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get backupTip =>
|
||||
'Das Backup wird nur einfach verschlüsselt.\nBitte bewahre die Datei sicher auf.';
|
||||
'Die exportierten Daten können mit einem Passwort verschlüsselt werden. \nBitte sicher aufbewahren.';
|
||||
|
||||
@override
|
||||
String get backupVersionNotMatch =>
|
||||
'Die Backup-Version stimmt nicht überein.';
|
||||
|
||||
@override
|
||||
String get backupPassword => 'Backup-Passwort';
|
||||
|
||||
@override
|
||||
String get backupPasswordTip =>
|
||||
'Setzen Sie ein Passwort, um Backup-Dateien zu verschlüsseln. Leer lassen, um Verschlüsselung zu deaktivieren.';
|
||||
|
||||
@override
|
||||
String get backupPasswordWrong => 'Falsches Backup-Passwort';
|
||||
|
||||
@override
|
||||
String get backupEncrypted => 'Backup ist verschlüsselt';
|
||||
|
||||
@override
|
||||
String get backupNotEncrypted => 'Backup ist nicht verschlüsselt';
|
||||
|
||||
@override
|
||||
String get backupPasswordSet => 'Backup-Passwort gesetzt';
|
||||
|
||||
@override
|
||||
String get backupPasswordRemoved => 'Backup-Passwort entfernt';
|
||||
|
||||
@override
|
||||
String get battery => 'Batterie';
|
||||
|
||||
@@ -470,9 +492,6 @@ class AppLocalizationsDe extends AppLocalizations {
|
||||
String get pveVersionLow =>
|
||||
'Diese Funktion befindet sich derzeit in der Testphase und wurde nur auf PVE 8+ getestet. Bitte verwenden Sie sie mit Vorsicht.';
|
||||
|
||||
@override
|
||||
String get pwd => 'Passwort';
|
||||
|
||||
@override
|
||||
String get read => 'Lesen';
|
||||
|
||||
|
||||
@@ -47,11 +47,33 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get backupTip =>
|
||||
'The exported data is weakly encrypted. \nPlease keep it safe.';
|
||||
'The exported data can be encrypted with password. \nPlease keep it safe.';
|
||||
|
||||
@override
|
||||
String get backupVersionNotMatch => 'Backup version is not match.';
|
||||
|
||||
@override
|
||||
String get backupPassword => 'Backup password';
|
||||
|
||||
@override
|
||||
String get backupPasswordTip =>
|
||||
'Set a password to encrypt backup files. Leave empty to disable encryption.';
|
||||
|
||||
@override
|
||||
String get backupPasswordWrong => 'Incorrect backup password';
|
||||
|
||||
@override
|
||||
String get backupEncrypted => 'Backup is encrypted';
|
||||
|
||||
@override
|
||||
String get backupNotEncrypted => 'Backup is not encrypted';
|
||||
|
||||
@override
|
||||
String get backupPasswordSet => 'Backup password set';
|
||||
|
||||
@override
|
||||
String get backupPasswordRemoved => 'Backup password removed';
|
||||
|
||||
@override
|
||||
String get battery => 'Battery';
|
||||
|
||||
@@ -468,9 +490,6 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||
String get pveVersionLow =>
|
||||
'This feature is currently in the testing phase and has only been tested on PVE 8+. Please use it with caution.';
|
||||
|
||||
@override
|
||||
String get pwd => 'Password';
|
||||
|
||||
@override
|
||||
String get read => 'Read';
|
||||
|
||||
|
||||
@@ -47,12 +47,34 @@ class AppLocalizationsEs extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get backupTip =>
|
||||
'Los datos exportados solo están encriptados de manera básica, por favor guárdalos en un lugar seguro.';
|
||||
'Los datos exportados pueden ser encriptados con contraseña. \nPor favor guárdalos en un lugar seguro.';
|
||||
|
||||
@override
|
||||
String get backupVersionNotMatch =>
|
||||
'La versión de la copia de seguridad no coincide, no se puede restaurar';
|
||||
|
||||
@override
|
||||
String get backupPassword => 'Contraseña de respaldo';
|
||||
|
||||
@override
|
||||
String get backupPasswordTip =>
|
||||
'Establece una contraseña para encriptar archivos de respaldo. Déjalo vacío para desactivar la encriptación.';
|
||||
|
||||
@override
|
||||
String get backupPasswordWrong => 'Contraseña de respaldo incorrecta';
|
||||
|
||||
@override
|
||||
String get backupEncrypted => 'El respaldo está encriptado';
|
||||
|
||||
@override
|
||||
String get backupNotEncrypted => 'El respaldo no está encriptado';
|
||||
|
||||
@override
|
||||
String get backupPasswordSet => 'Contraseña de respaldo establecida';
|
||||
|
||||
@override
|
||||
String get backupPasswordRemoved => 'Contraseña de respaldo eliminada';
|
||||
|
||||
@override
|
||||
String get battery => 'Batería';
|
||||
|
||||
@@ -472,9 +494,6 @@ class AppLocalizationsEs extends AppLocalizations {
|
||||
String get pveVersionLow =>
|
||||
'Esta función está actualmente en fase de prueba y solo se ha probado en PVE 8+. Úsela con precaución.';
|
||||
|
||||
@override
|
||||
String get pwd => 'Contraseña';
|
||||
|
||||
@override
|
||||
String get read => 'Leer';
|
||||
|
||||
|
||||
@@ -47,12 +47,34 @@ class AppLocalizationsFr extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get backupTip =>
|
||||
'Les données exportées sont simplement chiffrées. \nVeuillez les garder en sécurité.';
|
||||
'Les données exportées peuvent être chiffrées avec un mot de passe. \nVeuillez les garder en sécurité.';
|
||||
|
||||
@override
|
||||
String get backupVersionNotMatch =>
|
||||
'La version de sauvegarde ne correspond pas.';
|
||||
|
||||
@override
|
||||
String get backupPassword => 'Mot de passe de sauvegarde';
|
||||
|
||||
@override
|
||||
String get backupPasswordTip =>
|
||||
'Définissez un mot de passe pour chiffrer les fichiers de sauvegarde. Laissez vide pour désactiver le chiffrement.';
|
||||
|
||||
@override
|
||||
String get backupPasswordWrong => 'Mot de passe de sauvegarde incorrect';
|
||||
|
||||
@override
|
||||
String get backupEncrypted => 'La sauvegarde est chiffrée';
|
||||
|
||||
@override
|
||||
String get backupNotEncrypted => 'La sauvegarde n\'est pas chiffrée';
|
||||
|
||||
@override
|
||||
String get backupPasswordSet => 'Mot de passe de sauvegarde défini';
|
||||
|
||||
@override
|
||||
String get backupPasswordRemoved => 'Mot de passe de sauvegarde supprimé';
|
||||
|
||||
@override
|
||||
String get battery => 'Batterie';
|
||||
|
||||
@@ -473,9 +495,6 @@ class AppLocalizationsFr extends AppLocalizations {
|
||||
String get pveVersionLow =>
|
||||
'Cette fonctionnalité est actuellement en phase de test et n\'a été testée que sur PVE 8+. Veuillez l\'utiliser avec prudence.';
|
||||
|
||||
@override
|
||||
String get pwd => 'Mot de passe';
|
||||
|
||||
@override
|
||||
String get read => 'Lire';
|
||||
|
||||
|
||||
@@ -47,11 +47,33 @@ class AppLocalizationsId extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get backupTip =>
|
||||
'Data yang diekspor hanya dienkripsi.\nTolong jaga keamanannya.';
|
||||
'Data yang diekspor dapat dienkripsi dengan kata sandi. \nHarap jaga keamanannya.';
|
||||
|
||||
@override
|
||||
String get backupVersionNotMatch => 'Versi cadangan tidak cocok.';
|
||||
|
||||
@override
|
||||
String get backupPassword => 'Kata sandi cadangan';
|
||||
|
||||
@override
|
||||
String get backupPasswordTip =>
|
||||
'Setel kata sandi untuk mengenkripsi file cadangan. Biarkan kosong untuk menonaktifkan enkripsi.';
|
||||
|
||||
@override
|
||||
String get backupPasswordWrong => 'Kata sandi cadangan salah';
|
||||
|
||||
@override
|
||||
String get backupEncrypted => 'Cadangan telah dienkripsi';
|
||||
|
||||
@override
|
||||
String get backupNotEncrypted => 'Cadangan tidak dienkripsi';
|
||||
|
||||
@override
|
||||
String get backupPasswordSet => 'Kata sandi cadangan ditetapkan';
|
||||
|
||||
@override
|
||||
String get backupPasswordRemoved => 'Kata sandi cadangan dihapus';
|
||||
|
||||
@override
|
||||
String get battery => 'Baterai';
|
||||
|
||||
@@ -468,9 +490,6 @@ class AppLocalizationsId extends AppLocalizations {
|
||||
String get pveVersionLow =>
|
||||
'Fitur ini saat ini sedang dalam tahap pengujian dan hanya diuji pada PVE 8+. Gunakan dengan hati-hati.';
|
||||
|
||||
@override
|
||||
String get pwd => 'Kata sandi';
|
||||
|
||||
@override
|
||||
String get read => 'Baca';
|
||||
|
||||
|
||||
@@ -43,11 +43,33 @@ class AppLocalizationsJa extends AppLocalizations {
|
||||
String get autoUpdateHomeWidget => 'ホームウィジェットを自動更新';
|
||||
|
||||
@override
|
||||
String get backupTip => 'エクスポートされたデータは簡単に暗号化されています。適切に保管してください。';
|
||||
String get backupTip => 'エクスポートされたデータはパスワードで暗号化できます。 \n適切に保管してください。';
|
||||
|
||||
@override
|
||||
String get backupVersionNotMatch => 'バックアップバージョンが一致しないため、復元できません';
|
||||
|
||||
@override
|
||||
String get backupPassword => 'バックアップパスワード';
|
||||
|
||||
@override
|
||||
String get backupPasswordTip =>
|
||||
'バックアップファイルを暗号化するためのパスワードを設定してください。暗号化を無効にするには空白のままにしてください。';
|
||||
|
||||
@override
|
||||
String get backupPasswordWrong => 'バックアップパスワードが間違っています';
|
||||
|
||||
@override
|
||||
String get backupEncrypted => 'バックアップは暗号化されています';
|
||||
|
||||
@override
|
||||
String get backupNotEncrypted => 'バックアップは暗号化されていません';
|
||||
|
||||
@override
|
||||
String get backupPasswordSet => 'バックアップパスワードが設定されました';
|
||||
|
||||
@override
|
||||
String get backupPasswordRemoved => 'バックアップパスワードが削除されました';
|
||||
|
||||
@override
|
||||
String get battery => 'バッテリー';
|
||||
|
||||
@@ -453,9 +475,6 @@ class AppLocalizationsJa extends AppLocalizations {
|
||||
@override
|
||||
String get pveVersionLow => 'この機能は現在テスト段階にあり、PVE 8+でのみテストされています。ご利用の際は慎重に。';
|
||||
|
||||
@override
|
||||
String get pwd => 'パスワード';
|
||||
|
||||
@override
|
||||
String get read => '読み取り';
|
||||
|
||||
|
||||
@@ -47,11 +47,33 @@ class AppLocalizationsNl extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get backupTip =>
|
||||
'De geëxporteerde gegevens zijn simpelweg versleuteld. \nBewaar deze aub veilig.';
|
||||
'De geëxporteerde gegevens kunnen worden versleuteld met een wachtwoord. \nBewaar deze aub veilig.';
|
||||
|
||||
@override
|
||||
String get backupVersionNotMatch => 'Back-upversie komt niet overeen.';
|
||||
|
||||
@override
|
||||
String get backupPassword => 'Back-up wachtwoord';
|
||||
|
||||
@override
|
||||
String get backupPasswordTip =>
|
||||
'Stel een wachtwoord in om back-upbestanden te versleutelen. Laat leeg om versleuteling uit te schakelen.';
|
||||
|
||||
@override
|
||||
String get backupPasswordWrong => 'Onjuist back-up wachtwoord';
|
||||
|
||||
@override
|
||||
String get backupEncrypted => 'Back-up is versleuteld';
|
||||
|
||||
@override
|
||||
String get backupNotEncrypted => 'Back-up is niet versleuteld';
|
||||
|
||||
@override
|
||||
String get backupPasswordSet => 'Back-up wachtwoord ingesteld';
|
||||
|
||||
@override
|
||||
String get backupPasswordRemoved => 'Back-up wachtwoord verwijderd';
|
||||
|
||||
@override
|
||||
String get battery => 'Batterij';
|
||||
|
||||
@@ -469,9 +491,6 @@ class AppLocalizationsNl extends AppLocalizations {
|
||||
String get pveVersionLow =>
|
||||
'Deze functie bevindt zich momenteel in de testfase en is alleen getest op PVE 8+. Gebruik het met voorzichtigheid.';
|
||||
|
||||
@override
|
||||
String get pwd => 'Wachtwoord';
|
||||
|
||||
@override
|
||||
String get read => 'Lezen';
|
||||
|
||||
|
||||
@@ -47,12 +47,34 @@ class AppLocalizationsPt extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get backupTip =>
|
||||
'Os dados exportados são criptografados de forma simples, por favor, guarde-os com segurança.';
|
||||
'Os dados exportados podem ser criptografados com senha. \nPor favor, guarde-os com segurança.';
|
||||
|
||||
@override
|
||||
String get backupVersionNotMatch =>
|
||||
'Versão de backup não compatível, não é possível restaurar';
|
||||
|
||||
@override
|
||||
String get backupPassword => 'Senha de backup';
|
||||
|
||||
@override
|
||||
String get backupPasswordTip =>
|
||||
'Defina uma senha para criptografar arquivos de backup. Deixe vazio para desabilitar a criptografia.';
|
||||
|
||||
@override
|
||||
String get backupPasswordWrong => 'Senha de backup incorreta';
|
||||
|
||||
@override
|
||||
String get backupEncrypted => 'Backup está criptografado';
|
||||
|
||||
@override
|
||||
String get backupNotEncrypted => 'Backup não está criptografado';
|
||||
|
||||
@override
|
||||
String get backupPasswordSet => 'Senha de backup definida';
|
||||
|
||||
@override
|
||||
String get backupPasswordRemoved => 'Senha de backup removida';
|
||||
|
||||
@override
|
||||
String get battery => 'Bateria';
|
||||
|
||||
@@ -469,9 +491,6 @@ class AppLocalizationsPt extends AppLocalizations {
|
||||
String get pveVersionLow =>
|
||||
'Esta funcionalidade está atualmente em fase de teste e foi testada apenas no PVE 8+. Por favor, use com cautela.';
|
||||
|
||||
@override
|
||||
String get pwd => 'Senha';
|
||||
|
||||
@override
|
||||
String get read => 'Leitura';
|
||||
|
||||
|
||||
@@ -47,12 +47,34 @@ class AppLocalizationsRu extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get backupTip =>
|
||||
'Экспортированные данные зашифрованы простым способом \nПожалуйста, храните их в безопасности.';
|
||||
'Экспортированные данные могут быть зашифрованы паролем. \nПожалуйста, храните их в безопасности.';
|
||||
|
||||
@override
|
||||
String get backupVersionNotMatch =>
|
||||
'Версия резервной копии не совпадает, восстановление невозможно';
|
||||
|
||||
@override
|
||||
String get backupPassword => 'Пароль резервной копии';
|
||||
|
||||
@override
|
||||
String get backupPasswordTip =>
|
||||
'Установите пароль для шифрования файлов резервных копий. Оставьте пустым, чтобы отключить шифрование.';
|
||||
|
||||
@override
|
||||
String get backupPasswordWrong => 'Неверный пароль резервной копии';
|
||||
|
||||
@override
|
||||
String get backupEncrypted => 'Резервная копия зашифрована';
|
||||
|
||||
@override
|
||||
String get backupNotEncrypted => 'Резервная копия не зашифрована';
|
||||
|
||||
@override
|
||||
String get backupPasswordSet => 'Пароль резервной копии установлен';
|
||||
|
||||
@override
|
||||
String get backupPasswordRemoved => 'Пароль резервной копии удален';
|
||||
|
||||
@override
|
||||
String get battery => 'Батарея';
|
||||
|
||||
@@ -470,9 +492,6 @@ class AppLocalizationsRu extends AppLocalizations {
|
||||
String get pveVersionLow =>
|
||||
'Эта функция в настоящее время находится на стадии тестирования и была протестирована только на PVE 8+. Используйте ее с осторожностью.';
|
||||
|
||||
@override
|
||||
String get pwd => 'Пароль';
|
||||
|
||||
@override
|
||||
String get read => 'Чтение';
|
||||
|
||||
|
||||
@@ -46,11 +46,33 @@ class AppLocalizationsTr extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get backupTip =>
|
||||
'Dışa aktarılan veriler zayıf bir şekilde şifrelenmiştir. \nLütfen güvenli bir şekilde saklayın.';
|
||||
'Dışa aktarılan veriler parola ile şifrelenebilir. \nLütfen güvenli bir şekilde saklayın.';
|
||||
|
||||
@override
|
||||
String get backupVersionNotMatch => 'Yedekleme sürümü eşleşmiyor.';
|
||||
|
||||
@override
|
||||
String get backupPassword => 'Yedekleme parolası';
|
||||
|
||||
@override
|
||||
String get backupPasswordTip =>
|
||||
'Yedekleme dosyalarını şifrelemek için bir parola belirleyin. Şifrelemeyi devre dışı bırakmak için boş bırakın.';
|
||||
|
||||
@override
|
||||
String get backupPasswordWrong => 'Yanlış yedekleme parolası';
|
||||
|
||||
@override
|
||||
String get backupEncrypted => 'Yedekleme şifrelenmiş';
|
||||
|
||||
@override
|
||||
String get backupNotEncrypted => 'Yedekleme şifreli değil';
|
||||
|
||||
@override
|
||||
String get backupPasswordSet => 'Yedekleme parolası ayarlandı';
|
||||
|
||||
@override
|
||||
String get backupPasswordRemoved => 'Yedekleme parolası kaldırıldı';
|
||||
|
||||
@override
|
||||
String get battery => 'Pil';
|
||||
|
||||
@@ -467,9 +489,6 @@ class AppLocalizationsTr extends AppLocalizations {
|
||||
String get pveVersionLow =>
|
||||
'Bu özellik şu anda test aşamasında ve yalnızca PVE 8+ üzerinde test edildi. Lütfen dikkatli kullanın.';
|
||||
|
||||
@override
|
||||
String get pwd => 'Şifre';
|
||||
|
||||
@override
|
||||
String get read => 'Oku';
|
||||
|
||||
|
||||
@@ -47,12 +47,34 @@ class AppLocalizationsUk extends AppLocalizations {
|
||||
|
||||
@override
|
||||
String get backupTip =>
|
||||
'Експортовані дані слабо зашифровані. \nБудь ласка, зберігайте їх у безпеці.';
|
||||
'Експортовані дані можуть бути зашифровані паролем. \nБудь ласка, зберігайте їх у безпеці.';
|
||||
|
||||
@override
|
||||
String get backupVersionNotMatch =>
|
||||
'Версія резервного копіювання не збіглася.';
|
||||
|
||||
@override
|
||||
String get backupPassword => 'Пароль резервного копіювання';
|
||||
|
||||
@override
|
||||
String get backupPasswordTip =>
|
||||
'Встановіть пароль для шифрування файлів резервного копіювання. Залиште порожнім для відключення шифрування.';
|
||||
|
||||
@override
|
||||
String get backupPasswordWrong => 'Неправильний пароль резервного копіювання';
|
||||
|
||||
@override
|
||||
String get backupEncrypted => 'Резервна копія зашифрована';
|
||||
|
||||
@override
|
||||
String get backupNotEncrypted => 'Резервна копія не зашифрована';
|
||||
|
||||
@override
|
||||
String get backupPasswordSet => 'Пароль резервного копіювання встановлено';
|
||||
|
||||
@override
|
||||
String get backupPasswordRemoved => 'Пароль резервного копіювання видалено';
|
||||
|
||||
@override
|
||||
String get battery => 'Акумулятор';
|
||||
|
||||
@@ -472,9 +494,6 @@ class AppLocalizationsUk extends AppLocalizations {
|
||||
String get pveVersionLow =>
|
||||
'Ця функція наразі перебуває на стадії тестування та випробувалася лише на PVE 8+. Будь ласка, використовуйте її з обережністю.';
|
||||
|
||||
@override
|
||||
String get pwd => 'Пароль';
|
||||
|
||||
@override
|
||||
String get read => 'Читати';
|
||||
|
||||
|
||||
@@ -42,11 +42,32 @@ class AppLocalizationsZh extends AppLocalizations {
|
||||
String get autoUpdateHomeWidget => '自动更新桌面小部件';
|
||||
|
||||
@override
|
||||
String get backupTip => '导出的数据仅进行了简单加密,请妥善保管。';
|
||||
String get backupTip => '导出的数据可以使用密码加密,请妥善保管。';
|
||||
|
||||
@override
|
||||
String get backupVersionNotMatch => '备份版本不匹配,无法恢复';
|
||||
|
||||
@override
|
||||
String get backupPassword => '备份密码';
|
||||
|
||||
@override
|
||||
String get backupPasswordTip => '设置密码以加密备份文件。留空则禁用加密。';
|
||||
|
||||
@override
|
||||
String get backupPasswordWrong => '备份密码错误';
|
||||
|
||||
@override
|
||||
String get backupEncrypted => '备份已加密';
|
||||
|
||||
@override
|
||||
String get backupNotEncrypted => '备份未加密';
|
||||
|
||||
@override
|
||||
String get backupPasswordSet => '备份密码已设置';
|
||||
|
||||
@override
|
||||
String get backupPasswordRemoved => '备份密码已移除';
|
||||
|
||||
@override
|
||||
String get battery => '电池';
|
||||
|
||||
@@ -446,9 +467,6 @@ class AppLocalizationsZh extends AppLocalizations {
|
||||
@override
|
||||
String get pveVersionLow => '当前该功能处于测试阶段,仅在 PVE 8+ 上测试过,请谨慎使用';
|
||||
|
||||
@override
|
||||
String get pwd => '密码';
|
||||
|
||||
@override
|
||||
String get read => '读';
|
||||
|
||||
@@ -776,11 +794,32 @@ class AppLocalizationsZhTw extends AppLocalizationsZh {
|
||||
String get autoUpdateHomeWidget => '自動更新桌面小工具';
|
||||
|
||||
@override
|
||||
String get backupTip => '匯出的資料僅進行了簡單加密,請妥善保管。';
|
||||
String get backupTip => '匯出的資料可以使用密碼加密。 \n請妥善保管。';
|
||||
|
||||
@override
|
||||
String get backupVersionNotMatch => '備份版本不相符,無法還原';
|
||||
|
||||
@override
|
||||
String get backupPassword => '備份密碼';
|
||||
|
||||
@override
|
||||
String get backupPasswordTip => '設定密碼來加密備份檔案。留空則停用加密。';
|
||||
|
||||
@override
|
||||
String get backupPasswordWrong => '備份密碼錯誤';
|
||||
|
||||
@override
|
||||
String get backupEncrypted => '備份已加密';
|
||||
|
||||
@override
|
||||
String get backupNotEncrypted => '備份未加密';
|
||||
|
||||
@override
|
||||
String get backupPasswordSet => '備份密碼已設定';
|
||||
|
||||
@override
|
||||
String get backupPasswordRemoved => '備份密碼已移除';
|
||||
|
||||
@override
|
||||
String get battery => '電池';
|
||||
|
||||
@@ -1180,9 +1219,6 @@ class AppLocalizationsZhTw extends AppLocalizationsZh {
|
||||
@override
|
||||
String get pveVersionLow => '此功能目前處於測試階段,僅在 PVE 8+ 上進行過測試。請謹慎使用。';
|
||||
|
||||
@override
|
||||
String get pwd => '密碼';
|
||||
|
||||
@override
|
||||
String get read => '讀取';
|
||||
|
||||
|
||||
@@ -11,8 +11,15 @@
|
||||
"autoConnect": "Automatisch verbinden",
|
||||
"autoRun": "Automatischer Start",
|
||||
"autoUpdateHomeWidget": "Home-Widget automatisch aktualisieren",
|
||||
"backupTip": "Das Backup wird nur einfach verschlüsselt.\nBitte bewahre die Datei sicher auf.",
|
||||
"backupTip": "Die exportierten Daten können mit einem Passwort verschlüsselt werden. \nBitte sicher aufbewahren.",
|
||||
"backupVersionNotMatch": "Die Backup-Version stimmt nicht überein.",
|
||||
"backupPassword": "Backup-Passwort",
|
||||
"backupPasswordTip": "Setzen Sie ein Passwort, um Backup-Dateien zu verschlüsseln. Leer lassen, um Verschlüsselung zu deaktivieren.",
|
||||
"backupPasswordWrong": "Falsches Backup-Passwort",
|
||||
"backupEncrypted": "Backup ist verschlüsselt",
|
||||
"backupNotEncrypted": "Backup ist nicht verschlüsselt",
|
||||
"backupPasswordSet": "Backup-Passwort gesetzt",
|
||||
"backupPasswordRemoved": "Backup-Passwort entfernt",
|
||||
"battery": "Batterie",
|
||||
"bgRun": "Hintergrundaktualisierung",
|
||||
"bgRunTip": "Dieser Schalter bedeutet nur, dass die App versuchen wird, im Hintergrund zu laufen. Ob sie im Hintergrund laufen kann, hängt davon ab, ob die Berechtigungen aktiviert sind oder nicht. Bei nativem Android deaktivieren Sie bitte \"Batterieoptimierung\" in dieser App, und bei miui ändern Sie bitte die Energiesparrichtlinie auf \"Unbegrenzt\".",
|
||||
@@ -137,7 +144,6 @@
|
||||
"pveIgnoreCertTip": "Nicht empfohlen, Achten Sie auf Sicherheitsrisiken! Wenn Sie das Standardzertifikat von PVE verwenden, müssen Sie diese Option aktivieren.",
|
||||
"pveLoginFailed": "Anmeldung fehlgeschlagen. Kann nicht mit Benutzername/Passwort aus der Serverkonfiguration angemeldet werden, um sich über Linux PAM anzumelden.",
|
||||
"pveVersionLow": "Diese Funktion befindet sich derzeit in der Testphase und wurde nur auf PVE 8+ getestet. Bitte verwenden Sie sie mit Vorsicht.",
|
||||
"pwd": "Passwort",
|
||||
"read": "Lesen",
|
||||
"reboot": "Neustart",
|
||||
"rememberPwdInMem": "Passwort im Speicher behalten",
|
||||
|
||||
@@ -11,8 +11,15 @@
|
||||
"autoConnect": "Auto connect",
|
||||
"autoRun": "Auto run",
|
||||
"autoUpdateHomeWidget": "Automatic home widget update",
|
||||
"backupTip": "The exported data is weakly encrypted. \nPlease keep it safe.",
|
||||
"backupTip": "The exported data can be encrypted with password. \nPlease keep it safe.",
|
||||
"backupVersionNotMatch": "Backup version is not match.",
|
||||
"backupPassword": "Backup password",
|
||||
"backupPasswordTip": "Set a password to encrypt backup files. Leave empty to disable encryption.",
|
||||
"backupPasswordWrong": "Incorrect backup password",
|
||||
"backupEncrypted": "Backup is encrypted",
|
||||
"backupNotEncrypted": "Backup is not encrypted",
|
||||
"backupPasswordSet": "Backup password set",
|
||||
"backupPasswordRemoved": "Backup password removed",
|
||||
"battery": "Battery",
|
||||
"bgRun": "Run in background",
|
||||
"bgRunTip": "This switch only means the program will try to run in the background. Whether it can run in the background depends on whether the permission is enabled or not. For AOSP-based Android ROMs, please disable \"Battery Optimization\" in this app. For MIUI / HyperOS, please change the power saving policy to \"Unlimited\".",
|
||||
@@ -137,7 +144,6 @@
|
||||
"pveIgnoreCertTip": "Not recommended to enable, beware of security risks! If you are using the default certificate from PVE, you need to enable this option.",
|
||||
"pveLoginFailed": "Login failed. Unable to authenticate with username/password from server configuration for Linux PAM login.",
|
||||
"pveVersionLow": "This feature is currently in the testing phase and has only been tested on PVE 8+. Please use it with caution.",
|
||||
"pwd": "Password",
|
||||
"read": "Read",
|
||||
"reboot": "Reboot",
|
||||
"rememberPwdInMem": "Remember password in memory",
|
||||
|
||||
@@ -11,8 +11,15 @@
|
||||
"autoConnect": "Conexión automática",
|
||||
"autoRun": "Ejecución automática",
|
||||
"autoUpdateHomeWidget": "Actualizar automáticamente el widget del escritorio",
|
||||
"backupTip": "Los datos exportados solo están encriptados de manera básica, por favor guárdalos en un lugar seguro.",
|
||||
"backupTip": "Los datos exportados pueden ser encriptados con contraseña. \nPor favor guárdalos en un lugar seguro.",
|
||||
"backupVersionNotMatch": "La versión de la copia de seguridad no coincide, no se puede restaurar",
|
||||
"backupPassword": "Contraseña de respaldo",
|
||||
"backupPasswordTip": "Establece una contraseña para encriptar archivos de respaldo. Déjalo vacío para desactivar la encriptación.",
|
||||
"backupPasswordWrong": "Contraseña de respaldo incorrecta",
|
||||
"backupEncrypted": "El respaldo está encriptado",
|
||||
"backupNotEncrypted": "El respaldo no está encriptado",
|
||||
"backupPasswordSet": "Contraseña de respaldo establecida",
|
||||
"backupPasswordRemoved": "Contraseña de respaldo eliminada",
|
||||
"battery": "Batería",
|
||||
"bgRun": "Ejecución en segundo plano",
|
||||
"bgRunTip": "Este interruptor solo indica que la aplicación intentará correr en segundo plano, si puede hacerlo o no depende de si tiene el permiso correspondiente. En Android puro, por favor desactiva la “optimización de batería” para esta app, en MIUI por favor cambia la estrategia de ahorro de energía a “Sin restricciones”.",
|
||||
@@ -137,7 +144,6 @@
|
||||
"pveIgnoreCertTip": "No se recomienda activarlo, ¡tenga cuidado con los riesgos de seguridad! Si está utilizando el certificado predeterminado de PVE, debe habilitar esta opción.",
|
||||
"pveLoginFailed": "Fallo al iniciar sesión. No se puede autenticar con el nombre de usuario/contraseña de la configuración del servidor para el inicio de sesión de Linux PAM.",
|
||||
"pveVersionLow": "Esta función está actualmente en fase de prueba y solo se ha probado en PVE 8+. Úsela con precaución.",
|
||||
"pwd": "Contraseña",
|
||||
"read": "Leer",
|
||||
"reboot": "Reiniciar",
|
||||
"rememberPwdInMem": "Recordar contraseña en la memoria",
|
||||
|
||||
@@ -11,8 +11,15 @@
|
||||
"autoConnect": "Connexion automatique",
|
||||
"autoRun": "Exécution automatique",
|
||||
"autoUpdateHomeWidget": "Mise à jour automatique du widget d'accueil",
|
||||
"backupTip": "Les données exportées sont simplement chiffrées. \nVeuillez les garder en sécurité.",
|
||||
"backupTip": "Les données exportées peuvent être chiffrées avec un mot de passe. \nVeuillez les garder en sécurité.",
|
||||
"backupVersionNotMatch": "La version de sauvegarde ne correspond pas.",
|
||||
"backupPassword": "Mot de passe de sauvegarde",
|
||||
"backupPasswordTip": "Définissez un mot de passe pour chiffrer les fichiers de sauvegarde. Laissez vide pour désactiver le chiffrement.",
|
||||
"backupPasswordWrong": "Mot de passe de sauvegarde incorrect",
|
||||
"backupEncrypted": "La sauvegarde est chiffrée",
|
||||
"backupNotEncrypted": "La sauvegarde n'est pas chiffrée",
|
||||
"backupPasswordSet": "Mot de passe de sauvegarde défini",
|
||||
"backupPasswordRemoved": "Mot de passe de sauvegarde supprimé",
|
||||
"battery": "Batterie",
|
||||
"bgRun": "Exécution en arrière-plan",
|
||||
"bgRunTip": "Cette option signifie seulement que le programme essaiera de s'exécuter en arrière-plan, que cela soit possible dépend de l'autorisation activée ou non. Pour Android natif, veuillez désactiver l'« Optimisation de la batterie » dans cette application, et pour MIUI, veuillez changer la politique d'économie d'énergie en « Illimité ».",
|
||||
@@ -137,7 +144,6 @@
|
||||
"pveIgnoreCertTip": "Il n'est pas recommandé de l'activer, attention aux risques de sécurité ! Si vous utilisez le certificat par défaut de PVE, vous devez activer cette option.",
|
||||
"pveLoginFailed": "Échec de la connexion. Impossible d'authentifier avec le nom d'utilisateur / mot de passe de la configuration du serveur pour la connexion Linux PAM.",
|
||||
"pveVersionLow": "Cette fonctionnalité est actuellement en phase de test et n'a été testée que sur PVE 8+. Veuillez l'utiliser avec prudence.",
|
||||
"pwd": "Mot de passe",
|
||||
"read": "Lire",
|
||||
"reboot": "Redémarrer",
|
||||
"rememberPwdInMem": "Mémoriser le mot de passe en mémoire",
|
||||
|
||||
@@ -11,8 +11,15 @@
|
||||
"autoConnect": "Hubungkan otomatis",
|
||||
"autoRun": "Berjalan Otomatis",
|
||||
"autoUpdateHomeWidget": "Widget Rumah Pembaruan Otomatis",
|
||||
"backupTip": "Data yang diekspor hanya dienkripsi.\nTolong jaga keamanannya.",
|
||||
"backupTip": "Data yang diekspor dapat dienkripsi dengan kata sandi. \nHarap jaga keamanannya.",
|
||||
"backupVersionNotMatch": "Versi cadangan tidak cocok.",
|
||||
"backupPassword": "Kata sandi cadangan",
|
||||
"backupPasswordTip": "Setel kata sandi untuk mengenkripsi file cadangan. Biarkan kosong untuk menonaktifkan enkripsi.",
|
||||
"backupPasswordWrong": "Kata sandi cadangan salah",
|
||||
"backupEncrypted": "Cadangan telah dienkripsi",
|
||||
"backupNotEncrypted": "Cadangan tidak dienkripsi",
|
||||
"backupPasswordSet": "Kata sandi cadangan ditetapkan",
|
||||
"backupPasswordRemoved": "Kata sandi cadangan dihapus",
|
||||
"battery": "Baterai",
|
||||
"bgRun": "Jalankan di Backgroud",
|
||||
"bgRunTip": "Sakelar ini hanya berarti aplikasi akan mencoba berjalan di latar belakang, apakah aplikasi dapat berjalan di latar belakang tergantung pada apakah izin diaktifkan atau tidak. Untuk Android asli, nonaktifkan \"Pengoptimalan Baterai\" di aplikasi ini, dan untuk miui, ubah kebijakan penghematan daya ke \"Tidak Terbatas\".",
|
||||
@@ -137,7 +144,6 @@
|
||||
"pveIgnoreCertTip": "Tidak disarankan untuk diaktifkan, waspadai risiko keamanan! Jika Anda menggunakan sertifikat default dari PVE, Anda perlu mengaktifkan opsi ini.",
|
||||
"pveLoginFailed": "Login gagal. Tidak dapat mengautentikasi dengan nama pengguna/kata sandi dari konfigurasi server untuk login Linux PAM.",
|
||||
"pveVersionLow": "Fitur ini saat ini sedang dalam tahap pengujian dan hanya diuji pada PVE 8+. Gunakan dengan hati-hati.",
|
||||
"pwd": "Kata sandi",
|
||||
"read": "Baca",
|
||||
"reboot": "Reboot",
|
||||
"rememberPwdInMem": "Ingat kata sandi di dalam memori",
|
||||
|
||||
@@ -11,8 +11,15 @@
|
||||
"autoConnect": "自動接続",
|
||||
"autoRun": "自動実行",
|
||||
"autoUpdateHomeWidget": "ホームウィジェットを自動更新",
|
||||
"backupTip": "エクスポートされたデータは簡単に暗号化されています。適切に保管してください。",
|
||||
"backupTip": "エクスポートされたデータはパスワードで暗号化できます。 \n適切に保管してください。",
|
||||
"backupVersionNotMatch": "バックアップバージョンが一致しないため、復元できません",
|
||||
"backupPassword": "バックアップパスワード",
|
||||
"backupPasswordTip": "バックアップファイルを暗号化するためのパスワードを設定してください。暗号化を無効にするには空白のままにしてください。",
|
||||
"backupPasswordWrong": "バックアップパスワードが間違っています",
|
||||
"backupEncrypted": "バックアップは暗号化されています",
|
||||
"backupNotEncrypted": "バックアップは暗号化されていません",
|
||||
"backupPasswordSet": "バックアップパスワードが設定されました",
|
||||
"backupPasswordRemoved": "バックアップパスワードが削除されました",
|
||||
"battery": "バッテリー",
|
||||
"bgRun": "バックグラウンド実行",
|
||||
"bgRunTip": "このスイッチはプログラムがバックグラウンドで実行を試みることを意味しますが、実際にバックグラウンドで実行できるかどうかは、権限が有効になっているかに依存します。AOSPベースのAndroid ROMでは、このアプリの「バッテリー最適化」をオフにしてください。MIUIでは、省エネモードを「無制限」に変更してください。",
|
||||
@@ -137,7 +144,6 @@
|
||||
"pveIgnoreCertTip": "オプションを有効にすることは推奨されません、セキュリティリスクに注意してください!PVEのデフォルト証明書を使用している場合は、このオプションを有効にする必要があります。",
|
||||
"pveLoginFailed": "ログインに失敗しました。Linux PAMログインのためにサーバー構成からのユーザー名/パスワードで認証できません。",
|
||||
"pveVersionLow": "この機能は現在テスト段階にあり、PVE 8+でのみテストされています。ご利用の際は慎重に。",
|
||||
"pwd": "パスワード",
|
||||
"read": "読み取り",
|
||||
"reboot": "再起動",
|
||||
"rememberPwdInMem": "メモリにパスワードを記憶する",
|
||||
|
||||
@@ -11,8 +11,15 @@
|
||||
"autoConnect": "Automatisch verbinden",
|
||||
"autoRun": "Automatisch uitvoeren",
|
||||
"autoUpdateHomeWidget": "Automatische update van home-widget",
|
||||
"backupTip": "De geëxporteerde gegevens zijn simpelweg versleuteld. \nBewaar deze aub veilig.",
|
||||
"backupTip": "De geëxporteerde gegevens kunnen worden versleuteld met een wachtwoord. \nBewaar deze aub veilig.",
|
||||
"backupVersionNotMatch": "Back-upversie komt niet overeen.",
|
||||
"backupPassword": "Back-up wachtwoord",
|
||||
"backupPasswordTip": "Stel een wachtwoord in om back-upbestanden te versleutelen. Laat leeg om versleuteling uit te schakelen.",
|
||||
"backupPasswordWrong": "Onjuist back-up wachtwoord",
|
||||
"backupEncrypted": "Back-up is versleuteld",
|
||||
"backupNotEncrypted": "Back-up is niet versleuteld",
|
||||
"backupPasswordSet": "Back-up wachtwoord ingesteld",
|
||||
"backupPasswordRemoved": "Back-up wachtwoord verwijderd",
|
||||
"battery": "Batterij",
|
||||
"bgRun": "Uitvoeren op de achtergrond",
|
||||
"bgRunTip": "Deze schakelaar betekent alleen dat het programma zal proberen op de achtergrond uit te voeren, of het in de achtergrond kan worden uitgevoerd, hangt af van of de toestemming is ingeschakeld of niet. Voor native Android, schakel \"Batterijoptimalisatie\" uit in deze app, en voor miui, wijzig de energiebesparingsbeleid naar \"Onbeperkt\".",
|
||||
@@ -137,7 +144,6 @@
|
||||
"pveIgnoreCertTip": "Niet aanbevolen om in te schakelen, let op beveiligingsrisico's! Als u de standaardcertificaat van PVE gebruikt, moet u deze optie inschakelen.",
|
||||
"pveLoginFailed": "Aanmelden mislukt. Kan niet authenticeren met gebruikersnaam/wachtwoord van serverconfiguratie voor Linux PAM-login.",
|
||||
"pveVersionLow": "Deze functie bevindt zich momenteel in de testfase en is alleen getest op PVE 8+. Gebruik het met voorzichtigheid.",
|
||||
"pwd": "Wachtwoord",
|
||||
"read": "Lezen",
|
||||
"reboot": "Herstart",
|
||||
"rememberPwdInMem": "Wachtwoord onthouden in geheugen",
|
||||
|
||||
@@ -11,8 +11,15 @@
|
||||
"autoConnect": "Conexão automática",
|
||||
"autoRun": "Execução automática",
|
||||
"autoUpdateHomeWidget": "Atualização automática do widget da tela inicial",
|
||||
"backupTip": "Os dados exportados são criptografados de forma simples, por favor, guarde-os com segurança.",
|
||||
"backupTip": "Os dados exportados podem ser criptografados com senha. \nPor favor, guarde-os com segurança.",
|
||||
"backupVersionNotMatch": "Versão de backup não compatível, não é possível restaurar",
|
||||
"backupPassword": "Senha de backup",
|
||||
"backupPasswordTip": "Defina uma senha para criptografar arquivos de backup. Deixe vazio para desabilitar a criptografia.",
|
||||
"backupPasswordWrong": "Senha de backup incorreta",
|
||||
"backupEncrypted": "Backup está criptografado",
|
||||
"backupNotEncrypted": "Backup não está criptografado",
|
||||
"backupPasswordSet": "Senha de backup definida",
|
||||
"backupPasswordRemoved": "Senha de backup removida",
|
||||
"battery": "Bateria",
|
||||
"bgRun": "Execução em segundo plano",
|
||||
"bgRunTip": "Este interruptor indica que o programa tentará rodar em segundo plano, mas a capacidade de fazer isso depende das permissões concedidas. No Android nativo, desative a 'Otimização de bateria' para este app, no MIUI, altere a estratégia de economia de energia para 'Sem restrições'.",
|
||||
@@ -137,7 +144,6 @@
|
||||
"pveIgnoreCertTip": "Não recomendado para ativar, cuidado com os riscos de segurança! Se estiver usando o certificado padrão do PVE, você precisa habilitar esta opção.",
|
||||
"pveLoginFailed": "Falha no login. Não é possível autenticar com o nome de usuário/senha da configuração do servidor para login no Linux PAM.",
|
||||
"pveVersionLow": "Esta funcionalidade está atualmente em fase de teste e foi testada apenas no PVE 8+. Por favor, use com cautela.",
|
||||
"pwd": "Senha",
|
||||
"read": "Leitura",
|
||||
"reboot": "Reiniciar",
|
||||
"rememberPwdInMem": "Lembrar senha na memória",
|
||||
|
||||
@@ -11,8 +11,15 @@
|
||||
"autoConnect": "Автоматическое подключение",
|
||||
"autoRun": "Автозапуск",
|
||||
"autoUpdateHomeWidget": "Автоматическое обновление виджета на главном экране",
|
||||
"backupTip": "Экспортированные данные зашифрованы простым способом \nПожалуйста, храните их в безопасности.",
|
||||
"backupTip": "Экспортированные данные могут быть зашифрованы паролем. \nПожалуйста, храните их в безопасности.",
|
||||
"backupVersionNotMatch": "Версия резервной копии не совпадает, восстановление невозможно",
|
||||
"backupPassword": "Пароль резервной копии",
|
||||
"backupPasswordTip": "Установите пароль для шифрования файлов резервных копий. Оставьте пустым, чтобы отключить шифрование.",
|
||||
"backupPasswordWrong": "Неверный пароль резервной копии",
|
||||
"backupEncrypted": "Резервная копия зашифрована",
|
||||
"backupNotEncrypted": "Резервная копия не зашифрована",
|
||||
"backupPasswordSet": "Пароль резервной копии установлен",
|
||||
"backupPasswordRemoved": "Пароль резервной копии удален",
|
||||
"battery": "Батарея",
|
||||
"bgRun": "Работа в фоновом режиме",
|
||||
"bgRunTip": "Этот переключатель означает, что программа будет пытаться работать в фоновом режиме, но фактическое выполнение зависит от того, включено ли разрешение. Для нативного Android отключите «Оптимизацию батареи» для этого приложения, для MIUI измените контроль активности на «Нет ограничений».",
|
||||
@@ -137,7 +144,6 @@
|
||||
"pveIgnoreCertTip": "Не рекомендуется включать, обратите внимание на риски безопасности! Если вы используете стандартный сертификат от PVE, вам нужно включить эту опцию.",
|
||||
"pveLoginFailed": "Ошибка входа. Невозможно аутентифицироваться с помощью имени пользователя/пароля из конфигурации сервера для входа в Linux PAM.",
|
||||
"pveVersionLow": "Эта функция в настоящее время находится на стадии тестирования и была протестирована только на PVE 8+. Используйте ее с осторожностью.",
|
||||
"pwd": "Пароль",
|
||||
"read": "Чтение",
|
||||
"reboot": "Перезагрузка",
|
||||
"rememberPwdInMem": "Запомнить пароль в памяти",
|
||||
|
||||
@@ -11,8 +11,15 @@
|
||||
"autoConnect": "Otomatik bağlan",
|
||||
"autoRun": "Otomatik çalıştır",
|
||||
"autoUpdateHomeWidget": "Ana ekran bileşenini otomatik güncelle",
|
||||
"backupTip": "Dışa aktarılan veriler zayıf bir şekilde şifrelenmiştir. \nLütfen güvenli bir şekilde saklayın.",
|
||||
"backupTip": "Dışa aktarılan veriler parola ile şifrelenebilir. \nLütfen güvenli bir şekilde saklayın.",
|
||||
"backupVersionNotMatch": "Yedekleme sürümü eşleşmiyor.",
|
||||
"backupPassword": "Yedekleme parolası",
|
||||
"backupPasswordTip": "Yedekleme dosyalarını şifrelemek için bir parola belirleyin. Şifrelemeyi devre dışı bırakmak için boş bırakın.",
|
||||
"backupPasswordWrong": "Yanlış yedekleme parolası",
|
||||
"backupEncrypted": "Yedekleme şifrelenmiş",
|
||||
"backupNotEncrypted": "Yedekleme şifreli değil",
|
||||
"backupPasswordSet": "Yedekleme parolası ayarlandı",
|
||||
"backupPasswordRemoved": "Yedekleme parolası kaldırıldı",
|
||||
"battery": "Pil",
|
||||
"bgRun": "Arka planda çalıştır",
|
||||
"bgRunTip": "Bu anahtar yalnızca programın arka planda çalışmayı deneyeceği anlamına gelir. Arka planda çalışıp çalışamayacağı, iznin etkinleştirilip etkinleştirilmediğine bağlıdır. AOSP tabanlı Android ROM'lar için lütfen bu uygulamada \"Pil Optimizasyonu\"nu devre dışı bırakın. MIUI / HyperOS için lütfen güç tasarrufu politikasını \"Sınırsız\" olarak değiştirin.",
|
||||
@@ -137,7 +144,6 @@
|
||||
"pveIgnoreCertTip": "Etkinleştirilmesi önerilmez, güvenlik risklerine dikkat edin! PVE'den varsayılan sertifikayı kullanıyorsanız, bu seçeneği etkinleştirmeniz gerekir.",
|
||||
"pveLoginFailed": "Giriş başarısız. Linux PAM girişi için sunucu yapılandırmasındaki kullanıcı adı/şifre ile kimlik doğrulama yapılamadı.",
|
||||
"pveVersionLow": "Bu özellik şu anda test aşamasında ve yalnızca PVE 8+ üzerinde test edildi. Lütfen dikkatli kullanın.",
|
||||
"pwd": "Şifre",
|
||||
"read": "Oku",
|
||||
"reboot": "Yeniden başlat",
|
||||
"rememberPwdInMem": "Şifreyi bellekte hatırla",
|
||||
|
||||
@@ -11,8 +11,15 @@
|
||||
"autoConnect": "Авто підключення",
|
||||
"autoRun": "Авто запуск",
|
||||
"autoUpdateHomeWidget": "Автоматичне оновлення віджетів на головному екрані",
|
||||
"backupTip": "Експортовані дані слабо зашифровані. \nБудь ласка, зберігайте їх у безпеці.",
|
||||
"backupTip": "Експортовані дані можуть бути зашифровані паролем. \nБудь ласка, зберігайте їх у безпеці.",
|
||||
"backupVersionNotMatch": "Версія резервного копіювання не збіглася.",
|
||||
"backupPassword": "Пароль резервного копіювання",
|
||||
"backupPasswordTip": "Встановіть пароль для шифрування файлів резервного копіювання. Залиште порожнім для відключення шифрування.",
|
||||
"backupPasswordWrong": "Неправильний пароль резервного копіювання",
|
||||
"backupEncrypted": "Резервна копія зашифрована",
|
||||
"backupNotEncrypted": "Резервна копія не зашифрована",
|
||||
"backupPasswordSet": "Пароль резервного копіювання встановлено",
|
||||
"backupPasswordRemoved": "Пароль резервного копіювання видалено",
|
||||
"battery": "Акумулятор",
|
||||
"bgRun": "Запуск у фоновому режимі",
|
||||
"bgRunTip": "Цей перемикач лише вказує на те, що програма намагатиметься працювати у фоновому режимі. Чи може вона працювати у фоновому режимі, залежить від прав доступу. Для AOSP-орієнтованих Android ROM, будь ласка, вимкніть \"Оптимізацію акумулятора\" в цьому додатку. Для MIUI / HyperOS, будь ласка, змініть політику економії енергії на \"Нескінченна\".",
|
||||
@@ -137,7 +144,6 @@
|
||||
"pveIgnoreCertTip": "Не рекомендується включати, будьте обережні з ризиками безпеки! Якщо ви використовуєте стандартний сертифікат від PVE, вам потрібно увімкнути цю опцію.",
|
||||
"pveLoginFailed": "Не вдалося увійти. Неможливо пройти аутентифікацію за допомогою імені користувача/пароля з конфігурації сервера для входу Linux PAM.",
|
||||
"pveVersionLow": "Ця функція наразі перебуває на стадії тестування та випробувалася лише на PVE 8+. Будь ласка, використовуйте її з обережністю.",
|
||||
"pwd": "Пароль",
|
||||
"read": "Читати",
|
||||
"reboot": "Перезавантажити",
|
||||
"rememberPwdInMem": "Запам'ятати пароль у пам'яті",
|
||||
|
||||
@@ -11,8 +11,15 @@
|
||||
"autoConnect": "自动连接",
|
||||
"autoRun": "自动运行",
|
||||
"autoUpdateHomeWidget": "自动更新桌面小部件",
|
||||
"backupTip": "导出的数据仅进行了简单加密,请妥善保管。",
|
||||
"backupTip": "导出的数据可以使用密码加密,请妥善保管。",
|
||||
"backupVersionNotMatch": "备份版本不匹配,无法恢复",
|
||||
"backupPassword": "备份密码",
|
||||
"backupPasswordTip": "设置密码以加密备份文件。留空则禁用加密。",
|
||||
"backupPasswordWrong": "备份密码错误",
|
||||
"backupEncrypted": "备份已加密",
|
||||
"backupNotEncrypted": "备份未加密",
|
||||
"backupPasswordSet": "备份密码已设置",
|
||||
"backupPasswordRemoved": "备份密码已移除",
|
||||
"battery": "电池",
|
||||
"bgRun": "后台运行",
|
||||
"bgRunTip": "此开关只代表程序会尝试在后台运行,具体能否后台运行取决于是否开启了权限。原生 Android 请关闭本 App 的“电池优化”,MIUI / HyperOS 请修改省电策略为“无限制”。",
|
||||
@@ -137,7 +144,6 @@
|
||||
"pveIgnoreCertTip": "不推荐开启,注意安全隐患!如果你使用的 PVE 默认证书,需要开启该选项",
|
||||
"pveLoginFailed": "登录失败。无法使用服务器配置内的用户/密码,以 Linux PAM 方式登录。",
|
||||
"pveVersionLow": "当前该功能处于测试阶段,仅在 PVE 8+ 上测试过,请谨慎使用",
|
||||
"pwd": "密码",
|
||||
"read": "读",
|
||||
"reboot": "重启",
|
||||
"rememberPwdInMem": "在内存中记住密码",
|
||||
|
||||
@@ -11,8 +11,15 @@
|
||||
"autoConnect": "自動連線",
|
||||
"autoRun": "自動執行",
|
||||
"autoUpdateHomeWidget": "自動更新桌面小工具",
|
||||
"backupTip": "匯出的資料僅進行了簡單加密,請妥善保管。",
|
||||
"backupTip": "匯出的資料可以使用密碼加密。 \n請妥善保管。",
|
||||
"backupVersionNotMatch": "備份版本不相符,無法還原",
|
||||
"backupPassword": "備份密碼",
|
||||
"backupPasswordTip": "設定密碼來加密備份檔案。留空則停用加密。",
|
||||
"backupPasswordWrong": "備份密碼錯誤",
|
||||
"backupEncrypted": "備份已加密",
|
||||
"backupNotEncrypted": "備份未加密",
|
||||
"backupPasswordSet": "備份密碼已設定",
|
||||
"backupPasswordRemoved": "備份密碼已移除",
|
||||
"battery": "電池",
|
||||
"bgRun": "背景執行",
|
||||
"bgRunTip": "此開關只代表程式會嘗試在背景執行,具體能否在後臺執行取決於是否開啟了權限。 原生 Android 請關閉本 App 的“電池最佳化”,MIUI / HyperOS 請修改省電策略為“無限制”。",
|
||||
@@ -137,7 +144,6 @@
|
||||
"pveIgnoreCertTip": "不建議啟用,請注意安全風險!如果您使用的是 PVE 的預設憑證,則需要啟用此選項。",
|
||||
"pveLoginFailed": "登錄失敗。無法使用伺服器配置中的使用者名稱/密碼以 Linux PAM 方式登錄。",
|
||||
"pveVersionLow": "此功能目前處於測試階段,僅在 PVE 8+ 上進行過測試。請謹慎使用。",
|
||||
"pwd": "密碼",
|
||||
"read": "讀取",
|
||||
"reboot": "重開",
|
||||
"rememberPwdInMem": "在記憶體中記住密碼",
|
||||
|
||||
@@ -8,7 +8,8 @@ import 'package:icons_plus/icons_plus.dart';
|
||||
import 'package:server_box/core/extension/context/locale.dart';
|
||||
import 'package:server_box/core/sync.dart';
|
||||
import 'package:server_box/data/model/app/bak/backup2.dart';
|
||||
import 'package:server_box/data/model/app/bak/utils.dart';
|
||||
import 'package:server_box/data/model/app/bak/backup_service.dart';
|
||||
import 'package:server_box/data/model/app/bak/backup_source.dart';
|
||||
import 'package:server_box/data/model/server/server_private_info.dart';
|
||||
import 'package:server_box/data/model/server/snippet.dart';
|
||||
import 'package:server_box/data/provider/snippet.dart';
|
||||
@@ -22,10 +23,7 @@ class BackupPage extends StatefulWidget {
|
||||
@override
|
||||
State<BackupPage> createState() => _BackupPageState();
|
||||
|
||||
static const route = AppRouteNoArg(
|
||||
page: BackupPage.new,
|
||||
path: '/backup',
|
||||
);
|
||||
static const route = AppRouteNoArg(page: BackupPage.new, path: '/backup');
|
||||
}
|
||||
|
||||
final class _BackupPageState extends State<BackupPage> with AutomaticKeepAliveClientMixin {
|
||||
@@ -40,33 +38,27 @@ final class _BackupPageState extends State<BackupPage> with AutomaticKeepAliveCl
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
super.build(context);
|
||||
return Scaffold(
|
||||
body: _buildBody(context),
|
||||
);
|
||||
return Scaffold(body: _buildBody);
|
||||
}
|
||||
|
||||
Widget _buildBody(BuildContext context) {
|
||||
Widget get _buildBody {
|
||||
return MultiList(
|
||||
widthDivider: 2,
|
||||
children: [
|
||||
[
|
||||
CenterGreyTitle(libL10n.sync),
|
||||
_buildTip(),
|
||||
if (isMacOS || isIOS) _buildIcloud(context),
|
||||
_buildWebdav(context),
|
||||
_buildFile(context),
|
||||
_buildClipboard(context),
|
||||
],
|
||||
[
|
||||
CenterGreyTitle(libL10n.import),
|
||||
_buildBulkImportServers(context),
|
||||
_buildImportSnippet(context),
|
||||
_buildTip,
|
||||
if (isMacOS || isIOS) _buildIcloud,
|
||||
_buildWebdav,
|
||||
_buildFile,
|
||||
_buildClipboard,
|
||||
],
|
||||
[CenterGreyTitle(libL10n.import), _buildBulkImportServers, _buildImportSnippet],
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildTip() {
|
||||
Widget get _buildTip {
|
||||
return CardX(
|
||||
child: ListTile(
|
||||
leading: const Icon(Icons.warning),
|
||||
@@ -76,7 +68,7 @@ final class _BackupPageState extends State<BackupPage> with AutomaticKeepAliveCl
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildFile(BuildContext context) {
|
||||
Widget get _buildFile {
|
||||
return CardX(
|
||||
child: ExpandTile(
|
||||
leading: const Icon(Icons.file_open),
|
||||
@@ -86,22 +78,19 @@ final class _BackupPageState extends State<BackupPage> with AutomaticKeepAliveCl
|
||||
ListTile(
|
||||
title: Text(libL10n.backup),
|
||||
trailing: const Icon(Icons.save),
|
||||
onTap: () async {
|
||||
final path = await BackupV2.backup();
|
||||
await Pfs.sharePaths(paths: [path]);
|
||||
},
|
||||
onTap: () => BackupService.backup(context, FileBackupSource())
|
||||
),
|
||||
ListTile(
|
||||
trailing: const Icon(Icons.restore),
|
||||
title: Text(libL10n.restore),
|
||||
onTap: () async => _onTapFileRestore(context),
|
||||
onTap: () => BackupService.restore(context, FileBackupSource()),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildIcloud(BuildContext context) {
|
||||
Widget get _buildIcloud {
|
||||
return CardX(
|
||||
child: ListTile(
|
||||
leading: const Icon(Icons.cloud),
|
||||
@@ -123,7 +112,7 @@ final class _BackupPageState extends State<BackupPage> with AutomaticKeepAliveCl
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildWebdav(BuildContext context) {
|
||||
Widget get _buildWebdav {
|
||||
return CardX(
|
||||
child: ExpandTile(
|
||||
leading: const Icon(Icons.storage),
|
||||
@@ -171,33 +160,25 @@ final class _BackupPageState extends State<BackupPage> with AutomaticKeepAliveCl
|
||||
),
|
||||
ListTile(
|
||||
title: Text(l10n.manual),
|
||||
trailing: webdavLoading.listenVal(
|
||||
(loading) {
|
||||
if (loading) return SizedLoading.small;
|
||||
trailing: webdavLoading.listenVal((loading) {
|
||||
if (loading) return SizedLoading.small;
|
||||
|
||||
return Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: () async => _onTapWebdavDl(context),
|
||||
child: Text(libL10n.restore),
|
||||
),
|
||||
UIs.width7,
|
||||
TextButton(
|
||||
onPressed: () async => _onTapWebdavUp(context),
|
||||
child: Text(libL10n.backup),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
return Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
TextButton(onPressed: () async => _onTapWebdavDl(context), child: Text(libL10n.restore)),
|
||||
UIs.width7,
|
||||
TextButton(onPressed: () async => _onTapWebdavUp(context), child: Text(libL10n.backup)),
|
||||
],
|
||||
);
|
||||
}),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildClipboard(BuildContext context) {
|
||||
Widget get _buildClipboard {
|
||||
return CardX(
|
||||
child: ExpandTile(
|
||||
leading: const Icon(Icons.content_paste),
|
||||
@@ -206,23 +187,19 @@ final class _BackupPageState extends State<BackupPage> with AutomaticKeepAliveCl
|
||||
ListTile(
|
||||
title: Text(libL10n.backup),
|
||||
trailing: const Icon(Icons.save),
|
||||
onTap: () async {
|
||||
final path = await BackupV2.backup();
|
||||
Pfs.copy(await File(path).readAsString());
|
||||
context.showSnackBar(libL10n.success);
|
||||
},
|
||||
onTap: () => BackupService.backup(context, ClipboardBackupSource()),
|
||||
),
|
||||
ListTile(
|
||||
trailing: const Icon(Icons.restore),
|
||||
title: Text(libL10n.restore),
|
||||
onTap: () async => _onTapClipboardRestore(context),
|
||||
onTap: () => BackupService.restore(context, ClipboardBackupSource()),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildBulkImportServers(BuildContext context) {
|
||||
Widget get _buildBulkImportServers {
|
||||
return CardX(
|
||||
child: ListTile(
|
||||
title: Text(l10n.server),
|
||||
@@ -233,16 +210,13 @@ final class _BackupPageState extends State<BackupPage> with AutomaticKeepAliveCl
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildImportSnippet(BuildContext context) {
|
||||
Widget get _buildImportSnippet {
|
||||
return ListTile(
|
||||
title: Text(l10n.snippet),
|
||||
leading: const Icon(MingCute.code_line),
|
||||
trailing: const Icon(Icons.keyboard_arrow_right),
|
||||
onTap: () async {
|
||||
final data = await context.showImportDialog(
|
||||
title: l10n.snippet,
|
||||
modelDef: Snippet.example.toJson(),
|
||||
);
|
||||
final data = await context.showImportDialog(title: l10n.snippet, modelDef: Snippet.example.toJson());
|
||||
if (data == null) return;
|
||||
final str = String.fromCharCodes(data);
|
||||
final (list, _) = await context.showLoadingDialog(
|
||||
@@ -275,11 +249,7 @@ final class _BackupPageState extends State<BackupPage> with AutomaticKeepAliveCl
|
||||
final snippetNames = snippets.map((e) => e.name).join(', ');
|
||||
context.showRoundDialog(
|
||||
title: libL10n.attention,
|
||||
child: SingleChildScrollView(
|
||||
child: Text(
|
||||
libL10n.askContinue('${libL10n.import} [$snippetNames]'),
|
||||
),
|
||||
),
|
||||
child: SingleChildScrollView(child: Text(libL10n.askContinue('${libL10n.import} [$snippetNames]'))),
|
||||
actions: Btn.ok(
|
||||
onTap: () {
|
||||
for (final snippet in snippets) {
|
||||
@@ -294,33 +264,6 @@ final class _BackupPageState extends State<BackupPage> with AutomaticKeepAliveCl
|
||||
).cardx;
|
||||
}
|
||||
|
||||
Future<void> _onTapFileRestore(BuildContext context) async {
|
||||
final text = await Pfs.pickFileString();
|
||||
if (text == null) return;
|
||||
|
||||
try {
|
||||
final (backup, err) = await context.showLoadingDialog(
|
||||
fn: () => Computer.shared.start(MergeableUtils.fromJsonString, text.trim()),
|
||||
);
|
||||
if (err != null || backup == null) return;
|
||||
|
||||
await context.showRoundDialog(
|
||||
title: libL10n.restore,
|
||||
child: Text(libL10n.askContinue(
|
||||
'${libL10n.restore} ${libL10n.backup}(${backup.$2})',
|
||||
)),
|
||||
actions: Btn.ok(
|
||||
onTap: () async {
|
||||
await backup.$1.merge(force: true);
|
||||
context.pop();
|
||||
},
|
||||
).toList,
|
||||
);
|
||||
} catch (e, s) {
|
||||
Loggers.app.warning('Import backup failed', e, s);
|
||||
context.showErrDialog(e, s, libL10n.restore);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onTapWebdavDl(BuildContext context) async {
|
||||
webdavLoading.value = true;
|
||||
@@ -328,16 +271,12 @@ final class _BackupPageState extends State<BackupPage> with AutomaticKeepAliveCl
|
||||
final files = await Webdav.shared.list();
|
||||
if (files.isEmpty) return context.showSnackBar(l10n.dirEmpty);
|
||||
|
||||
final fileName = await context.showPickSingleDialog(
|
||||
title: libL10n.restore,
|
||||
items: files,
|
||||
);
|
||||
final fileName = await context.showPickSingleDialog(title: libL10n.restore, items: files);
|
||||
if (fileName == null) return;
|
||||
|
||||
await Webdav.shared.download(relativePath: fileName);
|
||||
final dlFile = await File('${Paths.doc}/$fileName').readAsString();
|
||||
final dlBak = await Computer.shared.start(BackupV2.fromJsonString, dlFile);
|
||||
await dlBak.merge(force: true);
|
||||
await BackupService.restoreFromText(context, dlFile);
|
||||
} catch (e, s) {
|
||||
context.showErrDialog(e, s, libL10n.restore);
|
||||
Loggers.app.warning('Download webdav backup failed', e, s);
|
||||
@@ -351,7 +290,8 @@ final class _BackupPageState extends State<BackupPage> with AutomaticKeepAliveCl
|
||||
final date = DateTime.now().ymdhms(ymdSep: '-', hmsSep: '-', sep: '-');
|
||||
final bakName = '$date-${Miscs.bakFileName}';
|
||||
try {
|
||||
await BackupV2.backup(bakName);
|
||||
final savedPassword = await Stores.setting.backupasswd.read();
|
||||
await BackupV2.backup(bakName, savedPassword);
|
||||
await Webdav.shared.upload(relativePath: bakName);
|
||||
Loggers.app.info('Upload webdav backup success');
|
||||
} catch (e, s) {
|
||||
@@ -388,7 +328,7 @@ final class _BackupPageState extends State<BackupPage> with AutomaticKeepAliveCl
|
||||
onSubmitted: (p0) => FocusScope.of(context).requestFocus(nodePwd),
|
||||
),
|
||||
Input(
|
||||
label: l10n.pwd,
|
||||
label: libL10n.pwd,
|
||||
controller: pwd,
|
||||
node: nodePwd,
|
||||
suggestion: false,
|
||||
@@ -417,42 +357,9 @@ final class _BackupPageState extends State<BackupPage> with AutomaticKeepAliveCl
|
||||
}
|
||||
}
|
||||
|
||||
void _onTapClipboardRestore(BuildContext context) async {
|
||||
final text = await Pfs.paste();
|
||||
if (text == null || text.isEmpty) {
|
||||
context.showSnackBar(libL10n.empty);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
final (backup, err) = await context.showLoadingDialog(
|
||||
fn: () => Computer.shared.start(MergeableUtils.fromJsonString, text.trim()),
|
||||
);
|
||||
if (err != null || backup == null) return;
|
||||
|
||||
await context.showRoundDialog(
|
||||
title: libL10n.restore,
|
||||
child: Text(libL10n.askContinue(
|
||||
'${libL10n.restore} ${libL10n.backup}(${backup.$2})',
|
||||
)),
|
||||
actions: Btn.ok(
|
||||
onTap: () async {
|
||||
await backup.$1.merge(force: true);
|
||||
context.pop();
|
||||
},
|
||||
).toList,
|
||||
);
|
||||
} catch (e, s) {
|
||||
Loggers.app.warning('Import backup failed', e, s);
|
||||
context.showErrDialog(e, s, libL10n.restore);
|
||||
}
|
||||
}
|
||||
|
||||
void _onBulkImportServers(BuildContext context) async {
|
||||
final data = await context.showImportDialog(
|
||||
title: l10n.server,
|
||||
modelDef: Spix.example.toJson(),
|
||||
);
|
||||
final data = await context.showImportDialog(title: l10n.server, modelDef: Spix.example.toJson());
|
||||
if (data == null) return;
|
||||
final text = String.fromCharCodes(data);
|
||||
|
||||
@@ -487,6 +394,11 @@ final class _BackupPageState extends State<BackupPage> with AutomaticKeepAliveCl
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool get wantKeepAlive => true;
|
||||
}
|
||||
|
||||
@@ -190,7 +190,7 @@ class _PrivateKeyEditPageState extends State<PrivateKeyEditPage> {
|
||||
type: TextInputType.text,
|
||||
node: _pwdNode,
|
||||
obscureText: true,
|
||||
label: l10n.pwd,
|
||||
label: libL10n.pwd,
|
||||
icon: Icons.password,
|
||||
suggestion: false,
|
||||
onSubmitted: (_) => _onTapSave(),
|
||||
|
||||
@@ -208,9 +208,8 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
controller: _passwordController,
|
||||
obscureText: true,
|
||||
type: TextInputType.text,
|
||||
label: l10n.pwd,
|
||||
label: libL10n.pwd,
|
||||
icon: Icons.password,
|
||||
hint: l10n.pwd,
|
||||
suggestion: false,
|
||||
onSubmitted: (_) => _onSave(),
|
||||
),
|
||||
@@ -427,9 +426,8 @@ class _ServerEditPageState extends State<ServerEditPage> with AfterLayoutMixin {
|
||||
controller: _wolPwdCtrl,
|
||||
type: TextInputType.text,
|
||||
obscureText: true,
|
||||
label: l10n.pwd,
|
||||
label: libL10n.pwd,
|
||||
icon: Icons.password,
|
||||
hint: l10n.pwd,
|
||||
suggestion: false,
|
||||
),
|
||||
],
|
||||
|
||||
@@ -497,8 +497,8 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: "."
|
||||
ref: "v1.0.324"
|
||||
resolved-ref: e64d5c46844605bbd85322d7c6f250b73977cdde
|
||||
ref: "v1.0.327"
|
||||
resolved-ref: "5075a679b814b10742f967066858ba4df92ea4ae"
|
||||
url: "https://github.com/lppcg/fl_lib"
|
||||
source: git
|
||||
version: "0.0.1"
|
||||
|
||||
@@ -63,7 +63,7 @@ dependencies:
|
||||
fl_lib:
|
||||
git:
|
||||
url: https://github.com/lppcg/fl_lib
|
||||
ref: v1.0.324
|
||||
ref: v1.0.327
|
||||
|
||||
dependency_overrides:
|
||||
# webdav_client_plus:
|
||||
|
||||
Reference in New Issue
Block a user