From 6936a30a74fca02c6f9f9ad928ff61634e6f5d84 Mon Sep 17 00:00:00 2001 From: qhy040404 Date: Fri, 23 Feb 2024 14:10:09 +0800 Subject: [PATCH 01/10] finish suggestion methods --- .../Snap.Hutao/Control/ScopedPage.cs | 4 +- .../Snap.Hutao/View/Page/WikiAvatarPage.xaml | 17 +++--- .../View/Page/WikiAvatarPage.xaml.cs | 15 +++++- .../Snap.Hutao/View/Page/WikiWeaponPage.xaml | 17 +++--- .../View/Page/WikiWeaponPage.xaml.cs | 15 +++++- .../ViewModel/Wiki/IAutoSuggestBoxAccessor.cs | 12 +++++ .../Wiki/IWikiViewModelInitialization.cs | 9 ++++ .../ViewModel/Wiki/WikiAvatarViewModel.cs | 54 +++++++++++++++++-- .../ViewModel/Wiki/WikiWeaponViewModel.cs | 51 ++++++++++++++++-- 9 files changed, 167 insertions(+), 27 deletions(-) create mode 100644 src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/IAutoSuggestBoxAccessor.cs create mode 100644 src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/IWikiViewModelInitialization.cs diff --git a/src/Snap.Hutao/Snap.Hutao/Control/ScopedPage.cs b/src/Snap.Hutao/Snap.Hutao/Control/ScopedPage.cs index 06db70e8..d3eac6c9 100644 --- a/src/Snap.Hutao/Snap.Hutao/Control/ScopedPage.cs +++ b/src/Snap.Hutao/Snap.Hutao/Control/ScopedPage.cs @@ -41,12 +41,14 @@ internal class ScopedPage : Page /// 应当在 InitializeComponent() 前调用 /// /// 视图模型类型 - protected void InitializeWith() + protected TViewModel InitializeWith() where TViewModel : class, IViewModel { IViewModel viewModel = currentScope.ServiceProvider.GetRequiredService(); viewModel.CancellationToken = viewCancellationTokenSource.Token; DataContext = viewModel; + + return (TViewModel)viewModel; } /// diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/WikiAvatarPage.xaml b/src/Snap.Hutao/Snap.Hutao/View/Page/WikiAvatarPage.xaml index 1bcfbd91..8be405da 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Page/WikiAvatarPage.xaml +++ b/src/Snap.Hutao/Snap.Hutao/View/Page/WikiAvatarPage.xaml @@ -73,6 +73,13 @@ + + + + @@ -266,21 +273,17 @@ - - - - - - + Text="{Binding FilterText, Mode=TwoWay}"/> public WikiAvatarPage() { - InitializeWith(); + WikiAvatarViewModel viewModel = InitializeWith(); InitializeComponent(); + + viewModel.Initialize(new AutoSuggestBoxAccessor(AvatarSuggestBox)); + } + + private class AutoSuggestBoxAccessor : IAutoSuggestBoxAccessor + { + public AutoSuggestBoxAccessor(AutoSuggestBox autoSuggestBox) + { + AutoSuggestBox = autoSuggestBox; + } + + public AutoSuggestBox AutoSuggestBox { get; private set; } } } diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/WikiWeaponPage.xaml b/src/Snap.Hutao/Snap.Hutao/View/Page/WikiWeaponPage.xaml index cef3bfa2..5358afed 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Page/WikiWeaponPage.xaml +++ b/src/Snap.Hutao/Snap.Hutao/View/Page/WikiWeaponPage.xaml @@ -32,6 +32,13 @@ Source="{Binding Converter={StaticResource PropertyDescriptor}}"/> + + + + @@ -132,20 +139,16 @@ - - - - - - + Text="{Binding FilterText, Mode=TwoWay}"/> public WikiWeaponPage() { - InitializeWith(); + WikiWeaponViewModel viewModel = InitializeWith(); InitializeComponent(); + + viewModel.Initialize(new AutoSuggestBoxAccessor(WeaponSuggestBox)); + } + + private class AutoSuggestBoxAccessor : IAutoSuggestBoxAccessor + { + public AutoSuggestBoxAccessor(AutoSuggestBox autoSuggestBox) + { + AutoSuggestBox = autoSuggestBox; + } + + public AutoSuggestBox AutoSuggestBox { get; private set; } } } diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/IAutoSuggestBoxAccessor.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/IAutoSuggestBoxAccessor.cs new file mode 100644 index 00000000..2f5233ca --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/IAutoSuggestBoxAccessor.cs @@ -0,0 +1,12 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.UI.Xaml.Controls; +using Snap.Hutao.Control; + +namespace Snap.Hutao.ViewModel.Wiki; + +internal interface IAutoSuggestBoxAccessor : IXamlElementAccessor +{ + AutoSuggestBox AutoSuggestBox { get; } +} diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/IWikiViewModelInitialization.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/IWikiViewModelInitialization.cs new file mode 100644 index 00000000..45335020 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/IWikiViewModelInitialization.cs @@ -0,0 +1,9 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +namespace Snap.Hutao.ViewModel.Wiki; + +internal interface IWikiViewModelInitialization +{ + void Initialize(IAutoSuggestBoxAccessor accessor); +} diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiAvatarViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiAvatarViewModel.cs index 250197cb..2c2283cc 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiAvatarViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiAvatarViewModel.cs @@ -1,11 +1,13 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. +using Microsoft.UI.Xaml.Controls; using Snap.Hutao.Control.Collection.AdvancedCollectionView; using Snap.Hutao.Factory.ContentDialog; using Snap.Hutao.Model.Calculable; using Snap.Hutao.Model.Entity.Primitive; using Snap.Hutao.Model.Intrinsic; +using Snap.Hutao.Model.Intrinsic.Frozen; using Snap.Hutao.Model.Metadata; using Snap.Hutao.Model.Metadata.Avatar; using Snap.Hutao.Model.Metadata.Item; @@ -17,6 +19,7 @@ using Snap.Hutao.Service.Notification; using Snap.Hutao.Service.User; using Snap.Hutao.View.Dialog; using Snap.Hutao.Web.Response; +using System.Collections.Frozen; using System.Runtime.InteropServices; using CalculateAvatarPromotionDelta = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.AvatarPromotionDelta; using CalculateClient = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.CalculateClient; @@ -32,7 +35,7 @@ namespace Snap.Hutao.ViewModel.Wiki; [HighQuality] [ConstructorGenerated] [Injection(InjectAs.Scoped)] -internal sealed partial class WikiAvatarViewModel : Abstraction.ViewModel +internal sealed partial class WikiAvatarViewModel : Abstraction.ViewModel, IWikiViewModelInitialization { private readonly IContentDialogFactory contentDialogFactory; private readonly ICultivationService cultivationService; @@ -49,6 +52,7 @@ internal sealed partial class WikiAvatarViewModel : Abstraction.ViewModel private BaseValueInfo? baseValueInfo; private Dictionary>? levelAvatarCurveMap; private List? promotes; + private FrozenSet availableQueries; /// /// 角色列表 @@ -79,6 +83,13 @@ internal sealed partial class WikiAvatarViewModel : Abstraction.ViewModel /// public string? FilterText { get => filterText; set => SetProperty(ref filterText, value); } + public void Initialize(IAutoSuggestBoxAccessor accessor) + { + accessor.AutoSuggestBox.TextChanged += OnFilterSuggestionRequested; + accessor.AutoSuggestBox.SuggestionChosen += OnFilterSuggestionChosen; + accessor.AutoSuggestBox.QuerySubmitted += ApplyFilter; + } + protected override async ValueTask InitializeUIAsync() { if (!await metadataService.InitializeAsync().ConfigureAwait(false)) @@ -101,6 +112,17 @@ internal sealed partial class WikiAvatarViewModel : Abstraction.ViewModel await taskContext.SwitchToMainThreadAsync(); Avatars = new(list, true); Selected = Avatars.View.ElementAtOrDefault(0); + + availableQueries = FrozenSet.ToFrozenSet( + [ + .. avatars.Select(a => a.Name), + .. IntrinsicFrozen.AssociationTypes, + .. IntrinsicFrozen.BodyTypes, + .. IntrinsicFrozen.ElementNames, + .. IntrinsicFrozen.ItemQualities, + .. IntrinsicFrozen.WeaponTypes, + ]); + return true; } @@ -202,21 +224,43 @@ internal sealed partial class WikiAvatarViewModel : Abstraction.ViewModel BaseValueInfo = new(avatar.MaxLevel, propertyCurveValues, levelAvatarCurveMap, avatarPromoteMap); } - [Command("FilterCommand")] - private void ApplyFilter(string? input) + private void OnFilterSuggestionRequested(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs args) { if (Avatars is null) { return; } - if (string.IsNullOrWhiteSpace(input)) + if (string.IsNullOrWhiteSpace(FilterText)) + { + return; + } + + if (args.Reason == AutoSuggestionBoxTextChangeReason.UserInput) + { + sender.ItemsSource = availableQueries.Where(q => q.Contains(FilterText, StringComparison.OrdinalIgnoreCase)); + } + } + + private void OnFilterSuggestionChosen(AutoSuggestBox sender, AutoSuggestBoxSuggestionChosenEventArgs args) + { + sender.Text = args.SelectedItem.ToString(); + } + + private void ApplyFilter(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args) + { + if (Avatars is null) + { + return; + } + + if (string.IsNullOrWhiteSpace(FilterText)) { Avatars.Filter = default!; return; } - Avatars.Filter = AvatarFilter.Compile(input); + Avatars.Filter = AvatarFilter.Compile(FilterText); if (Selected is not null && Avatars.Contains(Selected)) { diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiWeaponViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiWeaponViewModel.cs index 37615619..2cc99cbb 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiWeaponViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiWeaponViewModel.cs @@ -1,11 +1,13 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. +using Microsoft.UI.Xaml.Controls; using Snap.Hutao.Control.Collection.AdvancedCollectionView; using Snap.Hutao.Factory.ContentDialog; using Snap.Hutao.Model.Calculable; using Snap.Hutao.Model.Entity.Primitive; using Snap.Hutao.Model.Intrinsic; +using Snap.Hutao.Model.Intrinsic.Frozen; using Snap.Hutao.Model.Metadata; using Snap.Hutao.Model.Metadata.Item; using Snap.Hutao.Model.Metadata.Weapon; @@ -17,6 +19,7 @@ using Snap.Hutao.Service.Notification; using Snap.Hutao.Service.User; using Snap.Hutao.View.Dialog; using Snap.Hutao.Web.Response; +using System.Collections.Frozen; using System.Runtime.InteropServices; using CalculateAvatarPromotionDelta = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.AvatarPromotionDelta; using CalculateClient = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.CalculateClient; @@ -29,7 +32,7 @@ namespace Snap.Hutao.ViewModel.Wiki; /// [ConstructorGenerated] [Injection(InjectAs.Scoped)] -internal sealed partial class WikiWeaponViewModel : Abstraction.ViewModel +internal sealed partial class WikiWeaponViewModel : Abstraction.ViewModel, IWikiViewModelInitialization { private readonly IContentDialogFactory contentDialogFactory; private readonly CalculateClient calculateClient; @@ -46,6 +49,7 @@ internal sealed partial class WikiWeaponViewModel : Abstraction.ViewModel private BaseValueInfo? baseValueInfo; private Dictionary>? levelWeaponCurveMap; private List? promotes; + private FrozenSet availableQueries; /// /// 角色列表 @@ -76,6 +80,13 @@ internal sealed partial class WikiWeaponViewModel : Abstraction.ViewModel /// public string? FilterText { get => filterText; set => SetProperty(ref filterText, value); } + public void Initialize(IAutoSuggestBoxAccessor accessor) + { + accessor.AutoSuggestBox.TextChanged += OnFilterSuggestionRequested; + accessor.AutoSuggestBox.SuggestionChosen += OnFilterSuggestionChosen; + accessor.AutoSuggestBox.QuerySubmitted += ApplyFilter; + } + /// protected override async Task OpenUIAsync() { @@ -98,6 +109,14 @@ internal sealed partial class WikiWeaponViewModel : Abstraction.ViewModel Weapons = new(list, true); Selected = Weapons.View.ElementAtOrDefault(0); + + availableQueries = FrozenSet.ToFrozenSet( + [ + .. weapons.Select(w => w.Name), + .. IntrinsicFrozen.ItemQualities, + .. IntrinsicFrozen.FightProperties, + .. IntrinsicFrozen.WeaponTypes, + ]); } } @@ -187,21 +206,43 @@ internal sealed partial class WikiWeaponViewModel : Abstraction.ViewModel BaseValueInfo = new(weapon.MaxLevel, propertyCurveValues, levelWeaponCurveMap, weaponPromoteMap); } - [Command("FilterCommand")] - private void ApplyFilter(string? input) + private void OnFilterSuggestionRequested(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs args) { if (Weapons is null) { return; } - if (string.IsNullOrWhiteSpace(input)) + if (string.IsNullOrWhiteSpace(FilterText)) + { + return; + } + + if (args.Reason == AutoSuggestionBoxTextChangeReason.UserInput) + { + sender.ItemsSource = availableQueries.Where(q => q.Contains(FilterText, StringComparison.OrdinalIgnoreCase)); + } + } + + private void OnFilterSuggestionChosen(AutoSuggestBox sender, AutoSuggestBoxSuggestionChosenEventArgs args) + { + sender.Text = args.SelectedItem.ToString(); + } + + private void ApplyFilter(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args) + { + if (Weapons is null) + { + return; + } + + if (string.IsNullOrWhiteSpace(FilterText)) { Weapons.Filter = default!; return; } - Weapons.Filter = WeaponFilter.Compile(input); + Weapons.Filter = WeaponFilter.Compile(FilterText); if (Selected is not null && Weapons.Contains(Selected)) { From 9619835cc29bff3a75bbe9080c2b0904c928f305 Mon Sep 17 00:00:00 2001 From: qhy040404 Date: Fri, 23 Feb 2024 18:08:30 +0800 Subject: [PATCH 02/10] migrate to TokenizingTextBox --- src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj | 1 + .../Snap.Hutao/View/Page/WikiAvatarPage.xaml | 24 +++++----- .../View/Page/WikiAvatarPage.xaml.cs | 11 +++-- .../Snap.Hutao/View/Page/WikiWeaponPage.xaml | 21 +++++---- .../View/Page/WikiWeaponPage.xaml.cs | 12 ++--- ...essor.cs => ITokenizingTextBoxAccessor.cs} | 6 +-- .../Wiki/IWikiViewModelInitialization.cs | 2 +- .../ViewModel/Wiki/WikiAvatarViewModel.cs | 47 +++++++++++++------ .../ViewModel/Wiki/WikiWeaponViewModel.cs | 46 ++++++++++++------ 9 files changed, 104 insertions(+), 66 deletions(-) rename src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/{IAutoSuggestBoxAccessor.cs => ITokenizingTextBoxAccessor.cs} (50%) diff --git a/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj b/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj index cb0678ac..bd6cc9cd 100644 --- a/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj +++ b/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj @@ -298,6 +298,7 @@ + diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/WikiAvatarPage.xaml b/src/Snap.Hutao/Snap.Hutao/View/Page/WikiAvatarPage.xaml index 8be405da..e3cab592 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Page/WikiAvatarPage.xaml +++ b/src/Snap.Hutao/Snap.Hutao/View/Page/WikiAvatarPage.xaml @@ -7,7 +7,6 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mxi="using:Microsoft.Xaml.Interactivity" - xmlns:mxic="using:Microsoft.Xaml.Interactions.Core" xmlns:shc="using:Snap.Hutao.Control" xmlns:shcb="using:Snap.Hutao.Control.Behavior" xmlns:shci="using:Snap.Hutao.Control.Image" @@ -74,10 +73,7 @@ - + @@ -272,18 +268,20 @@ - + QueryIcon="{cw:FontIconSource Glyph=}" + SuggestedItemTemplate="{StaticResource SuggestionTemplate}" + SuggestedItemsSource="{Binding AvailableQueries}" + Text="{Binding FilterToken, Mode=TwoWay}" + TokenItemTemplate="{StaticResource SuggestionTemplate}"/> (); InitializeComponent(); - viewModel.Initialize(new AutoSuggestBoxAccessor(AvatarSuggestBox)); + viewModel.Initialize(new TokenizingTextBoxAccessor(AvatarSuggestBox)); } - private class AutoSuggestBoxAccessor : IAutoSuggestBoxAccessor + private class TokenizingTextBoxAccessor : ITokenizingTextBoxAccessor { - public AutoSuggestBoxAccessor(AutoSuggestBox autoSuggestBox) + public TokenizingTextBoxAccessor(TokenizingTextBox tokenizingTextBox) { - AutoSuggestBox = autoSuggestBox; + TokenizingTextBox = tokenizingTextBox; } - public AutoSuggestBox AutoSuggestBox { get; private set; } + public TokenizingTextBox TokenizingTextBox { get; private set; } } } diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/WikiWeaponPage.xaml b/src/Snap.Hutao/Snap.Hutao/View/Page/WikiWeaponPage.xaml index 5358afed..219c399c 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Page/WikiWeaponPage.xaml +++ b/src/Snap.Hutao/Snap.Hutao/View/Page/WikiWeaponPage.xaml @@ -33,10 +33,7 @@ - + @@ -138,17 +135,21 @@ LocalSettingKeySuffixForCurrent="WikiWeaponPage.Weapons"/> - + QueryIcon="{cw:FontIconSource Glyph=}" + SuggestedItemTemplate="{StaticResource SuggestionTemplate}" + SuggestedItemsSource="{Binding AvailableQueries}" + Text="{Binding FilterToken, Mode=TwoWay}" + TokenItemTemplate="{StaticResource SuggestionTemplate}"/> (); InitializeComponent(); - viewModel.Initialize(new AutoSuggestBoxAccessor(WeaponSuggestBox)); + viewModel.Initialize(new TokenizingTextBoxAccessor(WeaponSuggestBox)); } - private class AutoSuggestBoxAccessor : IAutoSuggestBoxAccessor + private class TokenizingTextBoxAccessor : ITokenizingTextBoxAccessor { - public AutoSuggestBoxAccessor(AutoSuggestBox autoSuggestBox) + public TokenizingTextBoxAccessor(TokenizingTextBox tokenizingTextBox) { - AutoSuggestBox = autoSuggestBox; + TokenizingTextBox = tokenizingTextBox; } - public AutoSuggestBox AutoSuggestBox { get; private set; } + public TokenizingTextBox TokenizingTextBox { get; private set; } } } diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/IAutoSuggestBoxAccessor.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/ITokenizingTextBoxAccessor.cs similarity index 50% rename from src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/IAutoSuggestBoxAccessor.cs rename to src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/ITokenizingTextBoxAccessor.cs index 2f5233ca..64964f1e 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/IAutoSuggestBoxAccessor.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/ITokenizingTextBoxAccessor.cs @@ -1,12 +1,12 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. -using Microsoft.UI.Xaml.Controls; +using CommunityToolkit.WinUI.Controls; using Snap.Hutao.Control; namespace Snap.Hutao.ViewModel.Wiki; -internal interface IAutoSuggestBoxAccessor : IXamlElementAccessor +internal interface ITokenizingTextBoxAccessor : IXamlElementAccessor { - AutoSuggestBox AutoSuggestBox { get; } + TokenizingTextBox TokenizingTextBox { get; } } diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/IWikiViewModelInitialization.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/IWikiViewModelInitialization.cs index 45335020..c41c48cf 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/IWikiViewModelInitialization.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/IWikiViewModelInitialization.cs @@ -5,5 +5,5 @@ namespace Snap.Hutao.ViewModel.Wiki; internal interface IWikiViewModelInitialization { - void Initialize(IAutoSuggestBoxAccessor accessor); + void Initialize(ITokenizingTextBoxAccessor accessor); } diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiAvatarViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiAvatarViewModel.cs index 2c2283cc..53f44fbf 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiAvatarViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiAvatarViewModel.cs @@ -1,6 +1,7 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. +using CommunityToolkit.WinUI.Controls; using Microsoft.UI.Xaml.Controls; using Snap.Hutao.Control.Collection.AdvancedCollectionView; using Snap.Hutao.Factory.ContentDialog; @@ -20,6 +21,7 @@ using Snap.Hutao.Service.User; using Snap.Hutao.View.Dialog; using Snap.Hutao.Web.Response; using System.Collections.Frozen; +using System.Collections.ObjectModel; using System.Runtime.InteropServices; using CalculateAvatarPromotionDelta = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.AvatarPromotionDelta; using CalculateClient = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.CalculateClient; @@ -48,7 +50,8 @@ internal sealed partial class WikiAvatarViewModel : Abstraction.ViewModel, IWiki private AdvancedCollectionView? avatars; private Avatar? selected; - private string? filterText; + private ObservableCollection? filterTokens; + private string? filterToken; private BaseValueInfo? baseValueInfo; private Dictionary>? levelAvatarCurveMap; private List? promotes; @@ -79,15 +82,20 @@ internal sealed partial class WikiAvatarViewModel : Abstraction.ViewModel, IWiki public BaseValueInfo? BaseValueInfo { get => baseValueInfo; set => SetProperty(ref baseValueInfo, value); } /// - /// 筛选文本 + /// 保存的筛选标志 /// - public string? FilterText { get => filterText; set => SetProperty(ref filterText, value); } + public ObservableCollection? FilterTokens { get => filterTokens; set => SetProperty(ref filterTokens, value); } - public void Initialize(IAutoSuggestBoxAccessor accessor) + public string? FilterToken { get => filterToken; set => SetProperty(ref filterToken, value); } + + public FrozenSet? AvailableQueries { get => availableQueries; } + + public void Initialize(ITokenizingTextBoxAccessor accessor) { - accessor.AutoSuggestBox.TextChanged += OnFilterSuggestionRequested; - accessor.AutoSuggestBox.SuggestionChosen += OnFilterSuggestionChosen; - accessor.AutoSuggestBox.QuerySubmitted += ApplyFilter; + accessor.TokenizingTextBox.TextChanged += OnFilterSuggestionRequested; + accessor.TokenizingTextBox.QuerySubmitted += OnQuerySubmitted; + accessor.TokenizingTextBox.TokenItemAdded += OnTokenItemModified; + accessor.TokenizingTextBox.TokenItemRemoved += OnTokenItemModified; } protected override async ValueTask InitializeUIAsync() @@ -112,6 +120,7 @@ internal sealed partial class WikiAvatarViewModel : Abstraction.ViewModel, IWiki await taskContext.SwitchToMainThreadAsync(); Avatars = new(list, true); Selected = Avatars.View.ElementAtOrDefault(0); + FilterTokens = []; availableQueries = FrozenSet.ToFrozenSet( [ @@ -231,36 +240,46 @@ internal sealed partial class WikiAvatarViewModel : Abstraction.ViewModel, IWiki return; } - if (string.IsNullOrWhiteSpace(FilterText)) + if (string.IsNullOrWhiteSpace(FilterToken)) { return; } if (args.Reason == AutoSuggestionBoxTextChangeReason.UserInput) { - sender.ItemsSource = availableQueries.Where(q => q.Contains(FilterText, StringComparison.OrdinalIgnoreCase)); + sender.ItemsSource = availableQueries.Where(q => q.Contains(FilterToken, StringComparison.OrdinalIgnoreCase)); } } - private void OnFilterSuggestionChosen(AutoSuggestBox sender, AutoSuggestBoxSuggestionChosenEventArgs args) + private void OnQuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args) { - sender.Text = args.SelectedItem.ToString(); + if (args.ChosenSuggestion is not null) + { + return; + } + + ApplyFilter(); } - private void ApplyFilter(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args) + private void OnTokenItemModified(TokenizingTextBox sender, object args) + { + ApplyFilter(); + } + + private void ApplyFilter() { if (Avatars is null) { return; } - if (string.IsNullOrWhiteSpace(FilterText)) + if (FilterTokens.IsNullOrEmpty()) { Avatars.Filter = default!; return; } - Avatars.Filter = AvatarFilter.Compile(FilterText); + Avatars.Filter = AvatarFilter.Compile(string.Join(' ', FilterTokens)); if (Selected is not null && Avatars.Contains(Selected)) { diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiWeaponViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiWeaponViewModel.cs index 2cc99cbb..a1912c90 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiWeaponViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiWeaponViewModel.cs @@ -1,6 +1,7 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. +using CommunityToolkit.WinUI.Controls; using Microsoft.UI.Xaml.Controls; using Snap.Hutao.Control.Collection.AdvancedCollectionView; using Snap.Hutao.Factory.ContentDialog; @@ -45,7 +46,8 @@ internal sealed partial class WikiWeaponViewModel : Abstraction.ViewModel, IWiki private AdvancedCollectionView? weapons; private Weapon? selected; - private string? filterText; + private List? filterTokens; + private string? filterToken; private BaseValueInfo? baseValueInfo; private Dictionary>? levelWeaponCurveMap; private List? promotes; @@ -76,15 +78,20 @@ internal sealed partial class WikiWeaponViewModel : Abstraction.ViewModel, IWiki public BaseValueInfo? BaseValueInfo { get => baseValueInfo; set => SetProperty(ref baseValueInfo, value); } /// - /// 筛选文本 + /// 保存的筛选标志 /// - public string? FilterText { get => filterText; set => SetProperty(ref filterText, value); } + public List? FilterTokens { get => filterTokens; set => SetProperty(ref filterTokens, value); } - public void Initialize(IAutoSuggestBoxAccessor accessor) + public string? FilterToken { get => filterToken; set => SetProperty(ref filterToken, value); } + + public FrozenSet AvailableQueries { get => availableQueries; } + + public void Initialize(ITokenizingTextBoxAccessor accessor) { - accessor.AutoSuggestBox.TextChanged += OnFilterSuggestionRequested; - accessor.AutoSuggestBox.SuggestionChosen += OnFilterSuggestionChosen; - accessor.AutoSuggestBox.QuerySubmitted += ApplyFilter; + accessor.TokenizingTextBox.TextChanged += OnFilterSuggestionRequested; + accessor.TokenizingTextBox.QuerySubmitted += OnQuerySubmitted; + accessor.TokenizingTextBox.TokenItemAdded += OnTokenItemModified; + accessor.TokenizingTextBox.TokenItemRemoved += OnTokenItemModified; } /// @@ -109,6 +116,7 @@ internal sealed partial class WikiWeaponViewModel : Abstraction.ViewModel, IWiki Weapons = new(list, true); Selected = Weapons.View.ElementAtOrDefault(0); + FilterTokens = []; availableQueries = FrozenSet.ToFrozenSet( [ @@ -213,36 +221,46 @@ internal sealed partial class WikiWeaponViewModel : Abstraction.ViewModel, IWiki return; } - if (string.IsNullOrWhiteSpace(FilterText)) + if (string.IsNullOrWhiteSpace(FilterToken)) { return; } if (args.Reason == AutoSuggestionBoxTextChangeReason.UserInput) { - sender.ItemsSource = availableQueries.Where(q => q.Contains(FilterText, StringComparison.OrdinalIgnoreCase)); + sender.ItemsSource = availableQueries.Where(q => q.Contains(FilterToken, StringComparison.OrdinalIgnoreCase)); } } - private void OnFilterSuggestionChosen(AutoSuggestBox sender, AutoSuggestBoxSuggestionChosenEventArgs args) + private void OnQuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args) { - sender.Text = args.SelectedItem.ToString(); + if (args.ChosenSuggestion is not null) + { + return; + } + + ApplyFilter(); } - private void ApplyFilter(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args) + private void OnTokenItemModified(TokenizingTextBox sender, object args) + { + ApplyFilter(); + } + + private void ApplyFilter() { if (Weapons is null) { return; } - if (string.IsNullOrWhiteSpace(FilterText)) + if (FilterTokens.IsNullOrEmpty()) { Weapons.Filter = default!; return; } - Weapons.Filter = WeaponFilter.Compile(FilterText); + Weapons.Filter = WeaponFilter.Compile(string.Join(' ', FilterTokens)); if (Selected is not null && Weapons.Contains(Selected)) { From e35c03ac90c20dd1c0a1c977c243622fd87f94d6 Mon Sep 17 00:00:00 2001 From: qhy040404 Date: Sun, 3 Mar 2024 21:03:28 +0800 Subject: [PATCH 03/10] support or in wiki search --- .../Converter/AssociationTypeIconConverter.cs | 54 ++++++++ .../Converter/QualityColorConverter.cs | 26 +++- .../Converter/WeaponTypeIconConverter.cs | 14 +++ .../Snap.Hutao/View/Page/WikiAvatarPage.xaml | 49 +++++++- .../Snap.Hutao/View/Page/WikiWeaponPage.xaml | 50 ++++++-- .../Snap.Hutao/ViewModel/Wiki/AvatarFilter.cs | 75 +++++------ .../Snap.Hutao/ViewModel/Wiki/SearchToken.cs | 118 ++++++++++++++++++ .../Snap.Hutao/ViewModel/Wiki/WeaponFilter.cs | 50 ++++---- .../ViewModel/Wiki/WikiAvatarViewModel.cs | 28 ++++- .../ViewModel/Wiki/WikiWeaponViewModel.cs | 29 ++++- 10 files changed, 411 insertions(+), 82 deletions(-) create mode 100644 src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/AssociationTypeIconConverter.cs create mode 100644 src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/SearchToken.cs diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/AssociationTypeIconConverter.cs b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/AssociationTypeIconConverter.cs new file mode 100644 index 00000000..93321a30 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/AssociationTypeIconConverter.cs @@ -0,0 +1,54 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +using Snap.Hutao.Control; +using Snap.Hutao.Model.Intrinsic; + +namespace Snap.Hutao.Model.Metadata.Converter; + +internal sealed class AssociationTypeIconConverter : ValueConverter +{ + private static readonly Dictionary LocalizedNameToAssociationType = new() + { + [SH.ModelIntrinsicAssociationTypeMondstadt] = AssociationType.ASSOC_TYPE_MONDSTADT, + [SH.ModelIntrinsicAssociationTypeLiyue] = AssociationType.ASSOC_TYPE_LIYUE, + [SH.ModelIntrinsicAssociationTypeFatui] = AssociationType.ASSOC_TYPE_FATUI, + [SH.ModelIntrinsicAssociationTypeInazuma] = AssociationType.ASSOC_TYPE_INAZUMA, + [SH.ModelIntrinsicAssociationTypeRanger] = AssociationType.ASSOC_TYPE_RANGER, + [SH.ModelIntrinsicAssociationTypeSumeru] = AssociationType.ASSOC_TYPE_SUMERU, + [SH.ModelIntrinsicAssociationTypeFontaine] = AssociationType.ASSOC_TYPE_FONTAINE, + [SH.ModelIntrinsicAssociationTypeNatlan] = AssociationType.ASSOC_TYPE_NATLAN, + [SH.ModelIntrinsicAssociationTypeSnezhnaya] = AssociationType.ASSOC_TYPE_SNEZHNAYA, + }; + + public static Uri? AssociationTypeNameToIconUri(string associationTypeName) + { + return AssociationTypeToIconUri(LocalizedNameToAssociationType.GetValueOrDefault(associationTypeName)); + } + + public static Uri? AssociationTypeToIconUri(AssociationType type) + { + string? association = type switch + { + AssociationType.ASSOC_TYPE_MONDSTADT => "Mengde", + AssociationType.ASSOC_TYPE_LIYUE => "Liyue", + AssociationType.ASSOC_TYPE_FATUI => null, + AssociationType.ASSOC_TYPE_INAZUMA => "Inazuma", + AssociationType.ASSOC_TYPE_RANGER => null, + AssociationType.ASSOC_TYPE_SUMERU => "Sumeru", + AssociationType.ASSOC_TYPE_FONTAINE => "Fontaine", + AssociationType.ASSOC_TYPE_NATLAN => null, + AssociationType.ASSOC_TYPE_SNEZHNAYA => null, + _ => throw Must.NeverHappen(), + }; + + return association is null + ? null + : Web.HutaoEndpoints.StaticRaw("ChapterIcon", $"UI_ChapterIcon_{association}.png").ToUri(); + } + + public override Uri? Convert(AssociationType from) + { + return AssociationTypeToIconUri(from); + } +} diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/QualityColorConverter.cs b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/QualityColorConverter.cs index 20df90d1..c3da4da8 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/QualityColorConverter.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/QualityColorConverter.cs @@ -15,10 +15,24 @@ namespace Snap.Hutao.Model.Metadata.Converter; [HighQuality] internal sealed class QualityColorConverter : ValueConverter { - /// - public override Color Convert(QualityType from) + private static readonly Dictionary LocalizedNameToQualityType = new() { - return from switch + [SH.ModelIntrinsicItemQualityWhite] = QualityType.QUALITY_WHITE, + [SH.ModelIntrinsicItemQualityGreen] = QualityType.QUALITY_GREEN, + [SH.ModelIntrinsicItemQualityBlue] = QualityType.QUALITY_BLUE, + [SH.ModelIntrinsicItemQualityPurple] = QualityType.QUALITY_PURPLE, + [SH.ModelIntrinsicItemQualityOrange] = QualityType.QUALITY_ORANGE, + [SH.ModelIntrinsicItemQualityRed] = QualityType.QUALITY_ORANGE_SP, + }; + + public static Color QualityNameToColor(string qualityName) + { + return QualityToColor(LocalizedNameToQualityType.GetValueOrDefault(qualityName)); + } + + public static Color QualityToColor(QualityType quality) + { + return quality switch { QualityType.QUALITY_WHITE => StructMarshal.Color(0xFF72778B), QualityType.QUALITY_GREEN => StructMarshal.Color(0xFF2A8F72), @@ -28,4 +42,10 @@ internal sealed class QualityColorConverter : ValueConverter _ => Colors.Transparent, }; } + + /// + public override Color Convert(QualityType from) + { + return QualityToColor(from); + } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/WeaponTypeIconConverter.cs b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/WeaponTypeIconConverter.cs index e6f34fe4..41712715 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/WeaponTypeIconConverter.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/WeaponTypeIconConverter.cs @@ -12,6 +12,20 @@ namespace Snap.Hutao.Model.Metadata.Converter; [HighQuality] internal sealed class WeaponTypeIconConverter : ValueConverter { + private static readonly Dictionary LocalizedNameToWeaponType = new() + { + [SH.ModelIntrinsicWeaponTypeSwordOneHand] = WeaponType.WEAPON_SWORD_ONE_HAND, + [SH.ModelIntrinsicWeaponTypeBow] = WeaponType.WEAPON_BOW, + [SH.ModelIntrinsicWeaponTypePole] = WeaponType.WEAPON_POLE, + [SH.ModelIntrinsicWeaponTypeClaymore] = WeaponType.WEAPON_CLAYMORE, + [SH.ModelIntrinsicWeaponTypeCatalyst] = WeaponType.WEAPON_CATALYST, + }; + + public static Uri WeaponTypeNameToIconUri(string weaponTypeName) + { + return WeaponTypeToIconUri(LocalizedNameToWeaponType.GetValueOrDefault(weaponTypeName)); + } + /// /// 将武器类型转换为图标链接 /// diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/WikiAvatarPage.xaml b/src/Snap.Hutao/Snap.Hutao/View/Page/WikiAvatarPage.xaml index e3cab592..43c5d46e 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Page/WikiAvatarPage.xaml +++ b/src/Snap.Hutao/Snap.Hutao/View/Page/WikiAvatarPage.xaml @@ -72,8 +72,45 @@ - - + + + + + + + + + + + + + + + @@ -270,18 +307,18 @@ + TokenItemTemplate="{StaticResource TokenTemplate}"/> - - + + + + + + + + + + + + + + + @@ -137,19 +174,18 @@ + TokenItemTemplate="{StaticResource TokenTemplate}"/> /// 输入 /// 筛选操作 - public static Predicate Compile(string input) + public static Predicate Compile(ObservableCollection input) { return (Avatar avatar) => DoFilter(input, avatar); } - private static bool DoFilter(string input, Avatar avatar) + private static bool DoFilter(ObservableCollection input, Avatar avatar) { List matches = []; - foreach (StringSegment segment in new StringTokenizer(input, [' '])) + + foreach (IGrouping tokens in input.GroupBy(token => token.Kind, token => token.Value)) { - string value = segment.ToString(); - - if (avatar.Name == value) + switch (tokens.Key) { - matches.Add(true); - continue; - } + case SearchTokenKind.ElementNames: + if (IntrinsicFrozen.ElementNames.Overlaps(tokens)) + { + matches.Add(tokens.Contains(avatar.FetterInfo.VisionBefore)); + } - if (IntrinsicFrozen.ElementNames.Contains(value)) - { - matches.Add(avatar.FetterInfo.VisionBefore == value); - continue; - } + break; + case SearchTokenKind.AssociationTypes: + if (IntrinsicFrozen.AssociationTypes.Overlaps(tokens)) + { + matches.Add(tokens.Contains(avatar.FetterInfo.Association.GetLocalizedDescriptionOrDefault())); + } - if (IntrinsicFrozen.AssociationTypes.Contains(value)) - { - matches.Add(avatar.FetterInfo.Association.GetLocalizedDescriptionOrDefault() == value); - continue; - } + break; + case SearchTokenKind.WeaponTypes: + if (IntrinsicFrozen.WeaponTypes.Overlaps(tokens)) + { + matches.Add(tokens.Contains(avatar.Weapon.GetLocalizedDescriptionOrDefault())); + } - if (IntrinsicFrozen.WeaponTypes.Contains(value)) - { - matches.Add(avatar.Weapon.GetLocalizedDescriptionOrDefault() == value); - continue; - } + break; + case SearchTokenKind.ItemQualities: + if (IntrinsicFrozen.ItemQualities.Overlaps(tokens)) + { + matches.Add(tokens.Contains(avatar.Quality.GetLocalizedDescriptionOrDefault())); + } - if (IntrinsicFrozen.ItemQualities.Contains(value)) - { - matches.Add(avatar.Quality.GetLocalizedDescriptionOrDefault() == value); - continue; - } + break; + case SearchTokenKind.BodyTypes: + if (IntrinsicFrozen.BodyTypes.Overlaps(tokens)) + { + matches.Add(tokens.Contains(avatar.Body.GetLocalizedDescriptionOrDefault())); + } - if (IntrinsicFrozen.BodyTypes.Contains(value)) - { - matches.Add(avatar.Body.GetLocalizedDescriptionOrDefault() == value); - continue; + break; + case SearchTokenKind.Other: + matches.Add(tokens.Contains(avatar.Name)); + break; } - - matches.Add(false); } return matches.Count > 0 && matches.Aggregate((a, b) => a && b); diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/SearchToken.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/SearchToken.cs new file mode 100644 index 00000000..cb7617a2 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/SearchToken.cs @@ -0,0 +1,118 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +using Snap.Hutao.Model.Intrinsic.Frozen; +using Snap.Hutao.Model.Metadata.Avatar; +using Snap.Hutao.Model.Metadata.Converter; +using Snap.Hutao.Model.Metadata.Weapon; +using Windows.UI; + +namespace Snap.Hutao.ViewModel.Wiki; + +internal class SearchToken +{ + private SearchTokenKind kind; + private bool isKindInitialized; + private object isKindInitializedLock = new(); + + public SearchToken(string value) + { + Value = value; + } + + public SearchToken(Avatar avatar) + { + Value = avatar.Name; + SideIconUri = AvatarSideIconConverter.IconNameToUri(avatar.SideIcon); + } + + public SearchToken(Weapon weapon) + { + Value = weapon.Name; + SideIconUri = EquipIconConverter.IconNameToUri(weapon.Icon); + } + + public string Value { get; } + + public Uri? SideIconUri { get; } + + public Uri? IconUri + { + get => Kind switch + { + SearchTokenKind.AssociationTypes => AssociationTypeIconConverter.AssociationTypeNameToIconUri(Value), + SearchTokenKind.ElementNames => ElementNameIconConverter.ElementNameToIconUri(Value), + SearchTokenKind.WeaponTypes => WeaponTypeIconConverter.WeaponTypeNameToIconUri(Value), + _ => null, + }; + } + + public Color? Quality + { + get => Kind switch + { + SearchTokenKind.ItemQualities => QualityColorConverter.QualityNameToColor(Value), + _ => null, + }; + } + + public SearchTokenKind Kind + { + get + { + return LazyInitializer.EnsureInitialized(ref kind, ref isKindInitialized, ref isKindInitializedLock, GetKind); + + SearchTokenKind GetKind() + { + if (IntrinsicFrozen.AssociationTypes.Contains(Value)) + { + return SearchTokenKind.AssociationTypes; + } + + if (IntrinsicFrozen.BodyTypes.Contains(Value)) + { + return SearchTokenKind.BodyTypes; + } + + if (IntrinsicFrozen.ElementNames.Contains(Value)) + { + return SearchTokenKind.ElementNames; + } + + if (IntrinsicFrozen.FightProperties.Contains(Value)) + { + return SearchTokenKind.FightProperties; + } + + if (IntrinsicFrozen.ItemQualities.Contains(Value)) + { + return SearchTokenKind.ItemQualities; + } + + if (IntrinsicFrozen.WeaponTypes.Contains(Value)) + { + return SearchTokenKind.WeaponTypes; + } + + return SearchTokenKind.Other; + } + } + } + + public override string ToString() + { + return Value; + } +} + +[SuppressMessage("", "SA1201")] +internal enum SearchTokenKind +{ + AssociationTypes, + BodyTypes, + ElementNames, + FightProperties, + ItemQualities, + Other, // Include avatar and weapon + WeaponTypes, +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WeaponFilter.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WeaponFilter.cs index 06731581..392a6027 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WeaponFilter.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WeaponFilter.cs @@ -1,9 +1,9 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. -using Microsoft.Extensions.Primitives; using Snap.Hutao.Model.Intrinsic.Frozen; using Snap.Hutao.Model.Metadata.Weapon; +using System.Collections.ObjectModel; namespace Snap.Hutao.ViewModel.Wiki; @@ -17,41 +17,43 @@ internal static class WeaponFilter /// /// 输入 /// 筛选操作 - public static Predicate Compile(string input) + public static Predicate Compile(ObservableCollection input) { return (Weapon weapon) => DoFilter(input, weapon); } - private static bool DoFilter(string input, Weapon weapon) + private static bool DoFilter(ObservableCollection input, Weapon weapon) { List matches = []; - foreach (StringSegment segment in new StringTokenizer(input, [' '])) + foreach (IGrouping tokens in input.GroupBy(token => token.Kind, token => token.Value)) { - string value = segment.ToString(); - - if (weapon.Name == value) + switch (tokens.Key) { - matches.Add(true); - continue; - } + case SearchTokenKind.WeaponTypes: + if (IntrinsicFrozen.WeaponTypes.Overlaps(tokens)) + { + matches.Add(tokens.Contains(weapon.WeaponType.GetLocalizedDescriptionOrDefault())); + } - if (IntrinsicFrozen.WeaponTypes.Contains(value)) - { - matches.Add(weapon.WeaponType.GetLocalizedDescriptionOrDefault() == value); - continue; - } + break; + case SearchTokenKind.ItemQualities: + if (IntrinsicFrozen.ItemQualities.Overlaps(tokens)) + { + matches.Add(tokens.Contains(weapon.Quality.GetLocalizedDescriptionOrDefault())); + } - if (IntrinsicFrozen.ItemQualities.Contains(value)) - { - matches.Add(weapon.Quality.GetLocalizedDescriptionOrDefault() == value); - continue; - } + break; + case SearchTokenKind.FightProperties: + if (IntrinsicFrozen.FightProperties.Overlaps(tokens)) + { + matches.Add(tokens.Contains(weapon.GrowCurves.ElementAtOrDefault(1)?.Type.GetLocalizedDescriptionOrDefault())); + } - if (IntrinsicFrozen.FightProperties.Contains(value)) - { - matches.Add(weapon.GrowCurves.ElementAtOrDefault(1)?.Type.GetLocalizedDescriptionOrDefault() == value); - continue; + break; + case SearchTokenKind.Other: + matches.Add(tokens.Contains(weapon.Name)); + break; } } diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiAvatarViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiAvatarViewModel.cs index 53f44fbf..1691c7ab 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiAvatarViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiAvatarViewModel.cs @@ -50,7 +50,7 @@ internal sealed partial class WikiAvatarViewModel : Abstraction.ViewModel, IWiki private AdvancedCollectionView? avatars; private Avatar? selected; - private ObservableCollection? filterTokens; + private ObservableCollection? filterTokens; private string? filterToken; private BaseValueInfo? baseValueInfo; private Dictionary>? levelAvatarCurveMap; @@ -84,7 +84,7 @@ internal sealed partial class WikiAvatarViewModel : Abstraction.ViewModel, IWiki /// /// 保存的筛选标志 /// - public ObservableCollection? FilterTokens { get => filterTokens; set => SetProperty(ref filterTokens, value); } + public ObservableCollection? FilterTokens { get => filterTokens; set => SetProperty(ref filterTokens, value); } public string? FilterToken { get => filterToken; set => SetProperty(ref filterToken, value); } @@ -94,6 +94,7 @@ internal sealed partial class WikiAvatarViewModel : Abstraction.ViewModel, IWiki { accessor.TokenizingTextBox.TextChanged += OnFilterSuggestionRequested; accessor.TokenizingTextBox.QuerySubmitted += OnQuerySubmitted; + accessor.TokenizingTextBox.TokenItemAdding += OnTokenItemAdding; accessor.TokenizingTextBox.TokenItemAdded += OnTokenItemModified; accessor.TokenizingTextBox.TokenItemRemoved += OnTokenItemModified; } @@ -261,6 +262,27 @@ internal sealed partial class WikiAvatarViewModel : Abstraction.ViewModel, IWiki ApplyFilter(); } + private void OnTokenItemAdding(TokenizingTextBox sender, TokenItemAddingEventArgs args) + { + if (string.IsNullOrWhiteSpace(args.TokenText)) + { + return; + } + + if (Avatars is null) + { + return; + } + + if (Avatars.SourceCollection.SingleOrDefault(a => a.Name == args.TokenText) is { } avatar) + { + args.Item = new SearchToken(avatar); + return; + } + + args.Item = new SearchToken(args.TokenText); + } + private void OnTokenItemModified(TokenizingTextBox sender, object args) { ApplyFilter(); @@ -279,7 +301,7 @@ internal sealed partial class WikiAvatarViewModel : Abstraction.ViewModel, IWiki return; } - Avatars.Filter = AvatarFilter.Compile(string.Join(' ', FilterTokens)); + Avatars.Filter = AvatarFilter.Compile(FilterTokens); if (Selected is not null && Avatars.Contains(Selected)) { diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiWeaponViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiWeaponViewModel.cs index a1912c90..3d8a2a3d 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiWeaponViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiWeaponViewModel.cs @@ -21,6 +21,7 @@ using Snap.Hutao.Service.User; using Snap.Hutao.View.Dialog; using Snap.Hutao.Web.Response; using System.Collections.Frozen; +using System.Collections.ObjectModel; using System.Runtime.InteropServices; using CalculateAvatarPromotionDelta = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.AvatarPromotionDelta; using CalculateClient = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.CalculateClient; @@ -46,7 +47,7 @@ internal sealed partial class WikiWeaponViewModel : Abstraction.ViewModel, IWiki private AdvancedCollectionView? weapons; private Weapon? selected; - private List? filterTokens; + private ObservableCollection? filterTokens; private string? filterToken; private BaseValueInfo? baseValueInfo; private Dictionary>? levelWeaponCurveMap; @@ -80,7 +81,7 @@ internal sealed partial class WikiWeaponViewModel : Abstraction.ViewModel, IWiki /// /// 保存的筛选标志 /// - public List? FilterTokens { get => filterTokens; set => SetProperty(ref filterTokens, value); } + public ObservableCollection? FilterTokens { get => filterTokens; set => SetProperty(ref filterTokens, value); } public string? FilterToken { get => filterToken; set => SetProperty(ref filterToken, value); } @@ -90,6 +91,7 @@ internal sealed partial class WikiWeaponViewModel : Abstraction.ViewModel, IWiki { accessor.TokenizingTextBox.TextChanged += OnFilterSuggestionRequested; accessor.TokenizingTextBox.QuerySubmitted += OnQuerySubmitted; + accessor.TokenizingTextBox.TokenItemAdding += OnTokenItemAdding; accessor.TokenizingTextBox.TokenItemAdded += OnTokenItemModified; accessor.TokenizingTextBox.TokenItemRemoved += OnTokenItemModified; } @@ -242,6 +244,27 @@ internal sealed partial class WikiWeaponViewModel : Abstraction.ViewModel, IWiki ApplyFilter(); } + private void OnTokenItemAdding(TokenizingTextBox sender, TokenItemAddingEventArgs args) + { + if (string.IsNullOrWhiteSpace(args.TokenText)) + { + return; + } + + if (Weapons is null) + { + return; + } + + if (Weapons.SourceCollection.SingleOrDefault(w => w.Name == args.TokenText) is { } weapon) + { + args.Item = new SearchToken(weapon); + return; + } + + args.Item = new SearchToken(args.TokenText); + } + private void OnTokenItemModified(TokenizingTextBox sender, object args) { ApplyFilter(); @@ -260,7 +283,7 @@ internal sealed partial class WikiWeaponViewModel : Abstraction.ViewModel, IWiki return; } - Weapons.Filter = WeaponFilter.Compile(string.Join(' ', FilterTokens)); + Weapons.Filter = WeaponFilter.Compile(FilterTokens); if (Selected is not null && Weapons.Contains(Selected)) { From 03c1bacfe958c19d7b99872547fc4bdd49d693f3 Mon Sep 17 00:00:00 2001 From: qhy040404 Date: Mon, 4 Mar 2024 00:01:52 +0800 Subject: [PATCH 04/10] maybe code style --- .../Snap.Hutao/Control/ScopedPage.cs | 4 +- .../Control/SuggestBox/AutoSuggestTokenBox.cs | 82 +++++++++++++++++++ .../Control/SuggestBox/ISearchToken.cs | 9 ++ .../Control/SuggestBox/ITokenizable.cs | 11 +++ .../SuggestBox/SearchToken.Wiki.cs} | 42 ++-------- .../Control/SuggestBox/SearchToken.cs | 19 +++++ .../SuggestBox/SearchTokenKind.Wiki.cs | 15 ++++ .../Metadata/Avatar/Avatar.Implementation.cs | 8 +- .../Metadata/Weapon/Weapon.Implementation.cs | 8 +- .../Snap.Hutao/View/Page/WikiAvatarPage.xaml | 4 +- .../View/Page/WikiAvatarPage.xaml.cs | 16 +--- .../Snap.Hutao/View/Page/WikiWeaponPage.xaml | 4 +- .../View/Page/WikiWeaponPage.xaml.cs | 15 +--- .../Snap.Hutao/ViewModel/Wiki/AvatarFilter.cs | 1 + .../Snap.Hutao/ViewModel/Wiki/WeaponFilter.cs | 1 + .../ViewModel/Wiki/WikiAvatarViewModel.cs | 69 +--------------- .../ViewModel/Wiki/WikiWeaponViewModel.cs | 69 +--------------- 17 files changed, 172 insertions(+), 205 deletions(-) create mode 100644 src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/AutoSuggestTokenBox.cs create mode 100644 src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/ISearchToken.cs create mode 100644 src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/ITokenizable.cs rename src/Snap.Hutao/Snap.Hutao/{ViewModel/Wiki/SearchToken.cs => Control/SuggestBox/SearchToken.Wiki.cs} (73%) create mode 100644 src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/SearchToken.cs create mode 100644 src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/SearchTokenKind.Wiki.cs diff --git a/src/Snap.Hutao/Snap.Hutao/Control/ScopedPage.cs b/src/Snap.Hutao/Snap.Hutao/Control/ScopedPage.cs index d3eac6c9..06db70e8 100644 --- a/src/Snap.Hutao/Snap.Hutao/Control/ScopedPage.cs +++ b/src/Snap.Hutao/Snap.Hutao/Control/ScopedPage.cs @@ -41,14 +41,12 @@ internal class ScopedPage : Page /// 应当在 InitializeComponent() 前调用 /// /// 视图模型类型 - protected TViewModel InitializeWith() + protected void InitializeWith() where TViewModel : class, IViewModel { IViewModel viewModel = currentScope.ServiceProvider.GetRequiredService(); viewModel.CancellationToken = viewCancellationTokenSource.Token; DataContext = viewModel; - - return (TViewModel)viewModel; } /// diff --git a/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/AutoSuggestTokenBox.cs b/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/AutoSuggestTokenBox.cs new file mode 100644 index 00000000..6ed4af22 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/AutoSuggestTokenBox.cs @@ -0,0 +1,82 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +using CommunityToolkit.WinUI.Controls; +using Microsoft.UI.Xaml.Controls; +using Snap.Hutao.Control.SuggestBox; + +namespace Snap.Hutao.View.Control; + +[DependencyProperty("FilterCommand", typeof(ICommand))] +[DependencyProperty("ITokenizableItemsSource", typeof(IEnumerable))] +internal sealed partial class AutoSuggestTokenBox : TokenizingTextBox +{ + public AutoSuggestTokenBox() + { + TextChanged += OnFilterSuggestionRequested; + QuerySubmitted += OnQuerySubmitted; + TokenItemAdding += OnTokenItemAdding; + TokenItemAdded += OnTokenItemModified; + TokenItemRemoved += OnTokenItemModified; + } + + private void OnFilterSuggestionRequested(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs args) + { + if (SuggestedItemsSource is not IEnumerable availableQueries) + { + return; + } + + if (string.IsNullOrWhiteSpace(Text)) + { + return; + } + + if (args.Reason == AutoSuggestionBoxTextChangeReason.UserInput) + { + sender.ItemsSource = availableQueries.Where(q => q.Contains(Text, StringComparison.OrdinalIgnoreCase)); + } + } + + private void OnQuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args) + { + if (args.ChosenSuggestion is not null) + { + return; + } + + if (FilterCommand.CanExecute(null)) + { + FilterCommand.Execute(null); + } + } + + private void OnTokenItemAdding(TokenizingTextBox sender, TokenItemAddingEventArgs args) + { + if (string.IsNullOrWhiteSpace(args.TokenText)) + { + return; + } + + if (ITokenizableItemsSource is null) + { + return; + } + + if (ITokenizableItemsSource.SingleOrDefault(i => i.Name == args.TokenText) is { } item) + { + args.Item = item.Tokenize(); + return; + } + + args.Item = new SearchToken(args.TokenText); + } + + private void OnTokenItemModified(TokenizingTextBox sender, object args) + { + if (FilterCommand.CanExecute(null)) + { + FilterCommand.Execute(null); + } + } +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/ISearchToken.cs b/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/ISearchToken.cs new file mode 100644 index 00000000..7b054f10 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/ISearchToken.cs @@ -0,0 +1,9 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +namespace Snap.Hutao.Control.SuggestBox; + +internal interface ISearchToken +{ + string Value { get; set; } +} diff --git a/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/ITokenizable.cs b/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/ITokenizable.cs new file mode 100644 index 00000000..bb8f32b8 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/ITokenizable.cs @@ -0,0 +1,11 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +namespace Snap.Hutao.Control.SuggestBox; + +internal interface ITokenizable +{ + string Name { get; } + + ISearchToken Tokenize(); +} diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/SearchToken.cs b/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/SearchToken.Wiki.cs similarity index 73% rename from src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/SearchToken.cs rename to src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/SearchToken.Wiki.cs index cb7617a2..256f51ee 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/SearchToken.cs +++ b/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/SearchToken.Wiki.cs @@ -2,38 +2,23 @@ // Licensed under the MIT license. using Snap.Hutao.Model.Intrinsic.Frozen; -using Snap.Hutao.Model.Metadata.Avatar; using Snap.Hutao.Model.Metadata.Converter; -using Snap.Hutao.Model.Metadata.Weapon; using Windows.UI; -namespace Snap.Hutao.ViewModel.Wiki; +namespace Snap.Hutao.Control.SuggestBox; -internal class SearchToken +internal partial class SearchToken { private SearchTokenKind kind; private bool isKindInitialized; private object isKindInitializedLock = new(); - public SearchToken(string value) + public SearchToken(string value, Uri? sideIconUri) + : this(value) { - Value = value; + SideIconUri = sideIconUri; } - public SearchToken(Avatar avatar) - { - Value = avatar.Name; - SideIconUri = AvatarSideIconConverter.IconNameToUri(avatar.SideIcon); - } - - public SearchToken(Weapon weapon) - { - Value = weapon.Name; - SideIconUri = EquipIconConverter.IconNameToUri(weapon.Icon); - } - - public string Value { get; } - public Uri? SideIconUri { get; } public Uri? IconUri @@ -98,21 +83,4 @@ internal class SearchToken } } } - - public override string ToString() - { - return Value; - } } - -[SuppressMessage("", "SA1201")] -internal enum SearchTokenKind -{ - AssociationTypes, - BodyTypes, - ElementNames, - FightProperties, - ItemQualities, - Other, // Include avatar and weapon - WeaponTypes, -} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/SearchToken.cs b/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/SearchToken.cs new file mode 100644 index 00000000..0eb17654 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/SearchToken.cs @@ -0,0 +1,19 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +namespace Snap.Hutao.Control.SuggestBox; + +internal sealed partial class SearchToken : ISearchToken +{ + public SearchToken(string value) + { + Value = value; + } + + public string Value { get; set; } = default!; + + public override string ToString() + { + return Value; + } +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/SearchTokenKind.Wiki.cs b/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/SearchTokenKind.Wiki.cs new file mode 100644 index 00000000..4f1868c8 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/SearchTokenKind.Wiki.cs @@ -0,0 +1,15 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +namespace Snap.Hutao.Control.SuggestBox; + +internal enum SearchTokenKind +{ + AssociationTypes, + BodyTypes, + ElementNames, + FightProperties, + ItemQualities, + Other, // Include avatar and weapon + WeaponTypes, +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Avatar/Avatar.Implementation.cs b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Avatar/Avatar.Implementation.cs index 4871692d..343afd8b 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Avatar/Avatar.Implementation.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Avatar/Avatar.Implementation.cs @@ -1,6 +1,7 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. +using Snap.Hutao.Control.SuggestBox; using Snap.Hutao.Model.Calculable; using Snap.Hutao.Model.Metadata.Abstraction; using Snap.Hutao.Model.Metadata.Converter; @@ -14,7 +15,7 @@ namespace Snap.Hutao.Model.Metadata.Avatar; /// /// 角色的接口实现部分 /// -internal partial class Avatar : IStatisticsItemSource, ISummaryItemSource, IItemSource, INameQuality, ICalculableSource +internal partial class Avatar : IStatisticsItemSource, ISummaryItemSource, IItemSource, INameQuality, ICalculableSource, ITokenizable { /// /// [非元数据] 搭配数据 @@ -96,4 +97,9 @@ internal partial class Avatar : IStatisticsItemSource, ISummaryItemSource, IItem IsUp = isUp, }; } + + public ISearchToken Tokenize() + { + return new SearchToken(Name, AvatarSideIconConverter.IconNameToUri(SideIcon)); + } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Weapon/Weapon.Implementation.cs b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Weapon/Weapon.Implementation.cs index 86a4465c..f677d19b 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Weapon/Weapon.Implementation.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Weapon/Weapon.Implementation.cs @@ -1,6 +1,7 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. +using Snap.Hutao.Control.SuggestBox; using Snap.Hutao.Model.Calculable; using Snap.Hutao.Model.Intrinsic; using Snap.Hutao.Model.Metadata.Abstraction; @@ -14,7 +15,7 @@ namespace Snap.Hutao.Model.Metadata.Weapon; /// /// 武器的接口实现 /// -internal sealed partial class Weapon : IStatisticsItemSource, ISummaryItemSource, IItemSource, INameQuality, ICalculableSource +internal sealed partial class Weapon : IStatisticsItemSource, ISummaryItemSource, IItemSource, INameQuality, ICalculableSource, ITokenizable { /// /// [非元数据] 搭配数据 @@ -104,4 +105,9 @@ internal sealed partial class Weapon : IStatisticsItemSource, ISummaryItemSource IsUp = isUp, }; } + + public ISearchToken Tokenize() + { + return new SearchToken(Name, EquipIconConverter.IconNameToUri(Icon)); + } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/WikiAvatarPage.xaml b/src/Snap.Hutao/Snap.Hutao/View/Page/WikiAvatarPage.xaml index 43c5d46e..af3cf59f 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Page/WikiAvatarPage.xaml +++ b/src/Snap.Hutao/Snap.Hutao/View/Page/WikiAvatarPage.xaml @@ -305,13 +305,15 @@ - public WikiAvatarPage() { - WikiAvatarViewModel viewModel = InitializeWith(); + InitializeWith(); InitializeComponent(); - - viewModel.Initialize(new TokenizingTextBoxAccessor(AvatarSuggestBox)); - } - - private class TokenizingTextBoxAccessor : ITokenizingTextBoxAccessor - { - public TokenizingTextBoxAccessor(TokenizingTextBox tokenizingTextBox) - { - TokenizingTextBox = tokenizingTextBox; - } - - public TokenizingTextBox TokenizingTextBox { get; private set; } } } diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/WikiWeaponPage.xaml b/src/Snap.Hutao/Snap.Hutao/View/Page/WikiWeaponPage.xaml index af05a9e6..4db320fc 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Page/WikiWeaponPage.xaml +++ b/src/Snap.Hutao/Snap.Hutao/View/Page/WikiWeaponPage.xaml @@ -172,13 +172,15 @@ LocalSettingKeySuffixForCurrent="WikiWeaponPage.Weapons"/> - public WikiWeaponPage() { - WikiWeaponViewModel viewModel = InitializeWith(); + InitializeWith(); InitializeComponent(); - - viewModel.Initialize(new TokenizingTextBoxAccessor(WeaponSuggestBox)); - } - - private class TokenizingTextBoxAccessor : ITokenizingTextBoxAccessor - { - public TokenizingTextBoxAccessor(TokenizingTextBox tokenizingTextBox) - { - TokenizingTextBox = tokenizingTextBox; - } - - public TokenizingTextBox TokenizingTextBox { get; private set; } } } diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/AvatarFilter.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/AvatarFilter.cs index 9ddad9e7..c18c963c 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/AvatarFilter.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/AvatarFilter.cs @@ -1,6 +1,7 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. +using Snap.Hutao.Control.SuggestBox; using Snap.Hutao.Model.Intrinsic.Frozen; using Snap.Hutao.Model.Metadata.Avatar; using System.Collections.ObjectModel; diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WeaponFilter.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WeaponFilter.cs index 392a6027..99fdd8a0 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WeaponFilter.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WeaponFilter.cs @@ -1,6 +1,7 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. +using Snap.Hutao.Control.SuggestBox; using Snap.Hutao.Model.Intrinsic.Frozen; using Snap.Hutao.Model.Metadata.Weapon; using System.Collections.ObjectModel; diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiAvatarViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiAvatarViewModel.cs index 1691c7ab..4c55dca1 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiAvatarViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiAvatarViewModel.cs @@ -1,9 +1,8 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. -using CommunityToolkit.WinUI.Controls; -using Microsoft.UI.Xaml.Controls; using Snap.Hutao.Control.Collection.AdvancedCollectionView; +using Snap.Hutao.Control.SuggestBox; using Snap.Hutao.Factory.ContentDialog; using Snap.Hutao.Model.Calculable; using Snap.Hutao.Model.Entity.Primitive; @@ -37,7 +36,7 @@ namespace Snap.Hutao.ViewModel.Wiki; [HighQuality] [ConstructorGenerated] [Injection(InjectAs.Scoped)] -internal sealed partial class WikiAvatarViewModel : Abstraction.ViewModel, IWikiViewModelInitialization +internal sealed partial class WikiAvatarViewModel : Abstraction.ViewModel { private readonly IContentDialogFactory contentDialogFactory; private readonly ICultivationService cultivationService; @@ -90,15 +89,6 @@ internal sealed partial class WikiAvatarViewModel : Abstraction.ViewModel, IWiki public FrozenSet? AvailableQueries { get => availableQueries; } - public void Initialize(ITokenizingTextBoxAccessor accessor) - { - accessor.TokenizingTextBox.TextChanged += OnFilterSuggestionRequested; - accessor.TokenizingTextBox.QuerySubmitted += OnQuerySubmitted; - accessor.TokenizingTextBox.TokenItemAdding += OnTokenItemAdding; - accessor.TokenizingTextBox.TokenItemAdded += OnTokenItemModified; - accessor.TokenizingTextBox.TokenItemRemoved += OnTokenItemModified; - } - protected override async ValueTask InitializeUIAsync() { if (!await metadataService.InitializeAsync().ConfigureAwait(false)) @@ -234,60 +224,7 @@ internal sealed partial class WikiAvatarViewModel : Abstraction.ViewModel, IWiki BaseValueInfo = new(avatar.MaxLevel, propertyCurveValues, levelAvatarCurveMap, avatarPromoteMap); } - private void OnFilterSuggestionRequested(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs args) - { - if (Avatars is null) - { - return; - } - - if (string.IsNullOrWhiteSpace(FilterToken)) - { - return; - } - - if (args.Reason == AutoSuggestionBoxTextChangeReason.UserInput) - { - sender.ItemsSource = availableQueries.Where(q => q.Contains(FilterToken, StringComparison.OrdinalIgnoreCase)); - } - } - - private void OnQuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args) - { - if (args.ChosenSuggestion is not null) - { - return; - } - - ApplyFilter(); - } - - private void OnTokenItemAdding(TokenizingTextBox sender, TokenItemAddingEventArgs args) - { - if (string.IsNullOrWhiteSpace(args.TokenText)) - { - return; - } - - if (Avatars is null) - { - return; - } - - if (Avatars.SourceCollection.SingleOrDefault(a => a.Name == args.TokenText) is { } avatar) - { - args.Item = new SearchToken(avatar); - return; - } - - args.Item = new SearchToken(args.TokenText); - } - - private void OnTokenItemModified(TokenizingTextBox sender, object args) - { - ApplyFilter(); - } - + [Command("FilterCommand")] private void ApplyFilter() { if (Avatars is null) diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiWeaponViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiWeaponViewModel.cs index 3d8a2a3d..05dfbb1c 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiWeaponViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiWeaponViewModel.cs @@ -1,9 +1,8 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. -using CommunityToolkit.WinUI.Controls; -using Microsoft.UI.Xaml.Controls; using Snap.Hutao.Control.Collection.AdvancedCollectionView; +using Snap.Hutao.Control.SuggestBox; using Snap.Hutao.Factory.ContentDialog; using Snap.Hutao.Model.Calculable; using Snap.Hutao.Model.Entity.Primitive; @@ -34,7 +33,7 @@ namespace Snap.Hutao.ViewModel.Wiki; /// [ConstructorGenerated] [Injection(InjectAs.Scoped)] -internal sealed partial class WikiWeaponViewModel : Abstraction.ViewModel, IWikiViewModelInitialization +internal sealed partial class WikiWeaponViewModel : Abstraction.ViewModel { private readonly IContentDialogFactory contentDialogFactory; private readonly CalculateClient calculateClient; @@ -87,15 +86,6 @@ internal sealed partial class WikiWeaponViewModel : Abstraction.ViewModel, IWiki public FrozenSet AvailableQueries { get => availableQueries; } - public void Initialize(ITokenizingTextBoxAccessor accessor) - { - accessor.TokenizingTextBox.TextChanged += OnFilterSuggestionRequested; - accessor.TokenizingTextBox.QuerySubmitted += OnQuerySubmitted; - accessor.TokenizingTextBox.TokenItemAdding += OnTokenItemAdding; - accessor.TokenizingTextBox.TokenItemAdded += OnTokenItemModified; - accessor.TokenizingTextBox.TokenItemRemoved += OnTokenItemModified; - } - /// protected override async Task OpenUIAsync() { @@ -216,60 +206,7 @@ internal sealed partial class WikiWeaponViewModel : Abstraction.ViewModel, IWiki BaseValueInfo = new(weapon.MaxLevel, propertyCurveValues, levelWeaponCurveMap, weaponPromoteMap); } - private void OnFilterSuggestionRequested(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs args) - { - if (Weapons is null) - { - return; - } - - if (string.IsNullOrWhiteSpace(FilterToken)) - { - return; - } - - if (args.Reason == AutoSuggestionBoxTextChangeReason.UserInput) - { - sender.ItemsSource = availableQueries.Where(q => q.Contains(FilterToken, StringComparison.OrdinalIgnoreCase)); - } - } - - private void OnQuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args) - { - if (args.ChosenSuggestion is not null) - { - return; - } - - ApplyFilter(); - } - - private void OnTokenItemAdding(TokenizingTextBox sender, TokenItemAddingEventArgs args) - { - if (string.IsNullOrWhiteSpace(args.TokenText)) - { - return; - } - - if (Weapons is null) - { - return; - } - - if (Weapons.SourceCollection.SingleOrDefault(w => w.Name == args.TokenText) is { } weapon) - { - args.Item = new SearchToken(weapon); - return; - } - - args.Item = new SearchToken(args.TokenText); - } - - private void OnTokenItemModified(TokenizingTextBox sender, object args) - { - ApplyFilter(); - } - + [Command("FilterCommand")] private void ApplyFilter() { if (Weapons is null) From 6de3cba550be704f41bffe18b375975cff5647b5 Mon Sep 17 00:00:00 2001 From: qhy040404 Date: Mon, 4 Mar 2024 00:09:38 +0800 Subject: [PATCH 05/10] remove unused code --- .../ViewModel/Wiki/ITokenizingTextBoxAccessor.cs | 12 ------------ .../ViewModel/Wiki/IWikiViewModelInitialization.cs | 9 --------- 2 files changed, 21 deletions(-) delete mode 100644 src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/ITokenizingTextBoxAccessor.cs delete mode 100644 src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/IWikiViewModelInitialization.cs diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/ITokenizingTextBoxAccessor.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/ITokenizingTextBoxAccessor.cs deleted file mode 100644 index 64964f1e..00000000 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/ITokenizingTextBoxAccessor.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) DGP Studio. All rights reserved. -// Licensed under the MIT license. - -using CommunityToolkit.WinUI.Controls; -using Snap.Hutao.Control; - -namespace Snap.Hutao.ViewModel.Wiki; - -internal interface ITokenizingTextBoxAccessor : IXamlElementAccessor -{ - TokenizingTextBox TokenizingTextBox { get; } -} diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/IWikiViewModelInitialization.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/IWikiViewModelInitialization.cs deleted file mode 100644 index c41c48cf..00000000 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/IWikiViewModelInitialization.cs +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright (c) DGP Studio. All rights reserved. -// Licensed under the MIT license. - -namespace Snap.Hutao.ViewModel.Wiki; - -internal interface IWikiViewModelInitialization -{ - void Initialize(ITokenizingTextBoxAccessor accessor); -} From 2ea53fd39d15b8c2428121db2c7e828efbf3ac0d Mon Sep 17 00:00:00 2001 From: qhy040404 Date: Mon, 4 Mar 2024 18:01:44 +0800 Subject: [PATCH 06/10] Frozen Dictionaries --- .../Control/Panel/PanelSelector.xaml.cs | 11 ++--- .../Snap.Hutao/Core/Caching/ImageCache.cs | 12 +++--- .../Snap.Hutao/Core/TypeNameHelper.cs | 39 ++++++++--------- .../Converter/AssociationTypeIconConverter.cs | 25 +++++------ .../Converter/ElementNameIconConverter.cs | 41 +++++++++--------- .../Converter/QualityColorConverter.cs | 19 +++++---- .../Converter/WeaponTypeIconConverter.cs | 17 ++++---- .../Factory/GachaConfigTypeComparer.cs | 16 +++---- .../Control/AnnouncementContentViewer.xaml.cs | 23 +++++----- .../AvatarProperty/AvatarProperty.cs | 42 +++++++++---------- .../Snap.Hutao/Web/Hoyolab/HoyolabOptions.cs | 25 +++++------ 11 files changed, 139 insertions(+), 131 deletions(-) diff --git a/src/Snap.Hutao/Snap.Hutao/Control/Panel/PanelSelector.xaml.cs b/src/Snap.Hutao/Snap.Hutao/Control/Panel/PanelSelector.xaml.cs index 8ce1ca54..796ef86b 100644 --- a/src/Snap.Hutao/Snap.Hutao/Control/Panel/PanelSelector.xaml.cs +++ b/src/Snap.Hutao/Snap.Hutao/Control/Panel/PanelSelector.xaml.cs @@ -4,6 +4,7 @@ using CommunityToolkit.WinUI.Controls; using Microsoft.UI.Xaml; using Snap.Hutao.Core.Setting; +using System.Collections.Frozen; namespace Snap.Hutao.Control.Panel; @@ -19,11 +20,11 @@ internal sealed partial class PanelSelector : Segmented public const string List = nameof(List); public const string Grid = nameof(Grid); - private static readonly Dictionary IndexTypeMap = new() - { - [0] = List, - [1] = Grid, - }; + private static readonly FrozenDictionary IndexTypeMap = FrozenDictionary.ToFrozenDictionary( + [ + KeyValuePair.Create(0, List), + KeyValuePair.Create(1, Grid), + ]); private readonly RoutedEventHandler loadedEventHandler; private readonly RoutedEventHandler unloadedEventHandler; diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Caching/ImageCache.cs b/src/Snap.Hutao/Snap.Hutao/Core/Caching/ImageCache.cs index 84a95a90..5fcf38ef 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/Caching/ImageCache.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/Caching/ImageCache.cs @@ -26,12 +26,12 @@ internal sealed partial class ImageCache : IImageCache, IImageCacheFilePathOpera { private const string CacheFolderName = nameof(ImageCache); - private readonly FrozenDictionary retryCountToDelay = new Dictionary() - { - [0] = TimeSpan.FromSeconds(4), - [1] = TimeSpan.FromSeconds(16), - [2] = TimeSpan.FromSeconds(64), - }.ToFrozenDictionary(); + private readonly FrozenDictionary retryCountToDelay = FrozenDictionary.ToFrozenDictionary( + [ + KeyValuePair.Create(0, TimeSpan.FromSeconds(4)), + KeyValuePair.Create(1, TimeSpan.FromSeconds(16)), + KeyValuePair.Create(2, TimeSpan.FromSeconds(64)), + ]); private readonly ConcurrentDictionary concurrentTasks = new(); diff --git a/src/Snap.Hutao/Snap.Hutao/Core/TypeNameHelper.cs b/src/Snap.Hutao/Snap.Hutao/Core/TypeNameHelper.cs index 66b635b9..b01f5ebe 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/TypeNameHelper.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/TypeNameHelper.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Collections.Frozen; using System.Text; namespace Snap.Hutao.Core; @@ -14,25 +15,25 @@ internal static class TypeNameHelper { private const char DefaultNestedTypeDelimiter = '+'; - private static readonly Dictionary BuiltInTypeNames = new() - { - { typeof(void), "void" }, - { typeof(bool), "bool" }, - { typeof(byte), "byte" }, - { typeof(char), "char" }, - { typeof(decimal), "decimal" }, - { typeof(double), "double" }, - { typeof(float), "float" }, - { typeof(int), "int" }, - { typeof(long), "long" }, - { typeof(object), "object" }, - { typeof(sbyte), "sbyte" }, - { typeof(short), "short" }, - { typeof(string), "string" }, - { typeof(uint), "uint" }, - { typeof(ulong), "ulong" }, - { typeof(ushort), "ushort" }, - }; + private static readonly FrozenDictionary BuiltInTypeNames = FrozenDictionary.ToFrozenDictionary( + [ + KeyValuePair.Create(typeof(void), "void"), + KeyValuePair.Create(typeof(bool), "bool"), + KeyValuePair.Create(typeof(byte), "byte"), + KeyValuePair.Create(typeof(char), "char"), + KeyValuePair.Create(typeof(decimal), "decimal"), + KeyValuePair.Create(typeof(double), "double"), + KeyValuePair.Create(typeof(float), "float"), + KeyValuePair.Create(typeof(int), "int"), + KeyValuePair.Create(typeof(long), "long"), + KeyValuePair.Create(typeof(object), "object"), + KeyValuePair.Create(typeof(sbyte), "sbyte"), + KeyValuePair.Create(typeof(short), "short"), + KeyValuePair.Create(typeof(string), "string"), + KeyValuePair.Create(typeof(uint), "uint"), + KeyValuePair.Create(typeof(ulong), "ulong"), + KeyValuePair.Create(typeof(ushort), "ushort"), + ]); /// /// 获取对象类型的显示名称 diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/AssociationTypeIconConverter.cs b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/AssociationTypeIconConverter.cs index 93321a30..d70a868a 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/AssociationTypeIconConverter.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/AssociationTypeIconConverter.cs @@ -3,23 +3,24 @@ using Snap.Hutao.Control; using Snap.Hutao.Model.Intrinsic; +using System.Collections.Frozen; namespace Snap.Hutao.Model.Metadata.Converter; internal sealed class AssociationTypeIconConverter : ValueConverter { - private static readonly Dictionary LocalizedNameToAssociationType = new() - { - [SH.ModelIntrinsicAssociationTypeMondstadt] = AssociationType.ASSOC_TYPE_MONDSTADT, - [SH.ModelIntrinsicAssociationTypeLiyue] = AssociationType.ASSOC_TYPE_LIYUE, - [SH.ModelIntrinsicAssociationTypeFatui] = AssociationType.ASSOC_TYPE_FATUI, - [SH.ModelIntrinsicAssociationTypeInazuma] = AssociationType.ASSOC_TYPE_INAZUMA, - [SH.ModelIntrinsicAssociationTypeRanger] = AssociationType.ASSOC_TYPE_RANGER, - [SH.ModelIntrinsicAssociationTypeSumeru] = AssociationType.ASSOC_TYPE_SUMERU, - [SH.ModelIntrinsicAssociationTypeFontaine] = AssociationType.ASSOC_TYPE_FONTAINE, - [SH.ModelIntrinsicAssociationTypeNatlan] = AssociationType.ASSOC_TYPE_NATLAN, - [SH.ModelIntrinsicAssociationTypeSnezhnaya] = AssociationType.ASSOC_TYPE_SNEZHNAYA, - }; + private static readonly FrozenDictionary LocalizedNameToAssociationType = FrozenDictionary.ToFrozenDictionary( + [ + KeyValuePair.Create(SH.ModelIntrinsicAssociationTypeMondstadt, AssociationType.ASSOC_TYPE_MONDSTADT), + KeyValuePair.Create(SH.ModelIntrinsicAssociationTypeLiyue, AssociationType.ASSOC_TYPE_LIYUE), + KeyValuePair.Create(SH.ModelIntrinsicAssociationTypeFatui, AssociationType.ASSOC_TYPE_FATUI), + KeyValuePair.Create(SH.ModelIntrinsicAssociationTypeInazuma, AssociationType.ASSOC_TYPE_INAZUMA), + KeyValuePair.Create(SH.ModelIntrinsicAssociationTypeRanger, AssociationType.ASSOC_TYPE_RANGER), + KeyValuePair.Create(SH.ModelIntrinsicAssociationTypeSumeru, AssociationType.ASSOC_TYPE_SUMERU), + KeyValuePair.Create(SH.ModelIntrinsicAssociationTypeFontaine, AssociationType.ASSOC_TYPE_FONTAINE), + KeyValuePair.Create(SH.ModelIntrinsicAssociationTypeNatlan, AssociationType.ASSOC_TYPE_NATLAN), + KeyValuePair.Create(SH.ModelIntrinsicAssociationTypeSnezhnaya, AssociationType.ASSOC_TYPE_SNEZHNAYA), + ]); public static Uri? AssociationTypeNameToIconUri(string associationTypeName) { diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/ElementNameIconConverter.cs b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/ElementNameIconConverter.cs index 34e2230b..a2579baa 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/ElementNameIconConverter.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/ElementNameIconConverter.cs @@ -3,6 +3,7 @@ using Snap.Hutao.Control; using Snap.Hutao.Model.Intrinsic; +using System.Collections.Frozen; namespace Snap.Hutao.Model.Metadata.Converter; @@ -12,27 +13,27 @@ namespace Snap.Hutao.Model.Metadata.Converter; [HighQuality] internal sealed class ElementNameIconConverter : ValueConverter { - private static readonly Dictionary LocalizedNameToElementIconName = new() - { - [SH.ModelIntrinsicElementNameElec] = "Electric", - [SH.ModelIntrinsicElementNameFire] = "Fire", - [SH.ModelIntrinsicElementNameGrass] = "Grass", - [SH.ModelIntrinsicElementNameIce] = "Ice", - [SH.ModelIntrinsicElementNameRock] = "Rock", - [SH.ModelIntrinsicElementNameWater] = "Water", - [SH.ModelIntrinsicElementNameWind] = "Wind", - }; + private static readonly FrozenDictionary LocalizedNameToElementIconName = FrozenDictionary.ToFrozenDictionary( + [ + KeyValuePair.Create(SH.ModelIntrinsicElementNameElec, "Electric"), + KeyValuePair.Create(SH.ModelIntrinsicElementNameFire, "Fire"), + KeyValuePair.Create(SH.ModelIntrinsicElementNameGrass, "Grass"), + KeyValuePair.Create(SH.ModelIntrinsicElementNameIce, "Ice"), + KeyValuePair.Create(SH.ModelIntrinsicElementNameRock, "Rock"), + KeyValuePair.Create(SH.ModelIntrinsicElementNameWater, "Water"), + KeyValuePair.Create(SH.ModelIntrinsicElementNameWind, "Wind"), + ]); - private static readonly Dictionary LocalizedNameToElementType = new() - { - [SH.ModelIntrinsicElementNameElec] = ElementType.Electric, - [SH.ModelIntrinsicElementNameFire] = ElementType.Fire, - [SH.ModelIntrinsicElementNameGrass] = ElementType.Grass, - [SH.ModelIntrinsicElementNameIce] = ElementType.Ice, - [SH.ModelIntrinsicElementNameRock] = ElementType.Rock, - [SH.ModelIntrinsicElementNameWater] = ElementType.Water, - [SH.ModelIntrinsicElementNameWind] = ElementType.Wind, - }; + private static readonly FrozenDictionary LocalizedNameToElementType = FrozenDictionary.ToFrozenDictionary( + [ + KeyValuePair.Create(SH.ModelIntrinsicElementNameElec, ElementType.Electric), + KeyValuePair.Create(SH.ModelIntrinsicElementNameFire, ElementType.Fire), + KeyValuePair.Create(SH.ModelIntrinsicElementNameGrass, ElementType.Grass), + KeyValuePair.Create(SH.ModelIntrinsicElementNameIce, ElementType.Ice), + KeyValuePair.Create(SH.ModelIntrinsicElementNameRock, ElementType.Rock), + KeyValuePair.Create(SH.ModelIntrinsicElementNameWater, ElementType.Water), + KeyValuePair.Create(SH.ModelIntrinsicElementNameWind, ElementType.Wind), + ]); /// /// 将中文元素名称转换为图标链接 diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/QualityColorConverter.cs b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/QualityColorConverter.cs index c3da4da8..b85cec8d 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/QualityColorConverter.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/QualityColorConverter.cs @@ -5,6 +5,7 @@ using Microsoft.UI; using Snap.Hutao.Control; using Snap.Hutao.Model.Intrinsic; using Snap.Hutao.Win32; +using System.Collections.Frozen; using Windows.UI; namespace Snap.Hutao.Model.Metadata.Converter; @@ -15,15 +16,15 @@ namespace Snap.Hutao.Model.Metadata.Converter; [HighQuality] internal sealed class QualityColorConverter : ValueConverter { - private static readonly Dictionary LocalizedNameToQualityType = new() - { - [SH.ModelIntrinsicItemQualityWhite] = QualityType.QUALITY_WHITE, - [SH.ModelIntrinsicItemQualityGreen] = QualityType.QUALITY_GREEN, - [SH.ModelIntrinsicItemQualityBlue] = QualityType.QUALITY_BLUE, - [SH.ModelIntrinsicItemQualityPurple] = QualityType.QUALITY_PURPLE, - [SH.ModelIntrinsicItemQualityOrange] = QualityType.QUALITY_ORANGE, - [SH.ModelIntrinsicItemQualityRed] = QualityType.QUALITY_ORANGE_SP, - }; + private static readonly FrozenDictionary LocalizedNameToQualityType = FrozenDictionary.ToFrozenDictionary( + [ + KeyValuePair.Create(SH.ModelIntrinsicItemQualityWhite, QualityType.QUALITY_WHITE), + KeyValuePair.Create(SH.ModelIntrinsicItemQualityGreen, QualityType.QUALITY_GREEN), + KeyValuePair.Create(SH.ModelIntrinsicItemQualityBlue, QualityType.QUALITY_BLUE), + KeyValuePair.Create(SH.ModelIntrinsicItemQualityPurple, QualityType.QUALITY_PURPLE), + KeyValuePair.Create(SH.ModelIntrinsicItemQualityOrange, QualityType.QUALITY_ORANGE), + KeyValuePair.Create(SH.ModelIntrinsicItemQualityRed, QualityType.QUALITY_ORANGE_SP), + ]); public static Color QualityNameToColor(string qualityName) { diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/WeaponTypeIconConverter.cs b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/WeaponTypeIconConverter.cs index 41712715..9768a170 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/WeaponTypeIconConverter.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/WeaponTypeIconConverter.cs @@ -3,6 +3,7 @@ using Snap.Hutao.Control; using Snap.Hutao.Model.Intrinsic; +using System.Collections.Frozen; namespace Snap.Hutao.Model.Metadata.Converter; @@ -12,14 +13,14 @@ namespace Snap.Hutao.Model.Metadata.Converter; [HighQuality] internal sealed class WeaponTypeIconConverter : ValueConverter { - private static readonly Dictionary LocalizedNameToWeaponType = new() - { - [SH.ModelIntrinsicWeaponTypeSwordOneHand] = WeaponType.WEAPON_SWORD_ONE_HAND, - [SH.ModelIntrinsicWeaponTypeBow] = WeaponType.WEAPON_BOW, - [SH.ModelIntrinsicWeaponTypePole] = WeaponType.WEAPON_POLE, - [SH.ModelIntrinsicWeaponTypeClaymore] = WeaponType.WEAPON_CLAYMORE, - [SH.ModelIntrinsicWeaponTypeCatalyst] = WeaponType.WEAPON_CATALYST, - }; + private static readonly FrozenDictionary LocalizedNameToWeaponType = FrozenDictionary.ToFrozenDictionary( + [ + KeyValuePair.Create(SH.ModelIntrinsicWeaponTypeSwordOneHand, WeaponType.WEAPON_SWORD_ONE_HAND), + KeyValuePair.Create(SH.ModelIntrinsicWeaponTypeBow, WeaponType.WEAPON_BOW), + KeyValuePair.Create(SH.ModelIntrinsicWeaponTypePole, WeaponType.WEAPON_POLE), + KeyValuePair.Create(SH.ModelIntrinsicWeaponTypeClaymore, WeaponType.WEAPON_CLAYMORE), + KeyValuePair.Create(SH.ModelIntrinsicWeaponTypeCatalyst, WeaponType.WEAPON_CATALYST), + ]); public static Uri WeaponTypeNameToIconUri(string weaponTypeName) { diff --git a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/GachaConfigTypeComparer.cs b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/GachaConfigTypeComparer.cs index c396f2ba..533ff220 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/GachaConfigTypeComparer.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/GachaLog/Factory/GachaConfigTypeComparer.cs @@ -13,14 +13,14 @@ namespace Snap.Hutao.Service.GachaLog.Factory; internal sealed class GachaConfigTypeComparer : IComparer { private static readonly Lazy LazyShared = new(() => new()); - private static readonly FrozenDictionary OrderMap = new Dictionary() - { - [GachaConfigType.AvatarEventWish] = 0, - [GachaConfigType.AvatarEventWish2] = 1, - [GachaConfigType.WeaponEventWish] = 2, - [GachaConfigType.StandardWish] = 3, - [GachaConfigType.NoviceWish] = 4, - }.ToFrozenDictionary(); + private static readonly FrozenDictionary OrderMap = FrozenDictionary.ToFrozenDictionary( + [ + KeyValuePair.Create(GachaConfigType.AvatarEventWish, 0), + KeyValuePair.Create(GachaConfigType.AvatarEventWish2, 1), + KeyValuePair.Create(GachaConfigType.WeaponEventWish, 2), + KeyValuePair.Create(GachaConfigType.StandardWish, 3), + KeyValuePair.Create(GachaConfigType.NoviceWish, 4), + ]); /// /// 共享的比较器 diff --git a/src/Snap.Hutao/Snap.Hutao/View/Control/AnnouncementContentViewer.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/Control/AnnouncementContentViewer.xaml.cs index 6d98101b..4fbc1f56 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Control/AnnouncementContentViewer.xaml.cs +++ b/src/Snap.Hutao/Snap.Hutao/View/Control/AnnouncementContentViewer.xaml.cs @@ -7,6 +7,7 @@ using Microsoft.Web.WebView2.Core; using Snap.Hutao.Control.Extension; using Snap.Hutao.Control.Theme; using Snap.Hutao.Web.Hoyolab.Hk4e.Common.Announcement; +using System.Collections.Frozen; using System.Text; using System.Text.RegularExpressions; using Windows.Foundation; @@ -29,17 +30,17 @@ internal sealed partial class AnnouncementContentViewer : UserControl } """; - private static readonly Dictionary DarkLightReverts = new() - { - { "color:rgba(0,0,0,1)", "color:rgba(255,255,255,1)" }, - { "color:rgba(17,17,17,1)", "color:rgba(238,238,238,1)" }, - { "color:rgba(51,51,51,1)", "color:rgba(204,204,204,1)" }, - { "color:rgba(57,59,64,1)", "color:rgba(198,196,191,1)" }, - { "color:rgba(85,85,85,1)", "color:rgba(170,170,170,1)" }, - { "background-color: rgb(255, 215, 185)", "background-color: rgb(0,40,70)" }, - { "background-color: rgb(254, 245, 231)", "background-color: rgb(1,40,70)" }, - { "background-color:rgb(244, 244, 245)", "background-color:rgba(11, 11, 10)" }, - }; + private static readonly FrozenDictionary DarkLightReverts = FrozenDictionary.ToFrozenDictionary( + [ + KeyValuePair.Create("color:rgba(0,0,0,1)", "color:rgba(255,255,255,1)"), + KeyValuePair.Create("color:rgba(17,17,17,1)", "color:rgba(238,238,238,1)"), + KeyValuePair.Create("color:rgba(51,51,51,1)", "color:rgba(204,204,204,1)"), + KeyValuePair.Create("color:rgba(57,59,64,1)", "color:rgba(198,196,191,1)"), + KeyValuePair.Create("color:rgba(85,85,85,1)", "color:rgba(170,170,170,1)"), + KeyValuePair.Create("background-color: rgb(255, 215, 185)", "background-color: rgb(0,40,70)"), + KeyValuePair.Create("background-color: rgb(254, 245, 231)", "background-color: rgb(1,40,70)"), + KeyValuePair.Create("background-color:rgb(244, 244, 245)", "background-color:rgba(11, 11, 10)"), + ]); private readonly RoutedEventHandler loadEventHandler; private readonly RoutedEventHandler unloadEventHandler; diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/AvatarProperty/AvatarProperty.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/AvatarProperty/AvatarProperty.cs index 9154a949..3162d788 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/AvatarProperty/AvatarProperty.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/AvatarProperty/AvatarProperty.cs @@ -16,27 +16,27 @@ namespace Snap.Hutao.ViewModel.AvatarProperty; [HighQuality] internal sealed class AvatarProperty : ObservableObject, INameIcon, IAlternatingItem { - private static readonly FrozenDictionary PropertyIcons = new Dictionary() - { - [FightProperty.FIGHT_PROP_SKILL_CD_MINUS_RATIO] = Web.HutaoEndpoints.StaticRaw("Property", "UI_Icon_CDReduce.png").ToUri(), - [FightProperty.FIGHT_PROP_CHARGE_EFFICIENCY] = Web.HutaoEndpoints.StaticRaw("Property", "UI_Icon_ChargeEfficiency.png").ToUri(), - [FightProperty.FIGHT_PROP_CRITICAL] = Web.HutaoEndpoints.StaticRaw("Property", "UI_Icon_Critical.png").ToUri(), - [FightProperty.FIGHT_PROP_CRITICAL_HURT] = Web.HutaoEndpoints.StaticRaw("Property", "UI_Icon_Critical_Hurt.png").ToUri(), - [FightProperty.FIGHT_PROP_CUR_ATTACK] = Web.HutaoEndpoints.StaticRaw("Property", "UI_Icon_CurAttack.png").ToUri(), - [FightProperty.FIGHT_PROP_CUR_DEFENSE] = Web.HutaoEndpoints.StaticRaw("Property", "UI_Icon_CurDefense.png").ToUri(), - [FightProperty.FIGHT_PROP_ELEMENT_MASTERY] = Web.HutaoEndpoints.StaticRaw("Property", "UI_Icon_Element.png").ToUri(), - [FightProperty.FIGHT_PROP_ELEC_ADD_HURT] = Web.HutaoEndpoints.StaticRaw("Property", "UI_Icon_Element_Electric.png").ToUri(), - [FightProperty.FIGHT_PROP_FIRE_ADD_HURT] = Web.HutaoEndpoints.StaticRaw("Property", "UI_Icon_Element_Fire.png").ToUri(), - [FightProperty.FIGHT_PROP_GRASS_ADD_HURT] = Web.HutaoEndpoints.StaticRaw("Property", "UI_Icon_Element_Grass.png").ToUri(), - [FightProperty.FIGHT_PROP_ICE_ADD_HURT] = Web.HutaoEndpoints.StaticRaw("Property", "UI_Icon_Element_Ice.png").ToUri(), - [FightProperty.FIGHT_PROP_ROCK_ADD_HURT] = Web.HutaoEndpoints.StaticRaw("Property", "UI_Icon_Element_Rock.png").ToUri(), - [FightProperty.FIGHT_PROP_WATER_ADD_HURT] = Web.HutaoEndpoints.StaticRaw("Property", "UI_Icon_Element_Water.png").ToUri(), - [FightProperty.FIGHT_PROP_WIND_ADD_HURT] = Web.HutaoEndpoints.StaticRaw("Property", "UI_Icon_Element_Wind.png").ToUri(), - [FightProperty.FIGHT_PROP_HEAL_ADD] = Web.HutaoEndpoints.StaticRaw("Property", "UI_Icon_Heal.png").ToUri(), - [FightProperty.FIGHT_PROP_MAX_HP] = Web.HutaoEndpoints.StaticRaw("Property", "UI_Icon_MaxHp.png").ToUri(), - [FightProperty.FIGHT_PROP_PHYSICAL_ADD_HURT] = Web.HutaoEndpoints.StaticRaw("Property", "UI_Icon_PhysicalAttackUp.png").ToUri(), - [FightProperty.FIGHT_PROP_SHIELD_COST_MINUS_RATIO] = Web.HutaoEndpoints.StaticRaw("Property", "UI_Icon_ShieldCostMinus.png").ToUri(), - }.ToFrozenDictionary(); + private static readonly FrozenDictionary PropertyIcons = FrozenDictionary.ToFrozenDictionary( + [ + KeyValuePair.Create(FightProperty.FIGHT_PROP_SKILL_CD_MINUS_RATIO, Web.HutaoEndpoints.StaticRaw("Property", "UI_Icon_CDReduce.png").ToUri()), + KeyValuePair.Create(FightProperty.FIGHT_PROP_CHARGE_EFFICIENCY, Web.HutaoEndpoints.StaticRaw("Property", "UI_Icon_ChargeEfficiency.png").ToUri()), + KeyValuePair.Create(FightProperty.FIGHT_PROP_CRITICAL, Web.HutaoEndpoints.StaticRaw("Property", "UI_Icon_Critical.png").ToUri()), + KeyValuePair.Create(FightProperty.FIGHT_PROP_CRITICAL_HURT, Web.HutaoEndpoints.StaticRaw("Property", "UI_Icon_Critical_Hurt.png").ToUri()), + KeyValuePair.Create(FightProperty.FIGHT_PROP_CUR_ATTACK, Web.HutaoEndpoints.StaticRaw("Property", "UI_Icon_CurAttack.png").ToUri()), + KeyValuePair.Create(FightProperty.FIGHT_PROP_CUR_DEFENSE, Web.HutaoEndpoints.StaticRaw("Property", "UI_Icon_CurDefense.png").ToUri()), + KeyValuePair.Create(FightProperty.FIGHT_PROP_ELEMENT_MASTERY, Web.HutaoEndpoints.StaticRaw("Property", "UI_Icon_Element.png").ToUri()), + KeyValuePair.Create(FightProperty.FIGHT_PROP_ELEC_ADD_HURT, Web.HutaoEndpoints.StaticRaw("Property", "UI_Icon_Element_Electric.png").ToUri()), + KeyValuePair.Create(FightProperty.FIGHT_PROP_FIRE_ADD_HURT, Web.HutaoEndpoints.StaticRaw("Property", "UI_Icon_Element_Fire.png").ToUri()), + KeyValuePair.Create(FightProperty.FIGHT_PROP_GRASS_ADD_HURT, Web.HutaoEndpoints.StaticRaw("Property", "UI_Icon_Element_Grass.png").ToUri()), + KeyValuePair.Create(FightProperty.FIGHT_PROP_ICE_ADD_HURT, Web.HutaoEndpoints.StaticRaw("Property", "UI_Icon_Element_Ice.png").ToUri()), + KeyValuePair.Create(FightProperty.FIGHT_PROP_ROCK_ADD_HURT, Web.HutaoEndpoints.StaticRaw("Property", "UI_Icon_Element_Rock.png").ToUri()), + KeyValuePair.Create(FightProperty.FIGHT_PROP_WATER_ADD_HURT, Web.HutaoEndpoints.StaticRaw("Property", "UI_Icon_Element_Water.png").ToUri()), + KeyValuePair.Create(FightProperty.FIGHT_PROP_WIND_ADD_HURT, Web.HutaoEndpoints.StaticRaw("Property", "UI_Icon_Element_Wind.png").ToUri()), + KeyValuePair.Create(FightProperty.FIGHT_PROP_HEAL_ADD, Web.HutaoEndpoints.StaticRaw("Property", "UI_Icon_Heal.png").ToUri()), + KeyValuePair.Create(FightProperty.FIGHT_PROP_MAX_HP, Web.HutaoEndpoints.StaticRaw("Property", "UI_Icon_MaxHp.png").ToUri()), + KeyValuePair.Create(FightProperty.FIGHT_PROP_PHYSICAL_ADD_HURT, Web.HutaoEndpoints.StaticRaw("Property", "UI_Icon_PhysicalAttackUp.png").ToUri()), + KeyValuePair.Create(FightProperty.FIGHT_PROP_SHIELD_COST_MINUS_RATIO, Web.HutaoEndpoints.StaticRaw("Property", "UI_Icon_ShieldCostMinus.png").ToUri()), + ]); private Brush? background; diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/HoyolabOptions.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/HoyolabOptions.cs index ed0b1d08..d521d199 100644 --- a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/HoyolabOptions.cs +++ b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/HoyolabOptions.cs @@ -47,21 +47,22 @@ internal static class HoyolabOptions /// /// 盐 /// - public static FrozenDictionary Salts { get; } = new Dictionary() - { + public static FrozenDictionary Salts { get; } = FrozenDictionary.ToFrozenDictionary( + [ + // Chinese - [SaltType.K2] = SaltConstants.CNK2, - [SaltType.LK2] = SaltConstants.CNLK2, - [SaltType.X4] = "xV8v4Qu54lUKrEYFZkJhB8cuOh9Asafs", - [SaltType.X6] = "t0qEgfub6cvueAPgR5m9aQWWVciEer7v", - [SaltType.PROD] = "JwYDpKvLj6MrMqqYU6jTKF17KNO2PXoS", + KeyValuePair.Create(SaltType.K2, SaltConstants.CNK2), + KeyValuePair.Create(SaltType.LK2, SaltConstants.CNLK2), + KeyValuePair.Create(SaltType.X4, "xV8v4Qu54lUKrEYFZkJhB8cuOh9Asafs"), + KeyValuePair.Create(SaltType.X6, "t0qEgfub6cvueAPgR5m9aQWWVciEer7v"), + KeyValuePair.Create(SaltType.PROD, "JwYDpKvLj6MrMqqYU6jTKF17KNO2PXoS"), // Oversea - [SaltType.OSK2] = SaltConstants.OSK2, - [SaltType.OSLK2] = SaltConstants.OSLK2, - [SaltType.OSX4] = "h4c1d6ywfq5bsbnbhm1bzq7bxzzv6srt", - [SaltType.OSX6] = "okr4obncj8bw5a65hbnn5oo6ixjc3l9w", - }.ToFrozenDictionary(); + KeyValuePair.Create(SaltType.OSK2, SaltConstants.OSK2), + KeyValuePair.Create(SaltType.OSLK2, SaltConstants.OSLK2), + KeyValuePair.Create(SaltType.OSX4, "h4c1d6ywfq5bsbnbhm1bzq7bxzzv6srt"), + KeyValuePair.Create(SaltType.OSX6, "okr4obncj8bw5a65hbnn5oo6ixjc3l9w"), + ]); [SuppressMessage("", "CA1308")] private static string GenerateDeviceId40() From 15a627e50a81614ce559fcbad74c237d91a7dcbe Mon Sep 17 00:00:00 2001 From: qhy040404 Date: Tue, 5 Mar 2024 16:55:28 +0800 Subject: [PATCH 07/10] init all tokens first --- .../Control/SuggestBox/AutoSuggestTokenBox.cs | 24 ++---- .../Control/SuggestBox/ISearchToken.cs | 9 -- .../Control/SuggestBox/ITokenizable.cs | 11 --- .../Control/SuggestBox/SearchToken.Wiki.cs | 86 ------------------- .../Control/SuggestBox/SearchToken.cs | 18 +++- ...chTokenKind.Wiki.cs => SearchTokenKind.cs} | 3 +- .../Metadata/Avatar/Avatar.Implementation.cs | 8 +- .../Metadata/Weapon/Weapon.Implementation.cs | 8 +- .../Snap.Hutao/View/Page/WikiAvatarPage.xaml | 3 +- .../Snap.Hutao/View/Page/WikiWeaponPage.xaml | 3 +- .../Snap.Hutao/ViewModel/Wiki/AvatarFilter.cs | 4 +- .../Snap.Hutao/ViewModel/Wiki/WeaponFilter.cs | 4 +- .../ViewModel/Wiki/WikiAvatarViewModel.cs | 25 +++--- .../ViewModel/Wiki/WikiWeaponViewModel.cs | 21 +++-- 14 files changed, 61 insertions(+), 166 deletions(-) delete mode 100644 src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/ISearchToken.cs delete mode 100644 src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/ITokenizable.cs delete mode 100644 src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/SearchToken.Wiki.cs rename src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/{SearchTokenKind.Wiki.cs => SearchTokenKind.cs} (87%) diff --git a/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/AutoSuggestTokenBox.cs b/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/AutoSuggestTokenBox.cs index 6ed4af22..2d6b7a45 100644 --- a/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/AutoSuggestTokenBox.cs +++ b/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/AutoSuggestTokenBox.cs @@ -4,11 +4,13 @@ using CommunityToolkit.WinUI.Controls; using Microsoft.UI.Xaml.Controls; using Snap.Hutao.Control.SuggestBox; +using Snap.Hutao.Model.Intrinsic.Frozen; +using System.Collections.Frozen; namespace Snap.Hutao.View.Control; [DependencyProperty("FilterCommand", typeof(ICommand))] -[DependencyProperty("ITokenizableItemsSource", typeof(IEnumerable))] +[DependencyProperty("AvailableTokens", typeof(FrozenDictionary))] internal sealed partial class AutoSuggestTokenBox : TokenizingTextBox { public AutoSuggestTokenBox() @@ -22,11 +24,6 @@ internal sealed partial class AutoSuggestTokenBox : TokenizingTextBox private void OnFilterSuggestionRequested(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs args) { - if (SuggestedItemsSource is not IEnumerable availableQueries) - { - return; - } - if (string.IsNullOrWhiteSpace(Text)) { return; @@ -34,7 +31,7 @@ internal sealed partial class AutoSuggestTokenBox : TokenizingTextBox if (args.Reason == AutoSuggestionBoxTextChangeReason.UserInput) { - sender.ItemsSource = availableQueries.Where(q => q.Contains(Text, StringComparison.OrdinalIgnoreCase)); + sender.ItemsSource = AvailableTokens.Values.Where(q => q.Value.Contains(Text, StringComparison.OrdinalIgnoreCase)); } } @@ -58,18 +55,7 @@ internal sealed partial class AutoSuggestTokenBox : TokenizingTextBox return; } - if (ITokenizableItemsSource is null) - { - return; - } - - if (ITokenizableItemsSource.SingleOrDefault(i => i.Name == args.TokenText) is { } item) - { - args.Item = item.Tokenize(); - return; - } - - args.Item = new SearchToken(args.TokenText); + args.Item = AvailableTokens[args.TokenText]; } private void OnTokenItemModified(TokenizingTextBox sender, object args) diff --git a/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/ISearchToken.cs b/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/ISearchToken.cs deleted file mode 100644 index 7b054f10..00000000 --- a/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/ISearchToken.cs +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright (c) DGP Studio. All rights reserved. -// Licensed under the MIT license. - -namespace Snap.Hutao.Control.SuggestBox; - -internal interface ISearchToken -{ - string Value { get; set; } -} diff --git a/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/ITokenizable.cs b/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/ITokenizable.cs deleted file mode 100644 index bb8f32b8..00000000 --- a/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/ITokenizable.cs +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) DGP Studio. All rights reserved. -// Licensed under the MIT license. - -namespace Snap.Hutao.Control.SuggestBox; - -internal interface ITokenizable -{ - string Name { get; } - - ISearchToken Tokenize(); -} diff --git a/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/SearchToken.Wiki.cs b/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/SearchToken.Wiki.cs deleted file mode 100644 index 256f51ee..00000000 --- a/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/SearchToken.Wiki.cs +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright (c) DGP Studio. All rights reserved. -// Licensed under the MIT license. - -using Snap.Hutao.Model.Intrinsic.Frozen; -using Snap.Hutao.Model.Metadata.Converter; -using Windows.UI; - -namespace Snap.Hutao.Control.SuggestBox; - -internal partial class SearchToken -{ - private SearchTokenKind kind; - private bool isKindInitialized; - private object isKindInitializedLock = new(); - - public SearchToken(string value, Uri? sideIconUri) - : this(value) - { - SideIconUri = sideIconUri; - } - - public Uri? SideIconUri { get; } - - public Uri? IconUri - { - get => Kind switch - { - SearchTokenKind.AssociationTypes => AssociationTypeIconConverter.AssociationTypeNameToIconUri(Value), - SearchTokenKind.ElementNames => ElementNameIconConverter.ElementNameToIconUri(Value), - SearchTokenKind.WeaponTypes => WeaponTypeIconConverter.WeaponTypeNameToIconUri(Value), - _ => null, - }; - } - - public Color? Quality - { - get => Kind switch - { - SearchTokenKind.ItemQualities => QualityColorConverter.QualityNameToColor(Value), - _ => null, - }; - } - - public SearchTokenKind Kind - { - get - { - return LazyInitializer.EnsureInitialized(ref kind, ref isKindInitialized, ref isKindInitializedLock, GetKind); - - SearchTokenKind GetKind() - { - if (IntrinsicFrozen.AssociationTypes.Contains(Value)) - { - return SearchTokenKind.AssociationTypes; - } - - if (IntrinsicFrozen.BodyTypes.Contains(Value)) - { - return SearchTokenKind.BodyTypes; - } - - if (IntrinsicFrozen.ElementNames.Contains(Value)) - { - return SearchTokenKind.ElementNames; - } - - if (IntrinsicFrozen.FightProperties.Contains(Value)) - { - return SearchTokenKind.FightProperties; - } - - if (IntrinsicFrozen.ItemQualities.Contains(Value)) - { - return SearchTokenKind.ItemQualities; - } - - if (IntrinsicFrozen.WeaponTypes.Contains(Value)) - { - return SearchTokenKind.WeaponTypes; - } - - return SearchTokenKind.Other; - } - } - } -} diff --git a/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/SearchToken.cs b/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/SearchToken.cs index 0eb17654..1ee15e17 100644 --- a/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/SearchToken.cs +++ b/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/SearchToken.cs @@ -1,17 +1,31 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. +using Windows.UI; + namespace Snap.Hutao.Control.SuggestBox; -internal sealed partial class SearchToken : ISearchToken +internal sealed class SearchToken { - public SearchToken(string value) + public SearchToken(string value, SearchTokenKind kind, Uri? iconUri = null, Uri? sideIconUri = null, Color? quality = null) { Value = value; + Kind = kind; + IconUri = iconUri; + SideIconUri = sideIconUri; + Quality = quality; } + public SearchTokenKind Kind { get; } + public string Value { get; set; } = default!; + public Uri? IconUri { get; } + + public Uri? SideIconUri { get; } + + public Color? Quality { get; } + public override string ToString() { return Value; diff --git a/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/SearchTokenKind.Wiki.cs b/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/SearchTokenKind.cs similarity index 87% rename from src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/SearchTokenKind.Wiki.cs rename to src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/SearchTokenKind.cs index 4f1868c8..f687a205 100644 --- a/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/SearchTokenKind.Wiki.cs +++ b/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/SearchTokenKind.cs @@ -6,10 +6,11 @@ namespace Snap.Hutao.Control.SuggestBox; internal enum SearchTokenKind { AssociationTypes, + Avatars, BodyTypes, ElementNames, FightProperties, ItemQualities, - Other, // Include avatar and weapon + Weapons, WeaponTypes, } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Avatar/Avatar.Implementation.cs b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Avatar/Avatar.Implementation.cs index 343afd8b..4871692d 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Avatar/Avatar.Implementation.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Avatar/Avatar.Implementation.cs @@ -1,7 +1,6 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. -using Snap.Hutao.Control.SuggestBox; using Snap.Hutao.Model.Calculable; using Snap.Hutao.Model.Metadata.Abstraction; using Snap.Hutao.Model.Metadata.Converter; @@ -15,7 +14,7 @@ namespace Snap.Hutao.Model.Metadata.Avatar; /// /// 角色的接口实现部分 /// -internal partial class Avatar : IStatisticsItemSource, ISummaryItemSource, IItemSource, INameQuality, ICalculableSource, ITokenizable +internal partial class Avatar : IStatisticsItemSource, ISummaryItemSource, IItemSource, INameQuality, ICalculableSource { /// /// [非元数据] 搭配数据 @@ -97,9 +96,4 @@ internal partial class Avatar : IStatisticsItemSource, ISummaryItemSource, IItem IsUp = isUp, }; } - - public ISearchToken Tokenize() - { - return new SearchToken(Name, AvatarSideIconConverter.IconNameToUri(SideIcon)); - } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Weapon/Weapon.Implementation.cs b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Weapon/Weapon.Implementation.cs index f677d19b..86a4465c 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Weapon/Weapon.Implementation.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Weapon/Weapon.Implementation.cs @@ -1,7 +1,6 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. -using Snap.Hutao.Control.SuggestBox; using Snap.Hutao.Model.Calculable; using Snap.Hutao.Model.Intrinsic; using Snap.Hutao.Model.Metadata.Abstraction; @@ -15,7 +14,7 @@ namespace Snap.Hutao.Model.Metadata.Weapon; /// /// 武器的接口实现 /// -internal sealed partial class Weapon : IStatisticsItemSource, ISummaryItemSource, IItemSource, INameQuality, ICalculableSource, ITokenizable +internal sealed partial class Weapon : IStatisticsItemSource, ISummaryItemSource, IItemSource, INameQuality, ICalculableSource { /// /// [非元数据] 搭配数据 @@ -105,9 +104,4 @@ internal sealed partial class Weapon : IStatisticsItemSource, ISummaryItemSource IsUp = isUp, }; } - - public ISearchToken Tokenize() - { - return new SearchToken(Name, EquipIconConverter.IconNameToUri(Icon)); - } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/WikiAvatarPage.xaml b/src/Snap.Hutao/Snap.Hutao/View/Page/WikiAvatarPage.xaml index af3cf59f..32660930 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Page/WikiAvatarPage.xaml +++ b/src/Snap.Hutao/Snap.Hutao/View/Page/WikiAvatarPage.xaml @@ -312,12 +312,13 @@ Margin="6,-2,6,6" HorizontalAlignment="Stretch" VerticalContentAlignment="Center" + AvailableTokens="{Binding AvailableTokens}" FilterCommand="{Binding FilterCommand}" - ITokenizableItemsSource="{Binding Avatars.SourceCollection}" ItemsSource="{Binding FilterTokens, Mode=TwoWay}" MaximumTokens="5" PlaceholderText="{shcm:ResourceString Name=ViewPageWiKiAvatarAutoSuggestBoxPlaceHolder}" QueryIcon="{cw:FontIconSource Glyph=}" + SuggestedItemTemplate="{StaticResource TokenTemplate}" SuggestedItemsSource="{Binding AvailableQueries}" Text="{Binding FilterToken, Mode=TwoWay}" TokenItemTemplate="{StaticResource TokenTemplate}"/> diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/WikiWeaponPage.xaml b/src/Snap.Hutao/Snap.Hutao/View/Page/WikiWeaponPage.xaml index 4db320fc..84f3f061 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Page/WikiWeaponPage.xaml +++ b/src/Snap.Hutao/Snap.Hutao/View/Page/WikiWeaponPage.xaml @@ -179,12 +179,13 @@ Margin="6,-2,6,6" HorizontalAlignment="Stretch" VerticalContentAlignment="Center" + AvailableTokens="{Binding AvailableTokens}" FilterCommand="{Binding FilterCommand}" - ITokenizableItemsSource="{Binding Weapons.SourceCollection}" ItemsSource="{Binding FilterTokens, Mode=TwoWay}" MaximumTokens="5" PlaceholderText="{shcm:ResourceString Name=ViewPageWiKiWeaponAutoSuggestBoxPlaceHolder}" QueryIcon="{cw:FontIconSource Glyph=}" + SuggestedItemTemplate="{StaticResource TokenTemplate}" SuggestedItemsSource="{Binding AvailableQueries}" Text="{Binding FilterToken, Mode=TwoWay}" TokenItemTemplate="{StaticResource TokenTemplate}"/> diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/AvatarFilter.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/AvatarFilter.cs index c18c963c..177b0e37 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/AvatarFilter.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/AvatarFilter.cs @@ -66,9 +66,11 @@ internal static class AvatarFilter } break; - case SearchTokenKind.Other: + case SearchTokenKind.Avatars: matches.Add(tokens.Contains(avatar.Name)); break; + default: + throw Must.NeverHappen(); } } diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WeaponFilter.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WeaponFilter.cs index 99fdd8a0..08308501 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WeaponFilter.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WeaponFilter.cs @@ -52,9 +52,11 @@ internal static class WeaponFilter } break; - case SearchTokenKind.Other: + case SearchTokenKind.Weapons: matches.Add(tokens.Contains(weapon.Name)); break; + default: + throw Must.NeverHappen(); } } diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiAvatarViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiAvatarViewModel.cs index 4c55dca1..74a2c3b2 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiAvatarViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiAvatarViewModel.cs @@ -10,6 +10,7 @@ using Snap.Hutao.Model.Intrinsic; using Snap.Hutao.Model.Intrinsic.Frozen; using Snap.Hutao.Model.Metadata; using Snap.Hutao.Model.Metadata.Avatar; +using Snap.Hutao.Model.Metadata.Converter; using Snap.Hutao.Model.Metadata.Item; using Snap.Hutao.Model.Primitive; using Snap.Hutao.Service.Cultivation; @@ -54,7 +55,7 @@ internal sealed partial class WikiAvatarViewModel : Abstraction.ViewModel private BaseValueInfo? baseValueInfo; private Dictionary>? levelAvatarCurveMap; private List? promotes; - private FrozenSet availableQueries; + private FrozenDictionary availableTokens; /// /// 角色列表 @@ -87,7 +88,9 @@ internal sealed partial class WikiAvatarViewModel : Abstraction.ViewModel public string? FilterToken { get => filterToken; set => SetProperty(ref filterToken, value); } - public FrozenSet? AvailableQueries { get => availableQueries; } + public FrozenDictionary? AvailableTokens { get => availableTokens; } + + public IEnumerable? AvailableQueries { get => availableTokens.Values; } protected override async ValueTask InitializeUIAsync() { @@ -113,15 +116,15 @@ internal sealed partial class WikiAvatarViewModel : Abstraction.ViewModel Selected = Avatars.View.ElementAtOrDefault(0); FilterTokens = []; - availableQueries = FrozenSet.ToFrozenSet( - [ - .. avatars.Select(a => a.Name), - .. IntrinsicFrozen.AssociationTypes, - .. IntrinsicFrozen.BodyTypes, - .. IntrinsicFrozen.ElementNames, - .. IntrinsicFrozen.ItemQualities, - .. IntrinsicFrozen.WeaponTypes, - ]); + availableTokens = FrozenDictionary.ToFrozenDictionary( + [ + .. avatars.Select(avatar => KeyValuePair.Create(avatar.Name, new SearchToken(avatar.Name, SearchTokenKind.Avatars, sideIconUri: AvatarSideIconConverter.IconNameToUri(avatar.SideIcon)))), + .. IntrinsicFrozen.AssociationTypes.Select(assoc => KeyValuePair.Create(assoc, new SearchToken(assoc, SearchTokenKind.AssociationTypes, iconUri: AssociationTypeIconConverter.AssociationTypeNameToIconUri(assoc)))), + .. IntrinsicFrozen.BodyTypes.Select(b => KeyValuePair.Create(b, new SearchToken(b, SearchTokenKind.BodyTypes))), + .. IntrinsicFrozen.ElementNames.Select(e => KeyValuePair.Create(e, new SearchToken(e, SearchTokenKind.ElementNames, iconUri: ElementNameIconConverter.ElementNameToIconUri(e)))), + .. IntrinsicFrozen.ItemQualities.Select(i => KeyValuePair.Create(i, new SearchToken(i, SearchTokenKind.ItemQualities, quality: QualityColorConverter.QualityNameToColor(i)))), + .. IntrinsicFrozen.WeaponTypes.Select(w => KeyValuePair.Create(w, new SearchToken(w, SearchTokenKind.WeaponTypes, iconUri: WeaponTypeIconConverter.WeaponTypeNameToIconUri(w)))), + ]); return true; } diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiWeaponViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiWeaponViewModel.cs index 05dfbb1c..2e44caa3 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiWeaponViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiWeaponViewModel.cs @@ -9,6 +9,7 @@ using Snap.Hutao.Model.Entity.Primitive; using Snap.Hutao.Model.Intrinsic; using Snap.Hutao.Model.Intrinsic.Frozen; using Snap.Hutao.Model.Metadata; +using Snap.Hutao.Model.Metadata.Converter; using Snap.Hutao.Model.Metadata.Item; using Snap.Hutao.Model.Metadata.Weapon; using Snap.Hutao.Model.Primitive; @@ -51,7 +52,7 @@ internal sealed partial class WikiWeaponViewModel : Abstraction.ViewModel private BaseValueInfo? baseValueInfo; private Dictionary>? levelWeaponCurveMap; private List? promotes; - private FrozenSet availableQueries; + private FrozenDictionary availableTokens; /// /// 角色列表 @@ -84,7 +85,9 @@ internal sealed partial class WikiWeaponViewModel : Abstraction.ViewModel public string? FilterToken { get => filterToken; set => SetProperty(ref filterToken, value); } - public FrozenSet AvailableQueries { get => availableQueries; } + public FrozenDictionary? AvailableTokens { get => availableTokens; } + + public IEnumerable? AvailableQueries { get => availableTokens.Values; } /// protected override async Task OpenUIAsync() @@ -110,13 +113,13 @@ internal sealed partial class WikiWeaponViewModel : Abstraction.ViewModel Selected = Weapons.View.ElementAtOrDefault(0); FilterTokens = []; - availableQueries = FrozenSet.ToFrozenSet( - [ - .. weapons.Select(w => w.Name), - .. IntrinsicFrozen.ItemQualities, - .. IntrinsicFrozen.FightProperties, - .. IntrinsicFrozen.WeaponTypes, - ]); + availableTokens = FrozenDictionary.ToFrozenDictionary( + [ + .. weapons.Select(w => KeyValuePair.Create(w.Name, new SearchToken(w.Name, SearchTokenKind.Weapons, sideIconUri: EquipIconConverter.IconNameToUri(w.Icon)))), + .. IntrinsicFrozen.FightProperties.Select(f => KeyValuePair.Create(f, new SearchToken(f, SearchTokenKind.FightProperties))), + .. IntrinsicFrozen.ItemQualities.Select(i => KeyValuePair.Create(i, new SearchToken(i, SearchTokenKind.ItemQualities, quality: QualityColorConverter.QualityNameToColor(i)))), + .. IntrinsicFrozen.WeaponTypes.Select(w => KeyValuePair.Create(w, new SearchToken(w, SearchTokenKind.WeaponTypes, iconUri: WeaponTypeIconConverter.WeaponTypeNameToIconUri(w)))), + ]); } } From 41853365562e249e8d6fd63dd9d8742788ed0181 Mon Sep 17 00:00:00 2001 From: qhy040404 Date: Tue, 5 Mar 2024 17:10:31 +0800 Subject: [PATCH 08/10] minor ui adjustment --- .../Snap.Hutao/Control/SuggestBox/AutoSuggestTokenBox.cs | 1 - src/Snap.Hutao/Snap.Hutao/View/Page/WikiAvatarPage.xaml | 4 ++-- src/Snap.Hutao/Snap.Hutao/View/Page/WikiWeaponPage.xaml | 2 +- .../Snap.Hutao/ViewModel/Wiki/WikiAvatarViewModel.cs | 2 -- .../Snap.Hutao/ViewModel/Wiki/WikiWeaponViewModel.cs | 2 -- 5 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/AutoSuggestTokenBox.cs b/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/AutoSuggestTokenBox.cs index 2d6b7a45..a9ab1d4a 100644 --- a/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/AutoSuggestTokenBox.cs +++ b/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/AutoSuggestTokenBox.cs @@ -4,7 +4,6 @@ using CommunityToolkit.WinUI.Controls; using Microsoft.UI.Xaml.Controls; using Snap.Hutao.Control.SuggestBox; -using Snap.Hutao.Model.Intrinsic.Frozen; using System.Collections.Frozen; namespace Snap.Hutao.View.Control; diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/WikiAvatarPage.xaml b/src/Snap.Hutao/Snap.Hutao/View/Page/WikiAvatarPage.xaml index 32660930..271de945 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Page/WikiAvatarPage.xaml +++ b/src/Snap.Hutao/Snap.Hutao/View/Page/WikiAvatarPage.xaml @@ -103,7 +103,7 @@ Grid.Column="0" Width="22" Height="22" - Margin="0,0,4,0" + Margin="-4,-2,8,2" Source="{Binding SideIconUri, Mode=OneWay}" Visibility="{Binding SideIconUri, Converter={StaticResource EmptyObjectToVisibilityConverter}}"/> diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/WikiWeaponPage.xaml b/src/Snap.Hutao/Snap.Hutao/View/Page/WikiWeaponPage.xaml index 84f3f061..6e6be0cd 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Page/WikiWeaponPage.xaml +++ b/src/Snap.Hutao/Snap.Hutao/View/Page/WikiWeaponPage.xaml @@ -186,7 +186,7 @@ PlaceholderText="{shcm:ResourceString Name=ViewPageWiKiWeaponAutoSuggestBoxPlaceHolder}" QueryIcon="{cw:FontIconSource Glyph=}" SuggestedItemTemplate="{StaticResource TokenTemplate}" - SuggestedItemsSource="{Binding AvailableQueries}" + SuggestedItemsSource="{Binding AvailableTokens.Values}" Text="{Binding FilterToken, Mode=TwoWay}" TokenItemTemplate="{StaticResource TokenTemplate}"/> diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiAvatarViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiAvatarViewModel.cs index 74a2c3b2..cbb5257f 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiAvatarViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiAvatarViewModel.cs @@ -90,8 +90,6 @@ internal sealed partial class WikiAvatarViewModel : Abstraction.ViewModel public FrozenDictionary? AvailableTokens { get => availableTokens; } - public IEnumerable? AvailableQueries { get => availableTokens.Values; } - protected override async ValueTask InitializeUIAsync() { if (!await metadataService.InitializeAsync().ConfigureAwait(false)) diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiWeaponViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiWeaponViewModel.cs index 2e44caa3..3dba3741 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiWeaponViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiWeaponViewModel.cs @@ -87,8 +87,6 @@ internal sealed partial class WikiWeaponViewModel : Abstraction.ViewModel public FrozenDictionary? AvailableTokens { get => availableTokens; } - public IEnumerable? AvailableQueries { get => availableTokens.Values; } - /// protected override async Task OpenUIAsync() { From 2ad6dad282ee0ef32f5c85ef40df5af47d21fdb4 Mon Sep 17 00:00:00 2001 From: qhy040404 Date: Tue, 5 Mar 2024 17:28:01 +0800 Subject: [PATCH 09/10] minor fix --- .../Control/SuggestBox/AutoSuggestTokenBox.cs | 5 ++--- .../Snap.Hutao/Control/SuggestBox/SearchTokenKind.cs | 1 + .../Snap.Hutao/Control/Theme/KnownColors.cs | 2 ++ .../Metadata/Converter/QualityColorConverter.cs | 12 ++++++------ .../Snap.Hutao/ViewModel/Wiki/AvatarFilter.cs | 3 ++- .../Snap.Hutao/ViewModel/Wiki/WeaponFilter.cs | 3 ++- 6 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/AutoSuggestTokenBox.cs b/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/AutoSuggestTokenBox.cs index a9ab1d4a..e49fe458 100644 --- a/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/AutoSuggestTokenBox.cs +++ b/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/AutoSuggestTokenBox.cs @@ -4,12 +4,11 @@ using CommunityToolkit.WinUI.Controls; using Microsoft.UI.Xaml.Controls; using Snap.Hutao.Control.SuggestBox; -using System.Collections.Frozen; namespace Snap.Hutao.View.Control; [DependencyProperty("FilterCommand", typeof(ICommand))] -[DependencyProperty("AvailableTokens", typeof(FrozenDictionary))] +[DependencyProperty("AvailableTokens", typeof(IReadOnlyDictionary))] internal sealed partial class AutoSuggestTokenBox : TokenizingTextBox { public AutoSuggestTokenBox() @@ -54,7 +53,7 @@ internal sealed partial class AutoSuggestTokenBox : TokenizingTextBox return; } - args.Item = AvailableTokens[args.TokenText]; + args.Item = AvailableTokens.GetValueOrDefault(args.TokenText) ?? new SearchToken(args.TokenText, SearchTokenKind.Others); } private void OnTokenItemModified(TokenizingTextBox sender, object args) diff --git a/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/SearchTokenKind.cs b/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/SearchTokenKind.cs index f687a205..7439eda7 100644 --- a/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/SearchTokenKind.cs +++ b/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/SearchTokenKind.cs @@ -11,6 +11,7 @@ internal enum SearchTokenKind ElementNames, FightProperties, ItemQualities, + Others, Weapons, WeaponTypes, } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Control/Theme/KnownColors.cs b/src/Snap.Hutao/Snap.Hutao/Control/Theme/KnownColors.cs index 980be1a5..c69a841a 100644 --- a/src/Snap.Hutao/Snap.Hutao/Control/Theme/KnownColors.cs +++ b/src/Snap.Hutao/Snap.Hutao/Control/Theme/KnownColors.cs @@ -11,4 +11,6 @@ internal static class KnownColors public static readonly Color Orange = StructMarshal.Color(0xFFBC6932); public static readonly Color Purple = StructMarshal.Color(0xFFA156E0); public static readonly Color Blue = StructMarshal.Color(0xFF5180CB); + public static readonly Color Green = StructMarshal.Color(0xFF2A8F72); + public static readonly Color White = StructMarshal.Color(0xFF72778B); } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/QualityColorConverter.cs b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/QualityColorConverter.cs index b85cec8d..1c59ddf8 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/QualityColorConverter.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/QualityColorConverter.cs @@ -3,8 +3,8 @@ using Microsoft.UI; using Snap.Hutao.Control; +using Snap.Hutao.Control.Theme; using Snap.Hutao.Model.Intrinsic; -using Snap.Hutao.Win32; using System.Collections.Frozen; using Windows.UI; @@ -35,11 +35,11 @@ internal sealed class QualityColorConverter : ValueConverter { return quality switch { - QualityType.QUALITY_WHITE => StructMarshal.Color(0xFF72778B), - QualityType.QUALITY_GREEN => StructMarshal.Color(0xFF2A8F72), - QualityType.QUALITY_BLUE => StructMarshal.Color(0xFF5180CB), - QualityType.QUALITY_PURPLE => StructMarshal.Color(0xFFA156E0), - QualityType.QUALITY_ORANGE or QualityType.QUALITY_ORANGE_SP => StructMarshal.Color(0xFFBC6932), + QualityType.QUALITY_WHITE => KnownColors.White, + QualityType.QUALITY_GREEN => KnownColors.Green, + QualityType.QUALITY_BLUE => KnownColors.Blue, + QualityType.QUALITY_PURPLE => KnownColors.Purple, + QualityType.QUALITY_ORANGE or QualityType.QUALITY_ORANGE_SP => KnownColors.Orange, _ => Colors.Transparent, }; } diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/AvatarFilter.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/AvatarFilter.cs index 177b0e37..bff91174 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/AvatarFilter.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/AvatarFilter.cs @@ -70,7 +70,8 @@ internal static class AvatarFilter matches.Add(tokens.Contains(avatar.Name)); break; default: - throw Must.NeverHappen(); + matches.Add(false); + break; } } diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WeaponFilter.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WeaponFilter.cs index 08308501..01651fa3 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WeaponFilter.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WeaponFilter.cs @@ -56,7 +56,8 @@ internal static class WeaponFilter matches.Add(tokens.Contains(weapon.Name)); break; default: - throw Must.NeverHappen(); + matches.Add(false); + break; } } From 59dabaa5bec093ab4690b96ec589d4b76a05d2b8 Mon Sep 17 00:00:00 2001 From: DismissedLight <1686188646@qq.com> Date: Tue, 5 Mar 2024 23:59:23 +0800 Subject: [PATCH 10/10] code style --- src/Snap.Hutao/Snap.Hutao/App.xaml | 1 + .../AutoSuggestTokenBox.cs | 27 ++++++++++--------- .../SearchToken.cs | 4 +-- .../Control/AutoSuggestBox/SearchTokenKind.cs | 17 ++++++++++++ .../Behavior/InvokeCommandOnLoadedBehavior.cs | 7 ++--- ...keCommandOrOnActualThemeChangedBehavior.cs | 6 ++--- .../Control/Extension/CommandExtension.cs | 18 +++++++++++++ .../Control/SuggestBox/SearchTokenKind.cs | 17 ------------ .../Extension/EnumerableExtension.cs | 6 +++++ .../Converter/AssociationTypeIconConverter.cs | 10 +++---- .../Converter/QualityColorConverter.cs | 20 +++++++------- .../Snap.Hutao/View/Page/WikiAvatarPage.xaml | 19 +++++++++---- .../Snap.Hutao/View/Page/WikiWeaponPage.xaml | 14 ++++++++-- .../Snap.Hutao/ViewModel/Wiki/AvatarFilter.cs | 18 ++++++------- .../Snap.Hutao/ViewModel/Wiki/WeaponFilter.cs | 14 +++++----- .../ViewModel/Wiki/WikiAvatarViewModel.cs | 14 +++++----- .../ViewModel/Wiki/WikiWeaponViewModel.cs | 10 +++---- 17 files changed, 132 insertions(+), 90 deletions(-) rename src/Snap.Hutao/Snap.Hutao/Control/{SuggestBox => AutoSuggestBox}/AutoSuggestTokenBox.cs (62%) rename src/Snap.Hutao/Snap.Hutao/Control/{SuggestBox => AutoSuggestBox}/SearchToken.cs (85%) create mode 100644 src/Snap.Hutao/Snap.Hutao/Control/AutoSuggestBox/SearchTokenKind.cs create mode 100644 src/Snap.Hutao/Snap.Hutao/Control/Extension/CommandExtension.cs delete mode 100644 src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/SearchTokenKind.cs diff --git a/src/Snap.Hutao/Snap.Hutao/App.xaml b/src/Snap.Hutao/Snap.Hutao/App.xaml index 92ab950a..eca83605 100644 --- a/src/Snap.Hutao/Snap.Hutao/App.xaml +++ b/src/Snap.Hutao/Snap.Hutao/App.xaml @@ -6,6 +6,7 @@ + diff --git a/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/AutoSuggestTokenBox.cs b/src/Snap.Hutao/Snap.Hutao/Control/AutoSuggestBox/AutoSuggestTokenBox.cs similarity index 62% rename from src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/AutoSuggestTokenBox.cs rename to src/Snap.Hutao/Snap.Hutao/Control/AutoSuggestBox/AutoSuggestTokenBox.cs index e49fe458..7c3b6782 100644 --- a/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/AutoSuggestTokenBox.cs +++ b/src/Snap.Hutao/Snap.Hutao/Control/AutoSuggestBox/AutoSuggestTokenBox.cs @@ -1,18 +1,22 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. +using CommunityToolkit.WinUI; using CommunityToolkit.WinUI.Controls; using Microsoft.UI.Xaml.Controls; -using Snap.Hutao.Control.SuggestBox; +using Microsoft.UI.Xaml.Controls.Primitives; +using Snap.Hutao.Control.Extension; -namespace Snap.Hutao.View.Control; +namespace Snap.Hutao.Control.AutoSuggestBox; [DependencyProperty("FilterCommand", typeof(ICommand))] +[DependencyProperty("FilterCommandParameter", typeof(object))] [DependencyProperty("AvailableTokens", typeof(IReadOnlyDictionary))] internal sealed partial class AutoSuggestTokenBox : TokenizingTextBox { public AutoSuggestTokenBox() { + DefaultStyleKey = typeof(TokenizingTextBox); TextChanged += OnFilterSuggestionRequested; QuerySubmitted += OnQuerySubmitted; TokenItemAdding += OnTokenItemAdding; @@ -20,7 +24,7 @@ internal sealed partial class AutoSuggestTokenBox : TokenizingTextBox TokenItemRemoved += OnTokenItemModified; } - private void OnFilterSuggestionRequested(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs args) + private void OnFilterSuggestionRequested(Microsoft.UI.Xaml.Controls.AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs args) { if (string.IsNullOrWhiteSpace(Text)) { @@ -30,20 +34,20 @@ internal sealed partial class AutoSuggestTokenBox : TokenizingTextBox if (args.Reason == AutoSuggestionBoxTextChangeReason.UserInput) { sender.ItemsSource = AvailableTokens.Values.Where(q => q.Value.Contains(Text, StringComparison.OrdinalIgnoreCase)); + + // TODO: CornerRadius + // Popup? popup = this.FindDescendant("SuggestionsPopup") as Popup; } } - private void OnQuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args) + private void OnQuerySubmitted(Microsoft.UI.Xaml.Controls.AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args) { if (args.ChosenSuggestion is not null) { return; } - if (FilterCommand.CanExecute(null)) - { - FilterCommand.Execute(null); - } + CommandExtension.TryExecute(FilterCommand, FilterCommandParameter); } private void OnTokenItemAdding(TokenizingTextBox sender, TokenItemAddingEventArgs args) @@ -53,14 +57,11 @@ internal sealed partial class AutoSuggestTokenBox : TokenizingTextBox return; } - args.Item = AvailableTokens.GetValueOrDefault(args.TokenText) ?? new SearchToken(args.TokenText, SearchTokenKind.Others); + args.Item = AvailableTokens.GetValueOrDefault(args.TokenText) ?? new SearchToken(SearchTokenKind.None, args.TokenText); } private void OnTokenItemModified(TokenizingTextBox sender, object args) { - if (FilterCommand.CanExecute(null)) - { - FilterCommand.Execute(null); - } + CommandExtension.TryExecute(FilterCommand, FilterCommandParameter); } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/SearchToken.cs b/src/Snap.Hutao/Snap.Hutao/Control/AutoSuggestBox/SearchToken.cs similarity index 85% rename from src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/SearchToken.cs rename to src/Snap.Hutao/Snap.Hutao/Control/AutoSuggestBox/SearchToken.cs index 1ee15e17..cfa8dc91 100644 --- a/src/Snap.Hutao/Snap.Hutao/Control/SuggestBox/SearchToken.cs +++ b/src/Snap.Hutao/Snap.Hutao/Control/AutoSuggestBox/SearchToken.cs @@ -3,11 +3,11 @@ using Windows.UI; -namespace Snap.Hutao.Control.SuggestBox; +namespace Snap.Hutao.Control.AutoSuggestBox; internal sealed class SearchToken { - public SearchToken(string value, SearchTokenKind kind, Uri? iconUri = null, Uri? sideIconUri = null, Color? quality = null) + public SearchToken(SearchTokenKind kind, string value, Uri? iconUri = null, Uri? sideIconUri = null, Color? quality = null) { Value = value; Kind = kind; diff --git a/src/Snap.Hutao/Snap.Hutao/Control/AutoSuggestBox/SearchTokenKind.cs b/src/Snap.Hutao/Snap.Hutao/Control/AutoSuggestBox/SearchTokenKind.cs new file mode 100644 index 00000000..4a155c86 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Control/AutoSuggestBox/SearchTokenKind.cs @@ -0,0 +1,17 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +namespace Snap.Hutao.Control.AutoSuggestBox; + +internal enum SearchTokenKind +{ + None, + AssociationType, + Avatar, + BodyType, + ElementName, + FightProperty, + ItemQuality, + Weapon, + WeaponType, +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Control/Behavior/InvokeCommandOnLoadedBehavior.cs b/src/Snap.Hutao/Snap.Hutao/Control/Behavior/InvokeCommandOnLoadedBehavior.cs index 26697a31..954d61cd 100644 --- a/src/Snap.Hutao/Snap.Hutao/Control/Behavior/InvokeCommandOnLoadedBehavior.cs +++ b/src/Snap.Hutao/Snap.Hutao/Control/Behavior/InvokeCommandOnLoadedBehavior.cs @@ -3,6 +3,7 @@ using CommunityToolkit.WinUI.Behaviors; using Microsoft.UI.Xaml; +using Snap.Hutao.Control.Extension; namespace Snap.Hutao.Control.Behavior; @@ -45,10 +46,6 @@ internal sealed partial class InvokeCommandOnLoadedBehavior : BehaviorBase(this IGrouping grouping, out TKey key, out IEnumerable elements) + { + key = grouping.Key; + elements = grouping; + } + public static TElement? ElementAtOrLastOrDefault(this IEnumerable source, int index) { return source.ElementAtOrDefault(index) ?? source.LastOrDefault(); diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/AssociationTypeIconConverter.cs b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/AssociationTypeIconConverter.cs index d70a868a..e307895f 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/AssociationTypeIconConverter.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/AssociationTypeIconConverter.cs @@ -33,18 +33,18 @@ internal sealed class AssociationTypeIconConverter : ValueConverter "Mengde", AssociationType.ASSOC_TYPE_LIYUE => "Liyue", - AssociationType.ASSOC_TYPE_FATUI => null, + AssociationType.ASSOC_TYPE_FATUI => default, AssociationType.ASSOC_TYPE_INAZUMA => "Inazuma", - AssociationType.ASSOC_TYPE_RANGER => null, + AssociationType.ASSOC_TYPE_RANGER => default, AssociationType.ASSOC_TYPE_SUMERU => "Sumeru", AssociationType.ASSOC_TYPE_FONTAINE => "Fontaine", - AssociationType.ASSOC_TYPE_NATLAN => null, - AssociationType.ASSOC_TYPE_SNEZHNAYA => null, + AssociationType.ASSOC_TYPE_NATLAN => default, + AssociationType.ASSOC_TYPE_SNEZHNAYA => default, _ => throw Must.NeverHappen(), }; return association is null - ? null + ? default : Web.HutaoEndpoints.StaticRaw("ChapterIcon", $"UI_ChapterIcon_{association}.png").ToUri(); } diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/QualityColorConverter.cs b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/QualityColorConverter.cs index 1c59ddf8..a2dda53c 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/QualityColorConverter.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/QualityColorConverter.cs @@ -26,6 +26,16 @@ internal sealed class QualityColorConverter : ValueConverter KeyValuePair.Create(SH.ModelIntrinsicItemQualityRed, QualityType.QUALITY_ORANGE_SP), ]); + private static readonly FrozenDictionary QualityTypeToColor = FrozenDictionary.ToFrozenDictionary( + [ + KeyValuePair.Create(QualityType.QUALITY_WHITE, KnownColors.White), + KeyValuePair.Create(QualityType.QUALITY_GREEN, KnownColors.Green), + KeyValuePair.Create(QualityType.QUALITY_BLUE, KnownColors.Blue), + KeyValuePair.Create(QualityType.QUALITY_PURPLE, KnownColors.Purple), + KeyValuePair.Create(QualityType.QUALITY_ORANGE, KnownColors.Orange), + KeyValuePair.Create(QualityType.QUALITY_ORANGE_SP, KnownColors.Orange), + ]); + public static Color QualityNameToColor(string qualityName) { return QualityToColor(LocalizedNameToQualityType.GetValueOrDefault(qualityName)); @@ -33,15 +43,7 @@ internal sealed class QualityColorConverter : ValueConverter public static Color QualityToColor(QualityType quality) { - return quality switch - { - QualityType.QUALITY_WHITE => KnownColors.White, - QualityType.QUALITY_GREEN => KnownColors.Green, - QualityType.QUALITY_BLUE => KnownColors.Blue, - QualityType.QUALITY_PURPLE => KnownColors.Purple, - QualityType.QUALITY_ORANGE or QualityType.QUALITY_ORANGE_SP => KnownColors.Orange, - _ => Colors.Transparent, - }; + return QualityTypeToColor.GetValueOrDefault(quality, Colors.Transparent); } /// diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/WikiAvatarPage.xaml b/src/Snap.Hutao/Snap.Hutao/View/Page/WikiAvatarPage.xaml index 271de945..2b5445d9 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Page/WikiAvatarPage.xaml +++ b/src/Snap.Hutao/Snap.Hutao/View/Page/WikiAvatarPage.xaml @@ -8,6 +8,7 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mxi="using:Microsoft.Xaml.Interactivity" xmlns:shc="using:Snap.Hutao.Control" + xmlns:shca="using:Snap.Hutao.Control.AutoSuggestBox" xmlns:shcb="using:Snap.Hutao.Control.Behavior" xmlns:shci="using:Snap.Hutao.Control.Image" xmlns:shcm="using:Snap.Hutao.Control.Markup" @@ -303,14 +304,12 @@ Margin="8,8,0,0" LocalSettingKeySuffixForCurrent="WikiAvatarPage.Avatars"/> - - + TokenItemTemplate="{StaticResource TokenTemplate}"> + + + + + + - + TokenItemTemplate="{StaticResource TokenTemplate}"> + + + + + + matches = []; - foreach (IGrouping tokens in input.GroupBy(token => token.Kind, token => token.Value)) + foreach ((SearchTokenKind kind, IEnumerable tokens) in input.GroupBy(token => token.Kind, token => token.Value)) { - switch (tokens.Key) + switch (kind) { - case SearchTokenKind.ElementNames: + case SearchTokenKind.ElementName: if (IntrinsicFrozen.ElementNames.Overlaps(tokens)) { matches.Add(tokens.Contains(avatar.FetterInfo.VisionBefore)); } break; - case SearchTokenKind.AssociationTypes: + case SearchTokenKind.AssociationType: if (IntrinsicFrozen.AssociationTypes.Overlaps(tokens)) { matches.Add(tokens.Contains(avatar.FetterInfo.Association.GetLocalizedDescriptionOrDefault())); } break; - case SearchTokenKind.WeaponTypes: + case SearchTokenKind.WeaponType: if (IntrinsicFrozen.WeaponTypes.Overlaps(tokens)) { matches.Add(tokens.Contains(avatar.Weapon.GetLocalizedDescriptionOrDefault())); } break; - case SearchTokenKind.ItemQualities: + case SearchTokenKind.ItemQuality: if (IntrinsicFrozen.ItemQualities.Overlaps(tokens)) { matches.Add(tokens.Contains(avatar.Quality.GetLocalizedDescriptionOrDefault())); } break; - case SearchTokenKind.BodyTypes: + case SearchTokenKind.BodyType: if (IntrinsicFrozen.BodyTypes.Overlaps(tokens)) { matches.Add(tokens.Contains(avatar.Body.GetLocalizedDescriptionOrDefault())); } break; - case SearchTokenKind.Avatars: + case SearchTokenKind.Avatar: matches.Add(tokens.Contains(avatar.Name)); break; default: diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WeaponFilter.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WeaponFilter.cs index 01651fa3..359f258d 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WeaponFilter.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WeaponFilter.cs @@ -1,7 +1,7 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. -using Snap.Hutao.Control.SuggestBox; +using Snap.Hutao.Control.AutoSuggestBox; using Snap.Hutao.Model.Intrinsic.Frozen; using Snap.Hutao.Model.Metadata.Weapon; using System.Collections.ObjectModel; @@ -27,32 +27,32 @@ internal static class WeaponFilter { List matches = []; - foreach (IGrouping tokens in input.GroupBy(token => token.Kind, token => token.Value)) + foreach ((SearchTokenKind kind, IEnumerable tokens) in input.GroupBy(token => token.Kind, token => token.Value)) { - switch (tokens.Key) + switch (kind) { - case SearchTokenKind.WeaponTypes: + case SearchTokenKind.WeaponType: if (IntrinsicFrozen.WeaponTypes.Overlaps(tokens)) { matches.Add(tokens.Contains(weapon.WeaponType.GetLocalizedDescriptionOrDefault())); } break; - case SearchTokenKind.ItemQualities: + case SearchTokenKind.ItemQuality: if (IntrinsicFrozen.ItemQualities.Overlaps(tokens)) { matches.Add(tokens.Contains(weapon.Quality.GetLocalizedDescriptionOrDefault())); } break; - case SearchTokenKind.FightProperties: + case SearchTokenKind.FightProperty: if (IntrinsicFrozen.FightProperties.Overlaps(tokens)) { matches.Add(tokens.Contains(weapon.GrowCurves.ElementAtOrDefault(1)?.Type.GetLocalizedDescriptionOrDefault())); } break; - case SearchTokenKind.Weapons: + case SearchTokenKind.Weapon: matches.Add(tokens.Contains(weapon.Name)); break; default: diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiAvatarViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiAvatarViewModel.cs index cbb5257f..5b526fca 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiAvatarViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiAvatarViewModel.cs @@ -1,8 +1,8 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. +using Snap.Hutao.Control.AutoSuggestBox; using Snap.Hutao.Control.Collection.AdvancedCollectionView; -using Snap.Hutao.Control.SuggestBox; using Snap.Hutao.Factory.ContentDialog; using Snap.Hutao.Model.Calculable; using Snap.Hutao.Model.Entity.Primitive; @@ -116,12 +116,12 @@ internal sealed partial class WikiAvatarViewModel : Abstraction.ViewModel availableTokens = FrozenDictionary.ToFrozenDictionary( [ - .. avatars.Select(avatar => KeyValuePair.Create(avatar.Name, new SearchToken(avatar.Name, SearchTokenKind.Avatars, sideIconUri: AvatarSideIconConverter.IconNameToUri(avatar.SideIcon)))), - .. IntrinsicFrozen.AssociationTypes.Select(assoc => KeyValuePair.Create(assoc, new SearchToken(assoc, SearchTokenKind.AssociationTypes, iconUri: AssociationTypeIconConverter.AssociationTypeNameToIconUri(assoc)))), - .. IntrinsicFrozen.BodyTypes.Select(b => KeyValuePair.Create(b, new SearchToken(b, SearchTokenKind.BodyTypes))), - .. IntrinsicFrozen.ElementNames.Select(e => KeyValuePair.Create(e, new SearchToken(e, SearchTokenKind.ElementNames, iconUri: ElementNameIconConverter.ElementNameToIconUri(e)))), - .. IntrinsicFrozen.ItemQualities.Select(i => KeyValuePair.Create(i, new SearchToken(i, SearchTokenKind.ItemQualities, quality: QualityColorConverter.QualityNameToColor(i)))), - .. IntrinsicFrozen.WeaponTypes.Select(w => KeyValuePair.Create(w, new SearchToken(w, SearchTokenKind.WeaponTypes, iconUri: WeaponTypeIconConverter.WeaponTypeNameToIconUri(w)))), + .. avatars.Select(avatar => KeyValuePair.Create(avatar.Name, new SearchToken(SearchTokenKind.Avatar, avatar.Name, sideIconUri: AvatarSideIconConverter.IconNameToUri(avatar.SideIcon)))), + .. IntrinsicFrozen.AssociationTypes.Select(assoc => KeyValuePair.Create(assoc, new SearchToken(SearchTokenKind.AssociationType, assoc, iconUri: AssociationTypeIconConverter.AssociationTypeNameToIconUri(assoc)))), + .. IntrinsicFrozen.BodyTypes.Select(b => KeyValuePair.Create(b, new SearchToken(SearchTokenKind.BodyType, b))), + .. IntrinsicFrozen.ElementNames.Select(e => KeyValuePair.Create(e, new SearchToken(SearchTokenKind.ElementName, e, iconUri: ElementNameIconConverter.ElementNameToIconUri(e)))), + .. IntrinsicFrozen.ItemQualities.Select(i => KeyValuePair.Create(i, new SearchToken(SearchTokenKind.ItemQuality, i, quality: QualityColorConverter.QualityNameToColor(i)))), + .. IntrinsicFrozen.WeaponTypes.Select(w => KeyValuePair.Create(w, new SearchToken(SearchTokenKind.WeaponType, w, iconUri: WeaponTypeIconConverter.WeaponTypeNameToIconUri(w)))), ]); return true; diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiWeaponViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiWeaponViewModel.cs index 3dba3741..6816423d 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiWeaponViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Wiki/WikiWeaponViewModel.cs @@ -1,8 +1,8 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. +using Snap.Hutao.Control.AutoSuggestBox; using Snap.Hutao.Control.Collection.AdvancedCollectionView; -using Snap.Hutao.Control.SuggestBox; using Snap.Hutao.Factory.ContentDialog; using Snap.Hutao.Model.Calculable; using Snap.Hutao.Model.Entity.Primitive; @@ -113,10 +113,10 @@ internal sealed partial class WikiWeaponViewModel : Abstraction.ViewModel availableTokens = FrozenDictionary.ToFrozenDictionary( [ - .. weapons.Select(w => KeyValuePair.Create(w.Name, new SearchToken(w.Name, SearchTokenKind.Weapons, sideIconUri: EquipIconConverter.IconNameToUri(w.Icon)))), - .. IntrinsicFrozen.FightProperties.Select(f => KeyValuePair.Create(f, new SearchToken(f, SearchTokenKind.FightProperties))), - .. IntrinsicFrozen.ItemQualities.Select(i => KeyValuePair.Create(i, new SearchToken(i, SearchTokenKind.ItemQualities, quality: QualityColorConverter.QualityNameToColor(i)))), - .. IntrinsicFrozen.WeaponTypes.Select(w => KeyValuePair.Create(w, new SearchToken(w, SearchTokenKind.WeaponTypes, iconUri: WeaponTypeIconConverter.WeaponTypeNameToIconUri(w)))), + .. weapons.Select(w => KeyValuePair.Create(w.Name, new SearchToken(SearchTokenKind.Weapon, w.Name, sideIconUri: EquipIconConverter.IconNameToUri(w.Icon)))), + .. IntrinsicFrozen.FightProperties.Select(f => KeyValuePair.Create(f, new SearchToken(SearchTokenKind.FightProperty, f))), + .. IntrinsicFrozen.ItemQualities.Select(i => KeyValuePair.Create(i, new SearchToken(SearchTokenKind.ItemQuality, i, quality: QualityColorConverter.QualityNameToColor(i)))), + .. IntrinsicFrozen.WeaponTypes.Select(w => KeyValuePair.Create(w, new SearchToken(SearchTokenKind.WeaponType, w, iconUri: WeaponTypeIconConverter.WeaponTypeNameToIconUri(w)))), ]); } }