mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
caching announcements
This commit is contained in:
@@ -2,7 +2,8 @@
|
|||||||
x:Class="Snap.Hutao.App"
|
x:Class="Snap.Hutao.App"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:muxc="using:Microsoft.UI.Xaml.Controls">
|
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
|
||||||
|
xmlns:system="using:System">
|
||||||
<Application.Resources>
|
<Application.Resources>
|
||||||
<ResourceDictionary>
|
<ResourceDictionary>
|
||||||
<ResourceDictionary.MergedDictionaries>
|
<ResourceDictionary.MergedDictionaries>
|
||||||
@@ -16,7 +17,6 @@
|
|||||||
<StaticResource x:Key="WindowCaptionForeground" ResourceKey="SystemControlForegroundBaseHighBrush" />
|
<StaticResource x:Key="WindowCaptionForeground" ResourceKey="SystemControlForegroundBaseHighBrush" />
|
||||||
<StaticResource x:Key="WindowCaptionForegroundDisabled" ResourceKey="SystemControlForegroundBaseHighBrush" />
|
<StaticResource x:Key="WindowCaptionForegroundDisabled" ResourceKey="SystemControlForegroundBaseHighBrush" />
|
||||||
|
|
||||||
<CornerRadius x:Key="WindowCornerRadius">8</CornerRadius>
|
|
||||||
<CornerRadius x:Key="CompatCornerRadius">4</CornerRadius>
|
<CornerRadius x:Key="CompatCornerRadius">4</CornerRadius>
|
||||||
<CornerRadius x:Key="CompatCornerRadiusTop">4,4,0,0</CornerRadius>
|
<CornerRadius x:Key="CompatCornerRadiusTop">4,4,0,0</CornerRadius>
|
||||||
<CornerRadius x:Key="CompatCornerRadiusRight">0,4,4,0</CornerRadius>
|
<CornerRadius x:Key="CompatCornerRadiusRight">0,4,4,0</CornerRadius>
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ public partial class App : Application
|
|||||||
{
|
{
|
||||||
IServiceProvider services = new ServiceCollection()
|
IServiceProvider services = new ServiceCollection()
|
||||||
.AddLogging(builder => builder.AddDebug())
|
.AddLogging(builder => builder.AddDebug())
|
||||||
|
.AddMemoryCache()
|
||||||
.AddDatebase()
|
.AddDatebase()
|
||||||
.AddHttpClients()
|
.AddHttpClients()
|
||||||
.AddDefaultJsonSerializerOptions()
|
.AddDefaultJsonSerializerOptions()
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ namespace Snap.Hutao.Core.Abstraction;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 可异步初始化
|
/// 可异步初始化
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal interface IAsyncInitializable
|
internal interface ISupportAsyncInitialization
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 是否已经初始化完成
|
/// 是否已经初始化完成
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
namespace Snap.Hutao.Core.Abstraction;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 表示支持验证
|
||||||
|
/// </summary>
|
||||||
|
internal interface ISupportValidation
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 验证
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>当前数据是否有效</returns>
|
||||||
|
public bool Validate();
|
||||||
|
}
|
||||||
@@ -9,21 +9,21 @@ namespace Snap.Hutao.Core.Json.Converter;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 实现日期的转换
|
/// 实现日期的转换
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal class DateTimeConverter : JsonConverter<DateTime>
|
internal class DateTimeOffsetConverter : JsonConverter<DateTimeOffset>
|
||||||
{
|
{
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
public override DateTimeOffset Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||||
{
|
{
|
||||||
if (reader.GetString() is string dataTimeString)
|
if (reader.GetString() is string dataTimeString)
|
||||||
{
|
{
|
||||||
return DateTime.Parse(dataTimeString);
|
return DateTimeOffset.Parse(dataTimeString);
|
||||||
}
|
}
|
||||||
|
|
||||||
return default(DateTime);
|
return default;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
|
public override void Write(Utf8JsonWriter writer, DateTimeOffset value, JsonSerializerOptions options)
|
||||||
{
|
{
|
||||||
writer.WriteStringValue(value.ToString("yyyy-MM-dd HH:mm:ss"));
|
writer.WriteStringValue(value.ToString("yyyy-MM-dd HH:mm:ss"));
|
||||||
}
|
}
|
||||||
@@ -9,11 +9,15 @@ namespace Snap.Hutao.Core;
|
|||||||
/// 检测 WebView2运行时 是否存在
|
/// 检测 WebView2运行时 是否存在
|
||||||
/// 不再使用注册表检查方式
|
/// 不再使用注册表检查方式
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static class WebView2Helper
|
internal class WebView2Helper
|
||||||
{
|
{
|
||||||
private static bool hasEverDetected = false;
|
private static bool hasEverDetected = false;
|
||||||
private static bool isSupported = false;
|
private static bool isSupported = false;
|
||||||
|
|
||||||
|
private WebView2Helper()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 检测 WebView2 是否存在
|
/// 检测 WebView2 是否存在
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -9,13 +9,14 @@
|
|||||||
|
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="28"/>
|
<RowDefinition Height="48.8"/>
|
||||||
<RowDefinition/>
|
<RowDefinition/>
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
<Grid
|
<view:TitleView
|
||||||
x:Name="TitleBarGrid"
|
x:Name="TitleBarView">
|
||||||
Background="Transparent"/>
|
|
||||||
|
</view:TitleView>
|
||||||
|
|
||||||
<view:MainView Grid.Row="1"/>
|
<view:MainView Grid.Row="1"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@@ -18,6 +18,6 @@ public sealed partial class MainWindow : Window
|
|||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
ExtendsContentIntoTitleBar = true;
|
ExtendsContentIntoTitleBar = true;
|
||||||
SetTitleBar(TitleBarGrid);
|
SetTitleBar(TitleBarView.DragableArea);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,10 +12,10 @@ namespace Snap.Hutao.Service.Abstraction;
|
|||||||
public interface IAnnouncementService
|
public interface IAnnouncementService
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 异步获取游戏公告与活动
|
/// 异步获取游戏公告与活动,通常会进行缓存
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="openAnnouncementUICommand">打开公告时触发的命令</param>
|
/// <param name="openAnnouncementUICommand">打开公告时触发的命令</param>
|
||||||
/// <param name="cancellationToken">取消令牌</param>
|
/// <param name="cancellationToken">取消令牌</param>
|
||||||
/// <returns>公告包装器</returns>
|
/// <returns>公告包装器</returns>
|
||||||
Task<AnnouncementWrapper> GetAnnouncementsAsync(ICommand openAnnouncementUICommand, CancellationToken cancellationToken = default);
|
ValueTask<AnnouncementWrapper> GetAnnouncementsAsync(ICommand openAnnouncementUICommand, CancellationToken cancellationToken = default);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) DGP Studio. All rights reserved.
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
// Licensed under the MIT license.
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
using Snap.Hutao.Service.Abstraction;
|
using Snap.Hutao.Service.Abstraction;
|
||||||
using Snap.Hutao.Web.Hoyolab.Hk4e.Common.Announcement;
|
using Snap.Hutao.Web.Hoyolab.Hk4e.Common.Announcement;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -14,20 +15,31 @@ namespace Snap.Hutao.Service;
|
|||||||
[Injection(InjectAs.Transient, typeof(IAnnouncementService))]
|
[Injection(InjectAs.Transient, typeof(IAnnouncementService))]
|
||||||
internal class AnnouncementService : IAnnouncementService
|
internal class AnnouncementService : IAnnouncementService
|
||||||
{
|
{
|
||||||
|
private const string CacheKey = $"{nameof(IAnnouncementService)}.Cache.{nameof(AnnouncementWrapper)}";
|
||||||
|
|
||||||
private readonly AnnouncementClient announcementClient;
|
private readonly AnnouncementClient announcementClient;
|
||||||
|
private readonly IMemoryCache memoryCache;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 构造一个新的公告服务
|
/// 构造一个新的公告服务
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="announcementClient">公告提供器</param>
|
/// <param name="announcementClient">公告提供器</param>
|
||||||
public AnnouncementService(AnnouncementClient announcementClient)
|
/// <param name="memoryCache">缓存</param>
|
||||||
|
public AnnouncementService(AnnouncementClient announcementClient, IMemoryCache memoryCache)
|
||||||
{
|
{
|
||||||
this.announcementClient = announcementClient;
|
this.announcementClient = announcementClient;
|
||||||
|
this.memoryCache = memoryCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public async Task<AnnouncementWrapper> GetAnnouncementsAsync(ICommand openAnnouncementUICommand, CancellationToken cancellationToken = default)
|
public async ValueTask<AnnouncementWrapper> GetAnnouncementsAsync(ICommand openAnnouncementUICommand, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
|
// 缓存中存在记录,直接返回
|
||||||
|
if (memoryCache.TryGetValue(CacheKey, out object? cache))
|
||||||
|
{
|
||||||
|
return Must.NotNull((cache as AnnouncementWrapper)!);
|
||||||
|
}
|
||||||
|
|
||||||
AnnouncementWrapper? wrapper = await announcementClient
|
AnnouncementWrapper? wrapper = await announcementClient
|
||||||
.GetAnnouncementsAsync(cancellationToken)
|
.GetAnnouncementsAsync(cancellationToken)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
@@ -46,7 +58,7 @@ internal class AnnouncementService : IAnnouncementService
|
|||||||
// 将公告内容联入公告列表
|
// 将公告内容联入公告列表
|
||||||
JoinAnnouncements(openAnnouncementUICommand, contentMap, wrapper.List);
|
JoinAnnouncements(openAnnouncementUICommand, contentMap, wrapper.List);
|
||||||
|
|
||||||
return wrapper;
|
return memoryCache.Set(CacheKey, wrapper, TimeSpan.FromMinutes(30));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void JoinAnnouncements(ICommand openAnnouncementUICommand, Dictionary<int, string> contentMap, List<AnnouncementListWrapper> announcementListWrappers)
|
private static void JoinAnnouncements(ICommand openAnnouncementUICommand, Dictionary<int, string> contentMap, List<AnnouncementListWrapper> announcementListWrappers)
|
||||||
|
|||||||
@@ -103,11 +103,6 @@ internal class NavigationService : INavigationService
|
|||||||
bool navigated = false;
|
bool navigated = false;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (data != null && data.GetType() != typeof(NavigationExtra))
|
|
||||||
{
|
|
||||||
data = new NavigationExtra(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
navigated = Frame?.Navigate(pageType, data) ?? false;
|
navigated = Frame?.Navigate(pageType, data) ?? false;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|||||||
@@ -32,6 +32,8 @@
|
|||||||
<None Remove="View\Page\AnnouncementContentPage.xaml" />
|
<None Remove="View\Page\AnnouncementContentPage.xaml" />
|
||||||
<None Remove="View\Page\AnnouncementPage.xaml" />
|
<None Remove="View\Page\AnnouncementPage.xaml" />
|
||||||
<None Remove="View\Page\SettingPage.xaml" />
|
<None Remove="View\Page\SettingPage.xaml" />
|
||||||
|
<None Remove="View\TitleView.xaml" />
|
||||||
|
<None Remove="View\UserView.xaml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<AdditionalFiles Include="stylecop.json" />
|
<AdditionalFiles Include="stylecop.json" />
|
||||||
@@ -55,6 +57,7 @@
|
|||||||
<PackageReference Include="Microsoft.AppCenter.Analytics" Version="4.5.1" />
|
<PackageReference Include="Microsoft.AppCenter.Analytics" Version="4.5.1" />
|
||||||
<PackageReference Include="Microsoft.AppCenter.Crashes" Version="4.5.1" />
|
<PackageReference Include="Microsoft.AppCenter.Crashes" Version="4.5.1" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.6" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.6" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="6.0.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="6.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="6.0.0" />
|
||||||
<PackageReference Include="Microsoft.VisualStudio.Threading" Version="17.2.32" />
|
<PackageReference Include="Microsoft.VisualStudio.Threading" Version="17.2.32" />
|
||||||
@@ -82,6 +85,16 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\SettingsUI\SettingsUI.csproj" />
|
<ProjectReference Include="..\..\SettingsUI\SettingsUI.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Page Update="View\UserView.xaml">
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
</Page>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Page Update="View\TitleView.xaml">
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
</Page>
|
||||||
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Page Update="View\Page\AnnouncementContentPage.xaml">
|
<Page Update="View\Page\AnnouncementContentPage.xaml">
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
|||||||
@@ -1,85 +0,0 @@
|
|||||||
// Copyright (c) DGP Studio. All rights reserved.
|
|
||||||
// Licensed under the MIT license.
|
|
||||||
|
|
||||||
using Microsoft.UI.Xaml;
|
|
||||||
using Microsoft.UI.Xaml.Data;
|
|
||||||
using Snap.Hutao.Core;
|
|
||||||
|
|
||||||
namespace Snap.Hutao.View.Converter;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This class converts a boolean value into an other object.
|
|
||||||
/// Can be used to convert true/false to visibility, a couple of colors, couple of images, etc.
|
|
||||||
/// </summary>
|
|
||||||
public class BoolToObjectConverter : DependencyObject, IValueConverter
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Identifies the <see cref="TrueValue"/> property.
|
|
||||||
/// </summary>
|
|
||||||
public static readonly DependencyProperty TrueValueProperty = Property<BoolToObjectConverter>.Depend<object>(nameof(TrueValue));
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Identifies the <see cref="FalseValue"/> property.
|
|
||||||
/// </summary>
|
|
||||||
public static readonly DependencyProperty FalseValueProperty = Property<BoolToObjectConverter>.Depend<object>(nameof(FalseValue));
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the value to be returned when the boolean is true
|
|
||||||
/// </summary>
|
|
||||||
public object TrueValue
|
|
||||||
{
|
|
||||||
get => GetValue(TrueValueProperty);
|
|
||||||
set => SetValue(TrueValueProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the value to be returned when the boolean is false
|
|
||||||
/// </summary>
|
|
||||||
public object FalseValue
|
|
||||||
{
|
|
||||||
get => GetValue(FalseValueProperty);
|
|
||||||
set => SetValue(FalseValueProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Convert a boolean value to an other object.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="value">The source data being passed to the target.</param>
|
|
||||||
/// <param name="targetType">The type of the target property, as a type reference.</param>
|
|
||||||
/// <param name="parameter">An optional parameter to be used to invert the converter logic.</param>
|
|
||||||
/// <param name="language">The language of the conversion.</param>
|
|
||||||
/// <returns>The value to be passed to the target dependency property.</returns>
|
|
||||||
public object Convert(object value, Type targetType, object parameter, string language)
|
|
||||||
{
|
|
||||||
bool boolValue = value is bool valid && valid;
|
|
||||||
|
|
||||||
// Negate if needed
|
|
||||||
if (ConvertHelper.TryParseBool(parameter))
|
|
||||||
{
|
|
||||||
boolValue = !boolValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ConvertHelper.Convert(boolValue ? TrueValue : FalseValue, targetType);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Convert back the value to a boolean
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>If the <paramref name="value"/> parameter is a reference type, <see cref="TrueValue"/> must match its reference to return true.</remarks>
|
|
||||||
/// <param name="value">The target data being passed to the source.</param>
|
|
||||||
/// <param name="targetType">The type of the target property, as a type reference (System.Type for Microsoft .NET, a TypeName helper struct for Visual C++ component extensions (C++/CX)).</param>
|
|
||||||
/// <param name="parameter">An optional parameter to be used to invert the converter logic.</param>
|
|
||||||
/// <param name="language">The language of the conversion.</param>
|
|
||||||
/// <returns>The value to be passed to the source object.</returns>
|
|
||||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
|
||||||
{
|
|
||||||
bool result = Equals(value, ConvertHelper.Convert(TrueValue, value.GetType()));
|
|
||||||
|
|
||||||
if (ConvertHelper.TryParseBool(parameter))
|
|
||||||
{
|
|
||||||
result = !result;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
// Copyright (c) DGP Studio. All rights reserved.
|
|
||||||
// Licensed under the MIT license.
|
|
||||||
|
|
||||||
using Microsoft.UI.Xaml;
|
|
||||||
|
|
||||||
namespace Snap.Hutao.View.Converter;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This class converts a boolean value into a Visibility enumeration.
|
|
||||||
/// </summary>
|
|
||||||
public class BoolToVisibilityConverter : BoolToObjectConverter
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="BoolToVisibilityConverter"/> class.
|
|
||||||
/// </summary>
|
|
||||||
public BoolToVisibilityConverter()
|
|
||||||
{
|
|
||||||
TrueValue = Visibility.Visible;
|
|
||||||
FalseValue = Visibility.Collapsed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) DGP Studio. All rights reserved.
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
// Licensed under the MIT license.
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
using CommunityToolkit.WinUI.UI.Converters;
|
||||||
using Microsoft.UI.Xaml;
|
using Microsoft.UI.Xaml;
|
||||||
|
|
||||||
namespace Snap.Hutao.View.Converter;
|
namespace Snap.Hutao.View.Converter;
|
||||||
@@ -11,7 +12,7 @@ namespace Snap.Hutao.View.Converter;
|
|||||||
public class BoolToVisibilityRevertConverter : BoolToObjectConverter
|
public class BoolToVisibilityRevertConverter : BoolToObjectConverter
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="BoolToVisibilityConverter"/> class.
|
/// Initializes a new instance of the <see cref="BoolToVisibilityRevertConverter"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public BoolToVisibilityRevertConverter()
|
public BoolToVisibilityRevertConverter()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,17 +6,24 @@
|
|||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:helper="using:Snap.Hutao.View.Helper"
|
xmlns:helper="using:Snap.Hutao.View.Helper"
|
||||||
xmlns:page="using:Snap.Hutao.View.Page"
|
xmlns:page="using:Snap.Hutao.View.Page"
|
||||||
|
xmlns:view="using:Snap.Hutao.View"
|
||||||
mc:Ignorable="d">
|
mc:Ignorable="d">
|
||||||
|
|
||||||
<Grid>
|
<Grid>
|
||||||
|
<!-- x:Bind can't get property update here seems like a WinUI 3 bug-->
|
||||||
<NavigationView
|
<NavigationView
|
||||||
x:Name="NavView"
|
x:Name="NavView"
|
||||||
CompactPaneLength="48"
|
CompactPaneLength="48"
|
||||||
OpenPaneLength="172"
|
OpenPaneLength="200"
|
||||||
CompactModeThresholdWidth="128"
|
CompactModeThresholdWidth="128"
|
||||||
ExpandedModeThresholdWidth="720"
|
ExpandedModeThresholdWidth="720"
|
||||||
IsPaneOpen="True"
|
IsPaneOpen="True"
|
||||||
IsBackEnabled="{Binding ElementName=ContentFrame,Path=CanGoBack}">
|
IsBackEnabled="{Binding ElementName=ContentFrame,Path=CanGoBack}">
|
||||||
<!-- x:Bind can't get property update here seems like a WinUI 3 bug-->
|
|
||||||
|
<NavigationView.PaneCustomContent>
|
||||||
|
<view:UserView IsExpanded="{Binding ElementName=NavView,Path=IsPaneOpen}"/>
|
||||||
|
</NavigationView.PaneCustomContent>
|
||||||
|
|
||||||
<NavigationView.MenuItems>
|
<NavigationView.MenuItems>
|
||||||
|
|
||||||
<NavigationViewItem Content="活动" helper:NavHelper.NavigateTo="page:AnnouncementPage">
|
<NavigationViewItem Content="活动" helper:NavHelper.NavigateTo="page:AnnouncementPage">
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
using Microsoft.UI.Xaml.Navigation;
|
using Microsoft.UI.Xaml.Navigation;
|
||||||
using Microsoft.VisualStudio.Threading;
|
using Microsoft.VisualStudio.Threading;
|
||||||
using Snap.Hutao.Core;
|
using Snap.Hutao.Core;
|
||||||
|
using Snap.Hutao.Service.Abstraction.Navigation;
|
||||||
|
|
||||||
namespace Snap.Hutao.View.Page;
|
namespace Snap.Hutao.View.Page;
|
||||||
|
|
||||||
@@ -33,11 +34,15 @@ openInWebview: function(url){ location.href = url }}";
|
|||||||
protected override void OnNavigatedTo(NavigationEventArgs e)
|
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||||
{
|
{
|
||||||
base.OnNavigatedTo(e);
|
base.OnNavigatedTo(e);
|
||||||
targetContent = e.Parameter as string;
|
|
||||||
LoadAnnouncementAsync().Forget();
|
if (e.Parameter is NavigationExtra extra)
|
||||||
|
{
|
||||||
|
targetContent = extra.Data as string;
|
||||||
|
LoadAnnouncementAsync(extra).Forget();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task LoadAnnouncementAsync()
|
private async Task LoadAnnouncementAsync(NavigationExtra extra)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -52,5 +57,6 @@ openInWebview: function(url){ location.href = url }}";
|
|||||||
}
|
}
|
||||||
|
|
||||||
WebView.NavigateToString(targetContent);
|
WebView.NavigateToString(targetContent);
|
||||||
|
extra.NavigationCompletedTaskCompletionSource.TrySetResult();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,16 +4,17 @@
|
|||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:cwui="using:CommunityToolkit.WinUI.UI"
|
xmlns:cwu="using:CommunityToolkit.WinUI.UI"
|
||||||
xmlns:cwua="using:CommunityToolkit.WinUI.UI.Animations"
|
xmlns:cwua="using:CommunityToolkit.WinUI.UI.Animations"
|
||||||
xmlns:cwub="using:CommunityToolkit.WinUI.UI.Behaviors"
|
xmlns:cwub="using:CommunityToolkit.WinUI.UI.Behaviors"
|
||||||
xmlns:cwuc="using:CommunityToolkit.WinUI.UI.Controls"
|
xmlns:cwucont="using:CommunityToolkit.WinUI.UI.Controls"
|
||||||
xmlns:mxic="using:Microsoft.Xaml.Interactions.Core"
|
xmlns:cwuconv="using:CommunityToolkit.WinUI.UI.Converters"
|
||||||
xmlns:mxim="using:Microsoft.Xaml.Interactions.Media"
|
|
||||||
xmlns:mxi="using:Microsoft.Xaml.Interactivity"
|
xmlns:mxi="using:Microsoft.Xaml.Interactivity"
|
||||||
|
xmlns:mxic="using:Microsoft.Xaml.Interactions.Core"
|
||||||
|
xmlns:shca="using:Snap.Hutao.Control.Animation"
|
||||||
xmlns:shcb="using:Snap.Hutao.Control.Behavior"
|
xmlns:shcb="using:Snap.Hutao.Control.Behavior"
|
||||||
xmlns:shcc="using:Snap.Hutao.Control.Cancellable"
|
xmlns:shcc="using:Snap.Hutao.Control.Cancellable"
|
||||||
xmlns:shvc="using:Snap.Hutao.View.Converter" xmlns:shca="using:Snap.Hutao.Control.Animation"
|
xmlns:shvc="using:Snap.Hutao.View.Converter"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||||
|
|
||||||
@@ -23,7 +24,7 @@
|
|||||||
</mxic:EventTriggerBehavior>
|
</mxic:EventTriggerBehavior>
|
||||||
</mxi:Interaction.Behaviors>
|
</mxi:Interaction.Behaviors>
|
||||||
<shcc:CancellablePage.Resources>
|
<shcc:CancellablePage.Resources>
|
||||||
<shvc:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter"/>
|
<cwuconv:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter"/>
|
||||||
<shvc:BoolToVisibilityRevertConverter x:Key="BoolToVisibilityRevertConverter"/>
|
<shvc:BoolToVisibilityRevertConverter x:Key="BoolToVisibilityRevertConverter"/>
|
||||||
</shcc:CancellablePage.Resources>
|
</shcc:CancellablePage.Resources>
|
||||||
<Grid>
|
<Grid>
|
||||||
@@ -35,7 +36,7 @@
|
|||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
ItemsSource="{Binding Announcement.List}"
|
ItemsSource="{Binding Announcement.List}"
|
||||||
Padding="0"
|
Padding="0"
|
||||||
Margin="12,12,0,0">
|
Margin="12,12,0,-12">
|
||||||
<ItemsControl.ItemTemplate>
|
<ItemsControl.ItemTemplate>
|
||||||
<DataTemplate>
|
<DataTemplate>
|
||||||
<StackPanel>
|
<StackPanel>
|
||||||
@@ -43,24 +44,24 @@
|
|||||||
Text="{Binding TypeLabel}"
|
Text="{Binding TypeLabel}"
|
||||||
Margin="0,0,0,12"
|
Margin="0,0,0,12"
|
||||||
Style="{StaticResource TitleTextBlockStyle}"/>
|
Style="{StaticResource TitleTextBlockStyle}"/>
|
||||||
<cwuc:AdaptiveGridView
|
<cwucont:AdaptiveGridView
|
||||||
cwua:ItemsReorderAnimation.Duration="0:0:0.06"
|
cwua:ItemsReorderAnimation.Duration="0:0:0.06"
|
||||||
SelectionMode="None"
|
SelectionMode="None"
|
||||||
DesiredWidth="320"
|
DesiredWidth="320"
|
||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
ItemsSource="{Binding List}"
|
ItemsSource="{Binding List}"
|
||||||
Margin="0,0,0,0">
|
Margin="0,0,0,0">
|
||||||
<cwuc:AdaptiveGridView.ItemContainerStyle>
|
<cwucont:AdaptiveGridView.ItemContainerStyle>
|
||||||
<Style BasedOn="{StaticResource DefaultGridViewItemStyle}" TargetType="GridViewItem">
|
<Style BasedOn="{StaticResource DefaultGridViewItemStyle}" TargetType="GridViewItem">
|
||||||
<Setter Property="Margin" Value="0,0,12,12"/>
|
<Setter Property="Margin" Value="0,0,12,12"/>
|
||||||
</Style>
|
</Style>
|
||||||
</cwuc:AdaptiveGridView.ItemContainerStyle>
|
</cwucont:AdaptiveGridView.ItemContainerStyle>
|
||||||
<cwuc:AdaptiveGridView.ItemTemplate>
|
<cwucont:AdaptiveGridView.ItemTemplate>
|
||||||
<DataTemplate>
|
<DataTemplate>
|
||||||
<Border
|
<Border
|
||||||
CornerRadius="{StaticResource CompatCornerRadius}"
|
CornerRadius="{StaticResource CompatCornerRadius}"
|
||||||
Background="{ThemeResource SystemControlPageBackgroundAltHighBrush}"
|
Background="{ThemeResource SystemControlPageBackgroundAltHighBrush}"
|
||||||
cwui:UIElementExtensions.ClipToBounds="True">
|
cwu:UIElementExtensions.ClipToBounds="True">
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition/>
|
<RowDefinition/>
|
||||||
@@ -68,10 +69,10 @@
|
|||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<!--Image Layer-->
|
<!--Image Layer-->
|
||||||
<Border
|
<Border
|
||||||
cwui:UIElementExtensions.ClipToBounds="True">
|
cwu:UIElementExtensions.ClipToBounds="True">
|
||||||
<Border
|
<Border
|
||||||
VerticalAlignment="Top"
|
VerticalAlignment="Top"
|
||||||
cwui:VisualExtensions.NormalizedCenterPoint="0.5">
|
cwu:VisualExtensions.NormalizedCenterPoint="0.5">
|
||||||
<mxi:Interaction.Behaviors>
|
<mxi:Interaction.Behaviors>
|
||||||
<shcb:AutoHeightBehavior TargetWidth="1080" TargetHeight="390"/>
|
<shcb:AutoHeightBehavior TargetWidth="1080" TargetHeight="390"/>
|
||||||
</mxi:Interaction.Behaviors>
|
</mxi:Interaction.Behaviors>
|
||||||
@@ -111,33 +112,14 @@
|
|||||||
Grid.Row="1"
|
Grid.Row="1"
|
||||||
CornerRadius="{StaticResource CompatCornerRadiusBottom}">
|
CornerRadius="{StaticResource CompatCornerRadiusBottom}">
|
||||||
<StackPanel Margin="4" VerticalAlignment="Bottom">
|
<StackPanel Margin="4" VerticalAlignment="Bottom">
|
||||||
<Grid Margin="4,6,0,0" HorizontalAlignment="Stretch">
|
<TextBlock
|
||||||
<Grid.ColumnDefinitions>
|
Margin="4,6,0,0"
|
||||||
<ColumnDefinition/>
|
HorizontalAlignment="Stretch"
|
||||||
<ColumnDefinition Width="auto"/>
|
Text="{Binding Subtitle}"
|
||||||
</Grid.ColumnDefinitions>
|
Style="{StaticResource SubtitleTextBlockStyle}"
|
||||||
|
TextWrapping="NoWrap"
|
||||||
|
TextTrimming="WordEllipsis"/>
|
||||||
|
|
||||||
<TextBlock
|
|
||||||
Text="{Binding Subtitle}"
|
|
||||||
Style="{StaticResource SubtitleTextBlockStyle}"
|
|
||||||
TextWrapping="NoWrap"
|
|
||||||
TextTrimming="WordEllipsis"/>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
x:Name="OpenAnnouncementButton"
|
|
||||||
Content=""
|
|
||||||
FontFamily="{StaticResource SymbolThemeFontFamily}"
|
|
||||||
HorizontalAlignment="Right"
|
|
||||||
VerticalAlignment="Stretch"
|
|
||||||
Grid.Column="1"
|
|
||||||
Background="Transparent"
|
|
||||||
BorderThickness="0"
|
|
||||||
BorderBrush="{x:Null}"
|
|
||||||
Visibility="Collapsed"
|
|
||||||
Command="{Binding OpenAnnouncementUICommand}"
|
|
||||||
CommandParameter="{Binding Content}"/>
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Text="{Binding Title}"
|
Text="{Binding Title}"
|
||||||
Style="{StaticResource BodyTextBlockStyle}"
|
Style="{StaticResource BodyTextBlockStyle}"
|
||||||
@@ -145,6 +127,7 @@
|
|||||||
TextTrimming="WordEllipsis"
|
TextTrimming="WordEllipsis"
|
||||||
Margin="4,6,0,0"
|
Margin="4,6,0,0"
|
||||||
Opacity="0.6"/>
|
Opacity="0.6"/>
|
||||||
|
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition/>
|
<ColumnDefinition/>
|
||||||
@@ -167,49 +150,26 @@
|
|||||||
Style="{StaticResource CaptionTextBlockStyle}"
|
Style="{StaticResource CaptionTextBlockStyle}"
|
||||||
Text="{Binding TimeDescription}" />
|
Text="{Binding TimeDescription}" />
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Border>
|
</Border>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Border.Resources>
|
|
||||||
<Storyboard x:Name="OpenAnnouncementButtonVisibleStoryboard">
|
|
||||||
<ObjectAnimationUsingKeyFrames
|
|
||||||
Storyboard.TargetName="OpenAnnouncementButton"
|
|
||||||
Storyboard.TargetProperty="Visibility">
|
|
||||||
<DiscreteObjectKeyFrame KeyTime="0">
|
|
||||||
<DiscreteObjectKeyFrame.Value>
|
|
||||||
<Visibility>Visible</Visibility>
|
|
||||||
</DiscreteObjectKeyFrame.Value>
|
|
||||||
</DiscreteObjectKeyFrame>
|
|
||||||
</ObjectAnimationUsingKeyFrames>
|
|
||||||
</Storyboard>
|
|
||||||
|
|
||||||
<Storyboard x:Name="OpenAnnouncementButtonCollapsedStoryboard">
|
|
||||||
<ObjectAnimationUsingKeyFrames
|
|
||||||
Storyboard.TargetName="OpenAnnouncementButton"
|
|
||||||
Storyboard.TargetProperty="Visibility">
|
|
||||||
<DiscreteObjectKeyFrame KeyTime="0">
|
|
||||||
<DiscreteObjectKeyFrame.Value>
|
|
||||||
<Visibility>Collapsed</Visibility>
|
|
||||||
</DiscreteObjectKeyFrame.Value>
|
|
||||||
</DiscreteObjectKeyFrame>
|
|
||||||
</ObjectAnimationUsingKeyFrames>
|
|
||||||
</Storyboard>
|
|
||||||
</Border.Resources>
|
|
||||||
<mxi:Interaction.Behaviors>
|
<mxi:Interaction.Behaviors>
|
||||||
|
<mxic:EventTriggerBehavior EventName="Tapped">
|
||||||
|
<mxic:InvokeCommandAction
|
||||||
|
Command="{Binding OpenAnnouncementUICommand}"
|
||||||
|
CommandParameter="{Binding Content}"/>
|
||||||
|
</mxic:EventTriggerBehavior>
|
||||||
<mxic:EventTriggerBehavior EventName="PointerEntered">
|
<mxic:EventTriggerBehavior EventName="PointerEntered">
|
||||||
<cwub:StartAnimationAction Animation="{Binding ElementName=ImageZoomInAnimation}" />
|
<cwub:StartAnimationAction Animation="{Binding ElementName=ImageZoomInAnimation}" />
|
||||||
<mxim:ControlStoryboardAction Storyboard="{StaticResource OpenAnnouncementButtonVisibleStoryboard}"/>
|
|
||||||
</mxic:EventTriggerBehavior>
|
</mxic:EventTriggerBehavior>
|
||||||
<mxic:EventTriggerBehavior EventName="PointerExited">
|
<mxic:EventTriggerBehavior EventName="PointerExited">
|
||||||
<cwub:StartAnimationAction Animation="{Binding ElementName=ImageZoomOutAnimation}" />
|
<cwub:StartAnimationAction Animation="{Binding ElementName=ImageZoomOutAnimation}" />
|
||||||
<mxim:ControlStoryboardAction Storyboard="{StaticResource OpenAnnouncementButtonCollapsedStoryboard}"/>
|
|
||||||
</mxic:EventTriggerBehavior>
|
</mxic:EventTriggerBehavior>
|
||||||
</mxi:Interaction.Behaviors>
|
</mxi:Interaction.Behaviors>
|
||||||
</Border>
|
</Border>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</cwuc:AdaptiveGridView.ItemTemplate>
|
</cwucont:AdaptiveGridView.ItemTemplate>
|
||||||
</cwuc:AdaptiveGridView>
|
</cwucont:AdaptiveGridView>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ItemsControl.ItemTemplate>
|
</ItemsControl.ItemTemplate>
|
||||||
|
|||||||
18
src/Snap.Hutao/Snap.Hutao/View/TitleView.xaml
Normal file
18
src/Snap.Hutao/Snap.Hutao/View/TitleView.xaml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<UserControl
|
||||||
|
x:Class="Snap.Hutao.View.TitleView"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:local="using:Snap.Hutao.View"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
Height="48.8">
|
||||||
|
<Grid x:Name="DragableGrid">
|
||||||
|
<TextBlock
|
||||||
|
Text="胡桃"
|
||||||
|
TextWrapping="NoWrap"
|
||||||
|
Style="{StaticResource CaptionTextBlockStyle}"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Margin="12,0,0,0"/>
|
||||||
|
</Grid>
|
||||||
|
</UserControl>
|
||||||
29
src/Snap.Hutao/Snap.Hutao/View/TitleView.xaml.cs
Normal file
29
src/Snap.Hutao/Snap.Hutao/View/TitleView.xaml.cs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
using Microsoft.UI.Xaml;
|
||||||
|
using Microsoft.UI.Xaml.Controls;
|
||||||
|
|
||||||
|
namespace Snap.Hutao.View;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 标题视图
|
||||||
|
/// </summary>
|
||||||
|
public sealed partial class TitleView : UserControl
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 构造一个新的标题视图
|
||||||
|
/// </summary>
|
||||||
|
public TitleView()
|
||||||
|
{
|
||||||
|
this.InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取可拖动区域
|
||||||
|
/// </summary>
|
||||||
|
public UIElement DragableArea
|
||||||
|
{
|
||||||
|
get => DragableGrid;
|
||||||
|
}
|
||||||
|
}
|
||||||
74
src/Snap.Hutao/Snap.Hutao/View/UserView.xaml
Normal file
74
src/Snap.Hutao/Snap.Hutao/View/UserView.xaml
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
<UserControl
|
||||||
|
x:Class="Snap.Hutao.View.UserView"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:local="using:Snap.Hutao.View"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
mc:Ignorable="d">
|
||||||
|
<Grid Height="48">
|
||||||
|
<Grid Height="48">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="auto"/>
|
||||||
|
<ColumnDefinition/>
|
||||||
|
<ColumnDefinition Width="auto"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<PersonPicture
|
||||||
|
ProfilePicture="https://upload-bbs.mihoyo.com/game_record/genshin/character_icon/UI_AvatarIcon_Hutao.png"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
Margin="4,0,4,0"
|
||||||
|
Height="40"
|
||||||
|
Initials="LB"/>
|
||||||
|
<TextBlock
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Margin="0,0,0,2"
|
||||||
|
Grid.Column="1"
|
||||||
|
Text="胡桃胡桃胡桃胡桃胡桃胡桃"
|
||||||
|
TextTrimming="CharacterEllipsis"/>
|
||||||
|
<Button
|
||||||
|
Background="Transparent"
|
||||||
|
BorderBrush="{x:Null}"
|
||||||
|
Height="38.4"
|
||||||
|
Content=""
|
||||||
|
FontFamily="{StaticResource SymbolThemeFontFamily}"
|
||||||
|
Grid.Column="2"
|
||||||
|
Margin="4">
|
||||||
|
<Button.Flyout>
|
||||||
|
<Flyout
|
||||||
|
Placement="BottomEdgeAlignedRight"
|
||||||
|
LightDismissOverlayMode="On">
|
||||||
|
<Flyout.FlyoutPresenterStyle>
|
||||||
|
<Style
|
||||||
|
TargetType="FlyoutPresenter"
|
||||||
|
BasedOn="{StaticResource DefaultFlyoutPresenterStyle}">
|
||||||
|
<Setter Property="Padding" Value="0,2,0,2"/>
|
||||||
|
</Style>
|
||||||
|
</Flyout.FlyoutPresenterStyle>
|
||||||
|
<StackPanel Width="192">
|
||||||
|
<CommandBar DefaultLabelPosition="Right">
|
||||||
|
<AppBarButton Icon="Add" Label="添加新用户"/>
|
||||||
|
</CommandBar>
|
||||||
|
<ListView
|
||||||
|
Grid.Row="1"
|
||||||
|
Margin="4"
|
||||||
|
CanReorderItems="True">
|
||||||
|
<ListViewItem Content="角色1"/>
|
||||||
|
<ListViewItem Content="角色2"/>
|
||||||
|
</ListView>
|
||||||
|
<MenuFlyoutSeparator/>
|
||||||
|
<ListView
|
||||||
|
Grid.Row="1"
|
||||||
|
Margin="4"
|
||||||
|
CanReorderItems="True">
|
||||||
|
<ListViewItem Content="用户1"/>
|
||||||
|
<ListViewItem Content="用户2"/>
|
||||||
|
<ListViewItem Content="用户3"/>
|
||||||
|
<ListViewItem Content="用户4"/>
|
||||||
|
</ListView>
|
||||||
|
</StackPanel>
|
||||||
|
</Flyout>
|
||||||
|
</Button.Flyout>
|
||||||
|
</Button>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</UserControl>
|
||||||
33
src/Snap.Hutao/Snap.Hutao/View/UserView.xaml.cs
Normal file
33
src/Snap.Hutao/Snap.Hutao/View/UserView.xaml.cs
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
using Microsoft.UI.Xaml;
|
||||||
|
using Microsoft.UI.Xaml.Controls;
|
||||||
|
using Snap.Hutao.Core;
|
||||||
|
|
||||||
|
namespace Snap.Hutao.View;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 用户视图
|
||||||
|
/// </summary>
|
||||||
|
public sealed partial class UserView : UserControl
|
||||||
|
{
|
||||||
|
private static readonly DependencyProperty IsExpandedProperty = Property<UserView>.Depend(nameof(IsExpanded), true);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 构造一个新的用户视图
|
||||||
|
/// </summary>
|
||||||
|
public UserView()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 当前用户控件是否处于展开状态
|
||||||
|
/// </summary>
|
||||||
|
public bool IsExpanded
|
||||||
|
{
|
||||||
|
get => (bool)GetValue(IsExpandedProperty);
|
||||||
|
set => SetValue(IsExpandedProperty, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -89,18 +89,18 @@ internal class AnnouncementViewModel : ObservableObject, ISupportCancellation
|
|||||||
}
|
}
|
||||||
catch (TaskCanceledException)
|
catch (TaskCanceledException)
|
||||||
{
|
{
|
||||||
logger.LogInformation("Open UI cancelled");
|
logger.LogInformation($"{nameof(OpenUIAsync)} cancelled");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OpenAnnouncementUI(string? content)
|
private void OpenAnnouncementUI(string? content)
|
||||||
{
|
{
|
||||||
logger.LogInformation("Open Announcement Command Triggered");
|
logger.LogInformation($"{nameof(OpenAnnouncementUICommand)} Triggered");
|
||||||
|
|
||||||
if (WebView2Helper.IsSupported)
|
if (WebView2Helper.IsSupported)
|
||||||
{
|
{
|
||||||
navigationService.Navigate<View.Page.AnnouncementContentPage>(data: content);
|
navigationService.Navigate<View.Page.AnnouncementContentPage>(data: new(content));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
// Copyright (c) DGP Studio. All rights reserved.
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
// Licensed under the MIT license.
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
using Snap.Hutao.Core.Json.Converter;
|
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
|
|
||||||
@@ -124,15 +123,15 @@ public class Announcement : AnnouncementContent
|
|||||||
/// 开始时间
|
/// 开始时间
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonPropertyName("start_time")]
|
[JsonPropertyName("start_time")]
|
||||||
[JsonConverter(typeof(DateTimeConverter))]
|
[JsonConverter(typeof(Core.Json.Converter.DateTimeOffsetConverter))]
|
||||||
public DateTime StartTime { get; set; }
|
public DateTimeOffset StartTime { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 结束时间
|
/// 结束时间
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonPropertyName("end_time")]
|
[JsonPropertyName("end_time")]
|
||||||
[JsonConverter(typeof(DateTimeConverter))]
|
[JsonConverter(typeof(Core.Json.Converter.DateTimeOffsetConverter))]
|
||||||
public DateTime EndTime { get; set; }
|
public DateTimeOffset EndTime { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 类型
|
/// 类型
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace Snap.Hutao.Web.Hutao;
|
|||||||
/// 胡桃API客户端
|
/// 胡桃API客户端
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Injection(InjectAs.Transient)]
|
[Injection(InjectAs.Transient)]
|
||||||
internal class HutaoClient : IAsyncInitializable
|
internal class HutaoClient : ISupportAsyncInitialization
|
||||||
{
|
{
|
||||||
private const string AuthAPIHost = "https://auth.snapgenshin.com";
|
private const string AuthAPIHost = "https://auth.snapgenshin.com";
|
||||||
private const string HutaoAPI = "https://hutao-api.snapgenshin.com";
|
private const string HutaoAPI = "https://hutao-api.snapgenshin.com";
|
||||||
@@ -342,7 +342,7 @@ internal class HutaoClient : IAsyncInitializable
|
|||||||
await playerRecord.UploadRecordAsync(this, token);
|
await playerRecord.UploadRecordAsync(this, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
await resultAsyncFunc(resp ?? Response.Response.CreateForException($"{role.GameUid}-记录提交失败。"));
|
// await resultAsyncFunc(resp ?? Response.Response.CreateForException($"{role.GameUid}-记录提交失败。"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
// Copyright (c) DGP Studio. All rights reserved.
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
// Licensed under the MIT license.
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
using Snap.Hutao.Core.Abstraction;
|
||||||
|
using Snap.Hutao.Service.Abstraction;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
namespace Snap.Hutao.Web.Response;
|
namespace Snap.Hutao.Web.Response;
|
||||||
@@ -8,8 +10,27 @@ namespace Snap.Hutao.Web.Response;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 提供 <see cref="Response{T}"/> 的非泛型基类
|
/// 提供 <see cref="Response{T}"/> 的非泛型基类
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Response
|
public class Response : ISupportValidation
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 构造一个新的响应
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="returnCode">返回代码</param>
|
||||||
|
/// <param name="message">消息</param>
|
||||||
|
[JsonConstructor]
|
||||||
|
public Response(int returnCode, string message)
|
||||||
|
{
|
||||||
|
ReturnCode = returnCode;
|
||||||
|
Message = message;
|
||||||
|
|
||||||
|
if (!Validate())
|
||||||
|
{
|
||||||
|
Ioc.Default
|
||||||
|
.GetRequiredService<IInfoBarService>()
|
||||||
|
.Information(ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 返回代码
|
/// 返回代码
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -32,18 +53,10 @@ public class Response
|
|||||||
return response is not null && response.ReturnCode == 0;
|
return response is not null && response.ReturnCode == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <inheritdoc/>
|
||||||
/// 构造一个失败的响应
|
public bool Validate()
|
||||||
/// </summary>
|
|
||||||
/// <param name="message">消息</param>
|
|
||||||
/// <returns>响应</returns>
|
|
||||||
public static Response CreateForException(string message)
|
|
||||||
{
|
{
|
||||||
return new Response()
|
return Enum.IsDefined(typeof(KnownReturnCode), ReturnCode);
|
||||||
{
|
|
||||||
ReturnCode = (int)KnownReturnCode.InternalFailure,
|
|
||||||
Message = message,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
|
|||||||
@@ -11,50 +11,21 @@ namespace Snap.Hutao.Web.Response;
|
|||||||
/// <typeparam name="TData">数据类型</typeparam>
|
/// <typeparam name="TData">数据类型</typeparam>
|
||||||
public class Response<TData> : Response
|
public class Response<TData> : Response
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 构造一个新的 Mihoyo 标准API响应
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="returnCode">返回代码</param>
|
||||||
|
/// <param name="message">消息</param>
|
||||||
|
/// <param name="data">数据</param>
|
||||||
|
public Response(int returnCode, string message, TData? data)
|
||||||
|
: base(returnCode, message)
|
||||||
|
{
|
||||||
|
Data = data;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 数据
|
/// 数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonPropertyName("data")]
|
[JsonPropertyName("data")]
|
||||||
public TData? Data { get; set; }
|
public TData? Data { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 构造一个失败的响应
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="message">消息</param>
|
|
||||||
/// <returns>响应</returns>
|
|
||||||
public static new Response<TData> CreateForException(string message)
|
|
||||||
{
|
|
||||||
return new Response<TData>()
|
|
||||||
{
|
|
||||||
ReturnCode = (int)KnownReturnCode.InternalFailure,
|
|
||||||
Message = message,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 构造一个失败的响应
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="message">消息</param>
|
|
||||||
/// <returns>响应</returns>
|
|
||||||
public static Response<TData> CreateForJsonException(string message)
|
|
||||||
{
|
|
||||||
return new Response<TData>()
|
|
||||||
{
|
|
||||||
ReturnCode = (int)KnownReturnCode.InternalFailure,
|
|
||||||
Message = message,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 构造一个空Url的响应
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>响应</returns>
|
|
||||||
public static Response<TData> CreateForEmptyUrl()
|
|
||||||
{
|
|
||||||
return new Response<TData>()
|
|
||||||
{
|
|
||||||
ReturnCode = (int)KnownReturnCode.UrlIsEmpty,
|
|
||||||
Message = "请求的 Url 不应为空",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user