diff --git a/src/Snap.Hutao/Snap.Hutao/App.xaml b/src/Snap.Hutao/Snap.Hutao/App.xaml index dd980061..590d52a5 100644 --- a/src/Snap.Hutao/Snap.Hutao/App.xaml +++ b/src/Snap.Hutao/Snap.Hutao/App.xaml @@ -12,6 +12,7 @@ + diff --git a/src/Snap.Hutao/Snap.Hutao/Control/Behavior/MarqueeTextBehavior.cs b/src/Snap.Hutao/Snap.Hutao/Control/Behavior/MarqueeTextBehavior.cs new file mode 100644 index 00000000..9f27b0e6 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Control/Behavior/MarqueeTextBehavior.cs @@ -0,0 +1,46 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +using CommunityToolkit.Labs.WinUI.MarqueeTextRns; +using CommunityToolkit.WinUI.Behaviors; +using Microsoft.UI.Xaml.Input; + +namespace Snap.Hutao.Control.Behavior; + +internal sealed class MarqueeTextBehavior : BehaviorBase +{ + private readonly PointerEventHandler pointerEnteredEventHandler; + private readonly PointerEventHandler pointerExitedEventHandler; + + public MarqueeTextBehavior() + { + pointerEnteredEventHandler = OnPointerEntered; + pointerExitedEventHandler = OnPointerExited; + } + + protected override bool Initialize() + { + AssociatedObject.PointerEntered += pointerEnteredEventHandler; + AssociatedObject.PointerExited += pointerExitedEventHandler; + + return true; + } + + protected override bool Uninitialize() + { + AssociatedObject.PointerEntered -= pointerEnteredEventHandler; + AssociatedObject.PointerExited -= pointerExitedEventHandler; + + return true; + } + + private void OnPointerEntered(object sender, PointerRoutedEventArgs e) + { + AssociatedObject.StartMarquee(); + } + + private void OnPointerExited(object sender, PointerRoutedEventArgs e) + { + AssociatedObject.StopMarquee(); + } +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Control/Behavior/StartAnimationActionNoThrow.cs b/src/Snap.Hutao/Snap.Hutao/Control/Behavior/StartAnimationActionNoThrow.cs new file mode 100644 index 00000000..b28641c0 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Control/Behavior/StartAnimationActionNoThrow.cs @@ -0,0 +1,31 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +using CommunityToolkit.WinUI.Animations; +using Microsoft.UI.Xaml; +using Microsoft.Xaml.Interactivity; + +namespace Snap.Hutao.Control.Behavior; + +[DependencyProperty("Animation", typeof(AnimationSet))] +[DependencyProperty("TargetObject", typeof(UIElement))] +internal sealed partial class StartAnimationActionNoThrow : DependencyObject, IAction +{ + /// + public object Execute(object sender, object parameter) + { + if (Animation is not null) + { + if (TargetObject is not null) + { + Animation.Start(TargetObject); + } + else + { + Animation.Start(sender as UIElement); + } + } + + return default!; + } +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Control/Theme/FlyoutStyle.xaml b/src/Snap.Hutao/Snap.Hutao/Control/Theme/FlyoutStyle.xaml new file mode 100644 index 00000000..b2da9a2e --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Control/Theme/FlyoutStyle.xaml @@ -0,0 +1,22 @@ + + + + + diff --git a/src/Snap.Hutao/Snap.Hutao/Control/Theme/ItemsPanelTemplate.xaml b/src/Snap.Hutao/Snap.Hutao/Control/Theme/ItemsPanelTemplate.xaml index 46d10041..28a32452 100644 --- a/src/Snap.Hutao/Snap.Hutao/Control/Theme/ItemsPanelTemplate.xaml +++ b/src/Snap.Hutao/Snap.Hutao/Control/Theme/ItemsPanelTemplate.xaml @@ -11,13 +11,28 @@ - + + + + + + + + + + diff --git a/src/Snap.Hutao/Snap.Hutao/Control/Theme/TransitionCollection.xaml b/src/Snap.Hutao/Snap.Hutao/Control/Theme/TransitionCollection.xaml index 146fc0cd..02b9df16 100644 --- a/src/Snap.Hutao/Snap.Hutao/Control/Theme/TransitionCollection.xaml +++ b/src/Snap.Hutao/Snap.Hutao/Control/Theme/TransitionCollection.xaml @@ -14,4 +14,10 @@ + + + + + + diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Entity/SettingEntry.Constant.cs b/src/Snap.Hutao/Snap.Hutao/Model/Entity/SettingEntry.Constant.cs index e0884f67..5c96234d 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Entity/SettingEntry.Constant.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Entity/SettingEntry.Constant.cs @@ -48,6 +48,11 @@ internal sealed partial class SettingEntry /// public const string DailyNoteSilentWhenPlayingGame = "DailyNote.SilentWhenPlayingGame"; + /// + /// 实时便笺 WebhookUrl + /// + public const string DailyNoteWebhookUrl = "DailyNote.WebhookUrl"; + /// /// 启动游戏 独占全屏 /// @@ -68,11 +73,15 @@ internal sealed partial class SettingEntry /// public const string LaunchScreenWidth = "Launch.ScreenWidth"; + public const string LaunchIsScreenWidthEnabled = "Launch.IsScreenWidthEnabled"; + /// /// 启动游戏 高度 /// public const string LaunchScreenHeight = "Launch.ScreenHeight"; + public const string LaunchIsScreenHeightEnabled = "Launch.IsScreenHeightEnabled"; + /// /// 启动游戏 解锁帧率 /// @@ -88,6 +97,8 @@ internal sealed partial class SettingEntry /// public const string LaunchMonitor = "Launch.Monitor"; + public const string LaunchIsMonitorEnabled = "Launch.IsMonitorEnabled"; + /// /// 启动游戏 多倍启动 /// diff --git a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx index 4dbcbd3e..27e1b0e2 100644 --- a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx +++ b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx @@ -539,9 +539,15 @@ 验证失败 + + 验证请求失败,不是当前登录的账号 + 验证码已发送至邮箱 + + 验证请求失败,当前邮箱已被注册 + 验证请求过快,请 1 分钟后再试 @@ -1796,6 +1802,9 @@ 输入 + + 从胡桃云恢复祈愿记录 + 刷新 @@ -2486,6 +2495,9 @@ 上传数据 + + 自动连点 + 工具 diff --git a/src/Snap.Hutao/Snap.Hutao/Service/DailyNote/DailyNoteOptions.cs b/src/Snap.Hutao/Snap.Hutao/Service/DailyNote/DailyNoteOptions.cs index 215137e8..3786ef2e 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/DailyNote/DailyNoteOptions.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/DailyNote/DailyNoteOptions.cs @@ -126,7 +126,7 @@ internal sealed partial class DailyNoteOptions : DbStoreOptions public string? WebhookUrl { - get => GetOption(ref webhookUrl, SettingEntry.DailyNoteSilentWhenPlayingGame); - set => SetOption(ref webhookUrl, SettingEntry.DailyNoteSilentWhenPlayingGame, value); + get => GetOption(ref webhookUrl, SettingEntry.DailyNoteWebhookUrl); + set => SetOption(ref webhookUrl, SettingEntry.DailyNoteWebhookUrl, value); } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/KnownLaunchSchemes.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/KnownLaunchSchemes.cs new file mode 100644 index 00000000..16fac365 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/KnownLaunchSchemes.cs @@ -0,0 +1,52 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +using Snap.Hutao.Model.Intrinsic; + +namespace Snap.Hutao.Service.Game; + +internal static class KnownLaunchSchemes +{ + private static readonly LaunchScheme ServerChineseChannelDefaultSubChannelDefaultCompat = new LaunchSchemeChinese(ChannelType.Default, SubChannelType.Default, false); + private static readonly LaunchScheme ServerChineseChannelOfficialSubChannelDefault = new LaunchSchemeChinese(ChannelType.Official, SubChannelType.Default); + private static readonly LaunchScheme ServerChineseChannelOfficialSubChannelOfficial = new LaunchSchemeChinese(ChannelType.Official, SubChannelType.Official); + private static readonly LaunchScheme ServerChineseChannelOfficialSubChannelNoTapTap = new LaunchSchemeChinese(ChannelType.Official, SubChannelType.NoTapTap); + private static readonly LaunchScheme ServerChineseChannelOfficialSubChannelEpicCompat = new LaunchSchemeChinese(ChannelType.Official, SubChannelType.Epic, false); + + private static readonly LaunchScheme ServerChineseChannelBilibiliSubChannelDefault = new LaunchSchemeBilibili(SubChannelType.Default); + private static readonly LaunchScheme ServerChineseChannelBilibiliSubChannelOfficialCompat = new LaunchSchemeBilibili(SubChannelType.Official, false); + + private static readonly LaunchScheme ServerGlobalChannelDefaultSubChannelDefaultCompat = new LaunchSchemeOversea(ChannelType.Default, SubChannelType.Default, false); + private static readonly LaunchScheme ServerGlobalChannelOfficialSubChannelDefault = new LaunchSchemeOversea(ChannelType.Official, SubChannelType.Default); + private static readonly LaunchScheme ServerGlobalChannelOfficialSubChannelOfficial = new LaunchSchemeOversea(ChannelType.Official, SubChannelType.Official); + private static readonly LaunchScheme ServerGlobalChannelOfficialSubChannelEpic = new LaunchSchemeOversea(ChannelType.Official, SubChannelType.Epic); + private static readonly LaunchScheme ServerGlobalChannelOfficialSubChannelGoogle = new LaunchSchemeOversea(ChannelType.Official, SubChannelType.Google); + + /// + /// 获取已知的启动方案 + /// + /// 已知的启动方案 + public static List Get() + { + return new List() + { + // 官服 + ServerChineseChannelDefaultSubChannelDefaultCompat, + ServerChineseChannelOfficialSubChannelDefault, + ServerChineseChannelOfficialSubChannelOfficial, + ServerChineseChannelOfficialSubChannelNoTapTap, + ServerChineseChannelOfficialSubChannelEpicCompat, + + // 渠道服 + ServerChineseChannelBilibiliSubChannelDefault, + ServerChineseChannelBilibiliSubChannelOfficialCompat, + + // 国际服 + ServerGlobalChannelDefaultSubChannelDefaultCompat, + ServerGlobalChannelOfficialSubChannelDefault, + ServerGlobalChannelOfficialSubChannelOfficial, + ServerGlobalChannelOfficialSubChannelEpic, + ServerGlobalChannelOfficialSubChannelGoogle, + }; + } +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/LaunchOptions.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/LaunchOptions.cs index 71fe1fcd..c086cd15 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/LaunchOptions.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/LaunchOptions.cs @@ -27,10 +27,13 @@ internal sealed class LaunchOptions : DbStoreOptions private bool? isBorderless; private bool? isExclusive; private int? screenWidth; + private bool? isScreenWidthEnabled; private int? screenHeight; + private bool? isScreenHeightEnabled; private bool? unlockFps; private int? targetFps; private NameValue? monitor; + private bool? isMonitorEnabled; /// /// 构造一个新的启动游戏选项 @@ -83,6 +86,12 @@ internal sealed class LaunchOptions : DbStoreOptions set => SetOption(ref screenWidth, SettingEntry.LaunchScreenWidth, value); } + public bool IsScreenWidthEnabled + { + get => GetOption(ref isScreenWidthEnabled, SettingEntry.LaunchIsScreenWidthEnabled, true); + set => SetOption(ref isScreenWidthEnabled, SettingEntry.LaunchIsScreenWidthEnabled, value); + } + /// /// 屏幕高度 /// @@ -92,6 +101,12 @@ internal sealed class LaunchOptions : DbStoreOptions set => SetOption(ref screenHeight, SettingEntry.LaunchScreenHeight, value); } + public bool IsScreenHeightEnabled + { + get => GetOption(ref isScreenHeightEnabled, SettingEntry.LaunchIsScreenHeightEnabled, true); + set => SetOption(ref isScreenHeightEnabled, SettingEntry.LaunchIsScreenHeightEnabled, value); + } + /// /// 是否全屏 /// @@ -131,6 +146,12 @@ internal sealed class LaunchOptions : DbStoreOptions } } + public bool IsMonitorEnabled + { + get => GetOption(ref isMonitorEnabled, SettingEntry.LaunchIsMonitorEnabled, true); + set => SetOption(ref isMonitorEnabled, SettingEntry.LaunchIsMonitorEnabled, value); + } + private static void InitializeMonitors(List> monitors) { // This list can't use foreach diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/LaunchScheme.KnownSchemes.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/LaunchScheme.KnownSchemes.cs deleted file mode 100644 index 338b3989..00000000 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/LaunchScheme.KnownSchemes.cs +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright (c) DGP Studio. All rights reserved. -// Licensed under the MIT license. - -using Snap.Hutao.Model.Intrinsic; - -namespace Snap.Hutao.Service.Game; - -/// -/// 方案列表部分 -/// -internal sealed partial class LaunchScheme -{ - private const int SdkStaticLauncherChineseId = 18; - private const int SdkStaticLauncherBilibiliId = 17; - private const int SdkStaticLauncherGlobalId = 10; - - private const string SdkStaticLauncherChineseKey = "eYd89JmJ"; - private const string SdkStaticLauncherBilibiliKey = "KAtdSsoQ"; - private const string SdkStaticLauncherGlobalKey = "gcStgarh"; - - private static readonly LaunchScheme ServerChineseChannelDefaultSubChannelDefaultCompatOnly = new() - { - LauncherId = SdkStaticLauncherChineseId, - Key = SdkStaticLauncherChineseKey, - Channel = ChannelType.Default, - SubChannel = SubChannelType.Default, - IsOversea = false, - IsNotCompatOnly = false, - }; - - private static readonly LaunchScheme ServerChineseChannelOfficialSubChannelDefault = new() - { - LauncherId = SdkStaticLauncherChineseId, - Key = SdkStaticLauncherChineseKey, - Channel = ChannelType.Official, - SubChannel = SubChannelType.Default, - IsOversea = false, - }; - - private static readonly LaunchScheme ServerChineseChannelOfficialSubChannelOfficial = new() - { - LauncherId = SdkStaticLauncherChineseId, - Key = SdkStaticLauncherChineseKey, - Channel = ChannelType.Official, - SubChannel = SubChannelType.Official, - IsOversea = false, - }; - - private static readonly LaunchScheme ServerChineseChannelOfficialSubChannelNoTapTap = new() - { - LauncherId = SdkStaticLauncherChineseId, - Key = SdkStaticLauncherChineseKey, - Channel = ChannelType.Official, - SubChannel = SubChannelType.NoTapTap, - IsOversea = false, - }; - - private static readonly LaunchScheme ServerChineseChannelOfficialSubChannelEpicCompatOnly = new() - { - LauncherId = SdkStaticLauncherChineseId, - Key = SdkStaticLauncherChineseKey, - Channel = ChannelType.Official, - SubChannel = SubChannelType.Epic, - IsOversea = false, - IsNotCompatOnly = false, - }; - - private static readonly LaunchScheme ServerChineseChannelBilibiliSubChannelDefault = new() - { - LauncherId = SdkStaticLauncherBilibiliId, - Key = SdkStaticLauncherBilibiliKey, - Channel = ChannelType.Bili, - SubChannel = SubChannelType.Default, - IsOversea = false, - }; - - private static readonly LaunchScheme ServerChineseChannelBilibiliSubChannelOfficialCompatOnly = new() - { - LauncherId = SdkStaticLauncherBilibiliId, - Key = SdkStaticLauncherBilibiliKey, - Channel = ChannelType.Bili, - SubChannel = SubChannelType.Official, - IsOversea = false, - IsNotCompatOnly = false, - }; - - private static readonly LaunchScheme ServerGlobalChannelDefaultSubChannelDefaultCompatOnly = new() - { - LauncherId = SdkStaticLauncherGlobalId, - Key = SdkStaticLauncherGlobalKey, - Channel = ChannelType.Default, - SubChannel = SubChannelType.Default, - IsOversea = true, - IsNotCompatOnly = false, - }; - - private static readonly LaunchScheme ServerGlobalChannelOfficialSubChannelDefault = new() - { - LauncherId = SdkStaticLauncherGlobalId, - Key = SdkStaticLauncherGlobalKey, - Channel = ChannelType.Official, - SubChannel = SubChannelType.Default, - IsOversea = true, - }; - - private static readonly LaunchScheme ServerGlobalChannelOfficialSubChannelOfficial = new() - { - LauncherId = SdkStaticLauncherGlobalId, - Key = SdkStaticLauncherGlobalKey, - Channel = ChannelType.Official, - SubChannel = SubChannelType.Official, - IsOversea = true, - }; - - private static readonly LaunchScheme ServerGlobalChannelOfficialSubChannelEpic = new() - { - LauncherId = SdkStaticLauncherGlobalId, - Key = SdkStaticLauncherGlobalKey, - Channel = ChannelType.Official, - SubChannel = SubChannelType.Epic, - IsOversea = true, - }; - - private static readonly LaunchScheme ServerGlobalChannelOfficialSubChannelGoogle = new() - { - LauncherId = SdkStaticLauncherGlobalId, - Key = SdkStaticLauncherGlobalKey, - Channel = ChannelType.Official, - SubChannel = SubChannelType.Google, - IsOversea = true, - }; - - /// - /// 获取已知的启动方案 - /// - /// 已知的启动方案 - public static List GetKnownSchemes() - { - return new List() - { - // 官服 - ServerChineseChannelDefaultSubChannelDefaultCompatOnly, - ServerChineseChannelOfficialSubChannelDefault, - ServerChineseChannelOfficialSubChannelOfficial, - ServerChineseChannelOfficialSubChannelNoTapTap, - ServerChineseChannelOfficialSubChannelEpicCompatOnly, - - // 渠道服 - ServerChineseChannelBilibiliSubChannelDefault, - ServerChineseChannelBilibiliSubChannelOfficialCompatOnly, - - // 国际服 - ServerGlobalChannelDefaultSubChannelDefaultCompatOnly, - ServerGlobalChannelOfficialSubChannelDefault, - ServerGlobalChannelOfficialSubChannelOfficial, - ServerGlobalChannelOfficialSubChannelEpic, - ServerGlobalChannelOfficialSubChannelGoogle, - }; - } -} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/LaunchScheme.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/LaunchScheme.cs index 523e0de6..5aeede35 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/LaunchScheme.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/LaunchScheme.cs @@ -9,7 +9,7 @@ namespace Snap.Hutao.Service.Game; /// 启动方案 /// [HighQuality] -internal sealed partial class LaunchScheme +internal partial class LaunchScheme { /// /// 显示名称 @@ -32,29 +32,29 @@ internal sealed partial class LaunchScheme /// /// 通道 /// - public ChannelType Channel { get; private set; } + public ChannelType Channel { get; private protected set; } /// /// 子通道 /// - public SubChannelType SubChannel { get; private set; } + public SubChannelType SubChannel { get; private protected set; } /// /// 启动器 Id /// - public int LauncherId { get; private set; } + public int LauncherId { get; private protected set; } /// /// API Key /// - public string Key { get; private set; } = default!; + public string Key { get; private protected set; } = default!; /// /// 是否为海外 /// - public bool IsOversea { get; private set; } + public bool IsOversea { get; private protected set; } - public bool IsNotCompatOnly { get; private set; } = true; + public bool IsNotCompatOnly { get; private protected set; } = true; /// /// 多通道相等 diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/LaunchSchemeBilibili.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/LaunchSchemeBilibili.cs new file mode 100644 index 00000000..cd5057be --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/LaunchSchemeBilibili.cs @@ -0,0 +1,22 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +using Snap.Hutao.Model.Intrinsic; + +namespace Snap.Hutao.Service.Game; + +internal sealed class LaunchSchemeBilibili : LaunchScheme +{ + private const int SdkStaticLauncherBilibiliId = 17; + private const string SdkStaticLauncherBilibiliKey = "KAtdSsoQ"; + + public LaunchSchemeBilibili(SubChannelType subChannel, bool isNotCompatOnly = true) + { + LauncherId = SdkStaticLauncherBilibiliId; + Key = SdkStaticLauncherBilibiliKey; + Channel = ChannelType.Bili; + SubChannel = subChannel; + IsOversea = false; + IsNotCompatOnly = isNotCompatOnly; + } +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/LaunchSchemeChinese.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/LaunchSchemeChinese.cs new file mode 100644 index 00000000..1e8f0e9f --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/LaunchSchemeChinese.cs @@ -0,0 +1,22 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +using Snap.Hutao.Model.Intrinsic; + +namespace Snap.Hutao.Service.Game; + +internal sealed class LaunchSchemeChinese : LaunchScheme +{ + private const int SdkStaticLauncherChineseId = 18; + private const string SdkStaticLauncherChineseKey = "eYd89JmJ"; + + public LaunchSchemeChinese(ChannelType channel, SubChannelType subChannel, bool isNotCompatOnly = true) + { + LauncherId = SdkStaticLauncherChineseId; + Key = SdkStaticLauncherChineseKey; + Channel = channel; + SubChannel = subChannel; + IsOversea = false; + IsNotCompatOnly = isNotCompatOnly; + } +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/LaunchSchemeOversea.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/LaunchSchemeOversea.cs new file mode 100644 index 00000000..2838d82e --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/LaunchSchemeOversea.cs @@ -0,0 +1,22 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +using Snap.Hutao.Model.Intrinsic; + +namespace Snap.Hutao.Service.Game; + +internal sealed class LaunchSchemeOversea : LaunchScheme +{ + private const int SdkStaticLauncherOverseaId = 10; + private const string SdkStaticLauncherOverseaKey = "gcStgarh"; + + public LaunchSchemeOversea(ChannelType channel, SubChannelType subChannel, bool isNotCompatOnly = true) + { + LauncherId = SdkStaticLauncherOverseaId; + Key = SdkStaticLauncherOverseaKey; + Channel = channel; + SubChannel = subChannel; + IsOversea = true; + IsNotCompatOnly = isNotCompatOnly; + } +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/ProcessInterop.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/ProcessInterop.cs index a1a4af71..15aafcd4 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/ProcessInterop.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/ProcessInterop.cs @@ -34,9 +34,9 @@ internal static class ProcessInterop .AppendIf("-popupwindow", options.IsBorderless) .AppendIf("-window-mode", options.IsExclusive, "exclusive") .Append("-screen-fullscreen", options.IsFullScreen ? 1 : 0) - .Append("-screen-width", options.ScreenWidth) - .Append("-screen-height", options.ScreenHeight) - .Append("-monitor", options.Monitor.Value) + .AppendIf("-screen-width", options.IsScreenWidthEnabled, options.ScreenWidth) + .AppendIf("-screen-height", options.IsScreenHeightEnabled, options.ScreenHeight) + .AppendIf("-monitor", options.IsMonitorEnabled, options.Monitor.Value) .ToString(); return new() diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Hutao/HutaoUserOptions.cs b/src/Snap.Hutao/Snap.Hutao/Service/Hutao/HutaoUserOptions.cs index 2dacefe0..f61058ff 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Hutao/HutaoUserOptions.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Hutao/HutaoUserOptions.cs @@ -4,6 +4,7 @@ using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Messaging; using Microsoft.Extensions.Options; +using Snap.Hutao.Core.Setting; using Snap.Hutao.Web.Hutao; using System.Text.RegularExpressions; @@ -62,8 +63,11 @@ internal sealed class HutaoUserOptions : ObservableObject, IOptions public HutaoUserOptions Value { get => this; } - public async ValueTask PostLoginSucceedAsync(HomaPassportClient passportClient, ITaskContext taskContext, string username, string? token) + public async ValueTask PostLoginSucceedAsync(HomaPassportClient passportClient, ITaskContext taskContext, string username, string password, string? token) { + LocalSetting.Set(SettingKeys.PassportUserName, username); + LocalSetting.Set(SettingKeys.PassportPassword, password); + await taskContext.SwitchToMainThreadAsync(); UserName = username; this.token = token; @@ -84,6 +88,9 @@ internal sealed class HutaoUserOptions : ObservableObject, IOptions response = await passportClient.LoginAsync(userName, passport, token).ConfigureAwait(false); + Web.Response.Response response = await passportClient.LoginAsync(userName, password, token).ConfigureAwait(false); if (response.IsOk()) { - if (await options.PostLoginSucceedAsync(passportClient, taskContext, userName, response.Data).ConfigureAwait(false)) + if (await options.PostLoginSucceedAsync(passportClient, taskContext, userName, password, response.Data).ConfigureAwait(false)) { isInitialized = true; } diff --git a/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj b/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj index 7782e62a..3b267b78 100644 --- a/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj +++ b/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj @@ -79,6 +79,7 @@ + @@ -307,6 +308,12 @@ + + + MSBuild:Compile + + + MSBuild:Compile diff --git a/src/Snap.Hutao/Snap.Hutao/View/Dialog/HutaoPassportLoginDialog.xaml b/src/Snap.Hutao/Snap.Hutao/View/Dialog/HutaoPassportLoginDialog.xaml index 3fef6d2f..c1d84662 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Dialog/HutaoPassportLoginDialog.xaml +++ b/src/Snap.Hutao/Snap.Hutao/View/Dialog/HutaoPassportLoginDialog.xaml @@ -13,7 +13,11 @@ mc:Ignorable="d"> - + - + @@ -28,7 +32,7 @@ - + \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/View/Dialog/HutaoPassportRegisterDialog.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/Dialog/HutaoPassportRegisterDialog.xaml.cs index e9801fcb..b2dbb09f 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Dialog/HutaoPassportRegisterDialog.xaml.cs +++ b/src/Snap.Hutao/Snap.Hutao/View/Dialog/HutaoPassportRegisterDialog.xaml.cs @@ -48,7 +48,7 @@ internal sealed partial class HutaoPassportRegisterDialog : ContentDialog return; } - HutaoResponse response = await homaPassportClient.VerifyAsync(UserName, false).ConfigureAwait(false); + HutaoResponse response = await homaPassportClient.RequestVerifyAsync(UserName, VerifyCodeRequestType.Registration).ConfigureAwait(false); infoBarService.Information(response.GetLocalizationMessage()); } } diff --git a/src/Snap.Hutao/Snap.Hutao/View/Dialog/HutaoPassportResetPasswordDialog.xaml b/src/Snap.Hutao/Snap.Hutao/View/Dialog/HutaoPassportResetPasswordDialog.xaml index 70345628..f388fc87 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Dialog/HutaoPassportResetPasswordDialog.xaml +++ b/src/Snap.Hutao/Snap.Hutao/View/Dialog/HutaoPassportResetPasswordDialog.xaml @@ -13,7 +13,11 @@ mc:Ignorable="d"> - + @@ -28,7 +32,7 @@ - + \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/View/Dialog/HutaoPassportResetPasswordDialog.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/Dialog/HutaoPassportResetPasswordDialog.xaml.cs index c88a0a93..480a71ce 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Dialog/HutaoPassportResetPasswordDialog.xaml.cs +++ b/src/Snap.Hutao/Snap.Hutao/View/Dialog/HutaoPassportResetPasswordDialog.xaml.cs @@ -48,7 +48,7 @@ internal sealed partial class HutaoPassportResetPasswordDialog : ContentDialog return; } - HutaoResponse response = await homaPassportClient.VerifyAsync(UserName, false).ConfigureAwait(false); + HutaoResponse response = await homaPassportClient.RequestVerifyAsync(UserName, VerifyCodeRequestType.ResetPassword).ConfigureAwait(false); infoBarService.Information(response.GetLocalizationMessage()); } } diff --git a/src/Snap.Hutao/Snap.Hutao/View/Dialog/HutaoPassportUnregisterDialog.xaml b/src/Snap.Hutao/Snap.Hutao/View/Dialog/HutaoPassportUnregisterDialog.xaml index 8b57b94c..e589664a 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Dialog/HutaoPassportUnregisterDialog.xaml +++ b/src/Snap.Hutao/Snap.Hutao/View/Dialog/HutaoPassportUnregisterDialog.xaml @@ -20,11 +20,26 @@ Severity="Error"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -110,12 +486,10 @@ - - - - - - + @@ -123,117 +497,9 @@ Margin="16,16,4,-8" cwa:ItemsReorderAnimation.Duration="0:0:0.1" ItemContainerStyle="{StaticResource LargeGridViewItemStyle}" + ItemTemplate="{StaticResource AvatarGridViewTemplate}" ItemsSource="{Binding Summary.Avatars}" - SelectedItem="{Binding SelectedAvatar, Mode=TwoWay}"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + SelectedItem="{Binding SelectedAvatar, Mode=TwoWay}"/> @@ -245,66 +511,10 @@ OpenPaneLength="{StaticResource CompatSplitViewOpenPaneLength2}" PaneBackground="Transparent"> - - - - - - - - - - - - - - - - - - - - - - - + @@ -449,12 +659,8 @@ Grid.Row="1" Grid.Column="0" Margin="16" + ItemsPanel="{StaticResource HorizontalStackPanelSpacing0Template}" ItemsSource="{Binding SelectedAvatar.Constellations}"> - - - - - - - - + ItemTemplate="{StaticResource AvatarConstellationTemplate}" + ItemsSource="{Binding SelectedAvatar.Skills}"/> @@ -598,221 +742,19 @@ HorizontalContentAlignment="Stretch" Background="{x:Null}" Header="{shcm:ResourceString Name=ViewPageAvatarPropertyHeader}"> - + - - - - - - - - - - - - - - - - - - - - - + ItemTemplate="{StaticResource AvatarPropertyTemplate}" + ItemsSource="{Binding SelectedAvatar.Properties}"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/CultivationPage.xaml b/src/Snap.Hutao/Snap.Hutao/View/Page/CultivationPage.xaml index ba5c34e4..33d02646 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Page/CultivationPage.xaml +++ b/src/Snap.Hutao/Snap.Hutao/View/Page/CultivationPage.xaml @@ -20,27 +20,219 @@ mc:Ignorable="d"> - + + + + + + + + + + + + + + + + + + - - - 0.4 - - - 1 - - + + + 0.4 + + + 1 + + - + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -85,6 +277,7 @@ @@ -95,158 +288,13 @@ MinItemWidth="300" MinRowSpacing="-4"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Visible - - - - - - - - - - Collapsed - - - - - - - - - - - - - - - - - - - @@ -257,42 +305,6 @@ MinItemWidth="300" MinRowSpacing="-4"/> - - - - - - - - - - - - - - - - - - - - - @@ -336,51 +348,15 @@ - + - - - - - - - - - - - - diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/DailyNotePage.xaml b/src/Snap.Hutao/Snap.Hutao/View/Page/DailyNotePage.xaml index 9ccec67a..48621191 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Page/DailyNotePage.xaml +++ b/src/Snap.Hutao/Snap.Hutao/View/Page/DailyNotePage.xaml @@ -27,6 +27,361 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -46,54 +401,27 @@ Label="{shcm:ResourceString Name=ViewPageDailyNoteVerify}"> - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/GachaLogPage.xaml b/src/Snap.Hutao/Snap.Hutao/View/Page/GachaLogPage.xaml index 76fe9c82..0f12787f 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Page/GachaLogPage.xaml +++ b/src/Snap.Hutao/Snap.Hutao/View/Page/GachaLogPage.xaml @@ -7,6 +7,7 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mxi="using:Microsoft.Xaml.Interactivity" + xmlns:mxic="using:Microsoft.Xaml.Interactions.Core" xmlns:shc="using:Snap.Hutao.Control" xmlns:shcb="using:Snap.Hutao.Control.Behavior" xmlns:shci="using:Snap.Hutao.Control.Image" @@ -21,6 +22,206 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + [SuppressMessage("", "CA1822")] - public List KnownSchemes { get => LaunchScheme.GetKnownSchemes(); } + public List KnownSchemes { get => KnownLaunchSchemes.Get(); } /// /// 当前选择的服务器方案 diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Setting/HutaoPassportViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Setting/HutaoPassportViewModel.cs index eb6bee68..f0709654 100644 --- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Setting/HutaoPassportViewModel.cs +++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Setting/HutaoPassportViewModel.cs @@ -31,12 +31,6 @@ internal sealed partial class HutaoPassportViewModel : Abstraction.ViewModel await Launcher.LaunchUriAsync("https://homa.snapgenshin.com/redeem.html".ToUri()); } - private static void SaveUserNameAndPassword(string username, string password) - { - LocalSetting.Set(SettingKeys.PassportUserName, username); - LocalSetting.Set(SettingKeys.PassportPassword, password); - } - [Command("RegisterCommand")] private async Task RegisterAsync() { @@ -56,9 +50,8 @@ internal sealed partial class HutaoPassportViewModel : Abstraction.ViewModel if (response.IsOk()) { - SaveUserNameAndPassword(username, password); infoBarService.Information(response.Message); - await hutaoUserOptions.PostLoginSucceedAsync(homaPassportClient, taskContext, username, response.Data).ConfigureAwait(false); + await hutaoUserOptions.PostLoginSucceedAsync(homaPassportClient, taskContext, username, password, response.Data).ConfigureAwait(false); } } } @@ -67,18 +60,18 @@ internal sealed partial class HutaoPassportViewModel : Abstraction.ViewModel private async Task UnregisterAsync() { HutaoPassportUnregisterDialog dialog = await contentDialogFactory.CreateInstanceAsync().ConfigureAwait(false); - ValueResult result = await dialog.GetInputAsync().ConfigureAwait(false); + ValueResult result = await dialog.GetInputAsync().ConfigureAwait(false); if (result.IsOk) { - (string username, string password) = result.Value; + (string username, string password, string verifyCode) = result.Value; - if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password)) + if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password) || string.IsNullOrEmpty(verifyCode)) { return; } - Response response = await homaPassportClient.UnregisterAsync(username, password).ConfigureAwait(false); + HutaoResponse response = await homaPassportClient.UnregisterAsync(username, password, verifyCode).ConfigureAwait(false); if (response.IsOk()) { @@ -109,10 +102,8 @@ internal sealed partial class HutaoPassportViewModel : Abstraction.ViewModel if (response.IsOk()) { - SaveUserNameAndPassword(username, password); infoBarService.Information(response.Message); - - await hutaoUserOptions.PostLoginSucceedAsync(homaPassportClient, taskContext, username, response.Data).ConfigureAwait(false); + await hutaoUserOptions.PostLoginSucceedAsync(homaPassportClient, taskContext, username, password, response.Data).ConfigureAwait(false); } } } @@ -121,6 +112,8 @@ internal sealed partial class HutaoPassportViewModel : Abstraction.ViewModel private void LogoutAsync() { hutaoUserOptions.LogoutOrUnregister(); + LocalSetting.Set(SettingKeys.PassportUserName, string.Empty); + LocalSetting.Set(SettingKeys.PassportPassword, string.Empty); } [Command("ResetPasswordCommand")] @@ -142,10 +135,8 @@ internal sealed partial class HutaoPassportViewModel : Abstraction.ViewModel if (response.IsOk()) { - SaveUserNameAndPassword(username, password); infoBarService.Information(response.Message); - - await hutaoUserOptions.PostLoginSucceedAsync(homaPassportClient, taskContext, username, response.Data).ConfigureAwait(false); + await hutaoUserOptions.PostLoginSucceedAsync(homaPassportClient, taskContext, username, password, response.Data).ConfigureAwait(false); } } } diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hutao/HomaPassportClient.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hutao/HomaPassportClient.cs index 8c813881..f2e52f9f 100644 --- a/src/Snap.Hutao/Snap.Hutao/Web/Hutao/HomaPassportClient.cs +++ b/src/Snap.Hutao/Snap.Hutao/Web/Hutao/HomaPassportClient.cs @@ -40,25 +40,29 @@ internal sealed partial class HomaPassportClient private readonly HutaoUserOptions hutaoUserOptions; private readonly HttpClient httpClient; - /// - /// 异步获取验证码 - /// - /// 邮箱 - /// 是否重置账号密码 - /// 取消令牌 - /// 响应 - public async ValueTask VerifyAsync(string email, bool isResetPassword, CancellationToken token = default) + public async ValueTask RequestVerifyAsync(string email, VerifyCodeRequestType requestType, CancellationToken token = default) { Dictionary data = new() { ["UserName"] = Encrypt(email), - ["IsResetPassword"] = isResetPassword, }; + if (requestType.HasFlag(VerifyCodeRequestType.ResetPassword)) + { + data["IsResetPassword"] = true; + } + + if (requestType.HasFlag(VerifyCodeRequestType.CancelRegistration)) + { + data["IsCancelRegistration"] = true; + } + HttpRequestMessageBuilder builder = httpRequestMessageBuilderFactory.Create() .SetRequestUri(HutaoEndpoints.PassportVerify) .PostJson(data); + await builder.TrySetTokenAsync(hutaoUserOptions).ConfigureAwait(false); + HutaoResponse? resp = await builder .TryCatchSendAsync(httpClient, logger, token) .ConfigureAwait(false); @@ -94,18 +98,21 @@ internal sealed partial class HomaPassportClient return HutaoResponse.DefaultIfNull(resp); } - public async ValueTask UnregisterAsync(string email, string password, CancellationToken token = default) + public async ValueTask UnregisterAsync(string email, string password, string verifyCode, CancellationToken token = default) { Dictionary data = new() { ["UserName"] = Encrypt(email), ["Password"] = Encrypt(password), + ["VerifyCode"] = Encrypt(verifyCode), }; HttpRequestMessageBuilder builder = httpRequestMessageBuilderFactory.Create() .SetRequestUri(HutaoEndpoints.PassportCancel) .PostJson(data); + await builder.TrySetTokenAsync(hutaoUserOptions).ConfigureAwait(false); + HutaoResponse? resp = await builder .TryCatchSendAsync(httpClient, logger, token) .ConfigureAwait(false); diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hutao/HutaoResponse.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hutao/HutaoResponse.cs index 37b54b81..56397a7f 100644 --- a/src/Snap.Hutao/Snap.Hutao/Web/Hutao/HutaoResponse.cs +++ b/src/Snap.Hutao/Snap.Hutao/Web/Hutao/HutaoResponse.cs @@ -1,7 +1,6 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. -using Snap.Hutao.Service.Notification; using System.Runtime.CompilerServices; namespace Snap.Hutao.Web.Hutao; diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hutao/VerifyCodeRequestType.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hutao/VerifyCodeRequestType.cs new file mode 100644 index 00000000..877ad67b --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Web/Hutao/VerifyCodeRequestType.cs @@ -0,0 +1,12 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +namespace Snap.Hutao.Web.Hutao; + +[Flags] +internal enum VerifyCodeRequestType +{ + Registration = 0b0000, + ResetPassword = 0b0001, + CancelRegistration = 0b0010, +} \ No newline at end of file