refine dailynote UI & fix transformer not obtained desc

This commit is contained in:
DismissedLight
2023-08-23 22:54:54 +08:00
parent b6080c45c2
commit 9259f173b5
11 changed files with 444 additions and 348 deletions

View File

@@ -5730,6 +5730,24 @@ namespace Snap.Hutao.Resource.Localization {
}
}
/// <summary>
/// 查找类似 尚未获得 的本地化字符串。
/// </summary>
internal static string WebDailyNoteTransformerNotObtained {
get {
return ResourceManager.GetString("WebDailyNoteTransformerNotObtained", resourceCulture);
}
}
/// <summary>
/// 查找类似 尚未获得参量质变仪 的本地化字符串。
/// </summary>
internal static string WebDailyNoteTransformerNotObtainedDetail {
get {
return ResourceManager.GetString("WebDailyNoteTransformerNotObtainedDetail", resourceCulture);
}
}
/// <summary>
/// 查找类似 冷却中 的本地化字符串。
/// </summary>

View File

@@ -2063,6 +2063,12 @@
<data name="WebDailyNoteTransformerMinutesFormat" xml:space="preserve">
<value>{0} 分</value>
</data>
<data name="WebDailyNoteTransformerNotObtained" xml:space="preserve">
<value>尚未获得</value>
</data>
<data name="WebDailyNoteTransformerNotObtainedDetail" xml:space="preserve">
<value>尚未获得参量质变仪</value>
</data>
<data name="WebDailyNoteTransformerNotReached" xml:space="preserve">
<value>冷却中</value>
</data>

View File

@@ -1,6 +1,7 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Snap.Hutao.Model.Entity;
using Snap.Hutao.ViewModel.User;
using Snap.Hutao.Web.Hoyolab;
using Snap.Hutao.Web.Hoyolab.Takumi.Binding;
@@ -57,15 +58,12 @@ internal interface IUserService
/// <returns>是否刷新成功</returns>
ValueTask<bool> RefreshCookieTokenAsync(BindingUser user);
ValueTask<bool> RefreshCookieTokenAsync(Model.Entity.User user);
/// <summary>
/// 异步移除用户
/// </summary>
/// <param name="user">待移除的用户</param>
/// <returns>任务</returns>
ValueTask RemoveUserAsync(BindingUser user);
}
internal interface IUserServiceUnsafe
{
ValueTask UnsafeRemoveUsersAsync();
}

View File

@@ -0,0 +1,9 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Service.User;
internal interface IUserServiceUnsafe
{
ValueTask UnsafeRemoveUsersAsync();
}

View File

@@ -161,13 +161,18 @@ internal sealed partial class UserService : IUserService, IUserServiceUnsafe
}
/// <inheritdoc/>
public async ValueTask<bool> RefreshCookieTokenAsync(BindingUser user)
public ValueTask<bool> RefreshCookieTokenAsync(BindingUser user)
{
return RefreshCookieTokenAsync(user.Entity);
}
public async ValueTask<bool> RefreshCookieTokenAsync(Model.Entity.User user)
{
// TODO: 提醒其他组件此用户的Cookie已更改
Response<UidCookieToken> cookieTokenResponse = await serviceProvider
.GetRequiredService<IOverseaSupportFactory<IPassportClient>>()
.Create(user.Entity.IsOversea)
.GetCookieAccountInfoBySTokenAsync(user.Entity)
.Create(user.IsOversea)
.GetCookieAccountInfoBySTokenAsync(user)
.ConfigureAwait(false);
if (cookieTokenResponse.IsOk())
@@ -179,7 +184,7 @@ internal sealed partial class UserService : IUserService, IUserServiceUnsafe
// Sync ui and database
user.CookieToken[Cookie.COOKIE_TOKEN] = cookieToken;
await userDbService.UpdateUserAsync(user.Entity).ConfigureAwait(false);
await userDbService.UpdateUserAsync(user).ConfigureAwait(false);
return true;
}

View File

@@ -103,334 +103,362 @@
</Flyout>
</AppBarButton.Flyout>
</AppBarButton>
<AppBarButton Icon="{shcm:FontIcon Glyph={StaticResource FontIconContentSetting}}" Label="{shcm:ResourceString Name=ViewPageDailyNoteNotificationSetting}">
<AppBarButton.Flyout>
<Flyout Placement="BottomEdgeAlignedRight">
<StackPanel>
<RadioButtons ItemsSource="{Binding Options.RefreshTimes}" SelectedItem="{Binding Options.SelectedRefreshTime, Mode=TwoWay}">
<RadioButtons.Header>
<TextBlock Style="{StaticResource BaseTextBlockStyle}" Text="{shcm:ResourceString Name=ViewPageDailyNoteRefreshTime}"/>
</RadioButtons.Header>
<RadioButtons.ItemTemplate>
<DataTemplate>
<TextBlock Margin="0,0,0,0" Text="{Binding Name}"/>
</DataTemplate>
</RadioButtons.ItemTemplate>
</RadioButtons>
<StackPanel Spacing="{StaticResource SettingsCardSpacing}">
<StackPanel.Resources>
<x:Double x:Key="SettingsCardMinHeight">0</x:Double>
<x:Double x:Key="SettingsCardWrapThreshold">0</x:Double>
<x:Double x:Key="SettingsCardWrapNoIconThreshold">0</x:Double>
</StackPanel.Resources>
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" Text="{shcm:ResourceString Name=ViewPageDailyNoteNotificationHeader}"/>
<cwc:SettingsCard
Description="{shcm:ResourceString Name=ViewPageDailyNoteSlientModeDescription}"
Header="{shcm:ResourceString Name=ViewPageDailyNoteSlientModeHeader}"
HeaderIcon="{shcm:FontIcon Glyph=&#xE7ED;}">
<ToggleSwitch Margin="24,0,0,0" IsOn="{Binding Options.IsSilentWhenPlayingGame, Mode=TwoWay}"/>
</cwc:SettingsCard>
<cwc:SettingsCard
Description="{shcm:ResourceString Name=ViewPageDailyNoteReminderDescription}"
Header="{shcm:ResourceString Name=ViewPageDailyNoteReminderHeader}"
HeaderIcon="{shcm:FontIcon Glyph=&#xEA8F;}">
<ToggleSwitch Margin="24,0,0,0" IsOn="{Binding Options.IsReminderNotification, Mode=TwoWay}"/>
</cwc:SettingsCard>
</StackPanel>
</StackPanel>
</Flyout>
</AppBarButton.Flyout>
</AppBarButton>
<AppBarToggleButton
Icon="{shcm:FontIcon Glyph={StaticResource FontIconContentSetting}}"
IsChecked="{x:Bind SettingPaneSplitView.IsPaneOpen, Mode=TwoWay}"
Label="{shcm:ResourceString Name=ViewPageDailyNoteNotificationSetting}"/>
</CommandBar>
<ScrollViewer Grid.Row="1">
<cwuc:AdaptiveGridView
Margin="16,16,4,-4"
cwa:ItemsReorderAnimation.Duration="0:0:0.1"
DesiredWidth="280"
ItemContainerStyle="{StaticResource LargeGridViewItemStyle}"
ItemsSource="{Binding DailyNoteEntries}"
SelectionMode="None"
StretchContentForSingleRow="False">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Padding="8" Style="{StaticResource BorderGridStyle}">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<SplitView
x:Name="SettingPaneSplitView"
Grid.Row="1"
OpenPaneLength="480"
PaneBackground="{ThemeResource SystemControlAcrylicElementMediumHighBrush}"
PanePlacement="Right">
<SplitView.Pane>
<ScrollViewer Padding="16">
<StackPanel>
<RadioButtons ItemsSource="{Binding Options.RefreshTimes}" SelectedItem="{Binding Options.SelectedRefreshTime, Mode=TwoWay}">
<RadioButtons.Header>
<TextBlock Style="{StaticResource BaseTextBlockStyle}" Text="{shcm:ResourceString Name=ViewPageDailyNoteRefreshTime}"/>
</RadioButtons.Header>
<RadioButtons.ItemTemplate>
<DataTemplate>
<TextBlock Margin="0,0,0,0" Text="{Binding Name}"/>
</DataTemplate>
</RadioButtons.ItemTemplate>
</RadioButtons>
<StackPanel Spacing="{StaticResource SettingsCardSpacing}">
<StackPanel.Resources>
<x:Double x:Key="SettingsCardMinHeight">0</x:Double>
<x:Double x:Key="SettingsCardWrapThreshold">0</x:Double>
<x:Double x:Key="SettingsCardWrapNoIconThreshold">0</x:Double>
</StackPanel.Resources>
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" Text="{shcm:ResourceString Name=ViewPageDailyNoteNotificationHeader}"/>
<cwc:SettingsCard
Description="{shcm:ResourceString Name=ViewPageDailyNoteSlientModeDescription}"
Header="{shcm:ResourceString Name=ViewPageDailyNoteSlientModeHeader}"
HeaderIcon="{shcm:FontIcon Glyph=&#xE7ED;}">
<ToggleSwitch Margin="24,0,0,0" IsOn="{Binding Options.IsSilentWhenPlayingGame, Mode=TwoWay}"/>
</cwc:SettingsCard>
<cwc:SettingsCard
Description="{shcm:ResourceString Name=ViewPageDailyNoteReminderDescription}"
Header="{shcm:ResourceString Name=ViewPageDailyNoteReminderHeader}"
HeaderIcon="{shcm:FontIcon Glyph=&#xEA8F;}">
<ToggleSwitch Margin="24,0,0,0" IsOn="{Binding Options.IsReminderNotification, Mode=TwoWay}"/>
</cwc:SettingsCard>
</StackPanel>
</StackPanel>
</ScrollViewer>
</SplitView.Pane>
<ScrollViewer>
<cwuc:AdaptiveGridView
Margin="16,16,4,-4"
cwa:ItemsReorderAnimation.Duration="0:0:0.1"
DesiredWidth="280"
ItemContainerStyle="{StaticResource LargeGridViewItemStyle}"
ItemsSource="{Binding DailyNoteEntries}"
SelectionMode="None"
StretchContentForSingleRow="False">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Padding="8" Style="{StaticResource BorderGridStyle}">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Grid.Resources>
<Storyboard x:Name="ButtonPanelVisibleStoryboard">
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ButtonPanel" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<Grid.Resources>
<Storyboard x:Name="ButtonPanelVisibleStoryboard">
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ButtonPanel" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Name="ButtonPanelCollapsedStoryboard">
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ButtonPanel" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</Grid.Resources>
<Storyboard x:Name="ButtonPanelCollapsedStoryboard">
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ButtonPanel" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</Grid.Resources>
<mxi:Interaction.Behaviors>
<mxic:EventTriggerBehavior EventName="PointerEntered">
<mxim:ControlStoryboardAction Storyboard="{StaticResource ButtonPanelVisibleStoryboard}"/>
</mxic:EventTriggerBehavior>
<mxic:EventTriggerBehavior EventName="PointerExited">
<mxim:ControlStoryboardAction Storyboard="{StaticResource ButtonPanelCollapsedStoryboard}"/>
</mxic:EventTriggerBehavior>
</mxi:Interaction.Behaviors>
<mxi:Interaction.Behaviors>
<mxic:EventTriggerBehavior EventName="PointerEntered">
<mxim:ControlStoryboardAction Storyboard="{StaticResource ButtonPanelVisibleStoryboard}"/>
</mxic:EventTriggerBehavior>
<mxic:EventTriggerBehavior EventName="PointerExited">
<mxim:ControlStoryboardAction Storyboard="{StaticResource ButtonPanelCollapsedStoryboard}"/>
</mxic:EventTriggerBehavior>
</mxi:Interaction.Behaviors>
<Grid MinHeight="40" HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<TextBlock
Grid.Column="0"
Margin="4,0,0,4"
VerticalAlignment="Center"
Style="{StaticResource BaseTextBlockStyle}"
Text="{Binding UserGameRole}"
TextTrimming="CharacterEllipsis"
TextWrapping="NoWrap"/>
<StackPanel
x:Name="ButtonPanel"
Grid.Column="1"
HorizontalAlignment="Right"
Orientation="Horizontal"
Visibility="Collapsed">
<Button
MinHeight="36.8"
Margin="8,0,0,0"
<Grid MinHeight="40" HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<TextBlock
Grid.Column="0"
Margin="4,2,0,4"
VerticalAlignment="Center"
Style="{StaticResource BaseTextBlockStyle}"
Text="{Binding UserGameRole}"
TextTrimming="CharacterEllipsis"
TextWrapping="NoWrap"/>
<StackPanel
x:Name="ButtonPanel"
Grid.Column="1"
HorizontalAlignment="Right"
VerticalAlignment="Stretch"
Background="Transparent"
BorderBrush="{x:Null}"
BorderThickness="0"
Command="{Binding DataContext.RemoveDailyNoteCommand, Source={StaticResource ViewModelBindingProxy}}"
CommandParameter="{Binding}"
Content="{StaticResource FontIconContentDelete}"
FontFamily="{StaticResource SymbolThemeFontFamily}"
ToolTipService.ToolTip="{shcm:ResourceString Name=ViewPageDailyNoteRemoveToolTip}"/>
<Button
MinHeight="36.8"
Margin="8,0,0,0"
VerticalAlignment="Stretch"
Background="Transparent"
BorderBrush="{x:Null}"
BorderThickness="0"
Command="{Binding DataContext.ModifyNotificationCommand, Source={StaticResource ViewModelBindingProxy}}"
CommandParameter="{Binding}"
Content="{StaticResource FontIconContentSetting}"
FontFamily="{StaticResource SymbolThemeFontFamily}"
ToolTipService.ToolTip="{shcm:ResourceString Name=ViewPageDailyNoteNotificationSetting}"/>
</StackPanel>
</Grid>
Orientation="Horizontal"
Visibility="Collapsed">
<Button
Margin="8,0,0,0"
HorizontalAlignment="Right"
VerticalAlignment="Stretch"
shvh:FrameworkElementHelper.SquareLength="40"
Background="Transparent"
BorderBrush="{x:Null}"
BorderThickness="0"
Command="{Binding DataContext.RemoveDailyNoteCommand, Source={StaticResource ViewModelBindingProxy}}"
CommandParameter="{Binding}"
Content="{StaticResource FontIconContentDelete}"
FontFamily="{StaticResource SymbolThemeFontFamily}"
ToolTipService.ToolTip="{shcm:ResourceString Name=ViewPageDailyNoteRemoveToolTip}"/>
<Button
Margin="8,0,0,0"
VerticalAlignment="Stretch"
shvh:FrameworkElementHelper.SquareLength="40"
Background="Transparent"
BorderBrush="{x:Null}"
BorderThickness="0"
Command="{Binding DataContext.ModifyNotificationCommand, Source={StaticResource ViewModelBindingProxy}}"
CommandParameter="{Binding}"
Content="{StaticResource FontIconContentSetting}"
FontFamily="{StaticResource SymbolThemeFontFamily}"
ToolTipService.ToolTip="{shcm:ResourceString Name=ViewPageDailyNoteNotificationSetting}"/>
</StackPanel>
</Grid>
<StackPanel
Grid.Row="1"
Margin="0,8,0,0"
Spacing="12">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid
Grid.Column="0"
Width="40"
Height="40"
VerticalAlignment="Center">
<Image Width="32" Source="ms-appx:///Resource/Icon/UI_ItemIcon_210.png"/>
<ProgressRing
Width="40"
<StackPanel
Grid.Row="1"
Margin="0,8,0,0"
Spacing="6">
<Grid Style="{ThemeResource BorderGridStyle}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<ProgressBar
Grid.ColumnSpan="2"
Height="40"
Background="{StaticResource CardBackgroundFillColorDefaultBrush}"
IsIndeterminate="False"
MinHeight="48"
Background="{x:Null}"
CornerRadius="{ThemeResource ControlCornerRadius}"
Maximum="{Binding DailyNote.MaxResin, Mode=OneWay}"
Opacity="{StaticResource LargeBackgroundProgressBarOpacity}"
Value="{Binding DailyNote.CurrentResin, Mode=OneWay}"/>
<shci:CachedImage
Grid.Column="0"
Margin="4"
VerticalAlignment="Center"
shvh:FrameworkElementHelper.SquareLength="32"
Source="{StaticResource UI_ItemIcon_210}"/>
<StackPanel
Grid.Column="1"
Margin="8,0,0,0"
VerticalAlignment="Center">
<TextBlock Style="{StaticResource SubtitleTextBlockStyle}" Text="{Binding DailyNote.ResinFormatted, Mode=OneWay}"/>
<TextBlock
Opacity="0.6"
Style="{StaticResource CaptionTextBlockStyle}"
Text="{Binding DailyNote.ResinRecoveryTargetTime, Mode=OneWay}"/>
</StackPanel>
</Grid>
<StackPanel Grid.Column="1" Margin="12,0,0,0">
<TextBlock Style="{StaticResource SubtitleTextBlockStyle}" Text="{Binding DailyNote.ResinFormatted, Mode=OneWay}"/>
<TextBlock
Opacity="0.6"
Style="{StaticResource CaptionTextBlockStyle}"
Text="{Binding DailyNote.ResinRecoveryTargetTime, Mode=OneWay}"/>
</StackPanel>
</Grid>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid
Grid.Column="0"
Width="40"
Height="40"
VerticalAlignment="Center">
<shci:CachedImage Width="32" Source="{StaticResource UI_ItemIcon_204}"/>
<ProgressRing
Width="40"
<Grid Style="{ThemeResource BorderGridStyle}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<ProgressBar
Grid.ColumnSpan="2"
Height="40"
Background="{StaticResource CardBackgroundFillColorDefaultBrush}"
IsIndeterminate="False"
MinHeight="48"
Background="{x:Null}"
CornerRadius="{ThemeResource ControlCornerRadius}"
Maximum="{Binding DailyNote.MaxHomeCoin, Mode=OneWay}"
Opacity="{StaticResource LargeBackgroundProgressBarOpacity}"
Value="{Binding DailyNote.CurrentHomeCoin, Mode=OneWay}"/>
<shci:CachedImage
Grid.Column="0"
Margin="4"
VerticalAlignment="Center"
shvh:FrameworkElementHelper.SquareLength="32"
Source="{StaticResource UI_ItemIcon_204}"/>
<StackPanel
Grid.Column="1"
Margin="8,0,0,0"
VerticalAlignment="Center">
<TextBlock Style="{StaticResource SubtitleTextBlockStyle}" Text="{Binding DailyNote.HomeCoinFormatted, Mode=OneWay}"/>
<TextBlock
Opacity="0.6"
Style="{StaticResource CaptionTextBlockStyle}"
Text="{Binding DailyNote.HomeCoinRecoveryTargetTimeFormatted, Mode=OneWay}"/>
</StackPanel>
</Grid>
<StackPanel Grid.Column="1" Margin="12,0,0,0">
<TextBlock Style="{StaticResource SubtitleTextBlockStyle}" Text="{Binding DailyNote.HomeCoinFormatted, Mode=OneWay}"/>
<TextBlock
Opacity="0.6"
Style="{StaticResource CaptionTextBlockStyle}"
Text="{Binding DailyNote.HomeCoinRecoveryTargetTimeFormatted, Mode=OneWay}"/>
</StackPanel>
</Grid>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid
Grid.Column="0"
Width="40"
Height="40"
VerticalAlignment="Center">
<Image Width="32" Source="ms-appx:///Resource/Icon/UI_MarkQuest_Events_Proce.png"/>
<ProgressRing
Width="40"
<Grid Style="{ThemeResource BorderGridStyle}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<ProgressBar
Grid.ColumnSpan="2"
Height="40"
Background="{StaticResource CardBackgroundFillColorDefaultBrush}"
IsIndeterminate="False"
MinHeight="48"
Background="{x:Null}"
CornerRadius="{ThemeResource ControlCornerRadius}"
Maximum="{Binding DailyNote.TotalTaskNum, Mode=OneWay}"
Opacity="{StaticResource LargeBackgroundProgressBarOpacity}"
Value="{Binding DailyNote.FinishedTaskNum, Mode=OneWay}"/>
<shci:CachedImage
Grid.Column="0"
Margin="4"
VerticalAlignment="Center"
shvh:FrameworkElementHelper.SquareLength="32"
Source="{StaticResource UI_MarkQuest_Events_Proce}"/>
<StackPanel
Grid.Column="1"
Margin="8,0,0,0"
VerticalAlignment="Center">
<TextBlock Style="{StaticResource SubtitleTextBlockStyle}" Text="{Binding DailyNote.TaskFormatted, Mode=OneWay}"/>
<TextBlock
Opacity="0.6"
Style="{StaticResource CaptionTextBlockStyle}"
Text="{Binding DailyNote.ExtraTaskRewardDescription, Mode=OneWay}"/>
</StackPanel>
</Grid>
<StackPanel Grid.Column="1" Margin="12,0,0,0">
<TextBlock Style="{StaticResource SubtitleTextBlockStyle}" Text="{Binding DailyNote.TaskFormatted, Mode=OneWay}"/>
<TextBlock
Opacity="0.6"
Style="{StaticResource CaptionTextBlockStyle}"
Text="{Binding DailyNote.ExtraTaskRewardDescription, Mode=OneWay}"/>
</StackPanel>
</Grid>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid
Grid.Column="0"
Width="40"
Height="40"
VerticalAlignment="Center">
<Image Width="32" Source="ms-appx:///Resource/Icon/UI_MarkTower.png"/>
<ProgressRing
Width="40"
<Grid Style="{ThemeResource BorderGridStyle}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<ProgressBar
Grid.ColumnSpan="2"
Height="40"
Background="{StaticResource CardBackgroundFillColorDefaultBrush}"
IsIndeterminate="False"
MinHeight="48"
Background="{x:Null}"
CornerRadius="{ThemeResource ControlCornerRadius}"
Maximum="{Binding DailyNote.ResinDiscountNumLimit, Mode=OneWay}"
Opacity="{StaticResource LargeBackgroundProgressBarOpacity}"
Value="{Binding DailyNote.ResinDiscountUsedNum, Mode=OneWay}"/>
<shci:CachedImage
Grid.Column="0"
Margin="4"
VerticalAlignment="Center"
shvh:FrameworkElementHelper.SquareLength="32"
Source="{StaticResource UI_MarkTower}"/>
<StackPanel
Grid.Column="1"
Margin="8,0,0,0"
VerticalAlignment="Center">
<TextBlock Style="{StaticResource SubtitleTextBlockStyle}" Text="{Binding DailyNote.ResinDiscountFormatted, Mode=OneWay}"/>
<TextBlock
Opacity="0.6"
Style="{StaticResource CaptionTextBlockStyle}"
Text="{shcm:ResourceString Name=ViewPageDailyNoteResinDiscountUsed}"/>
</StackPanel>
</Grid>
<StackPanel Grid.Column="1" Margin="12,0,0,0">
<TextBlock Style="{StaticResource SubtitleTextBlockStyle}" Text="{Binding DailyNote.ResinDiscountFormatted, Mode=OneWay}"/>
<TextBlock
Opacity="0.6"
Style="{StaticResource CaptionTextBlockStyle}"
Text="{shcm:ResourceString Name=ViewPageDailyNoteResinDiscountUsed}"/>
</StackPanel>
</Grid>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid
Grid.Column="0"
Width="40"
Height="40">
<Image Width="32" Source="ms-appx:///Resource/Icon/UI_ItemIcon_220021.png"/>
<ProgressRing
Width="40"
<Grid Style="{ThemeResource BorderGridStyle}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<ProgressBar
Grid.ColumnSpan="2"
Height="40"
Background="{StaticResource CardBackgroundFillColorDefaultBrush}"
IsIndeterminate="False"
MinHeight="48"
Background="{x:Null}"
CornerRadius="{ThemeResource ControlCornerRadius}"
Maximum="604800"
Opacity="{StaticResource LargeBackgroundProgressBarOpacity}"
Value="{Binding DailyNote.Transformer.RecoveryTime.TotalSeconds, Mode=OneWay}"/>
<shci:CachedImage
Grid.Column="0"
Margin="4"
VerticalAlignment="Center"
shvh:FrameworkElementHelper.SquareLength="32"
Source="{StaticResource UI_ItemIcon_220021}"/>
<StackPanel
Grid.Column="1"
Margin="8,0,0,0"
VerticalAlignment="Center">
<TextBlock Style="{StaticResource SubtitleTextBlockStyle}" Text="{Binding DailyNote.Transformer.ObtainedAndReachedFormatted, Mode=OneWay}"/>
<TextBlock
Opacity="0.6"
Style="{StaticResource CaptionTextBlockStyle}"
Text="{Binding DailyNote.Transformer.ObtainedAndTimeFormatted, Mode=OneWay}"/>
</StackPanel>
</Grid>
<StackPanel Grid.Column="1" Margin="12,0,0,0">
<TextBlock Style="{StaticResource SubtitleTextBlockStyle}" Text="{Binding DailyNote.Transformer.RecoveryTime.ReachedFormatted, Mode=OneWay}"/>
<TextBlock
Opacity="0.6"
Style="{StaticResource CaptionTextBlockStyle}"
Text="{Binding DailyNote.Transformer.RecoveryTime.TimeFormatted, Mode=OneWay}"/>
</StackPanel>
</StackPanel>
</Grid>
</StackPanel>
<MenuFlyoutSeparator Grid.Row="2" Margin="6,6,6,0"/>
<MenuFlyoutSeparator Grid.Row="2" Margin="8,16,8,0"/>
<ItemsControl
Grid.Row="3"
Margin="0,16,0,0"
ItemsSource="{Binding DailyNote.Expeditions, Mode=OneWay}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<cwuc:UniformGrid
ColumnSpacing="8"
Columns="2"
RowSpacing="8"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid
Grid.Column="0"
Width="40"
Height="40">
<ItemsControl
Grid.Row="3"
Margin="0,6,0,0"
ItemsSource="{Binding DailyNote.Expeditions, Mode=OneWay}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<cwuc:UniformGrid
ColumnSpacing="8"
Columns="2"
RowSpacing="8"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Style="{ThemeResource BorderGridStyle}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<ProgressBar
Grid.ColumnSpan="2"
MinHeight="40"
HorizontalAlignment="Stretch"
Background="{x:Null}"
CornerRadius="{ThemeResource ControlCornerRadius}"
Maximum="{Binding TotalTime, Mode=OneWay}"
Opacity="{StaticResource LargeBackgroundProgressBarOpacity}"
Value="{Binding PassedTime, Mode=OneWay}"/>
<shci:CachedImage
Margin="0,0,0,8"
shvh:FrameworkElementHelper.SquareLength="32"
Source="{Binding AvatarSideIcon, Mode=OneWay}"/>
<ProgressRing
shvh:FrameworkElementHelper.SquareLength="40"
Background="{StaticResource CardBackgroundFillColorDefaultBrush}"
IsIndeterminate="False"
Maximum="{Binding TotalTime, Mode=OneWay}"
Value="{Binding PassedTime, Mode=OneWay}"/>
<TextBlock
Grid.Column="1"
Margin="16,0,0,0"
VerticalAlignment="Center"
Style="{StaticResource BaseTextBlockStyle}"
Text="{Binding RemainedTimeFormatted, Mode=OneWay}"/>
</Grid>
<TextBlock
Grid.Column="1"
Margin="12,0,0,4"
VerticalAlignment="Center"
Style="{StaticResource BaseTextBlockStyle}"
Text="{Binding RemainedTimeFormatted, Mode=OneWay}"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</cwuc:AdaptiveGridView>
</ScrollViewer>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</cwuc:AdaptiveGridView>
</ScrollViewer>
</SplitView>
</Grid>
</shc:ScopedPage>

View File

@@ -25,8 +25,10 @@ namespace Snap.Hutao.ViewModel.Guide;
[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;
@@ -48,22 +50,16 @@ internal sealed partial class WelcomeViewModel : ObservableObject
{
taskContext.InvokeOnMainThread(() => DownloadSummaries.Remove(summary));
}
}).ConfigureAwait(true);
}).ConfigureAwait(false);
serviceProvider.GetRequiredService<IMessenger>().Send(new Message.WelcomeStateCompleteMessage());
messenger.Send(new Message.WelcomeStateCompleteMessage());
StaticResource.FulfillAllContracts();
try
{
new ToastContentBuilder()
.AddText(SH.ViewModelWelcomeDownloadCompleteTitle)
.AddText(SH.ViewModelWelcomeDownloadCompleteMessage)
.Show();
}
catch (COMException)
{
// 0x803E0105
}
await taskContext.SwitchToMainThreadAsync();
new ToastContentBuilder()
.AddText(SH.ViewModelWelcomeDownloadCompleteTitle)
.AddText(SH.ViewModelWelcomeDownloadCompleteMessage)
.Show();
}
private IEnumerable<DownloadSummary> GenerateStaticResourceDownloadTasks()

View File

@@ -2,7 +2,9 @@
// Licensed under the MIT license.
using Microsoft.Web.WebView2.Core;
using Snap.Hutao.Core.DependencyInjection.Abstraction;
using Snap.Hutao.Service;
using Snap.Hutao.Service.Metadata;
using Snap.Hutao.Service.User;
using Snap.Hutao.ViewModel.User;
using Snap.Hutao.Web.Bridge.Model;
@@ -10,8 +12,10 @@ using Snap.Hutao.Web.Hoyolab;
using Snap.Hutao.Web.Hoyolab.Bbs.User;
using Snap.Hutao.Web.Hoyolab.DynamicSecret;
using Snap.Hutao.Web.Hoyolab.Takumi.Auth;
using Snap.Hutao.Web.Response;
using System.Runtime.InteropServices;
using System.Text;
using Windows.Foundation;
namespace Snap.Hutao.Web.Bridge;
@@ -20,6 +24,7 @@ namespace Snap.Hutao.Web.Bridge;
/// </summary>
[HighQuality]
[SuppressMessage("", "CA1001")]
[SuppressMessage("", "CA1308")]
internal class MiHoYoJSInterface
{
private const string InitializeJsInterfaceScript2 = """
@@ -43,18 +48,27 @@ internal class MiHoYoJSInterface
private readonly ILogger<MiHoYoJSInterface> logger;
private readonly SemaphoreSlim webMessageSemaphore = new(1);
public MiHoYoJSInterface(IServiceProvider serviceProvider, CoreWebView2 webView, UserAndUid userAndUid)
private readonly TypedEventHandler<CoreWebView2, CoreWebView2WebMessageReceivedEventArgs> webMessageReceivedEventHandler;
private readonly TypedEventHandler<CoreWebView2, CoreWebView2DOMContentLoadedEventArgs> domContentLoadedEventHandler;
private readonly TypedEventHandler<CoreWebView2, CoreWebView2NavigationStartingEventArgs> navigationStartingEventHandler;
public MiHoYoJSInterface(CoreWebView2 webView, UserAndUid userAndUid)
{
this.serviceProvider = serviceProvider;
// 由于Webview2 的作用域特殊性,我们在此处直接使用根服务
serviceProvider = Ioc.Default;
this.webView = webView;
this.userAndUid = userAndUid;
taskContext = serviceProvider.GetRequiredService<ITaskContext>();
logger = serviceProvider.GetRequiredService<ILogger<MiHoYoJSInterface>>();
webView.WebMessageReceived += OnWebMessageReceived;
webView.DOMContentLoaded += OnDOMContentLoaded;
webView.NavigationStarting += OnNavigationStarting;
webMessageReceivedEventHandler = OnWebMessageReceived;
domContentLoadedEventHandler = OnDOMContentLoaded;
navigationStartingEventHandler = OnNavigationStarting;
webView.WebMessageReceived += webMessageReceivedEventHandler;
webView.DOMContentLoaded += domContentLoadedEventHandler;
webView.NavigationStarting += navigationStartingEventHandler;
}
public event Action? ClosePageRequested;
@@ -98,6 +112,7 @@ internal class MiHoYoJSInterface
public virtual JsResult<Dictionary<string, string>> GetCookieInfo(JsParam param)
{
ArgumentNullException.ThrowIfNull(userAndUid.User.LToken);
return new()
{
Data = new()
@@ -114,12 +129,12 @@ internal class MiHoYoJSInterface
/// </summary>
/// <param name="param">参数</param>
/// <returns>响应</returns>
[SuppressMessage("", "CA1308")]
public virtual JsResult<Dictionary<string, string>> GetDynamicSecrectV1(JsParam param)
{
string salt = HoyolabOptions.Salts[SaltType.LK2];
long t = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
string r = GetRandomString();
string check = Core.Convert.ToMd5HexString($"salt={salt}&t={t}&r={r}").ToLowerInvariant();
return new() { Data = new() { ["DS"] = $"{t},{r},{check}", }, };
@@ -145,7 +160,6 @@ internal class MiHoYoJSInterface
/// </summary>
/// <param name="param">参数</param>
/// <returns>响应</returns>
[SuppressMessage("", "CA1308")]
public virtual JsResult<Dictionary<string, string>> GetDynamicSecrectV2(JsParam<DynamicSecrect2Playload> param)
{
string salt = HoyolabOptions.Salts[SaltType.X4];
@@ -169,22 +183,33 @@ internal class MiHoYoJSInterface
/// </summary>
/// <param name="param">参数</param>
/// <returns>响应</returns>
public virtual JsResult<Dictionary<string, object>> GetUserInfo(JsParam param)
public virtual async ValueTask<JsResult<Dictionary<string, object>>> GetUserInfoAsync(JsParam param)
{
User user = serviceProvider.GetRequiredService<IUserService>().Current!;
UserInfo info = user.UserInfo!;
Response<UserFullInfoWrapper> response = await serviceProvider
.GetRequiredService<IOverseaSupportFactory<IUserClient>>()
.Create(userAndUid.User.IsOversea)
.GetUserFullInfoAsync(userAndUid.User)
.ConfigureAwait(false);
return new()
if (response.IsOk())
{
Data = new()
UserInfo info = response.Data.UserInfo;
return new()
{
["id"] = info.Uid,
["gender"] = info.Gender,
["nickname"] = info.Nickname,
["introduce"] = info.Introduce,
["avatar_url"] = info.AvatarUrl,
},
};
Data = new()
{
["id"] = info.Uid,
["gender"] = info.Gender,
["nickname"] = info.Nickname,
["introduce"] = info.Introduce,
["avatar_url"] = info.AvatarUrl,
},
};
}
else
{
return new();
}
}
/// <summary>
@@ -195,15 +220,16 @@ internal class MiHoYoJSInterface
public virtual async ValueTask<JsResult<Dictionary<string, string>>> GetCookieTokenAsync(JsParam<CookieTokenPayload> param)
{
IUserService userService = serviceProvider.GetRequiredService<IUserService>();
User user = userService.Current!;
if (param.Payload.ForceRefresh)
{
await userService.RefreshCookieTokenAsync(user).ConfigureAwait(false);
await userService.RefreshCookieTokenAsync(userAndUid.User).ConfigureAwait(false);
}
await taskContext.SwitchToMainThreadAsync();
webView.SetCookie(user.CookieToken, user.LToken);
return new() { Data = new() { [Cookie.COOKIE_TOKEN] = user.CookieToken![Cookie.COOKIE_TOKEN] } };
webView.SetCookie(userAndUid.User.CookieToken, userAndUid.User.LToken);
ArgumentNullException.ThrowIfNull(userAndUid.User.CookieToken);
return new() { Data = new() { [Cookie.COOKIE_TOKEN] = userAndUid.User.CookieToken[Cookie.COOKIE_TOKEN] } };
}
/// <summary>
@@ -260,14 +286,13 @@ internal class MiHoYoJSInterface
/// <returns>语言与时区</returns>
public virtual JsResult<Dictionary<string, string>> GetCurrentLocale(JsParam<PushPagePayload> param)
{
AppOptions appOptions = serviceProvider.GetRequiredService<AppOptions>();
MetadataOptions metadataOptions = serviceProvider.GetRequiredService<MetadataOptions>();
return new()
{
Data = new()
{
// TODO: replace with metadata options value
["language"] = appOptions.PreviousCulture.Name.ToLowerInvariant(),
["language"] = metadataOptions.LanguageCode,
["timeZone"] = "GMT+8",
},
};
@@ -331,7 +356,7 @@ internal class MiHoYoJSInterface
.Append('"')
.Append(callback)
.Append('"')
.AppendIf(payload != null, ',')
.AppendIf(!string.IsNullOrEmpty(payload), ',')
.Append(payload)
.Append(')')
.ToString();
@@ -356,14 +381,15 @@ internal class MiHoYoJSInterface
{
string message = args.TryGetWebMessageAsString();
logger.LogInformation("[OnRawMessage]\n{message}", message);
JsParam param = JsonSerializer.Deserialize<JsParam>(message)!;
JsParam? param = JsonSerializer.Deserialize<JsParam>(message);
ArgumentNullException.ThrowIfNull(param);
logger.LogInformation("[OnMessage]\nMethod : {method}\nPayload : {payload}\nCallback: {callback}", param.Method, param.Payload, param.Callback);
using (await webMessageSemaphore.EnterAsync().ConfigureAwait(false))
{
IJsResult? result = await TryGetJsResultFromJsParamAsync(param).ConfigureAwait(false);
if (result != null && param.Callback != null)
if (result is not null && param.Callback is not null)
{
await ExecuteCallbackScriptAsync(param.Callback, result.ToJson()).ConfigureAwait(false);
}
@@ -394,7 +420,7 @@ internal class MiHoYoJSInterface
"getDS2" => GetDynamicSecrectV2(param),
"getHTTPRequestHeaders" => GetHttpRequestHeader(param),
"getStatusBarHeight" => GetStatusBarHeight(param),
"getUserInfo" => GetUserInfo(param),
"getUserInfo" => await GetUserInfoAsync(param).ConfigureAwait(false),
"hideLoading" => null,
"login" => null,
"pushPage" => await PushPageAsync(param).ConfigureAwait(false),

View File

@@ -23,7 +23,7 @@ internal sealed class SignInJSInterfaceOversea : MiHoYoJSInterface
/// <inheritdoc cref="MiHoYoJSInterface(IServiceProvider, CoreWebView2)"/>
public SignInJSInterfaceOversea(CoreWebView2 webView, IServiceProvider serviceProvider, UserAndUid userAndUid)
: base(serviceProvider, webView, userAndUid)
: base(webView, userAndUid)
{
logger = serviceProvider.GetRequiredService<ILogger<MiHoYoJSInterface>>();
webView.DOMContentLoaded += OnDOMContentLoaded;

View File

@@ -16,7 +16,7 @@ internal sealed class SignInJsInterface : MiHoYoJSInterface
{
/// <inheritdoc cref="MiHoYoJSInterface(IServiceProvider, CoreWebView2)"/>
public SignInJsInterface(CoreWebView2 webView, IServiceProvider serviceProvider, UserAndUid userAndUid)
: base(serviceProvider, webView, userAndUid)
: base(webView, userAndUid)
{
}

View File

@@ -22,6 +22,16 @@ internal sealed class Transformer
[JsonPropertyName("recovery_time")]
public RecoveryTime? RecoveryTime { get; set; }
public string ObtainedAndReachedFormatted
{
get => Obtained ? RecoveryTime.ReachedFormatted : SH.WebDailyNoteTransformerNotObtained;
}
public string ObtainedAndTimeFormatted
{
get => Obtained ? RecoveryTime.TimeFormatted : SH.WebDailyNoteTransformerNotObtainedDetail;
}
/// <summary>
/// Wiki链接
/// </summary>