diff --git a/.editorconfig b/.editorconfig index 539bd3c28de..ce3fc3d92cf 100644 --- a/.editorconfig +++ b/.editorconfig @@ -13,11 +13,6 @@ insert_final_newline = true [*] charset = utf-8 -# 4 space indentation -[*.cs] -indent_style = space -indent_size = 4 - # Tab indentation (no size specified) [Makefile] indent_style = tab @@ -25,3 +20,208 @@ indent_style = tab [*.{js,json,xaml,axaml}] indent_style = space indent_size = 2 + +# c# 文件 +[*.cs] + +#### Core EditorConfig 选项 #### + +# 缩进和间距 +indent_size = 4 +indent_style = space +tab_width = 4 + +# 新行首选项 +end_of_line = crlf +insert_final_newline = false + +#### .NET 编码约定 #### + +# 组织 Using +dotnet_separate_import_directive_groups = false +dotnet_sort_system_directives_first = false +file_header_template = unset + +# this. 和 Me. 首选项 +dotnet_style_qualification_for_event = false:suggestion +dotnet_style_qualification_for_field = false +dotnet_style_qualification_for_method = false:suggestion +dotnet_style_qualification_for_property = false:suggestion + +# 语言关键字与 bcl 类型首选项 +dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion +dotnet_style_predefined_type_for_member_access = true:suggestion + +# 括号首选项 +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity +dotnet_style_parentheses_in_other_operators = never_if_unnecessary +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity + +# 修饰符首选项 +dotnet_style_require_accessibility_modifiers = for_non_interface_members + +# 表达式级首选项 +dotnet_style_coalesce_expression = true +dotnet_style_collection_initializer = true +dotnet_style_explicit_tuple_names = true +dotnet_style_null_propagation = true +dotnet_style_object_initializer = true +dotnet_style_operator_placement_when_wrapping = beginning_of_line +dotnet_style_prefer_auto_properties = true +dotnet_style_prefer_compound_assignment = true +dotnet_style_prefer_conditional_expression_over_assignment = true +dotnet_style_prefer_conditional_expression_over_return = true +dotnet_style_prefer_inferred_anonymous_type_member_names = true +dotnet_style_prefer_inferred_tuple_names = true +dotnet_style_prefer_is_null_check_over_reference_equality_method = true +dotnet_style_prefer_simplified_boolean_expressions = true +dotnet_style_prefer_simplified_interpolation = true + +# 字段首选项 +dotnet_style_readonly_field = true + +# 参数首选项 +dotnet_code_quality_unused_parameters = all + +# 禁止显示首选项 +dotnet_remove_unnecessary_suppression_exclusions = none + +#### c# 编码约定 #### + +# var 首选项 +csharp_style_var_elsewhere = true +csharp_style_var_for_built_in_types = true +csharp_style_var_when_type_is_apparent = true + +# Expression-bodied 成员 +csharp_style_expression_bodied_accessors = true +csharp_style_expression_bodied_constructors = false +csharp_style_expression_bodied_indexers = true +csharp_style_expression_bodied_lambdas = true +csharp_style_expression_bodied_local_functions = false +csharp_style_expression_bodied_methods = false +csharp_style_expression_bodied_operators = false +csharp_style_expression_bodied_properties = true + +# 模式匹配首选项 +csharp_style_pattern_matching_over_as_with_null_check = true +csharp_style_pattern_matching_over_is_with_cast_check = true +csharp_style_prefer_not_pattern = true +csharp_style_prefer_pattern_matching = true +csharp_style_prefer_switch_expression = true + +# Null 检查首选项 +csharp_style_conditional_delegate_call = true + +# 修饰符首选项 +csharp_prefer_static_local_function = true +csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async + +# 代码块首选项 +csharp_prefer_braces = true +csharp_prefer_simple_using_statement = true + +# 表达式级首选项 +csharp_prefer_simple_default_expression = true +csharp_style_deconstructed_variable_declaration = true +csharp_style_implicit_object_creation_when_type_is_apparent = true +csharp_style_inlined_variable_declaration = true +csharp_style_pattern_local_over_anonymous_function = true +csharp_style_prefer_index_operator = true +csharp_style_prefer_range_operator = true +csharp_style_throw_expression = true +csharp_style_unused_value_assignment_preference = discard_variable +csharp_style_unused_value_expression_statement_preference = discard_variable + +# "using" 指令首选项 +csharp_using_directive_placement = outside_namespace + +#### C# 格式规则 #### + +# 新行首选项 +csharp_new_line_before_catch = true +csharp_new_line_before_else = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_open_brace = all +csharp_new_line_between_query_expression_clauses = true + +# 缩进首选项 +csharp_indent_block_contents = true +csharp_indent_braces = false +csharp_indent_case_contents = true +csharp_indent_case_contents_when_block = true +csharp_indent_labels = one_less_than_current +csharp_indent_switch_labels = true + +# 空格键首选项 +csharp_space_after_cast = false +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_after_comma = true +csharp_space_after_dot = false +csharp_space_after_keywords_in_control_flow_statements = true +csharp_space_after_semicolon_in_for_statement = true +csharp_space_around_binary_operators = before_and_after +csharp_space_around_declaration_statements = false +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_before_comma = false +csharp_space_before_dot = false +csharp_space_before_open_square_brackets = false +csharp_space_before_semicolon_in_for_statement = false +csharp_space_between_empty_square_brackets = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_call_parameter_list_parentheses = false +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +csharp_space_between_method_declaration_name_and_open_parenthesis = false +csharp_space_between_method_declaration_parameter_list_parentheses = false +csharp_space_between_parentheses = false +csharp_space_between_square_brackets = false + +# 包装首选项 +csharp_preserve_single_line_blocks = true +csharp_preserve_single_line_statements = true + +#### 命名样式 #### + +# 命名规则 + +dotnet_naming_rule.interface_should_be_以_i_开始.severity = suggestion +dotnet_naming_rule.interface_should_be_以_i_开始.symbols = interface +dotnet_naming_rule.interface_should_be_以_i_开始.style = 以_i_开始 + +dotnet_naming_rule.类型_should_be_帕斯卡拼写法.severity = suggestion +dotnet_naming_rule.类型_should_be_帕斯卡拼写法.symbols = 类型 +dotnet_naming_rule.类型_should_be_帕斯卡拼写法.style = 帕斯卡拼写法 + +dotnet_naming_rule.非字段成员_should_be_帕斯卡拼写法.severity = suggestion +dotnet_naming_rule.非字段成员_should_be_帕斯卡拼写法.symbols = 非字段成员 +dotnet_naming_rule.非字段成员_should_be_帕斯卡拼写法.style = 帕斯卡拼写法 + +# 符号规范 + +dotnet_naming_symbols.interface.applicable_kinds = interface +dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.interface.required_modifiers = + +dotnet_naming_symbols.类型.applicable_kinds = class, struct, interface, enum +dotnet_naming_symbols.类型.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.类型.required_modifiers = + +dotnet_naming_symbols.非字段成员.applicable_kinds = property, event, method +dotnet_naming_symbols.非字段成员.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.非字段成员.required_modifiers = + +# 命名样式 + +dotnet_naming_style.帕斯卡拼写法.required_prefix = +dotnet_naming_style.帕斯卡拼写法.required_suffix = +dotnet_naming_style.帕斯卡拼写法.word_separator = +dotnet_naming_style.帕斯卡拼写法.capitalization = pascal_case + +dotnet_naming_style.以_i_开始.required_prefix = I +dotnet_naming_style.以_i_开始.required_suffix = +dotnet_naming_style.以_i_开始.word_separator = +dotnet_naming_style.以_i_开始.capitalization = pascal_case diff --git a/src/Common.CoreLib/Properties/AssemblyInfo.cs b/src/Common.CoreLib/Properties/AssemblyInfo.cs index 9c23b40dc97..a46e5f05332 100644 --- a/src/Common.CoreLib/Properties/AssemblyInfo.cs +++ b/src/Common.CoreLib/Properties/AssemblyInfo.cs @@ -1,4 +1,4 @@ -using System.Reflection; +using System.Reflection; using System.Runtime.CompilerServices; using static System.Properties.ThisAssembly; @@ -9,4 +9,5 @@ [assembly: AssemblyCopyright(AssemblyCopyright)] [assembly: AssemblyCompany(AssemblyCompany)] [assembly: AssemblyFileVersion(Version)] +[assembly: AssemblyInformationalVersion(InfoVersion)] [assembly: AssemblyVersion(Version)] \ No newline at end of file diff --git a/src/Common.CoreLib/Properties/ThisAssembly.cs b/src/Common.CoreLib/Properties/ThisAssembly.cs index 39910b3e66b..689c9d7df1a 100644 --- a/src/Common.CoreLib/Properties/ThisAssembly.cs +++ b/src/Common.CoreLib/Properties/ThisAssembly.cs @@ -1,10 +1,17 @@ -namespace System.Properties +namespace System.Properties { public static class ThisAssembly { - public const string Version = "2.0.0"; + public const string Version = "2.0.0.1"; - public static readonly Version ClientVersion = new(Version); + public const string InfoVersion = Version + "-beta"; + + static readonly Lazy mVersionDisplay = new(() => + { + Version version = new(Version); + return $"{version.ToString(3)}{(IsBetaRelease ? " β" : "")}{(version.Revision <= 0 ? "" : " rev." + version.Revision)}"; + }); + public static string VersionDisplay => mVersionDisplay.Value; /// /// 定义程序集清单的产品名自定义属性 @@ -49,5 +56,8 @@ public static class ThisAssembly false #endif ; + + static readonly Lazy mIsBetaRelease = new(() => InfoVersion.Contains("beta", StringComparison.OrdinalIgnoreCase)); + public static bool IsBetaRelease => mIsBetaRelease.Value; } } \ No newline at end of file diff --git a/src/ST.Client.Desktop.Avalonia.App/App.axaml.cs b/src/ST.Client.Desktop.Avalonia.App/App.axaml.cs index 5e3d1a741aa..c6aaf406b9b 100644 --- a/src/ST.Client.Desktop.Avalonia.App/App.axaml.cs +++ b/src/ST.Client.Desktop.Avalonia.App/App.axaml.cs @@ -312,7 +312,7 @@ void NotifyIcon_Click(object? sender, EventArgs e) RestoreMainWindow(); } - public async void SetClipboardText(string s) => await AvaloniaApplication.Current.Clipboard.SetTextAsync(s); + public async void SetClipboardText(string? s) => await Current.Clipboard.SetTextAsync(s ?? string.Empty); Window? mMainWindow; diff --git a/src/ST.Client.Desktop.Avalonia/Application/Converters/NameToFontFamilyConverter.cs b/src/ST.Client.Desktop.Avalonia/Application/Converters/NameToFontFamilyConverter.cs index 4cb88f7cbea..5933b107f2b 100644 --- a/src/ST.Client.Desktop.Avalonia/Application/Converters/NameToFontFamilyConverter.cs +++ b/src/ST.Client.Desktop.Avalonia/Application/Converters/NameToFontFamilyConverter.cs @@ -1,19 +1,52 @@ -using System.Globalization; -using System.Linq; -using Avalonia; using Avalonia.Data.Converters; using Avalonia.Media; +using System.Globalization; +using System.IO; +using System.Runtime.InteropServices; namespace System.Application.Converters { public class NameToFontFamilyConverter : IValueConverter { + static readonly Lazy lazy_has_msyh = new(() => + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + var fontsPath = Environment.GetFolderPath(Environment.SpecialFolder.Fonts); + var msyhFilePath = Path.Combine(fontsPath, "msyh.ttc"); + return File.Exists(msyhFilePath); + } + else + { + return false; + } + }); + static readonly Lazy mDefault = new(() => GetDefaultFontFamily()); + static FontFamily GetDefaultFontFamily(bool isLight = false) + { + if (lazy_has_msyh.Value) // (版权、许可)不能在非WinOS上使用 微软雅黑字体,不可将字体嵌入程序 + { + string name; + var major = Environment.OSVersion.Version.Major; + if (major > 6 || (major == 6 && Environment.OSVersion.Version.Minor >= 2)) + { + name = $"Microsoft YaHei UI{(isLight ? " Light" : "")}"; + } + else + { + name = $"Microsoft YaHei{(isLight ? " Light" : "")}"; + } + return new FontFamily(name); + } + return FontFamily.Default; + } + public object? Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (value is string s) { if (string.IsNullOrEmpty(s) || s.Equals("Default", StringComparison.OrdinalIgnoreCase)) - return FontFamily.Default; + return mDefault.Value; return FontFamily.Parse(s); } return null; diff --git a/src/ST.Client.Desktop.Avalonia/Application/UI/Styles/Controls/TextBox.xaml b/src/ST.Client.Desktop.Avalonia/Application/UI/Styles/Controls/TextBox.xaml index bdd3486df0b..bf50dc81a74 100644 --- a/src/ST.Client.Desktop.Avalonia/Application/UI/Styles/Controls/TextBox.xaml +++ b/src/ST.Client.Desktop.Avalonia/Application/UI/Styles/Controls/TextBox.xaml @@ -1,4 +1,4 @@ - @@ -25,7 +25,7 @@ - - - - - - - - - - - - Steam++ - - Tools - - 2.0 - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + Steam++ + + Tools + + 2.0 + + + + + + + + + + + + + + + + + - - - - - - + + + + + + - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/ST.Client.Desktop/Services/IDesktopAppService.cs b/src/ST.Client.Desktop/Services/IDesktopAppService.cs index fd422afce58..25ea0f61665 100644 --- a/src/ST.Client.Desktop/Services/IDesktopAppService.cs +++ b/src/ST.Client.Desktop/Services/IDesktopAppService.cs @@ -1,4 +1,4 @@ -using System.Application.Models; +using System.Application.Models; using System.Application.Mvvm; using System.Collections.Generic; using System.Windows.Input; @@ -35,7 +35,7 @@ public interface IDesktopAppService /// IReadOnlyDictionary NotifyIconMenus { get; } - void SetClipboardText(string s); + void SetClipboardText(string? s); bool IsCefInitComplete { get; } @@ -47,4 +47,4 @@ public interface IDesktopAppService /// bool HasActiveWindow(); } -} \ No newline at end of file +} diff --git a/src/ST.Client.Desktop/UI/Resx/R.cs b/src/ST.Client.Desktop/UI/Resx/R.cs index a830088abfe..457ad043062 100644 --- a/src/ST.Client.Desktop/UI/Resx/R.cs +++ b/src/ST.Client.Desktop/UI/Resx/R.cs @@ -1,4 +1,4 @@ -using ReactiveUI; +using ReactiveUI; using System.Collections.Generic; using System.Drawing; using System.Drawing.Text; @@ -53,7 +53,7 @@ static IReadOnlyCollection> GetFonts() { var culture = Culture; InstalledFontCollection ifc = new(); - var list = ifc.Families.Select(x => KeyValuePair.Create(x.GetName(culture.LCID), x.GetName(1033))).ToList(); + var list = ifc.Families.Where(x => x.IsStyleAvailable(FontStyle.Regular)).Select(x => KeyValuePair.Create(x.GetName(culture.LCID), x.GetName(1033))).ToList(); list.Insert(0, KeyValuePair.Create(AppResources.Default, "Default")); return list; } diff --git a/src/ST.Client.Desktop/UI/ViewModels/Pages/About/AboutPageViewModel.cs b/src/ST.Client.Desktop/UI/ViewModels/Pages/About/AboutPageViewModel.cs index 4db82b38186..42f6fb21867 100644 --- a/src/ST.Client.Desktop/UI/ViewModels/Pages/About/AboutPageViewModel.cs +++ b/src/ST.Client.Desktop/UI/ViewModels/Pages/About/AboutPageViewModel.cs @@ -1,9 +1,9 @@ -using ReactiveUI; +using ReactiveUI; using System.Application.Services; using System.Application.UI.Resx; -using System.CommandLine; using System.Properties; using System.Reactive; +using static System.Application.Services.CloudService.Constants; namespace System.Application.UI.ViewModels { @@ -21,19 +21,30 @@ public AboutPageViewModel() { IconKey = nameof(AboutPageViewModel).Replace("ViewModel", "Svg"); - OpenBrowserCommand = ReactiveCommand.Create( - (link) => System.Application.Services.CloudService.Constants.BrowserOpen(link)); + OpenBrowserCommand = ReactiveCommand.Create(BrowserOpen); - CopyLinkCommand = ReactiveCommand.Create( - (link) => DI.Get().SetClipboardText(link)); + CopyLinkCommand = ReactiveCommand.Create(IDesktopAppService.Instance.SetClipboardText); } public ReactiveCommand OpenBrowserCommand { get; } public ReactiveCommand CopyLinkCommand { get; } + public string VersionDisplay => ThisAssembly.VersionDisplay; - public Version ClientVersion => ThisAssembly.ClientVersion; + public string LabelVersionDisplay => (ThisAssembly.IsBetaRelease ? "Beta " : null) + "Version: "; + + public string Copyright + { + get + { + // https://www.w3cschool.cn/html/html-copyright.html + int startYear = 2020, thisYear = 2021; + var nowYear = DateTime.Now.Year; + if (nowYear < thisYear) nowYear = thisYear; + return $"© {startYear}{(nowYear == startYear ? startYear : "-" + nowYear)} {ThisAssembly.AssemblyCompany}. All Rights Reserved."; + } + } public static string RmbadminSteamLink => SteamApiUrls.MY_PROFILE_URL; @@ -46,10 +57,10 @@ public AboutPageViewModel() public static string CliencerLink => "https://space.bilibili.com/30031316"; public static string PrivacyLink => "https://steampp.net/privacy"; - public static string AgreementLink => "https://steampp.net/agreement"; + public static string AgreementLink => "https://steampp.net/agreement"; - public static string OfficialLink => "https://steampp.net/"; + public static string OfficialLink => "https://steampp.net"; public static string SourceCodeLink => "https://github.com/rmbadmin/SteamTools"; @@ -61,4 +72,4 @@ public AboutPageViewModel() public static string LicenseLink => "https://github.com/rmbadmin/SteamTools/blob/develop/LICENSE"; } -} +} \ No newline at end of file diff --git a/src/ST.Services.CloudService.Models/Services.CloudService/Constants.cs b/src/ST.Services.CloudService.Models/Services.CloudService/Constants.cs index 7055a2dd86d..236a13a83d3 100644 --- a/src/ST.Services.CloudService.Models/Services.CloudService/Constants.cs +++ b/src/ST.Services.CloudService.Models/Services.CloudService/Constants.cs @@ -1,4 +1,4 @@ -using System.Application.Properties; +using System.Application.Properties; using System.Diagnostics; using Xamarin.Essentials; @@ -70,8 +70,9 @@ public static string[] GetSplitValues(object @lock, string values, ref string? c /// 兼容 Linux/Mac/.NetCore/Android/iOS 的打开链接方法 /// /// - public static async void BrowserOpen(string url) + public static async void BrowserOpen(string? url) { + if (url == null) return; if (url.StartsWith(Prefix_HTTPS, StringComparison.OrdinalIgnoreCase) || url.StartsWith(Prefix_HTTP, StringComparison.OrdinalIgnoreCase)) { @@ -90,4 +91,4 @@ public static async void BrowserOpen(string url) } } } -} \ No newline at end of file +}