From 67f6fda900f36f91a2580f821dfe9e85e6802331 Mon Sep 17 00:00:00 2001 From: qhy040404 Date: Sun, 26 May 2024 21:53:22 +0800 Subject: [PATCH 01/68] another impl of hint when icon promoted for win10 --- .../Core/Windowing/XamlWindowController.cs | 28 ++++++++++++++++-- src/Snap.Hutao/Snap.Hutao/Win32/User32.cs | 29 +++++++++++++++++++ 2 files changed, 54 insertions(+), 3 deletions(-) diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/XamlWindowController.cs b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/XamlWindowController.cs index 2ebd955f..512b0c69 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/XamlWindowController.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/XamlWindowController.cs @@ -104,9 +104,7 @@ internal sealed class XamlWindowController args.Handled = true; window.Hide(); - RECT iconRect = serviceProvider.GetRequiredService().GetRect(); - RECT primaryRect = StructMarshal.RECT(DisplayArea.Primary.OuterBounds); - if (!IntersectRect(out _, in primaryRect, in iconRect)) + if (!IsNotifyIconVisible()) { new ToastContentBuilder() .AddText(SH.CoreWindowingNotifyIconPromotedHint) @@ -133,6 +131,30 @@ internal sealed class XamlWindowController } } + private unsafe bool IsNotifyIconVisible() + { + RECT iconRect = serviceProvider.GetRequiredService().GetRect(); + + if (UniversalApiContract.IsPresent(WindowsVersion.Windows11)) + { + RECT primaryRect = StructMarshal.RECT(DisplayArea.Primary.OuterBounds); + return IntersectRect(out _, in primaryRect, in iconRect); + } + else + { + HWND shellTrayWnd = FindWindowExW(default, default, "Shell_TrayWnd", default); + HWND trayNotifyWnd = FindWindowExW(shellTrayWnd, default, "TrayNotifyWnd", default); + HWND button = FindWindowExW(trayNotifyWnd, default, "Button", default); + + if (GetWindowRect(button, out RECT buttonRect)) + { + return !EqualRect(in buttonRect, in iconRect); + } + + return false; + } + } + #region SystemBackdrop & ElementTheme private void OnOptionsPropertyChanged(object? sender, PropertyChangedEventArgs e) diff --git a/src/Snap.Hutao/Snap.Hutao/Win32/User32.cs b/src/Snap.Hutao/Snap.Hutao/Win32/User32.cs index 795ab2e1..c6ed2ea7 100644 --- a/src/Snap.Hutao/Snap.Hutao/Win32/User32.cs +++ b/src/Snap.Hutao/Snap.Hutao/Win32/User32.cs @@ -55,6 +55,22 @@ internal static class User32 [SupportedOSPlatform("windows5.0")] public static extern BOOL DestroyWindow(HWND hWnd); + [DllImport("USER32.dll", CallingConvention = CallingConvention.Winapi, ExactSpelling = true)] + [SupportedOSPlatform("windows5.0")] + public static unsafe extern BOOL EqualRect(RECT* lprc1, RECT* lprc2); + + [DebuggerStepThrough] + public static unsafe BOOL EqualRect(in RECT rc1, in RECT rc2) + { + fixed (RECT* lprc1 = &rc1) + { + fixed (RECT* lprc2 = &rc2) + { + return EqualRect(lprc1, lprc2); + } + } + } + [DllImport("USER32.dll", CallingConvention = CallingConvention.Winapi, ExactSpelling = true)] [SupportedOSPlatform("windows5.0")] public static extern HWND FindWindowExW([AllowNull] HWND hWndParent, [AllowNull] HWND hWndChildAfter, [AllowNull] PCWSTR lpszClass, [AllowNull] PCWSTR lpszWindow); @@ -112,6 +128,19 @@ internal static class User32 } } + [DllImport("USER32.dll", CallingConvention = CallingConvention.Winapi, ExactSpelling = true)] + [SupportedOSPlatform("windows5.0")] + public static unsafe extern BOOL GetWindowRect(HWND hWnd, RECT* lpRect); + + [DebuggerStepThrough] + public static unsafe BOOL GetWindowRect(HWND hWnd, out RECT rect) + { + fixed (RECT* lpRect = &rect) + { + return GetWindowRect(hWnd, lpRect); + } + } + [DllImport("USER32.dll", CallingConvention = CallingConvention.Winapi, ExactSpelling = true)] [SupportedOSPlatform("windows5.0")] public static unsafe extern uint GetWindowThreadProcessId(HWND hWnd, [MaybeNull] uint* lpdwProcessId); From 86809609311b73923aafe8e05d9caf316c3429f6 Mon Sep 17 00:00:00 2001 From: qhy040404 Date: Sun, 26 May 2024 22:10:15 +0800 Subject: [PATCH 02/68] clear jumplist --- .../Core/LifeCycle/AppActivation.cs | 1 + .../Snap.Hutao/Core/Shell/IJumpListInterop.cs | 9 ++++++++ .../Snap.Hutao/Core/Shell/JumpListInterop.cs | 22 +++++++++++++++++++ 3 files changed, 32 insertions(+) create mode 100644 src/Snap.Hutao/Snap.Hutao/Core/Shell/IJumpListInterop.cs create mode 100644 src/Snap.Hutao/Snap.Hutao/Core/Shell/JumpListInterop.cs diff --git a/src/Snap.Hutao/Snap.Hutao/Core/LifeCycle/AppActivation.cs b/src/Snap.Hutao/Snap.Hutao/Core/LifeCycle/AppActivation.cs index 2031ed53..8304f4b0 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/LifeCycle/AppActivation.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/LifeCycle/AppActivation.cs @@ -69,6 +69,7 @@ internal sealed partial class AppActivation : IAppActivation, IAppActivationActi using (activateSemaphore.Enter()) { // TODO: Introduced in 1.10.2, remove in later version + serviceProvider.GetRequiredService().ClearAsync().SafeForget(); serviceProvider.GetRequiredService().UnregisterAllTasks(); if (UnsafeLocalSetting.Get(SettingKeys.Major1Minor10Revision0GuideState, GuideState.Language) < GuideState.Completed) diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Shell/IJumpListInterop.cs b/src/Snap.Hutao/Snap.Hutao/Core/Shell/IJumpListInterop.cs new file mode 100644 index 00000000..4750203f --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Core/Shell/IJumpListInterop.cs @@ -0,0 +1,9 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +namespace Snap.Hutao.Core.Shell; + +internal interface IJumpListInterop +{ + ValueTask ClearAsync(); +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Shell/JumpListInterop.cs b/src/Snap.Hutao/Snap.Hutao/Core/Shell/JumpListInterop.cs new file mode 100644 index 00000000..2a52b787 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Core/Shell/JumpListInterop.cs @@ -0,0 +1,22 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +using Windows.UI.StartScreen; + +namespace Snap.Hutao.Core.Shell; + +[Injection(InjectAs.Transient, typeof(IJumpListInterop))] +internal sealed class JumpListInterop : IJumpListInterop +{ + public async ValueTask ClearAsync() + { + if (JumpList.IsSupported()) + { + JumpList list = await JumpList.LoadCurrentAsync(); + + list.Items.Clear(); + + await list.SaveAsync(); + } + } +} \ No newline at end of file From cd91af8ae96c93f8abb742332fbacd456f2c2eca Mon Sep 17 00:00:00 2001 From: qhy040404 Date: Mon, 27 May 2024 09:29:58 +0800 Subject: [PATCH 03/68] use ref readonly --- src/Snap.Hutao/Snap.Hutao/Win32/User32.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Snap.Hutao/Snap.Hutao/Win32/User32.cs b/src/Snap.Hutao/Snap.Hutao/Win32/User32.cs index c6ed2ea7..e09b933a 100644 --- a/src/Snap.Hutao/Snap.Hutao/Win32/User32.cs +++ b/src/Snap.Hutao/Snap.Hutao/Win32/User32.cs @@ -60,7 +60,7 @@ internal static class User32 public static unsafe extern BOOL EqualRect(RECT* lprc1, RECT* lprc2); [DebuggerStepThrough] - public static unsafe BOOL EqualRect(in RECT rc1, in RECT rc2) + public static unsafe BOOL EqualRect(ref readonly RECT rc1, ref readonly RECT rc2) { fixed (RECT* lprc1 = &rc1) { From 9e3ec32ae6234998baee823ac464d9ef4830e3f1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 May 2024 07:57:43 +0000 Subject: [PATCH 04/68] Bump the packages group in /src/Snap.Hutao with 3 updates Bumps the packages group in /src/Snap.Hutao with 3 updates: [Microsoft.NET.Test.Sdk](https://github.com/microsoft/vstest), [MSTest.TestAdapter](https://github.com/microsoft/testfx) and [MSTest.TestFramework](https://github.com/microsoft/testfx). Updates `Microsoft.NET.Test.Sdk` from 17.9.0 to 17.10.0 - [Release notes](https://github.com/microsoft/vstest/releases) - [Changelog](https://github.com/microsoft/vstest/blob/main/docs/releases.md) - [Commits](https://github.com/microsoft/vstest/compare/v17.9.0...v17.10.0) Updates `MSTest.TestAdapter` from 3.3.1 to 3.4.0 - [Release notes](https://github.com/microsoft/testfx/releases) - [Changelog](https://github.com/microsoft/testfx/blob/main/docs/Changelog.md) - [Commits](https://github.com/microsoft/testfx/compare/v3.3.1...v3.4.0) Updates `MSTest.TestFramework` from 3.3.1 to 3.4.0 - [Release notes](https://github.com/microsoft/testfx/releases) - [Changelog](https://github.com/microsoft/testfx/blob/main/docs/Changelog.md) - [Commits](https://github.com/microsoft/testfx/compare/v3.3.1...v3.4.0) --- updated-dependencies: - dependency-name: Microsoft.NET.Test.Sdk dependency-type: direct:production update-type: version-update:semver-minor dependency-group: packages - dependency-name: MSTest.TestAdapter dependency-type: direct:production update-type: version-update:semver-minor dependency-group: packages - dependency-name: MSTest.TestFramework dependency-type: direct:production update-type: version-update:semver-minor dependency-group: packages ... Signed-off-by: dependabot[bot] --- src/Snap.Hutao/Snap.Hutao.Test/Snap.Hutao.Test.csproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Snap.Hutao/Snap.Hutao.Test/Snap.Hutao.Test.csproj b/src/Snap.Hutao/Snap.Hutao.Test/Snap.Hutao.Test.csproj index a8393dff..5d38d90e 100644 --- a/src/Snap.Hutao/Snap.Hutao.Test/Snap.Hutao.Test.csproj +++ b/src/Snap.Hutao/Snap.Hutao.Test/Snap.Hutao.Test.csproj @@ -13,9 +13,9 @@ - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive From 7aa4696ba513d4af0c411bd4ebbe4a1a33560399 Mon Sep 17 00:00:00 2001 From: qhy040404 Date: Mon, 27 May 2024 22:11:38 +0800 Subject: [PATCH 05/68] drop else --- .../Core/Windowing/XamlWindowController.cs | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/XamlWindowController.cs b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/XamlWindowController.cs index 512b0c69..a78cf106 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/XamlWindowController.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/XamlWindowController.cs @@ -140,19 +140,17 @@ internal sealed class XamlWindowController RECT primaryRect = StructMarshal.RECT(DisplayArea.Primary.OuterBounds); return IntersectRect(out _, in primaryRect, in iconRect); } - else + + HWND shellTrayWnd = FindWindowExW(default, default, "Shell_TrayWnd", default); + HWND trayNotifyWnd = FindWindowExW(shellTrayWnd, default, "TrayNotifyWnd", default); + HWND button = FindWindowExW(trayNotifyWnd, default, "Button", default); + + if (GetWindowRect(button, out RECT buttonRect)) { - HWND shellTrayWnd = FindWindowExW(default, default, "Shell_TrayWnd", default); - HWND trayNotifyWnd = FindWindowExW(shellTrayWnd, default, "TrayNotifyWnd", default); - HWND button = FindWindowExW(trayNotifyWnd, default, "Button", default); - - if (GetWindowRect(button, out RECT buttonRect)) - { - return !EqualRect(in buttonRect, in iconRect); - } - - return false; + return !EqualRect(in buttonRect, in iconRect); } + + return false; } #region SystemBackdrop & ElementTheme From 0cc48973542a5d1927d69ddcdc13e2489625a453 Mon Sep 17 00:00:00 2001 From: DismissedLight <1686188646@qq.com> Date: Mon, 27 May 2024 23:24:03 +0800 Subject: [PATCH 06/68] deferload experiment --- .../Control/Behavior/DeferLoadBehavior.cs | 44 +++++++++++++++++++ .../Control/Behavior/DeferLoadCollection.cs | 25 +++++++++++ .../Snap.Hutao/View/Helper/LoadDeferral.cs | 15 +++++++ src/Snap.Hutao/Snap.Hutao/View/MainView.xaml | 2 +- .../View/Page/AnnouncementPage.xaml | 9 +++- 5 files changed, 92 insertions(+), 3 deletions(-) create mode 100644 src/Snap.Hutao/Snap.Hutao/Control/Behavior/DeferLoadBehavior.cs create mode 100644 src/Snap.Hutao/Snap.Hutao/Control/Behavior/DeferLoadCollection.cs create mode 100644 src/Snap.Hutao/Snap.Hutao/View/Helper/LoadDeferral.cs diff --git a/src/Snap.Hutao/Snap.Hutao/Control/Behavior/DeferLoadBehavior.cs b/src/Snap.Hutao/Snap.Hutao/Control/Behavior/DeferLoadBehavior.cs new file mode 100644 index 00000000..27b52fbc --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Control/Behavior/DeferLoadBehavior.cs @@ -0,0 +1,44 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +using CommunityToolkit.WinUI.Behaviors; +using Microsoft.UI.Xaml; +using System.Runtime.InteropServices; + +namespace Snap.Hutao.Control.Behavior; + +[DependencyProperty("ElementNames", typeof(DeferLoadCollection))] +internal sealed partial class DeferLoadBehavior : BehaviorBase +{ + protected override bool Initialize() + { + if (ElementNames.IsNullOrEmpty()) + { + return true; + } + + ThreadPool.UnsafeQueueUserWorkItem(LoadElements, this); + return true; + } + + private static void LoadElements(object? state) + { + if (state is not DeferLoadBehavior behavior) + { + return; + } + + List? elementNames = null; + behavior.AssociatedObject.DispatcherQueue.Invoke(() => elementNames = [.. behavior.ElementNames]); + + foreach (string name in CollectionsMarshal.AsSpan(elementNames)) + { + Thread.Sleep(1000); + + behavior.AssociatedObject.DispatcherQueue.TryEnqueue(() => + { + behavior.AssociatedObject.FindName(name); + }); + } + } +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Control/Behavior/DeferLoadCollection.cs b/src/Snap.Hutao/Snap.Hutao/Control/Behavior/DeferLoadCollection.cs new file mode 100644 index 00000000..c7ae5eb8 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Control/Behavior/DeferLoadCollection.cs @@ -0,0 +1,25 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.Extensions.Primitives; +using Windows.Foundation.Metadata; + +namespace Snap.Hutao.Control.Behavior; + +[CreateFromString(MethodName = "Snap.Hutao.Control.Behavior.DeferLoadCollection.Parse")] +internal sealed class DeferLoadCollection : List +{ + public static DeferLoadCollection Parse(string text) + { + DeferLoadCollection collection = []; + foreach (StringSegment segment in new StringTokenizer(text, [','])) + { + if (segment.HasValue) + { + collection.Add(segment.Value); + } + } + + return collection; + } +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/View/Helper/LoadDeferral.cs b/src/Snap.Hutao/Snap.Hutao/View/Helper/LoadDeferral.cs new file mode 100644 index 00000000..e4934471 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/View/Helper/LoadDeferral.cs @@ -0,0 +1,15 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +using CommunityToolkit.Mvvm.ComponentModel; +using Microsoft.Extensions.Primitives; +using Windows.Foundation.Metadata; + +namespace Snap.Hutao.View.Helper; + +internal sealed class LoadDeferral : ObservableObject +{ + private bool canLoad; + + public bool CanLoad { get => canLoad; set => SetProperty(ref canLoad, value); } +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/View/MainView.xaml b/src/Snap.Hutao/Snap.Hutao/View/MainView.xaml index 04885ca6..0edacf43 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/MainView.xaml +++ b/src/Snap.Hutao/Snap.Hutao/View/MainView.xaml @@ -31,7 +31,7 @@ - + diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/AnnouncementPage.xaml b/src/Snap.Hutao/Snap.Hutao/View/Page/AnnouncementPage.xaml index 4c4abb6b..4304f903 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Page/AnnouncementPage.xaml +++ b/src/Snap.Hutao/Snap.Hutao/View/Page/AnnouncementPage.xaml @@ -23,6 +23,7 @@ mc:Ignorable="d"> + @@ -207,7 +208,7 @@ - + - + Date: Tue, 28 May 2024 16:01:13 +0800 Subject: [PATCH 07/68] remove blank spaces --- .../Snap.Hutao/Core/Windowing/XamlWindowController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/XamlWindowController.cs b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/XamlWindowController.cs index a78cf106..816af2c2 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/XamlWindowController.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/XamlWindowController.cs @@ -140,7 +140,7 @@ internal sealed class XamlWindowController RECT primaryRect = StructMarshal.RECT(DisplayArea.Primary.OuterBounds); return IntersectRect(out _, in primaryRect, in iconRect); } - + HWND shellTrayWnd = FindWindowExW(default, default, "Shell_TrayWnd", default); HWND trayNotifyWnd = FindWindowExW(shellTrayWnd, default, "TrayNotifyWnd", default); HWND button = FindWindowExW(trayNotifyWnd, default, "Button", default); From b07c569a9eaac9d185b0e7b10f4f5f739b7058de Mon Sep 17 00:00:00 2001 From: Masterain Date: Tue, 28 May 2024 02:07:00 -0700 Subject: [PATCH 08/68] New Crowdin updates (#1634) --- .../Resource/Localization/SH.en.resx | 38 +- .../Resource/Localization/SH.fr.resx | 58 +- .../Resource/Localization/SH.id.resx | 38 +- .../Resource/Localization/SH.ja.resx | 54 +- .../Resource/Localization/SH.ko.resx | 38 +- .../Resource/Localization/SH.pt.resx | 38 +- .../Resource/Localization/SH.ru.resx | 104 +- .../Resource/Localization/SH.vi.resx | 3266 +++++++++++++++++ .../Resource/Localization/SH.zh-Hant.resx | 204 +- 9 files changed, 3696 insertions(+), 142 deletions(-) create mode 100644 src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.vi.resx diff --git a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.en.resx b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.en.resx index 86898b7a..6cae5c70 100644 --- a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.en.resx +++ b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.en.resx @@ -192,6 +192,18 @@ Register [{0}] hotkey [{1}] failed + + 退出 + + + Launch + + + 胡桃已进入后台运行 + + + 窗口 + Dark @@ -1556,6 +1568,12 @@ Can't add plan with invalid name + + 此操作不可逆,此计划的养成物品与背包材料将会丢失 + + + 确认要删除当前计划吗? + Realtime Note Webhook URL successfully configured @@ -1946,6 +1964,9 @@ Notification Settings + + 胡桃的通知权限已被关闭 + Refresh @@ -1976,6 +1997,9 @@ Refresh + + 未启用通知区域图标,关闭窗口后自动刷新将不会执行 + Do not disturb during Genshin gaming @@ -2654,6 +2678,12 @@ Shortcut Keys + + 在通知区域显示图标,以允许执行后台任务,重启后生效 + + + 通知区域图标 + Official Website @@ -3006,7 +3036,7 @@ Weapon WIKI - (?:〓活动时间〓|〓任务开放时间〓).*?(\d\.\d)版本更新(?:完成|)后永久开放 + (?:(?:〓活动时间〓|〓任务开放时间〓).*?(\d\.\d)版本更新(?:完成|)|&lt;t class=\"t_(?:gl|lc)\".*?&gt;(.*?)&lt;/t&gt;)后永久开放 〓活动时间〓.*?(\d\.\d)版本期间持续开放 @@ -3044,6 +3074,9 @@ Copied to clipboard + + All Archon Quest Completed + Completed @@ -3224,6 +3257,9 @@ [{1}] network request exception in [{0}] please try again later + + 登录失败,请前往 HoYoLAB 初始化账号,原始消息:{0} + Monitor ID diff --git a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.fr.resx b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.fr.resx index e535314f..00b80665 100644 --- a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.fr.resx +++ b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.fr.resx @@ -192,6 +192,18 @@ Échec de l'enregistrement de [{0}] en touche de raccourci [{1}] + + 退出 + + + Lanceur de jeu + + + 胡桃已进入后台运行 + + + 窗口 + Sombre @@ -409,7 +421,7 @@ Need EXACT same string in game - 旅行者 + Voyageur {0} 月 {1} 日 @@ -1473,7 +1485,7 @@ 有新的通知 - 启动游戏 + Lanceur de jeu 管理员模式下无法拖动排序 @@ -1556,6 +1568,12 @@ 不能添加名称无效的计划 + + 此操作不可逆,此计划的养成物品与背包材料将会丢失 + + + 确认要删除当前计划吗? + 实时便笺 Webhook Url 配置成功 @@ -1647,7 +1665,7 @@ 我已阅读并同意上方的条款 - 完成 + Terminer 下一步 @@ -1773,7 +1791,7 @@ 下载完成 - 完成 + Terminer 响应内容不是有效的文件字节流 @@ -1791,7 +1809,7 @@ 创建新存档以继续 - 导出 + Exporter 从剪贴板导入 @@ -1800,7 +1818,7 @@ 从 UIAF 文件导入 - 导入 + Importer 删除当前存档 @@ -1946,6 +1964,9 @@ 通知设置 + + 胡桃的通知权限已被关闭 + 立即刷新 @@ -1976,6 +1997,9 @@ 刷新 + + 未启用通知区域图标,关闭窗口后自动刷新将不会执行 + 在我游玩原神时不通知我 @@ -2031,7 +2055,7 @@ 全量刷新 - 导出 + Exporter 尚未获取任何祈愿记录 @@ -2067,7 +2091,7 @@ 上传当前的祈愿存档 - 导入 + Importer 导入来自其它 App 的数据 @@ -2238,7 +2262,7 @@ 请输入验证码 - 启动游戏 + Lanceur de jeu 高级功能 @@ -2583,7 +2607,7 @@ 祈愿记录 - 启动游戏 + Lanceur de jeu 隐藏 @@ -2654,6 +2678,12 @@ 快捷键 + + 在通知区域显示图标,以允许执行后台任务,重启后生效 + + + 通知区域图标 + 前往官网 @@ -3006,7 +3036,7 @@ 武器资料 - (?:〓活动时间〓|〓任务开放时间〓).*?(\d\.\d)版本更新(?:完成|)后永久开放 + (?:(?:〓活动时间〓|〓任务开放时间〓).*?(\d\.\d)版本更新(?:完成|)|&lt;t class=\"t_(?:gl|lc)\".*?&gt;(.*?)&lt;/t&gt;)后永久开放 〓活动时间〓.*?(\d\.\d)版本期间持续开放 @@ -3044,6 +3074,9 @@ 已复制到剪贴板 + + 所有魔神任务已完成 + 全部完成 @@ -3224,6 +3257,9 @@ [{0}] 中的 [{1}] 网络请求异常,请稍后再试 + + 登录失败,请前往 HoYoLAB 初始化账号,原始消息:{0} + 显示器编号 diff --git a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.id.resx b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.id.resx index d60ef938..0c5f31e0 100644 --- a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.id.resx +++ b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.id.resx @@ -192,6 +192,18 @@ [{0}] Hotkey [{1}] gagal terdaftar + + 退出 + + + Luncurkan + + + 胡桃已进入后台运行 + + + 窗口 + 深色 @@ -1556,6 +1568,12 @@ Tidak dapat menambahkan rencana dengan nama yang salah. + + 此操作不可逆,此计划的养成物品与背包材料将会丢失 + + + 确认要删除当前计划吗? + URL Webhook Catatan Realtime berhasil dikonfigurasi. @@ -1946,6 +1964,9 @@ Pengaturan notifikasi + + 胡桃的通知权限已被关闭 + Segarkan sekarang @@ -1976,6 +1997,9 @@ Perbarui + + 未启用通知区域图标,关闭窗口后自动刷新将不会执行 + Jangan ganggu selama bermain Genshin @@ -2654,6 +2678,12 @@ Tombol Pintas + + 在通知区域显示图标,以允许执行后台任务,重启后生效 + + + 通知区域图标 + Website Resmi @@ -3006,7 +3036,7 @@ Senjata WIKI - (?:〓活动时间〓|〓任务开放时间〓).*?(\d\.\d)版本更新(?:完成|)后永久开放 + (?:(?:〓活动时间〓|〓任务开放时间〓).*?(\d\.\d)版本更新(?:完成|)|&lt;t class=\"t_(?:gl|lc)\".*?&gt;(.*?)&lt;/t&gt;)后永久开放 〓活动时间〓.*?(\d\.\d)版本期间持续开放 @@ -3044,6 +3074,9 @@ Disalin ke clipboard + + 所有魔神任务已完成 + Selesai @@ -3224,6 +3257,9 @@ [{1}] pengecualian permintaan jaringan di [{0}], harap coba lagi nanti + + 登录失败,请前往 HoYoLAB 初始化账号,原始消息:{0} + ID Monitor diff --git a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.ja.resx b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.ja.resx index 0357fa5b..776c9947 100644 --- a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.ja.resx +++ b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.ja.resx @@ -145,7 +145,7 @@ 保存 - 未找到结果 + 検索結果なし 無効なURL @@ -192,6 +192,18 @@ [{0}] 热键 [{1}] 注册失败 + + 退出 + + + ゲームランチャー + + + 胡桃已进入后台运行 + + + 窗口 + 深色 @@ -783,13 +795,13 @@ キャラクターラインナップ:{0:MM-dd HH:mm} - 必应每日一图 + Bingからのランダム画像 - 胡桃每日一图 + 日替わり胡桃画像 - 官方启动器壁纸 + 公式ランチャー背景 本地随机图片 @@ -873,7 +885,7 @@ イベント祈願・キャラクター - 集录祈愿 + 集録祈願 奔走世間 @@ -1556,6 +1568,12 @@ 育成計画名に無効な言葉が入っています + + 此操作不可逆,此计划的养成物品与背包材料将会丢失 + + + 确认要删除当前计划吗? + リアルタイムノートのWebhook URLの設定に成功しました。 @@ -1946,6 +1964,9 @@ 通知設定 + + 胡桃的通知权限已被关闭 + すぐに更新 @@ -1976,6 +1997,9 @@ 更新 + + 未启用通知区域图标,关闭窗口后自动刷新将不会执行 + プレイ中に通知をオフ @@ -2654,14 +2678,20 @@ ショートカットキー + + 在通知区域显示图标,以允许执行后台任务,重启后生效 + + + 通知区域图标 + 公式サイト - 自定义背景图片,支持 bmp / gif / ico / jpg / jpeg / png / tiff / webp 格式 + カスタム背景を設定する / bmp、git、ico、jpg、jpeg、png、tiff、webp形式をサポートしています - 打开背景图片文件夹 + カスタム背景フォルダーを開く リセット @@ -3006,7 +3036,7 @@ 武器一覧 - (?:〓活动时间〓|〓任务开放时间〓).*?(\d\.\d)版本更新(?:完成|)后永久开放 + (?:(?:〓活动时间〓|〓任务开放时间〓).*?(\d\.\d)版本更新(?:完成|)|&lt;t class=\"t_(?:gl|lc)\".*?&gt;(.*?)&lt;/t&gt;)后永久开放 〓活动时间〓.*?(\d\.\d)版本期间持续开放 @@ -3044,6 +3074,9 @@ クリップボードにコピーしました。 + + 所有魔神任务已完成 + すべて完了 @@ -3171,7 +3204,7 @@ イベント祈願・キャラクター2 - 集录祈愿 + 集録祈願 初心者祈願 @@ -3224,6 +3257,9 @@ [{0}] の[{1}] のリクエストにエラーが発生、時間をおいてから試してください + + 登录失败,请前往 HoYoLAB 初始化账号,原始消息:{0} + モニターID diff --git a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.ko.resx b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.ko.resx index 63a0799a..bf0e74a1 100644 --- a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.ko.resx +++ b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.ko.resx @@ -192,6 +192,18 @@ [{0}] 热键 [{1}] 注册失败 + + 退出 + + + 게임 시작 + + + 胡桃已进入后台运行 + + + 窗口 + 深色 @@ -1556,6 +1568,12 @@ 잘못된 이름을 가진 일정은 추가할 수 없습니다 + + 此操作不可逆,此计划的养成物品与背包材料将会丢失 + + + 确认要删除当前计划吗? + 实时便笺 Webhook Url 配置成功 @@ -1946,6 +1964,9 @@ 알림 설정 + + 胡桃的通知权限已被关闭 + 지금 동기화 @@ -1976,6 +1997,9 @@ 동기화 + + 未启用通知区域图标,关闭窗口后自动刷新将不会执行 + 원신을 플레이 할 때 알리지 않음 @@ -2654,6 +2678,12 @@ 快捷键 + + 在通知区域显示图标,以允许执行后台任务,重启后生效 + + + 通知区域图标 + 공식 홈페이지로 이동 @@ -3006,7 +3036,7 @@ 무기 자료 - (?:〓活动时间〓|〓任务开放时间〓).*?(\d\.\d)版本更新(?:完成|)后永久开放 + (?:(?:〓活动时间〓|〓任务开放时间〓).*?(\d\.\d)版本更新(?:完成|)|&lt;t class=\"t_(?:gl|lc)\".*?&gt;(.*?)&lt;/t&gt;)后永久开放 〓活动时间〓.*?(\d\.\d)版本期间持续开放 @@ -3044,6 +3074,9 @@ 已复制到剪贴板 + + 所有魔神任务已完成 + 全部完成 @@ -3224,6 +3257,9 @@ [{0}] 中的 [{1}] 网络请求异常,请稍后再试 + + 登录失败,请前往 HoYoLAB 初始化账号,原始消息:{0} + 显示器编号 diff --git a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.pt.resx b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.pt.resx index 4b9c31c2..ec3f4af2 100644 --- a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.pt.resx +++ b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.pt.resx @@ -192,6 +192,18 @@ Falha ao definir atalho [{0}] para [{1}]. + + 退出 + + + Iniciar + + + 胡桃已进入后台运行 + + + 窗口 + Tema Escuro @@ -1556,6 +1568,12 @@ Não é possível adicionar um plano com nome inválido + + 此操作不可逆,此计划的养成物品与背包材料将会丢失 + + + 确认要删除当前计划吗? + URL do webhook de lembrete de tempo real configurado com sucesso @@ -1946,6 +1964,9 @@ Configurações de notificação + + 胡桃的通知权限已被关闭 + Atualizar @@ -1976,6 +1997,9 @@ Atualizar + + 未启用通知区域图标,关闭窗口后自动刷新将不会执行 + Não incomodar durante o Genshin @@ -2654,6 +2678,12 @@ Teclas de atalho + + 在通知区域显示图标,以允许执行后台任务,重启后生效 + + + 通知区域图标 + Site oficial @@ -3006,7 +3036,7 @@ Wiki de armas - (?:〓活动时间〓|〓任务开放时间〓).*?(\d\.\d)版本更新(?:完成|)后永久开放 + (?:(?:〓活动时间〓|〓任务开放时间〓).*?(\d\.\d)版本更新(?:完成|)|&lt;t class=\"t_(?:gl|lc)\".*?&gt;(.*?)&lt;/t&gt;)后永久开放 〓活动时间〓.*?(\d\.\d)版本期间持续开放 @@ -3044,6 +3074,9 @@ Copiado para a área de transferência + + Todas as missões de arconte concluídas + Concluído @@ -3224,6 +3257,9 @@ [{1}] erro de solicitação de rede em [{0}], tente novamente mais tarde + + 登录失败,请前往 HoYoLAB 初始化账号,原始消息:{0} + ID do monitor diff --git a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.ru.resx b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.ru.resx index 2c07f428..2ddd964c 100644 --- a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.ru.resx +++ b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.ru.resx @@ -192,6 +192,18 @@ Регистрация [{0}] горячей клавиши [{1}] не удалась + + 退出 + + + Game Launcher + + + 胡桃已进入后台运行 + + + 窗口 + Тёмная @@ -1173,40 +1185,40 @@ Режим импорта - 贪婪(添加新数据,更新已完成项) + Жадно (добавляют новые данные, обновляют завершенные записи) - 懒惰(添加新数据,跳过已完成项) + Лениво (добавление новых данных, пропуск завершенных записей) - 覆盖(删除老数据,添加新的数据) + Перезапись (удаление старых данных, добавление новых) Импорт данных о достижениях в текущий архив - 角色目标等级 + Целевой уровень персонажа - 普通攻击目标等级 + Уровень цели обычной атаки - 元素战技目标等级 + Целевой уровень Элементального навыка - 元素爆发目标等级 + Целевой уровень Взрыва стихий - 武器目标等级 + Целевой уровень оружия - 绑定当前用户与角色 + Связать текущего пользователя и роль - 在此处输入计划名称 + Введите название плана - 创建新的养成计划 + Создание нового плана 批量添加或更新到当前养成计划 @@ -1218,7 +1230,7 @@ 每日委托上线提醒 - 探索派遣完成提醒 + Уведомление об окончании экспедиции 洞天宝钱提醒阈值 @@ -1236,7 +1248,7 @@ 参量质变仪提醒 - 请输入 Url + Пожалуйста, введите URL 实时便笺 Webhook Url @@ -1260,7 +1272,7 @@ 获取祈愿物品中 - 请输入 Url + Пожалуйста, введите URL 手动输入祈愿记录 Url @@ -1287,7 +1299,7 @@ 将会通过 GET 方式对接口发送请求 - 示例 + Пример 配置无感验证接口 @@ -1329,13 +1341,13 @@ UIGF 版本 - 在此处输入名称 + Введите имя - 为账号命名 + Назовите ваш аккаунт - 请选择当前游戏路径对应的游戏服务器 + Пожалуйста, выберите ваш игровой сервер Восстановление файла конфигурации @@ -1347,7 +1359,7 @@ 正在转换客户端 - 使用米游社扫描二维码 + Отсканируйте QR-код с помощью Miyusha 为防止你在无意间启用,请输入正在启用的功能开关的<b>标题名称</b> @@ -1356,7 +1368,7 @@ 你正在启用一个危险功能 - 该操作是不可逆的,所有用户登录状态会丢失 + Эта операция необратима, и все входы пользователей в систему будут удалены 是否永久删除用户数据 @@ -1368,7 +1380,7 @@ 当前未登录胡桃账号,上传深渊数据无法获赠胡桃云时长 - 继续上传 + Продолжить загрузку 上传深渊数据 @@ -1389,37 +1401,37 @@ 在此处输入包含 SToken 的 Cookie - 设置 Cookie + Установка cookie-файлов - 反馈中心 + Центр обратной связи - 祈愿记录 + История молитв - 预计下载大小:{0} + Примерный размер загрузки: {0} - 我已阅读并同意 + Я прочитал и согласен с 问题报告方式与流程 - Snap Hutao 开源许可 + Лицензия с открытым исходным кодом Snap Hutao - 用户数据与隐私权益 + Данные пользователя и права на конфиденциальность - 用户使用协议与法律声明 + Пользовательское соглашение - 基础设置 + Основные настройки - 稍后可以在设置中修改 + Это можно изменить позже в настройках Документация @@ -1556,6 +1568,12 @@ 不能添加名称无效的计划 + + 此操作不可逆,此计划的养成物品与背包材料将会丢失 + + + 确认要删除当前计划吗? + 实时便笺 Webhook Url 配置成功 @@ -1946,6 +1964,9 @@ Настройки уведомлений + + 胡桃的通知权限已被关闭 + Обновить @@ -1976,6 +1997,9 @@ Обновить + + 未启用通知区域图标,关闭窗口后自动刷新将不会执行 + 在我游玩原神时不通知我 @@ -2544,7 +2568,7 @@ 前往反馈 - 祈愿记录 + История молитв 游戏 @@ -2580,7 +2604,7 @@ Заметки в реальном времени - 祈愿记录 + История молитв Game Launcher @@ -2654,6 +2678,12 @@ 快捷键 + + 在通知区域显示图标,以允许执行后台任务,重启后生效 + + + 通知区域图标 + 前往官网 @@ -3006,7 +3036,7 @@ 武器资料 - (?:〓活动时间〓|〓任务开放时间〓).*?(\d\.\d)版本更新(?:完成|)后永久开放 + (?:(?:〓活动时间〓|〓任务开放时间〓).*?(\d\.\d)版本更新(?:完成|)|&lt;t class=\"t_(?:gl|lc)\".*?&gt;(.*?)&lt;/t&gt;)后永久开放 〓活动时间〓.*?(\d\.\d)版本期间持续开放 @@ -3044,6 +3074,9 @@ Скопировано в буфер обмена + + 所有魔神任务已完成 + Завершенно @@ -3224,6 +3257,9 @@ [{1}] исключение сетевого запроса в [{0}] пожалуйста, повторите попытку позже + + 登录失败,请前往 HoYoLAB 初始化账号,原始消息:{0} + 显示器编号 diff --git a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.vi.resx b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.vi.resx new file mode 100644 index 00000000..fa25d21a --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.vi.resx @@ -0,0 +1,3266 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Snap Hutao Dev {0} + + + Snap Hutao Dev {0} [Quyền Quản Trị Viên] + + + Snap Hutao {0} [Quản trị viên] + + + Snap Hutao + + + Snap Hutao {0} + + + Hủy bỏ + + + Hoàn thành + + + OK + + + Lưu + + + Không tìm thấy kết quả + + + Uri không hợp lệ + + + HTTP GET {0} + + + 应用 CompositionImage 的源时发生异常 + + + 网格 + + + Danh sách + + + 数据库已损坏:{0} + + + 用户数据已损坏:{0} + + + 请勿在管理员模式下使用此功能 {0} + + + 无法打开文件选择器 + + + Không đủ quyền hạn, không thể tạo các tập tin tạm thời + + + Trình khởi chạy + + + Tiến trình làm mới ghi chú thời gian thực của Snap Hutao. KHÔNG chỉnh sửa hoặc xoá nó. + + + 信号量已经被释放,操作取消 + + + Không phát hiện WebView2 Runtime + + + + + + Thoát + + + 启动游戏 + + + 胡桃已进入后台运行 + + + Cửa sổ + + + Tối + + + Sáng + + + Hệ thống + + + Xuất + + + Nhập + + + 欢迎使用胡桃 + + + Lựa chọn tài khoản để khởi động + + + <color=#1E90FF>王子</color>/<color=#FFB6C1>公主</color> + + + <color=#1E90FF>我</color>/<color=#FFB6C1>我</color> + + + 旅行者 + + + <color=#1E90FF>他</color>/<color=#FFB6C1>她</color> + + + Kẻ lang thang + + + 精炼 {0} + + + 周一/周四/周日 + + + 周二/周五/周日 + + + 周三/周六/周日 + + + {0:f2} 抽 + + + 最非 {0} 抽 + + + 最欧 {0} 抽 + + + {0} 抽 + + + 第 {0} 层 + + + Cấp độ {0} + + + 上场 {0} 次 + + + Máy chủ BiliBili + + + Máy chủ Trung Quốc + + + Máy chủ Quốc Tế + + + 网络异常 + + + 尚未刷新 + + + 刷新于 {0:MM.dd HH:mm:ss} + + + + + + Tài khoản + + + Không xác định + + + Vũ khí + + + Fatui + Need EXACT same string in game + + + Fontaine + Need EXACT same string in game + + + Inazuma + Need EXACT same string in game + + + Liyue + Need EXACT same string in game + + + Mondstadt + Need EXACT same string in game + + + Natlan + Need EXACT same string in game + + + Ranger + Need EXACT same string in game + + + Snezhnaya + Need EXACT same string in game + + + Sumeru + Need EXACT same string in game + + + 少男 + + + 少女 + + + 成女 + + + 萝莉 + + + 成男 + + + Lôi + Need EXACT same string in game + + + Hoả + Need EXACT same string in game + + + Thảo + Need EXACT same string in game + + + Băng + Need EXACT same string in game + + + Nham + Need EXACT same string in game + + + Thủy + Need EXACT same string in game + + + Phong + Need EXACT same string in game + + + 3 Sao + + + 2 Sao + + + 5 Sao + + + 4 Sao + + + + + + 1 sao + + + Cung + Need EXACT same string in game + + + Pháp Khí + Need EXACT same string in game + + + Trọng kiếm + Need EXACT same string in game + + + Vũ khí cán dài + Need EXACT same string in game + + + Kiếm đơn + Need EXACT same string in game + + + Nhà lữ hành + + + {0}/{1} + + + Nguyên liệu bồi dưỡng nhân vật và vũ khí + Need EXACT same string in game + + + 角色突破素材 + Need EXACT same string in game + + + Nguyên liệu EXP nhân vật + Need EXACT same string in game + + + 角色培养素材 + Need EXACT same string in game + + + Nguyên liệu thiên phú nhân vật + Need EXACT same string in game + + + ^[\u4e00-\u9fa5]{2}区域特产$ + If you don't know what is regex, DO NOT TRANSLATE THIS! + + + Nguyện liệu đột phá vũ khí + Need EXACT same string in game + + + Nguyên liệu cường hoá vũ khí + Need EXACT same string in game + + + 击败怪物 + + + 守护目标 + + + 附加:增援怪物 + + + 本间怪物 + + + A组:不同的组同时在场,各自分波独立 + + + A组第一波:不同的组同时在场,各自分波独立 + + + A组第二波:不同的组同时在场,各自分波独立 + + + A组第三波:不同的组同时在场,各自分波独立 + + + B组:不同的组同时在场,各自分波独立 + + + B组第一波:不同的组同时在场,各自分波独立 + + + B组第二波:不同的组同时在场,各自分波独立 + + + B组第三波:不同的组同时在场,各自分波独立 + + + C组:不同的组同时在场,各自分波独立 + + + C组第一波:不同的组同时在场,各自分波独立 + + + C组第二波:不同的组同时在场,各自分波独立 + + + C组第三波:不同的组同时在场,各自分波独立 + + + D组:不同的组同时在场,各自分波独立 + + + D组第一波:不同的组同时在场,各自分波独立 + + + D组第二波:不同的组同时在场,各自分波独立 + + + D组第三波:不同的组同时在场,各自分波独立 + + + 与其他怪物独立 + + + 暂时没有分波信息 + + + 第一波:击败所有怪物,下一波才会出现 + + + 第一波附加:增援第一波怪物 + + + 第二波:击败所有怪物,下一波才会出现 + + + 第三波:击败所有怪物,下一波才会出现 + + + 第四波:击败所有怪物,下一波才会出现 + + + 维持场上 4 个盗宝团怪物,击杀后立即替换,总数 12 个 + + + 请更新角色橱窗数据 + + + Không có dữ liệu + + + 精炼 {0} 阶 + + + Phải đăng nhập vào tài khoản MiHoYo BBS của bạn và chọn người dùng + + + Đã xoá {1} bản ghi cầu nguyện của UID: {0} + + + Đã đạt đến số lượng lịch sử cầu nguyện tối đa cho phép trên Snap Hutao Cloud + + + 未开通祈愿记录上传服务或已到期 + + + 祈愿数据存在无效的物品,无法保存至胡桃云 + + + Tìm thấy dữ liệu bất thường, không thể tải lên Snap Hutao Cloud. Vui lòng không tải lên từ nhiều tài khoản hoặc bạn có thể thử xóa dữ liệu đám mây và thử lại. + + + Đã tải lên {1} bản ghi cầu nguyện của UID: {0}, đã được lưu trữ {2} + + + Vui lòng đăng nhập hoặc đăng ký tài khoản Snap Hutao trước tiên + + + Đăng nhập thành công + + + Đăng ký thành công + + + 新密码设置成功 + + + 当前邮箱尚未注册 + + + Địa chỉ email hiện tại đã được đăng ký + + + Đăng ký không thành công, lỗi máy chủ, vui lòng liên hệ nhà phát triển để khắc phục + + + Người dùng không tồn tại, không thể xoá tài khoản + + + Huỷ đăng ký thành công + + + 用户不存在,获取用户信息失败 + + + 用户名或密码错误 + + + Xác minh thất bại + + + Yêu cầu xác minh không thành công, đó không phải là tài khoản hiện đang đăng nhập + + + Mã xác nhận đã được gửi đến email của bạn + + + Yêu cầu xác minh không thành công, địa chỉ email hiện tại đã được đăng ký + + + Yêu cầu xác minh quá thường xuyên. Vui lòng thử lại sau 1 phút. + + + Không thể tải lên bản ghi la hoàn thâm cảnh, UID hiện tại đã bị cơ sở dữ liệu Hutao cấm + + + Không thể tải lên bản ghi la hoàn thâm cảnh, máy chủ đang tính toán dữ liệu thống kê + + + Không lấy được dữ liệu, máy chủ đang tính toán dữ liệu thống kê + + + Không tải lên được bản ghi la hoàn thâm cảnh, lỗi máy chủ, vui lòng liên hệ nhà phát triển để khắc phục + + + Không thể tải lên bản ghi la hoàn thâm cảnh, phát hiện thấy dữ liệu không hợp lệ + + + UID không hợp lệ + + + 上传深渊记录失败,不是本期数据 + + + 上传深渊记录失败,当前 Uid 的记录仍在处理中,请勿重复操作 + + + Đã tải lên bản ghi la hoàn thâm cảnh thành công. Đã nhận được extension đặc quyền cho dịch vụ Snap Hutao Cloud. + + + Đã tải lên bản ghi la hoàn thành công. Không nhận được đặc quyền nào của Snap Hutao Cloud do chưa đăng nhập tài khoản Snap Hutao. + + + Đã tải lên bản ghi la hoàn thâm cảnh thành công. Không nhận được đặc quyền nào của Snap Hutao Cloud vì không tìm thấy tài khoản Snap Hutao. + + + Đã tải lên bản ghi la hoàn thành công. Không nhận được đặc quyền của Snap Hutao Cloud vì đây không phải là lần tải lên đầu tiên trong lịch trình hiện tại. + + + Mới: {0} thành tựu | Đã cập nhật: {1} thành tựu | Xoá: {2} thành tựu + + + Tập tin UIAF Json + + + 打开 UIAF Json 文件 + + + Đã tìm thấy nhiều ID thành tựu giống hệt nhau trong kho lưu trữ thành tựu + + + + Need EXACT same string in game + + + 基础攻击力 + Need EXACT same string in game + + + Phòng ngự cơ bản + Need EXACT same string in game + + + 基础生命值 + Need EXACT same string in game + + + 暴击伤害 + Need EXACT same string in game + + + Hiệu Quả Nạp Nguyên Tố + Need EXACT same string in game + + + Tỉ lệ bạo kích + Need EXACT same string in game + + + Tăng ST Nguyên Tố Lôi + Need EXACT same string in game + + + Tăng ST Nguyên Tố Lôi + Need EXACT same string in game + + + Tăng ST nguyên tố thảo + Need EXACT same string in game + + + Tăng ST nguyên tố băng + Need EXACT same string in game + + + Tăng ST vật lí + Need EXACT same string in game + + + Tăng ST nguyên tố nham + Need EXACT same string in game + + + 水元素伤害加成 + Need EXACT same string in game + + + Tăng ST nguyên tố phong + Need EXACT same string in game + + + 防御力 + Need EXACT same string in game + + + 元素精通 + Need EXACT same string in game + + + 治疗加成 + Need EXACT same string in game + + + HP + Need EXACT same string in game + + + 雷元素抗性 + Need EXACT same string in game + + + 火元素抗性 + Need EXACT same string in game + + + 草元素抗性 + Need EXACT same string in game + + + 冰元素抗性 + Need EXACT same string in game + + + 物理抗性 + Need EXACT same string in game + + + Kháng nguyên tố nham + Need EXACT same string in game + + + Kháng nguyên tố thuỷ + Need EXACT same string in game + + + Kháng nguyên tố phong + Need EXACT same string in game + + + 养成计算:尚未刷新 + + + 养成计算:{0:MM-dd HH:mm} + + + 原神战绩:尚未刷新 + + + 原神战绩:{0:MM-dd HH:mm} + + + Enka: N/A + + + 角色橱窗:{0:MM-dd HH:mm} + + + 必应每日一图 + + + Hình nền hằng ngày của Hutao + + + Hình nền launcher chính thức của Genshin + + + Hình nền ngẫu nhiên trong máy + + + 无背景图片 + + + 保存养成计划状态失败 + + + 存在多个选中的养成计划 + + + 开始游戏 + + + 我知道了 + + + Kháng nguyên tố thuỷ + + + Ủy thác mỗi ngày + + + 奖励未领取 + + + Phái đi thám hiểm + + + 已完成 + + + 探索派遣已完成 + + + 洞天宝钱 + + + Tiền động tiên hiện tại: {0} + + + 多个提醒项达到设定值 + + + 原粹树脂 + + + 当前原粹树脂:{0} + + + 实时便笺提醒 + + + 参量质变仪 + + + Sẵn sàng + + + 参量质变仪已准备完成 + + + 权限不足,将无法为您设置 Discord Activity 状态 + + + 正在提瓦特大陆中探索 + + + Bắt đầu bởi {0} + + + Không thể lấy lịch sử cầu nguyện: {0} + + + 无法获取祈愿记录 End Id + + + Cầu nguyện nhân vật + + + 集录祈愿 + + + 奔行世间 + + + Thân hình thần đúc + + + Không thể lấy lịch sử cầu nguyện trên cloud + + + Dịch vụ tải lên lịch sử cầu nguyện hiện không khả dụng + + + Dữ liệu chứa mục không mong muốn, ID: {0} + + + 请求验证密钥失败 + + + Đường dẫn trò chơi Genshin Impact chưa được thiết lập hoặc thiết lập không đúng + + + Không thể tìm thấy đường dẫn đến cache của trình duyệt nhúng Genshin Impact: \n{0} + + + 未找到可用的 Url + + + 提供的 Url 无效 + + + Làm mới SToken không hỗ trợ tài khoản HoYoLab + + + Ngôn ngữ của URL: {0} không khớp với ngôn ngữ của Snap Hutao: {1}, vui lòng thử lại sau khi chuyển ngôn ngữ của ứng dụng trùng với ngôn ngữ URL + + + 不支持的 Item Id:{0} + + + Ngôn ngữ của tập tin UIGF: {0} không khớp với ngôn ngữ của Snap Hutao: {1}, vui lòng thử lại sau khi chuyển ngôn ngữ của ứng dụng trùng với ngôn ngữ của tập tin UIGF + + + 存在多个匹配账号,请删除重复的账号 + + + Không có quyền ghi vào tập tin hệ thống, không thể bắt đầu quá trình chuyển đổi máy chủ. + + + 下载游戏资源索引 + + + 游戏文件操作失败:{0} + + + Không thể mở khoá giới hạn khung hình + + + Trò chơi đang chạy + + + Chọn đường dẫn game + + + 下载游戏资源索引失败: {0} + + + 游戏进程已退出 + + + 正在初始化游戏进程 + + + 游戏进程已启动 + + + 解锁帧率上限失败,正在结束游戏进程 + + + Mở khoá giới hạn khung hình thành công + + + Thử mở khoá giới hạn khung hình... + + + Đang đợi tiến trình trò chơi đóng... + + + 选择游戏本体 + + + 游戏本体 + + + 找不到 Unity 日志文件 + + + 在 Unity 日志文件中找不到游戏路径 + + + 备份:{0} + + + 重命名:{0} 到:{1} + + + 替换:{0} + + + 重命名数据文件夹名称失败 + + + 获取 Package Version + + + 获取 Package Version 失败 + + + + + + 无法找到游戏路径,请前往设置修改 + + + 未开启长路径功能,无法设置注册表键值 + + + 无法读取游戏配置文件 {0},可能是文件不存在 + + + 无法读取或保存配置文件,请以管理员模式重试 + + + 在查找必要的模块时遇到问题:无法读取任何模块,可能是保护驱动已经加载完成,请重试 + + + 在查找必要的模块时遇到问题:查找模块超时,请重试 + + + 在匹配内存时遇到问题:无法匹配到期望的内容 + + + 在读取必要的模块内存时遇到问题:无法将模块内存复制到指定位置 + + + 在读取游戏进程内存时遇到问题:无法读取到指定地址的有效值 + + + 祈愿记录上传服务有效期至\n{0:yyyy.MM.dd HH:mm:ss} + + + 无法找到缓存的元数据文件 + + + HTTP {0} | Error:{1}:元数据校验文件下载失败 + + + 元数据服务尚未初始化,或初始化失败 + + + 元数据校验文件解析失败 + + + 元数据校验文件下载失败 + + + 你的胡桃版本过低,请尽快升级 + + + 签到失败,{0} + + + 获取签到次数失败 + + + 获取奖励列表失败 + + + 验证失败,请前往米游社原神签到页面自行领取奖励 + + + 签到成功,{0}×{1} + + + 不支持的 UIGF 版本 + + + 发现新版本 {0} + + + 多个用户记录为选中状态 + + + 用户 {0} 状态保存失败 + + + 输入的 Cookie 必须包含 Mid + + + 输入的 Cookie 必须包含 SToken + + + 输入的 Cookie 无法获取用户信息 + + + 成就管理 + + + 主页 + + + 我的角色 + + + 同步角色信息 + + + 成就统计 + + + 保底计数 + + + 选择账号或直接启动 + + + 等级 + + + 突破后 + + + 需要管理员权限 + + + 加载中,请稍候 + + + 三星 + + + 保底 + + + 五星平均抽数 + + + 五星 + + + + + + 四星 + + + 距上个五星 + + + 距上个四星 + + + UP 平均抽数 + + + UP + + + 预测 + + + 比例 + + + 统计 + + + 当前 WebView2 版本不支持管理配置,继续使用可能会导致异常,请尽快升级 + + + 养成计划 + + + 实时便笺 + + + 数据 + + + 在此处输入 + + + 设置成就存档的名称 + + + 导入模式 + + + 贪婪(添加新数据,更新已完成项) + + + 懒惰(添加新数据,跳过已完成项) + + + 覆盖(删除老数据,添加新的数据) + + + 为当前存档导入成就 + + + 角色目标等级 + + + 普通攻击目标等级 + + + 元素战技目标等级 + + + 元素爆发目标等级 + + + 武器目标等级 + + + 绑定当前用户与角色 + + + 在此处输入计划名称 + + + 创建新的养成计划 + + + 批量添加或更新到当前养成计划 + + + 添加或更新到当前养成计划 + + + 每日委托上线提醒 + + + 探索派遣完成提醒 + + + 洞天宝钱提醒阈值 + + + 原粹树脂提醒阈值 + + + 在主页显示卡片 + + + 实时便笺通知设置 + + + 参量质变仪提醒 + + + 请输入 Url + + + 实时便笺 Webhook Url + + + 解除限制后需要使用其他工具恢复限制 + + + 是否解除 Loopback 限制 + + + 导入祈愿记录 + + + 祈愿记录 Url 已失效,请重新获取 + + + 正在获取 {0} + + + 获取祈愿物品中 + + + 请输入 Url + + + 手动输入祈愿记录 Url + + + 请输入请求接口的 Url 复合模板 + + + 接口需要返回形如上方所示的 Json 数据,多余的数据会被忽略 + + + "code" 为 0 时,指示验证成功,其他的值均视为验证失败 + + + 返回数据 + + + {0} 将在实际请求时替换为 gt + + + {1} 将在实际请求时替换为 challenge + + + 将会通过 GET 方式对接口发送请求 + + + 示例 + + + 配置无感验证接口 + + + 登录胡桃通行证 + + + 注册胡桃通行证 + + + 重置胡桃通行证密码 + + + 注销胡桃通行证账号 + + + 导出 App + + + 导出 App 版本 + + + 导出时间 + + + 成就个数 + + + UIAF 版本 + + + 记录条数 + + + UID + + + UIGF 版本 + + + 在此处输入名称 + + + 为账号命名 + + + 请选择当前游戏路径对应的游戏服务器 + + + 正在修复配置文件 + + + 转换可能需要花费一段时间,请勿关闭胡桃 + + + 正在转换客户端 + + + 使用米游社扫描二维码 + + + 为防止你在无意间启用,请输入正在启用的功能开关的<b>标题名称</b> + + + 你正在启用一个危险功能 + + + 该操作是不可逆的,所有用户登录状态会丢失 + + + 是否永久删除用户数据 + + + 前往登录 + + + 当前未登录胡桃账号,上传深渊数据无法获赠胡桃云时长 + + + 继续上传 + + + 上传深渊数据 + + + 查看更新日志 + + + 立即前往 + + + 进入文档页面并按指示操作 + + + 操作文档 + + + 在此处输入包含 SToken 的 Cookie + + + 设置 Cookie + + + 反馈中心 + + + 祈愿记录 + + + 预计下载大小:{0} + + + 我已阅读并同意 + + + 问题报告方式与流程 + + + Snap Hutao 开源许可 + + + 用户数据与隐私权益 + + + 用户使用协议与法律声明 + + + 基础设置 + + + 稍后可以在设置中修改 + + + 文档 + + + 环境 + + + 安装完成后重启胡桃以查看是否正常生效 + + + 如果上方的图标中存在乱码或方块字,请前往 + + + 下载并自行安装图标字体 + + + 若未检测到 WebView2 运行时信息,可以前往 + + + 下载并自行安装运行时 + + + 语言 + + + 资源 + + + 图像资源设置 + + + * 除非你卸载并重新安装胡桃,否则你将无法更改这些设置 + + + 图片资源包体 + + + 完整包体 + + + 精简包体 + + + 图片资源质量 + + + 深渊统计 + + + 有新的通知 + + + 启动游戏 + + + 管理员模式下无法拖动排序 + + + 存档 [{0}] 添加成功 + + + 不能添加名称重复的存档 [{0}] + + + 不能添加名称无效的存档 + + + UIAF 文件 + + + 导入成就中 + + + 数据的 UIAF 版本过低,无法导入 + + + 该操作是不可逆的,该存档和其内的所有成就状态会丢失 + + + 确定要删除存档 {0} 吗? + + + 导出 UIAF Json 文件到指定路径 + + + 获取培养材料中,请稍候... + + + 当前角色无法计算,请同步信息后再试 + + + 角色信息服务 [Enka API] 当前不可用 + + + 已导出到剪贴板 + + + 获取数据中 + + + 打开剪贴板失败 + + + 角色展柜尚未开启,请前往游戏操作后重试 + + + 无圣遗物或散件 + + + 养成计划添加失败 + + + 操作完成:添加/更新:{0} 个,跳过 {1} 个 + + + 操作未全部完成:添加/更新:{0} 个,跳过 {1} 个 + + + 已成功添加至当前养成计划 + + + 请先前往养成计划页面创建计划并选中 + + + 重新添加物品以查看养成描述 + + + 添加成功 + + + 不能添加名称重复的计划 + + + 不能添加名称无效的计划 + + + 此操作不可逆,此计划的养成物品与背包材料将会丢失 + + + 确认要删除当前计划吗? + + + 实时便笺 Webhook Url 配置成功 + + + HoYoLab 账号不支持验证实时便笺 + + + 修改计划任务失败 + + + 30 分钟 | 3.75 树脂 + + + 4 分钟 | 0.5 树脂 + + + 40 分钟 | 5 树脂 + + + 60 分钟 | 7.5 树脂 + + + 8 分钟 | 1 树脂 + + + 正在获取实时便笺信息,请稍候 + + + 成功保存到指定位置 + + + 导出成功 + + + 写入文件时遇到问题 + + + 导出失败 + + + UIGF Json 文件 + + + 导入完成 + + + 导入祈愿记录中 + + + 数据的 UIGF 版本过低,无法导入 + + + 导入数据中包含了不支持的物品 + + + 导入失败 + + + {1:P3} 概率 {0} 抽后获得五星物品 + + + {0:P3} 概率下一抽获得五星物品 + + + 获取祈愿记录失败 + + + 祈愿记录刷新操作被异常取消 + + + 该操作是不可逆的,该存档和其内的所有祈愿数据会丢失 + + + 确定要删除存档 {0} 吗? + + + 从胡桃云服务同步祈愿记录 + + + 导出 UIGF Json 文件到指定路径 + + + 正在上传到胡桃云服务 + + + 导入 UIGF Json 文件 + + + 我已阅读并同意上方的条款 + + + 完成 + + + 下一步 + + + 下载资源文件中,请稍候 + + + 高质量 + + + 原图 + + + 请输入正确的邮箱 + + + 剪贴板中的文本格式不正确 + + + 数据格式不正确 + + + 请先创建一个成就存档 + + + 导入失败 + + + 切换服务器失败 + + + 修复配置文件 + + + 修复完成 + + + 识别显示器 + + + 无法读取游戏配置文件: {0},可能是文件不存在或权限不足 + + + 游戏路径不正确,前往设置更改游戏路径 + + + 尚未选择任何服务器 + + + 设置游戏目录 + + + 切换账号失败 + + + 无法选择UID [{0}] 对应的账号 [{1}],该账号不属于当前服务器 + + + 操作完成 + + + 清除失败,文件目录权限不足,请使用管理员模式重试 + + + 清除失败,找不到目录:{0} + + + 清除完成 + + + 复制成功 + + + 创建桌面快捷方式失败 + + + 后续转换会重新下载所需的文件,确定要删除吗? + + + 删除转换服务器游戏客户端缓存 + + + 已使用磁盘空间:{0} + + + 无感验证复合 Url 配置成功 + + + 正在重置图片资源 + + + 设置数据目录成功,重启以应用更改 + + + 保存游戏路径失败 + + + 用户 [{0}] 添加成功 + + + 用户 [{0}] 的 Cookie 复制成功 + + + 此 Cookie 不完整,操作失败 + + + 此 Cookie 无效,操作失败 + + + 用户 [{0}] 成功移除 + + + 用户 [{0}] 的 Cookie 更新成功 + + + 页面资源已经被释放,操作取消 + + + 现在可以开始使用胡桃了 + + + 下载完成 + + + 完成 + + + 响应内容不是有效的文件字节流 + + + 等待中 + + + 文件下载异常 + + + 创建新存档 + + + 创建新存档以继续 + + + 导出 + + + 从剪贴板导入 + + + 从 UIAF 文件导入 + + + 导入 + + + 删除当前存档 + + + 搜索成就名称,描述,版本或编号 + + + 优先未完成 + + + 活动公告 + + + 游戏公告 + + + 查看详情 + + + 圣遗物评分 + + + 所有角色与武器 + + + 当前角色与武器 + + + 双暴评分 + + + 尚未获取任何角色信息 + + + 导出图片 + + + 角色属性 + + + 初始词条 + + + 同步 + + + 从游戏内角色橱窗同步 + + + 同步游戏内角色展柜中的信息 + + + 从米游社养成计算同步 + + + 同步角色天赋信息 + + + 从米游社原神战绩同步 + + + 同步角色天赋外的大部分信息 + + + 刷新时间 + + + 评分 + + + 强化词条 + + + 养成计算 + + + 新建计划 + + + 新建 + + + 新建养成计划以继续 + + + 稍后可以前往其他页面添加养成计划项 + + + 添加我的角色与武器到养成计划 + + + 养成物品 + + + 背包物品 + + + 材料清单 + + + 材料统计 + + + 前往 + + + 删除清单 + + + 删除当前计划 + + + 添加任意角色到养成计划 + + + 添加任意武器到养成计划 + + + 添加角色 + + + 添加角色以定时刷新 + + + 添加 + + + 历练点获取详情 + + + 在实时便笺刷新后推送到指定的 Webhook + + + 配置 Webhook + + + 数据互操作 + + + 通知 + + + 通知设置 + + + 胡桃的通知权限已被关闭 + + + 立即刷新 + + + 刷新间隔时间 + + + 防止通知自动收入操作中心 + + + 提醒通知 + + + 移除角色 + + + 本周已消耗减半次数 + + + 自动刷新 + + + 间隔选定的时间后刷新添加的实时便笺 + + + 这些选项仅允许在非管理员模式下更改 + + + 刷新 + + + 未启用通知区域图标,关闭窗口后自动刷新将不会执行 + + + 在我游玩原神时不通知我 + + + 免打扰模式 + + + 验证当前用户与角色 + + + 搜索问题与建议 + + + 基本信息 + + + 常用链接 + + + 当前代理 + + + 无代理 + + + 已解除 + + + 解除 Loopback 限制 + + + 与我们密切联系 + + + 功能指南 + + + 我们总是优先处理 GitHub 上的问题 + + + 开发路线规划 + + + 暂无搜索结果 + + + 胡桃服务可用性监控 + + + 胡桃服务 + + + 全量刷新 + + + 导出 + + + 尚未获取任何祈愿记录 + + + 胡桃云 + + + 前往爱发电购买相关服务 + + + 购买/续费云服务 + + + 删除此 Uid 的云端存档 + + + 开发者账号无视服务到期时间 + + + 胡桃云服务时长不足 + + + 下载此 Uid 的云端存档 + + + 每期深渊首次上传可免费获得 3 天时长 + + + 上传深渊记录 + + + 上传当前的祈愿存档 + + + 导入 + + + 导入来自其它 App 的数据 + + + 导入 UIGF Json + + + 输入 + + + 从胡桃云恢复祈愿记录 + + + 刷新 + + + 获取 + + + 手动输入 Url + + + 使用由你提供的 Url 刷新祈愿记录 + + + SToken 刷新 + + + 使用当前用户的 Cookie 信息刷新祈愿记录 + + + 网页缓存刷新 + + + 使用游戏内浏览器的网页缓存刷新祈愿记录 + + + 删除当前存档 + + + 角色 + + + 历史 + + + 总览 + + + 全球祈愿统计 + + + 武器 + + + 胡桃已经为你启动了 {0} 次游戏 + + + 你已经启动了胡桃 {0} 次 + + + 旅行者,欢迎来到提瓦特大陆! + + + 你说的对,但是《胡桃》是由 DGP Studio 自主研发的一款... + + + 呐,旅行者,这是你来到提瓦特大陆的第 {0} 天哦 + + + 设置 + + + 详情 + + + 角色出场 + + + 角色持有 + + + 角色使用 + + + 0 命 + + + 1 命 + + + 2 命 + + + 3 命 + + + 4 命 + + + 5 命 + + + 6 命 + + + 角色 + + + 持有 + + + 数据收集统计 + + + 上传记录总数 + + + 数据刷新时间 + + + 深渊数据统计 + + + 平均战斗次数 + + + 满星深渊记录 + + + 通关深渊记录 + + + 平均获取渊星 + + + 总计深渊记录 + + + 队伍出场 + + + 登录 + + + 请输入密码 + + + 至少需要 8 个字符 + + + 注册 + + + 重置密码 + + + 注销账号的数据将永远丢失,无法恢复 + + + 请输入邮箱 + + + 获取验证码 + + + 请输入验证码 + + + 启动游戏 + + + 高级功能 + + + 快速切换到指定的分辨率 + + + 分辨率 + + + 快捷设置分辨率 + + + 将窗口创建为弹出窗口,不带框架 + + + 无边框 + + + 启用内置触摸布局,不会响应键鼠输入 + + + 与游戏内浏览器不兼容,切屏等操作也能使游戏闪退 + + + 独占全屏 + + + 覆盖默认的全屏状态 + + + 全屏 + + + 外观 + + + 覆盖默认屏幕高度 + + + 高度 + + + 覆盖默认屏幕宽度 + + + 宽度 + + + 在游戏启动时修改其默认行为 + + + 启动参数 + + + 在游戏启动后尝试启动并使用 Better GI 进行自动化任务 + + + 自动化任务 + + + 常规 + + + 所有选项仅会在启动游戏成功后保存 + + + 在我游戏时设置 Discord Activity 状态 + + + Discord Activity + + + 文件 + + + 进程联动 + + + 在指定的显示器上运行 + + + 显示器 + + + 同时运行多个游戏客户端 + + + 多客户端 + + + 游戏选项 + + + 在游戏启动后尝试启动并使用 Starward 进行游戏时长统计 + + + 时长统计 + + + 进程 + + + 注册表 + + + 增量包 + + + 资源下载 + + + 完整包 + + + 预下载 + + + 选择游戏路径 + + + 该账号尚未绑定实时便笺通知 UID + + + 绑定当前用户的角色 + + + 在游戏内切换账号,网络环境发生变化后需要重新手动检测 + + + 检测 + + + 检测账号 + + + 删除 + + + 重命名 + + + 切换游戏服务器(国服/渠道服/国际服) + + + 服务器 + + + 版本更新前需要提前转换至与启动器匹配的服务器 + + + 请在游戏内关闭垂直同步选项,需要高性能的显卡以支持更高的帧率 + + + 解锁帧率限制 + + + 禁用 + + + 启用 + + + 充分利用支持高动态范围的显示器获得更亮、更生动、更精细的画面 + + + Windows HDR + + + 请输入你的 HoYoLab Uid + + + 你正在通过由我们提供的内嵌网页视图登录 米哈游通行证,我们会在你点击 我已登录 按钮后,读取你的 Cookie 信息,由此视图发起的网络通信只发生于你的计算机与米哈游服务器之间 + + + 我已登录 + + + 在下方登录米哈游通行证 + + + 打开截图文件夹 + + + 选择游戏路径 + + + 关于 胡桃 + + + 外观 + + + 设置呈现语言 + + + 语言 + + + 更改窗体的背景材质 + + + 背景材质 + + + 图片版权信息 + + + 更改窗体的背景图片来源,重启胡桃以尽快生效 + + + 背景图片 + + + 当前背景为本地图片,如遇版权问题由用户个人负责 + + + 图片缓存 在此处存放 + + + 缓存 文件夹 + + + 胡桃通行证 + + + 复制 + + + 创建 + + + 在桌面上创建默认以管理员身份启动的快捷方式 + + + 创建快捷方式 + + + 执行 + + + 危险功能 + + + 除非开发人员明确要求你这么做,否则不应尝试执行下方的操作! + + + 用户数据/元数据 在此处存放 + + + 数据 文件夹 + + + 删除 + + + 若祈愿记录缓存刷新频繁提示验证密钥过期,可以尝试此操作 + + + 删除游戏内网页缓存 + + + 直接删除用户表的所有记录,用于修复特定的账号冲突问题 + + + 删除所有用户 + + + 设备 ID + + + IP:{0} 归属服务器:{1} + + + 设备 IP + + + 管理员模式会影响部分功能的可用性与行为 + + + 管理员模式 + + + 以管理员身份重启 + + + 在祈愿记录页面显示或隐藏无记录的历史祈愿活动 + + + 无记录的历史祈愿活动 + + + 隐藏 + + + 显示 + + + 您解锁了含有违反原神服务条款风险的「启动游戏-高级功能」,将自行承担任何不良后果。 + + + 前往反馈 + + + 祈愿记录 + + + 游戏 + + + 配置 + + + 配置当请求触发人机验证时使用的验证接口 + + + 配置验证请求接口 + + + 无感验证 + + + 选择想要获取公告的游戏服务器 + + + 公告所属服务器 + + + 管理主页仪表板中的卡片 + + + 主页卡片 + + + 成就管理 + + + 实时便笺 + + + 祈愿记录 + + + 启动游戏 + + + 隐藏 + + + 显示 + + + 主页 + + + 三思而后行 + + + 危险操作 + + + 胡桃云服务到期时间 + + + 胡桃通行证账号 + + + 您可以无限制使用任何基于胡桃云服务的功能 + + + 已认证的合作开发者 + + + 登录 + + + 退出登录 + + + 您可以无限制的使用任何测试功能 + + + 胡桃开发/运维 + + + 我们有时会向某些用户赠送胡桃云兑换码 + + + 使用兑换码 + + + 注册 + + + 修改密码 + + + 注销账号 + + + 在完整阅读原神和胡桃工具箱用户协议后,我选择启用「启动游戏-高级功能」 + + + 高级功能 + + + 更改自动连点功能的快捷键 + + + 自动连点 + + + 快捷键 + + + 在通知区域显示图标,以允许执行后台任务,重启后生效 + + + 通知区域图标 + + + 前往官网 + + + 自定义背景图片,支持 bmp / gif / ico / jpg / jpeg / png / tiff / webp 格式 + + + 打开背景图片文件夹 + + + 重置 + + + 重新下载所有图像资源 + + + 重置图片资源 + + + 在启动游戏页面的进程部分加入解锁帧率限制选项 + + + 启动游戏-解锁帧率限制 + + + 更改目录后需要手动移动目录内的数据,否则会重新创建用户数据 + + + 更改数据目录 + + + 设置路径 + + + 游戏路径 + + + 设置游戏路径时,请选择游戏本体(YuanShen.exe 或 GenshinImpact.exe)而不是启动器(launcher.exe) + + + Shell 体验 + + + 赞助我们 + + + 存储空间 + + + 打开 + + + 更改 + + + 评价软件 + + + 更改窗体的颜色主题 + + + 颜色主题 + + + 贡献翻译 + + + 在祈愿记录页面角色与武器页签显示未抽取到的祈愿物品 + + + 未抽取到的祈愿物品 + + + 前往商店 + + + Webview2 运行时 + + + 下半 + + + 上半 + + + 搭配圣遗物 + + + 养成材料 + + + 筛选角色 + + + 汉语 CV + + + 命之座 + + + 衣装 + + + 生日 + + + 英语 CV + + + 料理 + + + 日语 CV + + + 韩语 CV + + + 其它 + + + 所属 + + + 原料理 + + + 资料 + + + 特殊料理 + + + 故事 + + + 天赋 + + + 搭配角色 + + + 搭配武器 + + + 添加到养成计划 + + + 筛选怪物 + + + 掉落物品 + + + 突破后 + + + 筛选武器 + + + 突破前 + + + 登录失败,请重新登录 + + + 立即登录或注册 + + + 控制胡桃启动时是否开启控制台,重启后生效 + + + 调试控制台 + + + 在启动游戏中转换服务器后会产生对应的游戏客户端文件用作缓存 + + + 删除转换服务器缓存 + + + 打开文件夹 + + + 设置 + + + 角色出场率 = 本层上阵该角色次数(层内重复出现只记一次)/ 深渊记录总数 + + + 角色使用率 = 本层上阵该角色次数(层内重复出现只记一次)/ 持有该角色的深渊记录总数 + + + 战斗数据 + + + 战斗次数 + + + 最强一击 + + + 尚未获取任何挑战记录 + + + 最多击破 + + + 分期详情 + + + 元素爆发 + + + 深境螺旋 + + + 本期统计 + + + 最深抵达 + + + 元素战技 + + + 上场角色 + + + 攻击地脉镇石 + + + 刷新数据 + + + 同步米游社的深渊挑战记录 + + + 出战次数 + + + 统计数据 + + + 最多承伤 + + + 获得渊星 + + + 上传数据 + + + 是否立即下载? + + + 下载更新失败 + + + 胡桃 {0} 版本已发布 + + + 是否立即安装? + + + 胡桃 {0} 版本已准备就绪 + + + 自动连点 + + + 正在安装更新 + + + 工具 + + + 米游社 + + + HoYoLAB + + + 当前用户 + + + 旅行工具 + + + 网页登录 + + + 扫码登录 + + + 手动输入 + + + 刷新 Cookie + + + 领取签到奖励 + + + 复制 Cookie + + + 请先登录 + + + 文档 + + + 尚未登录 + + + 刷新 CookieToken 成功 + + + 刷新 CookieToken 失败 + + + 移除用户 + + + 角色 + + + 用户 + + + 我们将为你下载最基本的图像资源 + + + 你可以继续使用电脑,丝毫不受影响 + + + 请勿关闭应用程序 + + + 欢迎使用 胡桃 + + + 角色资料 + + + 怪物资料 + + + 武器资料 + + + (?:(?:〓活动时间〓|〓任务开放时间〓).*?(\d\.\d)版本更新(?:完成|)|&lt;t class=\"t_(?:gl|lc)\".*?&gt;(.*?)&lt;/t&gt;)后永久开放 + + + 〓活动时间〓.*?(\d\.\d)版本期间持续开放 + + + (?:〓活动时间〓|祈愿时间|【上架时间】|〓折扣时间〓).*?(\d\.\d)版本更新后.*?~.*?&lt;t class="t_(?:gl|lc)".*?&gt;(.*?)&lt;/t&gt; + + + 将于&lt;t class=\"t_(?:gl|lc)\".*?&gt;(.*?)&lt;/t&gt;进行版本更新维护 + + + \d\.\d版本更新维护预告 + + + 〓更新时间〓.+?&lt;t class=\"t_(?:gl|lc)\".*?&gt;(.*?)&lt;/t&gt; + + + \d\.\d版本更新说明 + + + {0} 天后开始 + + + {0} 天后结束 + + + {0} 小时后开始 + + + {0} 小时后结束 + + + 打开剪贴板失败 + + + 已复制到剪贴板 + + + 所有魔神任务已完成 + + + 全部完成 + + + 尚未开启 + + + 进行中 + + + 已完成 + + + 禁止领取 + + + 无效 + + + 已领取 + + + 尚未完成 + + + 等待领取 + + + {0} 时 + + + {0} 分 + + + 今日完成委托数量不足 + + + 「每日委托」奖励未领取 + + + 「每日委托」奖励已领取 + + + 预计 {0} {1:HH:mm} 达到存储上限 + + + 尚未解锁洞天 + + + 今天 + + + 明天 + + + 后天 + + + {0} 天 + + + 原粹树脂已完全恢复 + + + 将于 {0} {1:HH:mm} 后全部恢复 + + + 后可再次使用 + + + {0} 天 + + + {0} 时 + + + {0} 分 + + + 尚未获得 + + + 尚未获得参量质变仪 + + + 冷却中 + + + 可使用 + + + 已准备完成 + + + {0} 秒 + + + 验证失败,请手动验证或前往「米游社-旅行工具-原神战绩-实时便笺」页面查看 + + + 错误的 UID 格式 + + + 角色 UID 不存在,请稍候再试 + + + 游戏维护中 + + + 请求过快,请稍后再试 + + + 服务器偶发错误 + + + 服务器严重错误 + + + 未知的服务器错误 + + + 角色活动祈愿 + + + 角色活动祈愿-2 + + + 集录祈愿 + + + 新手祈愿 + + + 常驻祈愿 + + + 武器活动祈愿 + + + 下载链接复制成功 + + + 无效的服务器 + + + 无效的 UID + + + 国服 官方服 + + + 国服 渠道服 + + + 国际服 亚服 + + + 国际服 港澳台服 + + + 国际服 欧服 + + + 国际服 美服 + + + 胡桃服务维护中 + + + 验证失败,请手动验证或前往「米游社-旅行工具-原神战绩」页面查看 + + + 状态:{0} | 信息:{1} + + + 请刷新 Cookie,原始消息:{0} + + + [{0}] 中的 [{1}] 网络请求异常,请稍后再试 + + + 登录失败,请前往 HoYoLAB 初始化账号,原始消息:{0} + + + 显示器编号 + + \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.zh-Hant.resx b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.zh-Hant.resx index 06f36fd7..57bf7253 100644 --- a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.zh-Hant.resx +++ b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.zh-Hant.resx @@ -163,7 +163,7 @@ 清單 - 資料庫已損壞:{0} + 數據庫已損壞:{0} 用户數據已損壞:{0} @@ -172,10 +172,10 @@ 請勿在系統管理員模式下使用此功能 {0} - 無法打開文件選擇器 + 無法打開檔案選擇器 - 權限不足,創建臨時文件失敗 + 權限不足,創建臨時檔案失敗 啟動遊戲 @@ -192,6 +192,18 @@ [{0}] 鍵盤快速鍵 [{1}] 註冊失敗 + + 退出 + + + 啟動遊戲 + + + 胡桃已進入後臺運行 + + + 窗口 + 深色 @@ -271,7 +283,7 @@ 國際伺服器 - 網路連線錯誤 + 網絡異常 尚未重新整理 @@ -340,7 +352,7 @@ 蘿莉 - 成年男子 + 成男 @@ -409,7 +421,7 @@ Need EXACT same string in game - 旅人 + 旅行者 {0} 月 {1} 日 @@ -540,7 +552,7 @@ 精煉 {0} 階 - 必须登入 米遊社/HoYoLAB 並選定一個用戶與角色 + 必須登入 米游社/ HoYoLAB 並選擇一個用戶與角色 刪除了 UID:{0} 的 {1} 筆祈願記錄 @@ -573,25 +585,25 @@ 新密碼設定成功 - 當前郵箱尚未註冊 + 當前電子郵件地址尚未註冊 - 當前郵箱已被註冊 + 當前電子郵件地址已被註冊 註冊失敗,伺服器異常,請盡快聯繫開發者解決 - 使用者不存在,刪除帳號失敗 + 用戶不存在,刪除帳號失敗 - 使用者刪除成功 + 用戶刪除成功 - 使用者不存在,獲取使用者信息失敗 + 用戶不存在,獲取用戶信息失敗 - 使用者名稱或密碼錯誤 + 用戶名稱或密碼錯誤 驗證失敗 @@ -600,10 +612,10 @@ 驗證請求失敗,不是當前登入的帳號 - 驗證碼已發送至郵箱 + 驗證碼已發送至信箱 - 驗證請求失敗,當前郵箱已被註冊 + 驗證請求失敗,當前電子郵件地址已被註冊 驗證請求過快,請 1 分鐘後再試 @@ -639,7 +651,7 @@ 上傳深淵記錄成功,但未登入胡桃通行證,無法獲贈祈願記錄上傳服務時長 - 上傳深淵記錄成功,但無法找到使用者,無法獲贈祈願記錄上傳服務時長 + 上傳深淵記錄成功,但無法找到用戶,無法獲贈祈願記錄上傳服務時長 上傳深淵記錄成功,但不是本期首次提交,無法獲贈祈願記錄上傳服務時長 @@ -651,7 +663,7 @@ UIAF Json 檔案 - 打開 UIAF Json 文件 + 打開 UIAF Json 檔案 單個成就存檔內發現多個相同的成就 Id @@ -771,10 +783,10 @@ 養成計算:{0:MM-dd HH:mm} - 原神戰績:尚未重新整理 + 戰績:尚未重新整理 - 原神戰績:{0:MM-dd HH:mm} + 戰績:{0:MM-dd HH:mm} 角色櫥窗:尚未重新整理 @@ -843,7 +855,7 @@ 目前原粹樹脂:{0} - 實時便箋提醒 + 即時便箋提醒 參數質變儀 @@ -894,7 +906,7 @@ 請求驗證密鑰失敗 - 未正確提供原神路徑,或目前設置的路徑不正確 + 未正確提供原神路徑,或目前設定的路徑不正確 找不到原神內置瀏覽器緩存路徑:\n{0} @@ -915,13 +927,13 @@ 不支持的 Item Id:{0} - UIGF 文件的語言:{0} 與胡桃的語言:{1} 不對應,請切換到對應語言重試 + UIGF 檔案的語言:{0} 與胡桃的語言:{1} 不對應,請切換到對應語言重試 存在多個匹配賬號,請刪除重複的賬號 - 文件系統權限不足,無法轉換伺服器 + 檔案系統權限不足,無法轉換伺服器 下載遊戲資源索引 @@ -969,10 +981,10 @@ 遊戲本體 - 找不到 Unity 日誌文件 + 找不到 Unity 日誌檔案 - 在 Unity 日誌文件中無法找到遊戲路徑 + 在 Unity 日誌檔案中無法找到遊戲路徑 備份:{0} @@ -984,7 +996,7 @@ 替換:{0} - 重新命名資料文件夾名稱失敗 + 重新命名資料檔案夾名稱失敗 正在獲取 Package Version @@ -993,7 +1005,7 @@ 獲取 Package Version 失敗 - 下載客戶端文件失敗:{0} + 下載客戶端檔案失敗:{0} 無法找到遊戲本體路徑,請前往設定修改 @@ -1005,7 +1017,7 @@ 無法讀取遊戲設定檔 {0},可能是檔案不存在 - 無法讀取或儲存配置文件,請用系統管理員模式重試 + 無法讀取或儲存配置檔案,請用系統管理員模式重試 在尋找必要的模組時遇到問題:無法讀取任何模組,可能是保護驅動已經載入完成,請重試 @@ -1026,19 +1038,19 @@ 祈願紀錄上傳服務有效期至\n{0:yyyy.MM.dd HH:mm:ss} - 無法找到暫存的元數據文件 + 無法找到暫存的元數據檔案 - HTTP {0} | Error:{1}:元資料校驗文件下載失敗 + HTTP {0} | Error:{1}:元資料校驗檔案下載失敗 元數據服務未初始化或初始化失敗 - 元數據文件解析失敗 + 元數據校驗檔案解析失敗 - 元數據文件下載失敗 + 元數據校驗檔案下載失敗 你的胡桃版本過低,請盡快升級 @@ -1053,7 +1065,7 @@ 獲取獎勵清單失敗 - 驗證失敗,請前往HoYoLAB原神簽到頁面自行領取獎勵 + 驗證失敗,請前往 HoYoLAB 原神簽到頁面自行領取獎勵 簽到成功,{0}×{1} @@ -1065,7 +1077,7 @@ 發現新版本 {0} - 已选中多条用户记录 + 多個用戶記錄為選中狀態 用戶 {0} 狀態儲存失敗 @@ -1167,7 +1179,7 @@ 在此處輸入 - 設置成就存檔的名稱 + 設定成就存檔的名稱 匯入模式 @@ -1230,7 +1242,7 @@ 在主頁顯示卡片 - 實時便箋通知設置 + 即時便箋通知設定 參數質變儀提醒 @@ -1335,10 +1347,10 @@ 為帳號命名 - 請選擇當前遊戲路徑對應的遊戲服務器 + 請選擇當前遊戲路徑對應的遊戲伺服器 - 正在修複配置文件 + 正在修複配置檔案 轉換可能需要花費一段時間,請勿關閉胡桃 @@ -1347,7 +1359,7 @@ 正在轉換客戶端 - 使用米遊社掃描 QR 碼 + 使用米游社掃描 QR 碼 為防止你在無意間啟用,請輸入正在啟用的功能開關的<b>標題名稱</b> @@ -1362,19 +1374,19 @@ 是否永久刪除用戶數據 - 前往登录 + 前往登入畫面 - 当前未登录胡桃账号,上传深渊数据无法获赠胡桃云时长 + 當前未登入胡桃賬號,上傳深淵數據無法獲贈胡桃雲時長 - 继续上传 + 繼續上傳 - 上传深渊数据 + Загрузите данные о Бездне - 查看更新日志 + 查看更新日誌 立即前往 @@ -1416,10 +1428,10 @@ 用戶使用協議與法律聲明 - 基礎設置 + 基礎設定 - 稍後可以在設置中修改 + 稍後可以在設定中修改 文檔 @@ -1449,10 +1461,10 @@ 資源 - 圖像資源設置 + 圖像資源設定 - * 除非你卸載並重新安裝胡桃,否則你將無法更改這些設置 + * 除非你卸載並重新安裝胡桃,否則你將無法更改這些設定 圖片資源包體 @@ -1556,11 +1568,17 @@ 不能新增名稱無效的計劃 + + 此操作不可逆,此計劃的養成物品與背包材料將會丟失 + + + 確定要刪除當前計劃嗎? + 即時便箋 Webhook URL 配置成功 - HoYoLAB 賬號不支持驗證實时便箋 + HoYoLAB 賬號不支持驗證即時便箋 修改計劃任務失敗 @@ -1581,7 +1599,7 @@ 8 分鐘 | 1 樹脂 - 正在獲取實時便箋信息,請稍候 + 正在獲取即時便箋信息,請稍候 成功儲存至指定位置 @@ -1590,13 +1608,13 @@ 匯出成功 - 寫入文件時遇到問題 + 寫入檔案時遇到問題 匯出失敗 - UIFG JSON 文件 + UIFG JSON 檔案 匯入完成 @@ -1653,7 +1671,7 @@ 下一步 - 下載資源文件中,請稍候 + 下載資源檔案中,請稍候 高品質 @@ -1662,7 +1680,7 @@ 原圖 - 請輸入正確的郵箱 + 請輸入正確的電子郵件地址 剪貼板中的文本格式不正塙 @@ -1680,7 +1698,7 @@ 切換伺服器失敗 - 修複配置文件 + 修複配置檔案 修複完成 @@ -1710,7 +1728,7 @@ 操作完成 - 清除失敗,文件目錄權限不足,請使用系統管理員模式重試 + 清除失敗,檔案目錄權限不足,請使用系統管理員模式重試 清除失敗,找不到目錄:{0} @@ -1737,7 +1755,7 @@ 無感驗證復合 URL 配置成功 - 正在重置图片资源 + 正在重設圖片資源 設置數據目錄成功,重新啟動以應用更改 @@ -1782,7 +1800,7 @@ 待處理 - 文件下載異常 + 檔案下載異常 建立新存檔 @@ -1797,7 +1815,7 @@ 從剪貼簿匯入 - 從 UIAF 文件匯入 + 從 UIAF 檔案匯入 匯入 @@ -1860,7 +1878,7 @@ 同步角色天賦信息 - 從米遊社原神戰績同步 + 從 HoYoLAB 戰績同步 同步角色天賦外的大部分信息 @@ -1946,6 +1964,9 @@ 通知設定 + + 胡桃的通知權限已被關閉 + 立即重新整理 @@ -1968,7 +1989,7 @@ 自動重新整理 - 間隔選定的時間後重新整理添加的實時便箋 + 間隔選定的時間後重新整理添加的即時便箋 這些選項僅允許在非系統管理員模式下更改 @@ -1976,6 +1997,9 @@ 重新整理 + + 為啟用通知區域圖標,關閉窗口後自動重新整理將不會執行 + 在我游玩原神時不通知我 @@ -2079,7 +2103,7 @@ 輸入 - 從胡桃云恢復祈願紀錄 + 從胡桃雲恢復祈願紀錄 重新整理 @@ -2229,7 +2253,7 @@ 刪除帳號的數據將永遠丢失,無法恢復 - 請輸入電郵地址 + 請輸入電子郵件地址 取得驗證碼 @@ -2367,7 +2391,7 @@ 綁定當前用戶的角色 - 在游戲内切換賬號,網絡環境發生變化后需要重新手動檢測 + 在游戲内切換賬號,網絡環境發生變化後需要重新手動檢測 檢測 @@ -2382,7 +2406,7 @@ 重新命名 - 切換遊戲伺服器(陸服/渠道服/國際服) + 切換遊戲伺服器(大陸伺服器/渠道伺服器/國際伺服器) 伺服器 @@ -2412,7 +2436,7 @@ 請輸入您的 HoYoLAB UID - 你正在通過由我們提供的內嵌網頁視圖登錄 米哈遊通行證,我們會在你點擊 我已登錄 按鈕後,讀取你的 Cookie 信息,由此視圖髪起的網絡通信只髪生於你的計算機與米哈遊服務器之間 + 你正在通過由我們提供的內嵌網頁視圖登入 miHoYo 通行證賬號,我們會在你點擊 我已登入 按鈕後,讀取你的 Cookie 信息,由此視圖發起的網絡通信只發生於你的計算機與 miHoYo 服務器之間 我已登入 @@ -2421,7 +2445,7 @@ 在下方登入 miHoYo 通行證賬號 - 開啟截圖資料夾 + 開啟截圖檔案夾 選定遊戲路徑 @@ -2460,7 +2484,7 @@ 圖片暫存存放在此 - 暫存檔案夾 + 暫存 檔案夾 胡桃通行證 @@ -2490,7 +2514,7 @@ 用戶數據/元數據 存放在此 - 資料檔案夾 + 資料 檔案夾 刪除 @@ -2577,7 +2601,7 @@ 成就管理 - 實時便籤 + 即時便籤 祈願紀錄 @@ -2640,7 +2664,7 @@ 刪除帳號 - 在完整閱讀原神和胡桃工具箱使用者協定後,我選擇啟用「啟動遊戲 - 進階功能」 + 在完整閱讀原神和胡桃工具箱用戶協定後,我選擇啟用「啟動遊戲 - 進階功能」 進階功能 @@ -2654,6 +2678,12 @@ 快速鍵 + + 在通知區域顯示圖標,以允許執行後臺任務,重新啟動後生效 + + + 通知區域圖標 + 前往官網 @@ -2661,7 +2691,7 @@ 自定義背景圖片,支援 bmp / gif / ico / jpg / jpeg / png / tiff / webp 格式 - 打開背景圖片資料夾 + 打開背景圖片檔案夾 重設 @@ -2691,7 +2721,7 @@ 遊戲路徑 - 設置遊戲路徑時,請選擇遊戲本體(YuanShen.exe 或 GenshinImpact.exe) 而不是啟動器(launcher.exe) + 設定遊戲路徑時,請選擇遊戲本體(YuanShen.exe 或 GenshinImpact.exe) 而不是啟動器(launcher.exe) Shell 體驗 @@ -2895,7 +2925,7 @@ 出戰次數 - 統計數據 + 統計資料 最多承傷 @@ -2907,7 +2937,7 @@ 上傳資料 - 是否立即下载? + 是否立即下載? 下載更新失敗 @@ -3006,19 +3036,19 @@ 武器資料 - (?:〓活动时间〓|〓任务开放时间〓).*?(\d\.\d)版本更新(?:完成|)后永久开放 + (?:(?:〓活動時間〓|〓任務開放時間〓).*?(\d\.\d)版本更新(?:完成|)|&lt;t class=\"t_(?:gl|lc)\".*?&gt;(.*?)&lt;/t&gt;)後永久開放 - 〓活动时间〓.*?(\d\.\d)版本期间持续开放 + 〓活動時間〓.*?(\d\.\d)版本期間持續開放 - (?:〓活动时间〓|祈愿时间|【上架时间】|〓折扣时间〓).*?(\d\.\d)版本更新后.*?~.*?&lt;t class="t_(?:gl|lc)".*?&gt;(.*?)&lt;/t&gt; + (?:〓活動時間〓|祈願時間|【上架時間】|〓折扣時間〓).*?(\d\.\d)版本更新後.*?~.*?&lt;t class="t_(?:gl|lc)".*?&gt;(.*?)&lt;/t&gt; - 将于&lt;t class=\"t_(?:gl|lc)\".*?&gt;(.*?)&lt;/t&gt;进行版本更新维护 + 將於&lt;t class=\"t_(?:gl|lc)\".*?&gt;(.*?)&lt;/t&gt;進行版本更新維護 - \d\.\d版本更新维护预告 + \d\.\d版本更新停服說明 〓更新時間〓.+?&lt;t class=\"t_(?:gl|lc)\".*?&gt;(.*?)&lt;/t&gt; @@ -3044,6 +3074,9 @@ 已複製到剪貼簿 + + 所有魔神任務已完成 + 全部完成 @@ -3141,7 +3174,7 @@ {0} 秒 - 驗證失敗,請手動進行驗證或前往「米遊社-旅行工具-原神戰績-實時便箋」頁面查看。 + 驗證失敗,請手動進行驗證或前往「 HoYoLAB -工具箱-戰績-即時便箋」頁面查看。 錯誤的 UID 格式 @@ -3192,10 +3225,10 @@ 無效的 UID - 陸服 官方服 + 大陸伺服器 官方伺服器 - 陸服 渠道服 + 大陸伺服器 渠道伺服器 國際服 亞服 @@ -3213,7 +3246,7 @@ 胡桃服務維護中 - 驗證失敗,請手動進行驗證或前往「米遊社-旅行工具-原神戰績」頁面查看。 + 驗證失敗,請手動進行驗證或前往「 HoYoLAB -工具箱-戰績」頁面查看。 狀態:{0} | 信息:{1} @@ -3224,6 +3257,9 @@ [{0}] 中的 [{1}] 網路請求異常,請稍後再試 + + 登入失敗,請前往 HoYoLAB 初始化賬號,原始消息:{0} + 顯示器編號 From 4ce064a71a576c337d58334d5ca6f83d7b8289e8 Mon Sep 17 00:00:00 2001 From: Lightczx <1686188646@qq.com> Date: Tue, 28 May 2024 17:28:53 +0800 Subject: [PATCH 09/68] Add Vietnamese and fix guide maximized state --- .../Windowing/NotifyIcon/NotifyIconContextMenu.xaml.cs | 3 ++- src/Snap.Hutao/Snap.Hutao/GuideWindow.xaml.cs | 7 +++++++ src/Snap.Hutao/Snap.Hutao/Service/SupportedCultures.cs | 2 +- src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj | 3 ++- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/NotifyIcon/NotifyIconContextMenu.xaml.cs b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/NotifyIcon/NotifyIconContextMenu.xaml.cs index 4b28f518..de02e04f 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/NotifyIcon/NotifyIconContextMenu.xaml.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/NotifyIcon/NotifyIconContextMenu.xaml.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. using Microsoft.UI.Xaml.Controls; +using Snap.Hutao.Control.Extension; using Snap.Hutao.ViewModel; namespace Snap.Hutao.Core.Windowing.NotifyIcon; @@ -12,6 +13,6 @@ internal sealed partial class NotifyIconContextMenu : Flyout { AllowFocusOnInteraction = false; InitializeComponent(); - Root.DataContext = serviceProvider.GetRequiredService(); + Root.InitializeDataContext(serviceProvider); } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/GuideWindow.xaml.cs b/src/Snap.Hutao/Snap.Hutao/GuideWindow.xaml.cs index 59f8e60d..a5bbcb56 100644 --- a/src/Snap.Hutao/Snap.Hutao/GuideWindow.xaml.cs +++ b/src/Snap.Hutao/Snap.Hutao/GuideWindow.xaml.cs @@ -1,6 +1,7 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. +using Microsoft.UI.Windowing; using Microsoft.UI.Xaml; using Snap.Hutao.Core.Setting; using Snap.Hutao.Core.Windowing; @@ -28,6 +29,12 @@ internal sealed partial class GuideWindow : Window, public GuideWindow(IServiceProvider serviceProvider) { InitializeComponent(); + + if (AppWindow.Presenter is OverlappedPresenter presenter) + { + presenter.IsMaximizable = false; + } + this.InitializeController(serviceProvider); } diff --git a/src/Snap.Hutao/Snap.Hutao/Service/SupportedCultures.cs b/src/Snap.Hutao/Snap.Hutao/Service/SupportedCultures.cs index 6940404d..345cabd2 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/SupportedCultures.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/SupportedCultures.cs @@ -24,7 +24,7 @@ internal static class SupportedCultures ToNameValue(CultureInfo.GetCultureInfo("ru")), /*ToNameValue(CultureInfo.GetCultureInfo("th")),*/ /*ToNameValue(CultureInfo.GetCultureInfo("tr")),*/ - /*ToNameValue(CultureInfo.GetCultureInfo("vi")),*/ + ToNameValue(CultureInfo.GetCultureInfo("vi")), ]; public static List> Get() diff --git a/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj b/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj index 0b27ec8a..57c4d436 100644 --- a/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj +++ b/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj @@ -223,6 +223,7 @@ + @@ -339,7 +340,7 @@ all runtime; build; native; contentfiles; analyzers - + all runtime; build; native; contentfiles; analyzers; buildtransitive From f7723d21a3415a5900f4a76040e60ea3e9dc552e Mon Sep 17 00:00:00 2001 From: qhy040404 Date: Tue, 28 May 2024 17:50:48 +0800 Subject: [PATCH 10/68] [skip ci] fix unexpected canceled workflow --- .github/workflows/alpha.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/alpha.yml b/.github/workflows/alpha.yml index 9577c104..b9a8c6a5 100644 --- a/.github/workflows/alpha.yml +++ b/.github/workflows/alpha.yml @@ -32,6 +32,7 @@ jobs: runs-on: ${{ matrix.runner }} strategy: + fail-fast: false matrix: runner: - self-hosted From e5c751771c89edf3432dbe06e216739bf3b2f728 Mon Sep 17 00:00:00 2001 From: DismissedLight <1686188646@qq.com> Date: Tue, 28 May 2024 22:34:32 +0800 Subject: [PATCH 11/68] avoid exception when Shell_TrayWnd not ready --- .../Core/Windowing/XamlWindowController.cs | 11 ++- .../View/Page/AnnouncementPage.xaml | 91 ++++++++++--------- .../Snap.Hutao/View/Page/SettingPage.xaml | 2 +- 3 files changed, 56 insertions(+), 48 deletions(-) diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/XamlWindowController.cs b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/XamlWindowController.cs index 816af2c2..e8077df1 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/XamlWindowController.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/XamlWindowController.cs @@ -131,8 +131,16 @@ internal sealed class XamlWindowController } } - private unsafe bool IsNotifyIconVisible() + private bool IsNotifyIconVisible() { + // Shell_NotifyIconGetRect returns E_FAIL when Shell_TrayWnd is not present, + // We pre-check it to avoid the exception. + HWND shellTrayWnd = FindWindowExW(default, default, "Shell_TrayWnd", default); + if (shellTrayWnd == default) + { + return false; + } + RECT iconRect = serviceProvider.GetRequiredService().GetRect(); if (UniversalApiContract.IsPresent(WindowsVersion.Windows11)) @@ -141,7 +149,6 @@ internal sealed class XamlWindowController return IntersectRect(out _, in primaryRect, in iconRect); } - HWND shellTrayWnd = FindWindowExW(default, default, "Shell_TrayWnd", default); HWND trayNotifyWnd = FindWindowExW(shellTrayWnd, default, "TrayNotifyWnd", default); HWND button = FindWindowExW(trayNotifyWnd, default, "Button", default); diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/AnnouncementPage.xaml b/src/Snap.Hutao/Snap.Hutao/View/Page/AnnouncementPage.xaml index 4304f903..3f809ced 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Page/AnnouncementPage.xaml +++ b/src/Snap.Hutao/Snap.Hutao/View/Page/AnnouncementPage.xaml @@ -64,20 +64,19 @@ - - + - - - + Background="Transparent" + CornerRadius="0" + Maximum="1" + Value="{Binding TimePercent, Mode=OneWay}"/> + @@ -123,6 +122,7 @@ + @@ -207,44 +207,45 @@ - - - + + + + + + - + - - - - - - - - - + + + + + + + + - + From 3948b81a483c292411abe6acafd2ad4b524638f5 Mon Sep 17 00:00:00 2001 From: Lightczx <1686188646@qq.com> Date: Wed, 29 May 2024 14:29:33 +0800 Subject: [PATCH 12/68] fix #1657 --- .../Abstraction/IXamlWindowHasInitSize.cs | 2 ++ .../Core/Windowing/XamlWindowController.cs | 14 +++++++++----- src/Snap.Hutao/Snap.Hutao/GuideWindow.xaml.cs | 2 ++ src/Snap.Hutao/Snap.Hutao/LaunchGameWindow.xaml.cs | 2 ++ src/Snap.Hutao/Snap.Hutao/MainWindow.xaml.cs | 2 ++ 5 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/Abstraction/IXamlWindowHasInitSize.cs b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/Abstraction/IXamlWindowHasInitSize.cs index 1aad4d24..49d2d6ce 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/Abstraction/IXamlWindowHasInitSize.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/Abstraction/IXamlWindowHasInitSize.cs @@ -8,4 +8,6 @@ namespace Snap.Hutao.Core.Windowing.Abstraction; internal interface IXamlWindowHasInitSize { SizeInt32 InitSize { get; } + + SizeInt32 MinSize { get; } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/XamlWindowController.cs b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/XamlWindowController.cs index e8077df1..bb6717c4 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/XamlWindowController.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/XamlWindowController.cs @@ -237,15 +237,18 @@ internal sealed class XamlWindowController private void RecoverOrInitWindowSize(IXamlWindowHasInitSize xamlWindow) { double scale = window.GetRasterizationScale(); - SizeInt32 scaledSize = xamlWindow.InitSize.Scale(scale); - RectInt32 rect = StructMarshal.RectInt32(scaledSize); + RectInt32 rect = StructMarshal.RectInt32(xamlWindow.InitSize.Scale(scale)); if (window is IXamlWindowRectPersisted rectPersisted) { - RectInt32 persistedRect = (CompactRect)LocalSetting.Get(rectPersisted.PersistRectKey, (CompactRect)rect); - if (persistedRect.Size() >= xamlWindow.InitSize.Size()) + RectInt32 nonDpiPersistedRect = (CompactRect)LocalSetting.Get(rectPersisted.PersistRectKey, (CompactRect)rect); + RectInt32 persistedRect = nonDpiPersistedRect.Scale(scale); + + // If the persisted size is less than min size, we want to reset to the init size. + // So we only recover the size when it's greater than or equal to the min size. + if (persistedRect.Size() >= xamlWindow.MinSize.Size()) { - rect = persistedRect.Scale(scale); + rect = persistedRect; } } @@ -261,6 +264,7 @@ internal sealed class XamlWindowController // prevent save value when we are maximized. if (!windowPlacement.ShowCmd.HasFlag(SHOW_WINDOW_CMD.SW_SHOWMAXIMIZED)) { + // We save the non-dpi rect here double scale = 1.0 / window.GetRasterizationScale(); LocalSetting.Set(rectPersisted.PersistRectKey, (CompactRect)window.AppWindow.GetRect().Scale(scale)); } diff --git a/src/Snap.Hutao/Snap.Hutao/GuideWindow.xaml.cs b/src/Snap.Hutao/Snap.Hutao/GuideWindow.xaml.cs index a5bbcb56..fedb4351 100644 --- a/src/Snap.Hutao/Snap.Hutao/GuideWindow.xaml.cs +++ b/src/Snap.Hutao/Snap.Hutao/GuideWindow.xaml.cs @@ -44,6 +44,8 @@ internal sealed partial class GuideWindow : Window, public SizeInt32 InitSize { get; } = new(MinWidth, MinHeight); + public SizeInt32 MinSize { get; } = new(MinWidth, MinHeight); + public unsafe void HandleMinMaxInfo(ref MINMAXINFO info, double scalingFactor) { info.ptMinTrackSize.x = (int)Math.Max(MinWidth * scalingFactor, info.ptMinTrackSize.x); diff --git a/src/Snap.Hutao/Snap.Hutao/LaunchGameWindow.xaml.cs b/src/Snap.Hutao/Snap.Hutao/LaunchGameWindow.xaml.cs index f661b2aa..71f93653 100644 --- a/src/Snap.Hutao/Snap.Hutao/LaunchGameWindow.xaml.cs +++ b/src/Snap.Hutao/Snap.Hutao/LaunchGameWindow.xaml.cs @@ -47,6 +47,8 @@ internal sealed partial class LaunchGameWindow : Window, public SizeInt32 InitSize { get; } = new(MaxWidth, MaxHeight); + public SizeInt32 MinSize { get; } = new(MinWidth, MinHeight); + /// public void Dispose() { diff --git a/src/Snap.Hutao/Snap.Hutao/MainWindow.xaml.cs b/src/Snap.Hutao/Snap.Hutao/MainWindow.xaml.cs index 5e49f7e9..54e0e4c9 100644 --- a/src/Snap.Hutao/Snap.Hutao/MainWindow.xaml.cs +++ b/src/Snap.Hutao/Snap.Hutao/MainWindow.xaml.cs @@ -39,6 +39,8 @@ internal sealed partial class MainWindow : Window, public SizeInt32 InitSize { get; } = new(1200, 741); + public SizeInt32 MinSize { get; } = new(MinWidth, MinHeight); + /// public unsafe void HandleMinMaxInfo(ref MINMAXINFO pInfo, double scalingFactor) { From 75287473c56e68468b55192f8c4cfc94857e7832 Mon Sep 17 00:00:00 2001 From: Lightczx <1686188646@qq.com> Date: Thu, 30 May 2024 10:39:20 +0800 Subject: [PATCH 13/68] adjust notifyicon logic and impl #1656 --- src/Snap.Hutao/Snap.Hutao/App.xaml.cs | 3 ++- .../Snap.Hutao/Core/LifeCycle/AppActivation.cs | 15 ++++++++++++--- .../Core/LifeCycle/HutaoActivationArguments.cs | 12 ++++++++++++ .../Core/LifeCycle/HutaoActivationKind.cs | 1 + .../Windowing/NotifyIcon/NotifyIconController.cs | 1 + .../NotifyIcon/NotifyIconMessageWindow.cs | 3 +++ src/Snap.Hutao/Snap.Hutao/Package.appxmanifest | 4 ++-- .../Snap.Hutao/Package.development.appxmanifest | 4 ++-- .../Snap.Hutao/View/Page/AnnouncementPage.xaml | 3 ++- 9 files changed, 37 insertions(+), 9 deletions(-) diff --git a/src/Snap.Hutao/Snap.Hutao/App.xaml.cs b/src/Snap.Hutao/Snap.Hutao/App.xaml.cs index ad1a653f..1cdc4086 100644 --- a/src/Snap.Hutao/Snap.Hutao/App.xaml.cs +++ b/src/Snap.Hutao/Snap.Hutao/App.xaml.cs @@ -72,6 +72,7 @@ public sealed partial class App : Application if (serviceProvider.GetRequiredService().TryRedirectActivationTo(activatedEventArgs)) { + logger.LogDebug("Application exiting on RedirectActivationTo"); Exit(); return; } @@ -85,7 +86,7 @@ public sealed partial class App : Application } catch (Exception ex) { - Debug.WriteLine(ex); + logger.LogError(ex, "Application failed in App.OnLaunched"); Process.GetCurrentProcess().Kill(); } } diff --git a/src/Snap.Hutao/Snap.Hutao/Core/LifeCycle/AppActivation.cs b/src/Snap.Hutao/Snap.Hutao/Core/LifeCycle/AppActivation.cs index 8304f4b0..ee82add7 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/LifeCycle/AppActivation.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/LifeCycle/AppActivation.cs @@ -52,7 +52,7 @@ internal sealed partial class AppActivation : IAppActivation, IAppActivationActi { // Before activate, we try to redirect to the opened process in App, // And we check if it's a toast activation. - if (ToastNotificationManagerCompat.WasCurrentProcessToastActivated()) + if (args.Kind is HutaoActivationKind.Toast) { return; } @@ -188,7 +188,12 @@ internal sealed partial class AppActivation : IAppActivation, IAppActivationActi if (UnsafeLocalSetting.Get(SettingKeys.Major1Minor10Revision0GuideState, GuideState.Language) < GuideState.Completed) { await taskContext.SwitchToMainThreadAsync(); - currentWindowReference.Window = serviceProvider.GetRequiredService(); + + GuideWindow guideWindow = serviceProvider.GetRequiredService(); + currentWindowReference.Window = guideWindow; + + guideWindow.SwitchTo(); + guideWindow.BringToForeground(); } else { @@ -205,7 +210,11 @@ internal sealed partial class AppActivation : IAppActivation, IAppActivationActi await taskContext.SwitchToMainThreadAsync(); - currentWindowReference.Window = serviceProvider.GetRequiredService(); + MainWindow mainWindow = serviceProvider.GetRequiredService(); + currentWindowReference.Window = mainWindow; + + mainWindow.SwitchTo(); + mainWindow.BringToForeground(); await taskContext.SwitchToBackgroundAsync(); diff --git a/src/Snap.Hutao/Snap.Hutao/Core/LifeCycle/HutaoActivationArguments.cs b/src/Snap.Hutao/Snap.Hutao/Core/LifeCycle/HutaoActivationArguments.cs index 5c3ce973..41b8dedb 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/LifeCycle/HutaoActivationArguments.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/LifeCycle/HutaoActivationArguments.cs @@ -1,6 +1,7 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. +using Microsoft.Extensions.Primitives; using Microsoft.Windows.AppLifecycle; namespace Snap.Hutao.Core.LifeCycle; @@ -9,6 +10,8 @@ internal sealed class HutaoActivationArguments { public bool IsRedirectTo { get; set; } + public bool IsToastActivated { get; set; } + public HutaoActivationKind Kind { get; set; } public Uri? ProtocolActivatedUri { get; set; } @@ -30,6 +33,15 @@ internal sealed class HutaoActivationArguments if (args.TryGetLaunchActivatedArguments(out string? arguments)) { result.LaunchActivatedArguments = arguments; + + foreach (StringSegment segment in new StringTokenizer(arguments, [' '])) + { + if (segment.AsSpan().SequenceEqual("-ToastActivated")) + { + result.Kind = HutaoActivationKind.Toast; + break; + } + } } break; diff --git a/src/Snap.Hutao/Snap.Hutao/Core/LifeCycle/HutaoActivationKind.cs b/src/Snap.Hutao/Snap.Hutao/Core/LifeCycle/HutaoActivationKind.cs index 031fec97..66211290 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/LifeCycle/HutaoActivationKind.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/LifeCycle/HutaoActivationKind.cs @@ -7,5 +7,6 @@ internal enum HutaoActivationKind { None, Launch, + Toast, Protocol, } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/NotifyIcon/NotifyIconController.cs b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/NotifyIcon/NotifyIconController.cs index b8570522..6f924ebb 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/NotifyIcon/NotifyIconController.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/NotifyIcon/NotifyIconController.cs @@ -37,6 +37,7 @@ internal sealed class NotifyIconController : IDisposable { TaskbarCreated = OnRecreateNotifyIconRequested, ContextMenuRequested = OnContextMenuRequested, + IconSelected = OnContextMenuRequested, }; CreateNotifyIcon(); diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/NotifyIcon/NotifyIconMessageWindow.cs b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/NotifyIcon/NotifyIconMessageWindow.cs index 506e118a..29b2b002 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/NotifyIcon/NotifyIconMessageWindow.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/NotifyIcon/NotifyIconMessageWindow.cs @@ -62,6 +62,8 @@ internal sealed class NotifyIconMessageWindow : IDisposable public Action? ContextMenuRequested { get; set; } + public Action? IconSelected { get; set; } + public HWND HWND { get; } public void Dispose() @@ -116,6 +118,7 @@ internal sealed class NotifyIconMessageWindow : IDisposable break; case NIN_SELECT: // X: wParam2.X Y: wParam2.Y Low: NIN_SELECT + window.IconSelected?.Invoke(window, wParam2); break; case NIN_POPUPOPEN: // X: wParam2.X Y: 0? Low: NIN_POPUPOPEN diff --git a/src/Snap.Hutao/Snap.Hutao/Package.appxmanifest b/src/Snap.Hutao/Snap.Hutao/Package.appxmanifest index 0d25e486..0aa319b1 100644 --- a/src/Snap.Hutao/Snap.Hutao/Package.appxmanifest +++ b/src/Snap.Hutao/Snap.Hutao/Package.appxmanifest @@ -46,12 +46,12 @@ - + - + diff --git a/src/Snap.Hutao/Snap.Hutao/Package.development.appxmanifest b/src/Snap.Hutao/Snap.Hutao/Package.development.appxmanifest index af410fe2..388af5d2 100644 --- a/src/Snap.Hutao/Snap.Hutao/Package.development.appxmanifest +++ b/src/Snap.Hutao/Snap.Hutao/Package.development.appxmanifest @@ -46,12 +46,12 @@ - + - + diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/AnnouncementPage.xaml b/src/Snap.Hutao/Snap.Hutao/View/Page/AnnouncementPage.xaml index 3f809ced..061fbf99 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Page/AnnouncementPage.xaml +++ b/src/Snap.Hutao/Snap.Hutao/View/Page/AnnouncementPage.xaml @@ -174,7 +174,7 @@ From c9ea4b358a53eea80ca1c3690a86059e7421a8c4 Mon Sep 17 00:00:00 2001 From: Lightczx <1686188646@qq.com> Date: Thu, 30 May 2024 11:28:06 +0800 Subject: [PATCH 14/68] fix #1650 --- .../Control/Theme/InfoBarOverride.xaml | 11 +++- .../Core/LifeCycle/AppActivation.cs | 58 ++++++++++--------- .../ViewModel/Setting/SettingViewModel.cs | 2 +- 3 files changed, 42 insertions(+), 29 deletions(-) diff --git a/src/Snap.Hutao/Snap.Hutao/Control/Theme/InfoBarOverride.xaml b/src/Snap.Hutao/Snap.Hutao/Control/Theme/InfoBarOverride.xaml index e09f672d..4151e2af 100644 --- a/src/Snap.Hutao/Snap.Hutao/Control/Theme/InfoBarOverride.xaml +++ b/src/Snap.Hutao/Snap.Hutao/Control/Theme/InfoBarOverride.xaml @@ -128,6 +128,7 @@ @@ -236,7 +238,14 @@ - + + + + + + + diff --git a/src/Snap.Hutao/Snap.Hutao/Core/LifeCycle/AppActivation.cs b/src/Snap.Hutao/Snap.Hutao/Core/LifeCycle/AppActivation.cs index ee82add7..81052e07 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/LifeCycle/AppActivation.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/LifeCycle/AppActivation.cs @@ -164,47 +164,51 @@ internal sealed partial class AppActivation : IAppActivation, IAppActivationActi { default: { - await HandleNormalLaunchActionAsync().ConfigureAwait(false); + await HandleNormalLaunchActionAsync(args.IsRedirectTo).ConfigureAwait(false); break; } } } } - private async ValueTask HandleNormalLaunchActionAsync() + private async ValueTask HandleNormalLaunchActionAsync(bool isRedirectTo) { - // Increase launch times - LocalSetting.Update(SettingKeys.LaunchTimes, 0, x => unchecked(x + 1)); - - // If the guide is completed, we check if there's any unfulfilled resource category present. - if (UnsafeLocalSetting.Get(SettingKeys.Major1Minor10Revision0GuideState, GuideState.Language) >= GuideState.StaticResourceBegin) + if (!isRedirectTo) { - if (StaticResource.IsAnyUnfulfilledCategoryPresent()) + // Increase launch times + LocalSetting.Update(SettingKeys.LaunchTimes, 0, x => unchecked(x + 1)); + + // If the guide is completed, we check if there's any unfulfilled resource category present. + if (UnsafeLocalSetting.Get(SettingKeys.Major1Minor10Revision0GuideState, GuideState.Language) >= GuideState.StaticResourceBegin) { - UnsafeLocalSetting.Set(SettingKeys.Major1Minor10Revision0GuideState, GuideState.StaticResourceBegin); + if (StaticResource.IsAnyUnfulfilledCategoryPresent()) + { + UnsafeLocalSetting.Set(SettingKeys.Major1Minor10Revision0GuideState, GuideState.StaticResourceBegin); + } + } + + if (UnsafeLocalSetting.Get(SettingKeys.Major1Minor10Revision0GuideState, GuideState.Language) < GuideState.Completed) + { + await taskContext.SwitchToMainThreadAsync(); + + GuideWindow guideWindow = serviceProvider.GetRequiredService(); + currentWindowReference.Window = guideWindow; + + guideWindow.SwitchTo(); + guideWindow.BringToForeground(); + return; } } - if (UnsafeLocalSetting.Get(SettingKeys.Major1Minor10Revision0GuideState, GuideState.Language) < GuideState.Completed) - { - await taskContext.SwitchToMainThreadAsync(); - - GuideWindow guideWindow = serviceProvider.GetRequiredService(); - currentWindowReference.Window = guideWindow; - - guideWindow.SwitchTo(); - guideWindow.BringToForeground(); - } - else - { - await WaitMainWindowAsync().ConfigureAwait(false); - } + await WaitMainWindowOrCurrentAsync().ConfigureAwait(false); } - private async ValueTask WaitMainWindowAsync() + private async ValueTask WaitMainWindowOrCurrentAsync() { - if (currentWindowReference.Window is not null) + if (currentWindowReference.Window is { } window) { + window.SwitchTo(); + window.BringToForeground(); return; } @@ -243,7 +247,7 @@ internal sealed partial class AppActivation : IAppActivation, IAppActivationActi { case CategoryAchievement: { - await WaitMainWindowAsync().ConfigureAwait(false); + await WaitMainWindowOrCurrentAsync().ConfigureAwait(false); await HandleAchievementActionAsync(action, parameter, isRedirectTo).ConfigureAwait(false); break; } @@ -256,7 +260,7 @@ internal sealed partial class AppActivation : IAppActivation, IAppActivationActi default: { - await HandleNormalLaunchActionAsync().ConfigureAwait(false); + await HandleNormalLaunchActionAsync(isRedirectTo).ConfigureAwait(false); break; } } diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Setting/SettingViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Setting/SettingViewModel.cs index dc5ab5e7..430413dd 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Setting/SettingViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Setting/SettingViewModel.cs @@ -371,7 +371,7 @@ internal sealed partial class SettingViewModel : Abstraction.ViewModel { if (await shellLinkInterop.TryCreateDesktopShoutcutForElevatedLaunchAsync().ConfigureAwait(false)) { - infoBarService.Information(SH.ViewModelSettingActionComplete); + infoBarService.Success(SH.ViewModelSettingActionComplete); } else { From f8e9b4a1b3b6572f92e7d85b7ae6007640562195 Mon Sep 17 00:00:00 2001 From: Lightczx <1686188646@qq.com> Date: Thu, 30 May 2024 12:36:30 +0800 Subject: [PATCH 15/68] fix pipe access control --- .../Snap.Hutao/Control/Theme/InfoBarOverride.xaml | 2 +- .../InterProcess/PrivateNamedPipeServer.cs | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/Snap.Hutao/Snap.Hutao/Control/Theme/InfoBarOverride.xaml b/src/Snap.Hutao/Snap.Hutao/Control/Theme/InfoBarOverride.xaml index 4151e2af..76af69ff 100644 --- a/src/Snap.Hutao/Snap.Hutao/Control/Theme/InfoBarOverride.xaml +++ b/src/Snap.Hutao/Snap.Hutao/Control/Theme/InfoBarOverride.xaml @@ -244,7 +244,7 @@ - diff --git a/src/Snap.Hutao/Snap.Hutao/Core/LifeCycle/InterProcess/PrivateNamedPipeServer.cs b/src/Snap.Hutao/Snap.Hutao/Core/LifeCycle/InterProcess/PrivateNamedPipeServer.cs index 2d61d09b..3cb7894e 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/LifeCycle/InterProcess/PrivateNamedPipeServer.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/LifeCycle/InterProcess/PrivateNamedPipeServer.cs @@ -4,6 +4,8 @@ using Snap.Hutao.Core.ExceptionService; using System.IO.Hashing; using System.IO.Pipes; +using System.Security.AccessControl; +using System.Security.Principal; namespace Snap.Hutao.Core.LifeCycle.InterProcess; @@ -12,7 +14,7 @@ namespace Snap.Hutao.Core.LifeCycle.InterProcess; internal sealed partial class PrivateNamedPipeServer : IDisposable { private readonly PrivateNamedPipeMessageDispatcher messageDispatcher; - + private readonly RuntimeOptions runtimeOptions; private readonly NamedPipeServerStream serverStream = new("Snap.Hutao.PrivateNamedPipe", PipeDirection.InOut, NamedPipeServerStream.MaxAllowedServerInstances, PipeTransmissionMode.Byte, PipeOptions.Asynchronous | PipeOptions.WriteThrough); private readonly CancellationTokenSource serverTokenSource = new(); private readonly SemaphoreSlim serverSemaphore = new(1); @@ -31,6 +33,17 @@ internal sealed partial class PrivateNamedPipeServer : IDisposable { using (await serverSemaphore.EnterAsync(serverTokenSource.Token).ConfigureAwait(false)) { + if (runtimeOptions.IsElevated) + { + SecurityIdentifier everyOne = new(WellKnownSidType.WorldSid, null); + SecurityIdentifier users = new(WellKnownSidType.BuiltinUsersSid, null); + + PipeSecurity pipeSecurity = new(); + pipeSecurity.AddAccessRule(new PipeAccessRule(everyOne, PipeAccessRights.ReadWrite, AccessControlType.Allow)); + pipeSecurity.AddAccessRule(new PipeAccessRule(users, PipeAccessRights.ReadWrite, AccessControlType.Allow)); + serverStream.SetAccessControl(pipeSecurity); + } + while (!serverTokenSource.IsCancellationRequested) { try From 7879f1278bb275abfecc7f2c1274fe6de24f2d0d Mon Sep 17 00:00:00 2001 From: Lightczx <1686188646@qq.com> Date: Thu, 30 May 2024 12:59:20 +0800 Subject: [PATCH 16/68] Update InfoBarOverride.xaml --- .../Snap.Hutao/Control/Theme/InfoBarOverride.xaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Snap.Hutao/Snap.Hutao/Control/Theme/InfoBarOverride.xaml b/src/Snap.Hutao/Snap.Hutao/Control/Theme/InfoBarOverride.xaml index 76af69ff..74e9a9fd 100644 --- a/src/Snap.Hutao/Snap.Hutao/Control/Theme/InfoBarOverride.xaml +++ b/src/Snap.Hutao/Snap.Hutao/Control/Theme/InfoBarOverride.xaml @@ -52,6 +52,12 @@ 19,16,19,16 0,0,0,0 20 + + 0,0,0,0 + 12,0,0,0 + 0,16,0,0 + 0,6,0,0 + - + \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Caching/ImageCache.cs b/src/Snap.Hutao/Snap.Hutao/Core/Caching/ImageCache.cs index af792574..9c939791 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/Caching/ImageCache.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/Caching/ImageCache.cs @@ -11,16 +11,13 @@ using Snap.Hutao.Web.Request.Builder; using Snap.Hutao.Web.Request.Builder.Abstraction; using System.Collections.Concurrent; using System.Collections.Frozen; +using System.Diagnostics; using System.IO; using System.Net; using System.Net.Http; namespace Snap.Hutao.Core.Caching; -/// -/// Provides methods and tools to cache files in a folder -/// The class's name will become the cache folder's name -/// [HighQuality] [ConstructorGenerated] [Injection(InjectAs.Singleton, typeof(IImageCache))] @@ -28,10 +25,9 @@ namespace Snap.Hutao.Core.Caching; [PrimaryHttpMessageHandler(MaxConnectionsPerServer = 8)] internal sealed partial class ImageCache : IImageCache, IImageCacheFilePathOperation { - private const string CacheFolderName = nameof(ImageCache); private const string CacheFailedDownloadTasksName = $"{nameof(ImageCache)}.FailedDownloadTasks"; - private readonly FrozenDictionary retryCountToDelay = FrozenDictionary.ToFrozenDictionary( + private static readonly FrozenDictionary DelayFromRetryCount = FrozenDictionary.ToFrozenDictionary( [ KeyValuePair.Create(0, TimeSpan.FromSeconds(4)), KeyValuePair.Create(1, TimeSpan.FromSeconds(16)), @@ -46,16 +42,13 @@ internal sealed partial class ImageCache : IImageCache, IImageCacheFilePathOpera private readonly ILogger logger; private readonly IMemoryCache memoryCache; - private string? baseFolder; private string? cacheFolder; private string CacheFolder { get => LazyInitializer.EnsureInitialized(ref cacheFolder, () => { - baseFolder ??= serviceProvider.GetRequiredService().LocalCache; - DirectoryInfo info = Directory.CreateDirectory(Path.Combine(baseFolder, CacheFolderName)); - return info.FullName; + return serviceProvider.GetRequiredService().GetLocalCacheImageCacheFolder(); }); } @@ -149,8 +142,7 @@ internal sealed partial class ImageCache : IImageCache, IImageCacheFilePathOpera return treatNullFileAsInvalid; } - FileInfo fileInfo = new(file); - return fileInfo.Length == 0; + return new FileInfo(file).Length == 0; } private void RemoveCore(IEnumerable filePaths) @@ -172,80 +164,76 @@ internal sealed partial class ImageCache : IImageCache, IImageCacheFilePathOpera [SuppressMessage("", "SH003")] private async Task DownloadFileAsync(Uri uri, string baseFile) { - int retryCount = 0; - HttpClient httpClient = httpClientFactory.CreateClient(nameof(ImageCache)); - while (retryCount < 3) + using (HttpClient httpClient = httpClientFactory.CreateClient(nameof(ImageCache))) { + int retryCount = 0; + HttpRequestMessageBuilder requestMessageBuilder = httpRequestMessageBuilderFactory .Create() .SetRequestUri(uri) - - // These headers are only available for our own api - .SetStaticResourceControlHeadersIf(uri.Host.Contains("api.snapgenshin.com", StringComparison.OrdinalIgnoreCase)) + .SetStaticResourceControlHeadersIf(uri.Host.Contains("api.snapgenshin.com", StringComparison.OrdinalIgnoreCase)) // These headers are only available for our own api .Get(); - using (HttpRequestMessage requestMessage = requestMessageBuilder.HttpRequestMessage) + while (retryCount < 3) { - using (HttpResponseMessage responseMessage = await httpClient.SendAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false)) - { - if (responseMessage.RequestMessage is { RequestUri: { } target } && target != uri) - { - logger.LogDebug("The Request '{Source}' has been redirected to '{Target}'", uri, target); - } + requestMessageBuilder.Resurrect(); - if (responseMessage.IsSuccessStatusCode) + using (HttpRequestMessage requestMessage = requestMessageBuilder.HttpRequestMessage) + { + using (HttpResponseMessage responseMessage = await httpClient.SendAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false)) { - if (responseMessage.Content.Headers.ContentType?.MediaType is "application/json") + // Redirect detection + if (responseMessage.RequestMessage is { RequestUri: { } target } && target != uri) { -#if DEBUG - DebugTrack(uri); -#endif - string raw = await responseMessage.Content.ReadAsStringAsync().ConfigureAwait(false); - logger.LogColorizedCritical("Failed to download '{Uri}' with unexpected body '{Raw}'", (uri, ConsoleColor.Red), (raw, ConsoleColor.DarkYellow)); - return; + logger.LogDebug("The Request '{Source}' has been redirected to '{Target}'", uri, target); } - using (Stream httpStream = await responseMessage.Content.ReadAsStreamAsync().ConfigureAwait(false)) + if (responseMessage.IsSuccessStatusCode) { - using (FileStream fileStream = File.Create(baseFile)) + if (responseMessage.Content.Headers.ContentType?.MediaType is "application/json") { - await httpStream.CopyToAsync(fileStream).ConfigureAwait(false); + DebugTrackFailedUri(uri); + string raw = await responseMessage.Content.ReadAsStringAsync().ConfigureAwait(false); + logger.LogColorizedCritical("Failed to download '{Uri}' with unexpected body '{Raw}'", (uri, ConsoleColor.Red), (raw, ConsoleColor.DarkYellow)); return; } - } - } - switch (responseMessage.StatusCode) - { - case HttpStatusCode.TooManyRequests: + using (Stream httpStream = await responseMessage.Content.ReadAsStreamAsync().ConfigureAwait(false)) { - retryCount++; - TimeSpan delay = responseMessage.Headers.RetryAfter?.Delta ?? retryCountToDelay[retryCount]; - logger.LogInformation("Retry download '{Uri}' after {Delay}.", uri, delay); - await Task.Delay(delay).ConfigureAwait(false); - break; + using (FileStream fileStream = File.Create(baseFile)) + { + await httpStream.CopyToAsync(fileStream).ConfigureAwait(false); + return; + } } + } - default: -#if DEBUG - DebugTrack(uri); -#endif - logger.LogColorizedCritical("Failed to download '{Uri}' with status code '{StatusCode}'", (uri, ConsoleColor.Red), (responseMessage.StatusCode, ConsoleColor.DarkYellow)); - return; + switch (responseMessage.StatusCode) + { + case HttpStatusCode.TooManyRequests: + { + retryCount++; + TimeSpan delay = responseMessage.Headers.RetryAfter?.Delta ?? DelayFromRetryCount[retryCount]; + logger.LogInformation("Retry download '{Uri}' after {Delay}.", uri, delay); + await Task.Delay(delay).ConfigureAwait(false); + break; + } + + default: + DebugTrackFailedUri(uri); + logger.LogColorizedCritical("Failed to download '{Uri}' with status code '{StatusCode}'", (uri, ConsoleColor.Red), (responseMessage.StatusCode, ConsoleColor.DarkYellow)); + return; + } } } } } } -} -#if DEBUG -internal partial class ImageCache -{ - private void DebugTrack(Uri uri) + [Conditional("DEBUG")] + private void DebugTrackFailedUri(Uri uri) { - HashSet? set = memoryCache.GetOrCreate(CacheFailedDownloadTasksName, entry => entry.Value ??= new HashSet()) as HashSet; + HashSet? set = memoryCache.GetOrCreate(CacheFailedDownloadTasksName, entry => new HashSet()); set?.Add(uri.ToString()); } -} -#endif \ No newline at end of file +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Database/ObservableReorderableDbCollection.cs b/src/Snap.Hutao/Snap.Hutao/Core/Database/ObservableReorderableDbCollection.cs index 7caba81f..6059d92a 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/Database/ObservableReorderableDbCollection.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/Database/ObservableReorderableDbCollection.cs @@ -70,7 +70,7 @@ internal sealed class ObservableReorderableDbCollection : ObservableCol [SuppressMessage("", "SA1402")] internal sealed class ObservableReorderableDbCollection : ObservableCollection - where TEntityOnly : class, IEntityOnly + where TEntityOnly : class, IEntityAccess where TEntity : class, IReorderable { private readonly IServiceProvider serviceProvider; diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Database/ScopedDbCurrent.cs b/src/Snap.Hutao/Snap.Hutao/Core/Database/ScopedDbCurrent.cs index fe550299..90e04cfc 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/Database/ScopedDbCurrent.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/Database/ScopedDbCurrent.cs @@ -73,7 +73,7 @@ internal sealed partial class ScopedDbCurrent [ConstructorGenerated] internal sealed partial class ScopedDbCurrent - where TEntityOnly : class, IEntityOnly + where TEntityOnly : class, IEntityAccess where TEntity : class, ISelectable where TMessage : Message.ValueChangedMessage, new() { diff --git a/src/Snap.Hutao/Snap.Hutao/Core/DependencyInjection/DependencyInjection.cs b/src/Snap.Hutao/Snap.Hutao/Core/DependencyInjection/DependencyInjection.cs index d32e7276..ee49a41f 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/DependencyInjection/DependencyInjection.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/DependencyInjection/DependencyInjection.cs @@ -41,7 +41,7 @@ internal static class DependencyInjection .AddJsonOptions() .AddDatabase() .AddInjections() - .AddAllHttpClients() + .AddConfiguredHttpClients() // Discrete services .AddSingleton() diff --git a/src/Snap.Hutao/Snap.Hutao/Core/DependencyInjection/IocConfiguration.cs b/src/Snap.Hutao/Snap.Hutao/Core/DependencyInjection/IocConfiguration.cs index fc3baa03..ac0cc302 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/DependencyInjection/IocConfiguration.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/DependencyInjection/IocConfiguration.cs @@ -34,27 +34,27 @@ internal static class IocConfiguration .AddTransient(typeof(Database.ScopedDbCurrent<,>)) .AddTransient(typeof(Database.ScopedDbCurrent<,,>)) .AddDbContextPool(AddDbContextCore); - } - private static void AddDbContextCore(IServiceProvider serviceProvider, DbContextOptionsBuilder builder) - { - RuntimeOptions runtimeOptions = serviceProvider.GetRequiredService(); - string dbFile = System.IO.Path.Combine(runtimeOptions.DataFolder, "Userdata.db"); - string sqlConnectionString = $"Data Source={dbFile}"; - - // Temporarily create a context - using (AppDbContext context = AppDbContext.Create(serviceProvider, sqlConnectionString)) + static void AddDbContextCore(IServiceProvider serviceProvider, DbContextOptionsBuilder builder) { - if (context.Database.GetPendingMigrations().Any()) - { - System.Diagnostics.Debug.WriteLine("[Database] Performing AppDbContext Migrations"); - context.Database.Migrate(); - } - } + RuntimeOptions runtimeOptions = serviceProvider.GetRequiredService(); + string dbFile = System.IO.Path.Combine(runtimeOptions.DataFolder, "Userdata.db"); + string sqlConnectionString = $"Data Source={dbFile}"; - builder - .EnableSensitiveDataLogging() - .UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking) - .UseSqlite(sqlConnectionString); + // Temporarily create a context + using (AppDbContext context = AppDbContext.Create(serviceProvider, sqlConnectionString)) + { + if (context.Database.GetPendingMigrations().Any()) + { + System.Diagnostics.Debug.WriteLine("[Database] Performing AppDbContext Migrations"); + context.Database.Migrate(); + } + } + + builder + .EnableSensitiveDataLogging() + .UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking) + .UseSqlite(sqlConnectionString); + } } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Core/DependencyInjection/IocHttpClientConfiguration.cs b/src/Snap.Hutao/Snap.Hutao/Core/DependencyInjection/IocHttpClientConfiguration.cs index de8ef22b..dfe5fe0e 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/DependencyInjection/IocHttpClientConfiguration.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/DependencyInjection/IocHttpClientConfiguration.cs @@ -15,7 +15,7 @@ internal static partial class IocHttpClientConfiguration { private const string ApplicationJson = "application/json"; - public static IServiceCollection AddAllHttpClients(this IServiceCollection services) + public static IServiceCollection AddConfiguredHttpClients(this IServiceCollection services) { services .ConfigureHttpClientDefaults(clientBuilder => @@ -27,7 +27,7 @@ internal static partial class IocHttpClientConfiguration HttpClientHandler clientHandler = (HttpClientHandler)handler; clientHandler.AllowAutoRedirect = true; clientHandler.UseProxy = true; - clientHandler.Proxy = provider.GetRequiredService(); + clientHandler.Proxy = provider.GetRequiredService(); }); }) .AddHttpClients(); diff --git a/src/Snap.Hutao/Snap.Hutao/Core/ExceptionService/ThrowHelper.cs b/src/Snap.Hutao/Snap.Hutao/Core/ExceptionService/ThrowHelper.cs deleted file mode 100644 index 5cdf3e36..00000000 --- a/src/Snap.Hutao/Snap.Hutao/Core/ExceptionService/ThrowHelper.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) DGP Studio. All rights reserved. -// Licensed under the MIT license. - -using System.Runtime.CompilerServices; - -namespace Snap.Hutao.Core.ExceptionService; - -/// -/// 帮助更好的抛出异常 -/// -[HighQuality] -[System.Diagnostics.StackTraceHidden] -[Obsolete("Use HutaoException instead")] -internal static class ThrowHelper -{ - [DoesNotReturn] - [MethodImpl(MethodImplOptions.NoInlining)] - public static ArgumentException Argument(string message, string? paramName) - { - throw new ArgumentException(message, paramName); - } -} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Core/IO/DirectoryOperation.cs b/src/Snap.Hutao/Snap.Hutao/Core/IO/DirectoryOperation.cs index 39132ba2..2e3894ad 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/IO/DirectoryOperation.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/IO/DirectoryOperation.cs @@ -2,7 +2,12 @@ // Licensed under the MIT license. using Microsoft.VisualBasic.FileIO; +using Snap.Hutao.Win32.System.Com; +using Snap.Hutao.Win32.UI.Shell; using System.IO; +using static Snap.Hutao.Win32.Macros; +using static Snap.Hutao.Win32.Ole32; +using static Snap.Hutao.Win32.Shell32; namespace Snap.Hutao.Core.IO; @@ -18,4 +23,29 @@ internal static class DirectoryOperation FileSystem.MoveDirectory(sourceDirName, destDirName, true); return true; } + + public static unsafe bool UnsafeRename(string path, string name, FILEOPERATION_FLAGS flags = FILEOPERATION_FLAGS.FOF_ALLOWUNDO | FILEOPERATION_FLAGS.FOF_NOCONFIRMMKDIR) + { + bool result = false; + + if (SUCCEEDED(CoCreateInstance(in Win32.UI.Shell.FileOperation.CLSID, default, CLSCTX.CLSCTX_INPROC_SERVER, in IFileOperation.IID, out IFileOperation* pFileOperation))) + { + if (SUCCEEDED(SHCreateItemFromParsingName(path, default, in IShellItem.IID, out IShellItem* pShellItem))) + { + pFileOperation->SetOperationFlags(flags); + pFileOperation->RenameItem(pShellItem, name, default); + + if (SUCCEEDED(pFileOperation->PerformOperations())) + { + result = true; + } + + IUnknownMarshal.Release(pShellItem); + } + + IUnknownMarshal.Release(pFileOperation); + } + + return result; + } } diff --git a/src/Snap.Hutao/Snap.Hutao/Core/IO/FileOperation.cs b/src/Snap.Hutao/Snap.Hutao/Core/IO/FileOperation.cs index 00b97aa5..83f8b2b4 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/IO/FileOperation.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/IO/FileOperation.cs @@ -45,6 +45,30 @@ internal static class FileOperation return true; } + public static unsafe bool UnsafeDelete(string path) + { + bool result = false; + + if (SUCCEEDED(CoCreateInstance(in Win32.UI.Shell.FileOperation.CLSID, default, CLSCTX.CLSCTX_INPROC_SERVER, in IFileOperation.IID, out IFileOperation* pFileOperation))) + { + if (SUCCEEDED(SHCreateItemFromParsingName(path, default, in IShellItem.IID, out IShellItem* pShellItem))) + { + pFileOperation->DeleteItem(pShellItem, default); + + if (SUCCEEDED(pFileOperation->PerformOperations())) + { + result = true; + } + + IUnknownMarshal.Release(pShellItem); + } + + IUnknownMarshal.Release(pFileOperation); + } + + return result; + } + public static unsafe bool UnsafeMove(string sourceFileName, string destFileName) { bool result = false; @@ -73,28 +97,4 @@ internal static class FileOperation return result; } - - public static unsafe bool UnsafeDelete(string path) - { - bool result = false; - - if (SUCCEEDED(CoCreateInstance(in Win32.UI.Shell.FileOperation.CLSID, default, CLSCTX.CLSCTX_INPROC_SERVER, in IFileOperation.IID, out IFileOperation* pFileOperation))) - { - if (SUCCEEDED(SHCreateItemFromParsingName(path, default, in IShellItem.IID, out IShellItem* pShellItem))) - { - pFileOperation->DeleteItem(pShellItem, default); - - if (SUCCEEDED(pFileOperation->PerformOperations())) - { - result = true; - } - - IUnknownMarshal.Release(pShellItem); - } - - IUnknownMarshal.Release(pFileOperation); - } - - return result; - } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Core/IO/Hashing/Hash.cs b/src/Snap.Hutao/Snap.Hutao/Core/IO/Hashing/Hash.cs index 86f4b96a..435597fc 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/IO/Hashing/Hash.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/IO/Hashing/Hash.cs @@ -6,6 +6,9 @@ using System.Text; namespace Snap.Hutao.Core.IO.Hashing; +#if NET9_0_OR_GREATER +[Obsolete] +#endif internal static class Hash { public static unsafe string SHA1HexString(string input) diff --git a/src/Snap.Hutao/Snap.Hutao/Core/IO/Http/Proxy/DynamicHttpProxy.cs b/src/Snap.Hutao/Snap.Hutao/Core/IO/Http/Proxy/HttpProxyUsingSystemProxy.cs similarity index 93% rename from src/Snap.Hutao/Snap.Hutao/Core/IO/Http/Proxy/DynamicHttpProxy.cs rename to src/Snap.Hutao/Snap.Hutao/Core/IO/Http/Proxy/HttpProxyUsingSystemProxy.cs index f40b8a4f..b0169e6c 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/IO/Http/Proxy/DynamicHttpProxy.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/IO/Http/Proxy/HttpProxyUsingSystemProxy.cs @@ -3,13 +3,14 @@ using CommunityToolkit.Mvvm.ComponentModel; using Snap.Hutao.Win32.Registry; +using System.Linq.Expressions; using System.Net; using System.Reflection; namespace Snap.Hutao.Core.IO.Http.Proxy; [Injection(InjectAs.Singleton)] -internal sealed partial class DynamicHttpProxy : ObservableObject, IWebProxy, IDisposable +internal sealed partial class HttpProxyUsingSystemProxy : ObservableObject, IWebProxy, IDisposable { private const string ProxySettingPath = @"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Connections"; @@ -20,7 +21,7 @@ internal sealed partial class DynamicHttpProxy : ObservableObject, IWebProxy, ID private IWebProxy innerProxy = default!; - public DynamicHttpProxy(IServiceProvider serviceProvider) + public HttpProxyUsingSystemProxy(IServiceProvider serviceProvider) { this.serviceProvider = serviceProvider; UpdateInnerProxy(); diff --git a/src/Snap.Hutao/Snap.Hutao/Core/RuntimeOptionsExtension.cs b/src/Snap.Hutao/Snap.Hutao/Core/RuntimeOptionsExtension.cs index acc10562..629a74b5 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/RuntimeOptionsExtension.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/RuntimeOptionsExtension.cs @@ -27,4 +27,11 @@ internal static class RuntimeOptionsExtension Directory.CreateDirectory(directory); return directory; } + + public static string GetLocalCacheImageCacheFolder(this RuntimeOptions options) + { + string directory = Path.Combine(options.LocalCache, "ImageCache"); + Directory.CreateDirectory(directory); + return directory; + } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Shell/ShellLinkInterop.cs b/src/Snap.Hutao/Snap.Hutao/Core/Shell/ShellLinkInterop.cs index 347f2638..67123d28 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/Shell/ShellLinkInterop.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/Shell/ShellLinkInterop.cs @@ -67,7 +67,7 @@ internal sealed partial class ShellLinkInterop : IShellLinkInterop IUnknownMarshal.Release(pPersistFile); } - uint value = IUnknownMarshal.Release(pShellLink); + IUnknownMarshal.Release(pShellLink); } return result; diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/CompactRect.cs b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/RectInt16.cs similarity index 55% rename from src/Snap.Hutao/Snap.Hutao/Core/Windowing/CompactRect.cs rename to src/Snap.Hutao/Snap.Hutao/Core/Windowing/RectInt16.cs index 9996fa4e..59f569e3 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/CompactRect.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/RectInt16.cs @@ -1,19 +1,18 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. -using System.Runtime.CompilerServices; using Windows.Graphics; namespace Snap.Hutao.Core.Windowing; -internal readonly struct CompactRect +internal readonly struct RectInt16 { private readonly short x; private readonly short y; private readonly short width; private readonly short height; - private CompactRect(int x, int y, int width, int height) + private RectInt16(int x, int y, int width, int height) { this.x = (short)x; this.y = (short)y; @@ -21,24 +20,22 @@ internal readonly struct CompactRect this.height = (short)height; } - public static implicit operator RectInt32(CompactRect rect) + public static implicit operator RectInt32(RectInt16 rect) { return new(rect.x, rect.y, rect.width, rect.height); } - public static explicit operator CompactRect(RectInt32 rect) + public static explicit operator RectInt16(RectInt32 rect) { return new(rect.X, rect.Y, rect.Width, rect.Height); } - public static unsafe explicit operator CompactRect(ulong value) + public static unsafe explicit operator RectInt16(ulong value) { - Unsafe.SkipInit(out CompactRect rect); - *(ulong*)&rect = value; - return rect; + return *(RectInt16*)&value; } - public static unsafe implicit operator ulong(CompactRect rect) + public static unsafe implicit operator ulong(RectInt16 rect) { return *(ulong*)▭ } diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/XamlWindowController.cs b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/XamlWindowController.cs index 564b73f4..98ab3d69 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/XamlWindowController.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/XamlWindowController.cs @@ -241,7 +241,7 @@ internal sealed class XamlWindowController if (window is IXamlWindowRectPersisted rectPersisted) { - RectInt32 nonDpiPersistedRect = (CompactRect)LocalSetting.Get(rectPersisted.PersistRectKey, (CompactRect)rect); + RectInt32 nonDpiPersistedRect = (RectInt16)LocalSetting.Get(rectPersisted.PersistRectKey, (RectInt16)rect); RectInt32 persistedRect = nonDpiPersistedRect.Scale(scale); // If the persisted size is less than min size, we want to reset to the init size. @@ -266,7 +266,7 @@ internal sealed class XamlWindowController { // We save the non-dpi rect here double scale = 1.0 / window.GetRasterizationScale(); - LocalSetting.Set(rectPersisted.PersistRectKey, (CompactRect)window.AppWindow.GetRect().Scale(scale)); + LocalSetting.Set(rectPersisted.PersistRectKey, (RectInt16)window.AppWindow.GetRect().Scale(scale)); } } #endregion diff --git a/src/Snap.Hutao/Snap.Hutao/Extension/EnumerableExtension.cs b/src/Snap.Hutao/Snap.Hutao/Extension/EnumerableExtension.cs index 85fb49f9..5b2e9993 100644 --- a/src/Snap.Hutao/Snap.Hutao/Extension/EnumerableExtension.cs +++ b/src/Snap.Hutao/Snap.Hutao/Extension/EnumerableExtension.cs @@ -104,7 +104,7 @@ internal static partial class EnumerableExtension [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ObservableReorderableDbCollection ToObservableReorderableDbCollection(this IEnumerable source, IServiceProvider serviceProvider) - where TEntityOnly : class, IEntityOnly + where TEntityOnly : class, IEntityAccess where TEntity : class, IReorderable { return source is List list diff --git a/src/Snap.Hutao/Snap.Hutao/Model/IEntityAccessWithMetadata.cs b/src/Snap.Hutao/Snap.Hutao/Model/IEntityAccessWithMetadata.cs new file mode 100644 index 00000000..83bc4e37 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Model/IEntityAccessWithMetadata.cs @@ -0,0 +1,14 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +namespace Snap.Hutao.Model; + +internal interface IEntityAccessWithMetadata : IEntityAccess +{ + TMetadata Inner { get; } +} + +internal interface IEntityAccess +{ + TEntity Entity { get; } +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Model/IEntityWithMetadata.cs b/src/Snap.Hutao/Snap.Hutao/Model/IEntityWithMetadata.cs deleted file mode 100644 index 3eedb828..00000000 --- a/src/Snap.Hutao/Snap.Hutao/Model/IEntityWithMetadata.cs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) DGP Studio. All rights reserved. -// Licensed under the MIT license. - -namespace Snap.Hutao.Model; - -/// -/// 实体与元数据 -/// -/// 实体 -/// 元数据 -[HighQuality] -internal interface IEntityWithMetadata : IEntityOnly -{ - /// - /// 元数据 - /// - TMetadata Inner { get; } -} - -internal interface IEntityOnly -{ - /// - /// 实体 - /// - TEntity Entity { get; } -} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Abstraction/DbStoreOptions.cs b/src/Snap.Hutao/Snap.Hutao/Service/Abstraction/DbStoreOptions.cs index 580a1fea..0709e1b8 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Abstraction/DbStoreOptions.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Abstraction/DbStoreOptions.cs @@ -82,31 +82,10 @@ internal abstract partial class DbStoreOptions : ObservableObject return storage.Value; } - [return: NotNull] - protected T GetOption(ref T? storage, string key, Func deserializer, [DisallowNull] T defaultValue) + [return: NotNullIfNotNull(nameof(defaultValue))] + protected T GetOption(ref T? storage, string key, Func deserializer, T defaultValue) { - if (storage is not null) - { - return storage; - } - - using (IServiceScope scope = serviceProvider.CreateScope()) - { - AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService(); - string? value = appDbContext.Settings.SingleOrDefault(e => e.Key == key)?.Value; - if (value is null) - { - storage = defaultValue; - } - else - { - T targetValue = deserializer(value); - ArgumentNullException.ThrowIfNull(targetValue); - storage = targetValue; - } - } - - return storage; + return GetOption(ref storage, key, deserializer, () => defaultValue); } protected T GetOption(ref T? storage, string key, Func deserializer, Func defaultValueFactory) diff --git a/src/Snap.Hutao/Snap.Hutao/Service/DailyNote/DailyNoteWebhookOperation.cs b/src/Snap.Hutao/Snap.Hutao/Service/DailyNote/DailyNoteWebhookOperation.cs index 0f008b7a..377c4fbc 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/DailyNote/DailyNoteWebhookOperation.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/DailyNote/DailyNoteWebhookOperation.cs @@ -32,6 +32,6 @@ internal sealed partial class DailyNoteWebhookOperation .SetHeader("x-uid", $"{playerUid}") .PostJson(dailyNote); - await builder.TryCatchSendAsync(httpClient, logger, token).ConfigureAwait(false); + await builder.SendAsync(httpClient, logger, token).ConfigureAwait(false); } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Automation/ScreenCapture/DirectX.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Automation/ScreenCapture/DirectX.cs index 2fdd8016..679c764f 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/Automation/ScreenCapture/DirectX.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Automation/ScreenCapture/DirectX.cs @@ -80,7 +80,6 @@ internal static class DirectX return false; } - //IUnknownMarshal.Release(swapChain); return true; } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/Automation/ScreenCapture/GameScreenCaptureSession.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/Automation/ScreenCapture/GameScreenCaptureSession.cs index 3e2be4bf..0369aeae 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/Automation/ScreenCapture/GameScreenCaptureSession.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/Automation/ScreenCapture/GameScreenCaptureSession.cs @@ -122,7 +122,8 @@ internal sealed class GameScreenCaptureSession : IDisposable try { captureContext.UpdatePreview(previewWindow, frame.Surface); - //UnsafeProcessFrameSurface(frame.Surface); + + // UnsafeProcessFrameSurface(frame.Surface); } catch (Exception ex) { diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/LoginHoyoverseUserPage.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/Page/LoginHoyoverseUserPage.xaml.cs index ef5deb5a..84f10397 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Page/LoginHoyoverseUserPage.xaml.cs +++ b/src/Snap.Hutao/Snap.Hutao/View/Page/LoginHoyoverseUserPage.xaml.cs @@ -49,7 +49,7 @@ internal sealed partial class LoginHoyoverseUserPage : Microsoft.UI.Xaml.Control HttpClient httpClient = serviceProvider.GetRequiredService(); WebApiResponse? resp = await builder - .TryCatchSendAsync>(httpClient, logger, token) + .SendAsync>(httpClient, logger, token) .ConfigureAwait(false); return $"{resp?.Data?.AccountInfo?.AccountId}"; diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/TestPage.xaml b/src/Snap.Hutao/Snap.Hutao/View/Page/TestPage.xaml index 75d81062..16227a0a 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Page/TestPage.xaml +++ b/src/Snap.Hutao/Snap.Hutao/View/Page/TestPage.xaml @@ -124,6 +124,11 @@ Header="Screen Capture Test" IsClickEnabled="True"/> + +