diff --git a/System.Application.SteamTools.Client.Desktop.Avalonia.App/App.axaml.cs b/System.Application.SteamTools.Client.Desktop.Avalonia.App/App.axaml.cs
index a55b039b8..3e11772ff 100644
--- a/System.Application.SteamTools.Client.Desktop.Avalonia.App/App.axaml.cs
+++ b/System.Application.SteamTools.Client.Desktop.Avalonia.App/App.axaml.cs
@@ -19,6 +19,8 @@ using Avalonia.Markup.Xaml.Styling;
using System.Application.Services;
using System.Windows.Input;
using System.Linq;
+using System.Application.Models.Settings;
+using System.Application.UI.Resx;
#if WINDOWS
using System.Windows.Shell;
using WpfApplication = System.Windows.Application;
@@ -77,6 +79,13 @@ namespace System.Application.UI
Name = ThisAssembly.AssemblyTrademark;
+ #region å�¯åŠ¨æ—¶åŠ è½½çš„èµ„æº�
+ SettingsHost.Load();
+ compositeDisposable.Add(SettingsHost.Save);
+ UISettings.Language.Subscribe(x => R.ChangeLanguage(x));
+
+ #endregion
+
MainWindow = new MainWindow
{
DataContext = new MainWindowViewModel(),
@@ -151,7 +160,6 @@ namespace System.Application.UI
{
notifyIcon.IconPath = string.Empty;
});
-
#endregion
#if WINDOWS
diff --git a/System.Application.SteamTools.Client.Desktop.Avalonia/Application/Converters/BitmapAssetValueConverter.cs b/System.Application.SteamTools.Client.Desktop.Avalonia/Application/Converters/BitmapAssetValueConverter.cs
index f2c9aa74b..95dc9310c 100644
--- a/System.Application.SteamTools.Client.Desktop.Avalonia/Application/Converters/BitmapAssetValueConverter.cs
+++ b/System.Application.SteamTools.Client.Desktop.Avalonia/Application/Converters/BitmapAssetValueConverter.cs
@@ -42,7 +42,10 @@ namespace System.Application.Converters
}
else if (value is Stream s)
{
- s.Position = 0;
+ if (s.Position > 0)
+ {
+ s.Position = 0;
+ }
return new Bitmap(s);
}
throw new NotSupportedException();
diff --git a/System.Application.SteamTools.Client.Desktop.Avalonia/Application/UI/Pages/Settings/Settings_UI.axaml b/System.Application.SteamTools.Client.Desktop.Avalonia/Application/UI/Pages/Settings/Settings_UI.axaml
index 7916d038c..a2363f99a 100644
--- a/System.Application.SteamTools.Client.Desktop.Avalonia/Application/UI/Pages/Settings/Settings_UI.axaml
+++ b/System.Application.SteamTools.Client.Desktop.Avalonia/Application/UI/Pages/Settings/Settings_UI.axaml
@@ -2,6 +2,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:System.Application.UI.ViewModels;assembly=System.Application.SteamTools.Client.Desktop"
xmlns:resx="clr-namespace:System.Application.UI.Resx;assembly=System.Application.SteamTools.Client.Desktop"
+ xmlns:ms="clr-namespace:System.Application.Models.Settings;assembly=System.Application.SteamTools.Client.Desktop"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
@@ -14,7 +15,7 @@
@@ -32,7 +33,7 @@
-
+
\ No newline at end of file
diff --git a/System.Application.SteamTools.Client.Desktop.Avalonia/Application/UI/Pages/SteamAccountPage.axaml b/System.Application.SteamTools.Client.Desktop.Avalonia/Application/UI/Pages/SteamAccountPage.axaml
index 830bb72c9..b20b0da0d 100644
--- a/System.Application.SteamTools.Client.Desktop.Avalonia/Application/UI/Pages/SteamAccountPage.axaml
+++ b/System.Application.SteamTools.Client.Desktop.Avalonia/Application/UI/Pages/SteamAccountPage.axaml
@@ -38,8 +38,8 @@
IsVisible="{Binding AvatarStream,Converter={StaticResource IsNullConverter},ConverterParameter=invert}"/>
-
-
+
+
TaskLog.Raise(new TaskLog(callerMemberName, callerFilePath, callerLineNumber, x.Exception)),
+ TaskContinuationOptions.OnlyOnFaulted);
+ }
+
+ public static void ForgetAndDispose(
+ this Task task,
+ [CallerMemberName] string callerMemberName = "",
+ [CallerFilePath] string callerFilePath = "",
+ [CallerLineNumber] int callerLineNumber = 0)
+ {
+ task.ContinueWith(
+ x => TaskLog.Raise(new TaskLog(callerMemberName, callerFilePath, callerLineNumber, x.Exception)),
+ TaskContinuationOptions.OnlyOnFaulted).ContinueWith(s=>s.Dispose());
+ }
+
+ public static Task WhenAll(this IEnumerable tasks)
+ {
+ return Task.WhenAll(tasks);
+ }
+
+ public static Task WhenAll(this IEnumerable> tasks)
+ {
+ return Task.WhenAll(tasks);
+ }
+ }
+
+ public class TaskLog
+ {
+ public string CallerMemberName { get; }
+
+ public string CallerFilePath { get; }
+
+ public int CallerLineNumber { get; }
+
+ public Exception Exception { get; }
+
+ public TaskLog(string callerMemberName, string callerFilePath, int callerLineNumber, Exception exception)
+ {
+ this.CallerMemberName = callerMemberName;
+ this.CallerFilePath = callerFilePath;
+ this.CallerLineNumber = callerLineNumber;
+ this.Exception = exception;
+ }
+
+
+ public static EventHandler Occured = (sender, e) =>
+ {
+ const string format = @"Unhandled Exception occured from Task.Forget()
+-----------
+Caller file : {1}
+ : line {2}
+Caller member: {0}
+Exception: {3}
+
+";
+ System.Diagnostics.Debug.WriteLine(format, e.CallerMemberName, e.CallerFilePath, e.CallerLineNumber, e.Exception);
+ };
+
+ internal static void Raise(TaskLog log)
+ {
+ Occured?.Invoke(typeof(TaskLog), log);
+ }
+ }
+}
diff --git a/System.Application.SteamTools.Client.Desktop/Models/TextReaderProvider.cs b/System.Application.SteamTools.Client.Desktop/Models/Enum/TextReaderProvider.cs
similarity index 100%
rename from System.Application.SteamTools.Client.Desktop/Models/TextReaderProvider.cs
rename to System.Application.SteamTools.Client.Desktop/Models/Enum/TextReaderProvider.cs
diff --git a/System.Application.SteamTools.Client.Desktop/Models/AppUserSettings.cs b/System.Application.SteamTools.Client.Desktop/Models/Settings/AppUserSettings.cs
similarity index 69%
rename from System.Application.SteamTools.Client.Desktop/Models/AppUserSettings.cs
rename to System.Application.SteamTools.Client.Desktop/Models/Settings/AppUserSettings.cs
index ef83e6c6c..a04658d83 100644
--- a/System.Application.SteamTools.Client.Desktop/Models/AppUserSettings.cs
+++ b/System.Application.SteamTools.Client.Desktop/Models/Settings/AppUserSettings.cs
@@ -24,18 +24,4 @@ namespace System.Application.Models
///
public Dictionary? TextReaderProvider { get; set; }
}
-
-#if DEBUG
-
- [Obsolete("use AppUserSettings", true)]
- public class SettingsModel
- {
- [Obsolete("use AppUserSettings.StartupArgs", true)]
- public string? SteamRunParam { get; set; }
-
- [Obsolete("use AppUserSettings.EnableTextLog", true)]
- public bool EnableTextLog { get; set; }
- }
-
-#endif
}
\ No newline at end of file
diff --git a/System.Application.SteamTools.Client.Desktop/Models/Settings/AuthSettings.cs b/System.Application.SteamTools.Client.Desktop/Models/Settings/AuthSettings.cs
new file mode 100644
index 000000000..025104c58
--- /dev/null
+++ b/System.Application.SteamTools.Client.Desktop/Models/Settings/AuthSettings.cs
@@ -0,0 +1,46 @@
+using System;
+using System.Application.Serialization;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Threading.Tasks;
+
+namespace System.Application.Models.Settings
+{
+ public static class AuthSettings
+ {
+ static AuthSettings()
+ {
+ Authenticators.ValueChanged += Authenticators_ValueChanged;
+ }
+
+ private static void Authenticators_ValueChanged(object sender, ValueChangedEventArgs e)
+ {
+ if (e.NewValue != e.OldValue)
+ {
+ if (AuthSettings.IsCurrentDirectorySaveAuthData.Value)
+ {
+ File.WriteAllText(Path.Combine(AppContext.BaseDirectory, Constants.AUTHDATA_FILE), e.NewValue);
+ }
+ }
+ }
+
+ ///
+ /// ÁîÅÆÊý¾Ý(ѹËõ´æ´¢£©
+ ///
+ public static SerializableProperty Authenticators { get; }
+ = new SerializableProperty(GetKey(), Providers.Local) { AutoSave = true };
+
+ ///
+ /// ÊÇ·ñ½«ÁîÅÆÊý¾Ý´æ´¢ÔÚ³ÌÐò·¾¶ÏÂ
+ ///
+ public static SerializableProperty IsCurrentDirectorySaveAuthData { get; }
+ = new SerializableProperty(GetKey(), Providers.Local, false) { AutoSave = true };
+
+ private static string GetKey([CallerMemberName] string propertyName = "")
+ {
+ return nameof(AuthSettings) + "." + propertyName;
+ }
+ }
+}
diff --git a/System.Application.SteamTools.Client.Desktop/Models/Settings/GeneralSettings.cs b/System.Application.SteamTools.Client.Desktop/Models/Settings/GeneralSettings.cs
new file mode 100644
index 000000000..6c74ef0de
--- /dev/null
+++ b/System.Application.SteamTools.Client.Desktop/Models/Settings/GeneralSettings.cs
@@ -0,0 +1,76 @@
+using System;
+using System.Application.Serialization;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Threading.Tasks;
+
+namespace System.Application.Models.Settings
+{
+ public static class GeneralSettings
+ {
+ static GeneralSettings()
+ {
+ WindowsStartupAutoRun.ValueChanged += WindowsStartupAutoRun_ValueChanged;
+ IsEnableLogRecord.ValueChanged += IsEnableLogRecord_ValueChanged;
+ //CreateDesktopShortcut.ValueChanged += CreateDesktopShortcut_ValueChanged;
+ }
+
+ private static void IsEnableLogRecord_ValueChanged(object sender, ValueChangedEventArgs e)
+ {
+
+ }
+
+ private static void WindowsStartupAutoRun_ValueChanged(object sender, ValueChangedEventArgs e)
+ {
+
+ }
+
+ ///
+ /// ³ÌÐòÊÇ·ñ¿ª»ú×ÔÆô¶¯
+ ///
+ public static SerializableProperty WindowsStartupAutoRun { get; }
+ = new SerializableProperty(GetKey(), Providers.Local, false) { AutoSave = true };
+
+ /////
+ ///// ´´½¨×ÀÃæ¿ì½Ý·½Ê½
+ /////
+ //public static SerializableProperty CreateDesktopShortcut { get; }
+ // = new SerializableProperty(GetKey(), Providers.Roaming, false) { AutoSave = true };
+
+ ///
+ /// ³ÌÐòÆô¶¯Ê±×îС»¯
+ ///
+ public static SerializableProperty IsStartupAppMinimized { get; }
+ = new SerializableProperty(GetKey(), Providers.Local, false) { AutoSave = true };
+
+ ///
+ /// ÊÇ·ñÏÔʾÆðʼҳ
+ ///
+ public static SerializableProperty IsShowStartPage { get; }
+ = new SerializableProperty(GetKey(), Providers.Local, true) { AutoSave = true };
+
+ ///
+ /// ÆôÓÃÓÎÏ·ÁÐ±í±¾µØ»º´æ
+ ///
+ public static SerializableProperty IsSteamAppListLocalCache { get; }
+ = new SerializableProperty(GetKey(), Providers.Local, true) { AutoSave = true };
+
+ ///
+ /// ×Ô¶¯¼ì²é¸üÐÂ
+ ///
+ public static SerializableProperty IsAutoCheckUpdate { get; }
+ = new SerializableProperty(GetKey(), Providers.Local, true) { AutoSave = true };
+
+ ///
+ /// ÆôÓôíÎóÈÕÖ¾¼Ç¼
+ ///
+ public static SerializableProperty IsEnableLogRecord { get; }
+ = new SerializableProperty(GetKey(), Providers.Local, false) { AutoSave = true };
+
+ private static string GetKey([CallerMemberName] string propertyName = "")
+ {
+ return nameof(GeneralSettings) + "." + propertyName;
+ }
+ }
+}
diff --git a/System.Application.SteamTools.Client.Desktop/Models/Settings/SettingsHost.cs b/System.Application.SteamTools.Client.Desktop/Models/Settings/SettingsHost.cs
new file mode 100644
index 000000000..461deb669
--- /dev/null
+++ b/System.Application.SteamTools.Client.Desktop/Models/Settings/SettingsHost.cs
@@ -0,0 +1,90 @@
+using System;
+using System.Application.Serialization;
+using System.Application.Services;
+using System.Collections.Generic;
+using System.IO;
+using System.Runtime.CompilerServices;
+using System.Text;
+
+namespace System.Application.Models.Settings
+{
+ public abstract class SettingsHost
+ {
+ private static readonly Dictionary instances = new();
+ private readonly Dictionary cachedProperties = new();
+
+ protected virtual string CategoryName => this.GetType().Name;
+
+ protected SettingsHost()
+ {
+ instances[this.GetType()] = this;
+ }
+
+ ///
+ /// 请å�‚阅 缓å˜åœ¨å½“å‰�实例ä¸èŽ·å�–
+ /// 如果没有缓å˜ï¼Œæ ¹æ�®åˆ›å»ºå®ƒ
+ ///
+ ///
+ protected SerializableProperty Cache(Func> create, [CallerMemberName] string propertyName = "")
+ {
+ var key = this.CategoryName + "." + propertyName;
+
+ if (this.cachedProperties.TryGetValue(key, out object obj) && obj is SerializableProperty property1)
+ return property1;
+
+ var property = create(key);
+ this.cachedProperties[key] = property;
+
+ return property;
+ }
+
+ #region Load / Save
+
+ public static void Load()
+ {
+ try
+ {
+ Providers.Local.Load();
+ }
+ catch (Exception ex)
+ {
+ Log.Error(nameof(SettingsHost), "Config Load", ex);
+
+ File.Delete(Providers.LocalFilePath);
+ Providers.Local.Load();
+ }
+
+ }
+
+ public static void Save()
+ {
+ try
+ {
+ Providers.Local.Save();
+ }
+ catch (Exception ex)
+ {
+ Log.Error(nameof(SettingsHost), "Config Save", ex);
+ throw;
+ }
+
+ }
+
+ #endregion
+
+ ///
+ /// 获�类型的�置对象的唯一实例。
+ ///
+ public static T Instance() where T : SettingsHost, new()
+ {
+ return instances.TryGetValue(typeof(T), out SettingsHost host) ? (T)host : new T();
+ }
+ }
+
+ public class Providers
+ {
+ public static string LocalFilePath => Path.Combine(IOPath.AppDataDirectory, IConfigFileService.ConfigFileName);
+
+ public static ISerializationProvider Local { get; } = new FileSettingsProvider(LocalFilePath);
+ }
+}
diff --git a/System.Application.SteamTools.Client.Desktop/Models/Settings/SteamSettings.cs b/System.Application.SteamTools.Client.Desktop/Models/Settings/SteamSettings.cs
new file mode 100644
index 000000000..17cafd8eb
--- /dev/null
+++ b/System.Application.SteamTools.Client.Desktop/Models/Settings/SteamSettings.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Application.Serialization;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Threading.Tasks;
+
+namespace System.Application.Models.Settings
+{
+ public static class SteamSettings
+ {
+ ///
+ /// SteamÆô¶¯²ÎÊý
+ ///
+ public static SerializableProperty SteamStratParameter { get; }
+ = new SerializableProperty(GetKey(), Providers.Local, string.Empty) { AutoSave = true };
+
+ ///
+ /// SteamƤ·ô
+ ///
+ public static SerializableProperty SteamSkin { get; }
+ = new SerializableProperty(GetKey(), Providers.Local, string.Empty) { AutoSave = true };
+
+ ///
+ /// ×Ô¶¯ÔËÐÐSteam
+ ///
+ public static SerializableProperty IsAutoRunSteam { get; }
+ = new SerializableProperty(GetKey(), Providers.Local, false) { AutoSave = true };
+
+ ///
+ /// ¼ì²âµ½SteamÆô¶¯Ê±µ¯³öÏûϢ֪ͨ
+ ///
+ public static SerializableProperty IsEnableSteamLaunchNotification { get; }
+ = new SerializableProperty(GetKey(), Providers.Local, false) { AutoSave = true };
+
+ private static string GetKey([CallerMemberName] string propertyName = "")
+ {
+ return nameof(SteamSettings) + "." + propertyName;
+ }
+ }
+}
diff --git a/System.Application.SteamTools.Client.Desktop/Models/Settings/UISettings.cs b/System.Application.SteamTools.Client.Desktop/Models/Settings/UISettings.cs
new file mode 100644
index 000000000..5fc9e0d37
--- /dev/null
+++ b/System.Application.SteamTools.Client.Desktop/Models/Settings/UISettings.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Application.Serialization;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Threading.Tasks;
+
+namespace System.Application.Models.Settings
+{
+ public static class UISettings
+ {
+ ///
+ /// Ö÷Ìâ
+ ///
+ public static SerializableProperty Theme { get; }
+ = new SerializableProperty(GetKey(), Providers.Local) { AutoSave = true };
+
+ ///
+ /// ÓïÑÔ
+ ///
+ public static SerializableProperty Language { get; }
+ = new SerializableProperty(GetKey(), Providers.Local) { AutoSave = true };
+
+
+
+ private static string GetKey([CallerMemberName] string propertyName = "")
+ {
+ return nameof(UISettings) + "." + propertyName;
+ }
+ }
+}
diff --git a/System.Application.SteamTools.Client.Desktop/Serialization/ApplicationSettingsProvider.cs b/System.Application.SteamTools.Client.Desktop/Serialization/ApplicationSettingsProvider.cs
new file mode 100644
index 000000000..1844d90b3
--- /dev/null
+++ b/System.Application.SteamTools.Client.Desktop/Serialization/ApplicationSettingsProvider.cs
@@ -0,0 +1,94 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Configuration;
+using System.Linq;
+
+namespace System.Application.Serialization
+{
+ public class ApplicationSettingsProvider : ApplicationSettingsBase, ISerializationProvider
+ {
+ public static ISerializationProvider Default { get; } = new ApplicationSettingsProvider(typeof(ApplicationSettingsProvider).FullName + "." + nameof(Default));
+
+ public bool IsLoaded { get; private set; }
+
+ // UserScopedSettings 除�至少有一个,�则似乎�会读�LocalFileSettingsProvider
+ // ReSharper disable once InconsistentNaming
+ // ReSharper disable once UnassignedGetOnlyAutoProperty
+ [UserScopedSetting, EditorBrowsable(EditorBrowsableState.Never)]
+ public object __Infrastructure { get; }
+
+ public ApplicationSettingsProvider() { }
+
+ public ApplicationSettingsProvider(string settingsKey) : base(settingsKey) { }
+
+ public void SetValue(string key, T value)
+ {
+ this.AddProperty(key, typeof(T));
+ this[key] = value;
+ }
+
+ public bool TryGetValue(string key, out T value)
+ {
+ this.AddProperty(key, typeof(T));
+
+ try
+ {
+ value = (T)this[key];
+ return true;
+ }
+ catch
+ {
+ value = default(T);
+ return false;
+ }
+ }
+
+ public bool RemoveValue(string key)
+ {
+ return this.RemoveProperry(key);
+ }
+
+ private void AddProperty(string key, Type type)
+ {
+ if (this.Properties.OfType().All(x => x.Name != key))
+ {
+ var property = new SettingsProperty(key)
+ {
+ PropertyType = type,
+ Provider = this.Providers.OfType().FirstOrDefault(),
+ SerializeAs = SettingsSerializeAs.Xml,
+ };
+ property.Attributes.Add(typeof(UserScopedSettingAttribute), new UserScopedSettingAttribute());
+
+ this.Properties.Add(property);
+ this.Reload();
+ }
+ }
+
+ private bool RemoveProperry(string key)
+ {
+ if (this.Properties.OfType().All(x => x.Name != key))
+ {
+ return false;
+ }
+
+ this.Properties.Remove(key);
+ this.Reload();
+
+ return true;
+ }
+
+ void ISerializationProvider.Load()
+ {
+ this.Reload();
+ this.IsLoaded = true;
+ }
+
+ event EventHandler ISerializationProvider.Reloaded
+ {
+ add { }
+ remove { }
+ }
+ }
+}
diff --git a/System.Application.SteamTools.Client.Desktop/Serialization/FileSettingsProvider.cs b/System.Application.SteamTools.Client.Desktop/Serialization/FileSettingsProvider.cs
new file mode 100644
index 000000000..aeec29e7d
--- /dev/null
+++ b/System.Application.SteamTools.Client.Desktop/Serialization/FileSettingsProvider.cs
@@ -0,0 +1,115 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+
+namespace System.Application.Serialization
+{
+ public class FileSettingsProvider : ISerializationProvider
+ {
+ private readonly string _path;
+ private readonly object _sync = new object();
+ private SortedDictionary _settings = new SortedDictionary();
+
+ public bool IsLoaded { get; private set; }
+
+
+ public FileSettingsProvider(string path)
+ {
+ this._path = path;
+ }
+
+ public void SetValue(string key, T value)
+ {
+ lock (this._sync)
+ {
+ this._settings[key] = value;
+ }
+ }
+
+ public bool TryGetValue(string key, out T value)
+ {
+ lock (this._sync)
+ {
+ object obj;
+ if (this._settings.TryGetValue(key, out obj) && obj is T)
+ {
+ value = (T)obj;
+ return true;
+ }
+ }
+
+ value = default(T);
+ return false;
+ }
+
+ public bool RemoveValue(string key)
+ {
+ lock (this._sync)
+ {
+ return this._settings.Remove(key);
+ }
+ }
+
+ public void Save()
+ {
+ if (this._settings.Count == 0) return;
+
+ var dir = Path.GetDirectoryName(this._path);
+ if (dir == null) throw new DirectoryNotFoundException();
+
+ if (!Directory.Exists(dir))
+ {
+ Directory.CreateDirectory(dir);
+ }
+
+ lock (this._sync)
+ {
+ using var stream = new FileStream(this._path, FileMode.Create, FileAccess.ReadWrite);
+ if (stream.Position > 0)
+ {
+ stream.Position = 0;
+ }
+ var data = Serializable.SMP(this._settings);
+ stream.Write(data, 0, data.Length);
+ //XamlServices.Save(stream, this._settings);
+ }
+ }
+
+ public void Load()
+ {
+ if (File.Exists(this._path))
+ {
+ using var stream = new FileStream(this._path, FileMode.Open, FileAccess.Read);
+ lock (this._sync)
+ {
+ if (stream.Position > 0)
+ {
+ stream.Position = 0;
+ }
+
+ var source = Serializable.DMP>(stream);
+ //var source = XamlServices.Load(stream) as IDictionary;
+ this._settings = source == null
+ ? new SortedDictionary()
+ : new SortedDictionary(source);
+ }
+ }
+ else
+ {
+ lock (this._sync)
+ {
+ this._settings = new SortedDictionary();
+ }
+ }
+
+ this.IsLoaded = true;
+ }
+
+ event EventHandler ISerializationProvider.Reloaded
+ {
+ add { }
+ remove { }
+ }
+ }
+}
diff --git a/System.Application.SteamTools.Client.Desktop/Serialization/ISerializationProvider.cs b/System.Application.SteamTools.Client.Desktop/Serialization/ISerializationProvider.cs
new file mode 100644
index 000000000..ba619283d
--- /dev/null
+++ b/System.Application.SteamTools.Client.Desktop/Serialization/ISerializationProvider.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace System.Application.Serialization
+{
+ public interface ISerializationProvider
+ {
+ bool IsLoaded { get; }
+
+ void Save();
+
+ void Load();
+
+ ///
+ /// ÔÚproviderÒÑÖØÐ¼ÓÔØµ½ÆÚʱ·¢Éú
+ ///
+ event EventHandler Reloaded;
+
+ void SetValue(string key, T value);
+
+ bool TryGetValue(string key, out T value);
+
+ bool RemoveValue(string key);
+ }
+}
diff --git a/System.Application.SteamTools.Client.Desktop/Serialization/SerializableProperty.cs b/System.Application.SteamTools.Client.Desktop/Serialization/SerializableProperty.cs
new file mode 100644
index 000000000..a48062222
--- /dev/null
+++ b/System.Application.SteamTools.Client.Desktop/Serialization/SerializableProperty.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace System.Application.Serialization
+{
+ public sealed class SerializableProperty : SerializablePropertyBase
+ {
+ public SerializableProperty(string key) : this(key, default(T)) { }
+
+ public SerializableProperty(string key, T defaultValue) : base(key, ApplicationSettingsProvider.Default, defaultValue) { }
+
+ public SerializableProperty(string key, ISerializationProvider provider) : base(key, provider) { }
+
+ public SerializableProperty(string key, ISerializationProvider provider, T defaultValue) : base(key, provider, defaultValue) { }
+ }
+}
diff --git a/System.Application.SteamTools.Client.Desktop/Serialization/SerializablePropertyBase.cs b/System.Application.SteamTools.Client.Desktop/Serialization/SerializablePropertyBase.cs
new file mode 100644
index 000000000..cfa70ac1a
--- /dev/null
+++ b/System.Application.SteamTools.Client.Desktop/Serialization/SerializablePropertyBase.cs
@@ -0,0 +1,194 @@
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Diagnostics;
+
+namespace System.Application.Serialization
+{
+ [DebuggerDisplay("Value={Value}, Key={Key}, Default={Default}")]
+ public abstract class SerializablePropertyBase : INotifyPropertyChanged
+ {
+ private T _value;
+ private bool _cached;
+
+ public string Key { get; }
+
+ public ISerializationProvider Provider { get; }
+
+ public bool AutoSave { get; set; }
+
+ public T Default { get; }
+
+ public virtual T Value
+ {
+ get
+ {
+ if (this._cached) return this._value;
+
+ if (!this.Provider.IsLoaded)
+ {
+ this.Provider.Load();
+ }
+
+ object obj;
+ if (this.Provider.TryGetValue(this.Key, out obj))
+ {
+ this._value = this.DeserializeCore(obj);
+ this._cached = true;
+ }
+ else
+ {
+ this._value = this.Default;
+ }
+
+ return this._cached ? this._value : this.Default;
+ }
+ set
+ {
+ if (this._cached && Equals(this._value, value)) return;
+
+ if (!this.Provider.IsLoaded)
+ {
+ this.Provider.Load();
+ }
+
+ var old = this._value;
+ this._value = value;
+ this._cached = true;
+ this.Provider.SetValue(this.Key, this.SerializeCore(value));
+ this.OnValueChanged(old, value);
+
+ if (this.AutoSave) this.Provider.Save();
+ }
+ }
+
+ protected SerializablePropertyBase(string key, ISerializationProvider provider) : this(key, provider, default(T)) { }
+
+ protected SerializablePropertyBase(string key, ISerializationProvider provider, T defaultValue)
+ {
+ if (key == null) throw new ArgumentNullException(nameof(key));
+ if (provider == null) throw new ArgumentNullException(nameof(provider));
+
+ this.Key = key;
+ this.Provider = provider;
+ this.Default = defaultValue;
+
+ this.Provider.Reloaded += (sender, args) =>
+ {
+ if (this._cached)
+ {
+ this._cached = false;
+
+ var oldValue = this._value;
+ var newValue = this.Value;
+ if (!Equals(oldValue, newValue))
+ {
+ this.OnValueChanged(oldValue, newValue);
+ }
+ }
+ else
+ {
+ var oldValue = default(T);
+ var newValue = this.Value;
+ this.OnValueChanged(oldValue, newValue);
+ }
+ };
+ }
+
+
+ protected virtual object SerializeCore(T value)
+ {
+ return value;
+ }
+
+ protected virtual T DeserializeCore(object value)
+ {
+ return (T)value;
+ }
+
+
+ public virtual IDisposable Subscribe(Action listener)
+ {
+ listener(this.Value);
+ return new ValueChangedEventListener(this, listener);
+ }
+
+ public virtual void Reset()
+ {
+ if (!this.Provider.IsLoaded)
+ {
+ this.Provider.Load();
+ }
+
+ object old;
+ if (this.Provider.TryGetValue(this.Key, out old))
+ {
+ if (this.Provider.RemoveValue(this.Key))
+ {
+ this._value = default(T);
+ this._cached = false;
+ this.OnValueChanged(this.DeserializeCore(old), this.Default);
+
+ if (this.AutoSave) this.Provider.Save();
+ }
+ }
+ }
+
+ private class ValueChangedEventListener : IDisposable
+ {
+ private readonly Action _listener;
+ private readonly SerializablePropertyBase _source;
+
+ public ValueChangedEventListener(SerializablePropertyBase property, Action listener)
+ {
+ this._listener = listener;
+ this._source = property;
+ this._source.ValueChanged += this.HandleValueChanged;
+ }
+
+ private void HandleValueChanged(object sender, ValueChangedEventArgs args)
+ {
+ this._listener(args.NewValue);
+ }
+
+ public void Dispose()
+ {
+ this._source.ValueChanged -= this.HandleValueChanged;
+ }
+ }
+
+
+ public static implicit operator T(SerializablePropertyBase property)
+ {
+ return property.Value;
+ }
+
+
+ #region events
+
+ public event EventHandler> ValueChanged;
+
+ protected virtual void OnValueChanged(T oldValue, T newValue)
+ {
+ this.ValueChanged?.Invoke(this, new ValueChangedEventArgs(oldValue, newValue));
+ }
+
+ private readonly Dictionary>> _handlers
+ = new Dictionary>>();
+
+ event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged
+ {
+ add { this.ValueChanged += (this._handlers[value] = (sender, args) => value(sender, new PropertyChangedEventArgs(nameof(this.Value)))); }
+ remove
+ {
+ EventHandler> handler;
+ if (this._handlers.TryGetValue(value, out handler))
+ {
+ this.ValueChanged -= handler;
+ this._handlers.Remove(value);
+ }
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/System.Application.SteamTools.Client.Desktop/Serialization/ValueChangedEventArgs.cs b/System.Application.SteamTools.Client.Desktop/Serialization/ValueChangedEventArgs.cs
new file mode 100644
index 000000000..7a3adfc1b
--- /dev/null
+++ b/System.Application.SteamTools.Client.Desktop/Serialization/ValueChangedEventArgs.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace System.Application.Serialization
+{
+ public class ValueChangedEventArgs : EventArgs
+ {
+ public T OldValue { get; }
+ public T NewValue { get; }
+
+ public ValueChangedEventArgs(T oldValue, T newValue)
+ {
+ this.OldValue = oldValue;
+ this.NewValue = newValue;
+ }
+ }
+}
\ No newline at end of file
diff --git a/System.Application.SteamTools.Client.Desktop/Services/IConfigFileService.cs b/System.Application.SteamTools.Client.Desktop/Services/IConfigFileService.cs
index bf8955e41..eb74b3919 100644
--- a/System.Application.SteamTools.Client.Desktop/Services/IConfigFileService.cs
+++ b/System.Application.SteamTools.Client.Desktop/Services/IConfigFileService.cs
@@ -23,21 +23,4 @@ namespace System.Application.Services
public static IConfigFileService Instance => DI.Get();
}
-
-#if DEBUG
-
- [Obsolete("use IConfigFileService.Instance", true)]
- public class ConfigService
- {
- [Obsolete("use IConfigFileService.Instance.UserSettings", true)]
- public SettingsModel? SteamToolModel { get; set; }
-
- [Obsolete("use IConfigFileService.Instance.SaveChanges", true)]
- public void SaveConfig() => throw new NotImplementedException();
-
- [Obsolete("changedAutoRead", true)]
- public SettingsModel ReadConfig() => throw new NotImplementedException();
- }
-
-#endif
}
\ No newline at end of file
diff --git a/System.Application.SteamTools.Client.Desktop/System.Application.SteamTools.Client.Desktop.csproj b/System.Application.SteamTools.Client.Desktop/System.Application.SteamTools.Client.Desktop.csproj
index 0a5c822d0..1bece56d8 100644
--- a/System.Application.SteamTools.Client.Desktop/System.Application.SteamTools.Client.Desktop.csproj
+++ b/System.Application.SteamTools.Client.Desktop/System.Application.SteamTools.Client.Desktop.csproj
@@ -22,6 +22,7 @@
+
diff --git a/System.Application.SteamTools.Client.Desktop/UI/Resx/AppResources.Designer.cs b/System.Application.SteamTools.Client.Desktop/UI/Resx/AppResources.Designer.cs
index 03fd76a36..ee1e54026 100644
--- a/System.Application.SteamTools.Client.Desktop/UI/Resx/AppResources.Designer.cs
+++ b/System.Application.SteamTools.Client.Desktop/UI/Resx/AppResources.Designer.cs
@@ -288,6 +288,15 @@ namespace System.Application.UI.Resx {
///
/// 查找类似 以该账å�·ç™»å½•Steam 的本地化å—符串。
///
+ public static string UserChange_BtnText {
+ get {
+ return ResourceManager.GetString("UserChange_BtnText", resourceCulture);
+ }
+ }
+
+ ///
+ /// 查找类似 æŒ‰ä¸‹æ¤æŒ‰é’®å°†é‡�å�¯Steam并以该账å�·ç™»å½• 的本地化å—符串。
+ ///
public static string UserChange_BtnTootlip {
get {
return ResourceManager.GetString("UserChange_BtnTootlip", resourceCulture);
diff --git a/System.Application.SteamTools.Client.Desktop/UI/Resx/AppResources.resx b/System.Application.SteamTools.Client.Desktop/UI/Resx/AppResources.resx
index c9761f6fa..e8b69cd08 100644
--- a/System.Application.SteamTools.Client.Desktop/UI/Resx/AppResources.resx
+++ b/System.Application.SteamTools.Client.Desktop/UI/Resx/AppResources.resx
@@ -192,9 +192,12 @@
本地令牌
-
+
以该账�登录Steam
+
+ æŒ‰ä¸‹æ¤æŒ‰é’®å°†é‡�å�¯Steam并以该账å�·ç™»å½•
+
账�切�
diff --git a/System.Application.SteamTools.Client.Desktop/UI/Resx/R.cs b/System.Application.SteamTools.Client.Desktop/UI/Resx/R.cs
index f7dc86d83..9ec45234c 100644
--- a/System.Application.SteamTools.Client.Desktop/UI/Resx/R.cs
+++ b/System.Application.SteamTools.Client.Desktop/UI/Resx/R.cs
@@ -18,6 +18,8 @@ namespace System.Application.UI.Resx
public static readonly IList> Languages;
public static readonly Dictionary SteamLanguages;
+ public AppResources Res { get; set; } = new AppResources();
+
public static CultureInfo DefaultCurrentUICulture { get; }
static R()
@@ -43,6 +45,8 @@ namespace System.Application.UI.Resx
{ "ja", "japanese" },
{ "ru", "russian" },
};
+
+ AppResources.Culture = DefaultCurrentUICulture;
}
static bool IsMatch(CultureInfo cultureInfo, string cultureName)
@@ -67,15 +71,19 @@ namespace System.Application.UI.Resx
///
public static void ChangeLanguage(string cultureName)
{
- void ChangeLanguage()
- {
- if (IsMatch(CultureInfo.CurrentUICulture, cultureName)) return;
- CultureInfo.CurrentUICulture = CultureInfo.GetCultureInfo(cultureName);
- AppResources.Culture = CultureInfo.GetCultureInfo(cultureName);
- Current.Res = new AppResources();
- Current.RaisePropertyChanged(nameof(Res));
- }
- MainThreadDesktop.BeginInvokeOnMainThread(ChangeLanguage);
+ //void ChangeLanguage()
+ //{
+ if (IsMatch(CultureInfo.CurrentUICulture, cultureName)) return;
+ // CultureInfo.CurrentUICulture = CultureInfo.GetCultureInfo(cultureName);
+ if (string.IsNullOrWhiteSpace(cultureName))
+ AppResources.Culture = null;
+ else
+ AppResources.Culture = CultureInfo.GetCultureInfo(Languages.SingleOrDefault(x => x.Key == cultureName).Key);
+ //AppResources.Culture = CultureInfo.GetCultureInfo(cultureName);
+ Current.Res = new AppResources();
+ Current.RaisePropertyChanged(nameof(Res));
+ //}
+ //MainThreadDesktop.BeginInvokeOnMainThread(ChangeLanguage);
}
public static string GetCurrentCultureSteamLanguageName()
@@ -83,7 +91,5 @@ namespace System.Application.UI.Resx
return AppResources.Culture == null ? Languages.First().Value : SteamLanguages[AppResources.Culture.Name];
}
- //public AppResources Res => new AppResources();
- public AppResources Res { get; set; } = new AppResources();
}
}
\ No newline at end of file
diff --git a/System.Application.SteamTools.Client.Desktop/UI/ViewModels/MainWindowViewModel.cs b/System.Application.SteamTools.Client.Desktop/UI/ViewModels/MainWindowViewModel.cs
index 81ec30657..ad94f02b8 100644
--- a/System.Application.SteamTools.Client.Desktop/UI/ViewModels/MainWindowViewModel.cs
+++ b/System.Application.SteamTools.Client.Desktop/UI/ViewModels/MainWindowViewModel.cs
@@ -1,4 +1,6 @@
using ReactiveUI;
+using System.Application.Models.Settings;
+using System.Application.UI.Resx;
using System.Collections.Generic;
using System.Linq;
using System.Properties;
@@ -58,8 +60,6 @@ namespace System.Application.UI.ViewModels
(this.ASFPage = new ArchiSteamFarmPlusPageViewModel().AddTo(this)),
(this.GameRelatedPage = new GameRelatedPageViewModel().AddTo(this)),
(this.OtherPlatformPage = new OtherPlatformPageViewModel().AddTo(this)),
-
-
#region SystemTab
SettingsPageViewModel.Instance,
@@ -72,15 +72,7 @@ namespace System.Application.UI.ViewModels
this.SelectedItem = this.TabItems.First();
- if (ViewModelBase.IsInDesignMode)
- {
- return;
- }
- Task.Run(Initialize).ContinueWith(s =>
- {
- Log.Error(nameof(MainWindowViewModel), s.Exception, nameof(Initialize) + "Action Error");
- }, TaskContinuationOptions.OnlyOnFaulted)
- .ContinueWith(s => s.Dispose());
+ Task.Run(Initialize).ForgetAndDispose();
}
diff --git a/System.Application.SteamTools.Client.Desktop/UI/ViewModels/Pages/AboutPageViewModel.cs b/System.Application.SteamTools.Client.Desktop/UI/ViewModels/Pages/About/AboutPageViewModel.cs
similarity index 100%
rename from System.Application.SteamTools.Client.Desktop/UI/ViewModels/Pages/AboutPageViewModel.cs
rename to System.Application.SteamTools.Client.Desktop/UI/ViewModels/Pages/About/AboutPageViewModel.cs
diff --git a/System.Application.SteamTools.Client.Desktop/UI/ViewModels/Pages/Settings/SettingsPageViewModel.cs b/System.Application.SteamTools.Client.Desktop/UI/ViewModels/Pages/Settings/SettingsPageViewModel.cs
index a47793258..cdf1dbbd0 100644
--- a/System.Application.SteamTools.Client.Desktop/UI/ViewModels/Pages/Settings/SettingsPageViewModel.cs
+++ b/System.Application.SteamTools.Client.Desktop/UI/ViewModels/Pages/Settings/SettingsPageViewModel.cs
@@ -1,4 +1,5 @@
using ReactiveUI;
+using System.Application.Models.Settings;
using System.Application.UI.Resx;
using System.Collections.Generic;
using System.Linq;
@@ -15,22 +16,20 @@ namespace System.Application.UI.ViewModels
protected set { throw new NotImplementedException(); }
}
+ KeyValuePair _SelectLanguage;
+ public KeyValuePair SelectLanguage
+ {
+ get => _SelectLanguage;
+ protected set => this.RaiseAndSetIfChanged(ref _SelectLanguage, value);
+ }
+
public SettingsPageViewModel()
{
-
+ SelectLanguage = R.Languages.SingleOrDefault(x => x.Key == UISettings.Language.Value);
+ if (SelectLanguage.Key == null)
+ SelectLanguage = R.Languages.First();
+ this.WhenAnyValue(x => x.SelectLanguage)
+ .Subscribe(x => UISettings.Language.Value = x.Key);
}
-
- KeyValuePair _CurrentLanguage = R.Languages.First();
- public KeyValuePair CurrentLanguage
- {
- get => _CurrentLanguage;
- set
- {
- this.RaiseAndSetIfChanged(ref _CurrentLanguage, value);
- R.ChangeLanguage(_CurrentLanguage.Key);
- }
- }
-
-
}
}
\ No newline at end of file
diff --git a/System.Common.CoreLib/Serializable.cs b/System.Common.CoreLib/Serializable.cs
index c2c978c57..aae984114 100644
--- a/System.Common.CoreLib/Serializable.cs
+++ b/System.Common.CoreLib/Serializable.cs
@@ -1,6 +1,7 @@
using MessagePack;
using Newtonsoft.Json;
using System.Diagnostics.CodeAnalysis;
+using System.IO;
using System.Text;
using System.Text.Encodings.Web;
using System.Threading;
@@ -181,6 +182,16 @@ namespace System
public static T DMP(byte[] buffer, CancellationToken cancellationToken = default)
=> MessagePackSerializer.Deserialize(buffer, cancellationToken: cancellationToken);
+ ///
+ /// (Deserialize)MessagePack ��列化
+ ///
+ ///
+ ///
+ ///
+ [return: MaybeNull]
+ public static T DMP(Stream buffer, CancellationToken cancellationToken = default)
+ => MessagePackSerializer.Deserialize(buffer, cancellationToken: cancellationToken);
+
///
/// (Deserialize)MessagePack ��列化 + Base64Url Decode
///
diff --git a/source/SteamTools/Models/Settings/SettingsHost.cs b/source/SteamTools/Models/Settings/SettingsHost.cs
index b45de1b9e..5a4580dfb 100644
--- a/source/SteamTools/Models/Settings/SettingsHost.cs
+++ b/source/SteamTools/Models/Settings/SettingsHost.cs
@@ -26,8 +26,8 @@ namespace SteamTools.Models.Settings
}
///
- /// <请å�‚阅cref ="SerializableProperty {T}" />缓å˜åœ¨å½“å‰�实例ä¸èŽ·å�–
- /// 如果没有缓å˜ï¼Œè¯·æ ¹æ�®åˆ›å»ºå®ƒ
+ /// 请å�‚阅 缓å˜åœ¨å½“å‰�实例ä¸èŽ·å�–
+ /// 如果没有缓å˜ï¼Œè¯·æ ¹æ�®åˆ›å»ºå®ƒ
///
///
protected SerializableProperty Cache(Func> create, [CallerMemberName] string propertyName = "")
diff --git a/source/SteamTools/Views/Pages/SettingsPage.xaml b/source/SteamTools/Views/Pages/SettingsPage.xaml
index 9cece7cc9..e1e3178ea 100644
--- a/source/SteamTools/Views/Pages/SettingsPage.xaml
+++ b/source/SteamTools/Views/Pages/SettingsPage.xaml
@@ -166,7 +166,6 @@
SelectedValue="{Binding Source={x:Static ms:GeneralSettings.Culture}, Path=Value, Mode=TwoWay}"
IsReadOnly="True"
MinWidth="250" />
-