[skip ci] broken

This commit is contained in:
DismissedLight
2024-06-30 22:50:19 +08:00
parent dc6dc94b45
commit d97bd4fd79
32 changed files with 100 additions and 339 deletions

View File

@@ -1,6 +1,7 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using CommunityToolkit.Mvvm.Messaging;
using Microsoft.EntityFrameworkCore;
using Snap.Hutao.Core.Database.Abstraction;
using Snap.Hutao.Model;
@@ -52,6 +53,10 @@ internal sealed class AdvancedDbCollectionView<TEntity> : AdvancedCollectionView
dbContext.Set<TEntity>().UpdateAndSave(currentItem);
}
}
serviceProvider
.GetRequiredService<IMessenger>()
.Send(new AdvancedDbCollectionViewCurrentChangedMessage<TEntity>(currentItem));
}
}
@@ -100,5 +105,9 @@ internal sealed class AdvancedDbCollectionView<TEntityAccess, TEntity> : Advance
dbContext.Set<TEntity>().UpdateAndSave(currentItem.Entity);
}
}
serviceProvider
.GetRequiredService<IMessenger>()
.Send(new AdvancedDbCollectionViewCurrentChangedMessage<TEntityAccess>(currentItem));
}
}

View File

@@ -0,0 +1,15 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Core.Database;
internal sealed class AdvancedDbCollectionViewCurrentChangedMessage<TItem>
where TItem : class
{
public AdvancedDbCollectionViewCurrentChangedMessage(TItem? currentItem)
{
CurrentItem = currentItem;
}
public TItem? CurrentItem { get; }
}

View File

@@ -44,7 +44,7 @@ internal static class DependencyInjection
.AddConfiguredHttpClients()
// Discrete services
.AddSingleton<IMessenger, WeakReferenceMessenger>()
.AddSingleton<IMessenger, StrongReferenceMessenger>()
.BuildServiceProvider(true);
Ioc.Default.ConfigureServices(serviceProvider);

View File

@@ -26,7 +26,7 @@ internal sealed partial class HttpProxyUsingSystemProxy : ObservableObject, IWeb
UpdateInnerProxy();
watcher = new(ProxySettingPath, OnSystemProxySettingsChanged);
watcher.Start();
watcher.Start(serviceProvider.GetRequiredService<ILogger<HttpProxyUsingSystemProxy>>());
}
public string CurrentProxyUri

View File

@@ -24,7 +24,9 @@ internal static class TaskExtension
return new(task);
}
#if NET9_0_OR_GREATER
[Obsolete("SafeForget without logger is not recommended.")]
#endif
public static async void SafeForget(this Task task)
{
try
@@ -101,7 +103,9 @@ internal static class TaskExtension
}
}
#if NET9_0_OR_GREATER
[Obsolete("SafeForget without logger is not recommended.")]
#endif
public static async void SafeForget(this ValueTask task)
{
try

View File

@@ -1,7 +0,0 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Message;
[Obsolete]
internal sealed class BackgroundImageTypeChangedMessage;

View File

@@ -1,15 +0,0 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Snap.Hutao.Model.Entity;
namespace Snap.Hutao.Message;
/// <summary>
/// 养成计划切换消息
/// </summary>
[HighQuality]
[Obsolete]
internal sealed class CultivateProjectChangedMessage : ValueChangedMessage<CultivateProject>
{
}

View File

@@ -1,15 +0,0 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Snap.Hutao.Model.Entity;
namespace Snap.Hutao.Message;
/// <summary>
/// 祈愿记录存档切换消息
/// </summary>
[HighQuality]
[Obsolete]
internal sealed class GachaArchiveChangedMessage : ValueChangedMessage<GachaArchive>
{
}

View File

@@ -1,12 +0,0 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Message;
internal enum UserChangeFlag
{
// This flag is impossible to appear alone
UserChanged = 0b0001,
RoleChanged = 0b0010,
UserAndRoleChanged = UserChanged | RoleChanged,
}

View File

@@ -1,60 +0,0 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Snap.Hutao.ViewModel.User;
using System.Diagnostics;
using System.Text;
namespace Snap.Hutao.Message;
/// <summary>
/// 用户切换消息
/// </summary>
[HighQuality]
[DebuggerDisplay("{DebuggerDisplay(),nq}")]
[Obsolete]
internal sealed class UserChangedMessage : ValueChangedMessage<User>
{
// defaults to the UserAndRoleChanged when we raise this message in ScopedDbCurrent
public UserChangeFlag Flag { get; private set; } = UserChangeFlag.UserAndRoleChanged;
public bool IsOnlyRoleChanged { get => Flag == UserChangeFlag.RoleChanged; }
public static UserChangedMessage Create(User oldValue, User newValue, UserChangeFlag flag)
{
return new UserChangedMessage
{
OldValue = oldValue,
NewValue = newValue,
Flag = flag,
};
}
public static UserChangedMessage CreateOnlyRoleChanged(User value)
{
return Create(value, value, UserChangeFlag.RoleChanged);
}
#if DEBUG
private string DebuggerDisplay()
{
StringBuilder stringBuilder = new();
stringBuilder
.Append("Name:")
.Append(OldValue?.UserInfo?.Nickname)
.Append("|Role[")
.Append(OldValue?.UserGameRoles?.Count)
.Append("]:<")
.Append(OldValue?.SelectedUserGameRole)
.Append("> -> Name:")
.Append(NewValue?.UserInfo?.Nickname)
.Append("|Role[")
.Append(NewValue?.UserGameRoles?.Count)
.Append("]:<")
.Append(NewValue?.SelectedUserGameRole)
.Append('>');
return stringBuilder.ToString();
}
#endif
}

View File

@@ -1,28 +0,0 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Snap.Hutao.Model.Entity;
namespace Snap.Hutao.Message;
/// <summary>
/// 用户删除消息
/// </summary>
[HighQuality]
[Obsolete]
internal sealed class UserRemovedMessage
{
/// <summary>
/// 构造一个新的用户删除消息
/// </summary>
/// <param name="user">用户</param>
public UserRemovedMessage(User user)
{
RemovedUserId = user.InnerId;
}
/// <summary>
/// 删除的用户Id
/// </summary>
public Guid RemovedUserId { get; }
}

View File

@@ -1,45 +0,0 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Message;
/// <summary>
/// 值变化消息
/// </summary>
/// <typeparam name="TValue">值的类型</typeparam>
[HighQuality]
[Obsolete]
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
internal abstract class ValueChangedMessage<TValue>
where TValue : class
{
/// <summary>
/// 动态访问
/// </summary>
public ValueChangedMessage()
{
}
/// <summary>
/// 构造一个新的值变化消息
/// </summary>
/// <param name="oldValue">旧值</param>
/// <param name="newValue">新值</param>
protected ValueChangedMessage(TValue? oldValue, TValue? newValue)
{
OldValue = oldValue;
NewValue = newValue;
}
/// <summary>
/// 旧的值
/// </summary>
public TValue? OldValue { get; set; }
/// <summary>
/// 新的值
/// </summary>
public TValue? NewValue { get; set; }
public Guid UniqueMessageId { get; } = Guid.NewGuid();
}

View File

@@ -64,24 +64,15 @@ internal sealed partial class AchievementDbService : IAchievementDbService
}
}
public async ValueTask OverwriteAchievementAsync(EntityAchievement achievement, CancellationToken token = default)
{
await this.DeleteByInnerIdAsync(achievement, token).ConfigureAwait(false);
if (achievement.Status >= Model.Intrinsic.AchievementStatus.STATUS_FINISHED)
{
await this.AddAsync(achievement, token).ConfigureAwait(false);
}
}
public ObservableCollection<AchievementArchive> GetAchievementArchiveCollection()
{
return this.ObservableCollection<AchievementArchive>();
}
public async ValueTask RemoveAchievementArchiveAsync(AchievementArchive archive, CancellationToken token = default)
public void RemoveAchievementArchive(AchievementArchive archive)
{
// It will cascade delete the achievements.
await this.DeleteAsync(archive, token).ConfigureAwait(false);
this.Delete(archive);
}
public List<EntityAchievement> GetAchievementListByArchiveId(Guid archiveId)

View File

@@ -77,7 +77,7 @@ internal sealed partial class AchievementService : IAchievementService
// Sync database
await taskContext.SwitchToBackgroundAsync();
await achievementDbService.RemoveAchievementArchiveAsync(archive).ConfigureAwait(false);
achievementDbService.RemoveAchievementArchive(archive);
}
public async ValueTask<ImportResult> ImportFromUIAFAsync(AchievementArchive archive, List<UIAFItem> list, ImportStrategyKind strategy)

View File

@@ -10,8 +10,6 @@ namespace Snap.Hutao.Service.Achievement;
internal interface IAchievementDbService : IAppDbService<Model.Entity.AchievementArchive>, IAppDbService<EntityAchievement>
{
ValueTask RemoveAchievementArchiveAsync(Model.Entity.AchievementArchive archive, CancellationToken token = default);
ObservableCollection<Model.Entity.AchievementArchive> GetAchievementArchiveCollection();
List<Model.Entity.AchievementArchive> GetAchievementArchiveList();
@@ -30,5 +28,5 @@ internal interface IAchievementDbService : IAppDbService<Model.Entity.Achievemen
void OverwriteAchievement(EntityAchievement achievement);
ValueTask OverwriteAchievementAsync(EntityAchievement achievement, CancellationToken token = default);
void RemoveAchievementArchive(Model.Entity.AchievementArchive archive);
}

View File

@@ -1,9 +1,7 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using CommunityToolkit.Mvvm.Messaging;
using Snap.Hutao.Core.DependencyInjection.Abstraction;
using Snap.Hutao.Message;
using Snap.Hutao.Model.Entity;
using Snap.Hutao.Service.Abstraction;
using Snap.Hutao.Service.Metadata;
@@ -18,13 +16,9 @@ using WebDailyNote = Snap.Hutao.Web.Hoyolab.Takumi.GameRecord.DailyNote.DailyNot
namespace Snap.Hutao.Service.DailyNote;
/// <summary>
/// 实时便笺服务
/// </summary>
[HighQuality]
[ConstructorGenerated]
[Injection(InjectAs.Singleton, typeof(IDailyNoteService))]
internal sealed partial class DailyNoteService : IDailyNoteService, IRecipient<UserRemovedMessage>
internal sealed partial class DailyNoteService : IDailyNoteService
{
private readonly DailyNoteNotificationOperation dailyNoteNotificationOperation;
private readonly IServiceProvider serviceProvider;
@@ -176,4 +170,4 @@ internal sealed partial class DailyNoteService : IDailyNoteService, IRecipient<U
}
}
}
}
}

View File

@@ -6,7 +6,6 @@ using Snap.Hutao.Model.Entity;
using Snap.Hutao.Model.InterChange.GachaLog;
using Snap.Hutao.Service.GachaLog.QueryProvider;
using Snap.Hutao.ViewModel.GachaLog;
using System.Collections.ObjectModel;
namespace Snap.Hutao.Service.GachaLog;

View File

@@ -4,7 +4,6 @@
using Snap.Hutao.Core.IO;
using Snap.Hutao.Service.Game;
using System.Collections.Specialized;
using System.Globalization;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
@@ -64,6 +63,7 @@ internal sealed partial class GachaLogQueryWebCacheProvider : IGachaLogQueryProv
return new(false, GachaLogQuery.Invalid(SH.FormatServiceGachaLogUrlProviderCachePathNotFound(cacheFile)));
}
// TODO: prevent allocation there
using (FileStream fileStream = new(file.Path, FileMode.Open, FileAccess.Read, FileShare.Read))
{
using (MemoryStream memoryStream = new())

View File

@@ -12,11 +12,9 @@ namespace Snap.Hutao.Service.User;
internal interface IUserCollectionService
{
BindingUser? CurrentUser { get; set; }
ValueTask<ObservableCollection<UserAndUid>> GetUserAndUidCollectionAsync();
ValueTask<ObservableReorderableDbCollection<BindingUser, EntityUser>> GetUserCollectionAsync();
ValueTask<AdvancedDbCollectionView<BindingUser, EntityUser>> GetUserCollectionAsync();
UserGameRole? GetUserGameRoleByUid(string uid);

View File

@@ -2,56 +2,20 @@
// Licensed under the MIT license.
using Snap.Hutao.Core.Database;
using Snap.Hutao.ViewModel.User;
using Snap.Hutao.Web.Hoyolab.Takumi.Binding;
using System.Collections.ObjectModel;
using BindingUser = Snap.Hutao.ViewModel.User.User;
using EntityUser = Snap.Hutao.Model.Entity.User;
namespace Snap.Hutao.Service.User;
/// <summary>
/// 用户服务
/// </summary>
[HighQuality]
internal interface IUserService
{
/// <summary>
/// 获取或设置当前用户
/// </summary>
BindingUser? Current { get; set; }
/// <summary>
/// 异步获取角色与用户集合
/// </summary>
/// <returns>角色与用户集合</returns>
ValueTask<ObservableCollection<UserAndUid>> GetRoleCollectionAsync();
/// <summary>
/// 初始化用户服务及所有用户
/// 异步获取同步的用户信息集合
/// 对集合的操作应通过服务抽象完成
/// 此操作不能取消
/// </summary>
/// <returns>准备完成的用户信息集合</returns>
ValueTask<ObservableReorderableDbCollection<BindingUser, EntityUser>> GetUserCollectionAsync();
/// <summary>
/// 获取角色信息
/// </summary>
/// <param name="uid">uid</param>
/// <returns>对应的角色信息</returns>
UserGameRole? GetUserGameRoleByUid(string uid);
ValueTask<AdvancedDbCollectionView<BindingUser, EntityUser>> GetUserCollectionAsync();
ValueTask<ValueResult<UserOptionResult, string>> ProcessInputCookieAsync(InputCookie inputCookie);
ValueTask<bool> RefreshCookieTokenAsync(Model.Entity.User user);
ValueTask<bool> RefreshCookieTokenAsync(EntityUser user);
/// <summary>
/// 异步移除用户
/// </summary>
/// <param name="user">待移除的用户</param>
/// <returns>任务</returns>
ValueTask RemoveUserAsync(BindingUser user);
ValueTask RefreshProfilePictureAsync(UserGameRole userGameRole);

View File

@@ -5,5 +5,5 @@ namespace Snap.Hutao.Service.User;
internal interface IUserServiceUnsafe
{
ValueTask UnsafeRemoveUsersAsync();
ValueTask UnsafeRemoveAllUsersAsync();
}

View File

@@ -3,7 +3,6 @@
using CommunityToolkit.Mvvm.Messaging;
using Snap.Hutao.Core.Database;
using Snap.Hutao.Message;
using Snap.Hutao.ViewModel.User;
using Snap.Hutao.Web.Hoyolab.Takumi.Binding;
using System.Collections.ObjectModel;
@@ -16,7 +15,6 @@ namespace Snap.Hutao.Service.User;
[Injection(InjectAs.Singleton, typeof(IUserCollectionService))]
internal sealed partial class UserCollectionService : IUserCollectionService, IDisposable
{
private readonly ScopedDbCurrent<BindingUser, EntityUser, UserChangedMessage> dbCurrent;
private readonly IUserInitializationService userInitializationService;
private readonly IServiceProvider serviceProvider;
private readonly IUserDbService userDbService;
@@ -25,37 +23,21 @@ internal sealed partial class UserCollectionService : IUserCollectionService, ID
private readonly SemaphoreSlim throttler = new(1);
private ObservableReorderableDbCollection<BindingUser, EntityUser>? userCollection;
private Dictionary<string, BindingUser>? midUserMap;
private AdvancedDbCollectionView<BindingUser, EntityUser>? users;
private ObservableCollection<UserAndUid>? userAndUidCollection;
private Dictionary<string, UserGameRole>? uidUserGameRoleMap;
public BindingUser? CurrentUser
{
get => dbCurrent.Current;
set => dbCurrent.Current = value;
}
public async ValueTask<ObservableReorderableDbCollection<BindingUser, EntityUser>> GetUserCollectionAsync()
public async ValueTask<AdvancedDbCollectionView<BindingUser, EntityUser>> GetUserCollectionAsync()
{
// Force run in background thread, otherwise will cause reentrance
await taskContext.SwitchToBackgroundAsync();
using (await throttler.EnterAsync().ConfigureAwait(false))
{
if (userCollection is null)
if (users is null)
{
List<EntityUser> entities = await userDbService.GetUserListAsync().ConfigureAwait(false);
List<BindingUser> users = await entities.SelectListAsync(userInitializationService.ResumeUserAsync).ConfigureAwait(false);
midUserMap = [];
foreach (BindingUser user in users)
{
if (user.Entity.Mid is not null)
{
midUserMap[user.Entity.Mid] = user;
}
if (user.NeedDbUpdateAfterResume)
{
await userDbService.UpdateUserAsync(user.Entity).ConfigureAwait(false);
@@ -63,25 +45,12 @@ internal sealed partial class UserCollectionService : IUserCollectionService, ID
}
}
userCollection = users.ToObservableReorderableDbCollection<BindingUser, EntityUser>(serviceProvider);
try
{
CurrentUser = users.SelectedOrDefault();
}
catch (InvalidOperationException)
{
foreach (BindingUser user in users)
{
user.IsSelected = false;
}
await userDbService.ClearUserSelectionAsync().ConfigureAwait(false);
}
await taskContext.SwitchToMainThreadAsync();
this.users = new(users.ToObservableReorderableDbCollection<BindingUser, EntityUser>(serviceProvider), serviceProvider);
}
}
return userCollection;
return users;
}
public async ValueTask<ObservableCollection<UserAndUid>> GetUserAndUidCollectionAsync()
@@ -112,8 +81,8 @@ internal sealed partial class UserCollectionService : IUserCollectionService, ID
{
// Sync cache
await taskContext.SwitchToMainThreadAsync();
ArgumentNullException.ThrowIfNull(userCollection);
userCollection.Remove(user);
ArgumentNullException.ThrowIfNull(users);
users.Remove(user);
userAndUidCollection?.RemoveWhere(r => r.User.Mid == user.Entity.Mid);
if (user.Entity.Mid is not null)
{
@@ -159,11 +128,11 @@ internal sealed partial class UserCollectionService : IUserCollectionService, ID
}
await GetUserCollectionAsync().ConfigureAwait(false);
ArgumentNullException.ThrowIfNull(userCollection);
ArgumentNullException.ThrowIfNull(users);
// Sync cache
await taskContext.SwitchToMainThreadAsync();
userCollection.Add(newUser); // Database synced in the collection
users.Add(newUser); // Database synced in the collection
if (newUser.Entity.Mid is not null)
{
midUserMap?.Add(newUser.Entity.Mid, newUser);

View File

@@ -9,14 +9,12 @@ using Snap.Hutao.Web.Hoyolab.Passport;
using Snap.Hutao.Web.Hoyolab.Takumi.Binding;
using Snap.Hutao.Web.Response;
using System.Collections.ObjectModel;
using Windows.Foundation;
using BindingUser = Snap.Hutao.ViewModel.User.User;
using EntityUser = Snap.Hutao.Model.Entity.User;
namespace Snap.Hutao.Service.User;
/// <summary>
/// 用户服务
/// </summary>
[ConstructorGenerated]
[Injection(InjectAs.Singleton, typeof(IUserService))]
internal sealed partial class UserService : IUserService, IUserServiceUnsafe
@@ -27,24 +25,18 @@ internal sealed partial class UserService : IUserService, IUserServiceUnsafe
private readonly IUserDbService userDbService;
private readonly ITaskContext taskContext;
public BindingUser? Current
{
get => userCollectionService.CurrentUser;
set => userCollectionService.CurrentUser = value;
}
public ValueTask RemoveUserAsync(BindingUser user)
{
return userCollectionService.RemoveUserAsync(user);
}
public async ValueTask UnsafeRemoveUsersAsync()
public async ValueTask UnsafeRemoveAllUsersAsync()
{
await taskContext.SwitchToBackgroundAsync();
await userDbService.RemoveUsersAsync().ConfigureAwait(false);
}
public ValueTask<ObservableReorderableDbCollection<BindingUser, EntityUser>> GetUserCollectionAsync()
public ValueTask<AdvancedDbCollectionView<BindingUser, EntityUser>> GetUserCollectionAsync()
{
return userCollectionService.GetUserCollectionAsync();
}

View File

@@ -16,6 +16,7 @@
mc:Ignorable="d">
<mxi:Interaction.Behaviors>
<shuxb:InvokeCommandOnLoadedBehavior Command="{Binding LoadCommand}"/>
<shuxb:PeriodicInvokeCommandOrOnActualThemeChangedBehavior Command="{Binding UpdateBackgroundCommand}" Period="0:5:0"/>
</mxi:Interaction.Behaviors>

View File

@@ -1,6 +1,7 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Snap.Hutao.Service.Navigation;
using Snap.Hutao.UI.Xaml.View.Page;
@@ -27,6 +28,8 @@ internal sealed partial class MainView : UserControl
InitializeComponent();
this.Unloaded += OnUnloaded;
(DataContext as MainViewModel)?.Initialize(new BackgroundImagePresenterAccessor(BackgroundImagePresenter));
navigationService = serviceProvider.GetRequiredService<INavigationService>();
@@ -38,6 +41,11 @@ internal sealed partial class MainView : UserControl
navigationService.Navigate<AnnouncementPage>(INavigationAwaiter.Default, true);
}
private void OnUnloaded(object sender, RoutedEventArgs e)
{
(DataContext as MainViewModel)?.Uninitialize();
}
private class NavigationViewAccessor : INavigationViewAccessor
{
public NavigationViewAccessor(NavigationView navigationView, Frame frame)

View File

@@ -16,7 +16,7 @@ namespace Snap.Hutao.ViewModel;
[ConstructorGenerated]
[Injection(InjectAs.Singleton)]
internal sealed partial class MainViewModel : Abstraction.ViewModel, IMainViewModelInitialization, IRecipient<BackgroundImageTypeChangedMessage>
internal sealed partial class MainViewModel : Abstraction.ViewModel, IMainViewModelInitialization
{
private readonly IBackgroundImageService backgroundImageService;
private readonly ILogger<MainViewModel> logger;
@@ -34,9 +34,23 @@ internal sealed partial class MainViewModel : Abstraction.ViewModel, IMainViewMo
UpdateBackgroundAsync(true).SafeForget();
}
public void Receive(BackgroundImageTypeChangedMessage message)
protected override ValueTask<bool> InitializeOverrideAsync()
{
UpdateBackgroundAsync().SafeForget();
appOptions.PropertyChanged += OnAppOptionsPropertyChanged;
return ValueTask.FromResult(true);
}
protected override void UninitializeOverride()
{
appOptions.PropertyChanged -= OnAppOptionsPropertyChanged;
}
private void OnAppOptionsPropertyChanged(object? sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(AppOptions.BackgroundImageType))
{
UpdateBackgroundAsync().SafeForget();
}
}
[Command("UpdateBackgroundCommand")]

View File

@@ -120,7 +120,6 @@ internal sealed partial class SettingViewModel : Abstraction.ViewModel
if (SetProperty(ref selectedBackgroundImageType, value) && value is not null)
{
AppOptions.BackgroundImageType = value.Value;
messenger.Send(new Message.BackgroundImageTypeChangedMessage());
}
}
}
@@ -347,7 +346,7 @@ internal sealed partial class SettingViewModel : Abstraction.ViewModel
if (result is ContentDialogResult.Primary)
{
await @unsafe.UnsafeRemoveUsersAsync().ConfigureAwait(false);
await @unsafe.UnsafeRemoveAllUsersAsync().ConfigureAwait(false);
AppInstance.Restart(string.Empty);
}
}

View File

@@ -8,6 +8,7 @@ using Snap.Hutao.Core.Database;
using Snap.Hutao.Core.Database.Abstraction;
using Snap.Hutao.Model;
using Snap.Hutao.Model.Entity.Database;
using Snap.Hutao.UI.Xaml.Data;
using Snap.Hutao.Web.Hoyolab;
using Snap.Hutao.Web.Hoyolab.Bbs.User;
using Snap.Hutao.Web.Hoyolab.Takumi.Binding;
@@ -15,11 +16,11 @@ using EntityUser = Snap.Hutao.Model.Entity.User;
namespace Snap.Hutao.ViewModel.User;
/// <summary>
/// 用于视图绑定的用户
/// </summary>
[HighQuality]
internal sealed class User : ObservableObject, IEntityAccess<EntityUser>, IMappingFrom<User, EntityUser, IServiceProvider>, ISelectable
internal sealed class User : ObservableObject,
IEntityAccess<EntityUser>,
IMappingFrom<User, EntityUser, IServiceProvider>,
ISelectable,
IAdvancedCollectionViewItem
{
private readonly EntityUser inner;
private readonly IServiceProvider serviceProvider;
@@ -34,19 +35,10 @@ internal sealed class User : ObservableObject, IEntityAccess<EntityUser>, IMappi
public bool IsInitialized { get; set; }
/// <summary>
/// 用户信息
/// </summary>
public UserInfo? UserInfo { get; set; }
/// <summary>
/// 用户信息
/// </summary>
public List<UserGameRole> UserGameRoles { get; set; } = default!;
/// <summary>
/// 用户信息
/// </summary>
public UserGameRole? SelectedUserGameRole
{
get => selectedUserGameRole;
@@ -57,42 +49,32 @@ internal sealed class User : ObservableObject, IEntityAccess<EntityUser>, IMappi
public Guid InnerId { get => inner.InnerId; }
/// <inheritdoc cref="EntityUser.IsSelected"/>
public bool IsSelected
{
get => inner.IsSelected;
set => inner.IsSelected = value;
}
/// <inheritdoc cref="EntityUser.CookieToken"/>
public Cookie? CookieToken
{
get => inner.CookieToken;
set => inner.CookieToken = value;
}
/// <inheritdoc cref="EntityUser.LToken"/>
public Cookie? LToken
{
get => inner.LToken;
set => inner.LToken = value;
}
/// <inheritdoc cref="EntityUser.SToken"/>
public Cookie? SToken
{
get => inner.SToken;
set => inner.SToken = value;
}
/// <summary>
/// 是否为国际服
/// </summary>
public bool IsOversea { get => Entity.IsOversea; }
/// <summary>
/// 内部的用户实体
/// </summary>
public EntityUser Entity { get => inner; }
public bool NeedDbUpdateAfterResume { get; set; }
@@ -123,4 +105,12 @@ internal sealed class User : ObservableObject, IEntityAccess<EntityUser>, IMappi
}
}
}
public object? GetPropertyValue(string name)
{
return name switch
{
_ => default,
};
}
}

View File

@@ -103,6 +103,8 @@ internal class MiHoYoJSBridgeFacade
public event Action? ClosePageRequested;
protected ILogger Logger { get => logger; }
public void Detach()
{
coreWebView2.WebMessageReceived -= OnWebMessageReceived;

View File

@@ -6,10 +6,6 @@ using Snap.Hutao.ViewModel.User;
namespace Snap.Hutao.Web.Bridge;
/// <summary>
/// HoYoLAB 签到页面JS桥
/// </summary>
[HighQuality]
internal sealed class SignInJSBridgeOversea : MiHoYoJSBridgeFacade
{
// 移除 请旋转手机 提示所在的HTML元素
@@ -30,6 +26,6 @@ internal sealed class SignInJSBridgeOversea : MiHoYoJSBridgeFacade
protected override void DOMContentLoaded(CoreWebView2 coreWebView2)
{
coreWebView2.ExecuteScriptAsync(RemoveRotationWarningScript).AsTask().SafeForget();
coreWebView2.ExecuteScriptAsync(RemoveRotationWarningScript).AsTask().SafeForget(Logger);
}
}

View File

@@ -47,10 +47,10 @@ internal sealed partial class RegistryWatcher : IDisposable
this.valueChangedCallback = valueChangedCallback;
}
public void Start()
public void Start(ILogger logger)
{
ObjectDisposedException.ThrowIf(disposed, this);
WatchAsync(cancellationTokenSource.Token).SafeForget();
WatchAsync(cancellationTokenSource.Token).SafeForget(logger);
}
public void Dispose()