mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
Compare commits
2 Commits
fix/naviga
...
feat/wikis
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3b86783493 | ||
|
|
e3adc2e595 |
@@ -41,12 +41,14 @@ internal class ScopedPage : Page
|
|||||||
/// 应当在 InitializeComponent() 前调用
|
/// 应当在 InitializeComponent() 前调用
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TViewModel">视图模型类型</typeparam>
|
/// <typeparam name="TViewModel">视图模型类型</typeparam>
|
||||||
protected void InitializeWith<TViewModel>()
|
protected TViewModel InitializeWith<TViewModel>()
|
||||||
where TViewModel : class, IViewModel
|
where TViewModel : class, IViewModel
|
||||||
{
|
{
|
||||||
IViewModel viewModel = currentScope.ServiceProvider.GetRequiredService<TViewModel>();
|
IViewModel viewModel = currentScope.ServiceProvider.GetRequiredService<TViewModel>();
|
||||||
viewModel.CancellationToken = viewCancellationTokenSource.Token;
|
viewModel.CancellationToken = viewCancellationTokenSource.Token;
|
||||||
DataContext = viewModel;
|
DataContext = viewModel;
|
||||||
|
|
||||||
|
return (TViewModel)viewModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
|
|||||||
@@ -298,6 +298,7 @@
|
|||||||
<PackageReference Include="CommunityToolkit.WinUI.Controls.Primitives" Version="8.0.240109" />
|
<PackageReference Include="CommunityToolkit.WinUI.Controls.Primitives" Version="8.0.240109" />
|
||||||
<PackageReference Include="CommunityToolkit.WinUI.Controls.Segmented" Version="8.0.240109" />
|
<PackageReference Include="CommunityToolkit.WinUI.Controls.Segmented" Version="8.0.240109" />
|
||||||
<PackageReference Include="CommunityToolkit.WinUI.Controls.SettingsControls" Version="8.0.240109" />
|
<PackageReference Include="CommunityToolkit.WinUI.Controls.SettingsControls" Version="8.0.240109" />
|
||||||
|
<PackageReference Include="CommunityToolkit.WinUI.Controls.TokenizingTextBox" Version="8.0.240109" />
|
||||||
<PackageReference Include="CommunityToolkit.WinUI.Media" Version="8.0.240109" />
|
<PackageReference Include="CommunityToolkit.WinUI.Media" Version="8.0.240109" />
|
||||||
<PackageReference Include="CommunityToolkit.WinUI.Notifications" Version="7.1.2" />
|
<PackageReference Include="CommunityToolkit.WinUI.Notifications" Version="7.1.2" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.2" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.2" />
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:mxi="using:Microsoft.Xaml.Interactivity"
|
xmlns:mxi="using:Microsoft.Xaml.Interactivity"
|
||||||
xmlns:mxic="using:Microsoft.Xaml.Interactions.Core"
|
|
||||||
xmlns:shc="using:Snap.Hutao.Control"
|
xmlns:shc="using:Snap.Hutao.Control"
|
||||||
xmlns:shcb="using:Snap.Hutao.Control.Behavior"
|
xmlns:shcb="using:Snap.Hutao.Control.Behavior"
|
||||||
xmlns:shci="using:Snap.Hutao.Control.Image"
|
xmlns:shci="using:Snap.Hutao.Control.Image"
|
||||||
@@ -73,6 +72,10 @@
|
|||||||
</shct:DescriptionTextBlock>
|
</shct:DescriptionTextBlock>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
|
|
||||||
|
<DataTemplate x:Key="SuggestionTemplate">
|
||||||
|
<TextBlock VerticalAlignment="Center" Text="{Binding}"/>
|
||||||
|
</DataTemplate>
|
||||||
|
|
||||||
<DataTemplate x:Key="AvatarListTemplate">
|
<DataTemplate x:Key="AvatarListTemplate">
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
@@ -265,22 +268,20 @@
|
|||||||
</CommandBar.Content>
|
</CommandBar.Content>
|
||||||
<!--<AppBarButton Icon="{shcm:FontIcon Glyph=}" Label="搜索提示"/>-->
|
<!--<AppBarButton Icon="{shcm:FontIcon Glyph=}" Label="搜索提示"/>-->
|
||||||
<AppBarElementContainer>
|
<AppBarElementContainer>
|
||||||
<AutoSuggestBox
|
<cwc:TokenizingTextBox
|
||||||
Width="240"
|
x:Name="AvatarSuggestBox"
|
||||||
Height="36"
|
Width="520"
|
||||||
Margin="6,6,6,0"
|
Margin="6,0,6,0"
|
||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
VerticalContentAlignment="Center"
|
VerticalContentAlignment="Center"
|
||||||
|
ItemsSource="{Binding FilterTokens, Mode=TwoWay}"
|
||||||
|
MaximumTokens="5"
|
||||||
PlaceholderText="{shcm:ResourceString Name=ViewPageWiKiAvatarAutoSuggestBoxPlaceHolder}"
|
PlaceholderText="{shcm:ResourceString Name=ViewPageWiKiAvatarAutoSuggestBoxPlaceHolder}"
|
||||||
QueryIcon="{shcm:FontIcon Glyph=}"
|
QueryIcon="{cw:FontIconSource Glyph=}"
|
||||||
Style="{StaticResource DefaultAutoSuggestBoxStyle}"
|
SuggestedItemTemplate="{StaticResource SuggestionTemplate}"
|
||||||
Text="{Binding FilterText, Mode=TwoWay}">
|
SuggestedItemsSource="{Binding AvailableQueries}"
|
||||||
<mxi:Interaction.Behaviors>
|
Text="{Binding FilterToken, Mode=TwoWay}"
|
||||||
<mxic:EventTriggerBehavior EventName="QuerySubmitted">
|
TokenItemTemplate="{StaticResource SuggestionTemplate}"/>
|
||||||
<mxic:InvokeCommandAction Command="{Binding FilterCommand}" CommandParameter="{Binding FilterText}"/>
|
|
||||||
</mxic:EventTriggerBehavior>
|
|
||||||
</mxi:Interaction.Behaviors>
|
|
||||||
</AutoSuggestBox>
|
|
||||||
</AppBarElementContainer>
|
</AppBarElementContainer>
|
||||||
<AppBarButton
|
<AppBarButton
|
||||||
Command="{Binding CultivateCommand}"
|
Command="{Binding CultivateCommand}"
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
// Copyright (c) DGP Studio. All rights reserved.
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
// Licensed under the MIT license.
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
using CommunityToolkit.WinUI.Controls;
|
||||||
|
using Microsoft.UI.Xaml.Controls;
|
||||||
using Snap.Hutao.Control;
|
using Snap.Hutao.Control;
|
||||||
using Snap.Hutao.ViewModel.Wiki;
|
using Snap.Hutao.ViewModel.Wiki;
|
||||||
|
|
||||||
@@ -17,7 +19,19 @@ internal sealed partial class WikiAvatarPage : ScopedPage
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public WikiAvatarPage()
|
public WikiAvatarPage()
|
||||||
{
|
{
|
||||||
InitializeWith<WikiAvatarViewModel>();
|
WikiAvatarViewModel viewModel = InitializeWith<WikiAvatarViewModel>();
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
|
viewModel.Initialize(new TokenizingTextBoxAccessor(AvatarSuggestBox));
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TokenizingTextBoxAccessor : ITokenizingTextBoxAccessor
|
||||||
|
{
|
||||||
|
public TokenizingTextBoxAccessor(TokenizingTextBox tokenizingTextBox)
|
||||||
|
{
|
||||||
|
TokenizingTextBox = tokenizingTextBox;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TokenizingTextBox TokenizingTextBox { get; private set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,10 @@
|
|||||||
Source="{Binding Converter={StaticResource PropertyDescriptor}}"/>
|
Source="{Binding Converter={StaticResource PropertyDescriptor}}"/>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
|
|
||||||
|
<DataTemplate x:Key="SuggestionTemplate">
|
||||||
|
<TextBlock VerticalAlignment="Center" Text="{Binding}"/>
|
||||||
|
</DataTemplate>
|
||||||
|
|
||||||
<DataTemplate x:Key="WeaponListTemplate">
|
<DataTemplate x:Key="WeaponListTemplate">
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
@@ -131,21 +135,21 @@
|
|||||||
LocalSettingKeySuffixForCurrent="WikiWeaponPage.Weapons"/>
|
LocalSettingKeySuffixForCurrent="WikiWeaponPage.Weapons"/>
|
||||||
</CommandBar.Content>
|
</CommandBar.Content>
|
||||||
<AppBarElementContainer>
|
<AppBarElementContainer>
|
||||||
<AutoSuggestBox
|
<cwc:TokenizingTextBox
|
||||||
Width="240"
|
x:Name="WeaponSuggestBox"
|
||||||
Height="36"
|
Width="520"
|
||||||
Margin="16,6,6,0"
|
Margin="16,0,6,0"
|
||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
VerticalContentAlignment="Center"
|
VerticalContentAlignment="Center"
|
||||||
|
ItemTemplate="{StaticResource SuggestionTemplate}"
|
||||||
|
ItemsSource="{Binding FilterTokens, Mode=TwoWay}"
|
||||||
|
MaximumTokens="5"
|
||||||
PlaceholderText="{shcm:ResourceString Name=ViewPageWiKiWeaponAutoSuggestBoxPlaceHolder}"
|
PlaceholderText="{shcm:ResourceString Name=ViewPageWiKiWeaponAutoSuggestBoxPlaceHolder}"
|
||||||
QueryIcon="{shcm:FontIcon Glyph=}"
|
QueryIcon="{cw:FontIconSource Glyph=}"
|
||||||
Text="{Binding FilterText, Mode=TwoWay}">
|
SuggestedItemTemplate="{StaticResource SuggestionTemplate}"
|
||||||
<mxi:Interaction.Behaviors>
|
SuggestedItemsSource="{Binding AvailableQueries}"
|
||||||
<mxic:EventTriggerBehavior EventName="QuerySubmitted">
|
Text="{Binding FilterToken, Mode=TwoWay}"
|
||||||
<mxic:InvokeCommandAction Command="{Binding FilterCommand}" CommandParameter="{Binding FilterText}"/>
|
TokenItemTemplate="{StaticResource SuggestionTemplate}"/>
|
||||||
</mxic:EventTriggerBehavior>
|
|
||||||
</mxi:Interaction.Behaviors>
|
|
||||||
</AutoSuggestBox>
|
|
||||||
</AppBarElementContainer>
|
</AppBarElementContainer>
|
||||||
<AppBarButton
|
<AppBarButton
|
||||||
Command="{Binding CultivateCommand}"
|
Command="{Binding CultivateCommand}"
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) DGP Studio. All rights reserved.
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
// Licensed under the MIT license.
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
using CommunityToolkit.WinUI.Controls;
|
||||||
using Snap.Hutao.Control;
|
using Snap.Hutao.Control;
|
||||||
using Snap.Hutao.ViewModel.Wiki;
|
using Snap.Hutao.ViewModel.Wiki;
|
||||||
|
|
||||||
@@ -17,7 +18,19 @@ internal sealed partial class WikiWeaponPage : ScopedPage
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public WikiWeaponPage()
|
public WikiWeaponPage()
|
||||||
{
|
{
|
||||||
InitializeWith<WikiWeaponViewModel>();
|
WikiWeaponViewModel viewModel = InitializeWith<WikiWeaponViewModel>();
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
|
viewModel.Initialize(new TokenizingTextBoxAccessor(WeaponSuggestBox));
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TokenizingTextBoxAccessor : ITokenizingTextBoxAccessor
|
||||||
|
{
|
||||||
|
public TokenizingTextBoxAccessor(TokenizingTextBox tokenizingTextBox)
|
||||||
|
{
|
||||||
|
TokenizingTextBox = tokenizingTextBox;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TokenizingTextBox TokenizingTextBox { get; private set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
// 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; }
|
||||||
|
}
|
||||||
@@ -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(ITokenizingTextBoxAccessor accessor);
|
||||||
|
}
|
||||||
@@ -1,11 +1,14 @@
|
|||||||
// Copyright (c) DGP Studio. All rights reserved.
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
// Licensed under the MIT license.
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
using CommunityToolkit.WinUI.Controls;
|
||||||
|
using Microsoft.UI.Xaml.Controls;
|
||||||
using Snap.Hutao.Control.Collection.AdvancedCollectionView;
|
using Snap.Hutao.Control.Collection.AdvancedCollectionView;
|
||||||
using Snap.Hutao.Factory.ContentDialog;
|
using Snap.Hutao.Factory.ContentDialog;
|
||||||
using Snap.Hutao.Model.Calculable;
|
using Snap.Hutao.Model.Calculable;
|
||||||
using Snap.Hutao.Model.Entity.Primitive;
|
using Snap.Hutao.Model.Entity.Primitive;
|
||||||
using Snap.Hutao.Model.Intrinsic;
|
using Snap.Hutao.Model.Intrinsic;
|
||||||
|
using Snap.Hutao.Model.Intrinsic.Frozen;
|
||||||
using Snap.Hutao.Model.Metadata;
|
using Snap.Hutao.Model.Metadata;
|
||||||
using Snap.Hutao.Model.Metadata.Avatar;
|
using Snap.Hutao.Model.Metadata.Avatar;
|
||||||
using Snap.Hutao.Model.Metadata.Item;
|
using Snap.Hutao.Model.Metadata.Item;
|
||||||
@@ -17,6 +20,8 @@ using Snap.Hutao.Service.Notification;
|
|||||||
using Snap.Hutao.Service.User;
|
using Snap.Hutao.Service.User;
|
||||||
using Snap.Hutao.View.Dialog;
|
using Snap.Hutao.View.Dialog;
|
||||||
using Snap.Hutao.Web.Response;
|
using Snap.Hutao.Web.Response;
|
||||||
|
using System.Collections.Frozen;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using CalculateAvatarPromotionDelta = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.AvatarPromotionDelta;
|
using CalculateAvatarPromotionDelta = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.AvatarPromotionDelta;
|
||||||
using CalculateClient = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.CalculateClient;
|
using CalculateClient = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.CalculateClient;
|
||||||
@@ -32,7 +37,7 @@ namespace Snap.Hutao.ViewModel.Wiki;
|
|||||||
[HighQuality]
|
[HighQuality]
|
||||||
[ConstructorGenerated]
|
[ConstructorGenerated]
|
||||||
[Injection(InjectAs.Scoped)]
|
[Injection(InjectAs.Scoped)]
|
||||||
internal sealed partial class WikiAvatarViewModel : Abstraction.ViewModel
|
internal sealed partial class WikiAvatarViewModel : Abstraction.ViewModel, IWikiViewModelInitialization
|
||||||
{
|
{
|
||||||
private readonly IContentDialogFactory contentDialogFactory;
|
private readonly IContentDialogFactory contentDialogFactory;
|
||||||
private readonly ICultivationService cultivationService;
|
private readonly ICultivationService cultivationService;
|
||||||
@@ -45,10 +50,12 @@ internal sealed partial class WikiAvatarViewModel : Abstraction.ViewModel
|
|||||||
|
|
||||||
private AdvancedCollectionView<Avatar>? avatars;
|
private AdvancedCollectionView<Avatar>? avatars;
|
||||||
private Avatar? selected;
|
private Avatar? selected;
|
||||||
private string? filterText;
|
private ObservableCollection<string>? filterTokens;
|
||||||
|
private string? filterToken;
|
||||||
private BaseValueInfo? baseValueInfo;
|
private BaseValueInfo? baseValueInfo;
|
||||||
private Dictionary<Level, Dictionary<GrowCurveType, float>>? levelAvatarCurveMap;
|
private Dictionary<Level, Dictionary<GrowCurveType, float>>? levelAvatarCurveMap;
|
||||||
private List<Promote>? promotes;
|
private List<Promote>? promotes;
|
||||||
|
private FrozenSet<string> availableQueries;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 角色列表
|
/// 角色列表
|
||||||
@@ -75,9 +82,21 @@ internal sealed partial class WikiAvatarViewModel : Abstraction.ViewModel
|
|||||||
public BaseValueInfo? BaseValueInfo { get => baseValueInfo; set => SetProperty(ref baseValueInfo, value); }
|
public BaseValueInfo? BaseValueInfo { get => baseValueInfo; set => SetProperty(ref baseValueInfo, value); }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 筛选文本
|
/// 保存的筛选标志
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string? FilterText { get => filterText; set => SetProperty(ref filterText, value); }
|
public ObservableCollection<string>? FilterTokens { get => filterTokens; set => SetProperty(ref filterTokens, value); }
|
||||||
|
|
||||||
|
public string? FilterToken { get => filterToken; set => SetProperty(ref filterToken, value); }
|
||||||
|
|
||||||
|
public FrozenSet<string>? AvailableQueries { get => availableQueries; }
|
||||||
|
|
||||||
|
public void Initialize(ITokenizingTextBoxAccessor accessor)
|
||||||
|
{
|
||||||
|
accessor.TokenizingTextBox.TextChanged += OnFilterSuggestionRequested;
|
||||||
|
accessor.TokenizingTextBox.QuerySubmitted += OnQuerySubmitted;
|
||||||
|
accessor.TokenizingTextBox.TokenItemAdded += OnTokenItemModified;
|
||||||
|
accessor.TokenizingTextBox.TokenItemRemoved += OnTokenItemModified;
|
||||||
|
}
|
||||||
|
|
||||||
protected override async ValueTask<bool> InitializeUIAsync()
|
protected override async ValueTask<bool> InitializeUIAsync()
|
||||||
{
|
{
|
||||||
@@ -101,6 +120,18 @@ internal sealed partial class WikiAvatarViewModel : Abstraction.ViewModel
|
|||||||
await taskContext.SwitchToMainThreadAsync();
|
await taskContext.SwitchToMainThreadAsync();
|
||||||
Avatars = new(list, true);
|
Avatars = new(list, true);
|
||||||
Selected = Avatars.View.ElementAtOrDefault(0);
|
Selected = Avatars.View.ElementAtOrDefault(0);
|
||||||
|
FilterTokens = [];
|
||||||
|
|
||||||
|
availableQueries = FrozenSet.ToFrozenSet<string>(
|
||||||
|
[
|
||||||
|
.. avatars.Select(a => a.Name),
|
||||||
|
.. IntrinsicFrozen.AssociationTypes,
|
||||||
|
.. IntrinsicFrozen.BodyTypes,
|
||||||
|
.. IntrinsicFrozen.ElementNames,
|
||||||
|
.. IntrinsicFrozen.ItemQualities,
|
||||||
|
.. IntrinsicFrozen.WeaponTypes,
|
||||||
|
]);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,21 +233,53 @@ internal sealed partial class WikiAvatarViewModel : Abstraction.ViewModel
|
|||||||
BaseValueInfo = new(avatar.MaxLevel, propertyCurveValues, levelAvatarCurveMap, avatarPromoteMap);
|
BaseValueInfo = new(avatar.MaxLevel, propertyCurveValues, levelAvatarCurveMap, avatarPromoteMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Command("FilterCommand")]
|
private void OnFilterSuggestionRequested(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs args)
|
||||||
private void ApplyFilter(string? input)
|
|
||||||
{
|
{
|
||||||
if (Avatars is null)
|
if (Avatars is null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(input))
|
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 OnTokenItemModified(TokenizingTextBox sender, object args)
|
||||||
|
{
|
||||||
|
ApplyFilter();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ApplyFilter()
|
||||||
|
{
|
||||||
|
if (Avatars is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FilterTokens.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
Avatars.Filter = default!;
|
Avatars.Filter = default!;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Avatars.Filter = AvatarFilter.Compile(input);
|
Avatars.Filter = AvatarFilter.Compile(string.Join(' ', FilterTokens));
|
||||||
|
|
||||||
if (Selected is not null && Avatars.Contains(Selected))
|
if (Selected is not null && Avatars.Contains(Selected))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
// Copyright (c) DGP Studio. All rights reserved.
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
// Licensed under the MIT license.
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
using CommunityToolkit.WinUI.Controls;
|
||||||
|
using Microsoft.UI.Xaml.Controls;
|
||||||
using Snap.Hutao.Control.Collection.AdvancedCollectionView;
|
using Snap.Hutao.Control.Collection.AdvancedCollectionView;
|
||||||
using Snap.Hutao.Factory.ContentDialog;
|
using Snap.Hutao.Factory.ContentDialog;
|
||||||
using Snap.Hutao.Model.Calculable;
|
using Snap.Hutao.Model.Calculable;
|
||||||
using Snap.Hutao.Model.Entity.Primitive;
|
using Snap.Hutao.Model.Entity.Primitive;
|
||||||
using Snap.Hutao.Model.Intrinsic;
|
using Snap.Hutao.Model.Intrinsic;
|
||||||
|
using Snap.Hutao.Model.Intrinsic.Frozen;
|
||||||
using Snap.Hutao.Model.Metadata;
|
using Snap.Hutao.Model.Metadata;
|
||||||
using Snap.Hutao.Model.Metadata.Item;
|
using Snap.Hutao.Model.Metadata.Item;
|
||||||
using Snap.Hutao.Model.Metadata.Weapon;
|
using Snap.Hutao.Model.Metadata.Weapon;
|
||||||
@@ -17,6 +20,7 @@ using Snap.Hutao.Service.Notification;
|
|||||||
using Snap.Hutao.Service.User;
|
using Snap.Hutao.Service.User;
|
||||||
using Snap.Hutao.View.Dialog;
|
using Snap.Hutao.View.Dialog;
|
||||||
using Snap.Hutao.Web.Response;
|
using Snap.Hutao.Web.Response;
|
||||||
|
using System.Collections.Frozen;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using CalculateAvatarPromotionDelta = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.AvatarPromotionDelta;
|
using CalculateAvatarPromotionDelta = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.AvatarPromotionDelta;
|
||||||
using CalculateClient = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.CalculateClient;
|
using CalculateClient = Snap.Hutao.Web.Hoyolab.Takumi.Event.Calculate.CalculateClient;
|
||||||
@@ -29,7 +33,7 @@ namespace Snap.Hutao.ViewModel.Wiki;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[ConstructorGenerated]
|
[ConstructorGenerated]
|
||||||
[Injection(InjectAs.Scoped)]
|
[Injection(InjectAs.Scoped)]
|
||||||
internal sealed partial class WikiWeaponViewModel : Abstraction.ViewModel
|
internal sealed partial class WikiWeaponViewModel : Abstraction.ViewModel, IWikiViewModelInitialization
|
||||||
{
|
{
|
||||||
private readonly IContentDialogFactory contentDialogFactory;
|
private readonly IContentDialogFactory contentDialogFactory;
|
||||||
private readonly CalculateClient calculateClient;
|
private readonly CalculateClient calculateClient;
|
||||||
@@ -42,10 +46,12 @@ internal sealed partial class WikiWeaponViewModel : Abstraction.ViewModel
|
|||||||
|
|
||||||
private AdvancedCollectionView<Weapon>? weapons;
|
private AdvancedCollectionView<Weapon>? weapons;
|
||||||
private Weapon? selected;
|
private Weapon? selected;
|
||||||
private string? filterText;
|
private List<string>? filterTokens;
|
||||||
|
private string? filterToken;
|
||||||
private BaseValueInfo? baseValueInfo;
|
private BaseValueInfo? baseValueInfo;
|
||||||
private Dictionary<Level, Dictionary<GrowCurveType, float>>? levelWeaponCurveMap;
|
private Dictionary<Level, Dictionary<GrowCurveType, float>>? levelWeaponCurveMap;
|
||||||
private List<Promote>? promotes;
|
private List<Promote>? promotes;
|
||||||
|
private FrozenSet<string> availableQueries;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 角色列表
|
/// 角色列表
|
||||||
@@ -72,9 +78,21 @@ internal sealed partial class WikiWeaponViewModel : Abstraction.ViewModel
|
|||||||
public BaseValueInfo? BaseValueInfo { get => baseValueInfo; set => SetProperty(ref baseValueInfo, value); }
|
public BaseValueInfo? BaseValueInfo { get => baseValueInfo; set => SetProperty(ref baseValueInfo, value); }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 筛选文本
|
/// 保存的筛选标志
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string? FilterText { get => filterText; set => SetProperty(ref filterText, value); }
|
public List<string>? FilterTokens { get => filterTokens; set => SetProperty(ref filterTokens, value); }
|
||||||
|
|
||||||
|
public string? FilterToken { get => filterToken; set => SetProperty(ref filterToken, value); }
|
||||||
|
|
||||||
|
public FrozenSet<string> AvailableQueries { get => availableQueries; }
|
||||||
|
|
||||||
|
public void Initialize(ITokenizingTextBoxAccessor accessor)
|
||||||
|
{
|
||||||
|
accessor.TokenizingTextBox.TextChanged += OnFilterSuggestionRequested;
|
||||||
|
accessor.TokenizingTextBox.QuerySubmitted += OnQuerySubmitted;
|
||||||
|
accessor.TokenizingTextBox.TokenItemAdded += OnTokenItemModified;
|
||||||
|
accessor.TokenizingTextBox.TokenItemRemoved += OnTokenItemModified;
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
protected override async Task OpenUIAsync()
|
protected override async Task OpenUIAsync()
|
||||||
@@ -98,6 +116,15 @@ internal sealed partial class WikiWeaponViewModel : Abstraction.ViewModel
|
|||||||
|
|
||||||
Weapons = new(list, true);
|
Weapons = new(list, true);
|
||||||
Selected = Weapons.View.ElementAtOrDefault(0);
|
Selected = Weapons.View.ElementAtOrDefault(0);
|
||||||
|
FilterTokens = [];
|
||||||
|
|
||||||
|
availableQueries = FrozenSet.ToFrozenSet(
|
||||||
|
[
|
||||||
|
.. weapons.Select(w => w.Name),
|
||||||
|
.. IntrinsicFrozen.ItemQualities,
|
||||||
|
.. IntrinsicFrozen.FightProperties,
|
||||||
|
.. IntrinsicFrozen.WeaponTypes,
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,21 +214,53 @@ internal sealed partial class WikiWeaponViewModel : Abstraction.ViewModel
|
|||||||
BaseValueInfo = new(weapon.MaxLevel, propertyCurveValues, levelWeaponCurveMap, weaponPromoteMap);
|
BaseValueInfo = new(weapon.MaxLevel, propertyCurveValues, levelWeaponCurveMap, weaponPromoteMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Command("FilterCommand")]
|
private void OnFilterSuggestionRequested(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs args)
|
||||||
private void ApplyFilter(string? input)
|
|
||||||
{
|
{
|
||||||
if (Weapons is null)
|
if (Weapons is null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(input))
|
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 OnTokenItemModified(TokenizingTextBox sender, object args)
|
||||||
|
{
|
||||||
|
ApplyFilter();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ApplyFilter()
|
||||||
|
{
|
||||||
|
if (Weapons is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FilterTokens.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
Weapons.Filter = default!;
|
Weapons.Filter = default!;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Weapons.Filter = WeaponFilter.Compile(input);
|
Weapons.Filter = WeaponFilter.Compile(string.Join(' ', FilterTokens));
|
||||||
|
|
||||||
if (Selected is not null && Weapons.Contains(Selected))
|
if (Selected is not null && Weapons.Contains(Selected))
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user