From 344e5cd31b894cbf8be1d83028c4e303f3640f76 Mon Sep 17 00:00:00 2001 From: DismissedLight <1686188646@qq.com> Date: Thu, 7 Jul 2022 15:48:52 +0800 Subject: [PATCH] add system backdrop mica --- src/Snap.Hutao/SettingsUI/SettingsUI.csproj | 2 +- .../Snap.Hutao.SourceGeneration.csproj | 1 + src/Snap.Hutao/Snap.Hutao.sln | 12 +- .../Backdroping/BackbdropFallBackBehavior.cs | 20 ++ .../Control/Backdroping/SystemBackdrop.cs | 184 ++++++++++++++++++ src/Snap.Hutao/Snap.Hutao/Core/Property.cs | 2 +- .../Snap.Hutao/Core/Setting/SettingKeys.cs | 20 ++ src/Snap.Hutao/Snap.Hutao/Core/Win32/POINT.cs | 30 +++ src/Snap.Hutao/Snap.Hutao/Core/Win32/RECT.cs | 129 ++++++++++++ .../Core/Win32/ShowWindowCommand.cs | 89 +++++++++ .../Snap.Hutao/Core/Win32/User32.cs | 65 +++++++ .../Snap.Hutao/Core/Win32/WINDOWPLACEMENT.cs | 60 ++++++ .../Snap.Hutao/Extension/EnumExtensions.cs | 27 +++ src/Snap.Hutao/Snap.Hutao/MainWindow.xaml | 2 +- src/Snap.Hutao/Snap.Hutao/MainWindow.xaml.cs | 62 +++++- .../Model/Annotation/DescriptionAttribute.cs | 25 +++ .../Model/Intrinsic/FightProperty.cs | 18 ++ .../Model/Metadata/Avatar/ProudableSkill.cs | 1 - .../Model/Metadata/Converter/IconConverter.cs | 26 +++ .../Metadata/Converter/SideIconConverter.cs | 26 +++ .../Snap.Hutao/Package.appxmanifest | 2 +- .../Snap.Hutao/Service/User/IUserService.cs | 3 +- .../Snap.Hutao/Service/User/UserAddResult.cs | 7 +- .../Snap.Hutao/Service/User/UserService.cs | 63 ++++-- src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj | 6 + .../Snap.Hutao/View/Dialog/UserDialog.xaml.cs | 7 +- src/Snap.Hutao/Snap.Hutao/View/MainView.xaml | 6 + .../Snap.Hutao/View/MainView.xaml.cs | 2 +- .../Snap.Hutao/View/Page/WikiAvatarPage.xaml | 33 ++++ .../View/Page/WikiAvatarPage.xaml.cs | 35 ++++ src/Snap.Hutao/Snap.Hutao/View/UserView.xaml | 4 +- .../Snap.Hutao/ViewModel/UserViewModel.cs | 30 +-- .../ViewModel/WikiAvatarViewModel.cs | 57 ++++++ .../Hk4e/Common/Announcement/Announcement.cs | 4 +- .../Snap.Hutao/Web/Hoyolab/PlayerUid.cs | 2 +- 35 files changed, 1004 insertions(+), 58 deletions(-) create mode 100644 src/Snap.Hutao/Snap.Hutao/Control/Backdroping/BackbdropFallBackBehavior.cs create mode 100644 src/Snap.Hutao/Snap.Hutao/Control/Backdroping/SystemBackdrop.cs create mode 100644 src/Snap.Hutao/Snap.Hutao/Core/Win32/POINT.cs create mode 100644 src/Snap.Hutao/Snap.Hutao/Core/Win32/RECT.cs create mode 100644 src/Snap.Hutao/Snap.Hutao/Core/Win32/ShowWindowCommand.cs create mode 100644 src/Snap.Hutao/Snap.Hutao/Core/Win32/User32.cs create mode 100644 src/Snap.Hutao/Snap.Hutao/Core/Win32/WINDOWPLACEMENT.cs create mode 100644 src/Snap.Hutao/Snap.Hutao/Extension/EnumExtensions.cs create mode 100644 src/Snap.Hutao/Snap.Hutao/Model/Annotation/DescriptionAttribute.cs create mode 100644 src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/IconConverter.cs create mode 100644 src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/SideIconConverter.cs create mode 100644 src/Snap.Hutao/Snap.Hutao/View/Page/WikiAvatarPage.xaml create mode 100644 src/Snap.Hutao/Snap.Hutao/View/Page/WikiAvatarPage.xaml.cs create mode 100644 src/Snap.Hutao/Snap.Hutao/ViewModel/WikiAvatarViewModel.cs diff --git a/src/Snap.Hutao/SettingsUI/SettingsUI.csproj b/src/Snap.Hutao/SettingsUI/SettingsUI.csproj index bc952b96..157821f1 100644 --- a/src/Snap.Hutao/SettingsUI/SettingsUI.csproj +++ b/src/Snap.Hutao/SettingsUI/SettingsUI.csproj @@ -11,7 +11,7 @@ - + diff --git a/src/Snap.Hutao/Snap.Hutao.SourceGeneration/Snap.Hutao.SourceGeneration.csproj b/src/Snap.Hutao/Snap.Hutao.SourceGeneration/Snap.Hutao.SourceGeneration.csproj index 9dd6ef85..003c57a2 100644 --- a/src/Snap.Hutao/Snap.Hutao.SourceGeneration/Snap.Hutao.SourceGeneration.csproj +++ b/src/Snap.Hutao/Snap.Hutao.SourceGeneration/Snap.Hutao.SourceGeneration.csproj @@ -5,6 +5,7 @@ false latest enable + x64 diff --git a/src/Snap.Hutao/Snap.Hutao.sln b/src/Snap.Hutao/Snap.Hutao.sln index bb171023..c5c47ce6 100644 --- a/src/Snap.Hutao/Snap.Hutao.sln +++ b/src/Snap.Hutao/Snap.Hutao.sln @@ -62,24 +62,24 @@ Global {DCA5678C-896E-49FB-97A7-5A504A5CFF17}.Release|Any CPU.Build.0 = Release|Any CPU {DCA5678C-896E-49FB-97A7-5A504A5CFF17}.Release|arm64.ActiveCfg = Release|Any CPU {DCA5678C-896E-49FB-97A7-5A504A5CFF17}.Release|arm64.Build.0 = Release|Any CPU - {DCA5678C-896E-49FB-97A7-5A504A5CFF17}.Release|x64.ActiveCfg = Release|Any CPU - {DCA5678C-896E-49FB-97A7-5A504A5CFF17}.Release|x64.Build.0 = Release|Any CPU + {DCA5678C-896E-49FB-97A7-5A504A5CFF17}.Release|x64.ActiveCfg = Release|x64 + {DCA5678C-896E-49FB-97A7-5A504A5CFF17}.Release|x64.Build.0 = Release|x64 {DCA5678C-896E-49FB-97A7-5A504A5CFF17}.Release|x86.ActiveCfg = Release|Any CPU {DCA5678C-896E-49FB-97A7-5A504A5CFF17}.Release|x86.Build.0 = Release|Any CPU {8B96721E-5604-47D2-9B72-06FEBAD0CE00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8B96721E-5604-47D2-9B72-06FEBAD0CE00}.Debug|Any CPU.Build.0 = Debug|Any CPU {8B96721E-5604-47D2-9B72-06FEBAD0CE00}.Debug|arm64.ActiveCfg = Debug|Any CPU {8B96721E-5604-47D2-9B72-06FEBAD0CE00}.Debug|arm64.Build.0 = Debug|Any CPU - {8B96721E-5604-47D2-9B72-06FEBAD0CE00}.Debug|x64.ActiveCfg = Debug|Any CPU - {8B96721E-5604-47D2-9B72-06FEBAD0CE00}.Debug|x64.Build.0 = Debug|Any CPU + {8B96721E-5604-47D2-9B72-06FEBAD0CE00}.Debug|x64.ActiveCfg = Debug|x64 + {8B96721E-5604-47D2-9B72-06FEBAD0CE00}.Debug|x64.Build.0 = Debug|x64 {8B96721E-5604-47D2-9B72-06FEBAD0CE00}.Debug|x86.ActiveCfg = Debug|Any CPU {8B96721E-5604-47D2-9B72-06FEBAD0CE00}.Debug|x86.Build.0 = Debug|Any CPU {8B96721E-5604-47D2-9B72-06FEBAD0CE00}.Release|Any CPU.ActiveCfg = Release|Any CPU {8B96721E-5604-47D2-9B72-06FEBAD0CE00}.Release|Any CPU.Build.0 = Release|Any CPU {8B96721E-5604-47D2-9B72-06FEBAD0CE00}.Release|arm64.ActiveCfg = Release|Any CPU {8B96721E-5604-47D2-9B72-06FEBAD0CE00}.Release|arm64.Build.0 = Release|Any CPU - {8B96721E-5604-47D2-9B72-06FEBAD0CE00}.Release|x64.ActiveCfg = Release|Any CPU - {8B96721E-5604-47D2-9B72-06FEBAD0CE00}.Release|x64.Build.0 = Release|Any CPU + {8B96721E-5604-47D2-9B72-06FEBAD0CE00}.Release|x64.ActiveCfg = Release|x64 + {8B96721E-5604-47D2-9B72-06FEBAD0CE00}.Release|x64.Build.0 = Release|x64 {8B96721E-5604-47D2-9B72-06FEBAD0CE00}.Release|x86.ActiveCfg = Release|Any CPU {8B96721E-5604-47D2-9B72-06FEBAD0CE00}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection diff --git a/src/Snap.Hutao/Snap.Hutao/Control/Backdroping/BackbdropFallBackBehavior.cs b/src/Snap.Hutao/Snap.Hutao/Control/Backdroping/BackbdropFallBackBehavior.cs new file mode 100644 index 00000000..678a2b43 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Control/Backdroping/BackbdropFallBackBehavior.cs @@ -0,0 +1,20 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +namespace Snap.Hutao.Control.HostBackdrop; + +/// +/// 回退行为 +/// +public enum BackbdropFallBackBehavior +{ + /// + /// 回退到无 + /// + None, + + /// + /// 回退到亚克力 + /// + Acrylic, +} diff --git a/src/Snap.Hutao/Snap.Hutao/Control/Backdroping/SystemBackdrop.cs b/src/Snap.Hutao/Snap.Hutao/Control/Backdroping/SystemBackdrop.cs new file mode 100644 index 00000000..b9286d1b --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Control/Backdroping/SystemBackdrop.cs @@ -0,0 +1,184 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.UI.Composition; +using Microsoft.UI.Composition.SystemBackdrops; +using Microsoft.UI.Xaml; +using System.Runtime.InteropServices; +using Windows.System; +using WinRT; + +namespace Snap.Hutao.Control.HostBackdrop; + +/// +/// 系统背景帮助类 +/// +public class SystemBackdrop +{ + private readonly Window window; + private readonly BackbdropFallBackBehavior fallBackBehavior; + + private WindowsSystemDispatcherQueueHelper? dispatcherQueueHelper; + private ISystemBackdropControllerWithTargets? backdropController; + private SystemBackdropConfiguration? configurationSource; + + /// + /// 构造一个新的系统背景帮助类 + /// + /// 窗体 + /// 回退行为 + public SystemBackdrop(Window window, BackbdropFallBackBehavior fallBackBehavior = BackbdropFallBackBehavior.Acrylic) + { + this.window = window; + this.fallBackBehavior = fallBackBehavior; + } + + private enum BackDropType + { + None, + Acrylic, + Mica, + } + + /// + /// 尝试设置背景 + /// + /// 是否设置成功 + public bool TrySetBackdrop() + { + BackDropType targetBackDropType = ResolveBackdropType(); + + if (targetBackDropType == BackDropType.None) + { + return false; + } + else + { + dispatcherQueueHelper = new WindowsSystemDispatcherQueueHelper(); + dispatcherQueueHelper.EnsureWindowsSystemDispatcherQueueController(); + + // Hooking up the policy object + configurationSource = new SystemBackdropConfiguration(); + window.Activated += WindowActivated; + window.Closed += WindowClosed; + ((FrameworkElement)window.Content).ActualThemeChanged += WindowThemeChanged; + + // Initial configuration state. + configurationSource.IsInputActive = true; + SetConfigurationSourceTheme(); + + backdropController = targetBackDropType switch + { + BackDropType.Mica => new MicaController(), + BackDropType.Acrylic => new DesktopAcrylicController(), + _ => throw Must.NeverHappen(), + }; + + ICompositionSupportsSystemBackdrop target = window.As(); + backdropController.AddSystemBackdropTarget(target); + backdropController.SetSystemBackdropConfiguration(configurationSource); + + return true; + } + } + + private BackDropType ResolveBackdropType() + { + BackDropType targetBackDropType = BackDropType.None; + if (MicaController.IsSupported()) + { + targetBackDropType = BackDropType.Mica; + } + else + { + if (fallBackBehavior == BackbdropFallBackBehavior.Acrylic) + { + if (DesktopAcrylicController.IsSupported()) + { + targetBackDropType = BackDropType.Acrylic; + } + } + } + + return targetBackDropType; + } + + private void WindowActivated(object sender, WindowActivatedEventArgs args) + { + Must.NotNull(configurationSource!); + configurationSource.IsInputActive = args.WindowActivationState != WindowActivationState.Deactivated; + } + + private void WindowClosed(object sender, WindowEventArgs args) + { + // Make sure any Mica/Acrylic controller is disposed so it doesn't try to + // use this closed window. + if (backdropController != null) + { + backdropController.Dispose(); + backdropController = null; + } + + window.Activated -= WindowActivated; + configurationSource = null; + } + + private void WindowThemeChanged(FrameworkElement sender, object args) + { + if (configurationSource != null) + { + SetConfigurationSourceTheme(); + } + } + + private void SetConfigurationSourceTheme() + { + Must.NotNull(configurationSource!).Theme = ((FrameworkElement)window.Content).ActualTheme switch + { + ElementTheme.Dark => SystemBackdropTheme.Dark, + ElementTheme.Light => SystemBackdropTheme.Light, + ElementTheme.Default => SystemBackdropTheme.Default, + _ => throw Must.NeverHappen(), + }; + } + + private class WindowsSystemDispatcherQueueHelper + { + private object dispatcherQueueController = null!; + + /// + /// 确保系统调度队列控制器存在 + /// + public void EnsureWindowsSystemDispatcherQueueController() + { + if (DispatcherQueue.GetForCurrentThread() != null) + { + // one already exists, so we'll just use it. + return; + } + + if (dispatcherQueueController == null) + { + DispatcherQueueOptions options; + options.DwSize = Marshal.SizeOf(typeof(DispatcherQueueOptions)); + options.ThreadType = 2; // DQTYPE_THREAD_CURRENT + options.ApartmentType = 2; // DQTAT_COM_STA + + _ = CreateDispatcherQueueController(options, ref dispatcherQueueController!); + } + } + + [DllImport("CoreMessaging.dll")] + private static extern int CreateDispatcherQueueController( + [In] DispatcherQueueOptions options, + [In, Out, MarshalAs(UnmanagedType.IUnknown)] ref object dispatcherQueueController); + + [StructLayout(LayoutKind.Sequential)] + private struct DispatcherQueueOptions + { + internal int DwSize; + internal int ThreadType; + internal int ApartmentType; + } + } +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Property.cs b/src/Snap.Hutao/Snap.Hutao/Core/Property.cs index 218acaff..52e99899 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/Property.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/Property.cs @@ -81,4 +81,4 @@ internal static class Property { return DependencyProperty.RegisterAttached(name, typeof(TProperty), typeof(TOwner), new(callback)); } -} +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Setting/SettingKeys.cs b/src/Snap.Hutao/Snap.Hutao/Core/Setting/SettingKeys.cs index c6138b23..dd757a36 100644 --- a/src/Snap.Hutao/Snap.Hutao/Core/Setting/SettingKeys.cs +++ b/src/Snap.Hutao/Snap.Hutao/Core/Setting/SettingKeys.cs @@ -12,4 +12,24 @@ internal static class SettingKeys /// 上次打开时App的版本 /// public const string LastAppVersion = "LastAppVersion"; + + /// + /// 窗体左侧 + /// + public const string WindowLeft = "WindowLeft"; + + /// + /// 窗体顶部 + /// + public const string WindowTop = "WindowTop"; + + /// + /// 窗体右侧 + /// + public const string WindowRight = "WindowRight"; + + /// + /// 窗体底部 + /// + public const string WindowBottom = "WindowBottom"; } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Win32/POINT.cs b/src/Snap.Hutao/Snap.Hutao/Core/Win32/POINT.cs new file mode 100644 index 00000000..adff3792 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Core/Win32/POINT.cs @@ -0,0 +1,30 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +using System.Runtime.InteropServices; + +namespace Snap.Hutao.Core.Win32; + +[SuppressMessage("", "SA1600")] +[StructLayout(LayoutKind.Sequential)] +public struct POINT +{ + public int X; + public int Y; + + public POINT(int x, int y) + { + this.X = x; + this.Y = y; + } + + public static implicit operator System.Drawing.Point(POINT p) + { + return new System.Drawing.Point(p.X, p.Y); + } + + public static implicit operator POINT(System.Drawing.Point p) + { + return new POINT(p.X, p.Y); + } +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Win32/RECT.cs b/src/Snap.Hutao/Snap.Hutao/Core/Win32/RECT.cs new file mode 100644 index 00000000..781b1de1 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Core/Win32/RECT.cs @@ -0,0 +1,129 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +using System.Globalization; +using System.Runtime.InteropServices; + +namespace Snap.Hutao.Core.Win32; + +[SuppressMessage("", "SA1132")] +[SuppressMessage("", "SA1600")] +[StructLayout(LayoutKind.Sequential)] +public struct RECT +{ + public int Left, Top, Right, Bottom; + + public RECT(int left, int top, int right, int bottom) + { + Left = left; + Top = top; + Right = right; + Bottom = bottom; + } + + public RECT(System.Drawing.Rectangle r) + : this(r.Left, r.Top, r.Right, r.Bottom) + { + } + + public int X + { + get => Left; + set + { + Right -= Left - value; + Left = value; + } + } + + public int Y + { + get => Top; + set + { + Bottom -= Top - value; + Top = value; + } + } + + public int Height + { + get => Bottom - Top; + set => Bottom = value + Top; + } + + public int Width + { + get => Right - Left; + set => Right = value + Left; + } + + public System.Drawing.Point Location + { + get => new(Left, Top); + set + { + X = value.X; + Y = value.Y; + } + } + + public System.Drawing.Size Size + { + get => new(Width, Height); + set + { + Width = value.Width; + Height = value.Height; + } + } + + public static implicit operator System.Drawing.Rectangle(RECT r) + { + return new System.Drawing.Rectangle(r.Left, r.Top, r.Width, r.Height); + } + + public static implicit operator RECT(System.Drawing.Rectangle r) + { + return new RECT(r); + } + + public static bool operator ==(RECT r1, RECT r2) + { + return r1.Equals(r2); + } + + public static bool operator !=(RECT r1, RECT r2) + { + return !r1.Equals(r2); + } + + public bool Equals(RECT r) + { + return r.Left == Left && r.Top == Top && r.Right == Right && r.Bottom == Bottom; + } + + public override bool Equals(object? obj) + { + if (obj is RECT rect) + { + return Equals(rect); + } + else if (obj is System.Drawing.Rectangle rectangle) + { + return Equals(new RECT(rectangle)); + } + + return false; + } + + public override int GetHashCode() + { + return ((System.Drawing.Rectangle)this).GetHashCode(); + } + + public override string ToString() + { + return string.Format(CultureInfo.CurrentCulture, "{{Left={0},Top={1},Right={2},Bottom={3}}}", Left, Top, Right, Bottom); + } +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Win32/ShowWindowCommand.cs b/src/Snap.Hutao/Snap.Hutao/Core/Win32/ShowWindowCommand.cs new file mode 100644 index 00000000..a0821434 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Core/Win32/ShowWindowCommand.cs @@ -0,0 +1,89 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +namespace Snap.Hutao.Core.Win32; + +[SuppressMessage("", "SA1600")] +public enum ShowWindowCommand +{ + /// + /// Hides the window and activates another window. + /// + Hide = 0, + + /// + /// Activates and displays a window. If the window is minimized or + /// maximized, the system restores it to its original size and position. + /// An application should specify this flag when displaying the window + /// for the first time. + /// + Normal = 1, + + /// + /// Activates the window and displays it as a minimized window. + /// + ShowMinimized = 2, + + /// + /// Maximizes the specified window. + /// + Maximize = 3, // is this the right value? + + /// + /// Activates the window and displays it as a maximized window. + /// + ShowMaximized = 3, + + /// + /// Displays a window in its most recent size and position. This value + /// is similar to , except + /// the window is not activated. + /// + ShowNoActivate = 4, + + /// + /// Activates the window and displays it in its current size and position. + /// + Show = 5, + + /// + /// Minimizes the specified window and activates the next top-level + /// window in the Z order. + /// + Minimize = 6, + + /// + /// Displays the window as a minimized window. This value is similar to + /// , except the + /// window is not activated. + /// + ShowMinNoActive = 7, + + /// + /// Displays the window in its current size and position. This value is + /// similar to , except the + /// window is not activated. + /// + ShowNA = 8, + + /// + /// Activates and displays the window. If the window is minimized or + /// maximized, the system restores it to its original size and position. + /// An application should specify this flag when restoring a minimized window. + /// + Restore = 9, + + /// + /// Sets the show state based on the SW_* value specified in the + /// STARTUPINFO structure passed to the CreateProcess function by the + /// program that started the application. + /// + ShowDefault = 10, + + /// + /// Windows 2000/XP: Minimizes a window, even if the thread + /// that owns the window is not responding. This flag should only be + /// used when minimizing windows from a different thread. + /// + ForceMinimize = 11, +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Win32/User32.cs b/src/Snap.Hutao/Snap.Hutao/Core/Win32/User32.cs new file mode 100644 index 00000000..69ff9d9f --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Core/Win32/User32.cs @@ -0,0 +1,65 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +using System.Runtime.InteropServices; + +namespace Snap.Hutao.Core.Win32; + +/// +/// 包含 user32.dll 平台调用的代码 +/// +internal static class User32 +{ + [SuppressMessage("", "SA1600")] + [DllImport("user32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool GetWindowPlacement(IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl); + + /// + /// Sets the show state and the restored, minimized, and maximized positions of the specified window. + /// + /// + /// A handle to the window. + /// + /// + /// A pointer to a WINDOWPLACEMENT structure that specifies the new show state and window positions. + /// + /// Before calling SetWindowPlacement, set the length member of the WINDOWPLACEMENT structure to sizeof(WINDOWPLACEMENT). SetWindowPlacement fails if the length member is not set correctly. + /// + /// + /// + /// If the function succeeds, the return value is nonzero. + /// + /// If the function fails, the return value is zero. To get extended error information, call GetLastError. + /// + /// + [DllImport("user32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool SetWindowPlacement(IntPtr hWnd, [In] ref WINDOWPLACEMENT lpwndpl); + + /// + /// Changes the text of the specified window's title bar (if it has one). If the specified window is a control, the + /// text of the control is changed. However, SetWindowText cannot change the text of a control in another application. + /// + /// Go to for more + /// information + /// + /// + /// C++ ( hWnd [in]. Type: HWND )
A handle to the window or control whose text is to be changed. + /// C++ ( lpString [in, optional]. Type: LPCTSTR )
The new title or control text. + /// + /// If the function succeeds, the return value is nonzero. If the function fails, the return value is zero.
+ /// To get extended error information, call GetLastError. + ///
+ /// + /// If the target window is owned by the current process, causes a WM_SETTEXT message to + /// be sent to the specified window or control. If the control is a list box control created with the WS_CAPTION style, + /// however, sets the text for the control, not for the list box entries.
To set the + /// text of a control in another process, send the WM_SETTEXT message directly instead of calling + /// . The function does not expand tab characters (ASCII code + /// 0x09). Tab characters are displayed as vertical bar(|) characters.
For an example go to + /// Sending a Message. + ///
+ [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] + public static extern bool SetWindowText(IntPtr hwnd, string lpString); +} diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Win32/WINDOWPLACEMENT.cs b/src/Snap.Hutao/Snap.Hutao/Core/Win32/WINDOWPLACEMENT.cs new file mode 100644 index 00000000..033a0950 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Core/Win32/WINDOWPLACEMENT.cs @@ -0,0 +1,60 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +using System.Runtime.InteropServices; + +namespace Snap.Hutao.Core.Win32; + +/// +/// Contains information about the placement of a window on the screen. +/// +[Serializable] +[StructLayout(LayoutKind.Sequential)] +internal struct WINDOWPLACEMENT +{ + /// + /// The length of the structure, in bytes. Before calling the GetWindowPlacement or SetWindowPlacement functions, set this member to sizeof(WINDOWPLACEMENT). + /// + /// GetWindowPlacement and SetWindowPlacement fail if this member is not set correctly. + /// + /// + public int Length; + + /// + /// Specifies flags that control the position of the minimized window and the method by which the window is restored. + /// + public int Flags; + + /// + /// The current show state of the window. + /// + public ShowWindowCommand ShowCmd; + + /// + /// The coordinates of the window's upper-left corner when the window is minimized. + /// + public POINT MinPosition; + + /// + /// The coordinates of the window's upper-left corner when the window is maximized. + /// + public POINT MaxPosition; + + /// + /// The window's coordinates when the window is in the restored position. + /// + public RECT NormalPosition; + + /// + /// Gets the default (empty) value. + /// + public static WINDOWPLACEMENT Default + { + get + { + WINDOWPLACEMENT result = default(WINDOWPLACEMENT); + result.Length = Marshal.SizeOf(result); + return result; + } + } +} diff --git a/src/Snap.Hutao/Snap.Hutao/Extension/EnumExtensions.cs b/src/Snap.Hutao/Snap.Hutao/Extension/EnumExtensions.cs new file mode 100644 index 00000000..2005005d --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Extension/EnumExtensions.cs @@ -0,0 +1,27 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +using System.Reflection; + +namespace Snap.Hutao.Extension; + +/// +/// 枚举拓展 +/// +public static class EnumExtensions +{ + /// + /// 获取枚举的描述 + /// + /// 枚举的类型 + /// 枚举值 + /// 描述 + public static string GetDescription(this TEnum @enum) + where TEnum : struct, Enum + { + string enumName = Must.NotNull(Enum.GetName(@enum)!); + FieldInfo? field = @enum.GetType().GetField(enumName); + DescriptionAttribute? attr = field?.GetCustomAttribute(); + return attr?.Description ?? enumName; + } +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/MainWindow.xaml b/src/Snap.Hutao/Snap.Hutao/MainWindow.xaml index 00f8412f..e98cc4a6 100644 --- a/src/Snap.Hutao/Snap.Hutao/MainWindow.xaml +++ b/src/Snap.Hutao/Snap.Hutao/MainWindow.xaml @@ -8,7 +8,7 @@ mc:Ignorable="d" Closed="MainWindowClosed"> - + diff --git a/src/Snap.Hutao/Snap.Hutao/MainWindow.xaml.cs b/src/Snap.Hutao/Snap.Hutao/MainWindow.xaml.cs index ab7740ef..02437512 100644 --- a/src/Snap.Hutao/Snap.Hutao/MainWindow.xaml.cs +++ b/src/Snap.Hutao/Snap.Hutao/MainWindow.xaml.cs @@ -3,6 +3,12 @@ using Microsoft.UI.Xaml; using Snap.Hutao.Context.Database; +using Snap.Hutao.Control.HostBackdrop; +using Snap.Hutao.Core.Setting; +using Snap.Hutao.Core.Win32; +using System.Drawing; +using System.Runtime.InteropServices; +using WinRT.Interop; namespace Snap.Hutao; @@ -13,22 +19,76 @@ namespace Snap.Hutao; public sealed partial class MainWindow : Window { private readonly AppDbContext appDbContext; + private readonly ILogger logger; + private readonly IntPtr handle; /// /// 构造一个新的主窗体 /// /// 数据库上下文 - public MainWindow(AppDbContext appDbContext) + /// 日志器 + public MainWindow(AppDbContext appDbContext, ILogger logger) { this.appDbContext = appDbContext; + this.logger = logger; InitializeComponent(); + ExtendsContentIntoTitleBar = true; SetTitleBar(TitleBarView.DragableArea); + + handle = WindowNative.GetWindowHandle(this); + InitializeWindow(); + } + + private static RECT RetriveWindowRect() + { + int left = LocalSetting.GetValueType(SettingKeys.WindowLeft); + int top = LocalSetting.GetValueType(SettingKeys.WindowTop); + int right = LocalSetting.GetValueType(SettingKeys.WindowRight); + int bottom = LocalSetting.GetValueType(SettingKeys.WindowBottom); + + return new RECT(left, top, right, bottom); + } + + private void InitializeWindow() + { + RECT rect = RetriveWindowRect(); + if (rect.Size.IsEmpty) + { + return; + } + + WINDOWPLACEMENT windowPlacement = new() + { + Length = Marshal.SizeOf(), + MaxPosition = new Point(-1, -1), + NormalPosition = rect, + ShowCmd = ShowWindowCommand.Normal, + }; + + User32.SetWindowPlacement(handle, ref windowPlacement); + User32.SetWindowText(handle, "胡桃"); + + bool micaApplied = new SystemBackdrop(this).TrySetBackdrop(); + logger.LogInformation("{name} 设置{result}", nameof(SystemBackdrop), micaApplied ? "成功" : "失败"); + } + + private void SaveWindowRect() + { + WINDOWPLACEMENT windowPlacement = WINDOWPLACEMENT.Default; + User32.GetWindowPlacement(handle, ref windowPlacement); + + LocalSetting.SetValueType(SettingKeys.WindowLeft, windowPlacement.NormalPosition.Left); + LocalSetting.SetValueType(SettingKeys.WindowTop, windowPlacement.NormalPosition.Top); + LocalSetting.SetValueType(SettingKeys.WindowRight, windowPlacement.NormalPosition.Right); + LocalSetting.SetValueType(SettingKeys.WindowBottom, windowPlacement.NormalPosition.Bottom); } private void MainWindowClosed(object sender, WindowEventArgs args) { + SaveWindowRect(); + // save datebase int changes = appDbContext.SaveChanges(); Verify.Operation(changes == 0, "存在可避免的未经处理的数据库更改"); diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Annotation/DescriptionAttribute.cs b/src/Snap.Hutao/Snap.Hutao/Model/Annotation/DescriptionAttribute.cs new file mode 100644 index 00000000..9b73569c --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Model/Annotation/DescriptionAttribute.cs @@ -0,0 +1,25 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +namespace Snap.Hutao.Model.Annotation; + +/// +/// 枚举的文本描述特性 +/// +[AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = false)] +internal class DescriptionAttribute : Attribute +{ + /// + /// 构造一个新的枚举的文本描述特性 + /// + /// 描述 + public DescriptionAttribute(string description) + { + Description = description; + } + + /// + /// 获取文本描述 + /// + public string Description { get; init; } +} diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Intrinsic/FightProperty.cs b/src/Snap.Hutao/Snap.Hutao/Model/Intrinsic/FightProperty.cs index 1a944118..21af660e 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Intrinsic/FightProperty.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Intrinsic/FightProperty.cs @@ -17,6 +17,7 @@ public enum FightProperty /// /// 基础生命值 /// + [Description("基础生命值")] FIGHT_PROP_BASE_HP = 1, /// @@ -27,11 +28,13 @@ public enum FightProperty /// /// 生命值加成百分比 /// + [Description("生命值")] FIGHT_PROP_HP_PERCENT = 3, /// /// 基础攻击力 /// + [Description("基础攻击力")] FIGHT_PROP_BASE_ATTACK = 4, /// @@ -42,11 +45,13 @@ public enum FightProperty /// /// 攻击力百分比 /// + [Description("攻击力")] FIGHT_PROP_ATTACK_PERCENT = 6, /// /// 基础防御力 /// + [Description("基础防御力")] FIGHT_PROP_BASE_DEFENSE = 7, /// @@ -57,6 +62,7 @@ public enum FightProperty /// /// 防御力百分比 /// + [Description("防御力")] FIGHT_PROP_DEFENSE_PERCENT = 9, /// @@ -82,6 +88,7 @@ public enum FightProperty /// /// 暴击率 /// + [Description("暴击率")] FIGHT_PROP_CRITICAL = 20, /// @@ -92,11 +99,13 @@ public enum FightProperty /// /// 暴击伤害 /// + [Description("暴击伤害")] FIGHT_PROP_CRITICAL_HURT = 22, /// /// 元素充能效率 /// + [Description("元素充能效率")] FIGHT_PROP_CHARGE_EFFICIENCY = 23, /// @@ -112,6 +121,7 @@ public enum FightProperty /// /// 治疗提升 /// + [Description("治疗加成")] FIGHT_PROP_HEAL_ADD = 26, /// @@ -122,6 +132,7 @@ public enum FightProperty /// /// 元素精通 /// + [Description("元素精通")] FIGHT_PROP_ELEMENT_MASTERY = 28, /// @@ -132,6 +143,7 @@ public enum FightProperty /// /// 物理伤害加成 /// + [Description("物理伤害加成")] FIGHT_PROP_PHYSICAL_ADD_HURT = 30, /// @@ -147,16 +159,19 @@ public enum FightProperty /// /// 火元素伤害加成 /// + [Description("火元素伤害加成")] FIGHT_PROP_FIRE_ADD_HURT = 40, /// /// 雷元素伤害加成 /// + [Description("雷元素伤害加成")] FIGHT_PROP_ELEC_ADD_HURT = 41, /// /// 水元素伤害加成 /// + [Description("水元素伤害加成")] FIGHT_PROP_WATER_ADD_HURT = 42, /// @@ -167,16 +182,19 @@ public enum FightProperty /// /// 风元素伤害加成 /// + [Description("风元素伤害加成")] FIGHT_PROP_WIND_ADD_HURT = 44, /// /// 岩元素伤害加成 /// + [Description("岩元素伤害加成")] FIGHT_PROP_ROCK_ADD_HURT = 45, /// /// 冰元素伤害加成 /// + [Description("冰元素伤害加成")] FIGHT_PROP_ICE_ADD_HURT = 46, /// diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Avatar/ProudableSkill.cs b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Avatar/ProudableSkill.cs index b24fdcea..37c4366f 100644 --- a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Avatar/ProudableSkill.cs +++ b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Avatar/ProudableSkill.cs @@ -8,7 +8,6 @@ namespace Snap.Hutao.Model.Metadata.Avatar; /// public class ProudableSkill : SkillBase { - /// /// 组Id /// diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/IconConverter.cs b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/IconConverter.cs new file mode 100644 index 00000000..c1b4018b --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/IconConverter.cs @@ -0,0 +1,26 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.UI.Xaml.Data; + +namespace Snap.Hutao.Model.Metadata.Converter; + +/// +/// 角色头像转换器 +/// +internal class IconConverter : IValueConverter +{ + private const string BaseUrl = "https://upload-bbs.mihoyo.com/game_record/genshin/character_icon/{0}.png"; + + /// + public object Convert(object value, Type targetType, object parameter, string language) + { + return new Uri(string.Format(BaseUrl, value)); + } + + /// + public object ConvertBack(object value, Type targetType, object parameter, string language) + { + throw Must.NeverHappen(); + } +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/SideIconConverter.cs b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/SideIconConverter.cs new file mode 100644 index 00000000..ef595504 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Model/Metadata/Converter/SideIconConverter.cs @@ -0,0 +1,26 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.UI.Xaml.Data; + +namespace Snap.Hutao.Model.Metadata.Converter; + +/// +/// 角色侧面头像转换器 +/// +internal class SideIconConverter : IValueConverter +{ + private const string BaseUrl = "https://upload-bbs.mihoyo.com/game_record/genshin/character_side_icon/{0}.png"; + + /// + public object Convert(object value, Type targetType, object parameter, string language) + { + return new Uri(string.Format(BaseUrl, value)); + } + + /// + public object ConvertBack(object value, Type targetType, object parameter, string language) + { + throw Must.NeverHappen(); + } +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Package.appxmanifest b/src/Snap.Hutao/Snap.Hutao/Package.appxmanifest index 04580171..faf68f1e 100644 --- a/src/Snap.Hutao/Snap.Hutao/Package.appxmanifest +++ b/src/Snap.Hutao/Snap.Hutao/Package.appxmanifest @@ -9,7 +9,7 @@ + Version="1.0.9.0" /> 胡桃 diff --git a/src/Snap.Hutao/Snap.Hutao/Service/User/IUserService.cs b/src/Snap.Hutao/Snap.Hutao/Service/User/IUserService.cs index c3069d98..8a31ef6a 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/User/IUserService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/User/IUserService.cs @@ -31,8 +31,9 @@ public interface IUserService /// 通常用户是未初始化的 /// /// 待添加的用户 + /// 用户的米游社UID /// 用户初始化是否成功 - Task TryAddUserAsync(User user); + Task TryAddUserAsync(User user, string uid); /// /// 异步移除用户 diff --git a/src/Snap.Hutao/Snap.Hutao/Service/User/UserAddResult.cs b/src/Snap.Hutao/Snap.Hutao/Service/User/UserAddResult.cs index 7722ebcd..2dd2b6f9 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/User/UserAddResult.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/User/UserAddResult.cs @@ -11,7 +11,12 @@ public enum UserAddResult /// /// 添加成功 /// - Ok, + Added, + + /// + /// 用户的Cookie成功更新 + /// + Updated, /// /// 已经存在该用户 diff --git a/src/Snap.Hutao/Snap.Hutao/Service/User/UserService.cs b/src/Snap.Hutao/Snap.Hutao/Service/User/UserService.cs index a33ae082..ea8a6a97 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/User/UserService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/User/UserService.cs @@ -69,31 +69,45 @@ internal class UserService : IUserService } /// - public async Task TryAddUserAsync(User user) + public async Task TryAddUserAsync(User newUser, string uid) { - string? newUsersCookie = user.Cookie; + Must.NotNull(cachedUsers!); - // Prevent users add same account. - bool userAlreadyExists = await appDbContext.Users - .AnyAsync(u => u.Cookie == newUsersCookie) - .ConfigureAwait(false); + // 查找是否有相同的uid + User? userWithSameUid = cachedUsers + .SingleOrDefault(u => u.UserInfo!.Uid == uid); - if (userAlreadyExists) + if (userWithSameUid != null) { - return UserAddResult.AlreadyExists; + // Prevent users from adding same cookie. + if (userWithSameUid.Cookie == newUser.Cookie) + { + return UserAddResult.AlreadyExists; + } + else + { + // Try update user here. + userWithSameUid.Cookie = newUser.Cookie; + appDbContext.Users.Update(userWithSameUid); + + await appDbContext + .SaveChangesAsync() + .ConfigureAwait(false); + + return UserAddResult.Updated; + } } - bool userInitialized = await user - .InitializeAsync(userClient, userGameRoleClient) - .ConfigureAwait(false); - - if (userInitialized) + // must continue on the caller thread. + if (await newUser.InitializeAsync(userClient, userGameRoleClient)) { - appDbContext.Users.Add(user); + appDbContext.Users.Add(newUser); + await appDbContext .SaveChangesAsync() .ConfigureAwait(false); - return UserAddResult.Ok; + + return UserAddResult.Added; } return UserAddResult.InitializeFailed; @@ -111,16 +125,23 @@ internal class UserService : IUserService { if (cachedUsers == null) { - appDbContext.Users.Load(); + await appDbContext.Users + .LoadAsync() + .ConfigureAwait(false); + cachedUsers = appDbContext.Users.Local.ToObservableCollection(); foreach (User user in cachedUsers) { user.RemoveCommand = removeCommand; - await user.InitializeAsync(userClient, userGameRoleClient); + await user + .InitializeAsync(userClient, userGameRoleClient) + .ConfigureAwait(false); } - CurrentUser = await appDbContext.Users.SingleOrDefaultAsync(user => user.IsSelected); + CurrentUser = await appDbContext.Users + .SingleOrDefaultAsync(user => user.IsSelected) + .ConfigureAwait(false); } return cachedUsers; @@ -129,15 +150,15 @@ internal class UserService : IUserService /// public IDictionary ParseCookie(string cookie) { - Dictionary cookieDictionary = new(); + SortedDictionary cookieDictionary = new(); string[] values = cookie.TrimEnd(';').Split(';'); - foreach (string[] parts in values.Select(c => c.Split(new[] { '=' }, 2))) + foreach (string[] parts in values.Select(c => c.Split('=', 2))) { string cookieName = parts[0].Trim(); string cookieValue = parts.Length == 1 ? string.Empty : parts[1].Trim(); - cookieDictionary[cookieName] = cookieValue; + cookieDictionary.Add(cookieName, cookieValue); } return cookieDictionary; diff --git a/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj b/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj index 98e100f4..c26ec322 100644 --- a/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj +++ b/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj @@ -36,6 +36,7 @@ + @@ -132,6 +133,11 @@ + + + MSBuild:Compile + + MSBuild:Compile diff --git a/src/Snap.Hutao/Snap.Hutao/View/Dialog/UserDialog.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/Dialog/UserDialog.xaml.cs index a9a63a97..683d15c6 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Dialog/UserDialog.xaml.cs +++ b/src/Snap.Hutao/Snap.Hutao/View/Dialog/UserDialog.xaml.cs @@ -14,10 +14,11 @@ public sealed partial class UserDialog : ContentDialog /// /// 构造一个新的添加用户对话框 /// - public UserDialog() + /// 呈现的父窗口 + public UserDialog(Microsoft.UI.Xaml.Window window) { InitializeComponent(); - XamlRoot = App.Window!.Content.XamlRoot; + XamlRoot = window.Content.XamlRoot; } /// @@ -29,7 +30,7 @@ public sealed partial class UserDialog : ContentDialog ContentDialogResult result = await ShowAsync(); string cookie = InputText.Text; - return new(result != ContentDialogResult.Secondary, cookie); + return new(result == ContentDialogResult.Primary, cookie); } private void InputTextChanged(object sender, TextChangedEventArgs e) diff --git a/src/Snap.Hutao/Snap.Hutao/View/MainView.xaml b/src/Snap.Hutao/Snap.Hutao/View/MainView.xaml index b7d33f69..063c6e3c 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/MainView.xaml +++ b/src/Snap.Hutao/Snap.Hutao/View/MainView.xaml @@ -34,6 +34,12 @@ + + + + + + diff --git a/src/Snap.Hutao/Snap.Hutao/View/MainView.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/MainView.xaml.cs index a78cba36..f2fbf6d1 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/MainView.xaml.cs +++ b/src/Snap.Hutao/Snap.Hutao/View/MainView.xaml.cs @@ -28,6 +28,6 @@ public sealed partial class MainView : UserControl navigationService = Ioc.Default.GetRequiredService(); navigationService.Initialize(NavView, ContentFrame); - navigationService.Navigate(INavigationAwaiter.Default, false); + navigationService.Navigate(INavigationAwaiter.Default, true); } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/WikiAvatarPage.xaml b/src/Snap.Hutao/Snap.Hutao/View/Page/WikiAvatarPage.xaml new file mode 100644 index 00000000..d1c0478d --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/View/Page/WikiAvatarPage.xaml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/WikiAvatarPage.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/Page/WikiAvatarPage.xaml.cs new file mode 100644 index 00000000..5b9dc449 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/View/Page/WikiAvatarPage.xaml.cs @@ -0,0 +1,35 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Controls.Primitives; +using Microsoft.UI.Xaml.Data; +using Microsoft.UI.Xaml.Input; +using Microsoft.UI.Xaml.Media; +using Microsoft.UI.Xaml.Navigation; +using Snap.Hutao.ViewModel; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices.WindowsRuntime; +using Windows.Foundation; +using Windows.Foundation.Collections; + +namespace Snap.Hutao.View.Page; + +/// +/// 角色资料页 +/// +public sealed partial class WikiAvatarPage : Microsoft.UI.Xaml.Controls.Page +{ + /// + /// 构造一个新的角色资料页 + /// + public WikiAvatarPage() + { + DataContext = Ioc.Default.GetRequiredService(); + InitializeComponent(); + } +} diff --git a/src/Snap.Hutao/Snap.Hutao/View/UserView.xaml b/src/Snap.Hutao/Snap.Hutao/View/UserView.xaml index df2bc99f..1dbddc2c 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/UserView.xaml +++ b/src/Snap.Hutao/Snap.Hutao/View/UserView.xaml @@ -35,7 +35,6 @@ Text="{Binding SelectedUser.UserInfo.Nickname,Mode=OneWay}" TextTrimming="CharacterEllipsis"/>