diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Abstraction/IAsyncInitializable.cs b/src/Snap.Hutao/Snap.Hutao/Core/Abstraction/IAsyncInitializable.cs
index a1e36db2..9057fb34 100644
--- a/src/Snap.Hutao/Snap.Hutao/Core/Abstraction/IAsyncInitializable.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Core/Abstraction/IAsyncInitializable.cs
@@ -19,4 +19,4 @@ internal interface IAsyncInitializable
/// 取消令牌
/// 初始化任务
Task InitializeAsync(CancellationToken cancellationToken = default);
-}
+}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Extension/TupleExtensions.cs b/src/Snap.Hutao/Snap.Hutao/Extension/TupleExtensions.cs
index dbf36b24..ae8d4066 100644
--- a/src/Snap.Hutao/Snap.Hutao/Extension/TupleExtensions.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Extension/TupleExtensions.cs
@@ -2,8 +2,6 @@
// Licensed under the MIT license.
using System.Collections.Generic;
-using System.Net.Http;
-using System.Net.Http.Headers;
namespace Snap.Hutao.Extension;
diff --git a/src/Snap.Hutao/Snap.Hutao/IocConfiguration.cs b/src/Snap.Hutao/Snap.Hutao/IocConfiguration.cs
index 54f7000a..7f07aa67 100644
--- a/src/Snap.Hutao/Snap.Hutao/IocConfiguration.cs
+++ b/src/Snap.Hutao/Snap.Hutao/IocConfiguration.cs
@@ -6,7 +6,6 @@ using Microsoft.Extensions.DependencyInjection;
using Snap.Hutao.Context.Database;
using Snap.Hutao.Context.FileSystem;
using Snap.Hutao.Core;
-using Snap.Hutao.Core.Json;
using Snap.Hutao.Core.Setting;
using System.Text.Json;
using System.Text.Json.Serialization;
diff --git a/src/Snap.Hutao/Snap.Hutao/Program.cs b/src/Snap.Hutao/Snap.Hutao/Program.cs
new file mode 100644
index 00000000..2041d2c5
--- /dev/null
+++ b/src/Snap.Hutao/Snap.Hutao/Program.cs
@@ -0,0 +1,32 @@
+// Copyright (c) DGP Studio. All rights reserved.
+// Licensed under the MIT license.
+
+using Microsoft.UI.Dispatching;
+using Microsoft.UI.Xaml;
+using System.Runtime.InteropServices;
+using WinRT;
+
+namespace Snap.Hutao;
+
+///
+/// Program class
+///
+public static class Program
+{
+ [DllImport("Microsoft.ui.xaml.dll")]
+ private static extern void XamlCheckProcessRequirements();
+
+ [STAThread]
+ private static void Main(string[] args)
+ {
+ XamlCheckProcessRequirements();
+
+ ComWrappersSupport.InitializeComWrappers();
+ Application.Start((p) =>
+ {
+ DispatcherQueueSynchronizationContext context = new(DispatcherQueue.GetForCurrentThread());
+ SynchronizationContext.SetSynchronizationContext(context);
+ _ = new App();
+ });
+ }
+}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Abstraction/IUserService.cs b/src/Snap.Hutao/Snap.Hutao/Service/Abstraction/IUserService.cs
index 413512bc..abee8da9 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/Abstraction/IUserService.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/Abstraction/IUserService.cs
@@ -13,5 +13,5 @@ public interface IUserService
///
/// 获取当前用户信息
///
- User CurrentUser { get; }
+ User Current { get; }
}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Abstraction/INavigationService.cs b/src/Snap.Hutao/Snap.Hutao/Service/Abstraction/Navigation/INavigationService.cs
similarity index 71%
rename from src/Snap.Hutao/Snap.Hutao/Service/Abstraction/INavigationService.cs
rename to src/Snap.Hutao/Snap.Hutao/Service/Abstraction/Navigation/INavigationService.cs
index b21c8509..39ea31ae 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/Abstraction/INavigationService.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/Abstraction/Navigation/INavigationService.cs
@@ -3,7 +3,7 @@
using Microsoft.UI.Xaml.Controls;
-namespace Snap.Hutao.Service.Abstraction;
+namespace Snap.Hutao.Service.Abstraction.Navigation;
///
/// 导航服务
@@ -44,7 +44,7 @@ public interface INavigationService
/// 是否同步标签,当在代码中调用时应设为 true
/// 要传递的数据
/// 是否导航成功
- bool Navigate(Type? pageType, bool isSyncTabRequested = false, object? data = null);
+ NavigationResult Navigate(Type pageType, bool isSyncTabRequested = false, NavigationExtra? data = null);
///
/// 导航到指定类型的页面
@@ -53,13 +53,23 @@ public interface INavigationService
/// 是否同步标签,当在代码中调用时应设为 true
/// 要传递的数据
/// 是否导航成功
- bool Navigate(bool isSyncTabRequested = false, object? data = null)
+ NavigationResult Navigate(bool isSyncTabRequested = false, NavigationExtra? data = null)
where T : Page;
+ ///
+ /// 异步的导航到指定类型的页面
+ ///
+ /// 指定的页面类型
+ /// 是否同步标签,当在代码中调用时应设为 true
+ /// 要传递的数据
+ /// 是否导航成功
+ Task NavigateAsync(bool syncNavigationViewItem = false, NavigationExtra? data = null)
+ where TPage : Page;
+
///
/// 同步导航标签
///
/// 同步的页面类型
/// 是否同步成功
bool SyncSelectedNavigationViewItemWith(Type pageType);
-}
\ No newline at end of file
+}
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Abstraction/Navigation/NavigationExtra.cs b/src/Snap.Hutao/Snap.Hutao/Service/Abstraction/Navigation/NavigationExtra.cs
new file mode 100644
index 00000000..47067c0f
--- /dev/null
+++ b/src/Snap.Hutao/Snap.Hutao/Service/Abstraction/Navigation/NavigationExtra.cs
@@ -0,0 +1,29 @@
+// Copyright (c) DGP Studio. All rights reserved.
+// Licensed under the MIT license.
+
+namespace Snap.Hutao.Service.Abstraction.Navigation;
+
+///
+/// 导航额外信息
+///
+public class NavigationExtra
+{
+ ///
+ /// 构造一个新的导航额外信息
+ ///
+ /// 数据
+ public NavigationExtra(object? data = null)
+ {
+ Data = data;
+ }
+
+ ///
+ /// 数据
+ ///
+ public object? Data { get; set; }
+
+ ///
+ /// 任务完成源
+ ///
+ public TaskCompletionSource NavigationCompletedTaskCompletionSource { get; } = new();
+}
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Abstraction/Navigation/NavigationResult.cs b/src/Snap.Hutao/Snap.Hutao/Service/Abstraction/Navigation/NavigationResult.cs
new file mode 100644
index 00000000..0f6e36bc
--- /dev/null
+++ b/src/Snap.Hutao/Snap.Hutao/Service/Abstraction/Navigation/NavigationResult.cs
@@ -0,0 +1,25 @@
+// Copyright (c) DGP Studio. All rights reserved.
+// Licensed under the MIT license.
+
+namespace Snap.Hutao.Service.Abstraction.Navigation;
+
+///
+/// 导航结果
+///
+public enum NavigationResult
+{
+ ///
+ /// 成功
+ ///
+ Succeed,
+
+ ///
+ /// 失败
+ ///
+ Failed,
+
+ ///
+ /// 已经处于该页面
+ ///
+ AlreadyNavigatedTo,
+}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/AnnouncementService.cs b/src/Snap.Hutao/Snap.Hutao/Service/AnnouncementService.cs
index a70caf9e..ae6f718a 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/AnnouncementService.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/AnnouncementService.cs
@@ -14,44 +14,46 @@ namespace Snap.Hutao.Service;
[Injection(InjectAs.Transient, typeof(IAnnouncementService))]
internal class AnnouncementService : IAnnouncementService
{
- private readonly AnnouncementClient announcementProvider;
+ private readonly AnnouncementClient announcementClient;
///
/// 构造一个新的公告服务
///
- /// 公告提供器
- public AnnouncementService(AnnouncementClient announcementProvider)
+ /// 公告提供器
+ public AnnouncementService(AnnouncementClient announcementClient)
{
- this.announcementProvider = announcementProvider;
+ this.announcementClient = announcementClient;
}
///
public async Task GetAnnouncementsAsync(ICommand openAnnouncementUICommand, CancellationToken cancellationToken = default)
{
- AnnouncementWrapper? wrapper = await announcementProvider.GetAnnouncementsAsync(cancellationToken);
- List contents = await announcementProvider.GetAnnouncementContentsAsync(cancellationToken);
+ AnnouncementWrapper? wrapper = await announcementClient
+ .GetAnnouncementsAsync(cancellationToken)
+ .ConfigureAwait(false);
+ List contents = await announcementClient
+ .GetAnnouncementContentsAsync(cancellationToken)
+ .ConfigureAwait(false);
- Dictionary contentMap = contents
+ Dictionary contentMap = contents
.ToDictionary(id => id.AnnId, content => content.Content);
- if (wrapper?.List is List announcementListWrappers)
- {
- // 将活动公告置于上方
- announcementListWrappers.Reverse();
+ Must.NotNull(wrapper!);
- // 将公告内容联入公告列表
- JoinAnnouncements(openAnnouncementUICommand, contentMap, announcementListWrappers);
+ // 将活动公告置于上方
+ wrapper.List.Reverse();
- return wrapper;
- }
+ // 将公告内容联入公告列表
+ JoinAnnouncements(openAnnouncementUICommand, contentMap, wrapper.List);
- return new();
+ return wrapper;
}
- private void JoinAnnouncements(ICommand openAnnouncementUICommand, Dictionary contentMap, List announcementListWrappers)
+ private static void JoinAnnouncements(ICommand openAnnouncementUICommand, Dictionary contentMap, List announcementListWrappers)
{
// 匹配特殊的时间格式: (.*?)
Regex timeTagRegrex = new("<t.*?>(.*?)</t>", RegexOptions.Multiline);
+
Regex timeTagInnerRegex = new("(?<=<t.*?>)(.*?)(?=</t>)");
announcementListWrappers.ForEach(listWrapper =>
@@ -64,7 +66,7 @@ internal class AnnouncementService : IAnnouncementService
rawContent = timeTagRegrex.Replace(rawContent!, x => timeTagInnerRegex.Match(x.Value).Value);
}
- item.Content = rawContent;
+ item.Content = rawContent ?? string.Empty;
item.OpenAnnouncementUICommand = openAnnouncementUICommand;
});
});
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/NavigationService.cs b/src/Snap.Hutao/Snap.Hutao/Service/NavigationService.cs
index 4bbf8e05..172ae527 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/NavigationService.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/NavigationService.cs
@@ -1,11 +1,9 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
-using Microsoft.AppCenter.Analytics;
using Microsoft.UI.Xaml.Controls;
using Snap.Hutao.Core.Logging;
-using Snap.Hutao.Extension;
-using Snap.Hutao.Service.Abstraction;
+using Snap.Hutao.Service.Abstraction.Navigation;
using Snap.Hutao.View.Helper;
using Snap.Hutao.View.Page;
using System.Linq;
@@ -82,6 +80,7 @@ internal class NavigationService : INavigationService
NavigationViewItem? target = NavigationView.MenuItems
.OfType()
.SingleOrDefault(menuItem => NavHelper.GetNavigateTo(menuItem) == pageType);
+
NavigationView.SelectedItem = target;
}
@@ -90,44 +89,59 @@ internal class NavigationService : INavigationService
}
///
- public bool Navigate(Type? pageType, bool isSyncTabRequested = false, object? data = null)
+ public NavigationResult Navigate(Type pageType, bool syncNavigationViewItem = false, NavigationExtra? data = null)
{
Type? currentType = Frame?.Content?.GetType();
- if (pageType is null || (currentType == pageType))
+
+ if (currentType == pageType)
{
- return false;
+ return NavigationResult.AlreadyNavigatedTo;
}
- _ = isSyncTabRequested && SyncSelectedNavigationViewItemWith(pageType);
+ _ = syncNavigationViewItem && SyncSelectedNavigationViewItemWith(pageType);
- bool result = false;
+ bool navigated = false;
try
{
- result = Frame?.Navigate(pageType, data) ?? false;
+ if (data != null && data.GetType() != typeof(NavigationExtra))
+ {
+ data = new NavigationExtra(data);
+ }
+
+ navigated = Frame?.Navigate(pageType, data) ?? false;
}
catch (Exception ex)
{
logger.LogError(EventIds.NavigationFailed, ex, "导航到指定页面时发生了错误");
}
- logger.LogInformation("Navigate to {pageType}:{result}", pageType, result ? "succeed" : "failed");
-
- // 分析页面统计数据时不应加入启动时导航的首个页面
- if (HasEverNavigated)
- {
- Analytics.TrackEvent("General", ("OpenUI", pageType.ToString()).AsDictionary());
- }
+ logger.LogInformation("Navigate to {pageType}:{result}", pageType, navigated ? "succeed" : "failed");
// 首次导航失败时使属性持续保存为false
- HasEverNavigated = HasEverNavigated || result;
- return result;
+ HasEverNavigated = HasEverNavigated || navigated;
+ return navigated ? NavigationResult.Succeed : NavigationResult.Failed;
}
///
- public bool Navigate(bool isSyncTabRequested = false, object? data = null)
- where T : Page
+ public NavigationResult Navigate(bool syncNavigationViewItem = false, NavigationExtra? data = null)
+ where TPage : Page
{
- return Navigate(typeof(T), isSyncTabRequested, data);
+ return Navigate(typeof(TPage), syncNavigationViewItem, data);
+ }
+
+ ///
+ public async Task NavigateAsync(bool syncNavigationViewItem = false, NavigationExtra? data = null)
+ where TPage : Page
+ {
+ data ??= new NavigationExtra();
+ NavigationResult result = Navigate(syncNavigationViewItem, data);
+
+ if (result is NavigationResult.Succeed)
+ {
+ await data.NavigationCompletedTaskCompletionSource.Task;
+ }
+
+ return result;
}
///
@@ -143,7 +157,8 @@ internal class NavigationService : INavigationService
Type? targetType = args.IsSettingsInvoked
? typeof(SettingPage)
: NavHelper.GetNavigateTo(Selected);
- Navigate(targetType, false, NavHelper.GetExtraData(Selected));
+
+ Navigate(Must.NotNull(targetType!), false, new(NavHelper.GetExtraData(Selected)));
}
private void OnBackRequested(NavigationView sender, NavigationViewBackRequestedEventArgs args)
@@ -154,4 +169,4 @@ internal class NavigationService : INavigationService
SyncSelectedNavigationViewItemWith(Frame.Content.GetType());
}
}
-}
+}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj b/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj
index 7336b6b7..e48e6f2a 100644
--- a/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj
+++ b/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj
@@ -23,6 +23,8 @@
True
Never
0
+ Snap.Hutao.Program
+ DISABLE_XAML_GENERATED_MAIN
@@ -52,7 +54,7 @@
-
+
@@ -60,8 +62,8 @@
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/src/Snap.Hutao/Snap.Hutao/View/Converter/BoolToObjectConverter.cs b/src/Snap.Hutao/Snap.Hutao/View/Converter/BoolToObjectConverter.cs
index 3307a7f9..fae94ca1 100644
--- a/src/Snap.Hutao/Snap.Hutao/View/Converter/BoolToObjectConverter.cs
+++ b/src/Snap.Hutao/Snap.Hutao/View/Converter/BoolToObjectConverter.cs
@@ -3,6 +3,7 @@
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Data;
+using Snap.Hutao.Core;
namespace Snap.Hutao.View.Converter;
@@ -15,14 +16,12 @@ public class BoolToObjectConverter : DependencyObject, IValueConverter
///
/// Identifies the property.
///
- public static readonly DependencyProperty TrueValueProperty =
- DependencyProperty.Register(nameof(TrueValue), typeof(object), typeof(BoolToObjectConverter), new PropertyMetadata(null));
+ public static readonly DependencyProperty TrueValueProperty = Property.Depend