diff --git a/src/Snap.Hutao/Snap.Hutao/Extension/MemoryCacheExtension.cs b/src/Snap.Hutao/Snap.Hutao/Extension/MemoryCacheExtension.cs
new file mode 100644
index 00000000..749a2fc5
--- /dev/null
+++ b/src/Snap.Hutao/Snap.Hutao/Extension/MemoryCacheExtension.cs
@@ -0,0 +1,30 @@
+// Copyright (c) DGP Studio. All rights reserved.
+// Licensed under the MIT license.
+
+using Microsoft.Extensions.Caching.Memory;
+
+namespace Snap.Hutao.Extension;
+
+///
+/// 内存缓存拓展
+///
+internal static class MemoryCacheExtension
+{
+ ///
+ /// 尝试从 IMemoryCache 中移除并返回具有指定键的值
+ ///
+ /// 缓存
+ /// 键
+ /// 值
+ /// 是否移除成功
+ public static bool TryRemove(this IMemoryCache memoryCache, string key, [NotNullWhen(true)] out object? value)
+ {
+ if (memoryCache.TryGetValue(key, out value))
+ {
+ memoryCache.Remove(key);
+ return true;
+ }
+
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/DailyNote/DailyNoteOptions.cs b/src/Snap.Hutao/Snap.Hutao/Service/DailyNote/DailyNoteOptions.cs
index 87625c61..a0659da3 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/DailyNote/DailyNoteOptions.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/DailyNote/DailyNoteOptions.cs
@@ -1,6 +1,9 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
+using Snap.Hutao.Core;
+using Snap.Hutao.Model;
+using Snap.Hutao.Model.Entity;
using Snap.Hutao.Service.Abstraction;
namespace Snap.Hutao.Service.DailyNote;
@@ -11,12 +14,72 @@ namespace Snap.Hutao.Service.DailyNote;
[Injection(InjectAs.Singleton)]
internal sealed class DailyNoteOptions : DbStoreOptions
{
+ private readonly IServiceProvider serviceProvider;
+ private readonly List> refreshTimes = new()
+ {
+ new(SH.ViewModelDailyNoteRefreshTime4, 240),
+ new(SH.ViewModelDailyNoteRefreshTime8, 480),
+ new(SH.ViewModelDailyNoteRefreshTime30, 1800),
+ new(SH.ViewModelDailyNoteRefreshTime40, 2400),
+ new(SH.ViewModelDailyNoteRefreshTime60, 3600),
+ };
+
+ private NameValue? selectedRefreshTime;
+ private bool? isReminderNotification;
+ private bool? isSilentWhenPlayingGame;
+
///
/// 构造一个新的实时便笺选项
///
- /// 服务范围工厂
- public DailyNoteOptions(IServiceScopeFactory serviceScopeFactory)
- : base(serviceScopeFactory)
+ /// 服务提供器
+ public DailyNoteOptions(IServiceProvider serviceProvider)
+ : base(serviceProvider.GetRequiredService())
{
+ this.serviceProvider = serviceProvider;
+ }
+
+ ///
+ /// 刷新时间
+ ///
+ public List> RefreshTimes { get => refreshTimes; }
+
+ ///
+ /// 选中的刷新时间
+ ///
+ public NameValue? SelectedRefreshTime
+ {
+ get => GetOption(ref selectedRefreshTime, SettingEntry.DailyNoteReminderNotify, time => RefreshTimes.Single(t => t.Value == int.Parse(time)), RefreshTimes[1]);
+ set
+ {
+ if (value != null)
+ {
+ if (ScheduleTaskHelper.RegisterForDailyNoteRefresh(value.Value))
+ {
+ SetOption(ref selectedRefreshTime, SettingEntry.DailyNoteReminderNotify, value, value => value.Value.ToString());
+ }
+ else
+ {
+ serviceProvider.GetRequiredService().Warning(SH.ViewModelDailyNoteRegisterTaskFail);
+ }
+ }
+ }
+ }
+
+ ///
+ /// 提醒式通知
+ ///
+ public bool IsReminderNotification
+ {
+ get => GetOption(ref isReminderNotification, SettingEntry.DailyNoteReminderNotify);
+ set => SetOption(ref isReminderNotification, SettingEntry.DailyNoteReminderNotify, value);
+ }
+
+ ///
+ /// 是否开启免打扰模式
+ ///
+ public bool IsSilentWhenPlayingGame
+ {
+ get => GetOption(ref isSilentWhenPlayingGame, SettingEntry.DailyNoteSilentWhenPlayingGame);
+ set => SetOption(ref isSilentWhenPlayingGame, SettingEntry.DailyNoteSilentWhenPlayingGame, value);
}
}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/GameService.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/GameService.cs
index 80e5f5fd..9c665a73 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/Game/GameService.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/GameService.cs
@@ -368,6 +368,28 @@ internal sealed class GameService : IGameService
}
}
+ ///
+ public GameAccount? DetectCurrentGameAccount()
+ {
+ Must.NotNull(gameAccounts!);
+
+ string? registrySdk = RegistryInterop.Get();
+
+ if (!string.IsNullOrEmpty(registrySdk))
+ {
+ try
+ {
+ return gameAccounts.SingleOrDefault(a => a.MihoyoSDK == registrySdk);
+ }
+ catch (InvalidOperationException ex)
+ {
+ ThrowHelper.UserdataCorrupted(SH.ServiceGameDetectGameAccountMultiMatched, ex);
+ }
+ }
+
+ return null;
+ }
+
///
public bool SetGameAccount(GameAccount account)
{
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/IGameService.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/IGameService.cs
index 7e44433c..2ee3a81a 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/Game/IGameService.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/IGameService.cs
@@ -92,4 +92,10 @@ internal interface IGameService
/// 方案
/// 是否更改了ini文件
bool SetMultiChannel(LaunchScheme scheme);
+
+ ///
+ /// 检测账号
+ ///
+ /// 账号
+ GameAccount? DetectCurrentGameAccount();
}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/LaunchOptions.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/LaunchOptions.cs
index 43cb4023..5a23cca4 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/Game/LaunchOptions.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/LaunchOptions.cs
@@ -148,7 +148,7 @@ internal sealed class LaunchOptions : DbStoreOptions
public NameValue Monitor
{
get => GetOption(ref monitor, SettingEntry.LaunchMonitor, index => Monitors[int.Parse(index) - 1], Monitors[0]);
- set => SetOption(ref monitor, SettingEntry.LaunchMonitor, value, selected => selected.Value.ToString());
+ set => SetOption(ref monitor, SettingEntry.LaunchMonitor, value, selected => selected?.Value.ToString() ?? "1");
}
///
diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/DailyNotePage.xaml b/src/Snap.Hutao/Snap.Hutao/View/Page/DailyNotePage.xaml
index e4065715..f1d2bb61 100644
--- a/src/Snap.Hutao/Snap.Hutao/View/Page/DailyNotePage.xaml
+++ b/src/Snap.Hutao/Snap.Hutao/View/Page/DailyNotePage.xaml
@@ -85,7 +85,7 @@
-
+
@@ -106,13 +106,13 @@
Description="{shcm:ResourceString Name=ViewPageDailyNoteSlientModeDescription}"
Header="{shcm:ResourceString Name=ViewPageDailyNoteSlientModeHeader}"
HeaderIcon="{shcm:FontIcon Glyph=}">
-
+
-
+
diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/DailyNoteViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/DailyNoteViewModel.cs
index d1ad0040..c4667184 100644
--- a/src/Snap.Hutao/Snap.Hutao/ViewModel/DailyNoteViewModel.cs
+++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/DailyNoteViewModel.cs
@@ -28,24 +28,8 @@ internal sealed class DailyNoteViewModel : Abstraction.ViewModel
private readonly IDailyNoteService dailyNoteService;
private readonly AppDbContext appDbContext;
- private readonly List> refreshTimes = new()
- {
- new(SH.ViewModelDailyNoteRefreshTime4, 240),
- new(SH.ViewModelDailyNoteRefreshTime8, 480),
- new(SH.ViewModelDailyNoteRefreshTime30, 1800),
- new(SH.ViewModelDailyNoteRefreshTime40, 2400),
- new(SH.ViewModelDailyNoteRefreshTime60, 3600),
- };
-
- private bool isReminderNotification;
- private NameValue? selectedRefreshTime;
private ObservableCollection? userAndUids;
-
- private SettingEntry? refreshSecondsEntry;
- private SettingEntry? reminderNotifyEntry;
- private SettingEntry? silentModeEntry;
private ObservableCollection? dailyNoteEntries;
- private bool isSilentWhenPlayingGame;
///
/// 构造一个新的实时便笺视图模型
@@ -56,6 +40,7 @@ internal sealed class DailyNoteViewModel : Abstraction.ViewModel
userService = serviceProvider.GetRequiredService();
dailyNoteService = serviceProvider.GetRequiredService();
appDbContext = serviceProvider.GetRequiredService();
+ Options = serviceProvider.GetRequiredService();
this.serviceProvider = serviceProvider;
TrackRoleCommand = new AsyncRelayCommand(TrackRoleAsync);
@@ -66,67 +51,9 @@ internal sealed class DailyNoteViewModel : Abstraction.ViewModel
}
///
- /// 刷新时间
+ /// 选项
///
- public List> RefreshTimes { get => refreshTimes; }
-
- ///
- /// 选中的刷新时间
- ///
- public NameValue? SelectedRefreshTime
- {
- get => selectedRefreshTime;
- set
- {
- if (SetProperty(ref selectedRefreshTime, value))
- {
- if (value != null)
- {
- if (!ScheduleTaskHelper.RegisterForDailyNoteRefresh(value.Value))
- {
- serviceProvider.GetRequiredService().Warning(SH.ViewModelDailyNoteRegisterTaskFail);
- }
- else
- {
- refreshSecondsEntry!.SetInt32(value.Value);
- appDbContext.Settings.UpdateAndSave(refreshSecondsEntry!);
- }
- }
- }
- }
- }
-
- ///
- /// 提醒式通知
- ///
- public bool IsReminderNotification
- {
- get => isReminderNotification;
- set
- {
- if (SetProperty(ref isReminderNotification, value))
- {
- reminderNotifyEntry!.SetBoolean(value);
- appDbContext.Settings.UpdateAndSave(reminderNotifyEntry!);
- }
- }
- }
-
- ///
- /// 是否开启免打扰模式
- ///
- public bool IsSilentWhenPlayingGame
- {
- get => isSilentWhenPlayingGame;
- set
- {
- if (SetProperty(ref isSilentWhenPlayingGame, value))
- {
- silentModeEntry!.SetBoolean(value);
- appDbContext.Settings.UpdateAndSave(silentModeEntry!);
- }
- }
- }
+ public DailyNoteOptions Options { get; }
///
/// 用户与角色集合
@@ -168,43 +95,19 @@ internal sealed class DailyNoteViewModel : Abstraction.ViewModel
{
try
{
- UserAndUids = await userService.GetRoleCollectionAsync().ConfigureAwait(true);
+ await ThreadHelper.SwitchToBackgroundAsync();
+ ObservableCollection roles = await userService.GetRoleCollectionAsync().ConfigureAwait(false);
+ ObservableCollection entries = await dailyNoteService.GetDailyNoteEntriesAsync().ConfigureAwait(false);
+
+ await ThreadHelper.SwitchToMainThreadAsync();
+ UserAndUids = roles;
+ DailyNoteEntries = entries;
}
catch (Core.ExceptionService.UserdataCorruptedException ex)
{
serviceProvider.GetRequiredService().Error(ex);
return;
}
-
- try
- {
- using (await EnterCriticalExecutionAsync().ConfigureAwait(false))
- {
- await ThreadHelper.SwitchToMainThreadAsync();
-
- refreshSecondsEntry = appDbContext.Settings.SingleOrAdd(SettingEntry.DailyNoteRefreshSeconds, "480");
- int refreshSeconds = refreshSecondsEntry.GetInt32();
- selectedRefreshTime = refreshTimes.Single(t => t.Value == refreshSeconds);
- OnPropertyChanged(nameof(SelectedRefreshTime));
- ScheduleTaskHelper.RegisterForDailyNoteRefresh(refreshSeconds);
-
- reminderNotifyEntry = appDbContext.Settings.SingleOrAdd(SettingEntry.DailyNoteReminderNotify, Core.StringLiterals.False);
- isReminderNotification = reminderNotifyEntry.GetBoolean();
- OnPropertyChanged(nameof(IsReminderNotification));
-
- silentModeEntry = appDbContext.Settings.SingleOrAdd(SettingEntry.DailyNoteSilentWhenPlayingGame, Core.StringLiterals.False);
- isSilentWhenPlayingGame = silentModeEntry.GetBoolean();
- OnPropertyChanged(nameof(IsSilentWhenPlayingGame));
- }
-
- await ThreadHelper.SwitchToBackgroundAsync();
- ObservableCollection entries = await dailyNoteService.GetDailyNoteEntriesAsync().ConfigureAwait(false);
- await ThreadHelper.SwitchToMainThreadAsync();
- DailyNoteEntries = entries;
- }
- catch (OperationCanceledException)
- {
- }
}
private async Task TrackRoleAsync(UserAndUid? role)
diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/Game/LaunchGameViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/Game/LaunchGameViewModel.cs
index 6d83c0db..8522e433 100644
--- a/src/Snap.Hutao/Snap.Hutao/ViewModel/Game/LaunchGameViewModel.cs
+++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/Game/LaunchGameViewModel.cs
@@ -171,11 +171,13 @@ internal sealed class LaunchGameViewModel : Abstraction.ViewModel
GameAccounts = accounts;
// Sync uid
- if (memoryCache.TryGetValue(DesiredUid, out object? value) && value is string uid)
+ if (memoryCache.TryRemove(DesiredUid, out object? value) && value is string uid)
{
SelectedGameAccount = GameAccounts.FirstOrDefault(g => g.AttachUid == uid);
- memoryCache.Remove(DesiredUid);
}
+
+ // Try set to the current account.
+ SelectedGameAccount ??= gameService.DetectCurrentGameAccount();
}
}
catch (OperationCanceledException)
diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/PlayerUid.cs b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/PlayerUid.cs
index 4e41ff53..03713791 100644
--- a/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/PlayerUid.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/PlayerUid.cs
@@ -65,6 +65,7 @@ internal readonly struct PlayerUid
// CN
>= '1' and <= '4' => "cn_gf01", // 国服
'5' => "cn_qd01", // 渠道
+
// OS
'6' => "os_usa", // 美服
'7' => "os_euro", // 欧服