init all tokens first

This commit is contained in:
qhy040404
2024-03-05 16:55:28 +08:00
parent 2ea53fd39d
commit 15a627e50a
14 changed files with 61 additions and 166 deletions

View File

@@ -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<ITokenizable>))]
[DependencyProperty("AvailableTokens", typeof(FrozenDictionary<string, SearchToken>))]
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<string> 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)

View File

@@ -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; }
}

View File

@@ -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();
}

View File

@@ -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;
}
}
}
}

View File

@@ -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;

View File

@@ -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,
}

View File

@@ -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;
/// <summary>
/// 角色的接口实现部分
/// </summary>
internal partial class Avatar : IStatisticsItemSource, ISummaryItemSource, IItemSource, INameQuality, ICalculableSource<ICalculableAvatar>, ITokenizable
internal partial class Avatar : IStatisticsItemSource, ISummaryItemSource, IItemSource, INameQuality, ICalculableSource<ICalculableAvatar>
{
/// <summary>
/// [非元数据] 搭配数据
@@ -97,9 +96,4 @@ internal partial class Avatar : IStatisticsItemSource, ISummaryItemSource, IItem
IsUp = isUp,
};
}
public ISearchToken Tokenize()
{
return new SearchToken(Name, AvatarSideIconConverter.IconNameToUri(SideIcon));
}
}

View File

@@ -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;
/// <summary>
/// 武器的接口实现
/// </summary>
internal sealed partial class Weapon : IStatisticsItemSource, ISummaryItemSource, IItemSource, INameQuality, ICalculableSource<ICalculableWeapon>, ITokenizable
internal sealed partial class Weapon : IStatisticsItemSource, ISummaryItemSource, IItemSource, INameQuality, ICalculableSource<ICalculableWeapon>
{
/// <summary>
/// [非元数据] 搭配数据
@@ -105,9 +104,4 @@ internal sealed partial class Weapon : IStatisticsItemSource, ISummaryItemSource
IsUp = isUp,
};
}
public ISearchToken Tokenize()
{
return new SearchToken(Name, EquipIconConverter.IconNameToUri(Icon));
}
}

View File

@@ -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=&#xE721;}"
SuggestedItemTemplate="{StaticResource TokenTemplate}"
SuggestedItemsSource="{Binding AvailableQueries}"
Text="{Binding FilterToken, Mode=TwoWay}"
TokenItemTemplate="{StaticResource TokenTemplate}"/>

View File

@@ -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=&#xE721;}"
SuggestedItemTemplate="{StaticResource TokenTemplate}"
SuggestedItemsSource="{Binding AvailableQueries}"
Text="{Binding FilterToken, Mode=TwoWay}"
TokenItemTemplate="{StaticResource TokenTemplate}"/>

View File

@@ -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();
}
}

View File

@@ -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();
}
}

View File

@@ -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<Level, Dictionary<GrowCurveType, float>>? levelAvatarCurveMap;
private List<Promote>? promotes;
private FrozenSet<string> availableQueries;
private FrozenDictionary<string, SearchToken> availableTokens;
/// <summary>
/// 角色列表
@@ -87,7 +88,9 @@ internal sealed partial class WikiAvatarViewModel : Abstraction.ViewModel
public string? FilterToken { get => filterToken; set => SetProperty(ref filterToken, value); }
public FrozenSet<string>? AvailableQueries { get => availableQueries; }
public FrozenDictionary<string, SearchToken>? AvailableTokens { get => availableTokens; }
public IEnumerable<SearchToken>? AvailableQueries { get => availableTokens.Values; }
protected override async ValueTask<bool> InitializeUIAsync()
{
@@ -113,15 +116,15 @@ internal sealed partial class WikiAvatarViewModel : Abstraction.ViewModel
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,
]);
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;
}

View File

@@ -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<Level, Dictionary<GrowCurveType, float>>? levelWeaponCurveMap;
private List<Promote>? promotes;
private FrozenSet<string> availableQueries;
private FrozenDictionary<string, SearchToken> availableTokens;
/// <summary>
/// 角色列表
@@ -84,7 +85,9 @@ internal sealed partial class WikiWeaponViewModel : Abstraction.ViewModel
public string? FilterToken { get => filterToken; set => SetProperty(ref filterToken, value); }
public FrozenSet<string> AvailableQueries { get => availableQueries; }
public FrozenDictionary<string, SearchToken>? AvailableTokens { get => availableTokens; }
public IEnumerable<SearchToken>? AvailableQueries { get => availableTokens.Values; }
/// <inheritdoc/>
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)))),
]);
}
}