mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
Compare commits
38 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
91b2db886f | ||
|
|
101d316525 | ||
|
|
59d62f931d | ||
|
|
f0bb19bc07 | ||
|
|
c0b05e2c2f | ||
|
|
fc02f833a0 | ||
|
|
7b8ebd86b1 | ||
|
|
47b24286b1 | ||
|
|
0e3e3b9e4a | ||
|
|
85d7b22e11 | ||
|
|
7caeb17788 | ||
|
|
b11b90e9f1 | ||
|
|
58643a60b5 | ||
|
|
a29b487c26 | ||
|
|
1bd6023e0a | ||
|
|
579173d464 | ||
|
|
9ed53e8c34 | ||
|
|
830556a043 | ||
|
|
7ba27e184f | ||
|
|
9aa6a2b57b | ||
|
|
5773902f4a | ||
|
|
06c5bcad3e | ||
|
|
c0165c57fd | ||
|
|
4e57520115 | ||
|
|
17c3480dae | ||
|
|
7d5faadbb5 | ||
|
|
b7df968ea7 | ||
|
|
5f6cc46774 | ||
|
|
a34b5a5101 | ||
|
|
457e3c4af2 | ||
|
|
26143079b3 | ||
|
|
20ad9aec60 | ||
|
|
61dd098d95 | ||
|
|
e7233fbf2a | ||
|
|
8de526274a | ||
|
|
5b1fb6e1dd | ||
|
|
1584fd1428 | ||
|
|
65179a340f |
4
.github/FUNDING.yml
vendored
4
.github/FUNDING.yml
vendored
@@ -1,8 +1,8 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
github: [DGP-Studio]
|
||||
patreon: # Replace with a single Patreon username
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
open_collective: snaphutao
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||

|
||||
|
||||
胡桃工具箱是一个 Windows 平台的开源的原神工具箱,旨在帮助玩家获得更好的游戏体验; 它是对官方移动端工具的一种非破坏性功能扩展,为不习惯在移动端进行原神游戏的 PC 玩家提供一个在 Windows 平台下获得接近移动端功能权利的途径
|
||||
胡桃工具箱是一款以 MIT 协议开源的原神工具箱,专为现代化 Windows 平台设计,旨在改善桌面端玩家的游戏体验。通过将既有的官方资源与开发团队设计的全新 功能相结合,它提供了一套完整且实用的工具集,且无需依赖任何移动设备。它不对游戏客户端进行任何破坏性修改以确保工具箱的安全性
|
||||
|
||||
Snap Hutao is an open-source Genshin Impact toolbox on Windows platform, aim to provide a better gaming experience for players. It's an nondestructive feature extension from Genshin Impact's official mobile application, to provide similar feature on desktop, to allow PC gamers gain deserved benefits from mobile platforms.
|
||||
Snap Hutao is an open-source Genshin Impact toolkit under MIT license, designed for modern Windows platform to improve the gaming experience for desktop players. By combining existing official resources with new features designed by the development team, it provides a complete and useful set of tools without the need to rely on mobile devices. Snap Hutao does not take any destructive modification to the game client to ensure the security of the toolkit.
|
||||
|
||||
## 下载使用 / Download
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/microsoft/CsWin32/main/src/Microsoft.Windows.CsWin32/settings.schema.json",
|
||||
"allowMarshaling": true,
|
||||
"useSafeHandles": false,
|
||||
"emitSingleFile": true
|
||||
"useSafeHandles": false
|
||||
}
|
||||
@@ -1,159 +1,36 @@
|
||||
<Application
|
||||
x:Class="Snap.Hutao.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:cwcont="using:CommunityToolkit.WinUI.Controls"
|
||||
xmlns:cwconv="using:CommunityToolkit.WinUI.Converters"
|
||||
xmlns:cwm="using:CommunityToolkit.WinUI.Media"
|
||||
xmlns:shci="using:Snap.Hutao.Control.Image"
|
||||
xmlns:shmmc="using:Snap.Hutao.Model.Metadata.Converter"
|
||||
xmlns:shvc="using:Snap.Hutao.View.Converter">
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<Application.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<XamlControlsResources/>
|
||||
<ResourceDictionary Source="Control/Theme/FontStyle.xaml"/>
|
||||
<ResourceDictionary Source="Control/Theme/InfoBarOverride.xaml"/>
|
||||
<ResourceDictionary Source="Control/Theme/PageOverride.xaml"/>
|
||||
<ResourceDictionary Source="Control/Theme/PivotOverride.xaml"/>
|
||||
<ResourceDictionary Source="Control/Theme/SettingsStyle.xaml"/>
|
||||
<ResourceDictionary Source="Control/Theme/TransitionCollection.xaml"/>
|
||||
<ResourceDictionary Source="Control/Theme/WindowOverride.xaml"/>
|
||||
<ResourceDictionary Source="Control/Loading.xaml"/>
|
||||
<ResourceDictionary Source="ms-appx:///Control/Loading.xaml"/>
|
||||
<ResourceDictionary Source="ms-appx:///Control/Image/CachedImage.xaml"/>
|
||||
<ResourceDictionary Source="ms-appx:///Control/Theme/Card.xaml"/>
|
||||
<ResourceDictionary Source="ms-appx:///Control/Theme/Color.xaml"/>
|
||||
<ResourceDictionary Source="ms-appx:///Control/Theme/Converter.xaml"/>
|
||||
<ResourceDictionary Source="ms-appx:///Control/Theme/CornerRadius.xaml"/>
|
||||
<ResourceDictionary Source="ms-appx:///Control/Theme/FontStyle.xaml"/>
|
||||
<ResourceDictionary Source="ms-appx:///Control/Theme/Glyph.xaml"/>
|
||||
<ResourceDictionary Source="ms-appx:///Control/Theme/InfoBarOverride.xaml"/>
|
||||
<ResourceDictionary Source="ms-appx:///Control/Theme/ItemsPanelTemplate.xaml"/>
|
||||
<ResourceDictionary Source="ms-appx:///Control/Theme/NumericValue.xaml"/>
|
||||
<ResourceDictionary Source="ms-appx:///Control/Theme/PageOverride.xaml"/>
|
||||
<ResourceDictionary Source="ms-appx:///Control/Theme/PivotOverride.xaml"/>
|
||||
<ResourceDictionary Source="ms-appx:///Control/Theme/SettingsStyle.xaml"/>
|
||||
<ResourceDictionary Source="ms-appx:///Control/Theme/TransitionCollection.xaml"/>
|
||||
<ResourceDictionary Source="ms-appx:///Control/Theme/Uri.xaml"/>
|
||||
<ResourceDictionary Source="ms-appx:///Control/Theme/WindowOverride.xaml"/>
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
|
||||
<ResourceDictionary.ThemeDictionaries>
|
||||
<ResourceDictionary x:Key="Light">
|
||||
<Color x:Key="AvatarPropertyAddValueColor">#FF74BF00</Color>
|
||||
<Color x:Key="CompatBackgroundColor">#FFF4F4F4</Color>
|
||||
<SolidColorBrush x:Key="DarkOnlyOverlayMaskBrush" Color="#00000000"/>
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="Dark">
|
||||
<Color x:Key="AvatarPropertyAddValueColor">#FF90E800</Color>
|
||||
<Color x:Key="CompatBackgroundColor">#FF242424</Color>
|
||||
<SolidColorBrush x:Key="DarkOnlyOverlayMaskBrush" Color="#60000000"/>
|
||||
</ResourceDictionary>
|
||||
</ResourceDictionary.ThemeDictionaries>
|
||||
|
||||
<!-- CornerRadius -->
|
||||
<CornerRadius x:Key="ControlCornerRadiusTop">4,4,0,0</CornerRadius>
|
||||
<CornerRadius x:Key="ControlCornerRadiusBottom">0,0,4,4</CornerRadius>
|
||||
<CornerRadius x:Key="CompatCornerRadius">6</CornerRadius>
|
||||
<CornerRadius x:Key="CompatCornerRadiusTop">6,6,0,0</CornerRadius>
|
||||
<CornerRadius x:Key="CompatCornerRadiusRight">0,6,6,0</CornerRadius>
|
||||
<CornerRadius x:Key="CompatCornerRadiusBottom">0,0,6,6</CornerRadius>
|
||||
<CornerRadius x:Key="CompatCornerRadiusSmall">2</CornerRadius>
|
||||
<!-- Length -->
|
||||
<GridLength x:Key="CompatGridLength2">288</GridLength>
|
||||
<x:Double x:Key="CompatSplitViewOpenPaneLength">212</x:Double>
|
||||
<x:Double x:Key="CompatSplitViewOpenPaneLength2">304</x:Double>
|
||||
<x:Double x:Key="CompatSplitViewOpenPaneLength3">320</x:Double>
|
||||
<x:Double x:Key="HomeAdaptiveCardHeight">180</x:Double>
|
||||
<x:Double x:Key="ContentDialogMinHeight">64</x:Double>
|
||||
<x:Double x:Key="LargeAppBarButtonWidth">100</x:Double>
|
||||
<!-- ProgressBar -->
|
||||
<x:Double x:Key="LargeBackgroundProgressBarOpacity">0.2</x:Double>
|
||||
<!-- Brushes -->
|
||||
<SolidColorBrush x:Key="AvatarPropertyAddValueBrush" Color="{ThemeResource AvatarPropertyAddValueColor}"/>
|
||||
<SolidColorBrush x:Key="BlueBrush" Color="#FF5180CB"/>
|
||||
<SolidColorBrush x:Key="PurpleBrush" Color="#FFA156E0"/>
|
||||
<SolidColorBrush x:Key="OrangeBrush" Color="#FFBC6932"/>
|
||||
<SolidColorBrush x:Key="GuaranteePullBrush" Color="#FF0063FF"/>
|
||||
<SolidColorBrush x:Key="UpPullBrush" Color="#FFFFA400"/>
|
||||
|
||||
<!-- Uris -->
|
||||
<x:String x:Key="DocumentLink_MhyAccountSwitch">https://hut.ao/features/mhy-account-switch.html</x:String>
|
||||
<x:String x:Key="DocumentLink_BugReport">https://hut.ao/statements/bug-report.html</x:String>
|
||||
<x:String x:Key="DocumentLink_Translate">https://translate.hut.ao</x:String>
|
||||
<x:String x:Key="DocumentLink_Home">https://hut.ao</x:String>
|
||||
<x:String x:Key="HolographicHat_GetToken_Release">https://github.com/HolographicHat/GetToken/releases/latest</x:String>
|
||||
<x:String x:Key="Sponsor_Afadian">https://afdian.net/a/DismissedLight</x:String>
|
||||
|
||||
<!-- Images -->
|
||||
<x:String x:Key="UI_ItemIcon_None">https://static.snapgenshin.com/Bg/UI_ItemIcon_None.png</x:String>
|
||||
<x:String x:Key="UI_MarkTower">https://static.snapgenshin.com/Bg/UI_MarkTower.png</x:String>
|
||||
<x:String x:Key="UI_Icon_Intee_Explore_1">https://static.snapgenshin.com/Bg/UI_Icon_Intee_Explore_1.png</x:String>
|
||||
<x:String x:Key="UI_MarkQuest_Events_Proce">https://static.snapgenshin.com/Bg/UI_MarkQuest_Events_Proce.png</x:String>
|
||||
<x:String x:Key="UI_ItemIcon_201">https://static.snapgenshin.com/ItemIcon/UI_ItemIcon_201.png</x:String>
|
||||
<x:String x:Key="UI_ItemIcon_204">https://static.snapgenshin.com/ItemIcon/UI_ItemIcon_204.png</x:String>
|
||||
<x:String x:Key="UI_ItemIcon_210">https://static.snapgenshin.com/ItemIcon/UI_ItemIcon_210.png</x:String>
|
||||
<x:String x:Key="UI_ItemIcon_220021">https://static.snapgenshin.com/ItemIcon/UI_ItemIcon_220021.png</x:String>
|
||||
<x:String x:Key="UI_ImgSign_ItemIcon">https://static.snapgenshin.com/Bg/UI_ImgSign_ItemIcon.png</x:String>
|
||||
<x:String x:Key="UI_AvatarIcon_Costume_Card">https://static.snapgenshin.com/AvatarCard/UI_AvatarIcon_Costume_Card.png</x:String>
|
||||
<x:String x:Key="UI_EmotionIcon25">https://static.snapgenshin.com/EmotionIcon/UI_EmotionIcon25.png</x:String>
|
||||
<x:String x:Key="UI_EmotionIcon71">https://static.snapgenshin.com/EmotionIcon/UI_EmotionIcon71.png</x:String>
|
||||
<x:String x:Key="UI_EmotionIcon250">https://static.snapgenshin.com/EmotionIcon/UI_EmotionIcon250.png</x:String>
|
||||
<x:String x:Key="UI_EmotionIcon272">https://static.snapgenshin.com/EmotionIcon/UI_EmotionIcon272.png</x:String>
|
||||
<x:String x:Key="UI_EmotionIcon293">https://static.snapgenshin.com/EmotionIcon/UI_EmotionIcon293.png</x:String>
|
||||
|
||||
<!-- FontIcon Content -->
|
||||
<x:String x:Key="FontIconContentAdd"></x:String>
|
||||
<x:String x:Key="FontIconContentSetting"></x:String>
|
||||
<x:String x:Key="FontIconContentRefresh"></x:String>
|
||||
<x:String x:Key="FontIconContentDelete"></x:String>
|
||||
<x:String x:Key="FontIconContentFolder"></x:String>
|
||||
<x:String x:Key="FontIconContentCheckList"></x:String>
|
||||
<x:String x:Key="FontIconContentAsteriskBadge12"></x:String>
|
||||
<x:String x:Key="FontIconContentZipFolder"></x:String>
|
||||
<!-- Converters -->
|
||||
<cwconv:BoolNegationConverter x:Key="BoolNegationConverter"/>
|
||||
<cwconv:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter"/>
|
||||
<cwconv:FileSizeToFriendlyStringConverter x:Key="FileSizeToFriendlyStringConverter"/>
|
||||
<shmmc:AchievementIconConverter x:Key="AchievementIconConverter"/>
|
||||
<shmmc:AvatarCardConverter x:Key="AvatarCardConverter"/>
|
||||
<shmmc:AvatarIconConverter x:Key="AvatarIconConverter"/>
|
||||
<shmmc:AvatarNameCardPicConverter x:Key="AvatarNameCardPicConverter"/>
|
||||
<shmmc:AvatarSideIconConverter x:Key="AvatarSideIconConverter"/>
|
||||
<shmmc:DescriptionsParametersDescriptor x:Key="DescParamDescriptor"/>
|
||||
<shmmc:ElementNameIconConverter x:Key="ElementNameIconConverter"/>
|
||||
<shmmc:EmotionIconConverter x:Key="EmotionIconConverter"/>
|
||||
<shmmc:EquipIconConverter x:Key="EquipIconConverter"/>
|
||||
<shmmc:GachaAvatarImgConverter x:Key="GachaAvatarImgConverter"/>
|
||||
<shmmc:GachaAvatarIconConverter x:Key="GachaAvatarIconConverter"/>
|
||||
<shmmc:GachaEquipIconConverter x:Key="GachaEquipIconConverter"/>
|
||||
<shmmc:ItemIconConverter x:Key="ItemIconConverter"/>
|
||||
<shmmc:MonsterIconConverter x:Key="MonsterIconConverter"/>
|
||||
<shmmc:PropertiesParametersDescriptor x:Key="PropertyDescriptor"/>
|
||||
<shmmc:QualityColorConverter x:Key="QualityColorConverter"/>
|
||||
<shmmc:WeaponTypeIconConverter x:Key="WeaponTypeIconConverter"/>
|
||||
<shvc:BoolToVisibilityRevertConverter x:Key="BoolToVisibilityRevertConverter"/>
|
||||
<shvc:EmptyObjectToBoolConverter x:Key="EmptyObjectToBoolConverter"/>
|
||||
<shvc:EmptyObjectToBoolRevertConverter x:Key="EmptyObjectToBoolRevertConverter"/>
|
||||
<shvc:EmptyObjectToVisibilityConverter x:Key="EmptyObjectToVisibilityConverter"/>
|
||||
<shvc:EmptyObjectToVisibilityRevertConverter x:Key="EmptyObjectToVisibilityRevertConverter"/>
|
||||
<shvc:Int32ToVisibilityConverter x:Key="Int32ToVisibilityConverter"/>
|
||||
<shvc:Int32ToVisibilityRevertConverter x:Key="Int32ToVisibilityRevertConverter"/>
|
||||
<shvc:StringBoolConverter x:Key="StringBoolConverter"/>
|
||||
|
||||
<!-- Styles -->
|
||||
<Style
|
||||
x:Key="LargeGridViewItemStyle"
|
||||
BasedOn="{StaticResource DefaultGridViewItemStyle}"
|
||||
TargetType="GridViewItem">
|
||||
<Setter Property="Margin" Value="0,0,12,12"/>
|
||||
</Style>
|
||||
<Style
|
||||
x:Key="SettingButtonStyle"
|
||||
BasedOn="{StaticResource DefaultButtonStyle}"
|
||||
TargetType="Button">
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource CardBorderBrush}"/>
|
||||
<Setter Property="CornerRadius" Value="{ThemeResource ControlCornerRadius}"/>
|
||||
<Setter Property="Padding" Value="16,6,16,6"/>
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch"/>
|
||||
<Setter Property="HorizontalContentAlignment" Value="Center"/>
|
||||
</Style>
|
||||
<Style x:Key="BorderCardStyle" TargetType="Border">
|
||||
<Setter Property="Background" Value="{ThemeResource CardBackgroundFillColorDefaultBrush}"/>
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource CardStrokeColorDefaultBrush}"/>
|
||||
<Setter Property="BorderThickness" Value="1"/>
|
||||
<Setter Property="CornerRadius" Value="{ThemeResource ControlCornerRadius}"/>
|
||||
</Style>
|
||||
<Style x:Key="BorderGridStyle" TargetType="Grid">
|
||||
<Setter Property="Background" Value="{ThemeResource CardBackgroundFillColorDefaultBrush}"/>
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource CardStrokeColorDefaultBrush}"/>
|
||||
<Setter Property="BorderThickness" Value="1"/>
|
||||
<Setter Property="CornerRadius" Value="{ThemeResource ControlCornerRadius}"/>
|
||||
</Style>
|
||||
<Style
|
||||
x:Name="NoneSelectionListViewItemStyle"
|
||||
BasedOn="{StaticResource DefaultListViewItemStyle}"
|
||||
@@ -168,108 +45,6 @@
|
||||
<Setter Property="Padding" Value="0"/>
|
||||
<Setter Property="Margin" Value="0,0,2,4"/>
|
||||
</Style>
|
||||
<Style TargetType="shci:CachedImage">
|
||||
<Setter Property="Background" Value="Transparent"/>
|
||||
<Setter Property="Foreground" Value="{ThemeResource ApplicationForegroundThemeBrush}"/>
|
||||
<Setter Property="IsTabStop" Value="False"/>
|
||||
<Setter Property="LazyLoadingThreshold" Value="256"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="shci:CachedImage">
|
||||
<Grid
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}">
|
||||
<Image
|
||||
Name="PlaceholderImage"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalAlignment}"
|
||||
Opacity="1.0"
|
||||
Source="{TemplateBinding PlaceholderSource}"
|
||||
Stretch="{TemplateBinding PlaceholderStretch}"/>
|
||||
<Image
|
||||
Name="Image"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalAlignment}"
|
||||
NineGrid="{TemplateBinding NineGrid}"
|
||||
Opacity="0.0"
|
||||
Stretch="{TemplateBinding Stretch}"/>
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Failed">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Image" Storyboard.TargetProperty="Opacity">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="0"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderImage" Storyboard.TargetProperty="Opacity">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Loading">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Image" Storyboard.TargetProperty="Opacity">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="0"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderImage" Storyboard.TargetProperty="Opacity">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Loaded">
|
||||
<Storyboard>
|
||||
<DoubleAnimation
|
||||
AutoReverse="False"
|
||||
BeginTime="0"
|
||||
Storyboard.TargetName="Image"
|
||||
Storyboard.TargetProperty="Opacity"
|
||||
From="0"
|
||||
To="1"
|
||||
Duration="0:0:0.5"/>
|
||||
<DoubleAnimation
|
||||
AutoReverse="False"
|
||||
BeginTime="0"
|
||||
Storyboard.TargetName="PlaceholderImage"
|
||||
Storyboard.TargetProperty="Opacity"
|
||||
From="1"
|
||||
To="0"
|
||||
Duration="0:0:0.5"/>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Unloaded"/>
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
<!-- ItemsPanelTemplate -->
|
||||
<ItemsPanelTemplate x:Key="ItemsStackPanelTemplate">
|
||||
<ItemsStackPanel/>
|
||||
</ItemsPanelTemplate>
|
||||
<ItemsPanelTemplate x:Key="WrapPanelSpacing0Template">
|
||||
<cwcont:WrapPanel/>
|
||||
</ItemsPanelTemplate>
|
||||
<ItemsPanelTemplate x:Key="WrapPanelSpacing4Template">
|
||||
<cwcont:WrapPanel HorizontalSpacing="4" VerticalSpacing="4"/>
|
||||
</ItemsPanelTemplate>
|
||||
<ItemsPanelTemplate x:Key="HorizontalStackPanelTemplate">
|
||||
<StackPanel Orientation="Horizontal"/>
|
||||
</ItemsPanelTemplate>
|
||||
<ItemsPanelTemplate x:Key="UniformGridColumns5Spacing4Template">
|
||||
<cwcont:UniformGrid
|
||||
ColumnSpacing="4"
|
||||
Columns="5"
|
||||
RowSpacing="4"/>
|
||||
</ItemsPanelTemplate>
|
||||
|
||||
|
||||
<cwm:AttachedCardShadow
|
||||
x:Key="CompatCardShadow"
|
||||
Opacity="0.1"
|
||||
Offset="0,4,0"/>
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
@@ -10,8 +10,8 @@ internal struct ContentDialogHideToken : IDisposable, IAsyncDisposable
|
||||
private readonly ContentDialog contentDialog;
|
||||
private readonly ITaskContext taskContext;
|
||||
|
||||
private bool disposed = false;
|
||||
private bool disposing = false;
|
||||
private bool disposed = false;
|
||||
|
||||
public ContentDialogHideToken(ContentDialog contentDialog, ITaskContext taskContext)
|
||||
{
|
||||
|
||||
82
src/Snap.Hutao/Snap.Hutao/Control/Image/CachedImage.xaml
Normal file
82
src/Snap.Hutao/Snap.Hutao/Control/Image/CachedImage.xaml
Normal file
@@ -0,0 +1,82 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:shci="using:Snap.Hutao.Control.Image">
|
||||
<Style TargetType="shci:CachedImage">
|
||||
<Setter Property="Background" Value="Transparent"/>
|
||||
<Setter Property="Foreground" Value="{ThemeResource ApplicationForegroundThemeBrush}"/>
|
||||
<Setter Property="IsTabStop" Value="False"/>
|
||||
<Setter Property="LazyLoadingThreshold" Value="256"/>
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="shci:CachedImage">
|
||||
<Grid
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}">
|
||||
<Image
|
||||
Name="PlaceholderImage"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalAlignment}"
|
||||
Opacity="1.0"
|
||||
Source="{TemplateBinding PlaceholderSource}"
|
||||
Stretch="{TemplateBinding PlaceholderStretch}"/>
|
||||
<Image
|
||||
Name="Image"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalAlignment}"
|
||||
NineGrid="{TemplateBinding NineGrid}"
|
||||
Opacity="0.0"
|
||||
Stretch="{TemplateBinding Stretch}"/>
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Failed">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Image" Storyboard.TargetProperty="Opacity">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="0"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderImage" Storyboard.TargetProperty="Opacity">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Loading">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Image" Storyboard.TargetProperty="Opacity">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="0"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderImage" Storyboard.TargetProperty="Opacity">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="1"/>
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Loaded">
|
||||
<Storyboard>
|
||||
<DoubleAnimation
|
||||
AutoReverse="False"
|
||||
BeginTime="0"
|
||||
Storyboard.TargetName="Image"
|
||||
Storyboard.TargetProperty="Opacity"
|
||||
From="0"
|
||||
To="1"
|
||||
Duration="0:0:0.5"/>
|
||||
<DoubleAnimation
|
||||
AutoReverse="False"
|
||||
BeginTime="0"
|
||||
Storyboard.TargetName="PlaceholderImage"
|
||||
Storyboard.TargetProperty="Opacity"
|
||||
From="1"
|
||||
To="0"
|
||||
Duration="0:0:0.5"/>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Unloaded"/>
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
@@ -164,11 +164,26 @@ internal abstract partial class CompositionImage : Microsoft.UI.Xaml.Controls.Co
|
||||
private async ValueTask<LoadedImageSurface> LoadImageSurfaceAsync(string file, CancellationToken token)
|
||||
{
|
||||
surfaceLoadTaskCompletionSource = new();
|
||||
LoadedImageSurface surface = LoadedImageSurface.StartLoadFromUri(file.ToUri());
|
||||
surface.LoadCompleted += loadedImageSourceLoadCompletedEventHandler;
|
||||
await surfaceLoadTaskCompletionSource.Task.ConfigureAwait(true);
|
||||
LoadImageSurfaceCompleted(surface);
|
||||
return surface;
|
||||
LoadedImageSurface? surface = default;
|
||||
try
|
||||
{
|
||||
surface = LoadedImageSurface.StartLoadFromUri(file.ToUri());
|
||||
surface.LoadCompleted += loadedImageSourceLoadCompletedEventHandler;
|
||||
if (surface.DecodedPhysicalSize.Size() <= 0D)
|
||||
{
|
||||
await surfaceLoadTaskCompletionSource.Task.ConfigureAwait(true);
|
||||
}
|
||||
|
||||
LoadImageSurfaceCompleted(surface);
|
||||
return surface;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (surface is not null)
|
||||
{
|
||||
surface.LoadCompleted -= loadedImageSourceLoadCompletedEventHandler;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async ValueTask ShowAsync(CancellationToken token)
|
||||
@@ -216,7 +231,6 @@ internal abstract partial class CompositionImage : Microsoft.UI.Xaml.Controls.Co
|
||||
private void OnLoadImageSurfaceLoadCompleted(LoadedImageSurface surface, LoadedImageSourceLoadCompletedEventArgs e)
|
||||
{
|
||||
surfaceLoadTaskCompletionSource?.TrySetResult();
|
||||
surface.LoadCompleted -= loadedImageSourceLoadCompletedEventHandler;
|
||||
}
|
||||
|
||||
private void OnSizeChanged(object sender, SizeChangedEventArgs e)
|
||||
|
||||
21
src/Snap.Hutao/Snap.Hutao/Control/Theme/Card.xaml
Normal file
21
src/Snap.Hutao/Snap.Hutao/Control/Theme/Card.xaml
Normal file
@@ -0,0 +1,21 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:cwm="using:CommunityToolkit.WinUI.Media">
|
||||
<Style x:Key="BorderCardStyle" TargetType="Border">
|
||||
<Setter Property="Background" Value="{ThemeResource CardBackgroundFillColorDefaultBrush}"/>
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource CardStrokeColorDefaultBrush}"/>
|
||||
<Setter Property="BorderThickness" Value="1"/>
|
||||
<Setter Property="CornerRadius" Value="{ThemeResource ControlCornerRadius}"/>
|
||||
</Style>
|
||||
<Style x:Key="GridCardStyle" TargetType="Grid">
|
||||
<Setter Property="Background" Value="{ThemeResource CardBackgroundFillColorDefaultBrush}"/>
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource CardStrokeColorDefaultBrush}"/>
|
||||
<Setter Property="BorderThickness" Value="1"/>
|
||||
<Setter Property="CornerRadius" Value="{ThemeResource ControlCornerRadius}"/>
|
||||
</Style>
|
||||
<cwm:AttachedCardShadow
|
||||
x:Key="CompatCardShadow"
|
||||
Opacity="0.1"
|
||||
Offset="0,4,0"/>
|
||||
</ResourceDictionary>
|
||||
31
src/Snap.Hutao/Snap.Hutao/Control/Theme/Color.xaml
Normal file
31
src/Snap.Hutao/Snap.Hutao/Control/Theme/Color.xaml
Normal file
@@ -0,0 +1,31 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<ResourceDictionary.ThemeDictionaries>
|
||||
<ResourceDictionary x:Key="Light">
|
||||
<Color x:Key="AvatarPropertyAddValueColor">#FF74BF00</Color>
|
||||
<Color x:Key="CompatBackgroundColor">#FFF4F4F4</Color>
|
||||
<Color x:Key="DarkOnlyOverlayMaskColor">#00000000</Color>
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="Dark">
|
||||
<Color x:Key="AvatarPropertyAddValueColor">#FF90E800</Color>
|
||||
<Color x:Key="CompatBackgroundColor">#FF242424</Color>
|
||||
<Color x:Key="DarkOnlyOverlayMaskColor">#60000000</Color>
|
||||
</ResourceDictionary>
|
||||
</ResourceDictionary.ThemeDictionaries>
|
||||
|
||||
<Color x:Key="BlueColor">#FF5180CB</Color>
|
||||
<Color x:Key="PurpleColor">#FFA156E0</Color>
|
||||
<Color x:Key="OrangeColor">#FFBC6932</Color>
|
||||
|
||||
<Color x:Key="GuaranteePullColor">#FF0063FF</Color>
|
||||
<Color x:Key="UpPullColor">#FFFFA400</Color>
|
||||
|
||||
<SolidColorBrush x:Key="BlueColorBrush" Color="{ThemeResource BlueColor}"/>
|
||||
<SolidColorBrush x:Key="PurpleColorBrush" Color="{ThemeResource PurpleColor}"/>
|
||||
<SolidColorBrush x:Key="OrangeColorBrush" Color="{ThemeResource OrangeColor}"/>
|
||||
|
||||
<SolidColorBrush x:Key="GuaranteePullCoolorBrush" Color="{ThemeResource GuaranteePullColor}"/>
|
||||
<SolidColorBrush x:Key="UpPullColorBrush" Color="{ThemeResource UpPullColor}"/>
|
||||
|
||||
<SolidColorBrush x:Key="DarkOnlyOverlayMaskColorBrush" Color="{ThemeResource DarkOnlyOverlayMaskColor}"/>
|
||||
<SolidColorBrush x:Key="AvatarPropertyAddValueColorBrush" Color="{ThemeResource AvatarPropertyAddValueColor}"/>
|
||||
</ResourceDictionary>
|
||||
35
src/Snap.Hutao/Snap.Hutao/Control/Theme/Converter.xaml
Normal file
35
src/Snap.Hutao/Snap.Hutao/Control/Theme/Converter.xaml
Normal file
@@ -0,0 +1,35 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:cwc="using:CommunityToolkit.WinUI.Converters"
|
||||
xmlns:shmmc="using:Snap.Hutao.Model.Metadata.Converter"
|
||||
xmlns:shvc="using:Snap.Hutao.View.Converter">
|
||||
<cwc:BoolNegationConverter x:Key="BoolNegationConverter"/>
|
||||
<cwc:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter"/>
|
||||
<cwc:FileSizeToFriendlyStringConverter x:Key="FileSizeToFriendlyStringConverter"/>
|
||||
<shmmc:AchievementIconConverter x:Key="AchievementIconConverter"/>
|
||||
<shmmc:AvatarCardConverter x:Key="AvatarCardConverter"/>
|
||||
<shmmc:AvatarIconConverter x:Key="AvatarIconConverter"/>
|
||||
<shmmc:AvatarNameCardPicConverter x:Key="AvatarNameCardPicConverter"/>
|
||||
<shmmc:AvatarSideIconConverter x:Key="AvatarSideIconConverter"/>
|
||||
<shmmc:DescriptionsParametersDescriptor x:Key="DescParamDescriptor"/>
|
||||
<shmmc:ElementNameIconConverter x:Key="ElementNameIconConverter"/>
|
||||
<shmmc:EmotionIconConverter x:Key="EmotionIconConverter"/>
|
||||
<shmmc:EquipIconConverter x:Key="EquipIconConverter"/>
|
||||
<shmmc:GachaAvatarImgConverter x:Key="GachaAvatarImgConverter"/>
|
||||
<shmmc:GachaAvatarIconConverter x:Key="GachaAvatarIconConverter"/>
|
||||
<shmmc:GachaEquipIconConverter x:Key="GachaEquipIconConverter"/>
|
||||
<shmmc:ItemIconConverter x:Key="ItemIconConverter"/>
|
||||
<shmmc:MonsterIconConverter x:Key="MonsterIconConverter"/>
|
||||
<shmmc:PropertiesParametersDescriptor x:Key="PropertyDescriptor"/>
|
||||
<shmmc:QualityColorConverter x:Key="QualityColorConverter"/>
|
||||
<shmmc:WeaponTypeIconConverter x:Key="WeaponTypeIconConverter"/>
|
||||
<shvc:BoolToVisibilityRevertConverter x:Key="BoolToVisibilityRevertConverter"/>
|
||||
<shvc:EmptyObjectToBoolConverter x:Key="EmptyObjectToBoolConverter"/>
|
||||
<shvc:EmptyObjectToBoolRevertConverter x:Key="EmptyObjectToBoolRevertConverter"/>
|
||||
<shvc:EmptyObjectToVisibilityConverter x:Key="EmptyObjectToVisibilityConverter"/>
|
||||
<shvc:EmptyObjectToVisibilityRevertConverter x:Key="EmptyObjectToVisibilityRevertConverter"/>
|
||||
<shvc:Int32ToVisibilityConverter x:Key="Int32ToVisibilityConverter"/>
|
||||
<shvc:Int32ToVisibilityRevertConverter x:Key="Int32ToVisibilityRevertConverter"/>
|
||||
<shvc:StringBoolConverter x:Key="StringBoolConverter"/>
|
||||
</ResourceDictionary>
|
||||
@@ -0,0 +1,4 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<CornerRadius x:Key="ControlCornerRadiusTop">4,4,0,0</CornerRadius>
|
||||
<CornerRadius x:Key="ControlCornerRadiusBottom">0,0,4,4</CornerRadius>
|
||||
</ResourceDictionary>
|
||||
@@ -1,7 +1,7 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:shch="using:Snap.Hutao.Control.Helper">
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<XamlControlsResources/>
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
<FontFamily x:Key="MiSans">ms-appx:///Resource/Font/MiSans-Regular.ttf#MiSans</FontFamily>
|
||||
<FontFamily x:Key="CascadiaMonoAndMiSans">ms-appx:///Resource/Font/CascadiaMono.ttf#Cascadia Mono, ms-appx:///Resource/Font/MiSans-Regular.ttf#MiSans</FontFamily>
|
||||
|
||||
|
||||
10
src/Snap.Hutao/Snap.Hutao/Control/Theme/Glyph.xaml
Normal file
10
src/Snap.Hutao/Snap.Hutao/Control/Theme/Glyph.xaml
Normal file
@@ -0,0 +1,10 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<x:String x:Key="FontIconContentAdd"></x:String>
|
||||
<x:String x:Key="FontIconContentSetting"></x:String>
|
||||
<x:String x:Key="FontIconContentRefresh"></x:String>
|
||||
<x:String x:Key="FontIconContentDelete"></x:String>
|
||||
<x:String x:Key="FontIconContentFolder"></x:String>
|
||||
<x:String x:Key="FontIconContentCheckList"></x:String>
|
||||
<x:String x:Key="FontIconContentAsteriskBadge12"></x:String>
|
||||
<x:String x:Key="FontIconContentZipFolder"></x:String>
|
||||
</ResourceDictionary>
|
||||
@@ -0,0 +1,23 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:cwcont="using:CommunityToolkit.WinUI.Controls">
|
||||
<ItemsPanelTemplate x:Key="ItemsStackPanelTemplate">
|
||||
<ItemsStackPanel/>
|
||||
</ItemsPanelTemplate>
|
||||
<ItemsPanelTemplate x:Key="WrapPanelSpacing0Template">
|
||||
<cwcont:WrapPanel/>
|
||||
</ItemsPanelTemplate>
|
||||
<ItemsPanelTemplate x:Key="WrapPanelSpacing4Template">
|
||||
<cwcont:WrapPanel HorizontalSpacing="4" VerticalSpacing="4"/>
|
||||
</ItemsPanelTemplate>
|
||||
<ItemsPanelTemplate x:Key="HorizontalStackPanelTemplate">
|
||||
<StackPanel Orientation="Horizontal"/>
|
||||
</ItemsPanelTemplate>
|
||||
<ItemsPanelTemplate x:Key="UniformGridColumns5Spacing4Template">
|
||||
<cwcont:UniformGrid
|
||||
ColumnSpacing="4"
|
||||
Columns="5"
|
||||
RowSpacing="4"/>
|
||||
</ItemsPanelTemplate>
|
||||
</ResourceDictionary>
|
||||
14
src/Snap.Hutao/Snap.Hutao/Control/Theme/NumericValue.xaml
Normal file
14
src/Snap.Hutao/Snap.Hutao/Control/Theme/NumericValue.xaml
Normal file
@@ -0,0 +1,14 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<!-- Length -->
|
||||
<GridLength x:Key="CompatGridLength2">288</GridLength>
|
||||
|
||||
<x:Double x:Key="CompatSplitViewOpenPaneLength">212</x:Double>
|
||||
<x:Double x:Key="CompatSplitViewOpenPaneLength2">304</x:Double>
|
||||
<x:Double x:Key="CompatSplitViewOpenPaneLength3">320</x:Double>
|
||||
<x:Double x:Key="HomeAdaptiveCardHeight">180</x:Double>
|
||||
<x:Double x:Key="ContentDialogMinHeight">64</x:Double>
|
||||
<x:Double x:Key="LargeAppBarButtonWidth">100</x:Double>
|
||||
|
||||
<!-- ProgressBar -->
|
||||
<x:Double x:Key="LargeBackgroundProgressBarOpacity">0.2</x:Double>
|
||||
</ResourceDictionary>
|
||||
@@ -2,5 +2,5 @@
|
||||
<!-- Page Transparent Background -->
|
||||
<StaticResource x:Key="ApplicationPageBackgroundThemeBrush" ResourceKey="ControlFillColorTransparentBrush"/>
|
||||
<!-- https://github.com/microsoft/microsoft-ui-xaml/issues/4811 -->
|
||||
<x:Int32 x:Key="__Discard">0</x:Int32>
|
||||
<x:Int32 x:Key="__DiscardPageOverride">0</x:Int32>
|
||||
</ResourceDictionary>
|
||||
@@ -18,4 +18,14 @@
|
||||
TargetType="ComboBox">
|
||||
<Setter Property="MinWidth" Value="120"/>
|
||||
</Style>
|
||||
<Style
|
||||
x:Key="SettingButtonStyle"
|
||||
BasedOn="{StaticResource DefaultButtonStyle}"
|
||||
TargetType="Button">
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource CardBorderBrush}"/>
|
||||
<Setter Property="CornerRadius" Value="{ThemeResource ControlCornerRadius}"/>
|
||||
<Setter Property="Padding" Value="16,6,16,6"/>
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch"/>
|
||||
<Setter Property="HorizontalContentAlignment" Value="Center"/>
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
|
||||
34
src/Snap.Hutao/Snap.Hutao/Control/Theme/Uri.xaml
Normal file
34
src/Snap.Hutao/Snap.Hutao/Control/Theme/Uri.xaml
Normal file
@@ -0,0 +1,34 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<!-- DocumentLink -->
|
||||
<x:String x:Key="DocumentLink_BugReport">https://hut.ao/statements/bug-report.html</x:String>
|
||||
<x:String x:Key="DocumentLink_Home">https://hut.ao</x:String>
|
||||
<x:String x:Key="DocumentLink_MhyAccountSwitch">https://hut.ao/features/mhy-account-switch.html</x:String>
|
||||
<x:String x:Key="DocumentLink_Translate">https://translate.hut.ao</x:String>
|
||||
|
||||
<!-- Other -->
|
||||
<x:String x:Key="HolographicHat_GetToken_Release">https://github.com/HolographicHat/GetToken/releases/latest</x:String>
|
||||
<x:String x:Key="Sponsor_Afadian">https://afdian.net/a/DismissedLight</x:String>
|
||||
|
||||
<!-- AvatarCard -->
|
||||
<x:String x:Key="UI_AvatarIcon_Costume_Card">https://static.snapgenshin.com/AvatarCard/UI_AvatarIcon_Costume_Card.png</x:String>
|
||||
|
||||
<!-- Bg -->
|
||||
<x:String x:Key="UI_Icon_Intee_Explore_1">https://static.snapgenshin.com/Bg/UI_Icon_Intee_Explore_1.png</x:String>
|
||||
<x:String x:Key="UI_ImgSign_ItemIcon">https://static.snapgenshin.com/Bg/UI_ImgSign_ItemIcon.png</x:String>
|
||||
<x:String x:Key="UI_ItemIcon_None">https://static.snapgenshin.com/Bg/UI_ItemIcon_None.png</x:String>
|
||||
<x:String x:Key="UI_MarkQuest_Events_Proce">https://static.snapgenshin.com/Bg/UI_MarkQuest_Events_Proce.png</x:String>
|
||||
<x:String x:Key="UI_MarkTower">https://static.snapgenshin.com/Bg/UI_MarkTower.png</x:String>
|
||||
|
||||
<!-- ItemIcon -->
|
||||
<x:String x:Key="UI_ItemIcon_201">https://static.snapgenshin.com/ItemIcon/UI_ItemIcon_201.png</x:String>
|
||||
<x:String x:Key="UI_ItemIcon_204">https://static.snapgenshin.com/ItemIcon/UI_ItemIcon_204.png</x:String>
|
||||
<x:String x:Key="UI_ItemIcon_210">https://static.snapgenshin.com/ItemIcon/UI_ItemIcon_210.png</x:String>
|
||||
<x:String x:Key="UI_ItemIcon_220021">https://static.snapgenshin.com/ItemIcon/UI_ItemIcon_220021.png</x:String>
|
||||
|
||||
<!-- EmotionIcon -->
|
||||
<x:String x:Key="UI_EmotionIcon25">https://static.snapgenshin.com/EmotionIcon/UI_EmotionIcon25.png</x:String>
|
||||
<x:String x:Key="UI_EmotionIcon71">https://static.snapgenshin.com/EmotionIcon/UI_EmotionIcon71.png</x:String>
|
||||
<x:String x:Key="UI_EmotionIcon250">https://static.snapgenshin.com/EmotionIcon/UI_EmotionIcon250.png</x:String>
|
||||
<x:String x:Key="UI_EmotionIcon272">https://static.snapgenshin.com/EmotionIcon/UI_EmotionIcon272.png</x:String>
|
||||
<x:String x:Key="UI_EmotionIcon293">https://static.snapgenshin.com/EmotionIcon/UI_EmotionIcon293.png</x:String>
|
||||
</ResourceDictionary>
|
||||
@@ -2,6 +2,7 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using Microsoft.Windows.ApplicationModel.Resources;
|
||||
using Snap.Hutao.Core.Logging;
|
||||
using Snap.Hutao.Service;
|
||||
using System.Globalization;
|
||||
|
||||
@@ -14,9 +14,7 @@ namespace Snap.Hutao.Core.ExceptionService;
|
||||
internal sealed partial class ExceptionRecorder
|
||||
{
|
||||
private readonly ILogger<ExceptionRecorder> logger;
|
||||
#if RELEASE
|
||||
private readonly IServiceProvider serviceProvider;
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// 记录应用程序异常
|
||||
@@ -31,13 +29,14 @@ internal sealed partial class ExceptionRecorder
|
||||
|
||||
private void OnAppUnhandledException(object? sender, Microsoft.UI.Xaml.UnhandledExceptionEventArgs e)
|
||||
{
|
||||
#if RELEASE
|
||||
serviceProvider
|
||||
ValueTask<string?> task = serviceProvider
|
||||
.GetRequiredService<Web.Hutao.Log.HomaLogUploadClient>()
|
||||
.UploadLogAsync(e.Exception)
|
||||
.GetAwaiter()
|
||||
.GetResult();
|
||||
#endif
|
||||
.UploadLogAsync(e.Exception);
|
||||
|
||||
if (!task.IsCompleted)
|
||||
{
|
||||
task.GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
logger.LogError("未经处理的全局异常:\r\n{Detail}", ExceptionFormat.Format(e.Exception));
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ internal sealed class RuntimeEnvironmentException : Exception
|
||||
/// </summary>
|
||||
/// <param name="message">消息</param>
|
||||
/// <param name="innerException">内部错误</param>
|
||||
public RuntimeEnvironmentException(string message, Exception innerException)
|
||||
public RuntimeEnvironmentException(string message, Exception? innerException)
|
||||
: base($"{message}\n{innerException.Message}", innerException)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -14,27 +14,27 @@ namespace Snap.Hutao.Core.ExceptionService;
|
||||
[System.Diagnostics.StackTraceHidden]
|
||||
internal static class ThrowHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 操作取消
|
||||
/// </summary>
|
||||
/// <param name="message">消息</param>
|
||||
/// <param name="inner">内部错误</param>
|
||||
/// <returns>nothing</returns>
|
||||
/// <exception cref="OperationCanceledException">操作取消异常</exception>
|
||||
[DoesNotReturn]
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public static OperationCanceledException OperationCanceled(string message, Exception? inner = default)
|
||||
public static ArgumentException Argument(string message, string? paramName)
|
||||
{
|
||||
throw new OperationCanceledException(message, inner);
|
||||
throw new ArgumentException(message, paramName);
|
||||
}
|
||||
|
||||
[DoesNotReturn]
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public static DatabaseCorruptedException DatabaseCorrupted(string message, Exception? inner)
|
||||
{
|
||||
throw new DatabaseCorruptedException(message, inner);
|
||||
}
|
||||
|
||||
[DoesNotReturn]
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public static GameFileOperationException GameFileOperation(string message, Exception? inner)
|
||||
{
|
||||
throw new GameFileOperationException(message, inner);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 无效操作
|
||||
/// </summary>
|
||||
/// <param name="message">消息</param>
|
||||
/// <param name="inner">内部错误</param>
|
||||
/// <returns>nothing</returns>
|
||||
/// <exception cref="InvalidOperationException">无效操作异常</exception>
|
||||
[DoesNotReturn]
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public static InvalidOperationException InvalidOperation(string message, Exception? inner = default)
|
||||
@@ -42,71 +42,38 @@ internal static class ThrowHelper
|
||||
throw new InvalidOperationException(message, inner);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 游戏文件操作失败
|
||||
/// </summary>
|
||||
/// <param name="message">消息</param>
|
||||
/// <param name="inner">内部错误</param>
|
||||
/// <returns>nothing</returns>
|
||||
/// <exception cref="GameFileOperationException">文件操作失败</exception>
|
||||
public static GameFileOperationException GameFileOperation(string message, Exception inner)
|
||||
{
|
||||
throw new GameFileOperationException(message, inner);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 包转换错误
|
||||
/// </summary>
|
||||
/// <param name="message">消息</param>
|
||||
/// <param name="inner">内部错误</param>
|
||||
/// <returns>nothing</returns>
|
||||
/// <exception cref="PackageConvertException">包转换错误异常</exception>
|
||||
[DoesNotReturn]
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public static PackageConvertException PackageConvert(string message, Exception inner)
|
||||
{
|
||||
throw new PackageConvertException(message, inner);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 用户数据损坏
|
||||
/// </summary>
|
||||
/// <param name="message">消息</param>
|
||||
/// <param name="inner">内部错误</param>
|
||||
/// <returns>nothing</returns>
|
||||
/// <exception cref="UserdataCorruptedException">数据损坏</exception>
|
||||
[DoesNotReturn]
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public static UserdataCorruptedException UserdataCorrupted(string message, Exception inner)
|
||||
{
|
||||
throw new UserdataCorruptedException(message, inner);
|
||||
}
|
||||
|
||||
[DoesNotReturn]
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public static DatabaseCorruptedException DatabaseCorrupted(string message, Exception inner)
|
||||
{
|
||||
throw new DatabaseCorruptedException(message, inner);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 运行环境异常
|
||||
/// </summary>
|
||||
/// <param name="message">消息</param>
|
||||
/// <param name="inner">内部错误</param>
|
||||
/// <returns>nothing</returns>
|
||||
/// <exception cref="RuntimeEnvironmentException">环境异常</exception>
|
||||
[DoesNotReturn]
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public static RuntimeEnvironmentException RuntimeEnvironment(string message, Exception inner)
|
||||
{
|
||||
throw new RuntimeEnvironmentException(message, inner);
|
||||
}
|
||||
|
||||
[DoesNotReturn]
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public static NotSupportedException NotSupported()
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
[DoesNotReturn]
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public static OperationCanceledException OperationCanceled(string message, Exception? inner = default)
|
||||
{
|
||||
throw new OperationCanceledException(message, inner);
|
||||
}
|
||||
|
||||
[DoesNotReturn]
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public static PackageConvertException PackageConvert(string message, Exception? inner)
|
||||
{
|
||||
throw new PackageConvertException(message, inner);
|
||||
}
|
||||
|
||||
[DoesNotReturn]
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public static RuntimeEnvironmentException RuntimeEnvironment(string message, Exception? inner)
|
||||
{
|
||||
throw new RuntimeEnvironmentException(message, inner);
|
||||
}
|
||||
|
||||
[DoesNotReturn]
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public static UserdataCorruptedException UserdataCorrupted(string message, Exception? inner)
|
||||
{
|
||||
throw new UserdataCorruptedException(message, inner);
|
||||
}
|
||||
}
|
||||
@@ -49,7 +49,14 @@ internal sealed partial class ShellLinkInterop : IShellLinkInterop
|
||||
string target = Path.Combine(desktop, $"{SH.AppNameAndVersion.Format(runtimeOptions.Version)}.lnk");
|
||||
|
||||
IPersistFile persistFile = (IPersistFile)shellLink;
|
||||
persistFile.Save(target, false);
|
||||
try
|
||||
{
|
||||
persistFile.Save(target, false);
|
||||
}
|
||||
catch (UnauthorizedAccessException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.UI.Dispatching;
|
||||
using System.Runtime.ExceptionServices;
|
||||
|
||||
namespace Snap.Hutao.Core.Threading;
|
||||
|
||||
@@ -18,15 +19,35 @@ internal static class DispatcherQueueExtension
|
||||
/// <param name="action">执行的回调</param>
|
||||
public static void Invoke(this DispatcherQueue dispatcherQueue, Action action)
|
||||
{
|
||||
using (ManualResetEventSlim blockEvent = new())
|
||||
if (dispatcherQueue.HasThreadAccess)
|
||||
{
|
||||
action();
|
||||
return;
|
||||
}
|
||||
|
||||
ExceptionDispatchInfo? exceptionDispatchInfo = null;
|
||||
using (ManualResetEventSlim blockEvent = new(false))
|
||||
{
|
||||
dispatcherQueue.TryEnqueue(() =>
|
||||
{
|
||||
action();
|
||||
blockEvent.Set();
|
||||
try
|
||||
{
|
||||
action();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ExceptionDispatchInfo.Capture(ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
blockEvent.Set();
|
||||
}
|
||||
});
|
||||
|
||||
blockEvent.Wait();
|
||||
#pragma warning disable CA1508
|
||||
exceptionDispatchInfo?.Throw();
|
||||
#pragma warning restore CA1508
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.UI.Dispatching;
|
||||
|
||||
namespace Snap.Hutao.Core.Threading;
|
||||
|
||||
internal sealed class DispatcherQueueSynchronizationContextSendSupport : SynchronizationContext
|
||||
{
|
||||
private readonly DispatcherQueue dispatcherQueue;
|
||||
|
||||
public DispatcherQueueSynchronizationContextSendSupport(DispatcherQueue dispatcherQueue)
|
||||
{
|
||||
this.dispatcherQueue = dispatcherQueue;
|
||||
}
|
||||
|
||||
public override void Post(SendOrPostCallback d, object? state)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(d);
|
||||
dispatcherQueue.TryEnqueue(() => d(state));
|
||||
}
|
||||
|
||||
public override void Send(SendOrPostCallback d, object? state)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(d);
|
||||
dispatcherQueue.Invoke(() => d(state));
|
||||
}
|
||||
|
||||
public override SynchronizationContext CreateCopy()
|
||||
{
|
||||
return new DispatcherQueueSynchronizationContextSendSupport(dispatcherQueue);
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ namespace Snap.Hutao.Core.Threading;
|
||||
[Injection(InjectAs.Singleton, typeof(ITaskContext))]
|
||||
internal sealed class TaskContext : ITaskContext
|
||||
{
|
||||
private readonly DispatcherQueueSynchronizationContext dispatcherQueueSynchronizationContext;
|
||||
private readonly DispatcherQueueSynchronizationContextSendSupport synchronizationContext;
|
||||
private readonly DispatcherQueue dispatcherQueue;
|
||||
|
||||
/// <summary>
|
||||
@@ -20,8 +20,8 @@ internal sealed class TaskContext : ITaskContext
|
||||
public TaskContext()
|
||||
{
|
||||
dispatcherQueue = DispatcherQueue.GetForCurrentThread();
|
||||
dispatcherQueueSynchronizationContext = new(dispatcherQueue);
|
||||
SynchronizationContext.SetSynchronizationContext(dispatcherQueueSynchronizationContext);
|
||||
synchronizationContext = new(dispatcherQueue);
|
||||
SynchronizationContext.SetSynchronizationContext(synchronizationContext);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -39,18 +39,11 @@ internal sealed class TaskContext : ITaskContext
|
||||
/// <inheritdoc/>
|
||||
public void InvokeOnMainThread(Action action)
|
||||
{
|
||||
if (dispatcherQueue.HasThreadAccess)
|
||||
{
|
||||
action();
|
||||
}
|
||||
else
|
||||
{
|
||||
dispatcherQueue.Invoke(action);
|
||||
}
|
||||
dispatcherQueue.Invoke(action);
|
||||
}
|
||||
|
||||
public IProgress<T> CreateProgressForMainThread<T>(Action<T> handler)
|
||||
{
|
||||
return new DispatcherQueueProgress<T>(handler, dispatcherQueueSynchronizationContext);
|
||||
return new DispatcherQueueProgress<T>(handler, synchronizationContext);
|
||||
}
|
||||
}
|
||||
@@ -48,7 +48,7 @@ internal sealed class HotKeyController : IHotKeyController
|
||||
|
||||
public void OnHotKeyPressed(in HotKeyParameter parameter)
|
||||
{
|
||||
if (parameter is { Key: VIRTUAL_KEY.VK_F8, Modifier: 0 })
|
||||
if (parameter is { Key: VIRTUAL_KEY.VK_F8, NativeModifier: 0 })
|
||||
{
|
||||
lock (locker)
|
||||
{
|
||||
|
||||
@@ -7,6 +7,11 @@ namespace Snap.Hutao.Core.Windowing.HotKey;
|
||||
|
||||
internal readonly struct HotKeyParameter
|
||||
{
|
||||
public readonly ushort Modifier;
|
||||
public readonly ushort NativeModifier;
|
||||
public readonly VIRTUAL_KEY Key;
|
||||
|
||||
public readonly HOT_KEY_MODIFIERS Modifier
|
||||
{
|
||||
get => (HOT_KEY_MODIFIERS)NativeModifier;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Windows.Win32.UI.WindowsAndMessaging;
|
||||
|
||||
namespace Snap.Hutao.Core.Windowing;
|
||||
|
||||
internal interface IMinMaxInfoHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// 处理最大最小信息
|
||||
/// </summary>
|
||||
/// <param name="info">信息</param>
|
||||
/// <param name="scalingFactor">缩放比</param>
|
||||
unsafe void HandleMinMaxInfo(ref MINMAXINFO info, double scalingFactor);
|
||||
}
|
||||
@@ -1,8 +1,6 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Windows.Win32.UI.WindowsAndMessaging;
|
||||
|
||||
namespace Snap.Hutao.Core.Windowing;
|
||||
|
||||
/// <summary>
|
||||
@@ -14,11 +12,4 @@ internal interface IWindowOptionsSource
|
||||
/// 窗体选项
|
||||
/// </summary>
|
||||
WindowOptions WindowOptions { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 处理最大最小信息
|
||||
/// </summary>
|
||||
/// <param name="pInfo">信息指针</param>
|
||||
/// <param name="scalingFactor">缩放比</param>
|
||||
unsafe void ProcessMinMaxInfo(MINMAXINFO* pInfo, double scalingFactor);
|
||||
}
|
||||
@@ -76,15 +76,15 @@ internal sealed class WindowController
|
||||
{
|
||||
// Set first launch size
|
||||
double scale = options.GetWindowScale();
|
||||
SizeInt32 transformedSize = options.InitSize.Scale(scale);
|
||||
RectInt32 rect = StructMarshal.RectInt32(transformedSize);
|
||||
SizeInt32 scaledSize = options.InitSize.Scale(scale);
|
||||
RectInt32 rect = StructMarshal.RectInt32(scaledSize);
|
||||
|
||||
if (options.PersistSize)
|
||||
{
|
||||
RectInt32 persistedRect = (CompactRect)LocalSetting.Get(SettingKeys.WindowRect, (CompactRect)rect);
|
||||
if (persistedRect.Size() >= options.InitSize.Size())
|
||||
{
|
||||
rect = persistedRect;
|
||||
rect = persistedRect.Scale(scale);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,7 +105,8 @@ internal sealed class WindowController
|
||||
// prevent save value when we are maximized.
|
||||
if (!windowPlacement.showCmd.HasFlag(SHOW_WINDOW_CMD.SW_SHOWMAXIMIZED))
|
||||
{
|
||||
LocalSetting.Set(SettingKeys.WindowRect, (CompactRect)window.AppWindow.GetRect());
|
||||
double scale = 1 / options.GetWindowScale();
|
||||
LocalSetting.Set(SettingKeys.WindowRect, (CompactRect)window.AppWindow.GetRect().Scale(scale));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,8 +114,10 @@ internal sealed class WindowController
|
||||
{
|
||||
if (e.PropertyName == nameof(AppOptions.BackdropType))
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(sender);
|
||||
UpdateSystemBackdrop(((AppOptions)sender).BackdropType);
|
||||
if (sender is AppOptions options)
|
||||
{
|
||||
UpdateSystemBackdrop(options.BackdropType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -71,17 +71,16 @@ internal sealed class WindowSubclass : IDisposable
|
||||
/// <inheritdoc/>
|
||||
public void Dispose()
|
||||
{
|
||||
hotKeyController.Unregister(options.Hwnd);
|
||||
|
||||
RemoveWindowSubclass(options.Hwnd, windowProc, WindowSubclassId);
|
||||
windowProc = null;
|
||||
|
||||
if (!options.UseLegacyDragBarImplementation)
|
||||
if (options.UseLegacyDragBarImplementation)
|
||||
{
|
||||
return;
|
||||
RemoveWindowSubclass(options.Hwnd, legacyDragBarProc, DragBarSubclassId);
|
||||
legacyDragBarProc = null;
|
||||
}
|
||||
|
||||
hotKeyController.Unregister(options.Hwnd);
|
||||
RemoveWindowSubclass(options.Hwnd, legacyDragBarProc, DragBarSubclassId);
|
||||
legacyDragBarProc = null;
|
||||
}
|
||||
|
||||
[SuppressMessage("", "SH002")]
|
||||
@@ -91,16 +90,18 @@ internal sealed class WindowSubclass : IDisposable
|
||||
{
|
||||
case WM_GETMINMAXINFO:
|
||||
{
|
||||
uint dpi = GetDpiForWindow(hwnd);
|
||||
double scalingFactor = Math.Round(dpi / 96D, 2, MidpointRounding.AwayFromZero);
|
||||
((IWindowOptionsSource)window).ProcessMinMaxInfo((MINMAXINFO*)lParam.Value, scalingFactor);
|
||||
if (window is IMinMaxInfoHandler handler)
|
||||
{
|
||||
handler.HandleMinMaxInfo(ref *(MINMAXINFO*)lParam.Value, options.GetWindowScale());
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_NCRBUTTONDOWN:
|
||||
case WM_NCRBUTTONUP:
|
||||
{
|
||||
return (LRESULT)(nint)WM_NULL;
|
||||
return default;
|
||||
}
|
||||
|
||||
case WM_HOTKEY:
|
||||
|
||||
@@ -62,4 +62,9 @@ internal static class StructExtension
|
||||
{
|
||||
return sizeInt32.Width * sizeInt32.Height;
|
||||
}
|
||||
|
||||
public static double Size(this Windows.Foundation.Size size)
|
||||
{
|
||||
return size.Width * size.Height;
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,8 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Core;
|
||||
using Snap.Hutao.Core.LifeCycle;
|
||||
using Snap.Hutao.Core.Windowing;
|
||||
using Snap.Hutao.Factory.Abstraction;
|
||||
using Windows.Storage.Pickers;
|
||||
using WinRT.Interop;
|
||||
@@ -16,7 +18,7 @@ internal sealed partial class PickerFactory : IPickerFactory
|
||||
{
|
||||
private const string AnyType = "*";
|
||||
|
||||
private readonly MainWindow mainWindow;
|
||||
private readonly ICurrentWindowReference currentWindow;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public FileOpenPicker GetFileOpenPicker(PickerLocationId location, string commitButton, params string[] fileTypes)
|
||||
@@ -78,7 +80,10 @@ internal sealed partial class PickerFactory : IPickerFactory
|
||||
{
|
||||
// Create a folder picker.
|
||||
T picker = new();
|
||||
InitializeWithWindow.Initialize(picker, mainWindow.WindowOptions.Hwnd);
|
||||
if (currentWindow.Window is IWindowOptionsSource optionsSource)
|
||||
{
|
||||
InitializeWithWindow.Initialize(picker, optionsSource.WindowOptions.Hwnd);
|
||||
}
|
||||
|
||||
return picker;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace Snap.Hutao;
|
||||
/// 指引窗口
|
||||
/// </summary>
|
||||
[Injection(InjectAs.Singleton)]
|
||||
internal sealed partial class GuideWindow : Window, IWindowOptionsSource
|
||||
internal sealed partial class GuideWindow : Window, IWindowOptionsSource, IMinMaxInfoHandler
|
||||
{
|
||||
private const int MinWidth = 1000;
|
||||
private const int MinHeight = 600;
|
||||
@@ -30,11 +30,11 @@ internal sealed partial class GuideWindow : Window, IWindowOptionsSource
|
||||
|
||||
WindowOptions IWindowOptionsSource.WindowOptions { get => windowOptions; }
|
||||
|
||||
public unsafe void ProcessMinMaxInfo(MINMAXINFO* pInfo, double scalingFactor)
|
||||
public unsafe void HandleMinMaxInfo(ref MINMAXINFO info, double scalingFactor)
|
||||
{
|
||||
pInfo->ptMinTrackSize.X = (int)Math.Max(MinWidth * scalingFactor, pInfo->ptMinTrackSize.X);
|
||||
pInfo->ptMinTrackSize.Y = (int)Math.Max(MinHeight * scalingFactor, pInfo->ptMinTrackSize.Y);
|
||||
pInfo->ptMaxTrackSize.X = (int)Math.Min(MaxWidth * scalingFactor, pInfo->ptMaxTrackSize.X);
|
||||
pInfo->ptMaxTrackSize.Y = (int)Math.Min(MaxHeight * scalingFactor, pInfo->ptMaxTrackSize.Y);
|
||||
info.ptMinTrackSize.X = (int)Math.Max(MinWidth * scalingFactor, info.ptMinTrackSize.X);
|
||||
info.ptMinTrackSize.Y = (int)Math.Max(MinHeight * scalingFactor, info.ptMinTrackSize.Y);
|
||||
info.ptMaxTrackSize.X = (int)Math.Min(MaxWidth * scalingFactor, info.ptMaxTrackSize.X);
|
||||
info.ptMaxTrackSize.Y = (int)Math.Min(MaxHeight * scalingFactor, info.ptMaxTrackSize.Y);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace Snap.Hutao;
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
[Injection(InjectAs.Singleton)]
|
||||
internal sealed partial class LaunchGameWindow : Window, IDisposable, IWindowOptionsSource
|
||||
internal sealed partial class LaunchGameWindow : Window, IDisposable, IWindowOptionsSource, IMinMaxInfoHandler
|
||||
{
|
||||
private const int MinWidth = 240;
|
||||
private const int MinHeight = 240;
|
||||
@@ -48,11 +48,11 @@ internal sealed partial class LaunchGameWindow : Window, IDisposable, IWindowOpt
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public unsafe void ProcessMinMaxInfo(MINMAXINFO* pInfo, double scalingFactor)
|
||||
public unsafe void HandleMinMaxInfo(ref MINMAXINFO info, double scalingFactor)
|
||||
{
|
||||
pInfo->ptMinTrackSize.X = (int)Math.Max(MinWidth * scalingFactor, pInfo->ptMinTrackSize.X);
|
||||
pInfo->ptMinTrackSize.Y = (int)Math.Max(MinHeight * scalingFactor, pInfo->ptMinTrackSize.Y);
|
||||
pInfo->ptMaxTrackSize.X = (int)Math.Min(MaxWidth * scalingFactor, pInfo->ptMaxTrackSize.X);
|
||||
pInfo->ptMaxTrackSize.Y = (int)Math.Min(MaxHeight * scalingFactor, pInfo->ptMaxTrackSize.Y);
|
||||
info.ptMinTrackSize.X = (int)Math.Max(MinWidth * scalingFactor, info.ptMinTrackSize.X);
|
||||
info.ptMinTrackSize.Y = (int)Math.Max(MinHeight * scalingFactor, info.ptMinTrackSize.Y);
|
||||
info.ptMaxTrackSize.X = (int)Math.Min(MaxWidth * scalingFactor, info.ptMaxTrackSize.X);
|
||||
info.ptMaxTrackSize.Y = (int)Math.Min(MaxHeight * scalingFactor, info.ptMaxTrackSize.Y);
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ namespace Snap.Hutao;
|
||||
[HighQuality]
|
||||
[Injection(InjectAs.Singleton)]
|
||||
[SuppressMessage("", "CA1001")]
|
||||
internal sealed partial class MainWindow : Window, IWindowOptionsSource
|
||||
internal sealed partial class MainWindow : Window, IWindowOptionsSource, IMinMaxInfoHandler
|
||||
{
|
||||
private const int MinWidth = 848;
|
||||
private const int MinHeight = 524;
|
||||
@@ -46,10 +46,10 @@ internal sealed partial class MainWindow : Window, IWindowOptionsSource
|
||||
public WindowOptions WindowOptions { get => windowOptions; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public unsafe void ProcessMinMaxInfo(MINMAXINFO* pInfo, double scalingFactor)
|
||||
public unsafe void HandleMinMaxInfo(ref MINMAXINFO pInfo, double scalingFactor)
|
||||
{
|
||||
pInfo->ptMinTrackSize.X = (int)Math.Max(MinWidth * scalingFactor, pInfo->ptMinTrackSize.X);
|
||||
pInfo->ptMinTrackSize.Y = (int)Math.Max(MinHeight * scalingFactor, pInfo->ptMinTrackSize.Y);
|
||||
pInfo.ptMinTrackSize.X = (int)Math.Max(MinWidth * scalingFactor, pInfo.ptMinTrackSize.X);
|
||||
pInfo.ptMinTrackSize.Y = (int)Math.Max(MinHeight * scalingFactor, pInfo.ptMinTrackSize.Y);
|
||||
}
|
||||
|
||||
private void OnClosed(object sender, WindowEventArgs args)
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Snap.Hutao.Model.InterChange.GachaLog;
|
||||
|
||||
/// <summary>
|
||||
@@ -49,20 +51,35 @@ internal sealed class UIGF
|
||||
/// <summary>
|
||||
/// 列表物品是否正常
|
||||
/// </summary>
|
||||
/// <param name="itemId">首个出错的Id</param>
|
||||
/// <param name="id">首个出错的Id</param>
|
||||
/// <returns>是否正常</returns>
|
||||
public bool IsMajor2Minor2OrLowerListValid([NotNullWhen(false)] out long itemId)
|
||||
public bool IsMajor2Minor2OrLowerListValid([NotNullWhen(false)] out long id)
|
||||
{
|
||||
foreach (UIGFItem item in List)
|
||||
foreach (ref readonly UIGFItem item in CollectionsMarshal.AsSpan(List))
|
||||
{
|
||||
if (item.ItemType != SH.ModelInterchangeUIGFItemTypeAvatar && item.ItemType != SH.ModelInterchangeUIGFItemTypeWeapon)
|
||||
{
|
||||
itemId = item.Id;
|
||||
id = item.Id;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
itemId = 0;
|
||||
id = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool IsMajor2Minor3OrHigherListValid([NotNullWhen(false)] out long id)
|
||||
{
|
||||
foreach (ref readonly UIGFItem item in CollectionsMarshal.AsSpan(List))
|
||||
{
|
||||
if (string.IsNullOrEmpty(item.ItemId))
|
||||
{
|
||||
id = item.Id;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
id = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -91,6 +91,8 @@ internal static class AvatarIds
|
||||
public static readonly AvatarId Freminet = 10000085;
|
||||
public static readonly AvatarId Wriothesley = 10000086;
|
||||
public static readonly AvatarId Neuvillette = 10000087;
|
||||
public static readonly AvatarId Charlotte = 10000088;
|
||||
public static readonly AvatarId Furina = 10000089;
|
||||
|
||||
/// <summary>
|
||||
/// 检查该角色是否为主角
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<Identity
|
||||
Name="60568DGPStudio.SnapHutao"
|
||||
Publisher="CN=35C8E923-85DF-49A7-9172-B39DC6312C52"
|
||||
Version="1.7.7.0" />
|
||||
Version="1.7.11.0" />
|
||||
|
||||
<Properties>
|
||||
<DisplayName>Snap Hutao</DisplayName>
|
||||
|
||||
@@ -2418,6 +2418,15 @@ namespace Snap.Hutao.Resource.Localization {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 当前 WebView2 版本不支持管理配置,继续使用可能会导致异常,请尽快升级 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string ViewControlWebViewerCoreWebView2ProfileQueryInterfaceFailed {
|
||||
get {
|
||||
return ResourceManager.GetString("ViewControlWebViewerCoreWebView2ProfileQueryInterfaceFailed", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 养成计划 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -3777,6 +3786,15 @@ namespace Snap.Hutao.Resource.Localization {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 保存游戏路径失败 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string ViewModelSettingSetGamePathDatabaseFailedTitle {
|
||||
get {
|
||||
return ResourceManager.GetString("ViewModelSettingSetGamePathDatabaseFailedTitle", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 用户 [{0}] 添加成功 的本地化字符串。
|
||||
/// </summary>
|
||||
|
||||
@@ -959,6 +959,9 @@
|
||||
<data name="ViewControlStatisticsSegmentedItemContentStatistics" xml:space="preserve">
|
||||
<value>Statistics</value>
|
||||
</data>
|
||||
<data name="ViewControlWebViewerCoreWebView2ProfileQueryInterfaceFailed" xml:space="preserve">
|
||||
<value>The current version of WebView2 does not support management configuration, continue to use may cause abnormalities, please upgrade as soon as possible</value>
|
||||
</data>
|
||||
<data name="ViewCultivationHeader" xml:space="preserve">
|
||||
<value>Dev Plan</value>
|
||||
</data>
|
||||
@@ -1412,6 +1415,9 @@
|
||||
<data name="ViewModelSettingSetDataFolderSuccess" xml:space="preserve">
|
||||
<value>Set data directory successfully. Restart to apply changes.</value>
|
||||
</data>
|
||||
<data name="ViewModelSettingSetGamePathDatabaseFailedTitle" xml:space="preserve">
|
||||
<value>Failed to save game path</value>
|
||||
</data>
|
||||
<data name="ViewModelUserAdded" xml:space="preserve">
|
||||
<value>User [{0}] added successfully</value>
|
||||
</data>
|
||||
@@ -1938,7 +1944,7 @@
|
||||
<value>Server</value>
|
||||
</data>
|
||||
<data name="ViewPageLaunchGameSwitchSchemeWarning" xml:space="preserve">
|
||||
<value>版本更新前需要提前转换至与启动器匹配的服务器</value>
|
||||
<value>You need to convert to a server that matches the launcher before updating the version</value>
|
||||
</data>
|
||||
<data name="ViewPageLaunchGameUnlockFpsDescription" xml:space="preserve">
|
||||
<value>Please turn off V-Sync in the game settings. You may need a high-performance graphic card to support a high frame rate limit.</value>
|
||||
|
||||
@@ -169,10 +169,10 @@
|
||||
<value>権限不足のため、一時ファイルを作成できませんでした</value>
|
||||
</data>
|
||||
<data name="CoreJumpListHelperLaunchGameItemDisplayName" xml:space="preserve">
|
||||
<value>ゲームスタート</value>
|
||||
<value>ゲームランチャー</value>
|
||||
</data>
|
||||
<data name="CoreScheduleTaskHelperDailyNoteRefreshTaskDescription" xml:space="preserve">
|
||||
<value>胡桃がリアルタイムノートを更新しています | 編集や削除をしないでください</value>
|
||||
<value>胡桃がリアルタイムノートを更新するために使用するタスクです。編集や削除をしないでください!</value>
|
||||
</data>
|
||||
<data name="CoreThreadingSemaphoreSlimDisposed" xml:space="preserve">
|
||||
<value>セマフォが解放され、操作がキャンセルされました</value>
|
||||
@@ -211,10 +211,10 @@
|
||||
<value>{0:f2} 回目</value>
|
||||
</data>
|
||||
<data name="ModelBindingGachaTypedWishSummaryMaxOrangePullFormat" xml:space="preserve">
|
||||
<value>最も引けなかった回数: {0} 回</value>
|
||||
<value>最も遅い回数: {0} 回</value>
|
||||
</data>
|
||||
<data name="ModelBindingGachaTypedWishSummaryMinOrangePullFormat" xml:space="preserve">
|
||||
<value>最も早く引けた回数: {0} 回</value>
|
||||
<value>最も早い回数: {0} 回</value>
|
||||
</data>
|
||||
<data name="ModelBindingGachaWishBaseTotalCountFormat" xml:space="preserve">
|
||||
<value>{0} 回目</value>
|
||||
@@ -295,7 +295,7 @@
|
||||
<comment>Need EXACT same string in game</comment>
|
||||
</data>
|
||||
<data name="ModelIntrinsicBodyTypeBoy" xml:space="preserve">
|
||||
<value>少年</value>
|
||||
<value>ショタ</value>
|
||||
</data>
|
||||
<data name="ModelIntrinsicBodyTypeGirl" xml:space="preserve">
|
||||
<value>少女</value>
|
||||
@@ -426,58 +426,58 @@
|
||||
<value>この階層のボス</value>
|
||||
</data>
|
||||
<data name="ModelMetadataTowerWaveTypeGroupA" xml:space="preserve">
|
||||
<value>A组:不同的组同时在场,各自分波独立</value>
|
||||
<value>グループA: 異なるグループが同時に存在し、それぞれ独立したウェーブがある</value>
|
||||
</data>
|
||||
<data name="ModelMetadataTowerWaveTypeGroupAWave1" xml:space="preserve">
|
||||
<value>A组第一波:不同的组同时在场,各自分波独立</value>
|
||||
<value>グループA ウェーブ1: 異なるグループが同時に存在し、それぞれ独立したウェーブがある</value>
|
||||
</data>
|
||||
<data name="ModelMetadataTowerWaveTypeGroupAWave2" xml:space="preserve">
|
||||
<value>A组第二波:不同的组同时在场,各自分波独立</value>
|
||||
<value>グループA ウェーブ2: 異なるグループが同時に存在し、それぞれ独立したウェーブがある</value>
|
||||
</data>
|
||||
<data name="ModelMetadataTowerWaveTypeGroupAWave3" xml:space="preserve">
|
||||
<value>A组第三波:不同的组同时在场,各自分波独立</value>
|
||||
<value>グループA ウェーブ3: 異なるグループが同時に存在し、それぞれ独立したウェーブがある</value>
|
||||
</data>
|
||||
<data name="ModelMetadataTowerWaveTypeGroupB" xml:space="preserve">
|
||||
<value>B组:不同的组同时在场,各自分波独立</value>
|
||||
<value>グループB: 異なるグループが同時に存在し、それぞれ独立したウェーブがある</value>
|
||||
</data>
|
||||
<data name="ModelMetadataTowerWaveTypeGroupBWave1" xml:space="preserve">
|
||||
<value>B组第一波:不同的组同时在场,各自分波独立</value>
|
||||
<value>グループB ウェーブ1: 異なるグループが同時に存在し、それぞれ独立したウェーブがある</value>
|
||||
</data>
|
||||
<data name="ModelMetadataTowerWaveTypeGroupBWave2" xml:space="preserve">
|
||||
<value>B组第二波:不同的组同时在场,各自分波独立</value>
|
||||
<value>グループB ウェーブ2: 異なるグループが同時に存在し、それぞれ独立したウェーブがある</value>
|
||||
</data>
|
||||
<data name="ModelMetadataTowerWaveTypeGroupBWave3" xml:space="preserve">
|
||||
<value>B组第三波:不同的组同时在场,各自分波独立</value>
|
||||
<value>グループB ウェーブ3: 異なるグループが同時に存在し、それぞれ独立したウェーブがある</value>
|
||||
</data>
|
||||
<data name="ModelMetadataTowerWaveTypeGroupC" xml:space="preserve">
|
||||
<value>C组:不同的组同时在场,各自分波独立</value>
|
||||
<value>グループC: 異なるグループが同時に存在し、それぞれ独立したウェーブがある</value>
|
||||
</data>
|
||||
<data name="ModelMetadataTowerWaveTypeGroupCWave1" xml:space="preserve">
|
||||
<value>C组第一波:不同的组同时在场,各自分波独立</value>
|
||||
<value>グループC ウェーブ1: 異なるグループが同時に存在し、それぞれ独立したウェーブがある</value>
|
||||
</data>
|
||||
<data name="ModelMetadataTowerWaveTypeGroupCWave2" xml:space="preserve">
|
||||
<value>C组第二波:不同的组同时在场,各自分波独立</value>
|
||||
<value>グループC ウェーブ2: 異なるグループが同時に存在し、それぞれ独立したウェーブがある</value>
|
||||
</data>
|
||||
<data name="ModelMetadataTowerWaveTypeGroupCWave3" xml:space="preserve">
|
||||
<value>C组第三波:不同的组同时在场,各自分波独立</value>
|
||||
<value>グループC ウェーブ3: 異なるグループが同時に存在し、それぞれ独立したウェーブがある</value>
|
||||
</data>
|
||||
<data name="ModelMetadataTowerWaveTypeGroupD" xml:space="preserve">
|
||||
<value>D组:不同的组同时在场,各自分波独立</value>
|
||||
<value>グループD: 異なるグループが同時に存在し、それぞれ独立したウェーブがある</value>
|
||||
</data>
|
||||
<data name="ModelMetadataTowerWaveTypeGroupDWave1" xml:space="preserve">
|
||||
<value>D组第一波:不同的组同时在场,各自分波独立</value>
|
||||
<value>グループD ウェーブ1: 異なるグループが同時に存在し、それぞれ独立したウェーブがある</value>
|
||||
</data>
|
||||
<data name="ModelMetadataTowerWaveTypeGroupDWave2" xml:space="preserve">
|
||||
<value>D组第二波:不同的组同时在场,各自分波独立</value>
|
||||
<value>グループD ウェーブ2: 異なるグループが同時に存在し、それぞれ独立したウェーブがある</value>
|
||||
</data>
|
||||
<data name="ModelMetadataTowerWaveTypeGroupDWave3" xml:space="preserve">
|
||||
<value>D组第三波:不同的组同时在场,各自分波独立</value>
|
||||
<value>グループD ウェーブ3: 異なるグループが同時に存在し、それぞれ独立したウェーブがある</value>
|
||||
</data>
|
||||
<data name="ModelMetadataTowerWaveTypeIndependent" xml:space="preserve">
|
||||
<value>与其他怪物独立</value>
|
||||
<value>他の敵とは独立</value>
|
||||
</data>
|
||||
<data name="ModelMetadataTowerWaveTypeSuppressed" xml:space="preserve">
|
||||
<value>暂时没有分波信息</value>
|
||||
<value>ウェーブ情報がありません</value>
|
||||
</data>
|
||||
<data name="ModelMetadataTowerWaveTypeWave1" xml:space="preserve">
|
||||
<value>ウェーブ 1: すべての敵を倒すと、次のウェーブの敵が出現する。</value>
|
||||
@@ -498,13 +498,13 @@
|
||||
<value>キャラクターラインナップを更新する</value>
|
||||
</data>
|
||||
<data name="ModelNameValueDefaultName" xml:space="preserve">
|
||||
<value>データありません</value>
|
||||
<value>データがありません</value>
|
||||
</data>
|
||||
<data name="ModelWeaponAffixFormat" xml:space="preserve">
|
||||
<value>精錬ランク{0}</value>
|
||||
</data>
|
||||
<data name="MustSelectUserAndUid" xml:space="preserve">
|
||||
<value>必须先选择一个用户与角色</value>
|
||||
<value>ユーザーとUIDを選択する必要があります</value>
|
||||
</data>
|
||||
<data name="ServiceAchievementImportResultFormat" xml:space="preserve">
|
||||
<value>{0} つのアチーブメントを追加 | {1} つのアチーブメントを更新 |{2} つのアチーブメントを削除</value>
|
||||
@@ -645,10 +645,10 @@
|
||||
<value>育成計画を複数選択しています</value>
|
||||
</data>
|
||||
<data name="ServiceDailyNoteNotifierActionLaunchGameButton" xml:space="preserve">
|
||||
<value>スタート</value>
|
||||
<value>ゲームを起動</value>
|
||||
</data>
|
||||
<data name="ServiceDailyNoteNotifierActionLaunchGameDismiss" xml:space="preserve">
|
||||
<value>わかりました</value>
|
||||
<value>了解</value>
|
||||
</data>
|
||||
<data name="ServiceDailyNoteNotifierAttribution" xml:space="preserve">
|
||||
<value>リクエストエラー</value>
|
||||
@@ -675,7 +675,7 @@
|
||||
<value>現在の洞天宝銭:{0}</value>
|
||||
</data>
|
||||
<data name="ServiceDailyNoteNotifierMultiValueReached" xml:space="preserve">
|
||||
<value>多个提醒项达到设定值</value>
|
||||
<value>複数の通知項目が設定値に達しました</value>
|
||||
</data>
|
||||
<data name="ServiceDailyNoteNotifierResin" xml:space="preserve">
|
||||
<value>天然樹脂</value>
|
||||
@@ -690,7 +690,7 @@
|
||||
<value>参量物質変化器</value>
|
||||
</data>
|
||||
<data name="ServiceDailyNoteNotifierTransformerAdaptiveHint" xml:space="preserve">
|
||||
<value>まもなく完成</value>
|
||||
<value>準備完了</value>
|
||||
</data>
|
||||
<data name="ServiceDailyNoteNotifierTransformerHint" xml:space="preserve">
|
||||
<value>参量物質変化器は使用可能</value>
|
||||
@@ -720,7 +720,7 @@
|
||||
<value>無効なアイテムが含まれてます、Id:{0}</value>
|
||||
</data>
|
||||
<data name="ServiceGachaLogUrlProviderAuthkeyRequestFailed" xml:space="preserve">
|
||||
<value>请求验证密钥失败</value>
|
||||
<value>認証キーのリクエストに失敗しました。</value>
|
||||
</data>
|
||||
<data name="ServiceGachaLogUrlProviderCachePathInvalid" xml:space="preserve">
|
||||
<value>原神のパスの書き方に誤りがあるか、またはパスを正しく設定されていません。</value>
|
||||
@@ -744,7 +744,7 @@
|
||||
<value>Item Id:{0} はサポートしていません</value>
|
||||
</data>
|
||||
<data name="ServiceGachaUIGFImportLanguageNotMatch" xml:space="preserve">
|
||||
<value>UIGF ファイルの言語:{0} と胡桃の設定言語:{1} とマッチングしません。言語を切り替えて再度試してください</value>
|
||||
<value>UIGF ファイルの言語:{0} と胡桃の設定言語:{1} がマッチングしません。言語を切り替えて再度試してください</value>
|
||||
</data>
|
||||
<data name="ServiceGameDetectGameAccountMultiMatched" xml:space="preserve">
|
||||
<value>一致するアカウントが複数見つかりました。重複しているアカウントを削除してください。</value>
|
||||
@@ -753,25 +753,25 @@
|
||||
<value>ゲームのリソース情報を確認</value>
|
||||
</data>
|
||||
<data name="ServiceGameFileOperationExceptionMessage" xml:space="preserve">
|
||||
<value>游戏文件操作失败:{0}</value>
|
||||
<value>ゲームファイルの操作に失敗しました。: {0}</value>
|
||||
</data>
|
||||
<data name="ServiceGameLaunchPhaseProcessExited" xml:space="preserve">
|
||||
<value>ゲームプロセスが終了した</value>
|
||||
<value>ゲームプロセスが終了しました</value>
|
||||
</data>
|
||||
<data name="ServiceGameLaunchPhaseProcessInitializing" xml:space="preserve">
|
||||
<value>ゲームプロセスが初期化している</value>
|
||||
<value>ゲームプロセスを初期化しています</value>
|
||||
</data>
|
||||
<data name="ServiceGameLaunchPhaseProcessStarted" xml:space="preserve">
|
||||
<value>ゲームプロセスが生成された</value>
|
||||
<value>ゲームプロセスが生成されました</value>
|
||||
</data>
|
||||
<data name="ServiceGameLaunchPhaseUnlockFpsFailed" xml:space="preserve">
|
||||
<value>FPS上限解除失敗、プロセスが終了させる</value>
|
||||
<value>FPS上限の解除に失敗しました、プロセスを終了します</value>
|
||||
</data>
|
||||
<data name="ServiceGameLaunchPhaseUnlockFpsSucceed" xml:space="preserve">
|
||||
<value>FPS上限解除成功</value>
|
||||
</data>
|
||||
<data name="ServiceGameLaunchPhaseUnlockingFps" xml:space="preserve">
|
||||
<value>FPS上限解除を試みる</value>
|
||||
<value>FPSの上限解除を試みています</value>
|
||||
</data>
|
||||
<data name="ServiceGameLaunchPhaseWaitingProcessExit" xml:space="preserve">
|
||||
<value>プロセスが終了するまで待機中</value>
|
||||
@@ -783,16 +783,16 @@
|
||||
<value>Unity ログファイルが見つかりません</value>
|
||||
</data>
|
||||
<data name="ServiceGameLocatorUnityLogGamePathNotFound" xml:space="preserve">
|
||||
<value>Unity ログファイル内にはゲームパスが見つかりません</value>
|
||||
<value>Unity ログファイル内にゲームパスが見つかりません</value>
|
||||
</data>
|
||||
<data name="ServiceGamePackageConvertMoveFileBackupFormat" xml:space="preserve">
|
||||
<value>バックアップ:{0}</value>
|
||||
</data>
|
||||
<data name="ServiceGamePackageConvertMoveFileRenameFormat" xml:space="preserve">
|
||||
<value>リネーム:{0} を:{1} に</value>
|
||||
<value>リネーム:{0} を:{1} へ</value>
|
||||
</data>
|
||||
<data name="ServiceGamePackageConvertMoveFileRestoreFormat" xml:space="preserve">
|
||||
<value>復元する:{0}</value>
|
||||
<value>置換:{0}</value>
|
||||
</data>
|
||||
<data name="ServiceGamePackageRenameDataFolderFailed" xml:space="preserve">
|
||||
<value>データフォルダの名前を変更できませんでした</value>
|
||||
@@ -804,13 +804,13 @@
|
||||
<value>Package Versionを取得できません</value>
|
||||
</data>
|
||||
<data name="ServiceGamePackageRequestScatteredFileFailed" xml:space="preserve">
|
||||
<value>下载客户端文件失败:{0}</value>
|
||||
<value>クライアントファイルのダウンロードに失敗しました。: {0}</value>
|
||||
</data>
|
||||
<data name="ServiceGamePathLocateFailed" xml:space="preserve">
|
||||
<value>ゲームパスが見つかりません、設定にて変更してください</value>
|
||||
<value>ゲームパスが見つかりません、設定で変更してください</value>
|
||||
</data>
|
||||
<data name="ServiceGameRegisteryInteropLongPathsDisabled" xml:space="preserve">
|
||||
<value>未开启长路径功能,无法设置注册表键值</value>
|
||||
<value>長いパスのサポートがオフになっているため、レジストリキーを編集できません。</value>
|
||||
</data>
|
||||
<data name="ServiceGameRegisteryInteropPowershellNotFound" xml:space="preserve">
|
||||
<value>PowerShellのインストールディレクトリが見つかりません</value>
|
||||
@@ -822,22 +822,22 @@
|
||||
<value>設定ファイルを読み取れない、または保存できませんでした。管理者モードで再試行してください。</value>
|
||||
</data>
|
||||
<data name="ServiceGameUnlockerFindModuleNoModuleFound" xml:space="preserve">
|
||||
<value>在查找必要的模块时遇到问题:无法读取任何模块,可能是保护驱动已经加载完成,请重试</value>
|
||||
<value>必要なモジュールの読み込みに失敗しました: モジュールの読み込みが出来ません。保護ドライバが読み込まれている可能性があります。もう一度お試しください。</value>
|
||||
</data>
|
||||
<data name="ServiceGameUnlockerFindModuleTimeLimitExeeded" xml:space="preserve">
|
||||
<value>在查找必要的模块时遇到问题:查找模块超时,请重试</value>
|
||||
<value>必要なモジュールの検索時にエラーが発生しました: タイムアウトしました。もう一度お試しください。</value>
|
||||
</data>
|
||||
<data name="ServiceGameUnlockerInterestedPatternNotFound" xml:space="preserve">
|
||||
<value>在匹配内存时遇到问题:无法匹配到期望的内容</value>
|
||||
<value>メモリパターンマッチングエラー: 予期しない値です。</value>
|
||||
</data>
|
||||
<data name="ServiceGameUnlockerReadModuleMemoryCopyVirtualMemoryFailed" xml:space="preserve">
|
||||
<value>在读取必要的模块内存时遇到问题:无法将模块内存复制到指定位置</value>
|
||||
<value>メモリへのモジュールの読み込みに失敗しました: 指定されたメモリ位置にモジュールをコピーできません。</value>
|
||||
</data>
|
||||
<data name="ServiceGameUnlockerReadProcessMemoryPointerAddressFailed" xml:space="preserve">
|
||||
<value>在读取游戏进程内存时遇到问题:无法读取到指定地址的有效值</value>
|
||||
<value>ゲームプロセスのメモリの読み取りに失敗しました: 指定されたアドレスで有効な値を読み取れませんでした。</value>
|
||||
</data>
|
||||
<data name="ServiceHutaoUserGachaLogExpiredAt" xml:space="preserve">
|
||||
<value>祈願履歴のアップロード期限は\n{0:yyyy.MM.dd HH:mm:ss}</value>
|
||||
<value>祈願履歴のアップロード期限は\n{0:yyyy.MM.dd HH:mm:ss}です。</value>
|
||||
</data>
|
||||
<data name="ServiceMetadataFileNotFound" xml:space="preserve">
|
||||
<value>キャッシュされたメタデータファイルが見つかりませんでした</value>
|
||||
@@ -846,34 +846,34 @@
|
||||
<value>メタデータサービスが初期化されていないか、または初期化できませんでした</value>
|
||||
</data>
|
||||
<data name="ServiceMetadataParseFailed" xml:space="preserve">
|
||||
<value>メタデータの検証ファイルを解析できなかった</value>
|
||||
<value>メタデータの検証ファイルを解析できませんでした。</value>
|
||||
</data>
|
||||
<data name="ServiceMetadataRequestFailed" xml:space="preserve">
|
||||
<value>メタデータの検証ファイルをダウンロードできなかった</value>
|
||||
<value>メタデータの検証ファイルのダウンロードに失敗しました。</value>
|
||||
</data>
|
||||
<data name="ServiceMetadataVersionNotSupported" xml:space="preserve">
|
||||
<value>胡桃のバージョンが古すぎるため、アップデートを推奨します。</value>
|
||||
</data>
|
||||
<data name="ServiceSignInClaimRewardFailedFormat" xml:space="preserve">
|
||||
<value>ログインボーナスを獲得できなかった、{0}</value>
|
||||
<value>ログインボーナスを獲得できませんでした。 {0}</value>
|
||||
</data>
|
||||
<data name="ServiceSignInInfoRequestFailed" xml:space="preserve">
|
||||
<value>获取签到次数失败</value>
|
||||
<value>サインイン日数の取得に失敗しました。</value>
|
||||
</data>
|
||||
<data name="ServiceSignInRewardListRequestFailed" xml:space="preserve">
|
||||
<value>获取奖励列表失败</value>
|
||||
<value>ログイン報酬リストの取得に失敗しました。</value>
|
||||
</data>
|
||||
<data name="ServiceSignInRiskVerificationFailed" xml:space="preserve">
|
||||
<value>認証に失敗した、MiYouSheの原神コーナーでログインボーナスを獲得してください</value>
|
||||
<value>認証に失敗しました、MiHoYo BBSの原神コーナーでログインボーナスを獲得してください</value>
|
||||
</data>
|
||||
<data name="ServiceSignInSuccessRewardFormat" xml:space="preserve">
|
||||
<value>ログインボーナスを獲得した、{0}×{1}</value>
|
||||
<value>ログインボーナスを獲得しました。{0}×{1}</value>
|
||||
</data>
|
||||
<data name="ServiceUIGFImportUnsupportedVersion" xml:space="preserve">
|
||||
<value>サポートされていないUIGFバージョン</value>
|
||||
</data>
|
||||
<data name="ServiceUserCurrentMultiMatched" xml:space="preserve">
|
||||
<value>ユーザー情報が複数セレクトしています</value>
|
||||
<value>ユーザー情報を複数選択しています。</value>
|
||||
</data>
|
||||
<data name="ServiceUserCurrentUpdateAndSaveFailed" xml:space="preserve">
|
||||
<value>ユーザー {0} のステータスを保存できません</value>
|
||||
@@ -959,6 +959,9 @@
|
||||
<data name="ViewControlStatisticsSegmentedItemContentStatistics" xml:space="preserve">
|
||||
<value>統計</value>
|
||||
</data>
|
||||
<data name="ViewControlWebViewerCoreWebView2ProfileQueryInterfaceFailed" xml:space="preserve">
|
||||
<value>現在インストールされているWebView2のバージョンは構成管理をサポートしていないため、エラーが発生する可能性があります。WebView2 コンポーネントを更新してください。</value>
|
||||
</data>
|
||||
<data name="ViewCultivationHeader" xml:space="preserve">
|
||||
<value>育成計画</value>
|
||||
</data>
|
||||
@@ -1044,7 +1047,7 @@
|
||||
<value>祈願記録をインポート</value>
|
||||
</data>
|
||||
<data name="ViewDialogGachaLogRefreshProgressAuthkeyTimeout" xml:space="preserve">
|
||||
<value>祈願履歴Urlは無効、再度取得してください</value>
|
||||
<value>祈願履歴Urlが無効です、再度取得してください</value>
|
||||
</data>
|
||||
<data name="ViewDialogGachaLogRefreshProgressDescription" xml:space="preserve">
|
||||
<value>{0} を取得中</value>
|
||||
@@ -1059,22 +1062,22 @@
|
||||
<value>祈願履歴のURLを直接入力</value>
|
||||
</data>
|
||||
<data name="ViewDialogGeetestCustomUrlCompositInputHint" xml:space="preserve">
|
||||
<value>请输入请求接口的 Url 复合模板</value>
|
||||
<value>パラメーターを使用したリクエストURLの入力</value>
|
||||
</data>
|
||||
<data name="ViewDialogGeetestCustomUrlReturnDataDescription1" xml:space="preserve">
|
||||
<value>接口需要返回形如上方所示的 Json 数据,多余的数据会被忽略</value>
|
||||
<value>認証サービスは、上記のようなJsonデータを返す必要があります。この例以外のデータは無視されます。</value>
|
||||
</data>
|
||||
<data name="ViewDialogGeetestCustomUrlReturnDataDescription2" xml:space="preserve">
|
||||
<value>"code" は 0 の場合のみ認証成功です。他の戻り値は認証失敗となります。</value>
|
||||
</data>
|
||||
<data name="ViewDialogGeetestCustomUrlReturnDataHeader" xml:space="preserve">
|
||||
<value>結果を返す</value>
|
||||
<value>戻り値</value>
|
||||
</data>
|
||||
<data name="ViewDialogGeetestCustomUrlSampleDescription1" xml:space="preserve">
|
||||
<value>{0} はリクエストの際、gtに切り替えます</value>
|
||||
<value>{0} はリクエストの際、gtに置き換えられます</value>
|
||||
</data>
|
||||
<data name="ViewDialogGeetestCustomUrlSampleDescription2" xml:space="preserve">
|
||||
<value>{1} はリクエストの際、challengeに切り替えます</value>
|
||||
<value>{1} はリクエストの際、challengeに置き換えられます</value>
|
||||
</data>
|
||||
<data name="ViewDialogGeetestCustomUrlSampleDescription3" xml:space="preserve">
|
||||
<value>GETメソッドでリクエストの処理を行います。</value>
|
||||
@@ -1083,7 +1086,7 @@
|
||||
<value>例</value>
|
||||
</data>
|
||||
<data name="ViewDialogGeetestCustomUrlTitle" xml:space="preserve">
|
||||
<value>配置无感验证接口</value>
|
||||
<value>Geetest/CAPTCHA 認証APIの設定</value>
|
||||
</data>
|
||||
<data name="ViewDialogImportExportApp" xml:space="preserve">
|
||||
<value>Appをエクスポート</value>
|
||||
@@ -1101,7 +1104,7 @@
|
||||
<value>UIAFバージョン</value>
|
||||
</data>
|
||||
<data name="ViewDialogImportUIGFExportListCount" xml:space="preserve">
|
||||
<value>记录条数</value>
|
||||
<value>レコード数</value>
|
||||
</data>
|
||||
<data name="ViewDialogImportUIGFExportUid" xml:space="preserve">
|
||||
<value>UID</value>
|
||||
@@ -1128,16 +1131,16 @@
|
||||
<value>ユーザーデータを完全に削除しますか</value>
|
||||
</data>
|
||||
<data name="ViewDialogUserDocumentAction" xml:space="preserve">
|
||||
<value>立即前往</value>
|
||||
<value>すぐに移動</value>
|
||||
</data>
|
||||
<data name="ViewDialogUserDocumentDescription" xml:space="preserve">
|
||||
<value>进入文档页面并按指示操作</value>
|
||||
<value>ドキュメントのページへ移動し、指示に従って操作してください</value>
|
||||
</data>
|
||||
<data name="ViewDialogUserDocumentHeader" xml:space="preserve">
|
||||
<value>ドキュメント</value>
|
||||
</data>
|
||||
<data name="ViewDialogUserInputPlaceholder" xml:space="preserve">
|
||||
<value>STokenが含めているCookieを入力してください</value>
|
||||
<value>STokenが含まれたCookieを入力してください</value>
|
||||
</data>
|
||||
<data name="ViewDialogUserTitle" xml:space="preserve">
|
||||
<value>クッキーを設定</value>
|
||||
@@ -1167,16 +1170,16 @@
|
||||
<value>実行環境</value>
|
||||
</data>
|
||||
<data name="ViewGuideStepEnvironmentAfterInstallDescription" xml:space="preserve">
|
||||
<value>安装完成后重启胡桃以查看是否正常生效</value>
|
||||
<value>インストール完了後に胡桃を再起動し、動作を確認してください</value>
|
||||
</data>
|
||||
<data name="ViewGuideStepEnvironmentFontDescription1" xml:space="preserve">
|
||||
<value>アイコンが文字化けが起きた場合は、ここに</value>
|
||||
<value>上のアイコンが読み込めなかったり文字化けしている場合はこちら</value>
|
||||
</data>
|
||||
<data name="ViewGuideStepEnvironmentFontDescription2" xml:space="preserve">
|
||||
<value>フォントを自動的にダウンロード、インストールします</value>
|
||||
</data>
|
||||
<data name="ViewGuideStepEnvironmentWebView2Description1" xml:space="preserve">
|
||||
<value>WebView2 ランタイムが検出されませんのアラートが出た場合は、ここに</value>
|
||||
<value>WebView2 ランタイムが検出されませんとアラートが出た場合はこちら</value>
|
||||
</data>
|
||||
<data name="ViewGuideStepEnvironmentWebView2Description2" xml:space="preserve">
|
||||
<value>ランタイムを自動的にダウンロード、インストールします</value>
|
||||
@@ -1197,13 +1200,13 @@
|
||||
<value>ゲームランチャー</value>
|
||||
</data>
|
||||
<data name="ViewModelAchievementArchiveAdded" xml:space="preserve">
|
||||
<value>アーカイブ [{0}] を作成されました</value>
|
||||
<value>アーカイブ [{0}] を作成しました</value>
|
||||
</data>
|
||||
<data name="ViewModelAchievementArchiveAlreadyExists" xml:space="preserve">
|
||||
<value>アーカイブ [{0}] はすでに使用されています。別の名前で作成してください</value>
|
||||
</data>
|
||||
<data name="ViewModelAchievementArchiveInvalidName" xml:space="preserve">
|
||||
<value>無効な文字が含むアーカイブを作成できません</value>
|
||||
<value>無効な文字を含むアーカイブは作成できません</value>
|
||||
</data>
|
||||
<data name="ViewModelAchievementExportFileType" xml:space="preserve">
|
||||
<value>UIAF ファイル</value>
|
||||
@@ -1224,7 +1227,7 @@
|
||||
<value>素材リスト取得中、しばらくお待ちください</value>
|
||||
</data>
|
||||
<data name="ViewModelAvatarPropertyCalculateWeaponNull" xml:space="preserve">
|
||||
<value>当前角色无法计算,请同步信息后再试</value>
|
||||
<value>現在のキャラクターを計算できません。データの同期後に再試行してください。</value>
|
||||
</data>
|
||||
<data name="ViewModelAvatarPropertyEnkaApiUnavailable" xml:space="preserve">
|
||||
<value>キャラクターデータサービス [Enka API] は現在利用できません。</value>
|
||||
@@ -1236,7 +1239,7 @@
|
||||
<value>データを取得中</value>
|
||||
</data>
|
||||
<data name="ViewModelAvatarPropertyOpenClipboardFail" xml:space="preserve">
|
||||
<value>クリップボードを読み込みできません</value>
|
||||
<value>クリップボードから読み込みできません</value>
|
||||
</data>
|
||||
<data name="ViewModelAvatarPropertyShowcaseNotOpen" xml:space="preserve">
|
||||
<value>キャラクターラインナップが未配置か非表示です。ゲーム内のプロフィール編集で設定してください</value>
|
||||
@@ -1248,10 +1251,10 @@
|
||||
<value>育成計画の追加に失敗しました</value>
|
||||
</data>
|
||||
<data name="ViewModelCultivationBatchAddCompletedFormat" xml:space="preserve">
|
||||
<value>完了した:追加/更新:{0}、スキップ{1}</value>
|
||||
<value>完了しました:追加/更新:{0}、スキップ{1}</value>
|
||||
</data>
|
||||
<data name="ViewModelCultivationBatchAddIncompletedFormat" xml:space="preserve">
|
||||
<value>一部完了した:追加/更新:{0}、スキップ{1}</value>
|
||||
<value>操作の一部に失敗しました:追加/更新:{0}、スキップ{1}</value>
|
||||
</data>
|
||||
<data name="ViewModelCultivationEntryAddSuccess" xml:space="preserve">
|
||||
<value>選択中の育成計画に正常に追加されました</value>
|
||||
@@ -1260,7 +1263,7 @@
|
||||
<value>育成計画で新規作成及びセットしてから続けてください</value>
|
||||
</data>
|
||||
<data name="ViewModelCultivationProjectAdded" xml:space="preserve">
|
||||
<value>追加完了</value>
|
||||
<value>正常に追加されました。</value>
|
||||
</data>
|
||||
<data name="ViewModelCultivationProjectAlreadyExists" xml:space="preserve">
|
||||
<value>育成計画は同じ名前を使えません。他の名前を使用してください。</value>
|
||||
@@ -1296,7 +1299,7 @@
|
||||
<value>指定された位置に保存しました</value>
|
||||
</data>
|
||||
<data name="ViewModelExportSuccessTitle" xml:space="preserve">
|
||||
<value>エクスポート成功しました</value>
|
||||
<value>エクスポートに成功しました</value>
|
||||
</data>
|
||||
<data name="ViewModelExportWarningMessage" xml:space="preserve">
|
||||
<value>書き込み処理でエラーが発生しました</value>
|
||||
@@ -1317,7 +1320,7 @@
|
||||
<value>UIGF バージョンが古いため、インポートできません</value>
|
||||
</data>
|
||||
<data name="ViewModelGachaLogImportWarningMessage2" xml:space="preserve">
|
||||
<value>インポートデータにサポートされないアイテムが含まれている</value>
|
||||
<value>インポートデータにサポートされていないアイテムが含まれています</value>
|
||||
</data>
|
||||
<data name="ViewModelGachaLogImportWarningTitle" xml:space="preserve">
|
||||
<value>インポート失敗</value>
|
||||
@@ -1341,7 +1344,7 @@
|
||||
<value>{0} を削除してよろしいでしょうか?</value>
|
||||
</data>
|
||||
<data name="ViewModelGachaLogRetrieveFromHutaoCloudProgress" xml:space="preserve">
|
||||
<value>胡桃クラウドから祈願履歴を同期します</value>
|
||||
<value>胡桃クラウドで祈願履歴を同期します</value>
|
||||
</data>
|
||||
<data name="ViewModelGachaLogUploadToHutaoCloudProgress" xml:space="preserve">
|
||||
<value>胡桃クラウドにアップロード中</value>
|
||||
@@ -1359,7 +1362,7 @@
|
||||
<value>アセットをダウンロード中、しばらくお待ちください</value>
|
||||
</data>
|
||||
<data name="ViewModelHutaoPassportEmailNotValidHint" xml:space="preserve">
|
||||
<value>メールが正しい形式ではありません</value>
|
||||
<value>メールアドレスが正しい形式ではありません</value>
|
||||
</data>
|
||||
<data name="ViewModelImportFromClipboardErrorTitle" xml:space="preserve">
|
||||
<value>クリップボードのテキスト形式が正しくありません</value>
|
||||
@@ -1374,7 +1377,7 @@
|
||||
<value>インポート失敗</value>
|
||||
</data>
|
||||
<data name="ViewModelLaunchGameEnsureGameResourceFail" xml:space="preserve">
|
||||
<value>サーバー切り替えできませんでした</value>
|
||||
<value>サーバーの切り替えができませんでした</value>
|
||||
</data>
|
||||
<data name="ViewModelLaunchGameMultiChannelReadFail" xml:space="preserve">
|
||||
<value>ゲーム設定ファイル {0} の読み込みに失敗しました。ファイルが無いか、権限が不足している可能性があります。</value>
|
||||
@@ -1389,7 +1392,7 @@
|
||||
<value>アカウントの切り替えができませんでした</value>
|
||||
</data>
|
||||
<data name="ViewModelSettingActionComplete" xml:space="preserve">
|
||||
<value>完了した</value>
|
||||
<value>操作は完了しました</value>
|
||||
</data>
|
||||
<data name="ViewModelSettingClearWebCacheFail" xml:space="preserve">
|
||||
<value>削除に失敗しました。ディレクトリのアクセス許可がありません。「管理者として実行」で再度試してください</value>
|
||||
@@ -1404,13 +1407,16 @@
|
||||
<value>コピーしました</value>
|
||||
</data>
|
||||
<data name="ViewModelSettingCreateDesktopShortcutFailed" xml:space="preserve">
|
||||
<value>创建桌面快捷方式失败</value>
|
||||
<value>デスクトップへのショートカット作成に失敗しました</value>
|
||||
</data>
|
||||
<data name="ViewModelSettingGeetestCustomUrlSucceed" xml:space="preserve">
|
||||
<value>无感验证复合 Url 配置成功</value>
|
||||
<value>非探知認証複合URLの構成に成功しました</value>
|
||||
</data>
|
||||
<data name="ViewModelSettingSetDataFolderSuccess" xml:space="preserve">
|
||||
<value>データディレクトリセット完了、再起動して適用する</value>
|
||||
<value>データディレクトリのリセットが完了しました、再起動して変更を適用します</value>
|
||||
</data>
|
||||
<data name="ViewModelSettingSetGamePathDatabaseFailedTitle" xml:space="preserve">
|
||||
<value>ゲームパスの保存に失敗しました</value>
|
||||
</data>
|
||||
<data name="ViewModelUserAdded" xml:space="preserve">
|
||||
<value>ユーザー [{0}] を正常に追加しました</value>
|
||||
@@ -1425,7 +1431,7 @@
|
||||
<value>このCookieが無効のため、操作できません</value>
|
||||
</data>
|
||||
<data name="ViewModelUserRemoved" xml:space="preserve">
|
||||
<value>ユーザー [{0}] は削除されました</value>
|
||||
<value>ユーザー [{0}] を削除しました</value>
|
||||
</data>
|
||||
<data name="ViewModelUserUpdated" xml:space="preserve">
|
||||
<value>ユーザー [{0}] の Cookie が更新されました。</value>
|
||||
@@ -1473,7 +1479,7 @@
|
||||
<value>アチーブメント、キャプション、バージョンまたは番号で検索</value>
|
||||
</data>
|
||||
<data name="ViewPageAchievementSortIncompletedItemsFirst" xml:space="preserve">
|
||||
<value>优先未完成</value>
|
||||
<value>未達成順にソート</value>
|
||||
</data>
|
||||
<data name="ViewPageAnnouncementActivity" xml:space="preserve">
|
||||
<value>イベント</value>
|
||||
@@ -1494,7 +1500,7 @@
|
||||
<value>会心スコア</value>
|
||||
</data>
|
||||
<data name="ViewPageAvatarPropertyDefaultDescription" xml:space="preserve">
|
||||
<value>旅人の仲間の情報まだ入手していない</value>
|
||||
<value>旅人の仲間の情報がまだ無いぞ!</value>
|
||||
</data>
|
||||
<data name="ViewPageAvatarPropertyExportAsImage" xml:space="preserve">
|
||||
<value>画像をエクスポート</value>
|
||||
@@ -1515,13 +1521,13 @@
|
||||
<value>キャラクターラインナップの情報を同期</value>
|
||||
</data>
|
||||
<data name="ViewPageAvatarPropertyRefreshFromHoyolabCalculate" xml:space="preserve">
|
||||
<value>MiYouShe育成ツールから同期</value>
|
||||
<value>MiHoYo BBS育成ツールから同期</value>
|
||||
</data>
|
||||
<data name="ViewPageAvatarPropertyRefreshFromHoyolabCalculateDescription" xml:space="preserve">
|
||||
<value>キャラクターの天賦情報を同期</value>
|
||||
</data>
|
||||
<data name="ViewPageAvatarPropertyRefreshFromHoyolabGameRecord" xml:space="preserve">
|
||||
<value>MiYouSheから所持キャラを同期する</value>
|
||||
<value>MiHoYo BBSから所持キャラを同期</value>
|
||||
</data>
|
||||
<data name="ViewPageAvatarPropertyRefreshFromHoyolabGameRecordDescription" xml:space="preserve">
|
||||
<value>キャラ天賦以外の情報を概ね同期</value>
|
||||
@@ -1530,7 +1536,7 @@
|
||||
<value>更新日時</value>
|
||||
</data>
|
||||
<data name="ViewPageAvatarPropertyScore" xml:space="preserve">
|
||||
<value>評価する</value>
|
||||
<value>評価スコア</value>
|
||||
</data>
|
||||
<data name="ViewPageAvatarPropertySecondaryProperties" xml:space="preserve">
|
||||
<value>強化後付与のサブOP</value>
|
||||
@@ -1548,10 +1554,10 @@
|
||||
<value>続けるには、まず「育成計画」を立てよう</value>
|
||||
</data>
|
||||
<data name="ViewPageCultivationAddProjectDescription" xml:space="preserve">
|
||||
<value>稍后可以前往其他页面添加养成计划项</value>
|
||||
<value>育成計画の項目は後から他のページでも追加できます。</value>
|
||||
</data>
|
||||
<data name="ViewPageCultivationAvatarPropertyDescription" xml:space="preserve">
|
||||
<value>添加我的角色与武器到养成计划</value>
|
||||
<value>マイ キャラクターと武器を育成計画に追加します</value>
|
||||
</data>
|
||||
<data name="ViewPageCultivationCultivateEntry" xml:space="preserve">
|
||||
<value>育成素材</value>
|
||||
@@ -1611,16 +1617,16 @@
|
||||
<value>カードを削除</value>
|
||||
</data>
|
||||
<data name="ViewPageDailyNoteResinDiscountUsed" xml:space="preserve">
|
||||
<value>今週の消費半減回数は消化済</value>
|
||||
<value>今週の消費半減は消化済</value>
|
||||
</data>
|
||||
<data name="ViewPageDailyNoteSettingAutoRefresh" xml:space="preserve">
|
||||
<value>自動更新</value>
|
||||
</data>
|
||||
<data name="ViewPageDailyNoteSettingAutoRefreshDescription" xml:space="preserve">
|
||||
<value>指定間隔でリアルタイムノートの更新を設定する</value>
|
||||
<value>指定間隔でリアルタイムノートを更新します</value>
|
||||
</data>
|
||||
<data name="ViewPageDailyNoteSettingRefreshElevatedHint" xml:space="preserve">
|
||||
<value>这些选项仅允许在非管理员模式下更改</value>
|
||||
<value>これらの設定は管理者モードでない時のみ変更できます。</value>
|
||||
</data>
|
||||
<data name="ViewPageDailyNoteSettingRefreshHeader" xml:space="preserve">
|
||||
<value>更新</value>
|
||||
@@ -1632,7 +1638,7 @@
|
||||
<value>おやすみモード</value>
|
||||
</data>
|
||||
<data name="ViewPageDailyNoteVerify" xml:space="preserve">
|
||||
<value>验证当前用户与角色</value>
|
||||
<value>現在のユーザーとUIDを確認する</value>
|
||||
</data>
|
||||
<data name="ViewPageGachaLogAggressiveRefresh" xml:space="preserve">
|
||||
<value>すべて更新</value>
|
||||
@@ -1656,16 +1662,16 @@
|
||||
<value>このUidのクラウドバックアップを削除する</value>
|
||||
</data>
|
||||
<data name="ViewPageGachaLogHutaoCloudDeveloperHint" xml:space="preserve">
|
||||
<value>デベロッパーアカウントは利用期限ありません</value>
|
||||
<value>デベロッパーアカウントは利用期限がありません</value>
|
||||
</data>
|
||||
<data name="ViewPageGachaLogHutaoCloudNotAllowed" xml:space="preserve">
|
||||
<value>胡桃クラウドのサービス有効期限が切れました。</value>
|
||||
<value>胡桃クラウドのサービス期限が切れました。</value>
|
||||
</data>
|
||||
<data name="ViewPageGachaLogHutaoCloudRetrieve" xml:space="preserve">
|
||||
<value>このUidのクラウドバックアップをダウンロードする</value>
|
||||
</data>
|
||||
<data name="ViewPageGachaLogHutaoCloudSpiralAbyssActivityDescription" xml:space="preserve">
|
||||
<value>每期深渊首次上传可免费获得 3 天时长</value>
|
||||
<value>各シーズンの深境螺旋の記録を初めてアップロードすると3日間のフリーライセンスが付与されます。</value>
|
||||
</data>
|
||||
<data name="ViewPageGachaLogHutaoCloudSpiralAbyssActivityHeader" xml:space="preserve">
|
||||
<value>螺旋の記録をアップロード</value>
|
||||
@@ -1704,13 +1710,13 @@
|
||||
<value>現在のユーザーのCookieで祈願履歴を表示する</value>
|
||||
</data>
|
||||
<data name="ViewPageGachaLogRefreshByWebCache" xml:space="preserve">
|
||||
<value>キャッシュの再読み込み</value>
|
||||
<value>ゲーム内ブラウザキャッシュで更新</value>
|
||||
</data>
|
||||
<data name="ViewPageGachaLogRefreshByWebCacheDescription" xml:space="preserve">
|
||||
<value>ゲーム内ブラウザのキャッシュで祈願履歴を更新</value>
|
||||
</data>
|
||||
<data name="ViewPageGachaLogRemoveArchiveAction" xml:space="preserve">
|
||||
<value>このアーカイブを削除する</value>
|
||||
<value>現在のアーカイブを削除する</value>
|
||||
</data>
|
||||
<data name="ViewPageGahcaLogPivotAvatar" xml:space="preserve">
|
||||
<value>キャラクター</value>
|
||||
@@ -1734,13 +1740,13 @@
|
||||
<value>胡桃を {0} 回起動しました</value>
|
||||
</data>
|
||||
<data name="ViewPageHomeGreetingTextDefault" xml:space="preserve">
|
||||
<value>テイワットへようこそ</value>
|
||||
<value>テイワットへようこそ!</value>
|
||||
</data>
|
||||
<data name="ViewPageHomeGreetingTextEasterEgg" xml:space="preserve">
|
||||
<value>あなたの言う通りだが、しかし「胡桃」はDGP Studioが開発した...</value>
|
||||
</data>
|
||||
<data name="ViewPageHomeGreetingTextEpic1" xml:space="preserve">
|
||||
<value>ねぇ、旅人、今日はテイワットでの{0} 日目の冒険だよ</value>
|
||||
<value>なあ、旅人、今日はテイワットで{0} 日目の冒険だぞ!</value>
|
||||
</data>
|
||||
<data name="ViewPageHomeLaunchGameSettingAction" xml:space="preserve">
|
||||
<value>設定</value>
|
||||
@@ -1821,7 +1827,7 @@
|
||||
<value>パスワードを入力してください</value>
|
||||
</data>
|
||||
<data name="ViewPageHutaoPassportPasswordRequirementHint" xml:space="preserve">
|
||||
<value>最低8文字以上</value>
|
||||
<value>8文字以上必要です</value>
|
||||
</data>
|
||||
<data name="ViewPageHutaoPassportRegisterHeader" xml:space="preserve">
|
||||
<value>アカウント作成</value>
|
||||
@@ -1845,10 +1851,10 @@
|
||||
<value>上級者向け設定</value>
|
||||
</data>
|
||||
<data name="ViewPageLaunchGameAppearanceBorderlessDescription" xml:space="preserve">
|
||||
<value>将窗口创建为弹出窗口,不带框架</value>
|
||||
<value>枠の無いポップアップウィンドウとして作成します。</value>
|
||||
</data>
|
||||
<data name="ViewPageLaunchGameAppearanceBorderlessHeader" xml:space="preserve">
|
||||
<value>フレームレス</value>
|
||||
<value>ボーダーレス</value>
|
||||
</data>
|
||||
<data name="ViewPageLaunchGameAppearanceExclusiveDescription" xml:space="preserve">
|
||||
<value>ゲーム内ブラウザには対応していません。ウィンドウの切り替え操作などによりゲームが強制終了する可能性があります。</value>
|
||||
@@ -1890,7 +1896,7 @@
|
||||
<value>モニター</value>
|
||||
</data>
|
||||
<data name="ViewPageLaunchGameMultipleInstancesDescription" xml:space="preserve">
|
||||
<value>同时运行多个游戏客户端</value>
|
||||
<value>複数のゲームプロセスを同時に実行します。</value>
|
||||
</data>
|
||||
<data name="ViewPageLaunchGameMultipleInstancesHeader" xml:space="preserve">
|
||||
<value>マルチクライアント</value>
|
||||
@@ -1914,7 +1920,7 @@
|
||||
<value>このアカウントは UID と紐付けしていません</value>
|
||||
</data>
|
||||
<data name="ViewPageLaunchGameSwitchAccountAttachUidToolTip" xml:space="preserve">
|
||||
<value>绑定当前用户的角色</value>
|
||||
<value>現在のユーザのUIDを連携する</value>
|
||||
</data>
|
||||
<data name="ViewPageLaunchGameSwitchAccountDescription" xml:space="preserve">
|
||||
<value>ゲーム内でアカウントを切り替えたり、インターネット環境を変更した場合は再検出が必要です。</value>
|
||||
@@ -1938,7 +1944,7 @@
|
||||
<value>サーバー</value>
|
||||
</data>
|
||||
<data name="ViewPageLaunchGameSwitchSchemeWarning" xml:space="preserve">
|
||||
<value>版本更新前需要提前转换至与启动器匹配的服务器</value>
|
||||
<value>アップデートをする前に、ランチャーと同じサーバーに変更する必要があります。</value>
|
||||
</data>
|
||||
<data name="ViewPageLaunchGameUnlockFpsDescription" xml:space="preserve">
|
||||
<value>ゲーム内のグラフィック設定で垂直同期を無効にしてください。フレームレートを上げるにはもっと高性能のグラフィックボードが必要となります。</value>
|
||||
@@ -1953,13 +1959,13 @@
|
||||
<value>有効</value>
|
||||
</data>
|
||||
<data name="ViewPageLoginHoyoverseUserHint" xml:space="preserve">
|
||||
<value>HoYo Lab UIDを入力してください</value>
|
||||
<value>HoYoLab UIDを入力してください</value>
|
||||
</data>
|
||||
<data name="ViewPageLoginMihoyoUserLoggedInAction" xml:space="preserve">
|
||||
<value>ログインしました</value>
|
||||
</data>
|
||||
<data name="ViewPageLoginMihoyoUserTitle" xml:space="preserve">
|
||||
<value>Hoyoverse通行証をログイン</value>
|
||||
<value>MiHoYo BBS通行証でログイン</value>
|
||||
</data>
|
||||
<data name="ViewPageOpenScreenshotFolderAction" xml:space="preserve">
|
||||
<value>スクリーンショットフォルダを開く</value>
|
||||
@@ -1983,7 +1989,7 @@
|
||||
<value>テーマ</value>
|
||||
</data>
|
||||
<data name="ViewPageSettingCacheFolderDescription" xml:space="preserve">
|
||||
<value>イメージキャッシュはここに格納</value>
|
||||
<value>イメージキャッシュはここに格納されます</value>
|
||||
</data>
|
||||
<data name="ViewPageSettingCacheFolderHeader" xml:space="preserve">
|
||||
<value>イメージキャッシュフォルダを開く</value>
|
||||
@@ -1995,7 +2001,7 @@
|
||||
<value>新規作成</value>
|
||||
</data>
|
||||
<data name="ViewPageSettingCreateDesktopShortcutDescription" xml:space="preserve">
|
||||
<value>デスクトップで常に「管理者として実行」のエイリアスを作成する</value>
|
||||
<value>管理者として実行できるショートカットを作成します</value>
|
||||
</data>
|
||||
<data name="ViewPageSettingCreateDesktopShortcutHeader" xml:space="preserve">
|
||||
<value>ショートカットを作成する</value>
|
||||
@@ -2061,7 +2067,7 @@
|
||||
<value>構成</value>
|
||||
</data>
|
||||
<data name="ViewPageSettingGeetestCustomUrlDescription" xml:space="preserve">
|
||||
<value>配置当请求触发人机验证时使用的验证接口</value>
|
||||
<value>ボット確認に使用される認証APIの設定</value>
|
||||
</data>
|
||||
<data name="ViewPageSettingGeetestCustomUrlHeader" xml:space="preserve">
|
||||
<value>Geetest認証サービスの設定</value>
|
||||
@@ -2100,7 +2106,7 @@
|
||||
<value>胡桃アカウント</value>
|
||||
</data>
|
||||
<data name="ViewPageSettingIsAdvancedLaunchOptionsEnabledDescription" xml:space="preserve">
|
||||
<value>原神およびSnap Hutaoの利用規約を全て熟読し、その後で『ゲームランチャー - 上級者向け設定』を有効にします。</value>
|
||||
<value>原神およびSnap Hutaoの利用規約を全て熟読し、その後に『ゲームランチャー - 上級者向け設定』を有効にします。</value>
|
||||
</data>
|
||||
<data name="ViewPageSettingIsAdvancedLaunchOptionsEnabledHeader" xml:space="preserve">
|
||||
<value>上級者向け設定を有効にする</value>
|
||||
@@ -2112,7 +2118,7 @@
|
||||
<value>リセット</value>
|
||||
</data>
|
||||
<data name="ViewPageSettingResetStaticResourceDescription" xml:space="preserve">
|
||||
<value>全ての画像リソースを削除し、すぐに再度ダウンロードする</value>
|
||||
<value>全ての画像リソースを削除し、次の起動時に再度ダウンロードします</value>
|
||||
</data>
|
||||
<data name="ViewPageSettingResetStaticResourceHeader" xml:space="preserve">
|
||||
<value>画像リソースをリセット</value>
|
||||
@@ -2292,13 +2298,13 @@
|
||||
<value>編成</value>
|
||||
</data>
|
||||
<data name="ViewSpiralAbyssRecordMonsterAttacksMonolith" xml:space="preserve">
|
||||
<value>攻击地脉镇石</value>
|
||||
<value>地脈石へ攻撃</value>
|
||||
</data>
|
||||
<data name="ViewSpiralAbyssRefresh" xml:space="preserve">
|
||||
<value>データを再読み込み</value>
|
||||
</data>
|
||||
<data name="ViewSpiralAbyssRefreshDescription" xml:space="preserve">
|
||||
<value>MiYouSheから深境螺旋の記録を同期</value>
|
||||
<value>HoYoLABから深境螺旋の記録を同期</value>
|
||||
</data>
|
||||
<data name="ViewSpiralAbyssReveal" xml:space="preserve">
|
||||
<value>出撃回数</value>
|
||||
@@ -2388,16 +2394,16 @@
|
||||
<value>武器一覧</value>
|
||||
</data>
|
||||
<data name="WebAnnouncementMatchPermanentActivityTime" xml:space="preserve">
|
||||
<value>(?:〓活动时间〓|〓任务开放时间〓).*?\d\.\d版本更新(?:完成|)后永久开放</value>
|
||||
<value>(?:〓イベント期間〓|〓任務開始時間〓).*?\d\.\dバージョンアップ(?:完了|)後常設オープン</value>
|
||||
</data>
|
||||
<data name="WebAnnouncementMatchPersistentActivityTime" xml:space="preserve">
|
||||
<value>〓活动时间〓.*?\d\.\d版本期间持续开放</value>
|
||||
<value>〓イベント期間〓.*?\d\.\d当バージョン期間オープン</value>
|
||||
</data>
|
||||
<data name="WebAnnouncementMatchTransientActivityTime" xml:space="preserve">
|
||||
<value>(?:〓活动时间〓|祈愿时间|【上架时间】).*?(\d\.\d版本更新后).*?~.*?&lt;t class="t_(?:gl|lc)".*?&gt;(.*?)&lt;/t&gt;</value>
|
||||
<value>(?:〓イベント期間〓|祈願期間|【開始日時】).*?(\d\.\dバージョンアップ完了後).*?~.*?&lt;t class="t_(?:gl|lc)".*?&gt;(.*?)&lt;/t&gt;</value>
|
||||
</data>
|
||||
<data name="WebAnnouncementMatchVersionUpdateTime" xml:space="preserve">
|
||||
<value>〓更新时间〓.+?&lt;t class=\"t_(?:gl|lc)\".*?&gt;(.*?)&lt;/t&gt;</value>
|
||||
<value>〓更新日時〓.+?&lt;t class=\"t_(?:gl|lc)\".*?&gt;(.*?)&lt;/t&gt;</value>
|
||||
</data>
|
||||
<data name="WebAnnouncementMatchVersionUpdateTitle" xml:space="preserve">
|
||||
<value>Ver.\d\.\d 更新内容</value>
|
||||
@@ -2424,16 +2430,16 @@
|
||||
<value>すべての依頼を完了していません</value>
|
||||
</data>
|
||||
<data name="WebDailyNoteExtraTaskRewardNotTaken" xml:space="preserve">
|
||||
<value>「デイリー依頼」の報酬はまだ受け取っていません</value>
|
||||
<value>デイリー依頼の報酬はまだ受け取っていません</value>
|
||||
</data>
|
||||
<data name="WebDailyNoteExtraTaskRewardReceived" xml:space="preserve">
|
||||
<value>「デイリー依頼」の報酬は受け取り済みです</value>
|
||||
<value>デイリー依頼の報酬は受け取り済みです</value>
|
||||
</data>
|
||||
<data name="WebDailyNoteHomeCoinRecoveryFormat" xml:space="preserve">
|
||||
<value>上限到達まで{0}{1:HH:mm}</value>
|
||||
<value>上限到達まで{0} {1:HH:mm}</value>
|
||||
</data>
|
||||
<data name="WebDailyNoteHomeLocked" xml:space="preserve">
|
||||
<value>洞天形態未開放</value>
|
||||
<value>塵歌壺が未解放です</value>
|
||||
</data>
|
||||
<data name="WebDailyNoteRecoveryTimeDay0" xml:space="preserve">
|
||||
<value>今日</value>
|
||||
@@ -2451,7 +2457,7 @@
|
||||
<value>天然樹脂は完全に回復しました</value>
|
||||
</data>
|
||||
<data name="WebDailyNoteResinRecoveryFormat" xml:space="preserve">
|
||||
<value>{0} {1:HH:mm} 後ですべて回復</value>
|
||||
<value>{0} {1:HH:mm} 後にすべて回復</value>
|
||||
</data>
|
||||
<data name="WebDailyNoteTransformerAppend" xml:space="preserve">
|
||||
<value>後に再び使用することができます</value>
|
||||
@@ -2469,7 +2475,7 @@
|
||||
<value>未獲得</value>
|
||||
</data>
|
||||
<data name="WebDailyNoteTransformerNotObtainedDetail" xml:space="preserve">
|
||||
<value>参量物質変化器未獲得</value>
|
||||
<value>参量物質変化器を持っていません</value>
|
||||
</data>
|
||||
<data name="WebDailyNoteTransformerNotReached" xml:space="preserve">
|
||||
<value>クールタイム中</value>
|
||||
@@ -2484,7 +2490,7 @@
|
||||
<value>{0} 秒</value>
|
||||
</data>
|
||||
<data name="WebDailyNoteVerificationFailed" xml:space="preserve">
|
||||
<value>認証に失敗しました。「MiYouShe - 戦績ツール - リアルタイムノート」で確認し、認証を行ってください</value>
|
||||
<value>認証に失敗しました。「MiHoYo BBS - 戦績ツール - リアルタイムノート」で確認し、認証を行ってください</value>
|
||||
</data>
|
||||
<data name="WebEnkaResponseStatusCode400" xml:space="preserve">
|
||||
<value>UIDは正しくありません</value>
|
||||
|
||||
@@ -959,6 +959,9 @@
|
||||
<data name="ViewControlStatisticsSegmentedItemContentStatistics" xml:space="preserve">
|
||||
<value>统计</value>
|
||||
</data>
|
||||
<data name="ViewControlWebViewerCoreWebView2ProfileQueryInterfaceFailed" xml:space="preserve">
|
||||
<value>当前 WebView2 版本不支持管理配置,继续使用可能会导致异常,请尽快升级</value>
|
||||
</data>
|
||||
<data name="ViewCultivationHeader" xml:space="preserve">
|
||||
<value>육성 계획</value>
|
||||
</data>
|
||||
@@ -1412,6 +1415,9 @@
|
||||
<data name="ViewModelSettingSetDataFolderSuccess" xml:space="preserve">
|
||||
<value>데이터 경로를 설정했습니다. 변경 사항을 적용하기 위해 재시작합니다</value>
|
||||
</data>
|
||||
<data name="ViewModelSettingSetGamePathDatabaseFailedTitle" xml:space="preserve">
|
||||
<value>保存游戏路径失败</value>
|
||||
</data>
|
||||
<data name="ViewModelUserAdded" xml:space="preserve">
|
||||
<value>사용자 [{0}]가 정상적으로 추가되었습니다</value>
|
||||
</data>
|
||||
|
||||
@@ -959,6 +959,9 @@
|
||||
<data name="ViewControlStatisticsSegmentedItemContentStatistics" xml:space="preserve">
|
||||
<value>统计</value>
|
||||
</data>
|
||||
<data name="ViewControlWebViewerCoreWebView2ProfileQueryInterfaceFailed" xml:space="preserve">
|
||||
<value>当前 WebView2 版本不支持管理配置,继续使用可能会导致异常,请尽快升级</value>
|
||||
</data>
|
||||
<data name="ViewCultivationHeader" xml:space="preserve">
|
||||
<value>养成计划</value>
|
||||
</data>
|
||||
@@ -1412,6 +1415,9 @@
|
||||
<data name="ViewModelSettingSetDataFolderSuccess" xml:space="preserve">
|
||||
<value>设置数据目录成功,重启以应用更改</value>
|
||||
</data>
|
||||
<data name="ViewModelSettingSetGamePathDatabaseFailedTitle" xml:space="preserve">
|
||||
<value>保存游戏路径失败</value>
|
||||
</data>
|
||||
<data name="ViewModelUserAdded" xml:space="preserve">
|
||||
<value>用户 [{0}] 添加成功</value>
|
||||
</data>
|
||||
|
||||
@@ -959,6 +959,9 @@
|
||||
<data name="ViewControlStatisticsSegmentedItemContentStatistics" xml:space="preserve">
|
||||
<value>統計</value>
|
||||
</data>
|
||||
<data name="ViewControlWebViewerCoreWebView2ProfileQueryInterfaceFailed" xml:space="preserve">
|
||||
<value>当前 WebView2 版本不支持管理配置,继续使用可能会导致异常,请尽快升级</value>
|
||||
</data>
|
||||
<data name="ViewCultivationHeader" xml:space="preserve">
|
||||
<value>養成計劃</value>
|
||||
</data>
|
||||
@@ -1412,6 +1415,9 @@
|
||||
<data name="ViewModelSettingSetDataFolderSuccess" xml:space="preserve">
|
||||
<value>設置數據目錄成功,重啓以應用更改</value>
|
||||
</data>
|
||||
<data name="ViewModelSettingSetGamePathDatabaseFailedTitle" xml:space="preserve">
|
||||
<value>保存游戏路径失败</value>
|
||||
</data>
|
||||
<data name="ViewModelUserAdded" xml:space="preserve">
|
||||
<value>用戶 [{0}] 新增成功</value>
|
||||
</data>
|
||||
|
||||
@@ -105,8 +105,12 @@ internal static class SummaryHelper
|
||||
/// <returns>分数</returns>
|
||||
public static float GetPercentSubAffixScore(in ReliquarySubAffixId appendId)
|
||||
{
|
||||
// 圣遗物相同类型副词条强化档位一共为 4 档
|
||||
// 恰好为 70% 80% 90% 100%
|
||||
// 圣遗物相同类型副词条强化档位一共为 4/3/2 档
|
||||
// 五星 为 70% 80% 90% 100%
|
||||
// 四星 为 70% 80% 90% 100%
|
||||
// 三星 为 70% 80% 90% 100%
|
||||
// 二星 为 70% 85% 100%
|
||||
// 二星 为 80% 100%
|
||||
// 通过计算与最大属性的 Id 差来决定当前副词条的强化档位
|
||||
uint maxId = GetAffixMaxId(appendId);
|
||||
uint delta = maxId - appendId;
|
||||
@@ -119,7 +123,11 @@ internal static class SummaryHelper
|
||||
(5 or 4 or 3, 3) => 70F,
|
||||
|
||||
(2, 0) => 100F,
|
||||
(2, 1) => 80F,
|
||||
(2, 1) => 85F,
|
||||
(2, 2) => 70F,
|
||||
|
||||
(1, 0) => 100F,
|
||||
(1, 1) => 80F,
|
||||
|
||||
_ => throw Must.NeverHappen($"Unexpected AppendId: {appendId.Value} Delta: {delta}"),
|
||||
};
|
||||
|
||||
@@ -35,10 +35,28 @@ internal sealed partial class UIGFImportService : IUIGFImportService
|
||||
// v2.3+ support any locale
|
||||
// v2.2 only support matched locale
|
||||
// v2.1 only support CHS
|
||||
if (version is UIGFVersion.Major2Minor2OrLower && !metadataOptions.IsCurrentLocale(uigf.Info.Language))
|
||||
if (version is UIGFVersion.Major2Minor2OrLower)
|
||||
{
|
||||
string message = SH.ServiceGachaUIGFImportLanguageNotMatch.Format(uigf.Info.Language, metadataOptions.LanguageCode);
|
||||
ThrowHelper.InvalidOperation(message, null);
|
||||
if (!metadataOptions.IsCurrentLocale(uigf.Info.Language))
|
||||
{
|
||||
string message = SH.ServiceGachaUIGFImportLanguageNotMatch.Format(uigf.Info.Language, metadataOptions.LanguageCode);
|
||||
ThrowHelper.InvalidOperation(message);
|
||||
}
|
||||
|
||||
if (!uigf.IsMajor2Minor2OrLowerListValid(out long id))
|
||||
{
|
||||
string message = SH.ServiceGachaLogUIGFImportItemInvalidFormat.Format(id);
|
||||
ThrowHelper.InvalidOperation(message);
|
||||
}
|
||||
}
|
||||
|
||||
if (version is UIGFVersion.Major2Minor3OrHigher)
|
||||
{
|
||||
if (!uigf.IsMajor2Minor3OrHigherListValid(out long id))
|
||||
{
|
||||
string message = SH.ServiceGachaLogUIGFImportItemInvalidFormat.Format(id);
|
||||
ThrowHelper.InvalidOperation(message);
|
||||
}
|
||||
}
|
||||
|
||||
GachaArchiveOperation.GetOrAdd(gachaLogDbService, taskContext, uigf.Info.Uid, archives, out GachaArchive? archive);
|
||||
|
||||
@@ -49,6 +49,13 @@ internal readonly struct ChannelOptions
|
||||
ConfigFilePath = configFilePath;
|
||||
}
|
||||
|
||||
public ChannelOptions(ChannelType channel, SubChannelType subChannel, bool isOversea)
|
||||
{
|
||||
Channel = channel;
|
||||
SubChannel = subChannel;
|
||||
IsOversea = isOversea;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 配置文件未找到
|
||||
/// </summary>
|
||||
@@ -65,4 +72,9 @@ internal readonly struct ChannelOptions
|
||||
{
|
||||
return $"[ChannelType:{Channel}] [SubChannel:{SubChannel}] [IsOversea: {IsOversea}]";
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return HashCode.Combine(Channel, SubChannel, IsOversea);
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ internal sealed class GameFileOperationException : Exception
|
||||
/// </summary>
|
||||
/// <param name="message">消息</param>
|
||||
/// <param name="innerException">内部错误</param>
|
||||
public GameFileOperationException(string message, Exception innerException)
|
||||
public GameFileOperationException(string message, Exception? innerException)
|
||||
: base(SH.ServiceGameFileOperationExceptionMessage.Format(message), innerException)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -281,7 +281,7 @@ internal sealed partial class GameService : IGameService
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async ValueTask DetectGameAccountAsync()
|
||||
public async ValueTask<GameAccount?> DetectGameAccountAsync()
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(gameAccounts);
|
||||
|
||||
@@ -318,7 +318,11 @@ internal sealed partial class GameService : IGameService
|
||||
gameAccounts.Add(account);
|
||||
}
|
||||
}
|
||||
|
||||
return account;
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
||||
@@ -26,11 +26,7 @@ internal interface IGameService
|
||||
/// <param name="uid">uid</param>
|
||||
void AttachGameAccountToUid(GameAccount gameAccount, string uid);
|
||||
|
||||
/// <summary>
|
||||
/// 检测并尝试添加游戏内账户
|
||||
/// </summary>
|
||||
/// <returns>任务</returns>
|
||||
ValueTask DetectGameAccountAsync();
|
||||
ValueTask<GameAccount?> DetectGameAccountAsync();
|
||||
|
||||
/// <summary>
|
||||
/// 异步获取游戏路径
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Model.Intrinsic;
|
||||
using System.Collections.Immutable;
|
||||
|
||||
namespace Snap.Hutao.Service.Game;
|
||||
|
||||
internal static class IgnoredInvalidChannelOptions
|
||||
{
|
||||
private static readonly ImmutableHashSet<ChannelOptions> InvalidOptions = new HashSet<ChannelOptions>()
|
||||
{
|
||||
new(ChannelType.Bili, SubChannelType.Official, true),
|
||||
}.ToImmutableHashSet();
|
||||
|
||||
public static bool Contains(in ChannelOptions options)
|
||||
{
|
||||
return InvalidOptions.Contains(options);
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@ namespace Snap.Hutao.Service.Game.Package;
|
||||
internal sealed class PackageConvertException : Exception
|
||||
{
|
||||
/// <inheritdoc cref="Exception(string?, Exception?)"/>
|
||||
public PackageConvertException(string message, Exception innerException)
|
||||
public PackageConvertException(string message, Exception? innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -26,7 +26,10 @@ internal static class ProcessInterop
|
||||
/// <returns>初始化后的游戏进程</returns>
|
||||
public static Process InitializeGameProcess(LaunchOptions options, string gamePath)
|
||||
{
|
||||
Must.Argument(!(options.IsBorderless && options.IsExclusive), "无边框与独占全屏选项无法同时生效");
|
||||
|
||||
// https://docs.unity.cn/cn/current/Manual/PlayerCommandLineArguments.html
|
||||
// https://docs.unity3d.com/2017.4/Documentation/Manual/CommandLineArguments.html
|
||||
string commandLine = new CommandLineBuilder()
|
||||
.AppendIf("-popupwindow", options.IsBorderless)
|
||||
.AppendIf("-window-mode", options.IsExclusive, "exclusive")
|
||||
|
||||
@@ -235,7 +235,7 @@ internal sealed class GameFpsUnlocker : IGameFpsUnlocker
|
||||
|
||||
using (localMemory)
|
||||
{
|
||||
int offset = IndexOfPattern(localMemory.Span[(int)moduleEntryInfo.UnityPlayer.Size..]);
|
||||
int offset = IndexOfPattern(localMemory.AsSpan()[(int)moduleEntryInfo.UnityPlayer.Size..]);
|
||||
Must.Range(offset >= 0, SH.ServiceGameUnlockerInterestedPatternNotFound);
|
||||
|
||||
byte* pLocalMemory = (byte*)localMemory.Pointer;
|
||||
|
||||
@@ -72,14 +72,23 @@
|
||||
<None Remove="Assets\Wide310x150Logo.scale-200.png" />
|
||||
<None Remove="Assets\Wide310x150Logo.scale-400.png" />
|
||||
<None Remove="CodeMetricsConfig.txt" />
|
||||
<None Remove="Control\Image\CachedImage.xaml" />
|
||||
<None Remove="Control\Loading.xaml" />
|
||||
<None Remove="Control\Panel\PanelSelector.xaml" />
|
||||
<None Remove="Control\Theme\Card.xaml" />
|
||||
<None Remove="Control\Theme\Color.xaml" />
|
||||
<None Remove="Control\Theme\Converter.xaml" />
|
||||
<None Remove="Control\Theme\CornerRadius.xaml" />
|
||||
<None Remove="Control\Theme\FontStyle.xaml" />
|
||||
<None Remove="Control\Theme\Glyph.xaml" />
|
||||
<None Remove="Control\Theme\InfoBarOverride.xaml" />
|
||||
<None Remove="Control\Theme\ItemsPanelTemplate.xaml" />
|
||||
<None Remove="Control\Theme\NumericValue.xaml" />
|
||||
<None Remove="Control\Theme\PageOverride.xaml" />
|
||||
<None Remove="Control\Theme\PivotOverride.xaml" />
|
||||
<None Remove="Control\Theme\SettingsStyle.xaml" />
|
||||
<None Remove="Control\Theme\TransitionCollection.xaml" />
|
||||
<None Remove="Control\Theme\Uri.xaml" />
|
||||
<None Remove="Control\Theme\WindowOverride.xaml" />
|
||||
<None Remove="GuideWindow.xaml" />
|
||||
<None Remove="IdentityStructs.json" />
|
||||
@@ -239,12 +248,12 @@
|
||||
<!-- Packages -->
|
||||
<ItemGroup>
|
||||
<!-- https://pkgs.dev.azure.com/dotnet/CommunityToolkit/_packaging/CommunityToolkit-Labs/nuget/v3/index.json -->
|
||||
<PackageReference Include="CommunityToolkit.Labs.WinUI.Controls.DataTable" Version="0.1.230809" />
|
||||
<PackageReference Include="CommunityToolkit.Labs.WinUI.MarqueeText" Version="0.1.230809" />
|
||||
<PackageReference Include="CommunityToolkit.Labs.WinUI.Shimmer" Version="0.1.230809" />
|
||||
<PackageReference Include="CommunityToolkit.Labs.WinUI.TokenView" Version="0.1.230809" />
|
||||
<PackageReference Include="CommunityToolkit.Labs.WinUI.TransitionHelper" Version="0.1.230809" />
|
||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2-build.1" />
|
||||
<PackageReference Include="CommunityToolkit.Labs.WinUI.Controls.DataTable" Version="0.1.230830" />
|
||||
<PackageReference Include="CommunityToolkit.Labs.WinUI.MarqueeText" Version="0.1.230830" />
|
||||
<PackageReference Include="CommunityToolkit.Labs.WinUI.Shimmer" Version="0.1.230830" />
|
||||
<PackageReference Include="CommunityToolkit.Labs.WinUI.TokenView" Version="0.1.230830" />
|
||||
<PackageReference Include="CommunityToolkit.Labs.WinUI.TransitionHelper" Version="0.1.230830" />
|
||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2-build.2" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Behaviors" Version="8.0.230907" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Collections" Version="8.0.230907" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Controls.HeaderedControls" Version="8.0.230907" />
|
||||
@@ -253,8 +262,8 @@
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Controls.SettingsControls" Version="8.0.230907" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Media" Version="8.0.230907" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Notifications" Version="7.1.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.11" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.11">
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.12" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.12">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
@@ -262,7 +271,7 @@
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Validation" Version="17.6.11" />
|
||||
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.22621.756" />
|
||||
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.4.230913002" />
|
||||
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.4.231008000" />
|
||||
<PackageReference Include="StyleCop.Analyzers.Unstable" Version="1.2.0.507">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
@@ -303,6 +312,60 @@
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Page Update="Control\Theme\NumericValue.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Page Update="Control\Theme\CornerRadius.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Page Update="Control\Theme\Color.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Page Update="Control\Theme\Card.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Page Update="Control\Image\CachedImage.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Page Update="Control\Theme\ItemsPanelTemplate.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Page Update="Control\Theme\Converter.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Page Update="Control\Theme\Glyph.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Page Update="Control\Theme\Uri.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Page Update="Control\Theme\TransitionCollection.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
|
||||
@@ -66,16 +66,16 @@
|
||||
Description="{Binding LastOrangePull}"
|
||||
Header="{shcm:ResourceString Name=ViewControlStatisticsCardOrangeText}"
|
||||
Maximum="{Binding GuaranteeOrangeThreshold}"
|
||||
ProgressForeground="{StaticResource OrangeBrush}"
|
||||
TextForeground="{StaticResource OrangeBrush}"
|
||||
ProgressForeground="{StaticResource OrangeColorBrush}"
|
||||
TextForeground="{StaticResource OrangeColorBrush}"
|
||||
Value="{Binding LastOrangePull}"/>
|
||||
<shvcp:CardProgressBar
|
||||
Grid.Column="0"
|
||||
Description="{Binding LastPurplePull}"
|
||||
Header="{shcm:ResourceString Name=ViewControlStatisticsCardPurpleText}"
|
||||
Maximum="{Binding GuaranteePurpleThreshold}"
|
||||
ProgressForeground="{StaticResource PurpleBrush}"
|
||||
TextForeground="{StaticResource PurpleBrush}"
|
||||
ProgressForeground="{StaticResource PurpleColorBrush}"
|
||||
TextForeground="{StaticResource PurpleColorBrush}"
|
||||
Value="{Binding LastPurplePull}"/>
|
||||
</StackPanel>
|
||||
|
||||
@@ -98,16 +98,16 @@
|
||||
Description="{Binding LastOrangePull}"
|
||||
Header="{shcm:ResourceString Name=ViewControlStatisticsCardOrangeText}"
|
||||
Maximum="{Binding GuaranteeOrangeThreshold}"
|
||||
ProgressForeground="{StaticResource OrangeBrush}"
|
||||
TextForeground="{StaticResource OrangeBrush}"
|
||||
ProgressForeground="{StaticResource OrangeColorBrush}"
|
||||
TextForeground="{StaticResource OrangeColorBrush}"
|
||||
Value="{Binding LastOrangePull}"/>
|
||||
<shvcp:CardProgressBar
|
||||
Grid.Column="0"
|
||||
Description="{Binding LastPurplePull}"
|
||||
Header="{shcm:ResourceString Name=ViewControlStatisticsCardPurpleText}"
|
||||
Maximum="{Binding GuaranteePurpleThreshold}"
|
||||
ProgressForeground="{StaticResource PurpleBrush}"
|
||||
TextForeground="{StaticResource PurpleBrush}"
|
||||
ProgressForeground="{StaticResource PurpleColorBrush}"
|
||||
TextForeground="{StaticResource PurpleColorBrush}"
|
||||
Value="{Binding LastPurplePull}"/>
|
||||
</StackPanel>
|
||||
|
||||
@@ -129,16 +129,16 @@
|
||||
Description="{Binding LastOrangePull}"
|
||||
Header="{shcm:ResourceString Name=ViewControlStatisticsCardOrangeText}"
|
||||
Maximum="{Binding GuaranteeOrangeThreshold}"
|
||||
ProgressForeground="{StaticResource OrangeBrush}"
|
||||
TextForeground="{StaticResource OrangeBrush}"
|
||||
ProgressForeground="{StaticResource OrangeColorBrush}"
|
||||
TextForeground="{StaticResource OrangeColorBrush}"
|
||||
Value="{Binding LastOrangePull}"/>
|
||||
<shvcp:CardProgressBar
|
||||
Grid.Column="0"
|
||||
Description="{Binding LastPurplePull}"
|
||||
Header="{shcm:ResourceString Name=ViewControlStatisticsCardPurpleText}"
|
||||
Maximum="{Binding GuaranteePurpleThreshold}"
|
||||
ProgressForeground="{StaticResource PurpleBrush}"
|
||||
TextForeground="{StaticResource PurpleBrush}"
|
||||
ProgressForeground="{StaticResource PurpleColorBrush}"
|
||||
TextForeground="{StaticResource PurpleColorBrush}"
|
||||
Value="{Binding LastPurplePull}"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:shch="using:Snap.Hutao.Control.Helper"
|
||||
xmlns:shci="using:Snap.Hutao.Control.Image"
|
||||
Style="{StaticResource BorderGridStyle}"
|
||||
Style="{ThemeResource GridCardStyle}"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<StackPanel VerticalAlignment="Center">
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
MinHeight="40"
|
||||
Style="{StaticResource BorderGridStyle}"
|
||||
Style="{ThemeResource GridCardStyle}"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Grid.ColumnDefinitions>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Markup;
|
||||
using Microsoft.Web.WebView2.Core;
|
||||
using Snap.Hutao.Control.Theme;
|
||||
using Snap.Hutao.Web.Bridge;
|
||||
@@ -131,9 +132,10 @@ internal sealed partial class AnnouncementContentViewer : UserControl
|
||||
|
||||
private void OnUnloaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
WebView.CoreWebView2.WebMessageReceived -= webMessageReceivedHandler;
|
||||
Loaded -= loadEventHandler;
|
||||
Unloaded -= unloadEventHandler;
|
||||
if (WebView is { CoreWebView2: CoreWebView2 coreWebView2 })
|
||||
{
|
||||
coreWebView2.WebMessageReceived -= webMessageReceivedHandler;
|
||||
}
|
||||
}
|
||||
|
||||
private async ValueTask LoadAnnouncementAsync()
|
||||
@@ -141,7 +143,7 @@ internal sealed partial class AnnouncementContentViewer : UserControl
|
||||
try
|
||||
{
|
||||
await WebView.EnsureCoreWebView2Async();
|
||||
WebView.CoreWebView2.DisableDevToolsOnReleaseBuild();
|
||||
WebView.CoreWebView2.DisableDevToolsForReleaseBuild();
|
||||
WebView.CoreWebView2.WebMessageReceived += webMessageReceivedHandler;
|
||||
|
||||
await WebView.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync(MihoyoSDKDefinition);
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
</DataTemplate>
|
||||
</UserControl.Resources>
|
||||
|
||||
<Grid Style="{StaticResource BorderGridStyle}">
|
||||
<Grid Style="{ThemeResource GridCardStyle}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="auto"/>
|
||||
<RowDefinition/>
|
||||
@@ -36,7 +36,7 @@
|
||||
Grid.Row="0"
|
||||
cw:UIElementExtensions.ClipToBounds="True"
|
||||
CornerRadius="{StaticResource ControlCornerRadiusTop}"
|
||||
Style="{StaticResource BorderGridStyle}">
|
||||
Style="{ThemeResource GridCardStyle}">
|
||||
<cwc:ConstrainedBox
|
||||
Margin="-1"
|
||||
HorizontalAlignment="Center"
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
<shvconv:Int32ToGradientColorConverter x:Key="Int32ToGradientColorConverter" MaximumValue="{Binding GuaranteeOrangeThreshold}"/>
|
||||
|
||||
<DataTemplate x:Key="OrangeListTemplate" d:DataType="shvg:SummaryItem">
|
||||
<Grid Margin="0" Style="{StaticResource BorderGridStyle}">
|
||||
<Grid Margin="0" Style="{ThemeResource GridCardStyle}">
|
||||
<ToolTipService.ToolTip>
|
||||
<TextBlock Text="{Binding TimeFormatted}"/>
|
||||
</ToolTipService.ToolTip>
|
||||
@@ -59,13 +59,13 @@
|
||||
<TextBlock
|
||||
Margin="0,0,8,0"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{StaticResource GuaranteePullBrush}"
|
||||
Foreground="{StaticResource GuaranteePullCoolorBrush}"
|
||||
Text="{shcm:ResourceString Name=ViewControlStatisticsCardGuaranteeText}"
|
||||
Visibility="{Binding IsGuarantee, Converter={StaticResource BoolToVisibilityConverter}}"/>
|
||||
<TextBlock
|
||||
Margin="0,0,8,0"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{StaticResource UpPullBrush}"
|
||||
Foreground="{StaticResource UpPullColorBrush}"
|
||||
Text="{shcm:ResourceString Name=ViewControlStatisticsCardUpText}"
|
||||
Visibility="{Binding IsUp, Converter={StaticResource BoolToVisibilityConverter}}"/>
|
||||
|
||||
@@ -103,7 +103,7 @@
|
||||
</DataTemplate>
|
||||
</UserControl.Resources>
|
||||
|
||||
<Grid Style="{StaticResource BorderGridStyle}">
|
||||
<Grid Style="{ThemeResource GridCardStyle}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="auto"/>
|
||||
<RowDefinition Height="auto"/>
|
||||
@@ -181,8 +181,8 @@
|
||||
Description="{Binding LastOrangePull}"
|
||||
Header="{shcm:ResourceString Name=ViewControlStatisticsCardToLastOrangeText}"
|
||||
Maximum="{Binding GuaranteeOrangeThreshold}"
|
||||
ProgressForeground="{StaticResource OrangeBrush}"
|
||||
TextForeground="{StaticResource OrangeBrush}"
|
||||
ProgressForeground="{StaticResource OrangeColorBrush}"
|
||||
TextForeground="{StaticResource OrangeColorBrush}"
|
||||
Value="{Binding LastOrangePull}"/>
|
||||
<shvcp:CardProgressBar
|
||||
Grid.Column="1"
|
||||
@@ -190,8 +190,8 @@
|
||||
Description="{Binding LastPurplePull}"
|
||||
Header="{shcm:ResourceString Name=ViewControlStatisticsCardToLastPurpleText}"
|
||||
Maximum="{Binding GuaranteePurpleThreshold}"
|
||||
ProgressForeground="{StaticResource PurpleBrush}"
|
||||
TextForeground="{StaticResource PurpleBrush}"
|
||||
ProgressForeground="{StaticResource PurpleColorBrush}"
|
||||
TextForeground="{StaticResource PurpleColorBrush}"
|
||||
Value="{Binding LastPurplePull}"/>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
@@ -243,37 +243,37 @@
|
||||
<StackPanel Spacing="2">
|
||||
<Grid>
|
||||
<TextBlock
|
||||
Foreground="{StaticResource OrangeBrush}"
|
||||
Foreground="{StaticResource OrangeColorBrush}"
|
||||
Style="{StaticResource BodyTextBlockStyle}"
|
||||
Text="{shcm:ResourceString Name=ViewControlStatisticsCardOrangeText}"/>
|
||||
<TextBlock
|
||||
HorizontalAlignment="Right"
|
||||
FontFamily="{StaticResource CascadiaMonoAndMiSans}"
|
||||
Foreground="{StaticResource OrangeBrush}"
|
||||
Foreground="{StaticResource OrangeColorBrush}"
|
||||
Style="{StaticResource BodyTextBlockStyle}"
|
||||
Text="{Binding TotalOrangeFormatted}"/>
|
||||
</Grid>
|
||||
<Grid>
|
||||
<TextBlock
|
||||
Foreground="{StaticResource PurpleBrush}"
|
||||
Foreground="{StaticResource PurpleColorBrush}"
|
||||
Style="{StaticResource BodyTextBlockStyle}"
|
||||
Text="{shcm:ResourceString Name=ViewControlStatisticsCardPurpleText}"/>
|
||||
<TextBlock
|
||||
HorizontalAlignment="Right"
|
||||
FontFamily="{StaticResource CascadiaMonoAndMiSans}"
|
||||
Foreground="{StaticResource PurpleBrush}"
|
||||
Foreground="{StaticResource PurpleColorBrush}"
|
||||
Style="{StaticResource BodyTextBlockStyle}"
|
||||
Text="{Binding TotalPurpleFormatted}"/>
|
||||
</Grid>
|
||||
<Grid>
|
||||
<TextBlock
|
||||
Foreground="{StaticResource BlueBrush}"
|
||||
Foreground="{StaticResource BlueColorBrush}"
|
||||
Style="{StaticResource BodyTextBlockStyle}"
|
||||
Text="{shcm:ResourceString Name=ViewControlStatisticsCardBlueText}"/>
|
||||
<TextBlock
|
||||
HorizontalAlignment="Right"
|
||||
FontFamily="{StaticResource CascadiaMonoAndMiSans}"
|
||||
Foreground="{StaticResource BlueBrush}"
|
||||
Foreground="{StaticResource BlueColorBrush}"
|
||||
Style="{StaticResource BodyTextBlockStyle}"
|
||||
Text="{Binding TotalBlueFormatted}"/>
|
||||
</Grid>
|
||||
|
||||
@@ -10,6 +10,8 @@ using Snap.Hutao.Service.Notification;
|
||||
using Snap.Hutao.Service.User;
|
||||
using Snap.Hutao.ViewModel.User;
|
||||
using Snap.Hutao.Web.Bridge;
|
||||
using WinRT;
|
||||
using WinRT.Interop;
|
||||
|
||||
namespace Snap.Hutao.View.Control;
|
||||
|
||||
@@ -17,23 +19,22 @@ namespace Snap.Hutao.View.Control;
|
||||
internal partial class WebViewer : UserControl, IRecipient<UserChangedMessage>
|
||||
{
|
||||
private readonly IServiceProvider serviceProvider;
|
||||
private readonly IInfoBarService infoBarService;
|
||||
private readonly RoutedEventHandler loadEventHandler;
|
||||
private readonly RoutedEventHandler unloadEventHandler;
|
||||
|
||||
[SuppressMessage("", "IDE0052")]
|
||||
private MiHoYoJSInterface? jsInterface;
|
||||
private bool isInitializingOrInitialized;
|
||||
|
||||
public WebViewer()
|
||||
{
|
||||
InitializeComponent();
|
||||
serviceProvider = Ioc.Default;
|
||||
infoBarService = serviceProvider.GetRequiredService<IInfoBarService>();
|
||||
serviceProvider.GetRequiredService<IMessenger>().Register(this);
|
||||
|
||||
loadEventHandler = OnLoaded;
|
||||
unloadEventHandler = OnUnloaded;
|
||||
|
||||
Loaded += loadEventHandler;
|
||||
Unloaded += unloadEventHandler;
|
||||
}
|
||||
|
||||
public void Receive(UserChangedMessage message)
|
||||
@@ -47,17 +48,17 @@ internal partial class WebViewer : UserControl, IRecipient<UserChangedMessage>
|
||||
InitializeAsync().SafeForget();
|
||||
}
|
||||
|
||||
private void OnUnloaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
jsInterface = null;
|
||||
Loaded -= loadEventHandler;
|
||||
Unloaded -= unloadEventHandler;
|
||||
}
|
||||
|
||||
private async ValueTask InitializeAsync()
|
||||
{
|
||||
if (isInitializingOrInitialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
isInitializingOrInitialized = true;
|
||||
|
||||
await WebView.EnsureCoreWebView2Async();
|
||||
WebView.CoreWebView2.DisableDevToolsOnReleaseBuild();
|
||||
WebView.CoreWebView2.DisableDevToolsForReleaseBuild();
|
||||
RefreshWebview2Content();
|
||||
}
|
||||
|
||||
@@ -86,19 +87,31 @@ internal partial class WebViewer : UserControl, IRecipient<UserChangedMessage>
|
||||
string source = SourceProvider.GetSource(userAndUid);
|
||||
if (!string.IsNullOrEmpty(source))
|
||||
{
|
||||
await coreWebView2.DeleteCookiesAsync(".mihoyo.com").ConfigureAwait(true);
|
||||
coreWebView2.SetCookie(user.CookieToken, user.LToken, user.SToken);
|
||||
_ = userAndUid.User.IsOversea ? coreWebView2.SetMobileOverseaUserAgent() : coreWebView2.SetMobileUserAgent();
|
||||
jsInterface = SourceProvider.CreateJsInterface(serviceProvider, coreWebView2, userAndUid);
|
||||
try
|
||||
{
|
||||
await coreWebView2.Profile.ClearBrowsingDataAsync();
|
||||
}
|
||||
catch (InvalidCastException)
|
||||
{
|
||||
infoBarService.Warning(SH.ViewControlWebViewerCoreWebView2ProfileQueryInterfaceFailed);
|
||||
await coreWebView2.DeleteCookiesAsync(userAndUid.IsOversea).ConfigureAwait(true);
|
||||
}
|
||||
|
||||
CoreWebView2Navigator navigator = new(coreWebView2);
|
||||
await navigator.NavigateAsync("about:blank").ConfigureAwait(true);
|
||||
|
||||
coreWebView2
|
||||
.SetCookie(user.CookieToken, user.LToken, userAndUid.IsOversea)
|
||||
.SetMobileUserAgent(userAndUid.IsOversea);
|
||||
jsInterface?.Detach();
|
||||
jsInterface = SourceProvider.CreateJsInterface(serviceProvider, coreWebView2, userAndUid);
|
||||
|
||||
await navigator.NavigateAsync(source).ConfigureAwait(true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
serviceProvider.GetRequiredService<IInfoBarService>().Warning(SH.MustSelectUserAndUid);
|
||||
infoBarService.Warning(SH.MustSelectUserAndUid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@
|
||||
<Grid
|
||||
Margin="8"
|
||||
DataContext="{x:Bind Avatar}"
|
||||
Style="{StaticResource BorderGridStyle}">
|
||||
Style="{ThemeResource GridCardStyle}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
<ColumnDefinition Width="160"/>
|
||||
@@ -129,7 +129,7 @@
|
||||
<Grid
|
||||
Margin="8"
|
||||
DataContext="{x:Bind Weapon}"
|
||||
Style="{StaticResource BorderGridStyle}">
|
||||
Style="{ThemeResource GridCardStyle}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
<ColumnDefinition Width="160"/>
|
||||
|
||||
@@ -314,7 +314,7 @@
|
||||
HorizontalAlignment="Left">
|
||||
<!-- 卡片面板 -->
|
||||
<Border Margin="16" cw:Effects.Shadow="{ThemeResource CompatCardShadow}">
|
||||
<Grid cw:UIElementExtensions.ClipToBounds="True" Style="{StaticResource BorderGridStyle}">
|
||||
<Grid cw:UIElementExtensions.ClipToBounds="True" Style="{ThemeResource GridCardStyle}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition/>
|
||||
<RowDefinition Height="auto"/>
|
||||
@@ -636,7 +636,7 @@
|
||||
Grid.Column="3"
|
||||
Margin="8,0,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
Foreground="{StaticResource AvatarPropertyAddValueBrush}"
|
||||
Foreground="{StaticResource AvatarPropertyAddValueColorBrush}"
|
||||
Text="{Binding AddValue}"/>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
|
||||
@@ -193,7 +193,7 @@
|
||||
<SolidColorBrush x:Key="ItemContainerPointerOverBackground" Color="Transparent"/>
|
||||
<SolidColorBrush x:Key="ItemContainerPressedBackground" Color="Transparent"/>
|
||||
</ItemContainer.Resources>
|
||||
<Grid Padding="8" Style="{StaticResource BorderGridStyle}">
|
||||
<Grid Padding="8" Style="{ThemeResource GridCardStyle}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="auto"/>
|
||||
<RowDefinition Height="auto"/>
|
||||
@@ -284,7 +284,7 @@
|
||||
Grid.Row="1"
|
||||
Margin="0,8,0,0"
|
||||
Spacing="6">
|
||||
<Grid Style="{ThemeResource BorderGridStyle}">
|
||||
<Grid Style="{ThemeResource GridCardStyle}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
<ColumnDefinition/>
|
||||
@@ -321,7 +321,7 @@
|
||||
TextWrapping="NoWrap"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<Grid Style="{ThemeResource BorderGridStyle}">
|
||||
<Grid Style="{ThemeResource GridCardStyle}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
<ColumnDefinition/>
|
||||
@@ -358,7 +358,7 @@
|
||||
TextWrapping="NoWrap"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<Grid Style="{ThemeResource BorderGridStyle}">
|
||||
<Grid Style="{ThemeResource GridCardStyle}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
<ColumnDefinition/>
|
||||
@@ -395,7 +395,7 @@
|
||||
TextWrapping="NoWrap"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<Grid Style="{ThemeResource BorderGridStyle}">
|
||||
<Grid Style="{ThemeResource GridCardStyle}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
<ColumnDefinition/>
|
||||
@@ -432,7 +432,7 @@
|
||||
TextWrapping="NoWrap"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<Grid Style="{ThemeResource BorderGridStyle}">
|
||||
<Grid Style="{ThemeResource GridCardStyle}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
<ColumnDefinition/>
|
||||
@@ -487,7 +487,7 @@
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Grid Style="{ThemeResource BorderGridStyle}">
|
||||
<Grid Style="{ThemeResource GridCardStyle}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
<ColumnDefinition/>
|
||||
|
||||
@@ -17,11 +17,11 @@ internal interface ISupportLoginByWebView
|
||||
try
|
||||
{
|
||||
await webView2.EnsureCoreWebView2Async();
|
||||
await webView2.CoreWebView2.DeleteCookiesAsync("https://user.mihoyo.com").ConfigureAwait(true);
|
||||
webView2.CoreWebView2.DisableDevToolsOnReleaseBuild();
|
||||
await webView2.CoreWebView2.DeleteCookiesAsync(cookie).ConfigureAwait(true);
|
||||
webView2.CoreWebView2.DisableDevToolsForReleaseBuild();
|
||||
webView2.CoreWebView2.DisableAutoCompletion();
|
||||
|
||||
webView2.CoreWebView2.Navigate("https://user.mihoyo.com/#/login/password");
|
||||
webView2.CoreWebView2.Navigate(navigate);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -33,7 +33,7 @@ internal interface ISupportLoginByWebView
|
||||
{
|
||||
(UserOptionResult result, string nickname) = await serviceProvider
|
||||
.GetRequiredService<IUserService>()
|
||||
.ProcessInputCookieAsync(cookie, false)
|
||||
.ProcessInputCookieAsync(cookie, isOversea)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
serviceProvider.GetRequiredService<INavigationService>().GoBack();
|
||||
|
||||
@@ -148,4 +148,4 @@ internal sealed partial class LoginHoyoverseUserPage : Microsoft.UI.Xaml.Control
|
||||
[JsonPropertyName("weblogin_token")]
|
||||
public string WebLoginToken { get; set; } = default!;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -44,7 +44,7 @@ internal sealed partial class LoginMihoyoUserPage : Microsoft.UI.Xaml.Controls.P
|
||||
IReadOnlyList<CoreWebView2Cookie> cookies = await WebView.CoreWebView2.CookieManager.GetCookiesAsync("https://user.mihoyo.com");
|
||||
Cookie webCookie = Cookie.FromCoreWebView2Cookies(cookies);
|
||||
|
||||
if (!webCookie.TryGetCookieToken(out Cookie? loginTicketCookie))
|
||||
if (!webCookie.TryGetLoginTicket(out Cookie? loginTicketCookie))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -21,11 +21,14 @@
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Margin="16,16,16,16" Spacing="{StaticResource SettingsCardSpacing}">
|
||||
<Border cw:Effects.Shadow="{ThemeResource CompatCardShadow}">
|
||||
<Grid Height="280" Style="{ThemeResource BorderGridStyle}">
|
||||
<Image
|
||||
VerticalAlignment="Center"
|
||||
Source="ms-appx:///Resource/BlurBackground.png"
|
||||
Stretch="Fill"/>
|
||||
<Grid Height="280" Style="{ThemeResource GridCardStyle}">
|
||||
<Border CornerRadius="{ThemeResource ControlCornerRadius}">
|
||||
<Image
|
||||
VerticalAlignment="Center"
|
||||
Source="ms-appx:///Resource/BlurBackground.png"
|
||||
Stretch="Fill"/>
|
||||
</Border>
|
||||
|
||||
<Grid Background="{ThemeResource SystemControlBackgroundAltMediumBrush}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition/>
|
||||
@@ -74,29 +77,31 @@
|
||||
Margin="0,4"
|
||||
Text="Copyright © 2022 - 2023 DGP Studio. All Rights Reserved."
|
||||
TextWrapping="Wrap"/>
|
||||
|
||||
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" Text="{shcm:ResourceString Name=ViewPageSettingAboutHeader}"/>
|
||||
<cwc:SettingsCard
|
||||
<cwc:SettingsExpander
|
||||
Description="{Binding HutaoOptions.Version}"
|
||||
Header="{shcm:ResourceString Name=AppName}"
|
||||
HeaderIcon="{shcm:FontIcon Glyph=}"/>
|
||||
HeaderIcon="{shcm:FontIcon Glyph=}"
|
||||
IsExpanded="True">
|
||||
<cwc:SettingsExpander.Items>
|
||||
<cwc:SettingsCard
|
||||
ActionIcon="{shcm:FontIcon Glyph=}"
|
||||
ActionIconToolTip="{shcm:ResourceString Name=ViewPageSettingCopyDeviceIdAction}"
|
||||
Command="{Binding CopyDeviceIdCommand}"
|
||||
Description="{Binding HutaoOptions.DeviceId}"
|
||||
Header="{shcm:ResourceString Name=ViewPageSettingDeviceIdHeader}"
|
||||
IsClickEnabled="True"/>
|
||||
<cwc:SettingsCard Description="{Binding HutaoOptions.WebView2Version}" Header="{shcm:ResourceString Name=ViewPageSettingWebview2Header}"/>
|
||||
</cwc:SettingsExpander.Items>
|
||||
</cwc:SettingsExpander>
|
||||
<cwc:SettingsCard
|
||||
Command="{Binding NavigateToHutaoPassportCommand}"
|
||||
Description="{Binding UserOptions.UserName}"
|
||||
Header="{shcm:ResourceString Name=ViewPageSettingHutaoPassportHeader}"
|
||||
HeaderIcon="{shcm:FontIcon Glyph=}"
|
||||
IsClickEnabled="True"/>
|
||||
<cwc:SettingsCard
|
||||
ActionIcon="{shcm:FontIcon Glyph=}"
|
||||
ActionIconToolTip="{shcm:ResourceString Name=ViewPageSettingCopyDeviceIdAction}"
|
||||
Command="{Binding CopyDeviceIdCommand}"
|
||||
Description="{Binding HutaoOptions.DeviceId}"
|
||||
Header="{shcm:ResourceString Name=ViewPageSettingDeviceIdHeader}"
|
||||
HeaderIcon="{shcm:FontIcon Glyph=}"
|
||||
IsClickEnabled="True"/>
|
||||
<cwc:SettingsCard
|
||||
Description="{Binding HutaoOptions.WebView2Version}"
|
||||
Header="{shcm:ResourceString Name=ViewPageSettingWebview2Header}"
|
||||
HeaderIcon="{shcm:FontIcon Glyph=}"/>
|
||||
|
||||
|
||||
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" Text="{shcm:ResourceString Name=ViewPageSettingGeetestVerificationHeader}"/>
|
||||
<cwc:SettingsCard
|
||||
@@ -141,7 +146,8 @@
|
||||
<cwc:SettingsExpander
|
||||
Description="{shcm:ResourceString Name=ViewpageSettingHomeCardDescription}"
|
||||
Header="{shcm:ResourceString Name=ViewpageSettingHomeCardHeader}"
|
||||
HeaderIcon="{shcm:FontIcon Glyph=}">
|
||||
HeaderIcon="{shcm:FontIcon Glyph=}"
|
||||
IsExpanded="True">
|
||||
<cwc:SettingsExpander.Items>
|
||||
<cwc:SettingsCard Header="{shcm:ResourceString Name=ViewpageSettingHomeCardItemLaunchGameHeader}">
|
||||
<ToggleSwitch
|
||||
@@ -238,7 +244,7 @@
|
||||
IsClickEnabled="True"/>
|
||||
|
||||
<cwc:SettingsCard
|
||||
Margin="0,4,0,0"
|
||||
Margin="0,3,0,0"
|
||||
ActionIcon="{shcm:FontIcon Glyph=}"
|
||||
ActionIconToolTip="{shcm:ResourceString Name=ViewPageSettingStorageOpenAction}"
|
||||
Command="{Binding OpenCacheFolderCommand}"
|
||||
@@ -276,7 +282,7 @@
|
||||
</StackPanel>
|
||||
</cwc:SettingsCard>
|
||||
<InfoBar
|
||||
Margin="0,4,0,0"
|
||||
Margin="0,3,0,0"
|
||||
IsClosable="False"
|
||||
IsOpen="True"
|
||||
Message="{shcm:ResourceString Name=ViewPageSettingDangerousHint}"
|
||||
|
||||
@@ -504,7 +504,7 @@
|
||||
|
||||
<Grid.Resources>
|
||||
<DataTemplate x:Key="TeamItemTemplate" d:DataType="shvcom:Team">
|
||||
<Border Margin="0,0,0,8" Style="{StaticResource BorderCardStyle}">
|
||||
<Border Margin="0,0,16,8" Style="{StaticResource BorderCardStyle}">
|
||||
<Viewbox Stretch="Uniform">
|
||||
<Grid Margin="6">
|
||||
<Grid.ColumnDefinitions>
|
||||
@@ -530,11 +530,13 @@
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
<TextBlock
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding Rate}"/>
|
||||
<Viewbox Grid.Column="1" Stretch="Uniform">
|
||||
<TextBlock
|
||||
Margin="16,8"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding Rate}"/>
|
||||
</Viewbox>
|
||||
</Grid>
|
||||
</Viewbox>
|
||||
</Border>
|
||||
@@ -675,6 +677,7 @@
|
||||
|
||||
<Grid
|
||||
Grid.Row="1"
|
||||
Margin="16,0,0,0"
|
||||
ColumnSpacing="8"
|
||||
DataContext="{Binding SelectedTeamAppearance}">
|
||||
<Grid.ColumnDefinitions>
|
||||
@@ -684,12 +687,14 @@
|
||||
<ListView
|
||||
Grid.Column="0"
|
||||
Padding="0,8,0,0"
|
||||
ItemContainerStyle="{ThemeResource NoneSelectionListViewItemStyle}"
|
||||
ItemTemplate="{StaticResource TeamItemTemplate}"
|
||||
ItemsSource="{Binding Up}"
|
||||
SelectionMode="None"/>
|
||||
<ListView
|
||||
Grid.Column="1"
|
||||
Padding="0,8,0,0"
|
||||
ItemContainerStyle="{ThemeResource NoneSelectionListViewItemStyle}"
|
||||
ItemTemplate="{StaticResource TeamItemTemplate}"
|
||||
ItemsSource="{Binding Down}"
|
||||
SelectionMode="None"/>
|
||||
|
||||
@@ -95,6 +95,12 @@
|
||||
Header="Compensation GachaLog Service Time For 15 Days"
|
||||
IsClickEnabled="True"/>
|
||||
|
||||
<cwc:SettingsCard Header="Crash">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Command="{Binding ExceptionCommand}" Content="Activate"/>
|
||||
</StackPanel>
|
||||
</cwc:SettingsCard>
|
||||
|
||||
<Expander
|
||||
HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
@@ -120,6 +126,7 @@
|
||||
<Button Command="{Binding UploadAnnouncementCommand}" Content="Upload"/>
|
||||
</StackPanel>
|
||||
</Expander>
|
||||
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</shc:ScopedPage>
|
||||
|
||||
@@ -424,7 +424,7 @@
|
||||
Text="{shcm:ResourceString Name=ViewPageWiKiAvatarMiscHeader}"/>
|
||||
<Border Margin="16,16,0,0" cw:Effects.Shadow="{ThemeResource CompatCardShadow}">
|
||||
<cwc:ConstrainedBox AspectRatio="2048:1024">
|
||||
<Grid Style="{StaticResource BorderGridStyle}">
|
||||
<Grid Style="{ThemeResource GridCardStyle}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
<ColumnDefinition/>
|
||||
|
||||
@@ -134,7 +134,7 @@
|
||||
<mxi:Interaction.Behaviors>
|
||||
<shcb:AutoHeightBehavior TargetHeight="1024" TargetWidth="2048"/>
|
||||
</mxi:Interaction.Behaviors>
|
||||
<Border Grid.ColumnSpan="2" Background="{ThemeResource DarkOnlyOverlayMaskBrush}"/>
|
||||
<Border Grid.ColumnSpan="2" Background="{ThemeResource DarkOnlyOverlayMaskColorBrush}"/>
|
||||
<ScrollViewer
|
||||
Grid.Column="0"
|
||||
Margin="16"
|
||||
|
||||
@@ -14,6 +14,7 @@ using Snap.Hutao.Service.GachaLog.QueryProvider;
|
||||
using Snap.Hutao.Service.Notification;
|
||||
using Snap.Hutao.View.Dialog;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Runtime.InteropServices;
|
||||
using Windows.Storage.Pickers;
|
||||
|
||||
namespace Snap.Hutao.ViewModel.GachaLog;
|
||||
@@ -115,21 +116,6 @@ internal sealed partial class GachaLogViewModel : Abstraction.ViewModel
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool CanImport(UIGFVersion version, UIGF uigf, out long id)
|
||||
{
|
||||
id = 0;
|
||||
if (version == UIGFVersion.Major2Minor3OrHigher)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (version == UIGFVersion.Major2Minor2OrLower && uigf.IsMajor2Minor2OrLowerListValid(out id))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
[Command("RefreshByWebCacheCommand")]
|
||||
private Task RefreshByWebCacheAsync()
|
||||
{
|
||||
@@ -159,7 +145,23 @@ internal sealed partial class GachaLogViewModel : Abstraction.ViewModel
|
||||
RefreshStrategy strategy = IsAggressiveRefresh ? RefreshStrategy.AggressiveMerge : RefreshStrategy.LazyMerge;
|
||||
|
||||
GachaLogRefreshProgressDialog dialog = await contentDialogFactory.CreateInstanceAsync<GachaLogRefreshProgressDialog>().ConfigureAwait(false);
|
||||
ContentDialogHideToken hideToken = await dialog.BlockAsync(taskContext).ConfigureAwait(false);
|
||||
|
||||
ContentDialogHideToken hideToken;
|
||||
try
|
||||
{
|
||||
hideToken = await dialog.BlockAsync(taskContext).ConfigureAwait(false);
|
||||
}
|
||||
catch (COMException ex)
|
||||
{
|
||||
if (ex.HResult == unchecked((int)0x80000019))
|
||||
{
|
||||
infoBarService.Error(ex);
|
||||
return;
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
|
||||
IProgress<GachaLogFetchStatus> progress = taskContext.CreateProgressForMainThread<GachaLogFetchStatus>(dialog.OnReport);
|
||||
bool authkeyValid;
|
||||
|
||||
@@ -221,7 +223,7 @@ internal sealed partial class GachaLogViewModel : Abstraction.ViewModel
|
||||
}
|
||||
else
|
||||
{
|
||||
await contentDialogFactory.CreateForConfirmAsync(SH.ViewModelImportWarningTitle, SH.ViewModelImportWarningMessage).ConfigureAwait(false);
|
||||
infoBarService.Error(SH.ViewModelImportWarningTitle, SH.ViewModelImportWarningMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -349,50 +351,42 @@ internal sealed partial class GachaLogViewModel : Abstraction.ViewModel
|
||||
|
||||
private async ValueTask<bool> TryImportUIGFInternalAsync(UIGF uigf)
|
||||
{
|
||||
if (uigf.IsCurrentVersionSupported(out UIGFVersion version))
|
||||
{
|
||||
GachaLogImportDialog importDialog = await contentDialogFactory.CreateInstanceAsync<GachaLogImportDialog>(uigf).ConfigureAwait(false);
|
||||
if (await importDialog.GetShouldImportAsync().ConfigureAwait(false))
|
||||
{
|
||||
if (CanImport(version, uigf, out long itemId))
|
||||
{
|
||||
await taskContext.SwitchToMainThreadAsync();
|
||||
ContentDialog dialog = await contentDialogFactory.CreateForIndeterminateProgressAsync(SH.ViewModelGachaLogImportProgress).ConfigureAwait(true);
|
||||
try
|
||||
{
|
||||
using (await dialog.BlockAsync(taskContext).ConfigureAwait(false))
|
||||
{
|
||||
await gachaLogService.ImportFromUIGFAsync(uigf).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
catch (InvalidOperationException ex)
|
||||
{
|
||||
// 导入物品中存在无效的项
|
||||
infoBarService.Error(ex);
|
||||
return false;
|
||||
}
|
||||
catch (FormatException ex)
|
||||
{
|
||||
infoBarService.Error(ex);
|
||||
return false;
|
||||
}
|
||||
|
||||
infoBarService.Success(SH.ViewModelGachaLogImportComplete);
|
||||
await taskContext.SwitchToMainThreadAsync();
|
||||
await SetSelectedArchiveAndUpdateStatisticsAsync(gachaLogService.CurrentArchive, true).ConfigureAwait(false);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
infoBarService.Warning(SH.ViewModelGachaLogImportWarningTitle, SH.ServiceGachaLogUIGFImportItemInvalidFormat.Format(itemId));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
if (!uigf.IsCurrentVersionSupported(out UIGFVersion version))
|
||||
{
|
||||
infoBarService.Warning(SH.ViewModelGachaLogImportWarningTitle, SH.ViewModelGachaLogImportWarningMessage);
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
GachaLogImportDialog importDialog = await contentDialogFactory.CreateInstanceAsync<GachaLogImportDialog>(uigf).ConfigureAwait(false);
|
||||
if (!await importDialog.GetShouldImportAsync().ConfigureAwait(false))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
await taskContext.SwitchToMainThreadAsync();
|
||||
ContentDialog dialog = await contentDialogFactory.CreateForIndeterminateProgressAsync(SH.ViewModelGachaLogImportProgress).ConfigureAwait(true);
|
||||
try
|
||||
{
|
||||
using (await dialog.BlockAsync(taskContext).ConfigureAwait(false))
|
||||
{
|
||||
await gachaLogService.ImportFromUIGFAsync(uigf).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
catch (InvalidOperationException ex)
|
||||
{
|
||||
// 语言不匹配/导入物品中存在无效的项
|
||||
infoBarService.Error(ex);
|
||||
return false;
|
||||
}
|
||||
catch (FormatException ex)
|
||||
{
|
||||
infoBarService.Error(ex);
|
||||
return false;
|
||||
}
|
||||
|
||||
infoBarService.Success(SH.ViewModelGachaLogImportComplete);
|
||||
await taskContext.SwitchToMainThreadAsync();
|
||||
await SetSelectedArchiveAndUpdateStatisticsAsync(gachaLogService.CurrentArchive, true).ConfigureAwait(false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -34,12 +34,12 @@ internal sealed partial class LaunchGameViewModel : Abstraction.ViewModel
|
||||
public const string DesiredUid = nameof(DesiredUid);
|
||||
|
||||
private readonly IContentDialogFactory contentDialogFactory;
|
||||
private readonly LaunchStatusOptions launchStatusOptions;
|
||||
private readonly INavigationService navigationService;
|
||||
private readonly IInfoBarService infoBarService;
|
||||
private readonly LaunchOptions launchOptions;
|
||||
private readonly LaunchStatusOptions launchStatusOptions;
|
||||
private readonly RuntimeOptions hutaoOptions;
|
||||
private readonly ResourceClient resourceClient;
|
||||
private readonly LaunchOptions launchOptions;
|
||||
private readonly RuntimeOptions hutaoOptions;
|
||||
private readonly IUserService userService;
|
||||
private readonly ITaskContext taskContext;
|
||||
private readonly IGameService gameService;
|
||||
@@ -125,8 +125,11 @@ internal sealed partial class LaunchGameViewModel : Abstraction.ViewModel
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
// 后台收集
|
||||
throw new NotSupportedException($"不支持的 MultiChannel: {options}");
|
||||
if (!IgnoredInvalidChannelOptions.Contains(options))
|
||||
{
|
||||
// 后台收集
|
||||
throw new NotSupportedException($"不支持的 MultiChannel: {options}");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -233,7 +236,15 @@ internal sealed partial class LaunchGameViewModel : Abstraction.ViewModel
|
||||
{
|
||||
try
|
||||
{
|
||||
await gameService.DetectGameAccountAsync().ConfigureAwait(false);
|
||||
GameAccount? account = await gameService.DetectGameAccountAsync().ConfigureAwait(false);
|
||||
|
||||
// If user canceled the operation, the return is null,
|
||||
// and thus we should not set SelectedAccount
|
||||
if (account is not null)
|
||||
{
|
||||
await taskContext.SwitchToMainThreadAsync();
|
||||
SelectedGameAccount = account;
|
||||
}
|
||||
}
|
||||
catch (UserdataCorruptedException ex)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.Data.Sqlite;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.Windows.AppLifecycle;
|
||||
@@ -126,7 +127,15 @@ internal sealed partial class SettingViewModel : Abstraction.ViewModel
|
||||
if (isOk)
|
||||
{
|
||||
await taskContext.SwitchToMainThreadAsync();
|
||||
Options.GamePath = path;
|
||||
try
|
||||
{
|
||||
Options.GamePath = path;
|
||||
}
|
||||
catch (SqliteException ex)
|
||||
{
|
||||
// 文件夹权限不足,无法写入数据库
|
||||
infoBarService.Error(ex, SH.ViewModelSettingSetGamePathDatabaseFailedTitle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,11 +18,6 @@ internal sealed class SpiralAbyssView : IEntityOnly<SpiralAbyssEntry?>,
|
||||
{
|
||||
private readonly SpiralAbyssEntry? entity;
|
||||
|
||||
/// <summary>
|
||||
/// 构造一个新的深渊视图
|
||||
/// </summary>
|
||||
/// <param name="entity">实体</param>
|
||||
/// <param name="idAvatarMap">Id角色映射</param>
|
||||
private SpiralAbyssView(SpiralAbyssEntry entity, SpiralAbyssMetadataContext context)
|
||||
: this(context.IdScheduleMap[entity.ScheduleId], context)
|
||||
{
|
||||
@@ -32,12 +27,12 @@ internal sealed class SpiralAbyssView : IEntityOnly<SpiralAbyssEntry?>,
|
||||
TotalBattleTimes = spiralAbyss.TotalBattleTimes;
|
||||
TotalStar = spiralAbyss.TotalStar;
|
||||
MaxFloor = spiralAbyss.MaxFloor;
|
||||
Reveals = spiralAbyss.RevealRank.SelectList(r => new RankAvatar(r.Value, context.IdAvatarMap[r.AvatarId]));
|
||||
Defeat = spiralAbyss.DefeatRank.Select(r => new RankAvatar(r.Value, context.IdAvatarMap[r.AvatarId])).SingleOrDefault();
|
||||
Damage = spiralAbyss.DamageRank.Select(r => new RankAvatar(r.Value, context.IdAvatarMap[r.AvatarId])).SingleOrDefault();
|
||||
TakeDamage = spiralAbyss.TakeDamageRank.Select(r => new RankAvatar(r.Value, context.IdAvatarMap[r.AvatarId])).SingleOrDefault();
|
||||
NormalSkill = spiralAbyss.NormalSkillRank.Select(r => new RankAvatar(r.Value, context.IdAvatarMap[r.AvatarId])).SingleOrDefault();
|
||||
EnergySkill = spiralAbyss.EnergySkillRank.Select(r => new RankAvatar(r.Value, context.IdAvatarMap[r.AvatarId])).SingleOrDefault();
|
||||
Reveals = ToRankAvatars(spiralAbyss.RevealRank, context);
|
||||
Defeat = ToRankAvatar(spiralAbyss.DefeatRank, context);
|
||||
Damage = ToRankAvatar(spiralAbyss.DamageRank, context);
|
||||
TakeDamage = ToRankAvatar(spiralAbyss.TakeDamageRank, context);
|
||||
NormalSkill = ToRankAvatar(spiralAbyss.NormalSkillRank, context);
|
||||
EnergySkill = ToRankAvatar(spiralAbyss.EnergySkillRank, context);
|
||||
Engaged = true;
|
||||
|
||||
foreach (Web.Hoyolab.Takumi.GameRecord.SpiralAbyss.Floor webFloor in spiralAbyss.Floors)
|
||||
@@ -143,4 +138,15 @@ internal sealed class SpiralAbyssView : IEntityOnly<SpiralAbyssEntry?>,
|
||||
return new(meta, context);
|
||||
}
|
||||
}
|
||||
|
||||
private static List<RankAvatar> ToRankAvatars(List<Web.Hoyolab.Takumi.GameRecord.SpiralAbyss.Rank> ranks, SpiralAbyssMetadataContext context)
|
||||
{
|
||||
return ranks.Where(r => r.AvatarId != 0U).Select(r => new RankAvatar(r.Value, context.IdAvatarMap[r.AvatarId])).ToList();
|
||||
}
|
||||
|
||||
private static RankAvatar? ToRankAvatar(List<Web.Hoyolab.Takumi.GameRecord.SpiralAbyss.Rank> ranks, SpiralAbyssMetadataContext context)
|
||||
{
|
||||
return ranks.Where(r => r.AvatarId != 0U).Select(r => new RankAvatar(r.Value, context.IdAvatarMap[r.AvatarId])).SingleOrDefault();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -50,6 +50,12 @@ internal sealed partial class TestViewModel : Abstraction.ViewModel
|
||||
LocalSetting.Set(SettingKeys.Major1Minor7Revision0GuideState, (uint)GuideState.Language);
|
||||
}
|
||||
|
||||
[Command("ExceptionCommand")]
|
||||
private static void ThrowTestException()
|
||||
{
|
||||
Must.NeverHappen();
|
||||
}
|
||||
|
||||
[Command("ResetMainWindowSizeCommand")]
|
||||
private void ResetMainWindowSize()
|
||||
{
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.Web.WebView2.Core;
|
||||
using Snap.Hutao.Web.Hoyolab;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Snap.Hutao.Web.Bridge;
|
||||
@@ -14,7 +13,7 @@ namespace Snap.Hutao.Web.Bridge;
|
||||
internal static class CoreWebView2Extension
|
||||
{
|
||||
[Conditional("RELEASE")]
|
||||
public static void DisableDevToolsOnReleaseBuild(this CoreWebView2 webView)
|
||||
public static void DisableDevToolsForReleaseBuild(this CoreWebView2 webView)
|
||||
{
|
||||
CoreWebView2Settings settings = webView.Settings;
|
||||
settings.AreBrowserAcceleratorKeysEnabled = false;
|
||||
@@ -38,64 +37,4 @@ internal static class CoreWebView2Extension
|
||||
manager.DeleteCookie(item);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置 移动端UA
|
||||
/// </summary>
|
||||
/// <param name="webView">webView2</param>
|
||||
/// <returns>链式调用的WebView2</returns>
|
||||
public static CoreWebView2 SetMobileUserAgent(this CoreWebView2 webView)
|
||||
{
|
||||
webView.Settings.UserAgent = HoyolabOptions.MobileUserAgent;
|
||||
return webView;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置 移动端OsUA
|
||||
/// </summary>
|
||||
/// <param name="webView">webView2</param>
|
||||
/// <returns>链式调用的WebView2</returns>
|
||||
public static CoreWebView2 SetMobileOverseaUserAgent(this CoreWebView2 webView)
|
||||
{
|
||||
webView.Settings.UserAgent = HoyolabOptions.MobileUserAgentOversea;
|
||||
return webView;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置WebView2的Cookie
|
||||
/// </summary>
|
||||
/// <param name="webView">webView2</param>
|
||||
/// <param name="cookieToken">CookieToken</param>
|
||||
/// <param name="lToken">LToken</param>
|
||||
/// <param name="sToken">SToken</param>
|
||||
/// <param name="isOversea">是否为国际服,用于改变 cookie domain</param>
|
||||
/// <returns>链式调用的WebView2</returns>
|
||||
public static CoreWebView2 SetCookie(this CoreWebView2 webView, Cookie? cookieToken = null, Cookie? lToken = null, Cookie? sToken = null, bool isOversea = false)
|
||||
{
|
||||
CoreWebView2CookieManager cookieManager = webView.CookieManager;
|
||||
|
||||
if (cookieToken is not null)
|
||||
{
|
||||
cookieManager.AddMihoyoCookie(Cookie.ACCOUNT_ID, cookieToken, isOversea).AddMihoyoCookie(Cookie.COOKIE_TOKEN, cookieToken, isOversea);
|
||||
}
|
||||
|
||||
if (lToken is not null)
|
||||
{
|
||||
cookieManager.AddMihoyoCookie(Cookie.LTUID, lToken, isOversea).AddMihoyoCookie(Cookie.LTOKEN, lToken, isOversea);
|
||||
}
|
||||
|
||||
if (sToken is not null)
|
||||
{
|
||||
cookieManager.AddMihoyoCookie(Cookie.STUID, sToken, isOversea).AddMihoyoCookie(Cookie.STOKEN, sToken, isOversea);
|
||||
}
|
||||
|
||||
return webView;
|
||||
}
|
||||
|
||||
private static CoreWebView2CookieManager AddMihoyoCookie(this CoreWebView2CookieManager manager, string name, Cookie cookie, bool isOversea = false)
|
||||
{
|
||||
string domain = isOversea ? ".hoyolab.com" : ".mihoyo.com";
|
||||
manager.AddOrUpdateCookie(manager.CreateCookie(name, cookie[name], domain, "/"));
|
||||
return manager;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.Web.WebView2.Core;
|
||||
using Snap.Hutao.Web.Hoyolab;
|
||||
|
||||
namespace Snap.Hutao.Web.Bridge;
|
||||
|
||||
internal static class HoyolabCoreWebView2Extension
|
||||
{
|
||||
public static ValueTask DeleteCookiesAsync(this CoreWebView2 webView, bool isOversea)
|
||||
{
|
||||
return webView.DeleteCookiesAsync(isOversea ? ".hoyolab.com" : ".mihoyo.com");
|
||||
}
|
||||
|
||||
public static CoreWebView2 SetMobileUserAgent(this CoreWebView2 webView, bool isOversea)
|
||||
{
|
||||
return isOversea
|
||||
? webView.SetMobileUserAgentOversea()
|
||||
: webView.SetMobileUserAgentChinese();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置 移动端UA
|
||||
/// </summary>
|
||||
/// <param name="webView">webView2</param>
|
||||
/// <returns>链式调用的WebView2</returns>
|
||||
public static CoreWebView2 SetMobileUserAgentChinese(this CoreWebView2 webView)
|
||||
{
|
||||
webView.Settings.UserAgent = HoyolabOptions.MobileUserAgent;
|
||||
return webView;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置 移动端OsUA
|
||||
/// </summary>
|
||||
/// <param name="webView">webView2</param>
|
||||
/// <returns>链式调用的WebView2</returns>
|
||||
public static CoreWebView2 SetMobileUserAgentOversea(this CoreWebView2 webView)
|
||||
{
|
||||
webView.Settings.UserAgent = HoyolabOptions.MobileUserAgentOversea;
|
||||
return webView;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置WebView2的Cookie
|
||||
/// </summary>
|
||||
/// <param name="webView">webView2</param>
|
||||
/// <param name="cookieToken">CookieToken</param>
|
||||
/// <param name="lToken">LToken</param>
|
||||
/// <param name="isOversea">是否为国际服,用于改变 cookie domain</param>
|
||||
/// <returns>链式调用的WebView2</returns>
|
||||
public static CoreWebView2 SetCookie(this CoreWebView2 webView, Cookie? cookieToken = null, Cookie? lToken = null, bool isOversea = false)
|
||||
{
|
||||
CoreWebView2CookieManager cookieManager = webView.CookieManager;
|
||||
|
||||
if (cookieToken is not null)
|
||||
{
|
||||
cookieManager
|
||||
.AddMihoyoCookie(Cookie.ACCOUNT_ID, cookieToken, isOversea)
|
||||
.AddMihoyoCookie(Cookie.COOKIE_TOKEN, cookieToken, isOversea);
|
||||
}
|
||||
|
||||
if (lToken is not null)
|
||||
{
|
||||
cookieManager
|
||||
.AddMihoyoCookie(Cookie.LTUID, lToken, isOversea)
|
||||
.AddMihoyoCookie(Cookie.LTOKEN, lToken, isOversea);
|
||||
}
|
||||
|
||||
return webView;
|
||||
}
|
||||
|
||||
private static CoreWebView2CookieManager AddMihoyoCookie(this CoreWebView2CookieManager manager, string name, Cookie cookie, bool isOversea = false)
|
||||
{
|
||||
string domain = isOversea ? ".hoyolab.com" : ".mihoyo.com";
|
||||
manager.AddOrUpdateCookie(manager.CreateCookie(name, cookie[name], domain, "/"));
|
||||
return manager;
|
||||
}
|
||||
}
|
||||
@@ -39,18 +39,20 @@ internal class MiHoYoJSInterface
|
||||
document.querySelector('body').appendChild(st);
|
||||
""";
|
||||
|
||||
private readonly IServiceProvider serviceProvider;
|
||||
private readonly CoreWebView2 webView;
|
||||
private readonly SemaphoreSlim webMessageSemaphore = new(1);
|
||||
private readonly Guid interfaceId = Guid.NewGuid();
|
||||
private readonly UserAndUid userAndUid;
|
||||
|
||||
private readonly IServiceProvider serviceProvider;
|
||||
private readonly ITaskContext taskContext;
|
||||
private readonly ILogger<MiHoYoJSInterface> logger;
|
||||
private readonly SemaphoreSlim webMessageSemaphore = new(1);
|
||||
|
||||
private readonly TypedEventHandler<CoreWebView2, CoreWebView2WebMessageReceivedEventArgs> webMessageReceivedEventHandler;
|
||||
private readonly TypedEventHandler<CoreWebView2, CoreWebView2DOMContentLoadedEventArgs> domContentLoadedEventHandler;
|
||||
private readonly TypedEventHandler<CoreWebView2, CoreWebView2NavigationStartingEventArgs> navigationStartingEventHandler;
|
||||
|
||||
private CoreWebView2 webView;
|
||||
|
||||
public MiHoYoJSInterface(CoreWebView2 webView, UserAndUid userAndUid)
|
||||
{
|
||||
// 由于Webview2 的作用域特殊性,我们在此处直接使用根服务
|
||||
@@ -342,6 +344,14 @@ internal class MiHoYoJSInterface
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Detach()
|
||||
{
|
||||
webView.WebMessageReceived -= webMessageReceivedEventHandler;
|
||||
webView.DOMContentLoaded -= domContentLoadedEventHandler;
|
||||
webView.NavigationStarting -= navigationStartingEventHandler;
|
||||
webView = default!;
|
||||
}
|
||||
|
||||
private async ValueTask<string> ExecuteCallbackScriptAsync(string callback, string? payload = null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(callback))
|
||||
@@ -360,25 +370,29 @@ internal class MiHoYoJSInterface
|
||||
.Append(')')
|
||||
.ToString();
|
||||
|
||||
logger?.LogInformation("[ExecuteScript: {callback}]\n{payload}", callback, payload);
|
||||
logger?.LogInformation("[{Id}][ExecuteScript: {callback}]\n{payload}", interfaceId, callback, payload);
|
||||
|
||||
await taskContext.SwitchToMainThreadAsync();
|
||||
try
|
||||
{
|
||||
return await webView.ExecuteScriptAsync(js);
|
||||
if (webView is not null)
|
||||
{
|
||||
return await webView.ExecuteScriptAsync(js);
|
||||
}
|
||||
}
|
||||
catch (COMException)
|
||||
{
|
||||
// COMException (0x8007139F): 组或资源的状态不是执行请求操作的正确状态。 (0x8007139F)
|
||||
// webview is disposing or disposed
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
private async void OnWebMessageReceived(CoreWebView2 webView2, CoreWebView2WebMessageReceivedEventArgs args)
|
||||
{
|
||||
string message = args.TryGetWebMessageAsString();
|
||||
logger.LogInformation("[OnRawMessage]\n{message}", message);
|
||||
logger.LogInformation("[{Id}][OnRawMessage]\n{message}", interfaceId, message);
|
||||
JsParam? param = JsonSerializer.Deserialize<JsParam>(message);
|
||||
|
||||
ArgumentNullException.ThrowIfNull(param);
|
||||
@@ -445,7 +459,7 @@ internal class MiHoYoJSInterface
|
||||
if (uriHostSpan.EndsWith("mihoyo.com") || uriHostSpan.EndsWith("hoyolab.com"))
|
||||
{
|
||||
// Execute this solve issue: When open same site second time,there might be no bridge init.
|
||||
coreWebView2.AddScriptToExecuteOnDocumentCreatedAsync(InitializeJsInterfaceScript2).AsTask().SafeForget(logger);
|
||||
// coreWebView2.AddScriptToExecuteOnDocumentCreatedAsync(InitializeJsInterfaceScript2).AsTask().SafeForget(logger);
|
||||
coreWebView2.ExecuteScriptAsync(InitializeJsInterfaceScript2).AsTask().SafeForget(logger);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ internal sealed partial class SignInClientOversea : ISignInClient
|
||||
HttpRequestMessageBuilder builder = httpRequestMessageBuilderFactory.Create()
|
||||
.SetRequestUri(ApiOsEndpoints.SignInRewardSign)
|
||||
.SetUserCookie(userAndUid, CookieType.CookieToken)
|
||||
.PostJson(new SignInData(userAndUid.Uid, false));
|
||||
.PostJson(new SignInData(userAndUid.Uid, true));
|
||||
|
||||
Response<SignInResult>? resp = await builder
|
||||
.TryCatchSendAsync<Response<SignInResult>>(httpClient, logger, token)
|
||||
@@ -73,7 +73,7 @@ internal sealed partial class SignInClientOversea : ISignInClient
|
||||
.SetRequestUri(ApiOsEndpoints.SignInRewardSign)
|
||||
.SetUserCookie(userAndUid, CookieType.CookieToken)
|
||||
.SetXrpcChallenge(challenge, validate)
|
||||
.PostJson(new SignInData(userAndUid.Uid, false));
|
||||
.PostJson(new SignInData(userAndUid.Uid, true));
|
||||
|
||||
resp = await verifiedBuilder
|
||||
.TryCatchSendAsync<Response<SignInResult>>(httpClient, logger, token)
|
||||
|
||||
@@ -22,13 +22,23 @@ internal sealed partial class HomaGeetestClient
|
||||
{
|
||||
string template = appOptions.GeetestCustomCompositeUrl;
|
||||
|
||||
if (string.IsNullOrEmpty(template))
|
||||
string url;
|
||||
try
|
||||
{
|
||||
url = template.Format(gt, challenge);
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
return GeetestResponse.InternalFailure;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(template) || !Uri.TryCreate(url, UriKind.Absolute, out Uri? uri))
|
||||
{
|
||||
return GeetestResponse.InternalFailure;
|
||||
}
|
||||
|
||||
HttpRequestMessageBuilder builder = httpRequestMessageBuilderFactory.Create()
|
||||
.SetRequestUri(template.Format(gt, challenge))
|
||||
.SetRequestUri(uri)
|
||||
.Get();
|
||||
|
||||
GeetestResponse? resp = await builder
|
||||
|
||||
@@ -31,7 +31,7 @@ internal sealed partial class HomaLogUploadClient
|
||||
public async ValueTask<string?> UploadLogAsync(Exception exception)
|
||||
{
|
||||
HttpRequestMessageBuilder builder = httpRequestMessageBuilderFactory.Create()
|
||||
.SetRequestUri(HutaoEndpoints.GachaLogUpload)
|
||||
.SetRequestUri(HutaoEndpoints.HutaoLogUpload)
|
||||
.PostJson(BuildFromException(exception));
|
||||
|
||||
Response<string>? resp = await builder
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Core.ExceptionService;
|
||||
using Snap.Hutao.Web.Request.Builder.Abstraction;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
@@ -66,7 +67,7 @@ internal abstract class HttpContentSerializer : IHttpContentSerializer, IHttpCon
|
||||
The content to be serialized does not match the specified type.
|
||||
Expected an instance of the class "{contentType.FullName}", but got "{actualContentType.FullName}".
|
||||
""";
|
||||
throw new ArgumentException(message, nameof(contentType));
|
||||
ThrowHelper.Argument(message, nameof(contentType));
|
||||
}
|
||||
|
||||
// The contentType is optional. In that case, try to get the type on our own.
|
||||
|
||||
@@ -33,6 +33,11 @@ internal static class HttpRequestMessageBuilderExtension
|
||||
logger.LogWarning(ex, RequestErrorMessage);
|
||||
return default;
|
||||
}
|
||||
catch (HttpContentSerializationException ex)
|
||||
{
|
||||
logger.LogWarning(ex, RequestErrorMessage);
|
||||
return default;
|
||||
}
|
||||
catch (SocketException ex)
|
||||
{
|
||||
logger.LogWarning(ex, RequestErrorMessage);
|
||||
|
||||
@@ -17,9 +17,4 @@ internal unsafe interface IUnmanagedMemory : IDisposable
|
||||
/// Gets size of referenced unmanaged memory, in bytes.
|
||||
/// </summary>
|
||||
uint Size { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a span of bytes from the current instance.
|
||||
/// </summary>
|
||||
Span<byte> Span { get; }
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Win32.Memory;
|
||||
|
||||
internal static class UnmanagedMemoryExtension
|
||||
{
|
||||
public static unsafe Span<byte> AsSpan(this IUnmanagedMemory unmanagedMemory)
|
||||
{
|
||||
return new(unmanagedMemory.Pointer, (int)unmanagedMemory.Size);
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ using static Windows.Win32.PInvoke;
|
||||
namespace Snap.Hutao.Win32.Memory;
|
||||
|
||||
/// <summary>
|
||||
/// NativeMemory.AllocZeroed wrapper
|
||||
/// VirtualAlloc wrapper
|
||||
/// </summary>
|
||||
internal readonly unsafe struct VirtualMemory : IUnmanagedMemory
|
||||
{
|
||||
@@ -38,9 +38,6 @@ internal readonly unsafe struct VirtualMemory : IUnmanagedMemory
|
||||
/// <inheritdoc/>
|
||||
public uint Size { get => size; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Span<byte> Span { get => new(pointer, (int)size); }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Dispose()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user