mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
Compare commits
1 Commits
feat/wikis
...
activity-c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7a572631e9 |
@@ -5,6 +5,7 @@ using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
using Microsoft.UI.Xaml.Shapes;
|
||||
using System.Collections.Specialized;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Snap.Hutao.Control.Brush;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
using CommunityToolkit.WinUI.Collections;
|
||||
using CommunityToolkit.WinUI.Helpers;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
using Snap.Hutao.Core.ExceptionService;
|
||||
using System.Collections;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Specialized;
|
||||
@@ -207,11 +208,13 @@ internal sealed class AdvancedCollectionView<T> : IAdvancedCollectionView<T>, IN
|
||||
|
||||
public void Add(T item)
|
||||
{
|
||||
ThrowHelper.NotSupportedIf(IsReadOnly, "Collection is read-only.");
|
||||
source.Add(item);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
ThrowHelper.NotSupportedIf(IsReadOnly, "Collection is read-only.");
|
||||
source.Clear();
|
||||
}
|
||||
|
||||
@@ -227,6 +230,7 @@ internal sealed class AdvancedCollectionView<T> : IAdvancedCollectionView<T>, IN
|
||||
|
||||
public bool Remove(T item)
|
||||
{
|
||||
ThrowHelper.NotSupportedIf(IsReadOnly, "Collection is read-only.");
|
||||
source.Remove(item);
|
||||
return true;
|
||||
}
|
||||
@@ -239,6 +243,7 @@ internal sealed class AdvancedCollectionView<T> : IAdvancedCollectionView<T>, IN
|
||||
|
||||
public void Insert(int index, T item)
|
||||
{
|
||||
ThrowHelper.NotSupportedIf(IsReadOnly, "Collection is read-only.");
|
||||
source.Insert(index, item);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Control;
|
||||
|
||||
internal interface IXamlElementAccessor;
|
||||
@@ -41,14 +41,12 @@ internal class ScopedPage : Page
|
||||
/// 应当在 InitializeComponent() 前调用
|
||||
/// </summary>
|
||||
/// <typeparam name="TViewModel">视图模型类型</typeparam>
|
||||
protected TViewModel InitializeWith<TViewModel>()
|
||||
protected void InitializeWith<TViewModel>()
|
||||
where TViewModel : class, IViewModel
|
||||
{
|
||||
IViewModel viewModel = currentScope.ServiceProvider.GetRequiredService<TViewModel>();
|
||||
viewModel.CancellationToken = viewCancellationTokenSource.Token;
|
||||
DataContext = viewModel;
|
||||
|
||||
return (TViewModel)viewModel;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Core.DependencyInjection.Abstraction;
|
||||
using Snap.Hutao.Core.IO;
|
||||
|
||||
namespace Snap.Hutao.Core.Caching;
|
||||
@@ -9,7 +10,7 @@ namespace Snap.Hutao.Core.Caching;
|
||||
/// 为图像缓存提供抽象
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
internal interface IImageCache
|
||||
internal interface IImageCache : ICastService
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the file path containing cached item for given Uri
|
||||
|
||||
@@ -7,6 +7,4 @@ internal enum HutaoExceptionKind
|
||||
{
|
||||
None,
|
||||
ServiceTypeCastFailed,
|
||||
FileSystemCreateFileInsufficientPermissions,
|
||||
PrivateNamedPipeContentHashIncorrect,
|
||||
}
|
||||
@@ -29,7 +29,7 @@ internal readonly struct TempFile : IDisposable
|
||||
}
|
||||
catch (UnauthorizedAccessException ex)
|
||||
{
|
||||
HutaoException.Throw(HutaoExceptionKind.FileSystemCreateFileInsufficientPermissions, SH.CoreIOTempFileCreateFail, ex);
|
||||
ThrowHelper.RuntimeEnvironment(SH.CoreIOTempFileCreateFail, ex);
|
||||
}
|
||||
|
||||
if (delete)
|
||||
|
||||
@@ -148,15 +148,17 @@ internal sealed partial class Activation : IActivation
|
||||
|
||||
await taskContext.SwitchToBackgroundAsync();
|
||||
|
||||
if (serviceProvider.GetRequiredService<IMetadataService>() is IMetadataServiceInitialization metadataServiceInitialization)
|
||||
{
|
||||
metadataServiceInitialization.InitializeInternalAsync().SafeForget();
|
||||
}
|
||||
serviceProvider
|
||||
.GetRequiredService<IMetadataService>()
|
||||
.As<IMetadataServiceInitialization>()?
|
||||
.InitializeInternalAsync()
|
||||
.SafeForget();
|
||||
|
||||
if (serviceProvider.GetRequiredService<IHutaoUserService>() is IHutaoUserServiceInitialization hutaoUserServiceInitialization)
|
||||
{
|
||||
hutaoUserServiceInitialization.InitializeInternalAsync().SafeForget();
|
||||
}
|
||||
serviceProvider
|
||||
.GetRequiredService<IHutaoUserService>()
|
||||
.As<IHutaoUserServiceInitialization>()?
|
||||
.InitializeInternalAsync()
|
||||
.SafeForget();
|
||||
|
||||
serviceProvider
|
||||
.GetRequiredService<IDiscordService>()
|
||||
|
||||
@@ -49,7 +49,7 @@ internal sealed partial class PrivateNamedPipeServer : IDisposable
|
||||
{
|
||||
byte[] content = new byte[header->ContentLength];
|
||||
serverStream.ReadAtLeast(content, header->ContentLength, false);
|
||||
HutaoException.ThrowIf(XxHash64.HashToUInt64(content) != header->Checksum, HutaoExceptionKind.PrivateNamedPipeContentHashIncorrect, "PipePacket Content Hash incorrect");
|
||||
ThrowHelper.InvalidDataIf(XxHash64.HashToUInt64(content) != header->Checksum, "PipePacket Content Hash incorrect");
|
||||
return content;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Snap.Hutao.Core.LifeCycle;
|
||||
using Snap.Hutao.Core.Setting;
|
||||
using Snap.Hutao.Model;
|
||||
using Snap.Hutao.Service.Notification;
|
||||
using Snap.Hutao.Win32.Foundation;
|
||||
using Snap.Hutao.Win32.UI.Input.KeyboardAndMouse;
|
||||
using System.Text;
|
||||
@@ -18,7 +17,6 @@ namespace Snap.Hutao.Core.Windowing.HotKey;
|
||||
internal sealed class HotKeyCombination : ObservableObject
|
||||
{
|
||||
private readonly ICurrentWindowReference currentWindowReference;
|
||||
private readonly IInfoBarService infoBarService;
|
||||
private readonly RuntimeOptions runtimeOptions;
|
||||
|
||||
private readonly string settingKey;
|
||||
@@ -39,7 +37,6 @@ internal sealed class HotKeyCombination : ObservableObject
|
||||
public HotKeyCombination(IServiceProvider serviceProvider, string settingKey, int hotKeyId, HOT_KEY_MODIFIERS defaultModifiers, VirtualKey defaultKey)
|
||||
{
|
||||
currentWindowReference = serviceProvider.GetRequiredService<ICurrentWindowReference>();
|
||||
infoBarService = serviceProvider.GetRequiredService<IInfoBarService>();
|
||||
runtimeOptions = serviceProvider.GetRequiredService<RuntimeOptions>();
|
||||
|
||||
this.settingKey = settingKey;
|
||||
@@ -189,12 +186,6 @@ internal sealed class HotKeyCombination : ObservableObject
|
||||
HWND hwnd = currentWindowReference.GetWindowHandle();
|
||||
BOOL result = RegisterHotKey(hwnd, hotKeyId, Modifiers, (uint)Key);
|
||||
registered = result;
|
||||
|
||||
if (!result)
|
||||
{
|
||||
infoBarService.Warning(SH.FormatCoreWindowHotkeyCombinationRegisterFailed(SH.ViewPageSettingKeyShortcutAutoClickingHeader, DisplayName));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,11 +18,20 @@ internal static class DateTimeOffsetExtension
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
return value switch
|
||||
try
|
||||
{
|
||||
>= -62135596800 and <= 253402300799 => DateTimeOffset.FromUnixTimeSeconds(value),
|
||||
>= -62135596800000 and <= 253402300799999 => DateTimeOffset.FromUnixTimeMilliseconds(value),
|
||||
_ => defaultValue,
|
||||
};
|
||||
return DateTimeOffset.FromUnixTimeSeconds(value);
|
||||
}
|
||||
catch (ArgumentOutOfRangeException)
|
||||
{
|
||||
try
|
||||
{
|
||||
return DateTimeOffset.FromUnixTimeMilliseconds(value);
|
||||
}
|
||||
catch (ArgumentOutOfRangeException)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -46,6 +46,34 @@ internal static partial class EnumerableExtension
|
||||
return first;
|
||||
}
|
||||
|
||||
public static string JoinToString<T>(this IEnumerable<T> source, char separator, Action<StringBuilder, T> selector)
|
||||
{
|
||||
StringBuilder resultBuilder = new();
|
||||
|
||||
IEnumerator<T> enumerator = source.GetEnumerator();
|
||||
if (!enumerator.MoveNext())
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
T first = enumerator.Current;
|
||||
selector(resultBuilder, first);
|
||||
|
||||
if (!enumerator.MoveNext())
|
||||
{
|
||||
return resultBuilder.ToString();
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
resultBuilder.Append(separator);
|
||||
selector(resultBuilder, enumerator.Current);
|
||||
}
|
||||
while (enumerator.MoveNext());
|
||||
|
||||
return resultBuilder.ToString();
|
||||
}
|
||||
|
||||
public static string JoinToString<TKey, TValue>(this IEnumerable<KeyValuePair<TKey, TValue>> source, char separator, Action<StringBuilder, TKey, TValue> selector)
|
||||
{
|
||||
StringBuilder resultBuilder = new();
|
||||
|
||||
@@ -27,7 +27,7 @@ internal sealed partial class MainWindow : Window, IWindowOptionsSource, IMinMax
|
||||
public MainWindow(IServiceProvider serviceProvider)
|
||||
{
|
||||
InitializeComponent();
|
||||
windowOptions = new(this, TitleBarView.DragArea, new(1200, 741), true);
|
||||
windowOptions = new(this, TitleBarView.DragArea, new(1200, 741), true, false);
|
||||
this.InitializeController(serviceProvider);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Message;
|
||||
|
||||
internal sealed class BackgroundImageTypeChangedMessage;
|
||||
@@ -186,9 +186,6 @@
|
||||
<data name="CoreWebView2HelperVersionUndetected" xml:space="preserve">
|
||||
<value>未检测到 WebView2 运行时</value>
|
||||
</data>
|
||||
<data name="CoreWindowHotkeyCombinationRegisterFailed" xml:space="preserve">
|
||||
<value>[{0}] 热键 [{1}] 注册失败</value>
|
||||
</data>
|
||||
<data name="FilePickerExportCommit" xml:space="preserve">
|
||||
<value>导出</value>
|
||||
</data>
|
||||
|
||||
@@ -86,7 +86,7 @@ internal sealed partial class AnnouncementService : IAnnouncementService
|
||||
foreach (ref readonly Announcement item in CollectionsMarshal.AsSpan(listWrapper.List))
|
||||
{
|
||||
item.Subtitle = new StringBuilder(item.Subtitle).Replace("\r<br>", string.Empty).ToString();
|
||||
item.Content = AnnouncementRegex.XmlTimeTagRegex().Replace(item.Content, x => x.Groups[1].Value);
|
||||
item.Content = AnnouncementRegex.XmlTimeTagRegex.Replace(item.Content, x => x.Groups[1].Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -133,7 +133,7 @@ internal sealed partial class AnnouncementService : IAnnouncementService
|
||||
continue;
|
||||
}
|
||||
|
||||
MatchCollection matches = AnnouncementRegex.XmlTimeTagRegex().Matches(announcement.Content);
|
||||
MatchCollection matches = AnnouncementRegex.XmlTimeTagRegex.Matches(announcement.Content);
|
||||
if (matches.Count < 2)
|
||||
{
|
||||
continue;
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Core.DependencyInjection.Abstraction;
|
||||
|
||||
namespace Snap.Hutao.Service.Hutao;
|
||||
|
||||
/// <summary>
|
||||
/// 胡桃用户服务
|
||||
/// </summary>
|
||||
internal interface IHutaoUserService
|
||||
internal interface IHutaoUserService : ICastService
|
||||
{
|
||||
/// <summary>
|
||||
/// 异步初始化
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace Snap.Hutao.Service.Metadata;
|
||||
/// 元数据服务
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
internal interface IMetadataService
|
||||
internal interface IMetadataService : ICastService
|
||||
{
|
||||
IMemoryCache MemoryCache { get; }
|
||||
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Service.Navigation;
|
||||
|
||||
internal interface INavigationCurrent
|
||||
{
|
||||
Type? Current { get; }
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
|
||||
namespace Snap.Hutao.Service.Navigation;
|
||||
|
||||
/// <summary>
|
||||
@@ -8,5 +10,10 @@ namespace Snap.Hutao.Service.Navigation;
|
||||
/// </summary>
|
||||
internal interface INavigationInitialization
|
||||
{
|
||||
void Initialize(INavigationViewAccessor accessor);
|
||||
/// <summary>
|
||||
/// 使用指定的对象进行初始化
|
||||
/// </summary>
|
||||
/// <param name="navigationView">管理的 <see cref="NavigationView"/></param>
|
||||
/// <param name="frame">管理的 <see cref="Frame"/></param>
|
||||
void Initialize(NavigationView navigationView, Frame frame);
|
||||
}
|
||||
@@ -10,7 +10,7 @@ namespace Snap.Hutao.Service.Navigation;
|
||||
/// 导航服务
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
internal interface INavigationService : INavigationCurrent
|
||||
internal interface INavigationService : ICastService, INavigationCurrent
|
||||
{
|
||||
/// <summary>
|
||||
/// 导航到指定类型的页面
|
||||
@@ -47,4 +47,9 @@ internal interface INavigationService : INavigationCurrent
|
||||
/// 尽可能尝试返回
|
||||
/// </summary>
|
||||
void GoBack();
|
||||
}
|
||||
|
||||
internal interface INavigationCurrent
|
||||
{
|
||||
Type? Current { get; }
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Snap.Hutao.Control;
|
||||
|
||||
namespace Snap.Hutao.Service.Navigation;
|
||||
|
||||
internal interface INavigationViewAccessor : IXamlElementAccessor
|
||||
{
|
||||
NavigationView NavigationView { get; }
|
||||
|
||||
Frame Frame { get; }
|
||||
}
|
||||
@@ -147,10 +147,10 @@ internal sealed class NavigationService : INavigationService, INavigationInitial
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Initialize(INavigationViewAccessor accessor)
|
||||
public void Initialize(NavigationView navigationView, Frame frame)
|
||||
{
|
||||
NavigationView = accessor.NavigationView;
|
||||
frame = accessor.Frame;
|
||||
NavigationView = navigationView;
|
||||
this.frame = frame;
|
||||
|
||||
NavigationView.IsPaneOpen = LocalSetting.Get(SettingKeys.IsNavPaneOpen, true);
|
||||
}
|
||||
|
||||
@@ -298,7 +298,6 @@
|
||||
<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.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.Notifications" Version="7.1.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.2" />
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<mxi:Interaction.Behaviors>
|
||||
<shcb:PeriodicInvokeCommandOrOnActualThemeChangedBehavior
|
||||
Command="{Binding UpdateBackgroundCommand}"
|
||||
CommandParameter="{x:Bind BackgroundImagePresenter}"
|
||||
CommandParameter="{x:Bind BackdroundImagePresenter}"
|
||||
Period="0:5:0"/>
|
||||
</mxi:Interaction.Behaviors>
|
||||
|
||||
@@ -28,10 +28,9 @@
|
||||
<x:Double x:Key="NavigationViewItemOnLeftIconBoxHeight">24</x:Double>
|
||||
<SolidColorBrush x:Key="NavigationViewExpandedPaneBackground" Color="Transparent"/>
|
||||
</UserControl.Resources>
|
||||
<!-- Background="{ThemeResource SolidBackgroundFillColorBaseBrush}" -->
|
||||
<Grid Transitions="{ThemeResource EntranceThemeTransitions}">
|
||||
<Grid Background="{ThemeResource SolidBackgroundFillColorBaseBrush}" Transitions="{ThemeResource EntranceThemeTransitions}">
|
||||
<Image
|
||||
x:Name="BackgroundImagePresenter"
|
||||
x:Name="BackdroundImagePresenter"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Opacity="0"
|
||||
|
||||
@@ -27,44 +27,17 @@ internal sealed partial class MainView : UserControl
|
||||
/// </summary>
|
||||
public MainView()
|
||||
{
|
||||
IServiceProvider serviceProvider = Ioc.Default;
|
||||
|
||||
MainViewModel mainViewModel = serviceProvider.GetRequiredService<MainViewModel>();
|
||||
|
||||
DataContext = mainViewModel;
|
||||
DataContext = Ioc.Default.GetRequiredService<MainViewModel>();
|
||||
InitializeComponent();
|
||||
|
||||
mainViewModel.Initialize(new BackgroundImagePresenterAccessor(BackgroundImagePresenter));
|
||||
IServiceProvider serviceProvider = Ioc.Default;
|
||||
|
||||
navigationService = serviceProvider.GetRequiredService<INavigationService>();
|
||||
if (navigationService is INavigationInitialization navigationInitialization)
|
||||
{
|
||||
navigationInitialization.Initialize(new NavigationViewAccessor(NavView, ContentFrame));
|
||||
navigationInitialization.Initialize(NavView, ContentFrame);
|
||||
}
|
||||
|
||||
navigationService.Navigate<AnnouncementPage>(INavigationAwaiter.Default, true);
|
||||
}
|
||||
|
||||
private class NavigationViewAccessor : INavigationViewAccessor
|
||||
{
|
||||
public NavigationViewAccessor(NavigationView navigationView, Frame frame)
|
||||
{
|
||||
NavigationView = navigationView;
|
||||
Frame = frame;
|
||||
}
|
||||
|
||||
public NavigationView NavigationView { get; private set; }
|
||||
|
||||
public Frame Frame { get; private set; }
|
||||
}
|
||||
|
||||
private class BackgroundImagePresenterAccessor : IBackgroundImagePresenterAccessor
|
||||
{
|
||||
public BackgroundImagePresenterAccessor(Image backgroundImagePresenter)
|
||||
{
|
||||
BackgroundImagePresenter = backgroundImagePresenter;
|
||||
}
|
||||
|
||||
public Image BackgroundImagePresenter { get; private set; }
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@
|
||||
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"
|
||||
@@ -72,10 +73,6 @@
|
||||
</shct:DescriptionTextBlock>
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate x:Key="SuggestionTemplate">
|
||||
<TextBlock VerticalAlignment="Center" Text="{Binding}"/>
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate x:Key="AvatarListTemplate">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
@@ -268,20 +265,22 @@
|
||||
</CommandBar.Content>
|
||||
<!--<AppBarButton Icon="{shcm:FontIcon Glyph=}" Label="搜索提示"/>-->
|
||||
<AppBarElementContainer>
|
||||
<cwc:TokenizingTextBox
|
||||
x:Name="AvatarSuggestBox"
|
||||
Width="520"
|
||||
Margin="6,0,6,0"
|
||||
<AutoSuggestBox
|
||||
Width="240"
|
||||
Height="36"
|
||||
Margin="6,6,6,0"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalContentAlignment="Center"
|
||||
ItemsSource="{Binding FilterTokens, Mode=TwoWay}"
|
||||
MaximumTokens="5"
|
||||
PlaceholderText="{shcm:ResourceString Name=ViewPageWiKiAvatarAutoSuggestBoxPlaceHolder}"
|
||||
QueryIcon="{cw:FontIconSource Glyph=}"
|
||||
SuggestedItemTemplate="{StaticResource SuggestionTemplate}"
|
||||
SuggestedItemsSource="{Binding AvailableQueries}"
|
||||
Text="{Binding FilterToken, Mode=TwoWay}"
|
||||
TokenItemTemplate="{StaticResource SuggestionTemplate}"/>
|
||||
QueryIcon="{shcm:FontIcon Glyph=}"
|
||||
Style="{StaticResource DefaultAutoSuggestBoxStyle}"
|
||||
Text="{Binding FilterText, Mode=TwoWay}">
|
||||
<mxi:Interaction.Behaviors>
|
||||
<mxic:EventTriggerBehavior EventName="QuerySubmitted">
|
||||
<mxic:InvokeCommandAction Command="{Binding FilterCommand}" CommandParameter="{Binding FilterText}"/>
|
||||
</mxic:EventTriggerBehavior>
|
||||
</mxi:Interaction.Behaviors>
|
||||
</AutoSuggestBox>
|
||||
</AppBarElementContainer>
|
||||
<AppBarButton
|
||||
Command="{Binding CultivateCommand}"
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// 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;
|
||||
using Snap.Hutao.ViewModel.Wiki;
|
||||
|
||||
@@ -19,19 +17,7 @@ internal sealed partial class WikiAvatarPage : ScopedPage
|
||||
/// </summary>
|
||||
public WikiAvatarPage()
|
||||
{
|
||||
WikiAvatarViewModel viewModel = InitializeWith<WikiAvatarViewModel>();
|
||||
InitializeWith<WikiAvatarViewModel>();
|
||||
InitializeComponent();
|
||||
|
||||
viewModel.Initialize(new TokenizingTextBoxAccessor(AvatarSuggestBox));
|
||||
}
|
||||
|
||||
private class TokenizingTextBoxAccessor : ITokenizingTextBoxAccessor
|
||||
{
|
||||
public TokenizingTextBoxAccessor(TokenizingTextBox tokenizingTextBox)
|
||||
{
|
||||
TokenizingTextBox = tokenizingTextBox;
|
||||
}
|
||||
|
||||
public TokenizingTextBox TokenizingTextBox { get; private set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,10 +32,6 @@
|
||||
Source="{Binding Converter={StaticResource PropertyDescriptor}}"/>
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate x:Key="SuggestionTemplate">
|
||||
<TextBlock VerticalAlignment="Center" Text="{Binding}"/>
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate x:Key="WeaponListTemplate">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
@@ -135,21 +131,21 @@
|
||||
LocalSettingKeySuffixForCurrent="WikiWeaponPage.Weapons"/>
|
||||
</CommandBar.Content>
|
||||
<AppBarElementContainer>
|
||||
<cwc:TokenizingTextBox
|
||||
x:Name="WeaponSuggestBox"
|
||||
Width="520"
|
||||
Margin="16,0,6,0"
|
||||
<AutoSuggestBox
|
||||
Width="240"
|
||||
Height="36"
|
||||
Margin="16,6,6,0"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalContentAlignment="Center"
|
||||
ItemTemplate="{StaticResource SuggestionTemplate}"
|
||||
ItemsSource="{Binding FilterTokens, Mode=TwoWay}"
|
||||
MaximumTokens="5"
|
||||
PlaceholderText="{shcm:ResourceString Name=ViewPageWiKiWeaponAutoSuggestBoxPlaceHolder}"
|
||||
QueryIcon="{cw:FontIconSource Glyph=}"
|
||||
SuggestedItemTemplate="{StaticResource SuggestionTemplate}"
|
||||
SuggestedItemsSource="{Binding AvailableQueries}"
|
||||
Text="{Binding FilterToken, Mode=TwoWay}"
|
||||
TokenItemTemplate="{StaticResource SuggestionTemplate}"/>
|
||||
QueryIcon="{shcm:FontIcon Glyph=}"
|
||||
Text="{Binding FilterText, Mode=TwoWay}">
|
||||
<mxi:Interaction.Behaviors>
|
||||
<mxic:EventTriggerBehavior EventName="QuerySubmitted">
|
||||
<mxic:InvokeCommandAction Command="{Binding FilterCommand}" CommandParameter="{Binding FilterText}"/>
|
||||
</mxic:EventTriggerBehavior>
|
||||
</mxi:Interaction.Behaviors>
|
||||
</AutoSuggestBox>
|
||||
</AppBarElementContainer>
|
||||
<AppBarButton
|
||||
Command="{Binding CultivateCommand}"
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using CommunityToolkit.WinUI.Controls;
|
||||
using Snap.Hutao.Control;
|
||||
using Snap.Hutao.ViewModel.Wiki;
|
||||
|
||||
@@ -18,19 +17,7 @@ internal sealed partial class WikiWeaponPage : ScopedPage
|
||||
/// </summary>
|
||||
public WikiWeaponPage()
|
||||
{
|
||||
WikiWeaponViewModel viewModel = InitializeWith<WikiWeaponViewModel>();
|
||||
InitializeWith<WikiWeaponViewModel>();
|
||||
InitializeComponent();
|
||||
|
||||
viewModel.Initialize(new TokenizingTextBoxAccessor(WeaponSuggestBox));
|
||||
}
|
||||
|
||||
private class TokenizingTextBoxAccessor : ITokenizingTextBoxAccessor
|
||||
{
|
||||
public TokenizingTextBoxAccessor(TokenizingTextBox tokenizingTextBox)
|
||||
{
|
||||
TokenizingTextBox = tokenizingTextBox;
|
||||
}
|
||||
|
||||
public TokenizingTextBox TokenizingTextBox { get; private set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
// 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;
|
||||
|
||||
internal interface IBackgroundImagePresenterAccessor : IXamlElementAccessor
|
||||
{
|
||||
Image BackgroundImagePresenter { get; }
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.ViewModel;
|
||||
|
||||
internal interface IMainViewModelInitialization
|
||||
{
|
||||
void Initialize(IBackgroundImagePresenterAccessor accessor);
|
||||
}
|
||||
@@ -1,45 +1,27 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using CommunityToolkit.WinUI.Animations;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Media.Animation;
|
||||
using Snap.Hutao.Control.Animation;
|
||||
using Snap.Hutao.Control.Theme;
|
||||
using Snap.Hutao.Message;
|
||||
using Snap.Hutao.Service.BackgroundImage;
|
||||
|
||||
namespace Snap.Hutao.ViewModel;
|
||||
|
||||
[ConstructorGenerated]
|
||||
[Injection(InjectAs.Singleton)]
|
||||
internal sealed partial class MainViewModel : Abstraction.ViewModel, IMainViewModelInitialization, IRecipient<BackgroundImageTypeChangedMessage>
|
||||
internal sealed partial class MainViewModel : Abstraction.ViewModel
|
||||
{
|
||||
private readonly IBackgroundImageService backgroundImageService;
|
||||
private readonly ITaskContext taskContext;
|
||||
|
||||
private BackgroundImage? previousBackgroundImage;
|
||||
private Image? backgroundImagePresenter;
|
||||
|
||||
public void Initialize(IBackgroundImagePresenterAccessor accessor)
|
||||
{
|
||||
backgroundImagePresenter = accessor.BackgroundImagePresenter;
|
||||
}
|
||||
|
||||
public void Receive(BackgroundImageTypeChangedMessage message)
|
||||
{
|
||||
UpdateBackgroundAsync().SafeForget();
|
||||
}
|
||||
|
||||
[Command("UpdateBackgroundCommand")]
|
||||
private async Task UpdateBackgroundAsync()
|
||||
private async Task UpdateBackgroundAsync(Image presenter)
|
||||
{
|
||||
if (backgroundImagePresenter is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
(bool isOk, BackgroundImage backgroundImage) = await backgroundImageService.GetNextBackgroundImageAsync(previousBackgroundImage).ConfigureAwait(false);
|
||||
|
||||
if (isOk)
|
||||
@@ -54,11 +36,11 @@ internal sealed partial class MainViewModel : Abstraction.ViewModel, IMainViewMo
|
||||
duration: ControlAnimationConstants.ImageOpacityFadeInOut,
|
||||
easingType: EasingType.Quartic,
|
||||
easingMode: EasingMode.EaseInOut)
|
||||
.StartAsync(backgroundImagePresenter)
|
||||
.StartAsync(presenter)
|
||||
.ConfigureAwait(true);
|
||||
|
||||
backgroundImagePresenter.Source = backgroundImage.ImageSource;
|
||||
double targetOpacity = ThemeHelper.IsDarkMode(backgroundImagePresenter.ActualTheme) ? 1 - backgroundImage.Luminance : backgroundImage.Luminance;
|
||||
presenter.Source = backgroundImage.ImageSource;
|
||||
double targetOpacity = ThemeHelper.IsDarkMode(presenter.ActualTheme) ? 1 - backgroundImage.Luminance : backgroundImage.Luminance;
|
||||
|
||||
await AnimationBuilder
|
||||
.Create()
|
||||
@@ -67,7 +49,7 @@ internal sealed partial class MainViewModel : Abstraction.ViewModel, IMainViewMo
|
||||
duration: ControlAnimationConstants.ImageOpacityFadeInOut,
|
||||
easingType: EasingType.Quartic,
|
||||
easingMode: EasingMode.EaseInOut)
|
||||
.StartAsync(backgroundImagePresenter)
|
||||
.StartAsync(presenter)
|
||||
.ConfigureAwait(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.Windows.AppLifecycle;
|
||||
using Snap.Hutao.Core;
|
||||
@@ -55,7 +54,6 @@ internal sealed partial class SettingViewModel : Abstraction.ViewModel
|
||||
private readonly IUserService userService;
|
||||
private readonly ITaskContext taskContext;
|
||||
private readonly AppOptions appOptions;
|
||||
private readonly IMessenger messenger;
|
||||
|
||||
private NameValue<BackdropType>? selectedBackdropType;
|
||||
private NameValue<BackgroundImageType>? selectedBackgroundImageType;
|
||||
@@ -102,7 +100,6 @@ internal sealed partial class SettingViewModel : Abstraction.ViewModel
|
||||
if (SetProperty(ref selectedBackgroundImageType, value) && value is not null)
|
||||
{
|
||||
AppOptions.BackgroundImageType = value.Value;
|
||||
messenger.Send(new Message.BackgroundImageTypeChangedMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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; }
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -1,14 +1,11 @@
|
||||
// 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;
|
||||
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;
|
||||
@@ -20,8 +17,6 @@ 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.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;
|
||||
@@ -37,7 +32,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;
|
||||
@@ -50,12 +45,10 @@ internal sealed partial class WikiAvatarViewModel : Abstraction.ViewModel, IWiki
|
||||
|
||||
private AdvancedCollectionView<Avatar>? avatars;
|
||||
private Avatar? selected;
|
||||
private ObservableCollection<string>? filterTokens;
|
||||
private string? filterToken;
|
||||
private string? filterText;
|
||||
private BaseValueInfo? baseValueInfo;
|
||||
private Dictionary<Level, Dictionary<GrowCurveType, float>>? levelAvatarCurveMap;
|
||||
private List<Promote>? promotes;
|
||||
private FrozenSet<string> availableQueries;
|
||||
|
||||
/// <summary>
|
||||
/// 角色列表
|
||||
@@ -82,21 +75,9 @@ internal sealed partial class WikiAvatarViewModel : Abstraction.ViewModel, IWiki
|
||||
public BaseValueInfo? BaseValueInfo { get => baseValueInfo; set => SetProperty(ref baseValueInfo, value); }
|
||||
|
||||
/// <summary>
|
||||
/// 保存的筛选标志
|
||||
/// 筛选文本
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
public string? FilterText { get => filterText; set => SetProperty(ref filterText, value); }
|
||||
|
||||
protected override async ValueTask<bool> InitializeUIAsync()
|
||||
{
|
||||
@@ -120,18 +101,6 @@ internal sealed partial class WikiAvatarViewModel : Abstraction.ViewModel, IWiki
|
||||
await taskContext.SwitchToMainThreadAsync();
|
||||
Avatars = new(list, true);
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -233,53 +202,21 @@ internal sealed partial class WikiAvatarViewModel : Abstraction.ViewModel, IWiki
|
||||
BaseValueInfo = new(avatar.MaxLevel, propertyCurveValues, levelAvatarCurveMap, avatarPromoteMap);
|
||||
}
|
||||
|
||||
private void OnFilterSuggestionRequested(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs args)
|
||||
[Command("FilterCommand")]
|
||||
private void ApplyFilter(string? input)
|
||||
{
|
||||
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 OnTokenItemModified(TokenizingTextBox sender, object args)
|
||||
{
|
||||
ApplyFilter();
|
||||
}
|
||||
|
||||
private void ApplyFilter()
|
||||
{
|
||||
if (Avatars is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (FilterTokens.IsNullOrEmpty())
|
||||
if (string.IsNullOrWhiteSpace(input))
|
||||
{
|
||||
Avatars.Filter = default!;
|
||||
return;
|
||||
}
|
||||
|
||||
Avatars.Filter = AvatarFilter.Compile(string.Join(' ', FilterTokens));
|
||||
Avatars.Filter = AvatarFilter.Compile(input);
|
||||
|
||||
if (Selected is not null && Avatars.Contains(Selected))
|
||||
{
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
// 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;
|
||||
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;
|
||||
@@ -20,7 +17,6 @@ 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;
|
||||
@@ -33,7 +29,7 @@ namespace Snap.Hutao.ViewModel.Wiki;
|
||||
/// </summary>
|
||||
[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;
|
||||
@@ -46,12 +42,10 @@ internal sealed partial class WikiWeaponViewModel : Abstraction.ViewModel, IWiki
|
||||
|
||||
private AdvancedCollectionView<Weapon>? weapons;
|
||||
private Weapon? selected;
|
||||
private List<string>? filterTokens;
|
||||
private string? filterToken;
|
||||
private string? filterText;
|
||||
private BaseValueInfo? baseValueInfo;
|
||||
private Dictionary<Level, Dictionary<GrowCurveType, float>>? levelWeaponCurveMap;
|
||||
private List<Promote>? promotes;
|
||||
private FrozenSet<string> availableQueries;
|
||||
|
||||
/// <summary>
|
||||
/// 角色列表
|
||||
@@ -78,21 +72,9 @@ internal sealed partial class WikiWeaponViewModel : Abstraction.ViewModel, IWiki
|
||||
public BaseValueInfo? BaseValueInfo { get => baseValueInfo; set => SetProperty(ref baseValueInfo, value); }
|
||||
|
||||
/// <summary>
|
||||
/// 保存的筛选标志
|
||||
/// 筛选文本
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
public string? FilterText { get => filterText; set => SetProperty(ref filterText, value); }
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override async Task OpenUIAsync()
|
||||
@@ -116,15 +98,6 @@ internal sealed partial class WikiWeaponViewModel : Abstraction.ViewModel, IWiki
|
||||
|
||||
Weapons = new(list, true);
|
||||
Selected = Weapons.View.ElementAtOrDefault(0);
|
||||
FilterTokens = [];
|
||||
|
||||
availableQueries = FrozenSet.ToFrozenSet(
|
||||
[
|
||||
.. weapons.Select(w => w.Name),
|
||||
.. IntrinsicFrozen.ItemQualities,
|
||||
.. IntrinsicFrozen.FightProperties,
|
||||
.. IntrinsicFrozen.WeaponTypes,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,53 +187,21 @@ internal sealed partial class WikiWeaponViewModel : Abstraction.ViewModel, IWiki
|
||||
BaseValueInfo = new(weapon.MaxLevel, propertyCurveValues, levelWeaponCurveMap, weaponPromoteMap);
|
||||
}
|
||||
|
||||
private void OnFilterSuggestionRequested(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs args)
|
||||
[Command("FilterCommand")]
|
||||
private void ApplyFilter(string? input)
|
||||
{
|
||||
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 OnTokenItemModified(TokenizingTextBox sender, object args)
|
||||
{
|
||||
ApplyFilter();
|
||||
}
|
||||
|
||||
private void ApplyFilter()
|
||||
{
|
||||
if (Weapons is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (FilterTokens.IsNullOrEmpty())
|
||||
if (string.IsNullOrWhiteSpace(input))
|
||||
{
|
||||
Weapons.Filter = default!;
|
||||
return;
|
||||
}
|
||||
|
||||
Weapons.Filter = WeaponFilter.Compile(string.Join(' ', FilterTokens));
|
||||
Weapons.Filter = WeaponFilter.Compile(input);
|
||||
|
||||
if (Selected is not null && Weapons.Contains(Selected))
|
||||
{
|
||||
|
||||
@@ -22,6 +22,9 @@ internal static partial class AnnouncementRegex
|
||||
/// <inheritdoc cref="SH.WebAnnouncementMatchPermanentActivityTime"/>
|
||||
public static readonly Regex PermanentActivityAfterUpdateTimeRegex = new(SH.WebAnnouncementMatchPermanentActivityTime, RegexOptions.Compiled);
|
||||
|
||||
/// <inheritdoc cref="XmlTagRegex"/>
|
||||
public static readonly Regex XmlTimeTagRegex = XmlTagRegex();
|
||||
|
||||
[GeneratedRegex("<t class=\"t_(?:gl|lc)\".*?>(.*?)</t>", RegexOptions.Multiline)]
|
||||
public static partial Regex XmlTimeTagRegex();
|
||||
private static partial Regex XmlTagRegex();
|
||||
}
|
||||
Reference in New Issue
Block a user