Merge branch 'feature/guide' into develop

This commit is contained in:
Lightczx
2023-08-29 10:46:53 +08:00
20 changed files with 673 additions and 293 deletions

View File

@@ -0,0 +1,18 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Microsoft.UI.Xaml.Markup;
namespace Snap.Hutao.Control.Markup;
[MarkupExtensionReturnType(ReturnType = typeof(uint))]
internal sealed class UInt32Extension : MarkupExtension
{
public string Value { get; set; } = default!;
protected override object ProvideValue()
{
_ = uint.TryParse(Value, out uint result);
return result;
}
}

View File

@@ -150,7 +150,7 @@ internal sealed class Activation : IActivation
// Increase launch times
LocalSetting.Set(SettingKeys.LaunchTimes, LocalSetting.Get(SettingKeys.LaunchTimes, 0) + 1);
if (false && LocalSetting.Get(SettingKeys.Major1Minor7Revision0GuideState, (uint)GuideState.None) < (uint)GuideState.Completed)
if (LocalSetting.Get(SettingKeys.Major1Minor7Revision0GuideState, (uint)GuideState.Language) < (uint)GuideState.Completed)
{
await taskContext.SwitchToMainThreadAsync();
serviceProvider.GetRequiredService<GuideWindow>();

View File

@@ -4,17 +4,11 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:mxi="using:Microsoft.Xaml.Interactivity"
xmlns:shcb="using:Snap.Hutao.Control.Behavior"
xmlns:shcm="using:Snap.Hutao.Control.Markup"
xmlns:shvg="using:Snap.Hutao.View.Guide"
mc:Ignorable="d">
<Grid x:Name="RootGrid">
<mxi:Interaction.Behaviors>
<shcb:InvokeCommandOnLoadedBehavior Command="{Binding OpenUICommand}"/>
</mxi:Interaction.Behaviors>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition/>

View File

@@ -14,24 +14,6 @@
Height="44"
Margin="48,0,0,0"/>
<cwuc:SwitchPresenter x:Name="ContentSwitchPresenter">
<cwuc:SwitchPresenter.ContentTransitions>
<TransitionCollection>
<EntranceThemeTransition/>
</TransitionCollection>
</cwuc:SwitchPresenter.ContentTransitions>
<cwuc:Case>
<cwuc:Case.Value>
<x:Boolean>True</x:Boolean>
</cwuc:Case.Value>
<shv:WelcomeView/>
</cwuc:Case>
<cwuc:Case>
<cwuc:Case.Value>
<x:Boolean>False</x:Boolean>
</cwuc:Case.Value>
<shv:MainView/>
</cwuc:Case>
</cwuc:SwitchPresenter>
<shv:MainView/>
</Grid>
</Window>

View File

@@ -1,11 +1,8 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using CommunityToolkit.Mvvm.Messaging;
using Microsoft.UI.Xaml;
using Snap.Hutao.Core.Setting;
using Snap.Hutao.Core.Windowing;
using Snap.Hutao.Message;
using Windows.Foundation;
using Windows.Win32.UI.WindowsAndMessaging;
@@ -17,7 +14,7 @@ namespace Snap.Hutao;
[HighQuality]
[Injection(InjectAs.Singleton)]
[SuppressMessage("", "CA1001")]
internal sealed partial class MainWindow : Window, IWindowOptionsSource, IRecipient<WelcomeStateCompleteMessage>
internal sealed partial class MainWindow : Window, IWindowOptionsSource
{
private const int MinWidth = 848;
private const int MinHeight = 524;
@@ -35,11 +32,8 @@ internal sealed partial class MainWindow : Window, IWindowOptionsSource, IRecipi
InitializeComponent();
windowOptions = new(this, TitleBarView.DragArea, new(1200, 741), true);
ExtendedWindow<MainWindow>.Initialize(this, serviceProvider);
serviceProvider.GetRequiredService<IMessenger>().Register(this);
logger = serviceProvider.GetRequiredService<ILogger<MainWindow>>();
// If not complete we should present the welcome view.
ContentSwitchPresenter.Value = StaticResource.IsAnyUnfulfilledContractPresent();
closedEventHander = OnClosed;
Closed += closedEventHander;
}
@@ -54,12 +48,6 @@ internal sealed partial class MainWindow : Window, IWindowOptionsSource, IRecipi
pInfo->ptMinTrackSize.Y = (int)Math.Max(MinHeight * scalingFactor, pInfo->ptMinTrackSize.Y);
}
/// <inheritdoc/>
public void Receive(WelcomeStateCompleteMessage message)
{
ContentSwitchPresenter.Value = false;
}
private void OnClosed(object sender, WindowEventArgs args)
{
logger.LogInformation("MainWindow Closed");

View File

@@ -1,12 +0,0 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Message;
/// <summary>
/// 欢迎状态完成消息
/// </summary>
[HighQuality]
internal sealed class WelcomeStateCompleteMessage
{
}

View File

@@ -2598,6 +2598,132 @@ namespace Snap.Hutao.Resource.Localization {
}
}
/// <summary>
/// 查找类似 我已阅读 的本地化字符串。
/// </summary>
internal static string ViewGuideStepAgreementIHaveReadText {
get {
return ResourceManager.GetString("ViewGuideStepAgreementIHaveReadText", resourceCulture);
}
}
/// <summary>
/// 查找类似 问题报告方式与流程 的本地化字符串。
/// </summary>
internal static string ViewGuideStepAgreementIssueReport {
get {
return ResourceManager.GetString("ViewGuideStepAgreementIssueReport", resourceCulture);
}
}
/// <summary>
/// 查找类似 Snap Hutao 开源许可 的本地化字符串。
/// </summary>
internal static string ViewGuideStepAgreementOpenSourceLicense {
get {
return ResourceManager.GetString("ViewGuideStepAgreementOpenSourceLicense", resourceCulture);
}
}
/// <summary>
/// 查找类似 用户数据与隐私权益 的本地化字符串。
/// </summary>
internal static string ViewGuideStepAgreementPrivacyPolicy {
get {
return ResourceManager.GetString("ViewGuideStepAgreementPrivacyPolicy", resourceCulture);
}
}
/// <summary>
/// 查找类似 用户使用协议与法律声明 的本地化字符串。
/// </summary>
internal static string ViewGuideStepAgreementTermOfService {
get {
return ResourceManager.GetString("ViewGuideStepAgreementTermOfService", resourceCulture);
}
}
/// <summary>
/// 查找类似 文档 的本地化字符串。
/// </summary>
internal static string ViewGuideStepDocument {
get {
return ResourceManager.GetString("ViewGuideStepDocument", resourceCulture);
}
}
/// <summary>
/// 查找类似 环境 的本地化字符串。
/// </summary>
internal static string ViewGuideStepEnvironment {
get {
return ResourceManager.GetString("ViewGuideStepEnvironment", resourceCulture);
}
}
/// <summary>
/// 查找类似 安装完成后重启胡桃以查看是否正常生效 的本地化字符串。
/// </summary>
internal static string ViewGuideStepEnvironmentAfterInstallDescription {
get {
return ResourceManager.GetString("ViewGuideStepEnvironmentAfterInstallDescription", resourceCulture);
}
}
/// <summary>
/// 查找类似 如果上方的图标中存在乱码,请前往 的本地化字符串。
/// </summary>
internal static string ViewGuideStepEnvironmentFontDescription1 {
get {
return ResourceManager.GetString("ViewGuideStepEnvironmentFontDescription1", resourceCulture);
}
}
/// <summary>
/// 查找类似 下载并自行安装图标字体 的本地化字符串。
/// </summary>
internal static string ViewGuideStepEnvironmentFontDescription2 {
get {
return ResourceManager.GetString("ViewGuideStepEnvironmentFontDescription2", resourceCulture);
}
}
/// <summary>
/// 查找类似 若未检测到 WebView2 运行时信息,可以前往 的本地化字符串。
/// </summary>
internal static string ViewGuideStepEnvironmentWebView2Description1 {
get {
return ResourceManager.GetString("ViewGuideStepEnvironmentWebView2Description1", resourceCulture);
}
}
/// <summary>
/// 查找类似 下载并自行安装运行时 的本地化字符串。
/// </summary>
internal static string ViewGuideStepEnvironmentWebView2Description2 {
get {
return ResourceManager.GetString("ViewGuideStepEnvironmentWebView2Description2", resourceCulture);
}
}
/// <summary>
/// 查找类似 语言 的本地化字符串。
/// </summary>
internal static string ViewGuideStepLanguage {
get {
return ResourceManager.GetString("ViewGuideStepLanguage", resourceCulture);
}
}
/// <summary>
/// 查找类似 资源 的本地化字符串。
/// </summary>
internal static string ViewGuideStepStaticResource {
get {
return ResourceManager.GetString("ViewGuideStepStaticResource", resourceCulture);
}
}
/// <summary>
/// 查找类似 深渊统计 的本地化字符串。
/// </summary>
@@ -3048,6 +3174,42 @@ namespace Snap.Hutao.Resource.Localization {
}
}
/// <summary>
/// 查找类似 我已阅读并同意上方的条款 的本地化字符串。
/// </summary>
internal static string ViewModelGuideActionAgreement {
get {
return ResourceManager.GetString("ViewModelGuideActionAgreement", resourceCulture);
}
}
/// <summary>
/// 查找类似 完成 的本地化字符串。
/// </summary>
internal static string ViewModelGuideActionComplete {
get {
return ResourceManager.GetString("ViewModelGuideActionComplete", resourceCulture);
}
}
/// <summary>
/// 查找类似 下一步 的本地化字符串。
/// </summary>
internal static string ViewModelGuideActionNext {
get {
return ResourceManager.GetString("ViewModelGuideActionNext", resourceCulture);
}
}
/// <summary>
/// 查找类似 下载资源文件中,请稍后 的本地化字符串。
/// </summary>
internal static string ViewModelGuideActionStaticResourceBegin {
get {
return ResourceManager.GetString("ViewModelGuideActionStaticResourceBegin", resourceCulture);
}
}
/// <summary>
/// 查找类似 请输入正确的邮箱 的本地化字符串。
/// </summary>

View File

@@ -1019,6 +1019,48 @@
<data name="ViewGachaLogHeader" xml:space="preserve">
<value>祈愿记录</value>
</data>
<data name="ViewGuideStepAgreementIHaveReadText" xml:space="preserve">
<value>我已阅读</value>
</data>
<data name="ViewGuideStepAgreementIssueReport" xml:space="preserve">
<value>问题报告方式与流程</value>
</data>
<data name="ViewGuideStepAgreementOpenSourceLicense" xml:space="preserve">
<value>Snap Hutao 开源许可</value>
</data>
<data name="ViewGuideStepAgreementPrivacyPolicy" xml:space="preserve">
<value>用户数据与隐私权益</value>
</data>
<data name="ViewGuideStepAgreementTermOfService" xml:space="preserve">
<value>用户使用协议与法律声明</value>
</data>
<data name="ViewGuideStepDocument" xml:space="preserve">
<value>文档</value>
</data>
<data name="ViewGuideStepEnvironment" xml:space="preserve">
<value>环境</value>
</data>
<data name="ViewGuideStepEnvironmentAfterInstallDescription" xml:space="preserve">
<value>安装完成后重启胡桃以查看是否正常生效</value>
</data>
<data name="ViewGuideStepEnvironmentFontDescription1" xml:space="preserve">
<value>如果上方的图标中存在乱码,请前往</value>
</data>
<data name="ViewGuideStepEnvironmentFontDescription2" xml:space="preserve">
<value>下载并自行安装图标字体</value>
</data>
<data name="ViewGuideStepEnvironmentWebView2Description1" xml:space="preserve">
<value>若未检测到 WebView2 运行时信息,可以前往</value>
</data>
<data name="ViewGuideStepEnvironmentWebView2Description2" xml:space="preserve">
<value>下载并自行安装运行时</value>
</data>
<data name="ViewGuideStepLanguage" xml:space="preserve">
<value>语言</value>
</data>
<data name="ViewGuideStepStaticResource" xml:space="preserve">
<value>资源</value>
</data>
<data name="ViewHutaoDatabaseHeader" xml:space="preserve">
<value>深渊统计</value>
</data>
@@ -1169,6 +1211,18 @@
<data name="ViewModelGachaLogUploadToHutaoCloudProgress" xml:space="preserve">
<value>正在上传到胡桃云服务</value>
</data>
<data name="ViewModelGuideActionAgreement" xml:space="preserve">
<value>我已阅读并同意上方的条款</value>
</data>
<data name="ViewModelGuideActionComplete" xml:space="preserve">
<value>完成</value>
</data>
<data name="ViewModelGuideActionNext" xml:space="preserve">
<value>下一步</value>
</data>
<data name="ViewModelGuideActionStaticResourceBegin" xml:space="preserve">
<value>下载资源文件中,请稍后</value>
</data>
<data name="ViewModelHutaoPassportEmailNotValidHint" xml:space="preserve">
<value>请输入正确的邮箱</value>
</data>

View File

@@ -155,7 +155,6 @@
<None Remove="View\Page\WikiWeaponPage.xaml" />
<None Remove="View\TitleView.xaml" />
<None Remove="View\UserView.xaml" />
<None Remove="View\WelcomeView.xaml" />
</ItemGroup>
<!-- Analyzer Files -->
@@ -376,11 +375,6 @@
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<Page Update="View\WelcomeView.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<Page Update="View\Page\TestPage.xaml">
<Generator>MSBuild:Compile</Generator>

View File

@@ -2,27 +2,210 @@
x:Class="Snap.Hutao.View.Guide.GuideView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:cwuc="using:CommunityToolkit.WinUI.UI.Controls"
xmlns:cwc="using:CommunityToolkit.WinUI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:mxi="using:Microsoft.Xaml.Interactivity"
xmlns:shcb="using:Snap.Hutao.Control.Behavior"
xmlns:shcm="using:Snap.Hutao.Control.Markup"
xmlns:shvg="using:Snap.Hutao.ViewModel.Guide"
d:DataContext="{d:DesignInstance shvg:GuideViewModel}"
mc:Ignorable="d">
<mxi:Interaction.Behaviors>
<shcb:InvokeCommandOnLoadedBehavior Command="{Binding OpenUICommand}"/>
</mxi:Interaction.Behaviors>
<Grid Background="{ThemeResource CardBackgroundFillColorSecondaryBrush}">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<cwuc:SwitchPresenter/>
<cwc:SwitchPresenter Value="{Binding State, Mode=OneWay}">
<cwc:Case Value="{shcm:UInt32 Value=0}">
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
<GridView
Grid.Row="0"
ItemsSource="{Binding AppOptions.Cultures}"
SelectedItem="{Binding SelectedCulture, Mode=TwoWay}"
SelectionMode="Single">
<GridView.ItemTemplate>
<DataTemplate>
<TextBlock
Margin="16"
Style="{StaticResource SubtitleTextBlockStyle}"
Text="{Binding Name}"/>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
</Grid>
</cwc:Case>
<cwc:Case Value="{shcm:UInt32 Value=1}">
<Grid
HorizontalAlignment="Center"
VerticalAlignment="Center"
ColumnSpacing="16">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<Image
Grid.Column="0"
Height="152"
Source="ms-appx:///Assets/Square44x44Logo.targetsize-256.png"/>
<StackPanel
Grid.Column="2"
VerticalAlignment="Center"
Spacing="8">
<CheckBox IsChecked="{Binding IsTermOfServiceAgreed, Mode=TwoWay}">
<TextBlock>
<TextBlock.Inlines>
<Run Text="{shcm:ResourceString Name=ViewGuideStepAgreementIHaveReadText}"/>
<Hyperlink NavigateUri="https://hut.ao/statements/tos.html">
<Run Text="{shcm:ResourceString Name=ViewGuideStepAgreementTermOfService}"/>
</Hyperlink>
</TextBlock.Inlines>
</TextBlock>
</CheckBox>
<CheckBox IsChecked="{Binding IsPrivacyPolicyAgreed, Mode=TwoWay}">
<TextBlock>
<TextBlock.Inlines>
<Run Text="{shcm:ResourceString Name=ViewGuideStepAgreementIHaveReadText}"/>
<Hyperlink NavigateUri="https://hut.ao/statements/privacy-notice.html">
<Run Text="{shcm:ResourceString Name=ViewGuideStepAgreementPrivacyPolicy}"/>
</Hyperlink>
</TextBlock.Inlines>
</TextBlock>
</CheckBox>
<CheckBox IsChecked="{Binding IsIssueReportAgreed, Mode=TwoWay}">
<TextBlock>
<TextBlock.Inlines>
<Run Text="{shcm:ResourceString Name=ViewGuideStepAgreementIHaveReadText}"/>
<Hyperlink NavigateUri="https://hut.ao/statements/bug-report.html">
<Run Text="{shcm:ResourceString Name=ViewGuideStepAgreementIssueReport}"/>
</Hyperlink>
</TextBlock.Inlines>
</TextBlock>
</CheckBox>
<CheckBox IsChecked="{Binding IsOpenSourceLicenseAgreed, Mode=TwoWay}">
<TextBlock>
<TextBlock.Inlines>
<Run Text="{shcm:ResourceString Name=ViewGuideStepAgreementIHaveReadText}"/>
<Hyperlink NavigateUri="https://github.com/DGP-Studio/Snap.Hutao/blob/main/LICENSE">
<Run Text="{shcm:ResourceString Name=ViewGuideStepAgreementOpenSourceLicense}"/>
</Hyperlink>
</TextBlock.Inlines>
</TextBlock>
</CheckBox>
</StackPanel>
</Grid>
</cwc:Case>
<cwc:Case Value="{shcm:UInt32 Value=2}">
<Grid>
<StackPanel
Margin="16"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<TextBlock
Margin="1,0,0,5"
Style="{StaticResource SettingsSectionHeaderTextBlockStyle}"
Text="Segoe Fluent Icons"/>
<StackPanel
Margin="0,8"
Orientation="Horizontal"
Spacing="8">
<!-- PUA E700-E900 -->
<FontIcon FontSize="{StaticResource SubtitleTextBlockFontSize}" Glyph="&#xE8DF;"/>
<!-- PUA EA00-EC00 -->
<FontIcon FontSize="{StaticResource SubtitleTextBlockFontSize}" Glyph="&#xEF58;"/>
<!-- PUA ED00-EF00 -->
<FontIcon FontSize="{StaticResource SubtitleTextBlockFontSize}" Glyph="&#xED56;"/>
<!-- PUA F000-F200 -->
<FontIcon FontSize="{StaticResource SubtitleTextBlockFontSize}" Glyph="&#xF012;"/>
<!-- PUA F300-F500 -->
<FontIcon FontSize="{StaticResource SubtitleTextBlockFontSize}" Glyph="&#xF439;"/>
<!-- PUA F600-F800 -->
<FontIcon FontSize="{StaticResource SubtitleTextBlockFontSize}" Glyph="&#xF6A9;"/>
</StackPanel>
<TextBlock>
<Run Text="{shcm:ResourceString Name=ViewGuideStepEnvironmentFontDescription1}"/>
<Hyperlink NavigateUri="https://aka.ms/SegoeFluentIcons">
<Run Text="Microsoft"/>
</Hyperlink>
<Run Text="{shcm:ResourceString Name=ViewGuideStepEnvironmentFontDescription2}"/>
</TextBlock>
<TextBlock Text="{shcm:ResourceString Name=ViewGuideStepEnvironmentAfterInstallDescription}"/>
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" Text="{shcm:ResourceString Name=ViewPageSettingWebview2Header}"/>
<TextBlock Style="{StaticResource SubtitleTextBlockStyle}" Text="{Binding RuntimeOptions.WebView2Version}"/>
<TextBlock>
<Run Text="{shcm:ResourceString Name=ViewGuideStepEnvironmentWebView2Description1}"/>
<Hyperlink NavigateUri="https://go.microsoft.com/fwlink/p/?LinkId=2124703">
<Run Text="Microsoft"/>
</Hyperlink>
<Run Text="{shcm:ResourceString Name=ViewGuideStepEnvironmentWebView2Description2}"/>
</TextBlock>
<TextBlock Text="{shcm:ResourceString Name=ViewGuideStepEnvironmentAfterInstallDescription}"/>
</StackPanel>
</Grid>
</cwc:Case>
<cwc:Case Value="{shcm:UInt32 Value=3}">
<StackPanel Margin="32,0" HorizontalAlignment="Left">
<TextBlock
Margin="1,16,0,5"
Style="{StaticResource BaseTextBlockStyle}"
Text="{shcm:ResourceString Name=ViewWelcomeBase}"/>
<ScrollViewer>
<ItemsControl
Margin="0,0,-4,0"
HorizontalAlignment="Center"
ItemsPanel="{StaticResource WrapPanelTemplate}"
ItemsSource="{Binding DownloadSummaries}">
<ItemsControl.ItemContainerTransitions>
<TransitionCollection>
<AddDeleteThemeTransition/>
<ContentThemeTransition/>
<ReorderThemeTransition/>
<EntranceThemeTransition IsStaggeringEnabled="False"/>
</TransitionCollection>
</ItemsControl.ItemContainerTransitions>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border
Width="180"
Margin="0,0,4,4"
Style="{StaticResource BorderCardStyle}">
<StackPanel Margin="8">
<TextBlock Text="{Binding DisplayName}"/>
<ProgressBar
Margin="0,4,0,0"
Maximum="1"
Value="{Binding ProgressValue}"/>
<TextBlock
Opacity="0.6"
Style="{StaticResource CaptionTextBlockStyle}"
Text="{Binding Description}"/>
</StackPanel>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</StackPanel>
</cwc:Case>
</cwc:SwitchPresenter>
<Grid Grid.Row="1">
<PipsPager
HorizontalAlignment="Center"
CanBeScrollAnchor="False"
IsEnabled="False"
NumberOfPages="5"
SelectedPageIndex="0"/>
<StackPanel HorizontalAlignment="Center" Orientation="Horizontal">
<cwc:Segmented Margin="16" SelectedIndex="{Binding State, Mode=TwoWay}">
<cwc:SegmentedItem Content="{shcm:ResourceString Name=ViewGuideStepLanguage}" Icon="{shcm:FontIcon Glyph=&#xF2B7;}"/>
<cwc:SegmentedItem Content="{shcm:ResourceString Name=ViewGuideStepDocument}" Icon="{shcm:FontIcon Glyph=&#xF28B;}"/>
<cwc:SegmentedItem Content="{shcm:ResourceString Name=ViewGuideStepEnvironment}" Icon="{shcm:FontIcon Glyph=&#xE81E;}"/>
<cwc:SegmentedItem Content="{shcm:ResourceString Name=ViewGuideStepStaticResource}" Icon="{shcm:FontIcon Glyph=&#xE8B9;}"/>
</cwc:Segmented>
<Button
Command="{Binding NextOrCompleteCommand}"
Content="{Binding NextOrCompleteButtonText}"
IsEnabled="{Binding IsNextOrCompleteButtonEnabled}"/>
</StackPanel>
</Grid>
</Grid>
</UserControl>

View File

@@ -148,7 +148,7 @@
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" Text="{shcm:ResourceString Name=ViewPageSettingGeetestVerificationHeader}"/>
<cwc:SettingsCard
ActionIcon="{shcm:FontIcon Glyph=&#xE76C;}"
ActionIcon="{shcm:FontIcon Glyph=&#xF32A;}"
ActionIconToolTip="{shcm:ResourceString Name=ViewPageSettingGeetestCustomUrlAction}"
Command="{Binding ConfigureGeetestUrlCommand}"
Description="{shcm:ResourceString Name=ViewPageSettingGeetestCustomUrlDescription}"

View File

@@ -58,13 +58,9 @@
</FlyoutBase.AttachedFlyout>
</cwc:SettingsCard>
<cwc:SettingsCard Header="RestartTest">
<cwc:SettingsCard Header="ResetGuideState">
<StackPanel Orientation="Horizontal">
<ToggleSwitch Name="ElevatedSwitch" Style="{StaticResource DefaultToggleSwitchStyle}"/>
<Button
Command="{Binding RestartAppCommand}"
CommandParameter="{Binding ElementName=ElevatedSwitch, Path=IsOn}"
Content="Restart"/>
<Button Command="{Binding ResetGuideStateCommand}" Content="Reset(No restart)"/>
</StackPanel>
</cwc:SettingsCard>
</StackPanel>

View File

@@ -8,14 +8,13 @@
xmlns:mxic="using:Microsoft.Xaml.Interactions.Core"
xmlns:mxim="using:Microsoft.Xaml.Interactions.Media"
xmlns:shc="using:Snap.Hutao.Control"
xmlns:shcb="using:Snap.Hutao.Control.Behavior"
xmlns:shcm="using:Snap.Hutao.Control.Markup"
xmlns:shvu="using:Snap.Hutao.ViewModel.User"
d:DataContext="{d:DesignInstance shvu:UserViewModel}"
mc:Ignorable="d">
<mxi:Interaction.Behaviors>
<mxic:EventTriggerBehavior EventName="Loaded">
<mxic:InvokeCommandAction Command="{Binding OpenUICommand}"/>
</mxic:EventTriggerBehavior>
<shcb:InvokeCommandOnLoadedBehavior Command="{Binding OpenUICommand}"/>
</mxi:Interaction.Behaviors>
<StackPanel>
<Button

View File

@@ -1,74 +0,0 @@
<UserControl
x:Class="Snap.Hutao.View.WelcomeView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:mxi="using:Microsoft.Xaml.Interactivity"
xmlns:shcb="using:Snap.Hutao.Control.Behavior"
xmlns:shcm="using:Snap.Hutao.Control.Markup"
xmlns:shv="using:Snap.Hutao.ViewModel"
d:DataContext="{d:DesignInstance shv:WelcomeViewModel}"
Unloaded="OnUnloaded"
mc:Ignorable="d">
<mxi:Interaction.Behaviors>
<shcb:InvokeCommandOnLoadedBehavior Command="{Binding OpenUICommand}"/>
</mxi:Interaction.Behaviors>
<Grid Margin="0,44,0,0">
<ScrollViewer>
<StackPanel Margin="32,0" HorizontalAlignment="Left">
<TextBlock Style="{StaticResource TitleTextBlockStyle}" Text="{shcm:ResourceString Name=ViewWelcomeTitle}"/>
<TextBlock
Margin="0,8,0,0"
Style="{StaticResource SubtitleTextBlockStyle}"
Text="{shcm:ResourceString Name=ViewWelcomeSubtitle}"/>
<TextBlock
Margin="0,8,0,0"
Style="{StaticResource BaseTextBlockStyle}"
Text="{shcm:ResourceString Name=ViewWelcomeBase}"/>
<TextBlock
Margin="0,0,0,8"
Style="{StaticResource BodyTextBlockStyle}"
Text="{shcm:ResourceString Name=ViewWelcomeBody}"/>
<ItemsControl
Width="256"
Margin="0,0,0,32"
HorizontalAlignment="Left"
ItemsSource="{Binding DownloadSummaries}">
<ItemsControl.ItemContainerTransitions>
<TransitionCollection>
<AddDeleteThemeTransition/>
<ContentThemeTransition/>
<ReorderThemeTransition/>
<EntranceThemeTransition IsStaggeringEnabled="False"/>
</TransitionCollection>
</ItemsControl.ItemContainerTransitions>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Margin="0,4,0,0" Style="{StaticResource BorderCardStyle}">
<StackPanel Margin="8">
<TextBlock Text="{Binding DisplayName}"/>
<ProgressBar
Margin="0,4,0,0"
Maximum="1"
Value="{Binding ProgressValue}"/>
<TextBlock
Opacity="0.6"
Style="{StaticResource CaptionTextBlockStyle}"
Text="{Binding Description}"/>
</StackPanel>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</ScrollViewer>
<Image
MaxWidth="640"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Source="ms-appx:///Resource/WelcomeView_Background.png"/>
</Grid>
</UserControl>

View File

@@ -1,32 +0,0 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Microsoft.UI.Xaml.Controls;
using Snap.Hutao.ViewModel.Guide;
namespace Snap.Hutao.View;
/// <summary>
/// 欢迎视图
/// </summary>
[HighQuality]
internal sealed partial class WelcomeView : UserControl
{
private readonly IServiceScope serviceScope;
/// <summary>
/// 构造一个新的欢迎视图
/// </summary>
public WelcomeView()
{
InitializeComponent();
serviceScope = Ioc.Default.CreateScope();
DataContext = serviceScope.ServiceProvider.GetRequiredService<WelcomeViewModel>();
}
private void OnUnloaded(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
DataContext = null;
serviceScope.Dispose();
}
}

View File

@@ -9,9 +9,24 @@ namespace Snap.Hutao.ViewModel.Guide;
internal enum GuideState : uint
{
/// <summary>
/// 尚未开始
/// 正在选择语言
/// </summary>
None,
Language,
/// <summary>
/// 正在查看文档与隐私政策
/// </summary>
Document,
/// <summary>
/// 正在查看环境配置
/// </summary>
Environment,
/// <summary>
/// 开始下载资源
/// </summary>
StaticResourceBegin,
/// <summary>
/// 完成

View File

@@ -1,16 +1,226 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using CommunityToolkit.Mvvm.Messaging;
using CommunityToolkit.WinUI.Notifications;
using Microsoft.Windows.AppLifecycle;
using Snap.Hutao.Core;
using Snap.Hutao.Core.Setting;
using Snap.Hutao.Model;
using Snap.Hutao.Service;
using System.Collections.ObjectModel;
using System.Globalization;
namespace Snap.Hutao.ViewModel.Guide;
/// <summary>
/// 指引视图模型
/// </summary>
[Injection(InjectAs.Transient)]
internal sealed class GuideViewModel : Abstraction.ViewModel
[ConstructorGenerated]
[Injection(InjectAs.Singleton)]
internal sealed partial class GuideViewModel : Abstraction.ViewModel
{
protected override Task OpenUIAsync()
private readonly IServiceProvider serviceProvider;
private readonly ITaskContext taskContext;
private readonly AppOptions appOptions;
private readonly RuntimeOptions runtimeOptions;
private string nextOrCompleteButtonText = SH.ViewModelGuideActionNext;
private bool isNextOrCompleteButtonEnabled = true;
private NameValue<string>? selectedCulture;
private bool isTermOfServiceAgreed;
private bool isPrivacyPolicyAgreed;
private bool isIssueReportAgreed;
private bool isOpenSourceLicenseAgreed;
private ObservableCollection<DownloadSummary>? downloadSummaries;
public uint State
{
throw new NotImplementedException();
get
{
uint value = LocalSetting.Get(SettingKeys.Major1Minor7Revision0GuideState, 0U);
GuideState state = (GuideState)value;
if (state is GuideState.Document)
{
IsTermOfServiceAgreed = false;
IsPrivacyPolicyAgreed = false;
IsIssueReportAgreed = false;
IsOpenSourceLicenseAgreed = false;
(NextOrCompleteButtonText, IsNextOrCompleteButtonEnabled) = (SH.ViewModelGuideActionNext, false);
}
else if (state is GuideState.StaticResourceBegin)
{
(NextOrCompleteButtonText, IsNextOrCompleteButtonEnabled) = (SH.ViewModelGuideActionStaticResourceBegin, false);
DownloadStaticResourceAsync().SafeForget();
}
else if (state is GuideState.Completed)
{
(NextOrCompleteButtonText, IsNextOrCompleteButtonEnabled) = (SH.ViewModelGuideActionComplete, true);
}
else
{
(NextOrCompleteButtonText, IsNextOrCompleteButtonEnabled) = (SH.ViewModelGuideActionNext, true);
}
return value;
}
set
{
LocalSetting.Set(SettingKeys.Major1Minor7Revision0GuideState, value);
OnPropertyChanged();
}
}
public string NextOrCompleteButtonText { get => nextOrCompleteButtonText; set => SetProperty(ref nextOrCompleteButtonText, value); }
public bool IsNextOrCompleteButtonEnabled { get => isNextOrCompleteButtonEnabled; set => SetProperty(ref isNextOrCompleteButtonEnabled, value); }
public AppOptions AppOptions { get => appOptions; }
public RuntimeOptions RuntimeOptions { get => runtimeOptions; }
public NameValue<string>? SelectedCulture
{
get => selectedCulture ??= AppOptions.Cultures.FirstOrDefault(c => c.Value == AppOptions.CurrentCulture.Name);
set
{
if (SetProperty(ref selectedCulture, value) && value is not null)
{
AppOptions.CurrentCulture = CultureInfo.GetCultureInfo(value.Value);
++State;
AppInstance.Restart(string.Empty);
}
}
}
public bool IsTermOfServiceAgreed
{
get => isTermOfServiceAgreed; set
{
if (SetProperty(ref isTermOfServiceAgreed, value))
{
OnAgreeSateChanged();
}
}
}
public bool IsPrivacyPolicyAgreed
{
get => isPrivacyPolicyAgreed; set
{
if (SetProperty(ref isPrivacyPolicyAgreed, value))
{
OnAgreeSateChanged();
}
}
}
public bool IsIssueReportAgreed
{
get => isIssueReportAgreed; set
{
if (SetProperty(ref isIssueReportAgreed, value))
{
OnAgreeSateChanged();
}
}
}
public bool IsOpenSourceLicenseAgreed
{
get => isOpenSourceLicenseAgreed; set
{
if (SetProperty(ref isOpenSourceLicenseAgreed, value))
{
OnAgreeSateChanged();
}
}
}
/// <summary>
/// 下载信息
/// </summary>
public ObservableCollection<DownloadSummary>? DownloadSummaries { get => downloadSummaries; set => SetProperty(ref downloadSummaries, value); }
protected override ValueTask<bool> InitializeUIAsync()
{
return ValueTask.FromResult(true);
}
[Command("NextOrCompleteCommand")]
private void NextOrComplete()
{
++State;
}
private void OnAgreeSateChanged()
{
IsNextOrCompleteButtonEnabled = IsTermOfServiceAgreed && IsPrivacyPolicyAgreed && IsIssueReportAgreed && IsOpenSourceLicenseAgreed;
}
private async ValueTask DownloadStaticResourceAsync()
{
IEnumerable<DownloadSummary> downloadSummaries = GenerateStaticResourceDownloadTasks();
DownloadSummaries = downloadSummaries.ToObservableCollection();
await Parallel.ForEachAsync(downloadSummaries, async (summary, token) =>
{
if (await summary.DownloadAndExtractAsync().ConfigureAwait(false))
{
taskContext.InvokeOnMainThread(() => DownloadSummaries.Remove(summary));
}
}).ConfigureAwait(false);
StaticResource.FulfillAllContracts();
LocalSetting.Set(SettingKeys.Major1Minor7Revision0GuideState, (uint)GuideState.Completed);
AppInstance.Restart(string.Empty);
}
private IEnumerable<DownloadSummary> GenerateStaticResourceDownloadTasks()
{
Dictionary<string, DownloadSummary> downloadSummaries = new();
if (StaticResource.IsContractUnfulfilled(StaticResource.V1Contract))
{
downloadSummaries.TryAdd("Bg", new(serviceProvider, "Bg"));
downloadSummaries.TryAdd("AvatarIcon", new(serviceProvider, "AvatarIcon"));
downloadSummaries.TryAdd("GachaAvatarIcon", new(serviceProvider, "GachaAvatarIcon"));
downloadSummaries.TryAdd("GachaAvatarImg", new(serviceProvider, "GachaAvatarImg"));
downloadSummaries.TryAdd("EquipIcon", new(serviceProvider, "EquipIcon"));
downloadSummaries.TryAdd("GachaEquipIcon", new(serviceProvider, "GachaEquipIcon"));
downloadSummaries.TryAdd("NameCardPic", new(serviceProvider, "NameCardPic"));
downloadSummaries.TryAdd("Skill", new(serviceProvider, "Skill"));
downloadSummaries.TryAdd("Talent", new(serviceProvider, "Talent"));
}
if (StaticResource.IsContractUnfulfilled(StaticResource.V2Contract))
{
downloadSummaries.TryAdd("AchievementIcon", new(serviceProvider, "AchievementIcon"));
downloadSummaries.TryAdd("ItemIcon", new(serviceProvider, "ItemIcon"));
downloadSummaries.TryAdd("IconElement", new(serviceProvider, "IconElement"));
downloadSummaries.TryAdd("RelicIcon", new(serviceProvider, "RelicIcon"));
}
if (StaticResource.IsContractUnfulfilled(StaticResource.V3Contract))
{
downloadSummaries.TryAdd("Skill", new(serviceProvider, "Skill"));
downloadSummaries.TryAdd("Talent", new(serviceProvider, "Talent"));
}
if (StaticResource.IsContractUnfulfilled(StaticResource.V4Contract))
{
downloadSummaries.TryAdd("AvatarIcon", new(serviceProvider, "AvatarIcon"));
}
if (StaticResource.IsContractUnfulfilled(StaticResource.V5Contract))
{
downloadSummaries.TryAdd("MonsterIcon", new(serviceProvider, "MonsterIcon"));
}
return downloadSummaries.Select(x => x.Value);
}
}

View File

@@ -1,101 +0,0 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Messaging;
using CommunityToolkit.WinUI.Notifications;
using Snap.Hutao.Core.Setting;
using System.Collections.ObjectModel;
namespace Snap.Hutao.ViewModel.Guide;
/// <summary>
/// 欢迎视图模型
/// </summary>
[HighQuality]
[ConstructorGenerated]
[Injection(InjectAs.Scoped)]
internal sealed partial class WelcomeViewModel : ObservableObject
{
[SuppressMessage("", "SH301")]
private readonly IServiceProvider serviceProvider;
private readonly ITaskContext taskContext;
private readonly IMessenger messenger;
private ObservableCollection<DownloadSummary>? downloadSummaries;
/// <summary>
/// 下载信息
/// </summary>
public ObservableCollection<DownloadSummary>? DownloadSummaries { get => downloadSummaries; set => SetProperty(ref downloadSummaries, value); }
[Command("OpenUICommand")]
private async Task OpenUIAsync()
{
IEnumerable<DownloadSummary> downloadSummaries = GenerateStaticResourceDownloadTasks();
DownloadSummaries = downloadSummaries.ToObservableCollection();
await Parallel.ForEachAsync(downloadSummaries, async (summary, token) =>
{
if (await summary.DownloadAndExtractAsync().ConfigureAwait(false))
{
taskContext.InvokeOnMainThread(() => DownloadSummaries.Remove(summary));
}
}).ConfigureAwait(false);
StaticResource.FulfillAllContracts();
await taskContext.SwitchToMainThreadAsync();
messenger.Send(new Message.WelcomeStateCompleteMessage());
new ToastContentBuilder()
.AddText(SH.ViewModelWelcomeDownloadCompleteTitle)
.AddText(SH.ViewModelWelcomeDownloadCompleteMessage)
.Show();
}
private IEnumerable<DownloadSummary> GenerateStaticResourceDownloadTasks()
{
Dictionary<string, DownloadSummary> downloadSummaries = new();
if (StaticResource.IsContractUnfulfilled(StaticResource.V1Contract))
{
downloadSummaries.TryAdd("Bg", new(serviceProvider, "Bg"));
downloadSummaries.TryAdd("AvatarIcon", new(serviceProvider, "AvatarIcon"));
downloadSummaries.TryAdd("GachaAvatarIcon", new(serviceProvider, "GachaAvatarIcon"));
downloadSummaries.TryAdd("GachaAvatarImg", new(serviceProvider, "GachaAvatarImg"));
downloadSummaries.TryAdd("EquipIcon", new(serviceProvider, "EquipIcon"));
downloadSummaries.TryAdd("GachaEquipIcon", new(serviceProvider, "GachaEquipIcon"));
downloadSummaries.TryAdd("NameCardPic", new(serviceProvider, "NameCardPic"));
downloadSummaries.TryAdd("Skill", new(serviceProvider, "Skill"));
downloadSummaries.TryAdd("Talent", new(serviceProvider, "Talent"));
}
if (StaticResource.IsContractUnfulfilled(StaticResource.V2Contract))
{
downloadSummaries.TryAdd("AchievementIcon", new(serviceProvider, "AchievementIcon"));
downloadSummaries.TryAdd("ItemIcon", new(serviceProvider, "ItemIcon"));
downloadSummaries.TryAdd("IconElement", new(serviceProvider, "IconElement"));
downloadSummaries.TryAdd("RelicIcon", new(serviceProvider, "RelicIcon"));
}
if (StaticResource.IsContractUnfulfilled(StaticResource.V3Contract))
{
downloadSummaries.TryAdd("Skill", new(serviceProvider, "Skill"));
downloadSummaries.TryAdd("Talent", new(serviceProvider, "Talent"));
}
if (StaticResource.IsContractUnfulfilled(StaticResource.V4Contract))
{
downloadSummaries.TryAdd("AvatarIcon", new(serviceProvider, "AvatarIcon"));
}
if (StaticResource.IsContractUnfulfilled(StaticResource.V5Contract))
{
downloadSummaries.TryAdd("MonsterIcon", new(serviceProvider, "MonsterIcon"));
}
return downloadSummaries.Select(x => x.Value);
}
}

View File

@@ -19,6 +19,7 @@ using Snap.Hutao.Service.Navigation;
using Snap.Hutao.Service.Notification;
using Snap.Hutao.Service.User;
using Snap.Hutao.View.Dialog;
using Snap.Hutao.ViewModel.Guide;
using System.Globalization;
using System.IO;
using System.Runtime.InteropServices;
@@ -99,6 +100,7 @@ internal sealed partial class SettingViewModel : Abstraction.ViewModel
private static void ResetStaticResource()
{
StaticResource.FailAllContracts();
LocalSetting.Set(SettingKeys.Major1Minor7Revision0GuideState, (uint)GuideState.StaticResourceBegin);
AppInstance.Restart(string.Empty);
}

View File

@@ -1,7 +1,8 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Microsoft.Windows.AppLifecycle;
using Snap.Hutao.Core.Setting;
using Snap.Hutao.ViewModel.Guide;
namespace Snap.Hutao.ViewModel;
@@ -19,9 +20,10 @@ internal sealed partial class TestViewModel : Abstraction.ViewModel
return Task.CompletedTask;
}
[Command("RestartAppCommand")]
private static void RestartApp(bool elevated)
[Command("ResetGuideStateCommand")]
private static void ResetGuideState()
{
AppInstance.Restart(string.Empty);
LocalSetting.Set(SettingKeys.Major1Minor7Revision0GuideState, (uint)GuideState.Language);
}
}