diff --git a/src/MaaWpfGui/Constants/ConfigurationKeys.cs b/src/MaaWpfGui/Constants/ConfigurationKeys.cs index 233cb5550c..a5924dc7ac 100644 --- a/src/MaaWpfGui/Constants/ConfigurationKeys.cs +++ b/src/MaaWpfGui/Constants/ConfigurationKeys.cs @@ -18,6 +18,12 @@ namespace MaaWpfGui.Constants /// public static class ConfigurationKeys { + public const string CurrentConfiguration = "Current"; + public const string DefaultConfiguration = "Default"; + public const string ConfigurationMap = "Configurations"; + public const string ConfigurationData = "Data"; + public const string ConfigurationCron = "Cron"; + public const string Localization = "GUI.Localization"; public const string MinimizeToTray = "GUI.MinimizeToTray"; public const string HideCloseButton = "GUI.HideCloseButton"; diff --git a/src/MaaWpfGui/Helper/ConfigurationHelper.cs b/src/MaaWpfGui/Helper/ConfigurationHelper.cs index 49666e778c..6fd916bc14 100644 --- a/src/MaaWpfGui/Helper/ConfigurationHelper.cs +++ b/src/MaaWpfGui/Helper/ConfigurationHelper.cs @@ -14,7 +14,10 @@ using System; using System.Collections.Generic; using System.IO; -using System.Text.Json; +using System.Linq; +using MaaWpfGui.Constants; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; using Serilog; namespace MaaWpfGui.Helper @@ -23,6 +26,8 @@ namespace MaaWpfGui.Helper { private static readonly string _configurationFile = Path.Combine(Environment.CurrentDirectory, "config/gui.json"); private static readonly string _configurationBakFile = Path.Combine(Environment.CurrentDirectory, "config/gui.json.bak"); + private static Dictionary> _kvsMap; + private static string _current = ConfigurationKeys.DefaultConfiguration; private static Dictionary _kvs; private static readonly ILogger _logger = Log.ForContext(); @@ -124,29 +129,6 @@ namespace MaaWpfGui.Helper Directory.CreateDirectory("config"); } - // Config file migration - const string OldConfigFile = "gui.json"; - if (File.Exists(OldConfigFile)) - { - if (File.Exists(_configurationFile)) - { - File.Delete(OldConfigFile); - } - - File.Move(OldConfigFile, _configurationFile); - } - - var oldBakFiles = Directory.GetFiles(".", "gui.json.bak*"); - if (oldBakFiles.Length != 0) - { - _logger.Information("Found old backup files, deleting..."); - foreach (var f in oldBakFiles) - { - File.Delete(f); - _logger.Information("Deleted {0}", f); - } - } - // Load configuration file var parsed = ParseJsonFile(_configurationFile); if (parsed is null) @@ -161,15 +143,34 @@ namespace MaaWpfGui.Helper if (parsed is null) { _logger.Information("Failed to load configuration file, creating a new one"); - _kvs = new Dictionary(); + + _kvsMap = new Dictionary>(); + _current = ConfigurationKeys.DefaultConfiguration; + _kvsMap[_current] = new Dictionary(); + _kvs = _kvsMap[_current]; + + return false; + } + + if (parsed.ContainsKey(ConfigurationKeys.ConfigurationMap)) + { + // new version + _kvsMap = parsed[ConfigurationKeys.ConfigurationMap].ToObject>>(); + _current = parsed[ConfigurationKeys.CurrentConfiguration].ToString(); + _kvs = _kvsMap[_current]; } else { - _kvs = parsed; - return true; + // old version + _logger.Information("Configuration file is in old version, migrating to new version"); + + _kvsMap = new Dictionary>(); + _current = ConfigurationKeys.DefaultConfiguration; + _kvsMap[_current] = parsed.ToObject>(); + _kvs = _kvsMap[_current]; } - return false; + return true; } /// @@ -184,10 +185,11 @@ namespace MaaWpfGui.Helper return false; } - var jsonStr = JsonSerializer.Serialize(_kvs, new JsonSerializerOptions + var jsonStr = JsonConvert.SerializeObject(new Dictionary { - WriteIndented = true, - }); + { ConfigurationKeys.ConfigurationMap, _kvsMap }, + { ConfigurationKeys.CurrentConfiguration, _current }, + }, Formatting.Indented); try { @@ -272,18 +274,18 @@ namespace MaaWpfGui.Helper Released = true; } - private static Dictionary ParseJsonFile(string filePath) + private static JObject ParseJsonFile(string filePath) { if (File.Exists(filePath) is false) { return null; } - var fs = File.OpenRead(filePath); + var str = File.ReadAllText(filePath); try { - var obj = JsonSerializer.Deserialize>(fs); + var obj = (JObject)JsonConvert.DeserializeObject(str); if (obj is null) { throw new Exception("Failed to parse json file"); @@ -295,12 +297,75 @@ namespace MaaWpfGui.Helper { _logger.Error(ex, "Failed to deserialize json file: {FilePath}", filePath); } - finally - { - fs.Close(); - } return null; } + + public static bool SwitchConfiguration(string configName) + { + if (_kvsMap.ContainsKey(configName) is false) + { + _logger.Warning("Configuration {ConfigName} does not exist", configName); + return false; + } + + _current = configName; + _kvs = _kvsMap[_current]; + return true; + } + + public static bool AddConfiguration(string configName, string copyFrom = null) + { + if (_kvsMap.ContainsKey(configName)) + { + _logger.Warning("Configuration {ConfigName} already exists", configName); + return false; + } + + if (copyFrom is null) + { + _kvsMap[configName] = new Dictionary(); + } + else + { + if (_kvsMap.ContainsKey(copyFrom) is false) + { + _logger.Warning("Configuration {ConfigName} does not exist", copyFrom); + return false; + } + + _kvsMap[configName] = new Dictionary(_kvsMap[copyFrom]); + } + + return true; + } + + public static bool DeleteConfiguration(string configName) + { + if (_kvsMap.ContainsKey(configName) is false) + { + _logger.Warning("Configuration {ConfigName} does not exist", configName); + return false; + } + + if (_current == configName) + { + _logger.Warning("Configuration {ConfigName} is current configuration, cannot delete", configName); + return false; + } + + _kvsMap.Remove(configName); + return true; + } + + public static List GetConfigurationList() + { + return _kvsMap.Keys.ToList(); + } + + public static string GetCurrentConfiguration() + { + return _current; + } } } diff --git a/src/MaaWpfGui/Res/Localizations/en-us.xaml b/src/MaaWpfGui/Res/Localizations/en-us.xaml index 30788b62a8..1a75db101e 100644 --- a/src/MaaWpfGui/Res/Localizations/en-us.xaml +++ b/src/MaaWpfGui/Res/Localizations/en-us.xaml @@ -197,6 +197,7 @@ Please download the full package manually to update. Timer + Switch Configuration Auto start with PC Auto Run task after launched diff --git a/src/MaaWpfGui/Res/Localizations/zh-cn.xaml b/src/MaaWpfGui/Res/Localizations/zh-cn.xaml index ab0ea9eb37..4c9d0dd15b 100644 --- a/src/MaaWpfGui/Res/Localizations/zh-cn.xaml +++ b/src/MaaWpfGui/Res/Localizations/zh-cn.xaml @@ -200,6 +200,8 @@ 定时 + 切换配置 + 开机自动启动MAA 启动MAA后直接运行 启动MAA后直接最小化 diff --git a/src/MaaWpfGui/ViewModels/UI/SettingsViewModel.cs b/src/MaaWpfGui/ViewModels/UI/SettingsViewModel.cs index e5954c8d4a..becdcc59bd 100644 --- a/src/MaaWpfGui/ViewModels/UI/SettingsViewModel.cs +++ b/src/MaaWpfGui/ViewModels/UI/SettingsViewModel.cs @@ -93,6 +93,7 @@ namespace MaaWpfGui.ViewModels.UI { DisplayName = LocalizationHelper.GetString("Settings"); + _listTitle.Add(LocalizationHelper.GetString("SwitchConfiguration")); _listTitle.Add(LocalizationHelper.GetString("ScheduleSettings")); _listTitle.Add(LocalizationHelper.GetString("GameSettings")); _listTitle.Add(LocalizationHelper.GetString("ConnectionSettings")); @@ -265,6 +266,14 @@ namespace MaaWpfGui.ViewModels.UI new CombinedData { Display = LocalizationHelper.GetString("txwy"), Value = "txwy" }, }; + var configurations = new List(); + foreach (var conf in ConfigurationHelper.GetConfigurationList()) + { + configurations.Add(new CombinedData { Display = conf, Value = conf }); + } + + ConfigurationList = configurations; + DarkModeList = new List { new CombinedData { Display = LocalizationHelper.GetString("Light"), Value = "Light" }, @@ -851,6 +860,23 @@ namespace MaaWpfGui.ViewModels.UI /// public List ClientTypeList { get; set; } + public List ConfigurationList { get; set; } + + private string _currentConfiguration = ConfigurationHelper.GetCurrentConfiguration(); + + public string CurrentConfiguration + { + get => _currentConfiguration; + set + { + SetAndNotify(ref _currentConfiguration, value); + ConfigurationHelper.SwitchConfiguration(value); + + Application.Current.Shutdown(); + Bootstrapper.RestartApplication(); + } + } + /// /// Gets or sets the list of the configuration of connection. /// diff --git a/src/MaaWpfGui/Views/UI/SettingsView.xaml b/src/MaaWpfGui/Views/UI/SettingsView.xaml index dba37b3f8d..328028e00a 100644 --- a/src/MaaWpfGui/Views/UI/SettingsView.xaml +++ b/src/MaaWpfGui/Views/UI/SettingsView.xaml @@ -45,33 +45,36 @@ - + + + + - + - + - + - + - + - + diff --git a/src/MaaWpfGui/Views/UserControl/ConfigurationMgrUserControl.xaml b/src/MaaWpfGui/Views/UserControl/ConfigurationMgrUserControl.xaml new file mode 100644 index 0000000000..050b10d12f --- /dev/null +++ b/src/MaaWpfGui/Views/UserControl/ConfigurationMgrUserControl.xaml @@ -0,0 +1,36 @@ + + + + + diff --git a/src/MaaWpfGui/Views/UserControl/ConfigurationMgrUserControl.xaml.cs b/src/MaaWpfGui/Views/UserControl/ConfigurationMgrUserControl.xaml.cs new file mode 100644 index 0000000000..7edf956340 --- /dev/null +++ b/src/MaaWpfGui/Views/UserControl/ConfigurationMgrUserControl.xaml.cs @@ -0,0 +1,29 @@ +// +// MaaWpfGui - A part of the MaaCoreArknights project +// Copyright (C) 2021 MistEO and Contributors +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY +// + +namespace MaaWpfGui.Views.UserControl +{ + /// + /// GameClientUserControl.xaml 的交互逻辑 + /// + public partial class ConfigurationMgrUserControl : System.Windows.Controls.UserControl + { + /// + /// Initializes a new instance of the class. + /// + public ConfigurationMgrUserControl() + { + InitializeComponent(); + } + } +}