From b08265221f9053b847505d0efe31d39bb61ca440 Mon Sep 17 00:00:00 2001 From: lollipopkit Date: Sat, 27 Jan 2024 21:11:40 +0800 Subject: [PATCH] fix: backup merge --- ios/Runner.xcodeproj/project.pbxproj | 36 ++++---- lib/core/utils/sync/icloud.dart | 35 +++----- lib/core/utils/sync/webdav.dart | 25 ++---- lib/data/model/app/backup.dart | 109 +++++++++++------------ lib/data/model/app/json.dart | 7 -- lib/data/model/app/menu/server_func.dart | 4 + lib/data/res/build_data.dart | 6 +- lib/data/store/container.dart | 2 + lib/data/store/history.dart | 2 + lib/data/store/private_key.dart | 2 + lib/data/store/server.dart | 3 + lib/data/store/snippet.dart | 2 + macos/Runner.xcodeproj/project.pbxproj | 12 +-- 13 files changed, 115 insertions(+), 130 deletions(-) delete mode 100644 lib/data/model/app/json.dart diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 93d4b625..14416e39 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -586,7 +586,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; - CURRENT_PROJECT_VERSION = 723; + CURRENT_PROJECT_VERSION = 724; DEVELOPMENT_TEAM = BA88US33G6; ENABLE_BITCODE = NO; INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist"; @@ -596,7 +596,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.723; + MARKETING_VERSION = 1.0.724; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; @@ -720,7 +720,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; - CURRENT_PROJECT_VERSION = 723; + CURRENT_PROJECT_VERSION = 724; DEVELOPMENT_TEAM = BA88US33G6; ENABLE_BITCODE = NO; INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist"; @@ -730,7 +730,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.723; + MARKETING_VERSION = 1.0.724; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; @@ -748,7 +748,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; - CURRENT_PROJECT_VERSION = 723; + CURRENT_PROJECT_VERSION = 724; DEVELOPMENT_TEAM = BA88US33G6; ENABLE_BITCODE = NO; INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist"; @@ -758,7 +758,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.723; + MARKETING_VERSION = 1.0.724; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; @@ -779,7 +779,7 @@ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 723; + CURRENT_PROJECT_VERSION = 724; DEVELOPMENT_TEAM = BA88US33G6; GCC_C_LANGUAGE_STANDARD = gnu11; GENERATE_INFOPLIST_FILE = YES; @@ -792,7 +792,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 1.0.723; + MARKETING_VERSION = 1.0.724; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget; @@ -818,7 +818,7 @@ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 723; + CURRENT_PROJECT_VERSION = 724; DEVELOPMENT_TEAM = BA88US33G6; GCC_C_LANGUAGE_STANDARD = gnu11; GENERATE_INFOPLIST_FILE = YES; @@ -831,7 +831,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 1.0.723; + MARKETING_VERSION = 1.0.724; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -854,7 +854,7 @@ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 723; + CURRENT_PROJECT_VERSION = 724; DEVELOPMENT_TEAM = BA88US33G6; GCC_C_LANGUAGE_STANDARD = gnu11; GENERATE_INFOPLIST_FILE = YES; @@ -867,7 +867,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 1.0.723; + MARKETING_VERSION = 1.0.724; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -890,7 +890,7 @@ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 723; + CURRENT_PROJECT_VERSION = 724; DEVELOPMENT_ASSET_PATHS = ""; DEVELOPMENT_TEAM = BA88US33G6; ENABLE_PREVIEWS = YES; @@ -902,7 +902,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.723; + MARKETING_VERSION = 1.0.724; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.WatchEnd; @@ -931,7 +931,7 @@ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 723; + CURRENT_PROJECT_VERSION = 724; DEVELOPMENT_ASSET_PATHS = ""; DEVELOPMENT_TEAM = BA88US33G6; ENABLE_PREVIEWS = YES; @@ -943,7 +943,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.723; + MARKETING_VERSION = 1.0.724; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.WatchEnd; PRODUCT_NAME = ServerBox; @@ -969,7 +969,7 @@ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 723; + CURRENT_PROJECT_VERSION = 724; DEVELOPMENT_ASSET_PATHS = ""; DEVELOPMENT_TEAM = BA88US33G6; ENABLE_PREVIEWS = YES; @@ -981,7 +981,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.723; + MARKETING_VERSION = 1.0.724; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.WatchEnd; PRODUCT_NAME = ServerBox; diff --git a/lib/core/utils/sync/icloud.dart b/lib/core/utils/sync/icloud.dart index 7d08594c..eab4b9e1 100644 --- a/lib/core/utils/sync/icloud.dart +++ b/lib/core/utils/sync/icloud.dart @@ -183,29 +183,22 @@ abstract final class ICloud { } static Future sync() async { - var dlSuccess = false; - try { - final result = await download(relativePath: Paths.bakName); - if (result != null) { - throw result; - } - dlSuccess = true; - } catch (e, s) { - _logger.warning('Download backup failed', e, s); - } - if (!dlSuccess) { - await Backup.backup(); - final uploadResult = await upload(relativePath: Paths.bakName); - if (uploadResult != null) { - _logger.warning('Upload backup failed: $uploadResult'); - } else { - _logger.info('Upload backup success'); - } + final result = await download(relativePath: Paths.bakName); + if (result != null) { + _logger.warning('Download backup failed: $result'); + await backup(); return; } - final dlFile = await File(await Paths.bak).readAsString(); - final dlBak = await Computer.shared.start(Backup.fromJsonString, dlFile); - await dlBak.restore(); + + final dlFile = await File(await Paths.bak).readAsString(); + final dlBak = await Computer.shared.start(Backup.fromJsonString, dlFile); + await dlBak.restore(); + + + await backup(); + } + + static Future backup() async { await Backup.backup(); final uploadResult = await upload(relativePath: Paths.bakName); if (uploadResult != null) { diff --git a/lib/core/utils/sync/webdav.dart b/lib/core/utils/sync/webdav.dart index 077e7b45..e27ce97c 100644 --- a/lib/core/utils/sync/webdav.dart +++ b/lib/core/utils/sync/webdav.dart @@ -98,26 +98,19 @@ abstract final class Webdav { static Future sync() async { final result = await download(relativePath: Paths.bakName); if (result != null) { + _logger.warning('Download failed: $result'); await backup(); return; } - final dlFile = await Computer.shared.start( - (message) async { - try { - final file = await File(message).readAsString(); - final bak = Backup.fromJsonString(file); - return bak; - } catch (_) { - return null; - } - }, - await Paths.bak, - ); - if (dlFile == null) { - await backup(); - return; + + try { + final dlFile = await File(await Paths.bak).readAsString(); + final dlBak = await Computer.shared.start(Backup.fromJsonString, dlFile); + await dlBak.restore(); + } catch (e) { + _logger.warning('Restore failed: $e'); } - await dlFile.restore(); + await backup(); } diff --git a/lib/data/model/app/backup.dart b/lib/data/model/app/backup.dart index f086010c..ba9cb584 100644 --- a/lib/data/model/app/backup.dart +++ b/lib/data/model/app/backup.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'dart:io'; +import 'package:logging/logging.dart'; import 'package:toolbox/core/persistant_store.dart'; import 'package:toolbox/data/model/server/private_key_info.dart'; import 'package:toolbox/data/model/server/server_private_info.dart'; @@ -13,6 +14,8 @@ import 'package:toolbox/data/res/store.dart'; const backupFormatVersion = 1; +final _logger = Logger('Backup'); + class Backup { // backup format version final int version; @@ -77,19 +80,20 @@ class Backup { history = Stores.history.box.toJson(); static Future backup([String? name]) async { - final result = _diyEncrypt(json.encode(Backup.loadFromStore())); + final result = _diyEncrypt(json.encode(Backup.loadFromStore().toJson())); final path = '${await Paths.doc}/${name ?? Paths.bakName}'; await File(path).writeAsString(result); return path; } - /// - Return null if same time - /// - Return false if local is newer - /// - Return true if restore success Future restore({bool force = false}) async { final curTime = Stores.lastModTime ?? 0; final bakTime = lastModTime ?? 0; final shouldRestore = force || curTime < bakTime; + if (!shouldRestore) { + _logger.info('No need to restore, local is newer'); + return; + } // Settings final nowSettingsKeys = Stores.setting.box.keys.toSet(); @@ -100,67 +104,59 @@ class Backup { for (final k in newSettingsKeys) { Stores.setting.box.put(k, settings[k]); } - if (shouldRestore) { - for (final k in delSettingsKeys) { - Stores.setting.box.delete(k); - } - for (final k in updateSettingsKeys) { - Stores.setting.box.put(k, settings[k]); - } + for (final k in delSettingsKeys) { + Stores.setting.box.delete(k); + } + for (final k in updateSettingsKeys) { + Stores.setting.box.put(k, settings[k]); } // Snippets - final nowSnippets = Stores.snippet.fetch().toSet(); - final bakSnippets = snippets.toSet(); + final nowSnippets = Stores.snippet.box.keys.toSet(); + final bakSnippets = snippets.map((e) => e.name).toSet(); final newSnippets = bakSnippets.difference(nowSnippets); final delSnippets = nowSnippets.difference(bakSnippets); final updateSnippets = nowSnippets.intersection(bakSnippets); for (final s in newSnippets) { - Stores.snippet.put(s); + Stores.snippet.box.put(s, snippets.firstWhere((e) => e.name == s)); } - if (shouldRestore) { - for (final s in delSnippets) { - Stores.snippet.delete(s); - } - for (final s in updateSnippets) { - Stores.snippet.put(s); - } + for (final s in delSnippets) { + Stores.snippet.box.delete(s); + } + for (final s in updateSnippets) { + Stores.snippet.box.put(s, snippets.firstWhere((e) => e.name == s)); } // ServerPrivateInfo - final nowSpis = Stores.server.fetch().toSet(); - final bakSpis = spis.toSet(); + final nowSpis = Stores.server.box.keys.toSet(); + final bakSpis = spis.map((e) => e.id).toSet(); final newSpis = bakSpis.difference(nowSpis); final delSpis = nowSpis.difference(bakSpis); final updateSpis = nowSpis.intersection(bakSpis); for (final s in newSpis) { - Stores.server.put(s); + Stores.server.box.put(s, spis.firstWhere((e) => e.id == s)); } - if (shouldRestore) { - for (final s in delSpis) { - Stores.server.delete(s.id); - } - for (final s in updateSpis) { - Stores.server.put(s); - } + for (final s in delSpis) { + Stores.server.box.delete(s); + } + for (final s in updateSpis) { + Stores.server.box.put(s, spis.firstWhere((e) => e.id == s)); } // PrivateKeyInfo - final nowKeys = Stores.key.fetch().toSet(); - final bakKeys = keys.toSet(); + final nowKeys = Stores.key.box.keys.toSet(); + final bakKeys = keys.map((e) => e.id).toSet(); final newKeys = bakKeys.difference(nowKeys); final delKeys = nowKeys.difference(bakKeys); final updateKeys = nowKeys.intersection(bakKeys); for (final s in newKeys) { - Stores.key.put(s); + Stores.key.box.put(s, keys.firstWhere((e) => e.id == s)); } - if (shouldRestore) { - for (final s in delKeys) { - Stores.key.delete(s); - } - for (final s in updateKeys) { - Stores.key.put(s); - } + for (final s in delKeys) { + Stores.key.box.delete(s); + } + for (final s in updateKeys) { + Stores.key.box.put(s, keys.firstWhere((e) => e.id == s)); } // History @@ -172,13 +168,11 @@ class Backup { for (final s in newHistory) { Stores.history.box.put(s, history[s]); } - if (shouldRestore) { - for (final s in delHistory) { - Stores.history.box.delete(s); - } - for (final s in updateHistory) { - Stores.history.box.put(s, history[s]); - } + for (final s in delHistory) { + Stores.history.box.delete(s); + } + for (final s in updateHistory) { + Stores.history.box.put(s, history[s]); } // Container @@ -188,22 +182,19 @@ class Backup { final delContainer = nowContainer.difference(bakContainer); final updateContainer = nowContainer.intersection(bakContainer); for (final s in newContainer) { - Stores.docker.put(s, container[s]); + Stores.docker.box.put(s, container[s]); } - if (shouldRestore) { - for (final s in delContainer) { - Stores.docker.box.delete(s); - } - for (final s in updateContainer) { - Stores.docker.put(s, container[s]); - } + for (final s in delContainer) { + Stores.docker.box.delete(s); + } + for (final s in updateContainer) { + Stores.docker.box.put(s, container[s]); } - - // update last modified time, avoid restore again - Stores.setting.box.updateLastModified(lastModTime); Pros.reload(); RebuildNodes.app.rebuild(); + + _logger.info('Restore success'); } Backup.fromJsonString(String raw) diff --git a/lib/data/model/app/json.dart b/lib/data/model/app/json.dart deleted file mode 100644 index 2566d85f..00000000 --- a/lib/data/model/app/json.dart +++ /dev/null @@ -1,7 +0,0 @@ -abstract class JsonSerializable { - /// Convert [this] to json - Map toJson(); - - /// Create [this] from json - T fromJson(Map json); -} diff --git a/lib/data/model/app/menu/server_func.dart b/lib/data/model/app/menu/server_func.dart index f022c4b1..ae514703 100644 --- a/lib/data/model/app/menu/server_func.dart +++ b/lib/data/model/app/menu/server_func.dart @@ -41,4 +41,8 @@ enum ServerFuncBtn { terminal => l10n.terminal, iperf => 'iperf', }; + + int toJson() => index; + + static ServerFuncBtn fromJson(int i) => values[i]; } diff --git a/lib/data/res/build_data.dart b/lib/data/res/build_data.dart index 5992cc56..877913ea 100644 --- a/lib/data/res/build_data.dart +++ b/lib/data/res/build_data.dart @@ -2,9 +2,9 @@ class BuildData { static const String name = "ServerBox"; - static const int build = 723; + static const int build = 724; static const String engine = "3.16.8"; - static const String buildAt = "2024-01-26 17:05:35"; - static const int modifications = 3; + static const String buildAt = "2024-01-26 21:05:29"; + static const int modifications = 2; static const int script = 36; } diff --git a/lib/data/store/container.dart b/lib/data/store/container.dart index a1724d29..ea229b72 100644 --- a/lib/data/store/container.dart +++ b/lib/data/store/container.dart @@ -13,6 +13,7 @@ class DockerStore extends PersistentStore { void put(String id, String host) { box.put(id, host); + box.updateLastModified(); } ContainerType getType([String? id]) { @@ -26,5 +27,6 @@ class DockerStore extends PersistentStore { void setType(String? id, ContainerType type) { box.put(_keyConfig + (id ?? ''), type.toString()); + box.updateLastModified(); } } diff --git a/lib/data/store/history.dart b/lib/data/store/history.dart index 26e401a8..a6670d7a 100644 --- a/lib/data/store/history.dart +++ b/lib/data/store/history.dart @@ -18,6 +18,7 @@ class _ListHistory { _history.remove(path); _history.insert(0, path); _box.put(_name, _history); + _box.updateLastModified(); } List get all => _history; @@ -38,6 +39,7 @@ class _MapHistory { void put(String id, String val) { _history[id] = val; _box.put(_name, _history); + _box.updateLastModified(); } String? fetch(String id) => _history[id]; diff --git a/lib/data/store/private_key.dart b/lib/data/store/private_key.dart index 2319266b..5c9ce4fa 100644 --- a/lib/data/store/private_key.dart +++ b/lib/data/store/private_key.dart @@ -6,6 +6,7 @@ class PrivateKeyStore extends PersistentStore { void put(PrivateKeyInfo info) { box.put(info.id, info); + box.updateLastModified(); } List fetch() { @@ -27,5 +28,6 @@ class PrivateKeyStore extends PersistentStore { void delete(PrivateKeyInfo s) { box.delete(s.id); + box.updateLastModified(); } } diff --git a/lib/data/store/server.dart b/lib/data/store/server.dart index dc3f857a..36e544ac 100644 --- a/lib/data/store/server.dart +++ b/lib/data/store/server.dart @@ -6,6 +6,7 @@ class ServerStore extends PersistentStore { void put(ServerPrivateInfo info) { box.put(info.id, info); + box.updateLastModified(); } List fetch() { @@ -22,10 +23,12 @@ class ServerStore extends PersistentStore { void delete(String id) { box.delete(id); + box.updateLastModified(); } void deleteAll() { box.clear(); + box.updateLastModified(); } void update(ServerPrivateInfo old, ServerPrivateInfo newInfo) { diff --git a/lib/data/store/snippet.dart b/lib/data/store/snippet.dart index 2062dda2..72b25b5b 100644 --- a/lib/data/store/snippet.dart +++ b/lib/data/store/snippet.dart @@ -6,6 +6,7 @@ class SnippetStore extends PersistentStore { void put(Snippet snippet) { box.put(snippet.name, snippet); + box.updateLastModified(); } List fetch() { @@ -22,5 +23,6 @@ class SnippetStore extends PersistentStore { void delete(Snippet s) { box.delete(s.name); + box.updateLastModified(); } } diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj index 47951472..92015c84 100644 --- a/macos/Runner.xcodeproj/project.pbxproj +++ b/macos/Runner.xcodeproj/project.pbxproj @@ -439,7 +439,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 723; + CURRENT_PROJECT_VERSION = 724; DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "Server Box"; @@ -449,7 +449,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.15; - MARKETING_VERSION = 1.0.723; + MARKETING_VERSION = 1.0.724; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox; PRODUCT_NAME = "Server Box"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -574,7 +574,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 723; + CURRENT_PROJECT_VERSION = 724; DEVELOPMENT_TEAM = BA88US33G6; INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "Server Box"; @@ -584,7 +584,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.15; - MARKETING_VERSION = 1.0.723; + MARKETING_VERSION = 1.0.724; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox; PRODUCT_NAME = "Server Box"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -604,7 +604,7 @@ "CODE_SIGN_IDENTITY[sdk=macosx*]" = "3rd Party Mac Developer Application"; CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 723; + CURRENT_PROJECT_VERSION = 724; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=macosx*]" = BA88US33G6; INFOPLIST_FILE = Runner/Info.plist; @@ -615,7 +615,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.15; - MARKETING_VERSION = 1.0.723; + MARKETING_VERSION = 1.0.724; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox; PRODUCT_NAME = "Server Box"; PROVISIONING_PROFILE_SPECIFIER = "";