mirror of
https://github.com/venera-app/venera.git
synced 2025-12-16 07:01:16 +00:00
feat: skip sync setting (#563)
* feat: skip sync setting * fix: upload origin data if nothing to skip * sync: optimize text
This commit is contained in:
@@ -201,6 +201,10 @@
|
|||||||
"Sync Data": "同步数据",
|
"Sync Data": "同步数据",
|
||||||
"Syncing Data": "正在同步数据",
|
"Syncing Data": "正在同步数据",
|
||||||
"Data Sync": "数据同步",
|
"Data Sync": "数据同步",
|
||||||
|
"Skip Setting Fields": "跳过设置项",
|
||||||
|
"Skip Setting Fields (Optional)": "跳过设置项(可选)",
|
||||||
|
"When sync data, skip certain setting fields, which means these won't be uploaded / override.": "同步时跳过指定设置项,这些项不会被上传或覆盖。",
|
||||||
|
"See source code for available fields.": "可用的设置项名称详见源码。",
|
||||||
"Quick Favorite": "快速收藏",
|
"Quick Favorite": "快速收藏",
|
||||||
"Long press on the favorite button to quickly add to this folder": "长按收藏按钮快速添加到这个文件夹",
|
"Long press on the favorite button to quickly add to this folder": "长按收藏按钮快速添加到这个文件夹",
|
||||||
"Added": "已添加",
|
"Added": "已添加",
|
||||||
@@ -624,6 +628,10 @@
|
|||||||
"Sync Data": "同步資料",
|
"Sync Data": "同步資料",
|
||||||
"Syncing Data": "正在同步資料",
|
"Syncing Data": "正在同步資料",
|
||||||
"Data Sync": "資料同步",
|
"Data Sync": "資料同步",
|
||||||
|
"Skip Setting Fields": "跳過設定項",
|
||||||
|
"Skip Setting Fields (Optional)": "跳過設定項(可選)",
|
||||||
|
"When sync data, skip certain setting fields, which means these won't be uploaded / override.": "同步時跳過指定設定項,這些項不會被上傳或覆寫。",
|
||||||
|
"See source code for available fields.": "可用的設定項名稱詳見源碼。",
|
||||||
"Quick Favorite": "快速收藏",
|
"Quick Favorite": "快速收藏",
|
||||||
"Long press on the favorite button to quickly add to this folder": "長按收藏按鈕快速添加到這個資料夾",
|
"Long press on the favorite button to quickly add to this folder": "長按收藏按鈕快速添加到這個資料夾",
|
||||||
"Added": "已添加",
|
"Added": "已添加",
|
||||||
|
|||||||
@@ -23,9 +23,26 @@ class Appdata with Init {
|
|||||||
}
|
}
|
||||||
_isSavingData = true;
|
_isSavingData = true;
|
||||||
try {
|
try {
|
||||||
var data = jsonEncode(toJson());
|
var futures = <Future>[];
|
||||||
|
var json = toJson();
|
||||||
|
var data = jsonEncode(json);
|
||||||
var file = File(FilePath.join(App.dataPath, 'appdata.json'));
|
var file = File(FilePath.join(App.dataPath, 'appdata.json'));
|
||||||
await file.writeAsString(data);
|
futures.add(file.writeAsString(data));
|
||||||
|
|
||||||
|
var disableSyncFields = json["settings"]["disableSyncFields"] as String;
|
||||||
|
if (disableSyncFields.isNotEmpty){
|
||||||
|
var json4sync = jsonDecode(data);
|
||||||
|
List<String> customDisableSync = splitField(disableSyncFields);
|
||||||
|
for (var field in customDisableSync) {
|
||||||
|
json4sync["settings"].remove(field);
|
||||||
|
}
|
||||||
|
var data4sync = jsonEncode(json4sync);
|
||||||
|
var file4sync = File(FilePath.join(App.dataPath, 'syncdata.json'));
|
||||||
|
futures.add(file4sync.writeAsString(data4sync));
|
||||||
|
}
|
||||||
|
|
||||||
|
await Future.wait(futures);
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
_isSavingData = false;
|
_isSavingData = false;
|
||||||
}
|
}
|
||||||
@@ -59,20 +76,33 @@ class Appdata with Init {
|
|||||||
return {'settings': settings._data, 'searchHistory': searchHistory};
|
return {'settings': settings._data, 'searchHistory': searchHistory};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<String> splitField(String merged) {
|
||||||
|
return merged
|
||||||
|
.split(',')
|
||||||
|
.map((field) => field.trim())
|
||||||
|
.where((field) => field.isNotEmpty)
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
/// Following fields are related to device-specific data and should not be synced.
|
/// Following fields are related to device-specific data and should not be synced.
|
||||||
static const _disableSync = [
|
static const _disableSync = [
|
||||||
"proxy",
|
"proxy",
|
||||||
"authorizationRequired",
|
"authorizationRequired",
|
||||||
"customImageProcessing",
|
"customImageProcessing",
|
||||||
"webdav",
|
"webdav",
|
||||||
|
"disableSyncFields",
|
||||||
];
|
];
|
||||||
|
|
||||||
/// Sync data from another device
|
/// Sync data from another device
|
||||||
void syncData(Map<String, dynamic> data) {
|
void syncData(Map<String, dynamic> data) {
|
||||||
if (data['settings'] is Map) {
|
if (data['settings'] is Map) {
|
||||||
var settings = data['settings'] as Map<String, dynamic>;
|
var settings = data['settings'] as Map<String, dynamic>;
|
||||||
|
|
||||||
|
List<String> customDisableSync = splitField(this.settings["disableSyncFields"] as String);
|
||||||
|
|
||||||
for (var key in settings.keys) {
|
for (var key in settings.keys) {
|
||||||
if (!_disableSync.contains(key)) {
|
if (!_disableSync.contains(key) &&
|
||||||
|
!customDisableSync.contains(key)) {
|
||||||
this.settings[key] = settings[key];
|
this.settings[key] = settings[key];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -166,6 +196,7 @@ class Settings with ChangeNotifier {
|
|||||||
'checkUpdateOnStart': false,
|
'checkUpdateOnStart': false,
|
||||||
'limitImageWidth': true,
|
'limitImageWidth': true,
|
||||||
'webdav': [], // empty means not configured
|
'webdav': [], // empty means not configured
|
||||||
|
"disableSyncFields": "", // "field1, field2, ..."
|
||||||
'dataVersion': 0,
|
'dataVersion': 0,
|
||||||
'quickFavorite': null,
|
'quickFavorite': null,
|
||||||
'enableTurnPageByVolumeKey': true,
|
'enableTurnPageByVolumeKey': true,
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ class _AppSettingsState extends State<AppSettings> {
|
|||||||
title: "Export App Data".tl,
|
title: "Export App Data".tl,
|
||||||
callback: () async {
|
callback: () async {
|
||||||
var controller = showLoadingDialog(context);
|
var controller = showLoadingDialog(context);
|
||||||
var file = await exportAppData();
|
var file = await exportAppData(false);
|
||||||
await saveFile(filename: "data.venera", file: file);
|
await saveFile(filename: "data.venera", file: file);
|
||||||
controller.close();
|
controller.close();
|
||||||
},
|
},
|
||||||
@@ -353,6 +353,8 @@ class _WebdavSettingState extends State<_WebdavSetting> {
|
|||||||
String url = "";
|
String url = "";
|
||||||
String user = "";
|
String user = "";
|
||||||
String pass = "";
|
String pass = "";
|
||||||
|
String disableSync = "";
|
||||||
|
|
||||||
bool autoSync = true;
|
bool autoSync = true;
|
||||||
|
|
||||||
bool isTesting = false;
|
bool isTesting = false;
|
||||||
@@ -364,6 +366,9 @@ class _WebdavSettingState extends State<_WebdavSetting> {
|
|||||||
if (appdata.settings['webdav'] is! List) {
|
if (appdata.settings['webdav'] is! List) {
|
||||||
appdata.settings['webdav'] = [];
|
appdata.settings['webdav'] = [];
|
||||||
}
|
}
|
||||||
|
if (appdata.settings['disableSyncFields'].trim().isNotEmpty) {
|
||||||
|
disableSync = appdata.settings['disableSyncFields'];
|
||||||
|
}
|
||||||
var configs = appdata.settings['webdav'] as List;
|
var configs = appdata.settings['webdav'] as List;
|
||||||
if (configs.whereType<String>().length != 3) {
|
if (configs.whereType<String>().length != 3) {
|
||||||
return;
|
return;
|
||||||
@@ -418,6 +423,56 @@ class _WebdavSettingState extends State<_WebdavSetting> {
|
|||||||
onChanged: (value) => pass = value,
|
onChanged: (value) => pass = value,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
|
TextField(
|
||||||
|
decoration: InputDecoration(
|
||||||
|
labelText: "Skip Setting Fields (Optional)".tl,
|
||||||
|
hintText: "field0, field1, field2, ...",
|
||||||
|
hintStyle: TextStyle(color: Theme.of(context).hintColor),
|
||||||
|
border: OutlineInputBorder(),
|
||||||
|
suffixIcon: IconButton(
|
||||||
|
icon: Icon(Icons.help_outline),
|
||||||
|
onPressed: () {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (_) => AlertDialog(
|
||||||
|
title: Text("Skip Setting Fields".tl),
|
||||||
|
content: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"When sync data, skip certain setting fields, which means these won't be uploaded / override.".tl,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
"See source code for available fields.".tl,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Align(
|
||||||
|
alignment: Alignment.centerRight,
|
||||||
|
child: IconButton(
|
||||||
|
icon: const Icon(Icons.open_in_new),
|
||||||
|
onPressed: () {
|
||||||
|
launchUrlString("https://github.com/venera-app/venera/blob/b08f11f6ac49bd07d34b4fcde233ed07e86efbc9/lib/foundation/appdata.dart#L138");
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
controller: TextEditingController(text: disableSync),
|
||||||
|
onChanged: (value) => disableSync = value,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 12),
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: Icon(Icons.sync),
|
leading: Icon(Icons.sync),
|
||||||
title: Text("Auto Sync Data".tl),
|
title: Text("Auto Sync Data".tl),
|
||||||
@@ -494,6 +549,7 @@ class _WebdavSettingState extends State<_WebdavSetting> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
appdata.settings['webdav'] = [url, user, pass];
|
appdata.settings['webdav'] = [url, user, pass];
|
||||||
|
appdata.settings['disableSyncFields'] = disableSync;
|
||||||
appdata.implicitData['webdavAutoSync'] = autoSync;
|
appdata.implicitData['webdavAutoSync'] = autoSync;
|
||||||
appdata.writeImplicitData();
|
appdata.writeImplicitData();
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import 'package:zip_flutter/zip_flutter.dart';
|
|||||||
|
|
||||||
import 'io.dart';
|
import 'io.dart';
|
||||||
|
|
||||||
Future<File> exportAppData() async {
|
Future<File> exportAppData([bool sync = true]) async {
|
||||||
var time = DateTime.now().millisecondsSinceEpoch ~/ 1000;
|
var time = DateTime.now().millisecondsSinceEpoch ~/ 1000;
|
||||||
var cacheFilePath = FilePath.join(App.cachePath, '$time.venera');
|
var cacheFilePath = FilePath.join(App.cachePath, '$time.venera');
|
||||||
var cacheFile = File(cacheFilePath);
|
var cacheFile = File(cacheFilePath);
|
||||||
@@ -27,7 +27,7 @@ Future<File> exportAppData() async {
|
|||||||
var zipFile = ZipFile.open(cacheFilePath);
|
var zipFile = ZipFile.open(cacheFilePath);
|
||||||
var historyFile = FilePath.join(dataPath, "history.db");
|
var historyFile = FilePath.join(dataPath, "history.db");
|
||||||
var localFavoriteFile = FilePath.join(dataPath, "local_favorite.db");
|
var localFavoriteFile = FilePath.join(dataPath, "local_favorite.db");
|
||||||
var appdata = FilePath.join(dataPath, "appdata.json");
|
var appdata = FilePath.join(dataPath, sync ? "syncdata.json" : "appdata.json");
|
||||||
var cookies = FilePath.join(dataPath, "cookie.db");
|
var cookies = FilePath.join(dataPath, "cookie.db");
|
||||||
zipFile.addFile("history.db", historyFile);
|
zipFile.addFile("history.db", historyFile);
|
||||||
zipFile.addFile("local_favorite.db", localFavoriteFile);
|
zipFile.addFile("local_favorite.db", localFavoriteFile);
|
||||||
|
|||||||
@@ -130,7 +130,9 @@ class DataSync with ChangeNotifier {
|
|||||||
try {
|
try {
|
||||||
appdata.settings['dataVersion']++;
|
appdata.settings['dataVersion']++;
|
||||||
await appdata.saveData(false);
|
await appdata.saveData(false);
|
||||||
var data = await exportAppData();
|
var data = await exportAppData(
|
||||||
|
appdata.settings['disableSyncFields'].toString().isNotEmpty
|
||||||
|
);
|
||||||
var time =
|
var time =
|
||||||
(DateTime.now().millisecondsSinceEpoch ~/ 86400000).toString();
|
(DateTime.now().millisecondsSinceEpoch ~/ 86400000).toString();
|
||||||
var filename = time;
|
var filename = time;
|
||||||
|
|||||||
Reference in New Issue
Block a user