Compare commits

..

7 Commits
1.9.0 ... 1.9.1

Author SHA1 Message Date
DismissedLight
b11526761e Merge pull request #1214 from DGP-Studio/develop 2023-12-23 19:19:45 +08:00
DismissedLight
d293149672 1.9.1 package 2023-12-23 19:18:29 +08:00
DismissedLight
3784df67a3 adjust launch page ui 2023-12-23 19:15:04 +08:00
DismissedLight
4aaca4d19f fix reentrant issue 2023-12-23 18:51:41 +08:00
DismissedLight
e6cf39831d fix daily note fetch uid crash 2023-12-23 18:22:12 +08:00
DismissedLight
24a2a18760 fix #1212 2023-12-23 17:34:44 +08:00
DismissedLight
d8dce5c062 empty sha256 tolerance 2023-12-23 14:48:24 +08:00
10 changed files with 37 additions and 44 deletions

View File

@@ -31,4 +31,5 @@
<x:String x:Key="UI_EmotionIcon250">https://api.snapgenshin.com/static/raw/EmotionIcon/UI_EmotionIcon250.png</x:String> <x:String x:Key="UI_EmotionIcon250">https://api.snapgenshin.com/static/raw/EmotionIcon/UI_EmotionIcon250.png</x:String>
<x:String x:Key="UI_EmotionIcon272">https://api.snapgenshin.com/static/raw/EmotionIcon/UI_EmotionIcon272.png</x:String> <x:String x:Key="UI_EmotionIcon272">https://api.snapgenshin.com/static/raw/EmotionIcon/UI_EmotionIcon272.png</x:String>
<x:String x:Key="UI_EmotionIcon293">https://api.snapgenshin.com/static/raw/EmotionIcon/UI_EmotionIcon293.png</x:String> <x:String x:Key="UI_EmotionIcon293">https://api.snapgenshin.com/static/raw/EmotionIcon/UI_EmotionIcon293.png</x:String>
<x:String x:Key="UI_EmotionIcon445">https://api.snapgenshin.com/static/raw/EmotionIcon/UI_EmotionIcon445.png</x:String>
</ResourceDictionary> </ResourceDictionary>

View File

@@ -1,19 +0,0 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using System.Collections.Concurrent;
using System.Runtime.CompilerServices;
namespace Snap.Hutao.Core.Threading;
internal sealed class Throttler
{
private readonly ConcurrentDictionary<string, SemaphoreSlim> methodSemaphoreMap = new();
public ValueTask<SemaphoreSlimToken> ThrottleAsync(CancellationToken token = default, [CallerMemberName] string callerName = default!, [CallerLineNumber] int callerLine = 0)
{
string key = $"{callerName}L{callerLine}";
SemaphoreSlim semaphore = methodSemaphoreMap.GetOrAdd(key, name => new SemaphoreSlim(1));
return semaphore.EnterAsync(token);
}
}

View File

@@ -12,7 +12,7 @@
<Identity <Identity
Name="60568DGPStudio.SnapHutao" Name="60568DGPStudio.SnapHutao"
Publisher="CN=35C8E923-85DF-49A7-9172-B39DC6312C52" Publisher="CN=35C8E923-85DF-49A7-9172-B39DC6312C52"
Version="1.9.0.0" /> Version="1.9.1.0" />
<Properties> <Properties>
<DisplayName>Snap Hutao</DisplayName> <DisplayName>Snap Hutao</DisplayName>

View File

@@ -12,7 +12,7 @@
<Identity <Identity
Name="60568DGPStudio.SnapHutaoDev" Name="60568DGPStudio.SnapHutaoDev"
Publisher="CN=35C8E923-85DF-49A7-9172-B39DC6312C52" Publisher="CN=35C8E923-85DF-49A7-9172-B39DC6312C52"
Version="1.9.0.0" /> Version="1.9.1.0" />
<Properties> <Properties>
<DisplayName>Snap Hutao Dev</DisplayName> <DisplayName>Snap Hutao Dev</DisplayName>

View File

@@ -2144,6 +2144,9 @@
<data name="ViewPageLaunchGameResourcePreDownloadHeader" xml:space="preserve"> <data name="ViewPageLaunchGameResourcePreDownloadHeader" xml:space="preserve">
<value>预下载</value> <value>预下载</value>
</data> </data>
<data name="ViewPageLaunchGameSelectGamePath" xml:space="preserve">
<value>选择游戏路径</value>
</data>
<data name="ViewPageLaunchGameSwitchAccountAttachUidNull" xml:space="preserve"> <data name="ViewPageLaunchGameSwitchAccountAttachUidNull" xml:space="preserve">
<value>该账号尚未绑定实时便笺通知 UID</value> <value>该账号尚未绑定实时便笺通知 UID</value>
</data> </data>

View File

@@ -77,7 +77,7 @@ internal sealed partial class DailyNoteService : IDailyNoteService, IRecipient<U
List<DailyNoteEntry> entryList = await dailyNoteDbService.GetDailyNoteEntryIncludeUserListAsync().ConfigureAwait(false); List<DailyNoteEntry> entryList = await dailyNoteDbService.GetDailyNoteEntryIncludeUserListAsync().ConfigureAwait(false);
entryList.ForEach(entry => { entry.UserGameRole = userService.GetUserGameRoleByUid(entry.Uid); }); entryList.ForEach(entry => { entry.UserGameRole = userService.GetUserGameRoleByUid(entry.Uid); });
entries = new(entryList); entries = entryList.ToObservableCollection();
} }
return entries; return entries;

View File

@@ -49,7 +49,7 @@ internal sealed partial class UpdateService : IUpdateService
progress.Report(new(versionInformation.Version.ToString(), 0, 0)); progress.Report(new(versionInformation.Version.ToString(), 0, 0));
if (versionInformation.Sha256 is not { } sha256) if (versionInformation.Sha256 is not { Length: > 0 } sha256)
{ {
return false; return false;
} }

View File

@@ -14,7 +14,7 @@ namespace Snap.Hutao.Service.User;
[ConstructorGenerated] [ConstructorGenerated]
[Injection(InjectAs.Singleton, typeof(IUserCollectionService))] [Injection(InjectAs.Singleton, typeof(IUserCollectionService))]
internal sealed partial class UserCollectionService : IUserCollectionService internal sealed partial class UserCollectionService : IUserCollectionService, IDisposable
{ {
private readonly ScopedDbCurrent<BindingUser, Model.Entity.User, UserChangedMessage> dbCurrent; private readonly ScopedDbCurrent<BindingUser, Model.Entity.User, UserChangedMessage> dbCurrent;
private readonly IUserInitializationService userInitializationService; private readonly IUserInitializationService userInitializationService;
@@ -22,7 +22,7 @@ internal sealed partial class UserCollectionService : IUserCollectionService
private readonly ITaskContext taskContext; private readonly ITaskContext taskContext;
private readonly IMessenger messenger; private readonly IMessenger messenger;
private readonly Throttler throttler = new(); private readonly SemaphoreSlim throttler = new(1);
private ObservableCollection<BindingUser>? userCollection; private ObservableCollection<BindingUser>? userCollection;
private Dictionary<string, BindingUser>? midUserMap; private Dictionary<string, BindingUser>? midUserMap;
@@ -38,7 +38,9 @@ internal sealed partial class UserCollectionService : IUserCollectionService
public async ValueTask<ObservableCollection<BindingUser>> GetUserCollectionAsync() public async ValueTask<ObservableCollection<BindingUser>> GetUserCollectionAsync()
{ {
using (await throttler.ThrottleAsync().ConfigureAwait(false)) // Force run in background thread, otherwise will cause reentrance
await Task.CompletedTask.ConfigureAwait(ConfigureAwaitOptions.ForceYielding);
using (await throttler.EnterAsync().ConfigureAwait(false))
{ {
if (userCollection is null) if (userCollection is null)
{ {
@@ -131,17 +133,7 @@ internal sealed partial class UserCollectionService : IUserCollectionService
return default; return default;
} }
try return uidUserGameRoleMap.GetValueOrDefault(uid);
{
return uidUserGameRoleMap[uid];
}
catch (InvalidOperationException)
{
// Sequence contains more than one matching element
// TODO: return a specialize UserGameRole to indicate error
}
return default;
} }
public bool TryGetUserByMid(string mid, [NotNullWhen(true)] out BindingUser? user) public bool TryGetUserByMid(string mid, [NotNullWhen(true)] out BindingUser? user)
@@ -186,4 +178,9 @@ internal sealed partial class UserCollectionService : IUserCollectionService
ArgumentNullException.ThrowIfNull(newUser.UserInfo); ArgumentNullException.ThrowIfNull(newUser.UserInfo);
return new(UserOptionResult.Added, newUser.UserInfo.Uid); return new(UserOptionResult.Added, newUser.UserInfo.Uid);
} }
public void Dispose()
{
throttler.Dispose();
}
} }

View File

@@ -13,6 +13,7 @@
xmlns:shcb="using:Snap.Hutao.Control.Behavior" xmlns:shcb="using:Snap.Hutao.Control.Behavior"
xmlns:shccs="using:Snap.Hutao.Control.Collection.Selector" xmlns:shccs="using:Snap.Hutao.Control.Collection.Selector"
xmlns:shch="using:Snap.Hutao.Control.Helper" xmlns:shch="using:Snap.Hutao.Control.Helper"
xmlns:shci="using:Snap.Hutao.Control.Image"
xmlns:shcm="using:Snap.Hutao.Control.Markup" xmlns:shcm="using:Snap.Hutao.Control.Markup"
xmlns:shvc="using:Snap.Hutao.View.Control" xmlns:shvc="using:Snap.Hutao.View.Control"
xmlns:shvg="using:Snap.Hutao.ViewModel.Game" xmlns:shvg="using:Snap.Hutao.ViewModel.Game"
@@ -346,10 +347,20 @@
</Grid> </Grid>
<Grid Visibility="{Binding GamePathSelectedAndValid, Converter={StaticResource BoolToVisibilityRevertConverter}}"> <Grid Visibility="{Binding GamePathSelectedAndValid, Converter={StaticResource BoolToVisibilityRevertConverter}}">
<StackPanel <StackPanel
MaxWidth="600" Margin="128,0"
HorizontalAlignment="Center" HorizontalAlignment="Center"
VerticalAlignment="Center" VerticalAlignment="Center"
Spacing="3"> Spacing="3">
<shci:CachedImage
Width="120"
Height="120"
EnableLazyLoading="False"
Source="{StaticResource UI_EmotionIcon445}"/>
<TextBlock
Margin="0,5,0,21"
HorizontalAlignment="Center"
Style="{StaticResource SubtitleTextBlockStyle}"
Text="{shcm:ResourceString Name=ViewPageLaunchGameSelectGamePath}"/>
<Border Style="{ThemeResource BorderCardStyle}"> <Border Style="{ThemeResource BorderCardStyle}">
<ListView <ListView
ItemTemplate="{StaticResource GamePathEntryListTemplate}" ItemTemplate="{StaticResource GamePathEntryListTemplate}"

View File

@@ -136,17 +136,17 @@
Background="{ThemeResource SystemFillColorSuccessBackgroundBrush}" Background="{ThemeResource SystemFillColorSuccessBackgroundBrush}"
Description="{shcm:ResourceString Name=ViewPageSettingHutaoPassportLicensedDeveloperDescription}" Description="{shcm:ResourceString Name=ViewPageSettingHutaoPassportLicensedDeveloperDescription}"
Header="{shcm:ResourceString Name=ViewPageSettingHutaoPassportLicensedDeveloperHeader}" Header="{shcm:ResourceString Name=ViewPageSettingHutaoPassportLicensedDeveloperHeader}"
Visibility="{Binding UserOptions.IsLicensedDeveloper, Converter={StaticResource BoolToVisibilityConverter}}"/> Visibility="{Binding UserOptions.IsLicensedDeveloper, Converter={StaticResource BoolToVisibilityConverter}}">
<cwc:SettingsCard
Background="{ThemeResource SystemFillColorSuccessBackgroundBrush}"
Description="{shcm:ResourceString Name=ViewPageSettingHutaoPassportMaintainerDescription}"
Header="{shcm:ResourceString Name=ViewPageSettingHutaoPassportMaintainerHeader}"
Visibility="{Binding UserOptions.IsMaintainer, Converter={StaticResource BoolToVisibilityConverter}}">
<Button <Button
Command="{Binding OpenTestPageCommand}" Command="{Binding OpenTestPageCommand}"
Content="TEST" Content="TEST"
Style="{ThemeResource SettingButtonStyle}"/> Style="{ThemeResource SettingButtonStyle}"/>
</cwc:SettingsCard> </cwc:SettingsCard>
<cwc:SettingsCard
Background="{ThemeResource SystemFillColorSuccessBackgroundBrush}"
Description="{shcm:ResourceString Name=ViewPageSettingHutaoPassportMaintainerDescription}"
Header="{shcm:ResourceString Name=ViewPageSettingHutaoPassportMaintainerHeader}"
Visibility="{Binding UserOptions.IsMaintainer, Converter={StaticResource BoolToVisibilityConverter}}"/>
<cwc:SettingsCard Description="{Binding UserOptions.GachaLogExpireAtSlim}" Header="{shcm:ResourceString Name=ViewPageSettingHutaoPassportGachaLogExpiredAtHeader}"/> <cwc:SettingsCard Description="{Binding UserOptions.GachaLogExpireAtSlim}" Header="{shcm:ResourceString Name=ViewPageSettingHutaoPassportGachaLogExpiredAtHeader}"/>
<cwc:SettingsCard <cwc:SettingsCard
Command="{Binding Passport.OpenRedeemWebsiteCommand}" Command="{Binding Passport.OpenRedeemWebsiteCommand}"