mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
Compare commits
15 Commits
feat/wikis
...
feat/1434
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
402bb17507 | ||
|
|
dcac7ac792 | ||
|
|
d157476a9a | ||
|
|
506d198167 | ||
|
|
9c2131cb9d | ||
|
|
896e3d49f2 | ||
|
|
7da24790c4 | ||
|
|
ebf163f200 | ||
|
|
26043a6a73 | ||
|
|
ad67001556 | ||
|
|
428cd35a7f | ||
|
|
1cf3450264 | ||
|
|
1849ac16da | ||
|
|
4e9d87af50 | ||
|
|
eb125e547f |
@@ -15,7 +15,7 @@
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="3.2.1" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="3.2.1" />
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.0">
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.1">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
||||
@@ -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/>
|
||||
|
||||
@@ -25,6 +25,7 @@ internal static partial class IocHttpClientConfiguration
|
||||
.ConfigurePrimaryHttpMessageHandler((handler, provider) =>
|
||||
{
|
||||
HttpClientHandler clientHandler = (HttpClientHandler)handler;
|
||||
clientHandler.AllowAutoRedirect = true;
|
||||
clientHandler.UseProxy = true;
|
||||
clientHandler.Proxy = provider.GetRequiredService<DynamicHttpProxy>();
|
||||
});
|
||||
|
||||
@@ -23,8 +23,16 @@ internal sealed partial class ExceptionRecorder
|
||||
public void Record(Application app)
|
||||
{
|
||||
app.UnhandledException += OnAppUnhandledException;
|
||||
app.DebugSettings.FailFastOnErrors = false;
|
||||
|
||||
app.DebugSettings.IsBindingTracingEnabled = true;
|
||||
app.DebugSettings.BindingFailed += OnXamlBindingFailed;
|
||||
|
||||
app.DebugSettings.IsXamlResourceReferenceTracingEnabled = true;
|
||||
app.DebugSettings.XamlResourceReferenceFailed += OnXamlResourceReferenceFailed;
|
||||
|
||||
app.DebugSettings.LayoutCycleTracingLevel = LayoutCycleTracingLevel.High;
|
||||
app.DebugSettings.LayoutCycleDebugBreakLevel = LayoutCycleDebugBreakLevel.High;
|
||||
}
|
||||
|
||||
[SuppressMessage("", "CA2012")]
|
||||
|
||||
17
src/Snap.Hutao/Snap.Hutao/Core/Windowing/Theme.cs
Normal file
17
src/Snap.Hutao/Snap.Hutao/Core/Windowing/Theme.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Core.Windowing;
|
||||
|
||||
[Localization]
|
||||
internal enum Theme
|
||||
{
|
||||
[LocalizationKey(nameof(SH.CoreWindowThemeLight))]
|
||||
Light,
|
||||
|
||||
[LocalizationKey(nameof(SH.CoreWindowThemeDark))]
|
||||
Dark,
|
||||
|
||||
[LocalizationKey(nameof(SH.CoreWindowThemeSystem))]
|
||||
System,
|
||||
}
|
||||
@@ -129,6 +129,13 @@ internal sealed class WindowController
|
||||
UpdateSystemBackdrop(options.BackdropType);
|
||||
}
|
||||
}
|
||||
else if (e.PropertyName is nameof(AppOptions.Theme))
|
||||
{
|
||||
if (sender is AppOptions options)
|
||||
{
|
||||
UpdateTheme(options.Theme);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnWindowClosed(object sender, WindowEventArgs args)
|
||||
@@ -170,6 +177,16 @@ internal sealed class WindowController
|
||||
};
|
||||
}
|
||||
|
||||
private void UpdateTheme(Theme theme)
|
||||
{
|
||||
((FrameworkElement)window.Content).RequestedTheme = theme switch
|
||||
{
|
||||
Theme.Light => ElementTheme.Light,
|
||||
Theme.Dark => ElementTheme.Dark,
|
||||
_ => ElementTheme.Default,
|
||||
};
|
||||
}
|
||||
|
||||
private void UpdateTitleButtonColor()
|
||||
{
|
||||
AppWindowTitleBar appTitleBar = window.AppWindow.TitleBar;
|
||||
|
||||
@@ -41,6 +41,30 @@
|
||||
"Equatable": true,
|
||||
"EqualityOperators": true
|
||||
},
|
||||
{
|
||||
"Name": "FurnitureId",
|
||||
"Documentation": "家具 Id",
|
||||
"Equatable": true,
|
||||
"EqualityOperators": true
|
||||
},
|
||||
{
|
||||
"Name": "FurnitureMakeId",
|
||||
"Documentation": "家具配方 Id",
|
||||
"Equatable": true,
|
||||
"EqualityOperators": true
|
||||
},
|
||||
{
|
||||
"Name": "FurnitureSuiteId",
|
||||
"Documentation": "家具套装 Id",
|
||||
"Equatable": true,
|
||||
"EqualityOperators": true
|
||||
},
|
||||
{
|
||||
"Name": "FurnitureTypeId",
|
||||
"Documentation": "家具分类 Id",
|
||||
"Equatable": true,
|
||||
"EqualityOperators": true
|
||||
},
|
||||
{
|
||||
"Name": "Level",
|
||||
"Documentation": "等级 1 - 90",
|
||||
|
||||
@@ -13,6 +13,7 @@ internal sealed partial class SettingEntry
|
||||
public const string Culture = "Culture";
|
||||
|
||||
public const string SystemBackdropType = "SystemBackdropType";
|
||||
public const string Theme = "Theme";
|
||||
public const string BackgroundImageType = "BackgroundImageType";
|
||||
|
||||
public const string AnnouncementRegion = "AnnouncementRegion";
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Model.Intrinsic;
|
||||
|
||||
internal enum FurnitureDeploySurfaceType
|
||||
{
|
||||
Ground = 0,
|
||||
Wall = 1,
|
||||
Ceil = 2,
|
||||
StackObjPlane = 3,
|
||||
Door = 4,
|
||||
Chandelier = 5,
|
||||
Floor = 6,
|
||||
WallBody = 7,
|
||||
Carpet = 8,
|
||||
LegoRockery = 9,
|
||||
Stair = 10,
|
||||
NPC = 11,
|
||||
Animal = 12,
|
||||
Apartment = 13,
|
||||
FurnitureSuite = 14,
|
||||
Road = 15,
|
||||
Terrain = 16,
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Model.Intrinsic;
|
||||
|
||||
internal enum FurnitureDeployType
|
||||
{
|
||||
Interior,
|
||||
Exterior,
|
||||
InteriorRoom,
|
||||
InteriorHall,
|
||||
Skybox,
|
||||
}
|
||||
14
src/Snap.Hutao/Snap.Hutao/Model/Intrinsic/GroupRecordType.cs
Normal file
14
src/Snap.Hutao/Snap.Hutao/Model/Intrinsic/GroupRecordType.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Model.Intrinsic;
|
||||
|
||||
internal enum GroupRecordType
|
||||
{
|
||||
None,
|
||||
Racing,
|
||||
Balloon,
|
||||
Stake,
|
||||
Seek,
|
||||
Explosion,
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Model.Intrinsic;
|
||||
|
||||
internal enum SpecialFurnitureType
|
||||
{
|
||||
NormalFurniture,
|
||||
BlockDependent,
|
||||
FarmField,
|
||||
TeleportPoint,
|
||||
Fishpond,
|
||||
Npc,
|
||||
Apartment,
|
||||
FurnitureSuite,
|
||||
Paimon,
|
||||
Fish,
|
||||
CustomBaseFurniture,
|
||||
CustomNodeFurniture,
|
||||
VirtualFurniture,
|
||||
GroupFurniture,
|
||||
CoopPictureFrame,
|
||||
ChangeBgmFurniture,
|
||||
ServerGadget,
|
||||
Fishtank,
|
||||
}
|
||||
@@ -8,15 +8,4 @@ namespace Snap.Hutao.Model.Metadata.Achievement;
|
||||
/// <summary>
|
||||
/// 奖励
|
||||
/// </summary>
|
||||
internal sealed class Reward
|
||||
{
|
||||
/// <summary>
|
||||
/// Id
|
||||
/// </summary>
|
||||
public MaterialId Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 数量
|
||||
/// </summary>
|
||||
public uint Count { get; set; }
|
||||
}
|
||||
internal sealed class Reward : IdCount;
|
||||
@@ -0,0 +1,50 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Model.Intrinsic;
|
||||
using Snap.Hutao.Model.Primitive;
|
||||
|
||||
namespace Snap.Hutao.Model.Metadata.Furniture;
|
||||
|
||||
internal sealed class Furniture
|
||||
{
|
||||
public List<FurnitureTypeId> Types { get; set; } = default!;
|
||||
|
||||
public FurnitureDeploySurfaceType SurfaceType { get; set; }
|
||||
|
||||
public bool IsSpecial { get; set; }
|
||||
|
||||
public SpecialFurnitureType SpecialType { get; set; }
|
||||
|
||||
public uint Comfort { get; set; }
|
||||
|
||||
public uint Cost { get; set; }
|
||||
|
||||
public uint DiscountCost { get; set; }
|
||||
|
||||
public bool CanFloat { get; set; }
|
||||
|
||||
public bool IsUnique { get; set; }
|
||||
|
||||
public string? ItemIcon { get; set; }
|
||||
|
||||
public string? EffectIcon { get; set; }
|
||||
|
||||
public QualityType RankLevel { get; set; }
|
||||
|
||||
public List<FurnitureId> GruopUnits { get; set; } = default!;
|
||||
|
||||
public GroupRecordType GroupRecordType { get; set; }
|
||||
|
||||
public List<string> SourceTexts { get; set; } = default!;
|
||||
|
||||
public FurnitureId Id { get; set; }
|
||||
|
||||
public string Name { get; set; } = default!;
|
||||
|
||||
public string Description { get; set; } = default!;
|
||||
|
||||
public string? Icon { get; set; }
|
||||
|
||||
public uint Rank { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Model.Intrinsic;
|
||||
using Snap.Hutao.Model.Primitive;
|
||||
|
||||
namespace Snap.Hutao.Model.Metadata.Furniture;
|
||||
|
||||
internal sealed class FurnitureMake
|
||||
{
|
||||
public FurnitureMakeId Id { get; set; }
|
||||
|
||||
public FurnitureId ItemId { get; set; }
|
||||
|
||||
public uint Experience { get; set; }
|
||||
|
||||
public List<IdCount> Materials { get; set; } = default!;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Model.Intrinsic;
|
||||
using Snap.Hutao.Model.Primitive;
|
||||
|
||||
namespace Snap.Hutao.Model.Metadata.Furniture;
|
||||
|
||||
internal sealed class FurnitureSuite
|
||||
{
|
||||
public FurnitureSuiteId Id { get; set; }
|
||||
|
||||
public List<FurnitureTypeId> Types { get; set; } = default!;
|
||||
|
||||
public string Name { get; set; } = default!;
|
||||
|
||||
public string Description { get; set; } = default!;
|
||||
|
||||
public string ItemIcon { get; set; } = default!;
|
||||
|
||||
public string? MapIcon { get; set; }
|
||||
|
||||
public List<AvatarId>? FavoriteNpcs { get; set; }
|
||||
|
||||
public List<FurnitureId> Units { get; set; } = default!;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Model.Intrinsic;
|
||||
using Snap.Hutao.Model.Primitive;
|
||||
|
||||
namespace Snap.Hutao.Model.Metadata.Furniture;
|
||||
|
||||
internal sealed class FurnitureType
|
||||
{
|
||||
public FurnitureTypeId Id { get; set; }
|
||||
|
||||
public uint Category { get; set; }
|
||||
|
||||
public string Name { get; set; } = default!;
|
||||
|
||||
public string Name2 { get; set; } = default!;
|
||||
|
||||
public string TabIcon { get; set; } = default!;
|
||||
|
||||
public FurnitureDeployType SceneType { get; set; }
|
||||
|
||||
public bool BagPageOnly { get; set; }
|
||||
|
||||
public bool IsShowInBag { get; set; }
|
||||
|
||||
public uint Sort { get; set; }
|
||||
}
|
||||
20
src/Snap.Hutao/Snap.Hutao/Model/Metadata/IdCount.cs
Normal file
20
src/Snap.Hutao/Snap.Hutao/Model/Metadata/IdCount.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Model.Intrinsic;
|
||||
using Snap.Hutao.Model.Primitive;
|
||||
|
||||
namespace Snap.Hutao.Model.Metadata;
|
||||
|
||||
internal class IdCount
|
||||
{
|
||||
/// <summary>
|
||||
/// Id
|
||||
/// </summary>
|
||||
public MaterialId Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 数量
|
||||
/// </summary>
|
||||
public uint Count { get; set; }
|
||||
}
|
||||
@@ -60,45 +60,45 @@
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="root">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0"/>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string"/>
|
||||
<xsd:attribute name="type" type="xsd:string"/>
|
||||
<xsd:attribute name="mimetype" type="xsd:string"/>
|
||||
<xsd:attribute ref="xml:space"/>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string"/>
|
||||
<xsd:attribute name="name" type="xsd:string"/>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2"/>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1"/>
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3"/>
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4"/>
|
||||
<xsd:attribute ref="xml:space"/>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1"/>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
@@ -186,6 +186,15 @@
|
||||
<data name="CoreWebView2HelperVersionUndetected" xml:space="preserve">
|
||||
<value>No WebView2 Runtime detected</value>
|
||||
</data>
|
||||
<data name="CoreWindowThemeDark" xml:space="preserve">
|
||||
<value>Dark</value>
|
||||
</data>
|
||||
<data name="CoreWindowThemeLight" xml:space="preserve">
|
||||
<value>Light</value>
|
||||
</data>
|
||||
<data name="CoreWindowThemeSystem" xml:space="preserve">
|
||||
<value>System</value>
|
||||
</data>
|
||||
<data name="FilePickerExportCommit" xml:space="preserve">
|
||||
<value>Export</value>
|
||||
</data>
|
||||
|
||||
@@ -189,6 +189,15 @@
|
||||
<data name="CoreWindowHotkeyCombinationRegisterFailed" xml:space="preserve">
|
||||
<value>[{0}] 热键 [{1}] 注册失败</value>
|
||||
</data>
|
||||
<data name="CoreWindowThemeDark" xml:space="preserve">
|
||||
<value>深色</value>
|
||||
</data>
|
||||
<data name="CoreWindowThemeLight" xml:space="preserve">
|
||||
<value>浅色</value>
|
||||
</data>
|
||||
<data name="CoreWindowThemeSystem" xml:space="preserve">
|
||||
<value>跟随系统</value>
|
||||
</data>
|
||||
<data name="FilePickerExportCommit" xml:space="preserve">
|
||||
<value>导出</value>
|
||||
</data>
|
||||
@@ -2624,6 +2633,12 @@
|
||||
<data name="ViewPageSettingStoreReviewNavigate" xml:space="preserve">
|
||||
<value>评价软件</value>
|
||||
</data>
|
||||
<data name="ViewPageSettingThemeDescription" xml:space="preserve">
|
||||
<value>更改窗体的颜色主题</value>
|
||||
</data>
|
||||
<data name="ViewPageSettingThemeHeader" xml:space="preserve">
|
||||
<value>颜色主题</value>
|
||||
</data>
|
||||
<data name="ViewPageSettingTranslateNavigate" xml:space="preserve">
|
||||
<value>贡献翻译</value>
|
||||
</data>
|
||||
@@ -2895,7 +2910,7 @@
|
||||
<value>〓活动时间〓.*?\d\.\d版本期间持续开放</value>
|
||||
</data>
|
||||
<data name="WebAnnouncementMatchTransientActivityTime" xml:space="preserve">
|
||||
<value>(?:〓活动时间〓|祈愿时间|【上架时间】).*?(\d\.\d版本更新后).*?~.*?&lt;t class="t_(?:gl|lc)".*?&gt;(.*?)&lt;/t&gt;</value>
|
||||
<value>(?:〓活动时间〓|祈愿时间|【上架时间】|〓折扣时间〓).*?(\d\.\d版本更新后).*?~.*?&lt;t class="t_(?:gl|lc)".*?&gt;(.*?)&lt;/t&gt;</value>
|
||||
</data>
|
||||
<data name="WebAnnouncementMatchVersionUpdateTime" xml:space="preserve">
|
||||
<value>〓更新时间〓.+?&lt;t class=\"t_(?:gl|lc)\".*?&gt;(.*?)&lt;/t&gt;</value>
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 8.0 KiB |
@@ -85,8 +85,13 @@ 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.Subtitle = new StringBuilder(item.Subtitle)
|
||||
.Replace("\r<br>", string.Empty)
|
||||
.Replace("<br />", string.Empty)
|
||||
.ToString();
|
||||
item.Content = AnnouncementRegex
|
||||
.XmlTimeTagRegex()
|
||||
.Replace(item.Content, x => x.Groups[1].Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ internal sealed partial class AppOptions : DbStoreOptions
|
||||
{
|
||||
private bool? isEmptyHistoryWishVisible;
|
||||
private BackdropType? backdropType;
|
||||
private Theme? theme;
|
||||
private BackgroundImageType? backgroundImageType;
|
||||
private Region? region;
|
||||
private string? geetestCustomCompositeUrl;
|
||||
@@ -34,6 +35,14 @@ internal sealed partial class AppOptions : DbStoreOptions
|
||||
set => SetOption(ref backdropType, SettingEntry.SystemBackdropType, value, EnumToStringOrEmpty);
|
||||
}
|
||||
|
||||
public List<NameValue<Theme>> Themes { get; } = CollectionsNameValue.FromEnum<Theme>(theme => theme.GetLocalizedDescription());
|
||||
|
||||
public Theme Theme
|
||||
{
|
||||
get => GetOption(ref theme, SettingEntry.Theme, EnumParse<Theme>, Theme.System).Value;
|
||||
set => SetOption(ref theme, SettingEntry.Theme, value, EnumToStringOrEmpty);
|
||||
}
|
||||
|
||||
public List<NameValue<BackgroundImageType>> BackgroundImageTypes { get; } = CollectionsNameValue.FromEnum<BackgroundImageType>(type => type.GetLocalizedDescription());
|
||||
|
||||
public BackgroundImageType BackgroundImageType
|
||||
|
||||
@@ -28,13 +28,13 @@ internal sealed partial class BackgroundImageService : IBackgroundImageService
|
||||
|
||||
private HashSet<string> currentBackgroundPathSet;
|
||||
|
||||
public async ValueTask<ValueResult<bool, BackgroundImage>> GetNextBackgroundImageAsync(BackgroundImage? previous)
|
||||
public async ValueTask<ValueResult<bool, BackgroundImage?>> GetNextBackgroundImageAsync(BackgroundImage? previous)
|
||||
{
|
||||
HashSet<string> backgroundSet = await SkipOrInitBackgroundAsync().ConfigureAwait(false);
|
||||
|
||||
if (backgroundSet.Count <= 0)
|
||||
{
|
||||
return new(false, default!);
|
||||
return new(true, default!);
|
||||
}
|
||||
|
||||
string path = System.Random.Shared.GetItems([..backgroundSet], 1)[0];
|
||||
@@ -109,6 +109,9 @@ internal sealed partial class BackgroundImageService : IBackgroundImageService
|
||||
case BackgroundImageType.HutaoOfficialLauncher:
|
||||
await SetCurrentBackgroundPathSetAsync(client => client.GetLauncherWallpaperAsync()).ConfigureAwait(false);
|
||||
break;
|
||||
default:
|
||||
currentBackgroundPathSet = [];
|
||||
break;
|
||||
}
|
||||
|
||||
currentBackgroundPathSet ??= [];
|
||||
|
||||
@@ -5,5 +5,5 @@ namespace Snap.Hutao.Service.BackgroundImage;
|
||||
|
||||
internal interface IBackgroundImageService
|
||||
{
|
||||
ValueTask<ValueResult<bool, BackgroundImage>> GetNextBackgroundImageAsync(BackgroundImage? previous);
|
||||
ValueTask<ValueResult<bool, BackgroundImage?>> GetNextBackgroundImageAsync(BackgroundImage? previous);
|
||||
}
|
||||
@@ -41,39 +41,33 @@ internal sealed partial class DiscordService : IDiscordService, IDisposable
|
||||
|
||||
private bool IsSupported()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Actually requires a discord client to be running on Windows platform.
|
||||
// If not, discord core creation code will throw.
|
||||
Process[] discordProcesses = Process.GetProcessesByName("Discord");
|
||||
// Actually requires a discord client to be running on Windows platform.
|
||||
// If not, discord core creation code will throw.
|
||||
Process[] discordProcesses = Process.GetProcessesByName("Discord");
|
||||
|
||||
if (discordProcesses.Length <= 0)
|
||||
if (discordProcesses.Length <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (Process process in discordProcesses)
|
||||
{
|
||||
try
|
||||
{
|
||||
_ = process.Handle;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
if (!isInitialized)
|
||||
{
|
||||
isInitialized = true;
|
||||
infoBarService.Warning(SH.ServiceDiscordActivityElevationRequiredHint);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (Process process in discordProcesses)
|
||||
{
|
||||
try
|
||||
{
|
||||
_ = process.Handle;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
if (!isInitialized)
|
||||
{
|
||||
infoBarService.Warning(SH.ServiceDiscordActivityElevationRequiredHint);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
finally
|
||||
{
|
||||
isInitialized = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -23,8 +23,15 @@ internal sealed class LaunchExecutionBetterGenshinImpactAutomationHandlder : ILa
|
||||
Uri betterGenshinImpactUri = "bettergi://start".ToUri();
|
||||
if (await Launcher.QueryUriSupportAsync(betterGenshinImpactUri, LaunchQuerySupportType.Uri) is LaunchQuerySupportStatus.Available)
|
||||
{
|
||||
context.Logger.LogInformation("Waiting game window to be ready");
|
||||
context.Process.WaitForInputIdle();
|
||||
try
|
||||
{
|
||||
context.Logger.LogInformation("Waiting game window to be ready");
|
||||
context.Process.WaitForInputIdle();
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
context.Logger.LogInformation("Launching BetterGI");
|
||||
await Launcher.LaunchUriAsync(betterGenshinImpactUri);
|
||||
|
||||
@@ -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" />
|
||||
@@ -316,8 +315,8 @@
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.VisualStudio.Validation" Version="17.8.8" />
|
||||
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.22621.2428" />
|
||||
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.4.240211001" />
|
||||
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.22621.3233" />
|
||||
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.5.240227000" />
|
||||
<PackageReference Include="QRCoder" Version="1.4.3" />
|
||||
<PackageReference Include="Snap.Discord.GameSDK" Version="1.6.0" />
|
||||
<PackageReference Include="Snap.Hutao.Deployment.Runtime" Version="1.15.3">
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Control;
|
||||
using Snap.Hutao.Core.Windowing;
|
||||
|
||||
namespace Snap.Hutao.View.Converter.Specialized;
|
||||
|
||||
internal sealed class BackdropTypeToOpacityConverter : ValueConverter<BackdropType, double>
|
||||
{
|
||||
public override double Convert(BackdropType from)
|
||||
{
|
||||
return from is BackdropType.None ? 1 : 0;
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@
|
||||
xmlns:shch="using:Snap.Hutao.Control.Helper"
|
||||
xmlns:shcm="using:Snap.Hutao.Control.Markup"
|
||||
xmlns:shv="using:Snap.Hutao.View"
|
||||
xmlns:shvcs="using:Snap.Hutao.View.Converter.Specialized"
|
||||
xmlns:shvh="using:Snap.Hutao.View.Helper"
|
||||
xmlns:shvm="using:Snap.Hutao.ViewModel"
|
||||
xmlns:shvp="using:Snap.Hutao.View.Page"
|
||||
@@ -27,9 +28,16 @@
|
||||
<Thickness x:Key="NavigationViewContentGridBorderThickness">0,1,0,0</Thickness>
|
||||
<x:Double x:Key="NavigationViewItemOnLeftIconBoxHeight">24</x:Double>
|
||||
<SolidColorBrush x:Key="NavigationViewExpandedPaneBackground" Color="Transparent"/>
|
||||
<shvcs:BackdropTypeToOpacityConverter x:Key="BackdropTypeToOpacityConverter"/>
|
||||
</UserControl.Resources>
|
||||
<!-- Background="{ThemeResource SolidBackgroundFillColorBaseBrush}" -->
|
||||
|
||||
<Grid Transitions="{ThemeResource EntranceThemeTransitions}">
|
||||
<Border Background="{ThemeResource SolidBackgroundFillColorBaseBrush}" Opacity="{Binding AppOptions.BackdropType, Converter={StaticResource BackdropTypeToOpacityConverter}, Mode=OneWay}">
|
||||
<Border.OpacityTransition>
|
||||
<ScalarTransition Duration="0:0:1"/>
|
||||
</Border.OpacityTransition>
|
||||
</Border>
|
||||
|
||||
<Image
|
||||
x:Name="BackgroundImagePresenter"
|
||||
HorizontalAlignment="Center"
|
||||
|
||||
@@ -1,13 +1,7 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using CommunityToolkit.WinUI.Animations;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Media.Animation;
|
||||
using Snap.Hutao.Control.Animation;
|
||||
using Snap.Hutao.Control.Theme;
|
||||
using Snap.Hutao.Service.BackgroundImage;
|
||||
using Snap.Hutao.Service.Navigation;
|
||||
using Snap.Hutao.View.Page;
|
||||
using Snap.Hutao.ViewModel;
|
||||
|
||||
@@ -314,6 +314,17 @@
|
||||
SelectedItem="{Binding SelectedBackdropType, Mode=TwoWay}"/>
|
||||
</shc:SizeRestrictedContentControl>
|
||||
</cwc:SettingsCard>
|
||||
<cwc:SettingsCard
|
||||
Description="{shcm:ResourceString Name=ViewPageSettingThemeDescription}"
|
||||
Header="{shcm:ResourceString Name=ViewPageSettingThemeHeader}"
|
||||
HeaderIcon="{shcm:FontIcon Glyph=}">
|
||||
<shc:SizeRestrictedContentControl>
|
||||
<ComboBox
|
||||
DisplayMemberPath="Name"
|
||||
ItemsSource="{Binding AppOptions.Themes}"
|
||||
SelectedItem="{Binding SelectedTheme, Mode=TwoWay}"/>
|
||||
</shc:SizeRestrictedContentControl>
|
||||
</cwc:SettingsCard>
|
||||
<cwc:SettingsExpander
|
||||
Description="{shcm:ResourceString Name=ViewPageSettingBackgroundImageDescription}"
|
||||
Header="{shcm:ResourceString Name=ViewPageSettingBackgroundImageHeader}"
|
||||
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,9 +76,10 @@ internal sealed class DownloadSummary : ObservableObject
|
||||
{
|
||||
HttpResponseMessage response = await httpClient.GetAsync(fileUrl, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false);
|
||||
|
||||
if (response.Content.Headers.ContentType?.MediaType is not "application/octet-stream")
|
||||
if (response.Content.Headers.ContentType?.MediaType is not ("application/octet-stream" or "application/zip"))
|
||||
{
|
||||
logger.LogWarning("Download Static Zip failed, Content-Type is {Type}", response.Content.Headers.ContentType);
|
||||
await taskContext.SwitchToMainThreadAsync();
|
||||
Description = SH.ViewModelWelcomeDownloadSummaryContentTypeNotMatch;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,9 @@ using Microsoft.UI.Xaml.Media.Animation;
|
||||
using Snap.Hutao.Control.Animation;
|
||||
using Snap.Hutao.Control.Theme;
|
||||
using Snap.Hutao.Message;
|
||||
using Snap.Hutao.Service;
|
||||
using Snap.Hutao.Service.BackgroundImage;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Snap.Hutao.ViewModel;
|
||||
|
||||
@@ -17,11 +19,15 @@ namespace Snap.Hutao.ViewModel;
|
||||
internal sealed partial class MainViewModel : Abstraction.ViewModel, IMainViewModelInitialization, IRecipient<BackgroundImageTypeChangedMessage>
|
||||
{
|
||||
private readonly IBackgroundImageService backgroundImageService;
|
||||
private readonly ILogger<MainViewModel> logger;
|
||||
private readonly ITaskContext taskContext;
|
||||
private readonly AppOptions appOptions;
|
||||
|
||||
private BackgroundImage? previousBackgroundImage;
|
||||
private Image? backgroundImagePresenter;
|
||||
|
||||
public AppOptions AppOptions { get => appOptions; }
|
||||
|
||||
public void Initialize(IBackgroundImagePresenterAccessor accessor)
|
||||
{
|
||||
backgroundImagePresenter = accessor.BackgroundImagePresenter;
|
||||
@@ -40,9 +46,9 @@ internal sealed partial class MainViewModel : Abstraction.ViewModel, IMainViewMo
|
||||
return;
|
||||
}
|
||||
|
||||
(bool isOk, BackgroundImage backgroundImage) = await backgroundImageService.GetNextBackgroundImageAsync(previousBackgroundImage).ConfigureAwait(false);
|
||||
(bool shouldRefresh, BackgroundImage? backgroundImage) = await backgroundImageService.GetNextBackgroundImageAsync(previousBackgroundImage).ConfigureAwait(false);
|
||||
|
||||
if (isOk)
|
||||
if (shouldRefresh)
|
||||
{
|
||||
previousBackgroundImage = backgroundImage;
|
||||
await taskContext.SwitchToMainThreadAsync();
|
||||
@@ -57,8 +63,18 @@ internal sealed partial class MainViewModel : Abstraction.ViewModel, IMainViewMo
|
||||
.StartAsync(backgroundImagePresenter)
|
||||
.ConfigureAwait(true);
|
||||
|
||||
backgroundImagePresenter.Source = backgroundImage.ImageSource;
|
||||
double targetOpacity = ThemeHelper.IsDarkMode(backgroundImagePresenter.ActualTheme) ? 1 - backgroundImage.Luminance : backgroundImage.Luminance;
|
||||
backgroundImagePresenter.Source = backgroundImage?.ImageSource;
|
||||
double targetOpacity = backgroundImage is not null
|
||||
? ThemeHelper.IsDarkMode(backgroundImagePresenter.ActualTheme)
|
||||
? 1 - backgroundImage.Luminance
|
||||
: backgroundImage.Luminance
|
||||
: 0;
|
||||
|
||||
logger.LogInformation(
|
||||
"Background image: [Accent color: {AccentColor}] [Luminance: {Luminance}] [Opacity: {TargetOpacity}]",
|
||||
backgroundImage?.AccentColor.ToString(CultureInfo.CurrentCulture),
|
||||
backgroundImage?.Luminance,
|
||||
targetOpacity);
|
||||
|
||||
await AnimationBuilder
|
||||
.Create()
|
||||
|
||||
@@ -58,6 +58,7 @@ internal sealed partial class SettingViewModel : Abstraction.ViewModel
|
||||
private readonly IMessenger messenger;
|
||||
|
||||
private NameValue<BackdropType>? selectedBackdropType;
|
||||
private NameValue<Theme>? selectedTheme;
|
||||
private NameValue<BackgroundImageType>? selectedBackgroundImageType;
|
||||
private NameValue<CultureInfo>? selectedCulture;
|
||||
private NameValue<Region>? selectedRegion;
|
||||
@@ -94,6 +95,18 @@ internal sealed partial class SettingViewModel : Abstraction.ViewModel
|
||||
}
|
||||
}
|
||||
|
||||
public NameValue<Theme>? SelectedTheme
|
||||
{
|
||||
get => selectedTheme ??= AppOptions.Themes.Single(t => t.Value == AppOptions.Theme);
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref selectedTheme, value) && value is not null)
|
||||
{
|
||||
AppOptions.Theme = value.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public NameValue<BackgroundImageType>? SelectedBackgroundImageType
|
||||
{
|
||||
get => selectedBackgroundImageType ??= AppOptions.BackgroundImageTypes.Single(t => t.Value == AppOptions.BackgroundImageType);
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user