Compare commits

..

2 Commits
1.3.1 ... 1.3.3

Author SHA1 Message Date
DismissedLight
915b1aae32 fix pipeline 2023-01-02 16:50:01 +08:00
DismissedLight
71a1bdc173 add empty page template view 2023-01-02 15:09:53 +08:00
40 changed files with 2766 additions and 2446 deletions

View File

@@ -28,7 +28,7 @@ variables:
project: $(Build.SourcesDirectory)/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj' project: $(Build.SourcesDirectory)/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj'
buildPlatform: 'x64' buildPlatform: 'x64'
buildConfiguration: 'Release' buildConfiguration: 'Release'
build_date: $[ format('{0:yyyy}.{0:MM}.{0:dd}', pipeline.startTime) ] build_date: $[ format('{0:yyyy}.{0:M}.{0:d}', pipeline.startTime) ]
steps: steps:

View File

@@ -52,6 +52,7 @@
<shmmc:AvatarSideIconConverter x:Key="AvatarSideIconConverter"/> <shmmc:AvatarSideIconConverter x:Key="AvatarSideIconConverter"/>
<shmmc:DescParamDescriptor x:Key="DescParamDescriptor"/> <shmmc:DescParamDescriptor x:Key="DescParamDescriptor"/>
<shmmc:ElementNameIconConverter x:Key="ElementNameIconConverter"/> <shmmc:ElementNameIconConverter x:Key="ElementNameIconConverter"/>
<shmmc:EmotionIconConverter x:Key="EmotionIconConverter"/>
<shmmc:EquipIconConverter x:Key="EquipIconConverter"/> <shmmc:EquipIconConverter x:Key="EquipIconConverter"/>
<shmmc:GachaAvatarImgConverter x:Key="GachaAvatarImgConverter"/> <shmmc:GachaAvatarImgConverter x:Key="GachaAvatarImgConverter"/>
<shmmc:GachaAvatarIconConverter x:Key="GachaAvatarIconConverter"/> <shmmc:GachaAvatarIconConverter x:Key="GachaAvatarIconConverter"/>
@@ -61,8 +62,14 @@
<shmmc:QualityColorConverter x:Key="QualityColorConverter"/> <shmmc:QualityColorConverter x:Key="QualityColorConverter"/>
<shmmc:WeaponTypeIconConverter x:Key="WeaponTypeIconConverter"/> <shmmc:WeaponTypeIconConverter x:Key="WeaponTypeIconConverter"/>
<shvc:BoolToVisibilityRevertConverter x:Key="BoolToVisibilityRevertConverter"/> <shvc:BoolToVisibilityRevertConverter x:Key="BoolToVisibilityRevertConverter"/>
<shvc:EmptyCollectionToBoolConverter x:Key="EmptyCollectionToBoolConverter"/>
<shvc:EmptyCollectionToBoolRevertConverter x:Key="EmptyCollectionToBoolRevertConverter"/>
<shvc:EmptyCollectionToVisibilityConverter x:Key="EmptyCollectionToVisibilityConverter"/>
<shvc:EmptyCollectionToVisibilityRevertConverter x:Key="EmptyCollectionToVisibilityRevertConverter"/>
<shvc:EmptyObjectToBoolConverter x:Key="EmptyObjectToBoolConverter"/>
<shvc:EmptyObjectToBoolRevertConverter x:Key="EmptyObjectToBoolRevertConverter"/>
<shvc:EmptyObjectToVisibilityConverter x:Key="EmptyObjectToVisibilityConverter"/> <shvc:EmptyObjectToVisibilityConverter x:Key="EmptyObjectToVisibilityConverter"/>
<shvc:EmptyObjectToVisibilityRevertConverter x:Key="EmptyObjectToVisibilityRevertConverter"/>
<!-- Styles --> <!-- Styles -->
<Style <Style
x:Key="LargeGridViewItemStyle" x:Key="LargeGridViewItemStyle"
@@ -70,7 +77,6 @@
TargetType="GridViewItem"> TargetType="GridViewItem">
<Setter Property="Margin" Value="0,0,12,12"/> <Setter Property="Margin" Value="0,0,12,12"/>
</Style> </Style>
<Style <Style
x:Key="SettingButtonStyle" x:Key="SettingButtonStyle"
BasedOn="{StaticResource DefaultButtonStyle}" BasedOn="{StaticResource DefaultButtonStyle}"
@@ -81,7 +87,6 @@
<Setter Property="HorizontalAlignment" Value="Stretch"/> <Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/> <Setter Property="HorizontalContentAlignment" Value="Center"/>
</Style> </Style>
<Style x:Key="BorderCardStyle" TargetType="Border"> <Style x:Key="BorderCardStyle" TargetType="Border">
<Setter Property="Background" Value="{ThemeResource CardBackgroundFillColorDefaultBrush}"/> <Setter Property="Background" Value="{ThemeResource CardBackgroundFillColorDefaultBrush}"/>
<Setter Property="BorderBrush" Value="{ThemeResource CardStrokeColorDefaultBrush}"/> <Setter Property="BorderBrush" Value="{ThemeResource CardStrokeColorDefaultBrush}"/>
@@ -92,7 +97,6 @@
<ItemsPanelTemplate x:Key="ItemsStackPanelTemplate"> <ItemsPanelTemplate x:Key="ItemsStackPanelTemplate">
<ItemsStackPanel/> <ItemsStackPanel/>
</ItemsPanelTemplate> </ItemsPanelTemplate>
<ItemsPanelTemplate x:Key="HorizontalStackPanelTemplate"> <ItemsPanelTemplate x:Key="HorizontalStackPanelTemplate">
<StackPanel Orientation="Horizontal"/> <StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate> </ItemsPanelTemplate>

View File

@@ -1,68 +0,0 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Microsoft.UI.Xaml.Markup;
using Snap.Hutao.Extension;
using Snap.Hutao.Localization;
using System.Globalization;
namespace Snap.Hutao.Control.Markup;
/// <summary>
/// 国际化拓展
/// </summary>
[MarkupExtensionReturnType(ReturnType = typeof(string))]
internal class I18NExtension : MarkupExtension
{
private static readonly ITranslation Translation;
private static readonly Dictionary<string, Type> TranslationMap = new()
{
["zh-CN"] = typeof(LanguagezhCN),
};
static I18NExtension()
{
string currentName = CultureInfo.CurrentUICulture.Name;
Type? languageType = TranslationMap.GetValueOrDefault2(currentName, typeof(LanguagezhCN));
Translation = (ITranslation)Activator.CreateInstance(languageType!)!;
}
/// <summary>
/// 构造默认的国际化拓展
/// </summary>
public I18NExtension()
: base()
{
}
/// <summary>
/// 构造默认的国际化拓展
/// </summary>
/// <param name="key">键</param>
public I18NExtension(string key)
{
Key = key;
}
/// <summary>
/// 键名称
/// </summary>
public string Key { get; set; } = default!;
/// <summary>
/// 获取字符串
/// </summary>
/// <param name="key">键</param>
/// <returns>翻译的字符串</returns>
internal static string Get(string key)
{
return Translation[key];
}
/// <inheritdoc/>
protected override object ProvideValue()
{
return Translation[Key];
}
}

View File

@@ -1,68 +0,0 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
namespace Snap.Hutao.Control.Markup;
/// <summary>
/// 国际化帮助类
/// WinUI 3 目前存在部分页面无法使用 MarkupExtension 的问题
/// 使用 此帮助类 绕过限制
/// </summary>
internal class I18NHelper
{
private static readonly DependencyProperty TranslationProperty = Property<I18NHelper>.Attach("Translation", string.Empty, OnKeyChanged);
/// <summary>
/// 获取键
/// </summary>
/// <param name="obj">对象</param>
/// <returns>值</returns>
public static string GetTranslation(DependencyObject obj)
{
return (string)obj.GetValue(TranslationProperty);
}
/// <summary>
/// 设置键
/// </summary>
/// <param name="obj">对象</param>
/// <param name="value">值</param>
public static void SetTranslation(DependencyObject obj, string value)
{
string tarnslation = I18NExtension.Get(value);
obj.SetValue(TranslationProperty, tarnslation);
}
private static void OnKeyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs arg)
{
string translation = I18NExtension.Get(arg.NewValue.ToString() ?? string.Empty);
if (obj is AppBarButton appBarButton)
{
appBarButton.Label = translation;
}
else if (obj is AppBarToggleButton appBarToggleButton)
{
appBarToggleButton.Label = translation;
}
else if (obj is AutoSuggestBox autoSuggestBox)
{
autoSuggestBox.PlaceholderText = translation;
}
else if (obj is ContentControl contentControl)
{
contentControl.Content = translation;
}
else if (obj is MenuFlyoutItem menuFlyoutItem)
{
menuFlyoutItem.Text = translation;
}
else if (obj is TextBlock textBlock)
{
textBlock.Text = translation;
}
}
}

View File

@@ -5,6 +5,8 @@ using Microsoft.Win32;
using Snap.Hutao.Core.Convert; using Snap.Hutao.Core.Convert;
using Snap.Hutao.Core.Json; using Snap.Hutao.Core.Json;
using Snap.Hutao.Extension; using Snap.Hutao.Extension;
using Snap.Hutao.Web.Hoyolab.DynamicSecret;
using System.Collections.Immutable;
using System.Text.Json.Serialization.Metadata; using System.Text.Json.Serialization.Metadata;
using Windows.ApplicationModel; using Windows.ApplicationModel;
@@ -28,7 +30,20 @@ internal static class CoreEnvironment
/// <summary> /// <summary>
/// 米游社 Rpc 版本 /// 米游社 Rpc 版本
/// </summary> /// </summary>
public const string HoyolabXrpcVersion = "2.42.1"; public const string HoyolabXrpcVersion = "2.43.1";
/// <summary>
/// 盐
/// </summary>
// https://github.com/UIGF-org/Hoyolab.Salt
public static readonly ImmutableDictionary<string, string> DynamicSecrets = new Dictionary<string, string>()
{
[nameof(SaltType.K2)] = "ODzG1Jrn6zebX19VRmaJwjFI2CDvBUGq",
[nameof(SaltType.LK2)] = "V1PYbXKQY7ysdx3MNCcNbsE1LtY2QZpW",
[nameof(SaltType.X4)] = "xV8v4Qu54lUKrEYFZkJhB8cuOh9Asafs",
[nameof(SaltType.X6)] = "t0qEgfub6cvueAPgR5m9aQWWVciEer7v",
[nameof(SaltType.PROD)] = "JwYDpKvLj6MrMqqYU6jTKF17KNO2PXoS",
}.ToImmutableDictionary();
/// <summary> /// <summary>
/// 标准UA /// 标准UA

View File

@@ -40,6 +40,11 @@ public class SettingEntry
/// </summary> /// </summary>
public const string DailyNoteReminderNotify = "DailyNote.ReminderNotify"; public const string DailyNoteReminderNotify = "DailyNote.ReminderNotify";
/// <summary>
/// 实时便笺免打扰模式
/// </summary>
public const string DailyNoteSilentWhenPlayingGame = "DailyNote.SilentWhenPlayingGame";
/// <summary> /// <summary>
/// 启动游戏 全屏 /// 启动游戏 全屏
/// </summary> /// </summary>

View File

@@ -0,0 +1,30 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Snap.Hutao.Control;
namespace Snap.Hutao.Model.Metadata.Converter;
/// <summary>
/// 表情图片转换器
/// </summary>
internal class EmotionIconConverter : ValueConverterBase<string, Uri>
{
private const string BaseUrl = "https://static.snapgenshin.com/EmotionIcon/{0}.png";
/// <summary>
/// 名称转Uri
/// </summary>
/// <param name="name">名称</param>
/// <returns>链接</returns>
public static Uri IconNameToUri(string name)
{
return new Uri(string.Format(BaseUrl, name));
}
/// <inheritdoc/>
public override Uri Convert(string from)
{
return IconNameToUri(from);
}
}

View File

@@ -12,7 +12,7 @@
<Identity <Identity
Name="7f0db578-026f-4e0b-a75b-d5d06bb0a74d" Name="7f0db578-026f-4e0b-a75b-d5d06bb0a74d"
Publisher="CN=DGP Studio" Publisher="CN=DGP Studio"
Version="1.3.0.0" /> Version="1.3.1.0" />
<Properties> <Properties>
<DisplayName>胡桃</DisplayName> <DisplayName>胡桃</DisplayName>

View File

@@ -2,7 +2,7 @@
"profiles": { "profiles": {
"Snap.Hutao (Package)": { "Snap.Hutao (Package)": {
"commandName": "MsixPackage", "commandName": "MsixPackage",
"nativeDebugging": true, "nativeDebugging": false,
"doNotLaunchApp": false "doNotLaunchApp": false
}, },
"Snap.Hutao (Unpackaged)": { "Snap.Hutao (Unpackaged)": {

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

View File

@@ -167,6 +167,10 @@ internal class DailyNoteNotifier
builder.SetToastScenario(ToastScenario.Reminder); builder.SetToastScenario(ToastScenario.Reminder);
} }
if (notifyInfos.Count > 2)
{
builder.AddText("多个提醒项达到设定值");
// Desktop and Mobile started supporting adaptive toasts in API contract 3 (Anniversary Update) // Desktop and Mobile started supporting adaptive toasts in API contract 3 (Anniversary Update)
if (ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 3)) if (ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 3))
{ {
@@ -188,13 +192,7 @@ internal class DailyNoteNotifier
} }
builder.AddVisualChild(group); builder.AddVisualChild(group);
builder.AddText("一个或多个提醒项达到设定值");
} }
else
{
if (notifyInfos.Count > 2)
{
builder.AddText("多个提醒项达到设定值");
} }
else else
{ {
@@ -203,7 +201,6 @@ internal class DailyNoteNotifier
builder.AddText(info.Hint); builder.AddText(info.Hint);
} }
} }
}
await ThreadHelper.SwitchToMainThreadAsync(); await ThreadHelper.SwitchToMainThreadAsync();
builder.Show(); builder.Show();

View File

@@ -10,6 +10,7 @@ using Snap.Hutao.Message;
using Snap.Hutao.Model.Binding.User; using Snap.Hutao.Model.Binding.User;
using Snap.Hutao.Model.Entity; using Snap.Hutao.Model.Entity;
using Snap.Hutao.Model.Entity.Database; using Snap.Hutao.Model.Entity.Database;
using Snap.Hutao.Service.Game;
using Snap.Hutao.Service.User; using Snap.Hutao.Service.User;
using Snap.Hutao.Web.Hoyolab.Takumi.GameRecord; using Snap.Hutao.Web.Hoyolab.Takumi.GameRecord;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
@@ -96,6 +97,13 @@ internal class DailyNoteService : IDailyNoteService, IRecipient<UserRemovedMessa
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>(); AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
GameRecordClient gameRecordClient = scope.ServiceProvider.GetRequiredService<GameRecordClient>(); GameRecordClient gameRecordClient = scope.ServiceProvider.GetRequiredService<GameRecordClient>();
if (appDbContext.Settings.SingleOrAdd(SettingEntry.DailyNoteSilentWhenPlayingGame, SettingEntryHelper.FalseString).GetBoolean()
&& Ioc.Default.GetRequiredService<IGameService>().IsGameRunning())
{
// Prevent notify when we are in silent mode.
notify = false;
}
foreach (DailyNoteEntry entry in appDbContext.DailyNotes.Include(n => n.User)) foreach (DailyNoteEntry entry in appDbContext.DailyNotes.Include(n => n.User))
{ {
WebDailyNote? dailyNote = await gameRecordClient.GetDailyNoteAsync(entry.User, entry.Uid).ConfigureAwait(false); WebDailyNote? dailyNote = await gameRecordClient.GetDailyNoteAsync(entry.User, entry.Uid).ConfigureAwait(false);

View File

@@ -71,7 +71,7 @@ internal class GameService : IGameService, IDisposable
if (!result.IsOk) if (!result.IsOk)
{ {
// Try locate manually // Try locate by registry
locator = gameLocators.Single(l => l.Name == nameof(RegistryLauncherLocator)); locator = gameLocators.Single(l => l.Name == nameof(RegistryLauncherLocator));
result = await locator.LocateGamePathAsync().ConfigureAwait(false); result = await locator.LocateGamePathAsync().ConfigureAwait(false);
} }

View File

@@ -22,7 +22,7 @@
<AppxPackageSigningEnabled>True</AppxPackageSigningEnabled> <AppxPackageSigningEnabled>True</AppxPackageSigningEnabled>
<PackageCertificateThumbprint>F8C2255969BEA4A681CED102771BF807856AEC02</PackageCertificateThumbprint> <PackageCertificateThumbprint>F8C2255969BEA4A681CED102771BF807856AEC02</PackageCertificateThumbprint>
<AppxPackageSigningTimestampDigestAlgorithm>SHA256</AppxPackageSigningTimestampDigestAlgorithm> <AppxPackageSigningTimestampDigestAlgorithm>SHA256</AppxPackageSigningTimestampDigestAlgorithm>
<AppxAutoIncrementPackageRevision>False</AppxAutoIncrementPackageRevision> <AppxAutoIncrementPackageRevision>True</AppxAutoIncrementPackageRevision>
<AppxSymbolPackageEnabled>True</AppxSymbolPackageEnabled> <AppxSymbolPackageEnabled>True</AppxSymbolPackageEnabled>
<GenerateTestArtifacts>True</GenerateTestArtifacts> <GenerateTestArtifacts>True</GenerateTestArtifacts>
<AppxBundle>Never</AppxBundle> <AppxBundle>Never</AppxBundle>
@@ -40,6 +40,7 @@
<None Remove="LaunchGameWindow.xaml" /> <None Remove="LaunchGameWindow.xaml" />
<None Remove="NativeMethods.json" /> <None Remove="NativeMethods.json" />
<None Remove="NativeMethods.txt" /> <None Remove="NativeMethods.txt" />
<None Remove="Resource\Icon\UI_AchievementIcon_3_3.png" />
<None Remove="Resource\Icon\UI_BagTabIcon_Avatar.png" /> <None Remove="Resource\Icon\UI_BagTabIcon_Avatar.png" />
<None Remove="Resource\Icon\UI_BagTabIcon_Weapon.png" /> <None Remove="Resource\Icon\UI_BagTabIcon_Weapon.png" />
<None Remove="Resource\Icon\UI_BtnIcon_ActivityEntry.png" /> <None Remove="Resource\Icon\UI_BtnIcon_ActivityEntry.png" />
@@ -119,6 +120,7 @@
<Content Include="Assets\StoreLogo.png" /> <Content Include="Assets\StoreLogo.png" />
<Content Include="Assets\Wide310x150Logo.scale-200.png" /> <Content Include="Assets\Wide310x150Logo.scale-200.png" />
<Content Include="Resource\Font\Segoe Fluent Icons.ttf" /> <Content Include="Resource\Font\Segoe Fluent Icons.ttf" />
<Content Include="Resource\Icon\UI_AchievementIcon_3_3.png" />
<Content Include="Resource\Icon\UI_BagTabIcon_Avatar.png" /> <Content Include="Resource\Icon\UI_BagTabIcon_Avatar.png" />
<Content Include="Resource\Icon\UI_BagTabIcon_Weapon.png" /> <Content Include="Resource\Icon\UI_BagTabIcon_Weapon.png" />
<Content Include="Resource\Icon\UI_BtnIcon_ActivityEntry.png" /> <Content Include="Resource\Icon\UI_BtnIcon_ActivityEntry.png" />

View File

@@ -0,0 +1,22 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using CommunityToolkit.WinUI.UI.Converters;
using Microsoft.UI.Xaml;
namespace Snap.Hutao.View.Converter;
/// <summary>
/// This class converts a collection size into a boolean value.
/// </summary>
public class EmptyCollectionToBoolConverter : EmptyCollectionToObjectConverter
{
/// <summary>
/// Initializes a new instance of the <see cref="EmptyCollectionToVisibilityConverter"/> class.
/// </summary>
public EmptyCollectionToBoolConverter()
{
EmptyValue = false;
NotEmptyValue = true;
}
}

View File

@@ -0,0 +1,22 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using CommunityToolkit.WinUI.UI.Converters;
using Microsoft.UI.Xaml;
namespace Snap.Hutao.View.Converter;
/// <summary>
/// This class converts a collection size into a boolean value in reverse.
/// </summary>
public class EmptyCollectionToBoolRevertConverter : EmptyCollectionToObjectConverter
{
/// <summary>
/// Initializes a new instance of the <see cref="EmptyCollectionToVisibilityConverter"/> class.
/// </summary>
public EmptyCollectionToBoolRevertConverter()
{
EmptyValue = true;
NotEmptyValue = false;
}
}

View File

@@ -0,0 +1,22 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using CommunityToolkit.WinUI.UI.Converters;
using Microsoft.UI.Xaml;
namespace Snap.Hutao.View.Converter;
/// <summary>
/// This class converts a collection size into a Visibility enumeration.
/// </summary>
public class EmptyCollectionToVisibilityConverter : EmptyCollectionToObjectConverter
{
/// <summary>
/// Initializes a new instance of the <see cref="EmptyCollectionToVisibilityConverter"/> class.
/// </summary>
public EmptyCollectionToVisibilityConverter()
{
EmptyValue = Visibility.Collapsed;
NotEmptyValue = Visibility.Visible;
}
}

View File

@@ -0,0 +1,22 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using CommunityToolkit.WinUI.UI.Converters;
using Microsoft.UI.Xaml;
namespace Snap.Hutao.View.Converter;
/// <summary>
/// This class converts a collection size into a Visibility enumeration in reverse.
/// </summary>
public class EmptyCollectionToVisibilityRevertConverter : EmptyCollectionToObjectConverter
{
/// <summary>
/// Initializes a new instance of the <see cref="EmptyCollectionToVisibilityRevertConverter"/> class.
/// </summary>
public EmptyCollectionToVisibilityRevertConverter()
{
EmptyValue = Visibility.Visible;
NotEmptyValue = Visibility.Collapsed;
}
}

View File

@@ -0,0 +1,22 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using CommunityToolkit.WinUI.UI.Converters;
using Microsoft.UI.Xaml;
namespace Snap.Hutao.View.Converter;
/// <summary>
/// This class converts a object? value into a boolean.
/// </summary>
public class EmptyObjectToBoolConverter : EmptyObjectToObjectConverter
{
/// <summary>
/// Initializes a new instance of the <see cref="EmptyObjectToVisibilityRevertConverter"/> class.
/// </summary>
public EmptyObjectToBoolConverter()
{
EmptyValue = false;
NotEmptyValue = true;
}
}

View File

@@ -0,0 +1,22 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using CommunityToolkit.WinUI.UI.Converters;
using Microsoft.UI.Xaml;
namespace Snap.Hutao.View.Converter;
/// <summary>
/// This class converts a object? value into a boolean in reverse.
/// </summary>
public class EmptyObjectToBoolRevertConverter : EmptyObjectToObjectConverter
{
/// <summary>
/// Initializes a new instance of the <see cref="EmptyObjectToVisibilityRevertConverter"/> class.
/// </summary>
public EmptyObjectToBoolRevertConverter()
{
EmptyValue = true;
NotEmptyValue = false;
}
}

View File

@@ -0,0 +1,22 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using CommunityToolkit.WinUI.UI.Converters;
using Microsoft.UI.Xaml;
namespace Snap.Hutao.View.Converter;
/// <summary>
/// This class converts a object? value into a Visibility enumeration in reverse.
/// </summary>
public class EmptyObjectToVisibilityRevertConverter : EmptyObjectToObjectConverter
{
/// <summary>
/// Initializes a new instance of the <see cref="EmptyObjectToVisibilityRevertConverter"/> class.
/// </summary>
public EmptyObjectToVisibilityRevertConverter()
{
EmptyValue = Visibility.Visible;
NotEmptyValue = Visibility.Collapsed;
}
}

View File

@@ -24,6 +24,7 @@
</mxi:Interaction.Behaviors> </mxi:Interaction.Behaviors>
<Grid Visibility="{Binding IsInitialized, Converter={StaticResource BoolToVisibilityConverter}}"> <Grid Visibility="{Binding IsInitialized, Converter={StaticResource BoolToVisibilityConverter}}">
<Grid Visibility="{Binding SelectedArchive, Converter={StaticResource EmptyObjectToVisibilityConverter}}">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="auto"/> <RowDefinition Height="auto"/>
<RowDefinition/> <RowDefinition/>
@@ -228,4 +229,24 @@
</SplitView.Content> </SplitView.Content>
</SplitView> </SplitView>
</Grid> </Grid>
<Grid Visibility="{Binding SelectedArchive, Converter={StaticResource EmptyObjectToVisibilityRevertConverter}}">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<Image
Width="120"
Height="120"
Source="ms-appx:///Resource/Icon/UI_AchievementIcon_3_3.png"/>
<TextBlock
Margin="0,16,0,0"
HorizontalAlignment="Center"
Style="{StaticResource SubtitleTextBlockStyle}"
Text="创建新存档以继续"/>
<Button
Margin="0,16,0,0"
Padding="16"
HorizontalAlignment="Stretch"
Command="{Binding AddArchiveCommand}"
Content="创建新存档"/>
</StackPanel>
</Grid>
</Grid>
</shc:ScopedPage> </shc:ScopedPage>

View File

@@ -37,6 +37,7 @@
</Page.Resources> </Page.Resources>
<Grid> <Grid>
<Grid Visibility="{Binding Summary, Converter={StaticResource EmptyObjectToVisibilityConverter}}">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="auto"/> <RowDefinition Height="auto"/>
<RowDefinition/> <RowDefinition/>
@@ -561,4 +562,29 @@
</SplitView.Content> </SplitView.Content>
</SplitView> </SplitView>
</Grid> </Grid>
<Grid Visibility="{Binding Summary, Converter={StaticResource EmptyObjectToVisibilityRevertConverter}}">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<shci:CachedImage
Width="120"
Height="120"
Source="https://static.snapgenshin.com/EmotionIcon/UI_EmotionIcon250.png"/>
<TextBlock
Margin="0,16,0,0"
HorizontalAlignment="Center"
Style="{StaticResource SubtitleTextBlockStyle}"
Text="尚未获取任何角色信息"/>
<wsc:SettingsGroup Margin="0,-36,0,0" HorizontalAlignment="Center">
<wsc:Setting Description="同步游戏内角色橱窗中的信息" Header="从 Enka API 同步">
<Button Command="{Binding RefreshFromEnkaApiCommand}" Content="同步"/>
</wsc:Setting>
<wsc:Setting Description="同步角色天赋外的大部分信息" Header="从米游社我的角色同步">
<Button Command="{Binding RefreshFromHoyolabGameRecordCommand}" Content="同步"/>
</wsc:Setting>
<wsc:Setting Description="同步角色天赋信息" Header="从米游社养成计算同步">
<Button Command="{Binding RefreshFromHoyolabCalculateCommand}" Content="同步"/>
</wsc:Setting>
</wsc:SettingsGroup>
</StackPanel>
</Grid>
</Grid>
</shc:ScopedPage> </shc:ScopedPage>

View File

@@ -12,9 +12,11 @@
xmlns:mxim="using:Microsoft.Xaml.Interactions.Media" xmlns:mxim="using:Microsoft.Xaml.Interactions.Media"
xmlns:shc="using:Snap.Hutao.Control" xmlns:shc="using:Snap.Hutao.Control"
xmlns:shcb="using:Snap.Hutao.Control.Behavior" xmlns:shcb="using:Snap.Hutao.Control.Behavior"
xmlns:shci="using:Snap.Hutao.Control.Image"
xmlns:shcm="using:Snap.Hutao.Control.Markup" xmlns:shcm="using:Snap.Hutao.Control.Markup"
xmlns:shv="using:Snap.Hutao.ViewModel" xmlns:shv="using:Snap.Hutao.ViewModel"
xmlns:shvc="using:Snap.Hutao.View.Control" xmlns:shvc="using:Snap.Hutao.View.Control"
xmlns:wsc="using:WinUICommunity.SettingsUI.Controls"
d:DataContext="{d:DesignInstance shv:CultivationViewModel}" d:DataContext="{d:DesignInstance shv:CultivationViewModel}"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
mc:Ignorable="d"> mc:Ignorable="d">
@@ -41,6 +43,7 @@
<shcb:InvokeCommandOnLoadedBehavior Command="{Binding OpenUICommand}"/> <shcb:InvokeCommandOnLoadedBehavior Command="{Binding OpenUICommand}"/>
</mxi:Interaction.Behaviors> </mxi:Interaction.Behaviors>
<Grid> <Grid>
<Grid Visibility="{Binding Projects, Converter={StaticResource EmptyCollectionToVisibilityConverter}}">
<Rectangle <Rectangle
Height="48" Height="48"
VerticalAlignment="Top" VerticalAlignment="Top"
@@ -123,13 +126,15 @@
</Pivot.RightHeader> </Pivot.RightHeader>
<PivotItem Header="材料清单"> <PivotItem Header="材料清单">
<Grid>
<cwucont:AdaptiveGridView <cwucont:AdaptiveGridView
Padding="16,16,4,4" Padding="16,16,4,4"
cwua:ItemsReorderAnimation.Duration="0:0:0.1" cwua:ItemsReorderAnimation.Duration="0:0:0.1"
DesiredWidth="320" DesiredWidth="320"
ItemContainerStyle="{StaticResource LargeGridViewItemStyle}" ItemContainerStyle="{StaticResource LargeGridViewItemStyle}"
ItemsSource="{Binding CultivateEntries}" ItemsSource="{Binding CultivateEntries}"
SelectionMode="None"> SelectionMode="None"
Visibility="{Binding CultivateEntries, Converter={StaticResource EmptyCollectionToVisibilityConverter}}">
<cwucont:AdaptiveGridView.ItemTemplate> <cwucont:AdaptiveGridView.ItemTemplate>
<DataTemplate> <DataTemplate>
<Border Style="{StaticResource BorderCardStyle}"> <Border Style="{StaticResource BorderCardStyle}">
@@ -265,6 +270,42 @@
</DataTemplate> </DataTemplate>
</cwucont:AdaptiveGridView.ItemTemplate> </cwucont:AdaptiveGridView.ItemTemplate>
</cwucont:AdaptiveGridView> </cwucont:AdaptiveGridView>
<StackPanel
HorizontalAlignment="Center"
VerticalAlignment="Center"
Visibility="{Binding CultivateEntries, Converter={StaticResource EmptyCollectionToVisibilityRevertConverter}}">
<wsc:SettingsGroup Margin="0,-36,0,0" HorizontalAlignment="Center">
<wsc:Setting
Description="添加任意角色到养成计划"
Header="角色资料"
Icon="{shcm:BitmapIcon Source=ms-appx:///Resource/Icon/UI_BagTabIcon_Avatar.png}">
<Button
Command="{Binding NavigateToPageCommand}"
CommandParameter="Snap.Hutao.View.Page.WikiAvatarPage"
Content="前往"/>
</wsc:Setting>
<wsc:Setting
Description="添加任意武器到养成计划"
Header="武器资料"
Icon="{shcm:BitmapIcon Source=ms-appx:///Resource/Icon/UI_BagTabIcon_Weapon.png}">
<Button
Command="{Binding NavigateToPageCommand}"
CommandParameter="Snap.Hutao.View.Page.WikiWeaponPage"
Content="前往"/>
</wsc:Setting>
<wsc:Setting
Description="添加我的角色与武器到养成计划"
Header="我的角色"
Icon="{shcm:BitmapIcon Source=ms-appx:///Resource/Icon/UI_Icon_BoostUp.png}">
<Button
Command="{Binding NavigateToPageCommand}"
CommandParameter="Snap.Hutao.View.Page.AvatarPropertyPage"
Content="前往"/>
</wsc:Setting>
</wsc:SettingsGroup>
</StackPanel>
</Grid>
</PivotItem> </PivotItem>
<PivotItem Header="背包物品"> <PivotItem Header="背包物品">
<cwucont:AdaptiveGridView <cwucont:AdaptiveGridView
@@ -309,4 +350,27 @@
</PivotItem> </PivotItem>
</Pivot> </Pivot>
</Grid> </Grid>
<Grid Visibility="{Binding Projects, Converter={StaticResource EmptyCollectionToVisibilityRevertConverter}}">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<shci:CachedImage
Width="120"
Height="120"
Source="https://static.snapgenshin.com/EmotionIcon/UI_EmotionIcon293.png"/>
<TextBlock
Margin="0,16,0,0"
HorizontalAlignment="Center"
Style="{StaticResource SubtitleTextBlockStyle}"
Text="新建养成计划以继续"/>
<wsc:SettingsGroup Margin="0,-36,0,0" HorizontalAlignment="Center">
<wsc:Setting
Description="稍后可以前往其他页面添加养成计划项"
Header="新建计划"
Icon="{shcm:FontIcon Glyph=&#xE710;}">
<Button Command="{Binding AddProjectCommand}" Content="新建"/>
</wsc:Setting>
</wsc:SettingsGroup>
</StackPanel>
</Grid>
</Grid>
</shc:ScopedPage> </shc:ScopedPage>

View File

@@ -106,6 +106,15 @@
</RadioButtons.ItemTemplate> </RadioButtons.ItemTemplate>
</RadioButtons> </RadioButtons>
<wsc:SettingsGroup Margin="0,-16,0,0" Header="通知"> <wsc:SettingsGroup Margin="0,-16,0,0" Header="通知">
<wsc:Setting
Description="在我游玩原神时不通知我"
Header="免打扰模式"
Icon="&#xE7ED;">
<ToggleSwitch
Margin="24,0,0,0"
IsOn="{Binding IsSilentWhenPlayingGame, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchSettingStyle}"/>
</wsc:Setting>
<wsc:Setting <wsc:Setting
Description="防止通知自动收入操作中心" Description="防止通知自动收入操作中心"
Header="提醒通知" Header="提醒通知"

View File

@@ -11,6 +11,7 @@
xmlns:shcm="using:Snap.Hutao.Control.Markup" xmlns:shcm="using:Snap.Hutao.Control.Markup"
xmlns:shv="using:Snap.Hutao.ViewModel" xmlns:shv="using:Snap.Hutao.ViewModel"
xmlns:shvc="using:Snap.Hutao.View.Control" xmlns:shvc="using:Snap.Hutao.View.Control"
xmlns:wsc="using:WinUICommunity.SettingsUI.Controls"
d:DataContext="{d:DesignInstance shv:GachaLogViewModel}" d:DataContext="{d:DesignInstance shv:GachaLogViewModel}"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
mc:Ignorable="d"> mc:Ignorable="d">
@@ -20,6 +21,7 @@
</mxi:Interaction.Behaviors> </mxi:Interaction.Behaviors>
<Grid Visibility="{Binding IsInitialized, Converter={StaticResource BoolToVisibilityConverter}}"> <Grid Visibility="{Binding IsInitialized, Converter={StaticResource BoolToVisibilityConverter}}">
<Grid Visibility="{Binding Statistics, Converter={StaticResource EmptyObjectToVisibilityConverter}}">
<Rectangle <Rectangle
Height="48" Height="48"
VerticalAlignment="Top" VerticalAlignment="Top"
@@ -51,7 +53,7 @@
<MenuFlyoutItem <MenuFlyoutItem
Command="{Binding RefreshByWebCacheCommand}" Command="{Binding RefreshByWebCacheCommand}"
Icon="{shcm:FontIcon Glyph=&#xE81E;}" Icon="{shcm:FontIcon Glyph=&#xE81E;}"
Text="缓存刷新"/> Text="网页缓存刷新"/>
<MenuFlyoutItem <MenuFlyoutItem
Command="{Binding RefreshByManualInputCommand}" Command="{Binding RefreshByManualInputCommand}"
Icon="{shcm:FontIcon Glyph=&#xE765;}" Icon="{shcm:FontIcon Glyph=&#xE765;}"
@@ -64,30 +66,14 @@
</AppBarButton.Flyout> </AppBarButton.Flyout>
</AppBarButton> </AppBarButton>
<AppBarSeparator/> <AppBarSeparator/>
<AppBarButton Icon="{shcm:FontIcon Glyph=&#xE8B5;}" Label="导入"> <AppBarButton
<AppBarButton.Flyout> Command="{Binding ImportFromUIGFJsonCommand}"
<MenuFlyout Placement="Bottom"> Icon="{shcm:FontIcon Glyph=&#xE8B5;}"
<MenuFlyoutItem Command="{Binding ImportFromUIGFJsonCommand}" Text="从 UIGF Json 文件导入"/> Label="导入"/>
<MenuFlyoutItem <AppBarButton
Command="{Binding ImportFromUIGFExcelCommand}" Command="{Binding ExportToUIGFJsonCommand}"
IsEnabled="False" Icon="{shcm:FontIcon Glyph=&#xEDE1;}"
Text="从 UIGF Excel 文件导入" Label="导出"/>
Visibility="Collapsed"/>
</MenuFlyout>
</AppBarButton.Flyout>
</AppBarButton>
<AppBarButton Icon="{shcm:FontIcon Glyph=&#xEDE1;}" Label="导出">
<AppBarButton.Flyout>
<MenuFlyout Placement="Bottom">
<MenuFlyoutItem Command="{Binding ExportToUIGFJsonCommand}" Text="导出到 UIGF Json 文件"/>
<MenuFlyoutItem
Command="{Binding ExportToUIGFExcelCommand}"
IsEnabled="False"
Text="导出到 UIGF Excel 文件"
Visibility="Collapsed"/>
</MenuFlyout>
</AppBarButton.Flyout>
</AppBarButton>
<CommandBar.SecondaryCommands> <CommandBar.SecondaryCommands>
<AppBarButton <AppBarButton
Command="{Binding RemoveArchiveCommand}" Command="{Binding RemoveArchiveCommand}"
@@ -477,4 +463,44 @@
</PivotItem> </PivotItem>
</Pivot> </Pivot>
</Grid> </Grid>
<Grid Visibility="{Binding Statistics, Converter={StaticResource EmptyObjectToVisibilityRevertConverter}}">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<shci:CachedImage
Width="120"
Height="120"
Source="https://static.snapgenshin.com/EmotionIcon/UI_EmotionIcon71.png"/>
<TextBlock
Margin="0,16,0,0"
HorizontalAlignment="Center"
Style="{StaticResource SubtitleTextBlockStyle}"
Text="尚未获取任何祈愿记录"/>
<wsc:SettingsGroup Margin="0,-36,0,0" HorizontalAlignment="Center">
<wsc:Setting
Description="使用当前账号的Cookie信息刷新祈愿记录"
Header="Stoken 刷新"
Icon="{shcm:FontIcon Glyph=&#xE192;}">
<Button Command="{Binding RefreshByStokenCommand}" Content="获取"/>
</wsc:Setting>
<wsc:Setting
Description="使用游戏内浏览器的网页缓存刷新祈愿记录"
Header="网页缓存刷新"
Icon="{shcm:FontIcon Glyph=&#xE81E;}">
<Button Command="{Binding RefreshByWebCacheCommand}" Content="获取"/>
</wsc:Setting>
<wsc:Setting
Description="使用由你提供的 Url 刷新祈愿记录"
Header="手动输入 Url"
Icon="{shcm:FontIcon Glyph=&#xE765;}">
<Button Command="{Binding RefreshByManualInputCommand}" Content="输入"/>
</wsc:Setting>
<wsc:Setting
Description="导入从其他 App 中导出的数据"
Header="导入 UIGF Json"
Icon="{shcm:FontIcon Glyph=&#xE8B5;}">
<Button Command="{Binding ImportFromUIGFJsonCommand}" Content="导入"/>
</wsc:Setting>
</wsc:SettingsGroup>
</StackPanel>
</Grid>
</Grid>
</shc:ScopedPage> </shc:ScopedPage>

View File

@@ -8,6 +8,7 @@
xmlns:mxi="using:Microsoft.Xaml.Interactivity" xmlns:mxi="using:Microsoft.Xaml.Interactivity"
xmlns:shc="using:Snap.Hutao.Control" xmlns:shc="using:Snap.Hutao.Control"
xmlns:shcb="using:Snap.Hutao.Control.Behavior" xmlns:shcb="using:Snap.Hutao.Control.Behavior"
xmlns:shci="using:Snap.Hutao.Control.Image"
xmlns:shcm="using:Snap.Hutao.Control.Markup" xmlns:shcm="using:Snap.Hutao.Control.Markup"
xmlns:shmbh="using:Snap.Hutao.Model.Binding.Hutao" xmlns:shmbh="using:Snap.Hutao.Model.Binding.Hutao"
xmlns:shv="using:Snap.Hutao.ViewModel" xmlns:shv="using:Snap.Hutao.ViewModel"
@@ -63,7 +64,7 @@
</Page.Resources> </Page.Resources>
<Grid> <Grid>
<Pivot> <Pivot Visibility="{Binding Overview, Converter={StaticResource EmptyObjectToVisibilityConverter}}">
<Pivot.RightHeader> <Pivot.RightHeader>
<CommandBar DefaultLabelPosition="Right"> <CommandBar DefaultLabelPosition="Right">
<AppBarButton Icon="{shcm:FontIcon Glyph=&#xE946;}" Label="详情"> <AppBarButton Icon="{shcm:FontIcon Glyph=&#xE946;}" Label="详情">
@@ -330,5 +331,19 @@
</Grid> </Grid>
</PivotItem> </PivotItem>
</Pivot> </Pivot>
<cwuc:Loading IsLoading="{Binding Overview, Converter={StaticResource EmptyObjectToBoolRevertConverter}}">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<shci:CachedImage
Width="120"
Height="120"
Source="https://static.snapgenshin.com/EmotionIcon/UI_EmotionIcon272.png"/>
<TextBlock
Margin="0,16,0,0"
HorizontalAlignment="Center"
Style="{StaticResource SubtitleTextBlockStyle}"
Text="加载中,请稍候"/>
<ProgressRing Margin="0,16,0,0" IsActive="True"/>
</StackPanel>
</cwuc:Loading>
</Grid> </Grid>
</shc:ScopedPage> </shc:ScopedPage>

View File

@@ -22,31 +22,13 @@
</mxi:Interaction.Behaviors> </mxi:Interaction.Behaviors>
<Grid> <Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<CommandBar
Grid.Row="0"
Background="{StaticResource CardBackgroundFillColorDefaultBrush}"
DefaultLabelPosition="Right">
<AppBarButton
Command="{Binding UploadSpiralAbyssRecordCommand}"
Icon="{shcm:FontIcon Glyph=&#xE898;}"
Label="上传数据"/>
<AppBarButton
Command="{Binding RefreshCommand}"
Icon="{shcm:FontIcon Glyph=&#xE72C;}"
Label="刷新数据"/>
</CommandBar>
<SplitView <SplitView
Grid.Row="1" Grid.Row="1"
DisplayMode="Inline" DisplayMode="Inline"
IsPaneOpen="True" IsPaneOpen="True"
OpenPaneLength="96" OpenPaneLength="96"
PaneBackground="Transparent"> PaneBackground="Transparent"
Visibility="{Binding SpiralAbyssEntries, Converter={StaticResource EmptyCollectionToVisibilityConverter}}">
<SplitView.Pane> <SplitView.Pane>
<ListView ItemsSource="{Binding SpiralAbyssEntries}" SelectedItem="{Binding SelectedEntry, Mode=TwoWay}"> <ListView ItemsSource="{Binding SpiralAbyssEntries}" SelectedItem="{Binding SelectedEntry, Mode=TwoWay}">
<ListView.ItemTemplate> <ListView.ItemTemplate>
@@ -57,9 +39,21 @@
</ListView> </ListView>
</SplitView.Pane> </SplitView.Pane>
<SplitView.Content> <SplitView.Content>
<Grid DataContext="{Binding SpiralAbyssView}"> <Grid>
<Pivot> <Pivot>
<PivotItem Header="统计数据"> <Pivot.RightHeader>
<CommandBar Grid.Row="0" DefaultLabelPosition="Right">
<AppBarButton
Command="{Binding UploadSpiralAbyssRecordCommand}"
Icon="{shcm:FontIcon Glyph=&#xE898;}"
Label="上传数据"/>
<AppBarButton
Command="{Binding RefreshCommand}"
Icon="{shcm:FontIcon Glyph=&#xE72C;}"
Label="刷新数据"/>
</CommandBar>
</Pivot.RightHeader>
<PivotItem DataContext="{Binding SpiralAbyssView}" Header="统计数据">
<ScrollViewer> <ScrollViewer>
<Grid> <Grid>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
@@ -163,7 +157,7 @@
</ScrollViewer> </ScrollViewer>
</PivotItem> </PivotItem>
<PivotItem Header="详细数据"> <PivotItem DataContext="{Binding SpiralAbyssView}" Header="详细数据">
<ScrollViewer HorizontalScrollBarVisibility="Auto"> <ScrollViewer HorizontalScrollBarVisibility="Auto">
<ItemsControl <ItemsControl
Margin="16,16,0,0" Margin="16,16,0,0"
@@ -287,5 +281,27 @@
</Grid> </Grid>
</SplitView.Content> </SplitView.Content>
</SplitView> </SplitView>
<Grid Visibility="{Binding SpiralAbyssEntries, Converter={StaticResource EmptyCollectionToVisibilityRevertConverter}}">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<shci:CachedImage
Width="120"
Height="120"
Source="https://static.snapgenshin.com/EmotionIcon/UI_EmotionIcon25.png"/>
<TextBlock
Margin="0,16,0,0"
HorizontalAlignment="Center"
Style="{StaticResource SubtitleTextBlockStyle}"
Text="尚未获取任何挑战记录"/>
<wsc:SettingsGroup Margin="0,-36,0,0" HorizontalAlignment="Center">
<wsc:Setting
Description="同步米游社的深渊挑战记录"
Header="刷新数据"
Icon="&#xE72c;">
<Button Command="{Binding RefreshCommand}" Content="刷新"/>
</wsc:Setting>
</wsc:SettingsGroup>
</StackPanel>
</Grid> </Grid>
</Grid>
</shc:ScopedPage> </shc:ScopedPage>

View File

@@ -59,6 +59,7 @@
</Page.Resources> </Page.Resources>
<Grid> <Grid>
<Grid Visibility="{Binding Avatars, Converter={StaticResource EmptyCollectionToVisibilityConverter}}">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="auto"/> <RowDefinition Height="auto"/>
<RowDefinition/> <RowDefinition/>
@@ -603,4 +604,20 @@
</SplitView.Content> </SplitView.Content>
</SplitView> </SplitView>
</Grid> </Grid>
<cwuc:Loading IsLoading="{Binding Avatars, Converter={StaticResource EmptyCollectionToBoolRevertConverter}}">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<shci:CachedImage
Width="120"
Height="120"
Source="https://static.snapgenshin.com/EmotionIcon/UI_EmotionIcon272.png"/>
<TextBlock
Margin="0,16,0,0"
HorizontalAlignment="Center"
Style="{StaticResource SubtitleTextBlockStyle}"
Text="加载中,请稍候"/>
<ProgressRing Margin="0,16,0,0" IsActive="True"/>
</StackPanel>
</cwuc:Loading>
</Grid>
</Page> </Page>

View File

@@ -32,6 +32,7 @@
</Page.Resources> </Page.Resources>
<Grid> <Grid>
<Grid Visibility="{Binding Weapons, Converter={StaticResource EmptyCollectionToVisibilityConverter}}">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="auto"/> <RowDefinition Height="auto"/>
<RowDefinition/> <RowDefinition/>
@@ -242,5 +243,19 @@
</SplitView.Content> </SplitView.Content>
</SplitView> </SplitView>
</Grid> </Grid>
<cwuc:Loading IsLoading="{Binding Weapons, Converter={StaticResource EmptyCollectionToBoolRevertConverter}}">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<shci:CachedImage
Width="120"
Height="120"
Source="https://static.snapgenshin.com/EmotionIcon/UI_EmotionIcon272.png"/>
<TextBlock
Margin="0,16,0,0"
HorizontalAlignment="Center"
Style="{StaticResource SubtitleTextBlockStyle}"
Text="加载中,请稍候"/>
<ProgressRing Margin="0,16,0,0" IsActive="True"/>
</StackPanel>
</cwuc:Loading>
</Grid>
</shc:ScopedPage> </shc:ScopedPage>

View File

@@ -62,6 +62,7 @@
</Style> </Style>
</Flyout.FlyoutPresenterStyle> </Flyout.FlyoutPresenterStyle>
<StackPanel> <StackPanel>
<StackPanel Visibility="{Binding Users, Converter={StaticResource EmptyCollectionToVisibilityConverter}}">
<TextBlock <TextBlock
Margin="10,6,0,6" Margin="10,6,0,6"
Style="{StaticResource BaseTextBlockStyle}" Style="{StaticResource BaseTextBlockStyle}"
@@ -184,6 +185,12 @@
</DataTemplate> </DataTemplate>
</ListView.ItemTemplate> </ListView.ItemTemplate>
</ListView> </ListView>
</StackPanel>
<TextBlock
Margin="10,6,0,6"
Style="{StaticResource SubtitleTextBlockStyle}"
Text="请先登录"
Visibility="{Binding Users, Converter={StaticResource EmptyCollectionToVisibilityRevertConverter}}"/>
<TextBlock <TextBlock
Margin="10,6,0,6" Margin="10,6,0,6"
Style="{StaticResource BaseTextBlockStyle}" Style="{StaticResource BaseTextBlockStyle}"

View File

@@ -286,11 +286,6 @@ internal class AchievementViewModel
Archives = achievementService.GetArchiveCollection(); Archives = achievementService.GetArchiveCollection();
SelectedArchive = Archives.SingleOrDefault(a => a.IsSelected == true); SelectedArchive = Archives.SingleOrDefault(a => a.IsSelected == true);
if (SelectedArchive == null)
{
infoBarService.Warning("请创建一个成就存档");
}
} }
catch (TaskCanceledException) catch (TaskCanceledException)
{ {

View File

@@ -74,7 +74,6 @@ internal class AnnouncementViewModel : ObservableObject, ISupportCancellation
} }
catch (OperationCanceledException) catch (OperationCanceledException)
{ {
logger.LogInformation($"{nameof(OpenUIAsync)} cancelled");
} }
} }

View File

@@ -10,6 +10,7 @@ using Snap.Hutao.Model.Entity;
using Snap.Hutao.Service.Abstraction; using Snap.Hutao.Service.Abstraction;
using Snap.Hutao.Service.Cultivation; using Snap.Hutao.Service.Cultivation;
using Snap.Hutao.Service.Metadata; using Snap.Hutao.Service.Metadata;
using Snap.Hutao.Service.Navigation;
using Snap.Hutao.View.Dialog; using Snap.Hutao.View.Dialog;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
@@ -58,6 +59,7 @@ internal class CultivationViewModel : ObservableObject, ISupportCancellation
RemoveEntryCommand = asyncRelayCommandFactory.Create<Model.Binding.Cultivation.CultivateEntry>(RemoveEntryAsync); RemoveEntryCommand = asyncRelayCommandFactory.Create<Model.Binding.Cultivation.CultivateEntry>(RemoveEntryAsync);
SaveInventoryItemCommand = new RelayCommand<Model.Binding.Inventory.InventoryItem>(SaveInventoryItem); SaveInventoryItemCommand = new RelayCommand<Model.Binding.Inventory.InventoryItem>(SaveInventoryItem);
UpdateStatisticsItemsCommand = asyncRelayCommandFactory.Create(UpdateStatisticsItemsAsync); UpdateStatisticsItemsCommand = asyncRelayCommandFactory.Create(UpdateStatisticsItemsAsync);
NavigateToPageCommand = new RelayCommand<string>(NavigateToPage);
} }
/// <inheritdoc/> /// <inheritdoc/>
@@ -131,6 +133,11 @@ internal class CultivationViewModel : ObservableObject, ISupportCancellation
/// </summary> /// </summary>
public ICommand UpdateStatisticsItemsCommand { get; } public ICommand UpdateStatisticsItemsCommand { get; }
/// <summary>
/// 导航到指定的页面命令
/// </summary>
public ICommand NavigateToPageCommand { get; set; }
private async Task OpenUIAsync() private async Task OpenUIAsync()
{ {
if (await metadataService.InitializeAsync().ConfigureAwait(true)) if (await metadataService.InitializeAsync().ConfigureAwait(true))
@@ -154,6 +161,9 @@ internal class CultivationViewModel : ObservableObject, ISupportCancellation
{ {
case ProjectAddResult.Added: case ProjectAddResult.Added:
infoBarService.Success($"添加成功"); infoBarService.Success($"添加成功");
await ThreadHelper.SwitchToMainThreadAsync();
SelectedProject = project;
break; break;
case ProjectAddResult.InvalidName: case ProjectAddResult.InvalidName:
infoBarService.Information($"不能添加名称无效的计划"); infoBarService.Information($"不能添加名称无效的计划");
@@ -228,4 +238,13 @@ internal class CultivationViewModel : ObservableObject, ISupportCancellation
} }
} }
} }
private void NavigateToPage(string? typeString)
{
if (typeString != null)
{
Type? pageType = Type.GetType(typeString);
Ioc.Default.GetRequiredService<INavigationService>().Navigate(pageType!, INavigationAwaiter.Default, true);
}
}
} }

View File

@@ -44,7 +44,9 @@ internal class DailyNoteViewModel : ObservableObject, ISupportCancellation
private SettingEntry? refreshSecondsEntry; private SettingEntry? refreshSecondsEntry;
private SettingEntry? reminderNotifyEntry; private SettingEntry? reminderNotifyEntry;
private SettingEntry? silentModeEntry;
private ObservableCollection<DailyNoteEntry>? dailyNoteEntries; private ObservableCollection<DailyNoteEntry>? dailyNoteEntries;
private bool isSilentWhenPlayingGame;
/// <summary> /// <summary>
/// 构造一个新的实时便笺视图模型 /// 构造一个新的实时便笺视图模型
@@ -115,6 +117,22 @@ internal class DailyNoteViewModel : ObservableObject, ISupportCancellation
} }
} }
/// <summary>
/// 是否开启免打扰模式
/// </summary>
public bool IsSilentWhenPlayingGame
{
get => isSilentWhenPlayingGame;
set
{
if (SetProperty(ref isSilentWhenPlayingGame, value))
{
silentModeEntry!.SetBoolean(value);
appDbContext.Settings.UpdateAndSave(silentModeEntry!);
}
}
}
/// <summary> /// <summary>
/// 用户与角色集合 /// 用户与角色集合
/// </summary> /// </summary>
@@ -164,11 +182,17 @@ internal class DailyNoteViewModel : ObservableObject, ISupportCancellation
ScheduleTaskHelper.RegisterForDailyNoteRefresh(480); ScheduleTaskHelper.RegisterForDailyNoteRefresh(480);
OnPropertyChanged(nameof(SelectedRefreshTime)); OnPropertyChanged(nameof(SelectedRefreshTime));
reminderNotifyEntry = appDbContext.Settings.SingleOrAdd(SettingEntry.DailyNoteReminderNotify, false.ToString()); reminderNotifyEntry = appDbContext.Settings.SingleOrAdd(SettingEntry.DailyNoteReminderNotify, SettingEntryHelper.FalseString);
isReminderNotification = reminderNotifyEntry.GetBoolean(); isReminderNotification = reminderNotifyEntry.GetBoolean();
OnPropertyChanged(nameof(IsReminderNotification)); OnPropertyChanged(nameof(IsReminderNotification));
DailyNoteEntries = await dailyNoteService.GetDailyNoteEntriesAsync().ConfigureAwait(true); silentModeEntry = appDbContext.Settings.SingleOrAdd(SettingEntry.DailyNoteSilentWhenPlayingGame, SettingEntryHelper.FalseString);
isSilentWhenPlayingGame = silentModeEntry.GetBoolean();
OnPropertyChanged(nameof(IsSilentWhenPlayingGame));
ObservableCollection<DailyNoteEntry> temp = await dailyNoteService.GetDailyNoteEntriesAsync().ConfigureAwait(false);
await ThreadHelper.SwitchToMainThreadAsync();
DailyNoteEntries = temp;
} }
private async Task TrackRoleAsync(UserAndRole? role) private async Task TrackRoleAsync(UserAndRole? role)

View File

@@ -184,11 +184,6 @@ internal class GachaLogViewModel : ObservableObject, ISupportCancellation
Archives = gachaLogService.GetArchiveCollection(); Archives = gachaLogService.GetArchiveCollection();
SelectedArchive = Archives.SingleOrDefault(a => a.IsSelected == true); SelectedArchive = Archives.SingleOrDefault(a => a.IsSelected == true);
if (SelectedArchive == null)
{
infoBarService.Information("请刷新或导入祈愿记录");
}
await ThreadHelper.SwitchToMainThreadAsync(); await ThreadHelper.SwitchToMainThreadAsync();
IsInitialized = true; IsInitialized = true;
} }

View File

@@ -120,6 +120,12 @@ internal class UserViewModel : ObservableObject
switch (optionResult) switch (optionResult)
{ {
case UserOptionResult.Added: case UserOptionResult.Added:
if (Users!.Count == 1)
{
await ThreadHelper.SwitchToMainThreadAsync();
SelectedUser = Users.Single();
}
infoBarService.Success($"用户 [{uid}] 添加成功"); infoBarService.Success($"用户 [{uid}] 添加成功");
break; break;
case UserOptionResult.Incomplete: case UserOptionResult.Incomplete:

View File

@@ -124,7 +124,7 @@ public class MiHoYoJSInterface
[JsMethod("getDS")] [JsMethod("getDS")]
public virtual JsResult<Dictionary<string, string>> GetDynamicSecrectV1(JsParam param) public virtual JsResult<Dictionary<string, string>> GetDynamicSecrectV1(JsParam param)
{ {
string salt = DynamicSecretHandler.DynamicSecrets[nameof(SaltType.LK2)]; string salt = Core.CoreEnvironment.DynamicSecrets[nameof(SaltType.LK2)];
long t = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); long t = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
string r = GetRandomString(); string r = GetRandomString();
string check = Md5Convert.ToHexString($"salt={salt}&t={t}&r={r}").ToLowerInvariant(); string check = Md5Convert.ToHexString($"salt={salt}&t={t}&r={r}").ToLowerInvariant();
@@ -155,7 +155,7 @@ public class MiHoYoJSInterface
[JsMethod("getDS2")] [JsMethod("getDS2")]
public virtual JsResult<Dictionary<string, string>> GetDynamicSecrectV2(JsParam<DynamicSecrect2Playload> param) public virtual JsResult<Dictionary<string, string>> GetDynamicSecrectV2(JsParam<DynamicSecrect2Playload> param)
{ {
string salt = DynamicSecretHandler.DynamicSecrets[nameof(SaltType.X4)]; string salt = Core.CoreEnvironment.DynamicSecrets[nameof(SaltType.X4)];
long t = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); long t = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
int r = GetRandom(); int r = GetRandom();
string b = param.Payload.Body; string b = param.Payload.Body;

View File

@@ -15,19 +15,6 @@ namespace Snap.Hutao.Web.Hoyolab.DynamicSecret;
[Injection(InjectAs.Transient)] [Injection(InjectAs.Transient)]
public class DynamicSecretHandler : DelegatingHandler public class DynamicSecretHandler : DelegatingHandler
{ {
/// <summary>
/// 盐
/// </summary>
// https://github.com/UIGF-org/Hoyolab.Salt
public static readonly ImmutableDictionary<string, string> DynamicSecrets = new Dictionary<string, string>()
{
[nameof(SaltType.K2)] = "jrU9ULHGZdM9Os3uGHOpjyRELYxby5cg",
[nameof(SaltType.LK2)] = "9gaxOdeeY2W9dw5x62pywhik8cxy5TIJ",
[nameof(SaltType.X4)] = "xV8v4Qu54lUKrEYFZkJhB8cuOh9Asafs",
[nameof(SaltType.X6)] = "t0qEgfub6cvueAPgR5m9aQWWVciEer7v",
[nameof(SaltType.PROD)] = "JwYDpKvLj6MrMqqYU6jTKF17KNO2PXoS",
}.ToImmutableDictionary();
private const string RandomRange = "abcdefghijklmnopqrstuvwxyz1234567890"; private const string RandomRange = "abcdefghijklmnopqrstuvwxyz1234567890";
/// <inheritdoc/> /// <inheritdoc/>
@@ -40,7 +27,7 @@ public class DynamicSecretHandler : DelegatingHandler
string saltType = definations[1]; string saltType = definations[1];
bool includeChars = definations[2] == "true"; bool includeChars = definations[2] == "true";
string salt = DynamicSecrets[saltType]; string salt = Core.CoreEnvironment.DynamicSecrets[saltType];
long t = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); long t = DateTimeOffset.UtcNow.ToUnixTimeSeconds();