mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
fix #825
This commit is contained in:
@@ -81,6 +81,12 @@
|
|||||||
<x:String x:Key="UI_EmotionIcon250">https://static.snapgenshin.com/EmotionIcon/UI_EmotionIcon250.png</x:String>
|
<x:String x:Key="UI_EmotionIcon250">https://static.snapgenshin.com/EmotionIcon/UI_EmotionIcon250.png</x:String>
|
||||||
<x:String x:Key="UI_EmotionIcon272">https://static.snapgenshin.com/EmotionIcon/UI_EmotionIcon272.png</x:String>
|
<x:String x:Key="UI_EmotionIcon272">https://static.snapgenshin.com/EmotionIcon/UI_EmotionIcon272.png</x:String>
|
||||||
<x:String x:Key="UI_EmotionIcon293">https://static.snapgenshin.com/EmotionIcon/UI_EmotionIcon293.png</x:String>
|
<x:String x:Key="UI_EmotionIcon293">https://static.snapgenshin.com/EmotionIcon/UI_EmotionIcon293.png</x:String>
|
||||||
|
<!-- 图床 Url -->
|
||||||
|
<x:String x:Key="UI_ItemIcon_204">https://smms.app/image/x9psnPrcbYoCl6U</x:String>
|
||||||
|
<x:String x:Key="UI_ItemIcon_210">https://smms.app/image/n4gwxlFGPTX2j8p</x:String>
|
||||||
|
<x:String x:Key="UI_ItemIcon_220021">https://smms.app/image/kbh1a2YVXpxWuez</x:String>
|
||||||
|
<x:String x:Key="UI_Icon_Intee_Explore_1">https://smms.app/image/zJ4UYqKiD6uQlLc</x:String>
|
||||||
|
<x:String x:Key="UI_MarkQuest_Events_Proce">https://smms.app/image/DQyTF3rv4aA8MZV</x:String>
|
||||||
<!-- Converters -->
|
<!-- Converters -->
|
||||||
<cwuc:BoolNegationConverter x:Key="BoolNegationConverter"/>
|
<cwuc:BoolNegationConverter x:Key="BoolNegationConverter"/>
|
||||||
<cwuc:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter"/>
|
<cwuc:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter"/>
|
||||||
|
|||||||
@@ -105,17 +105,19 @@ internal static partial class EnumerableExtension
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 按元素的键排序
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="TSource">元素类型</typeparam>
|
|
||||||
/// <typeparam name="TKey">键类型</typeparam>
|
|
||||||
/// <param name="list">列表</param>
|
|
||||||
/// <param name="keySelector">键选择器</param>
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
public static void SortBy<TSource, TKey>(this List<TSource> list, Func<TSource, TKey> keySelector)
|
public static List<TSource> SortBy<TSource, TKey>(this List<TSource> list, Func<TSource, TKey> keySelector)
|
||||||
where TKey : IComparable
|
where TKey : IComparable
|
||||||
{
|
{
|
||||||
list.Sort((left, right) => keySelector(left).CompareTo(keySelector(right)));
|
list.Sort((left, right) => keySelector(left).CompareTo(keySelector(right)));
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
|
public static List<TSource> SortByDescending<TSource, TKey>(this List<TSource> list, Func<TSource, TKey> keySelector)
|
||||||
|
where TKey : IComparable
|
||||||
|
{
|
||||||
|
list.Sort((left, right) => keySelector(right).CompareTo(keySelector(left)));
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 59 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 3.9 KiB |
@@ -141,7 +141,7 @@ internal sealed class DailyNoteNotificationOperation
|
|||||||
{
|
{
|
||||||
notifyInfos.Add(new(
|
notifyInfos.Add(new(
|
||||||
SH.ServiceDailyNoteNotifierResin,
|
SH.ServiceDailyNoteNotifierResin,
|
||||||
Web.Hoyolab.OssImages.UIItemIcon210,
|
Web.Hoyolab.Images.UIItemIcon210,
|
||||||
$"{entry.DailyNote.CurrentResin}",
|
$"{entry.DailyNote.CurrentResin}",
|
||||||
string.Format(SH.ServiceDailyNoteNotifierResinCurrent, entry.DailyNote.CurrentResin)));
|
string.Format(SH.ServiceDailyNoteNotifierResinCurrent, entry.DailyNote.CurrentResin)));
|
||||||
entry.ResinNotifySuppressed = true;
|
entry.ResinNotifySuppressed = true;
|
||||||
@@ -158,7 +158,7 @@ internal sealed class DailyNoteNotificationOperation
|
|||||||
{
|
{
|
||||||
notifyInfos.Add(new(
|
notifyInfos.Add(new(
|
||||||
SH.ServiceDailyNoteNotifierHomeCoin,
|
SH.ServiceDailyNoteNotifierHomeCoin,
|
||||||
Web.Hoyolab.OssImages.UIItemIcon204,
|
Web.Hoyolab.Images.UIItemIcon204,
|
||||||
$"{entry.DailyNote.CurrentHomeCoin}",
|
$"{entry.DailyNote.CurrentHomeCoin}",
|
||||||
string.Format(SH.ServiceDailyNoteNotifierHomeCoinCurrent, entry.DailyNote.CurrentHomeCoin)));
|
string.Format(SH.ServiceDailyNoteNotifierHomeCoinCurrent, entry.DailyNote.CurrentHomeCoin)));
|
||||||
entry.HomeCoinNotifySuppressed = true;
|
entry.HomeCoinNotifySuppressed = true;
|
||||||
@@ -175,7 +175,7 @@ internal sealed class DailyNoteNotificationOperation
|
|||||||
{
|
{
|
||||||
notifyInfos.Add(new(
|
notifyInfos.Add(new(
|
||||||
SH.ServiceDailyNoteNotifierDailyTask,
|
SH.ServiceDailyNoteNotifierDailyTask,
|
||||||
Web.Hoyolab.OssImages.UIMarkQuestEventsProce,
|
Web.Hoyolab.Images.UIMarkQuestEventsProce,
|
||||||
SH.ServiceDailyNoteNotifierDailyTaskHint,
|
SH.ServiceDailyNoteNotifierDailyTaskHint,
|
||||||
entry.DailyNote.ExtraTaskRewardDescription));
|
entry.DailyNote.ExtraTaskRewardDescription));
|
||||||
entry.DailyTaskNotifySuppressed = true;
|
entry.DailyTaskNotifySuppressed = true;
|
||||||
@@ -192,7 +192,7 @@ internal sealed class DailyNoteNotificationOperation
|
|||||||
{
|
{
|
||||||
notifyInfos.Add(new(
|
notifyInfos.Add(new(
|
||||||
SH.ServiceDailyNoteNotifierTransformer,
|
SH.ServiceDailyNoteNotifierTransformer,
|
||||||
Web.Hoyolab.OssImages.UIItemIcon220021,
|
Web.Hoyolab.Images.UIItemIcon220021,
|
||||||
SH.ServiceDailyNoteNotifierTransformerAdaptiveHint,
|
SH.ServiceDailyNoteNotifierTransformerAdaptiveHint,
|
||||||
SH.ServiceDailyNoteNotifierTransformerHint));
|
SH.ServiceDailyNoteNotifierTransformerHint));
|
||||||
entry.TransformerNotifySuppressed = true;
|
entry.TransformerNotifySuppressed = true;
|
||||||
@@ -209,7 +209,7 @@ internal sealed class DailyNoteNotificationOperation
|
|||||||
{
|
{
|
||||||
notifyInfos.Add(new(
|
notifyInfos.Add(new(
|
||||||
SH.ServiceDailyNoteNotifierExpedition,
|
SH.ServiceDailyNoteNotifierExpedition,
|
||||||
Web.Hoyolab.OssImages.UIIconInteeExplore1,
|
Web.Hoyolab.Images.UIIconInteeExplore1,
|
||||||
SH.ServiceDailyNoteNotifierExpeditionAdaptiveHint,
|
SH.ServiceDailyNoteNotifierExpeditionAdaptiveHint,
|
||||||
SH.ServiceDailyNoteNotifierExpeditionHint));
|
SH.ServiceDailyNoteNotifierExpeditionHint));
|
||||||
entry.ExpeditionNotifySuppressed = true;
|
entry.ExpeditionNotifySuppressed = true;
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ namespace Snap.Hutao.Service.Game;
|
|||||||
[HighQuality]
|
[HighQuality]
|
||||||
internal readonly struct ChannelOptions
|
internal readonly struct ChannelOptions
|
||||||
{
|
{
|
||||||
|
public const string ChannelName = "channel";
|
||||||
|
public const string SubChannelName = "sub_channel";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 通道
|
/// 通道
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
62
src/Snap.Hutao/Snap.Hutao/Service/Game/GameDbService.cs
Normal file
62
src/Snap.Hutao/Snap.Hutao/Service/Game/GameDbService.cs
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Snap.Hutao.Core.Database;
|
||||||
|
using Snap.Hutao.Model.Entity;
|
||||||
|
using Snap.Hutao.Model.Entity.Database;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
|
||||||
|
namespace Snap.Hutao.Service.Game;
|
||||||
|
|
||||||
|
[ConstructorGenerated]
|
||||||
|
[Injection(InjectAs.Singleton, typeof(IGameDbService))]
|
||||||
|
internal sealed partial class GameDbService : IGameDbService
|
||||||
|
{
|
||||||
|
private readonly IServiceProvider serviceProvider;
|
||||||
|
|
||||||
|
public ObservableCollection<GameAccount> GetGameAccountCollection()
|
||||||
|
{
|
||||||
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
|
{
|
||||||
|
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
return appDbContext.GameAccounts.AsNoTracking().ToObservableCollection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask AddGameAccountAsync(GameAccount gameAccount)
|
||||||
|
{
|
||||||
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
|
{
|
||||||
|
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
await appDbContext.GameAccounts.AddAndSaveAsync(gameAccount).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask UpdateGameAccountAsync(GameAccount gameAccount)
|
||||||
|
{
|
||||||
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
|
{
|
||||||
|
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
await appDbContext.GameAccounts.UpdateAndSaveAsync(gameAccount).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateGameAccount(GameAccount gameAccount)
|
||||||
|
{
|
||||||
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
|
{
|
||||||
|
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
appDbContext.GameAccounts.UpdateAndSave(gameAccount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask DeleteGameAccountByIdAsync(Guid id)
|
||||||
|
{
|
||||||
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
|
{
|
||||||
|
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||||
|
await appDbContext.GameAccounts.ExecuteDeleteWhereAsync(a => a.InnerId == id).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,13 +1,10 @@
|
|||||||
// Copyright (c) DGP Studio. All rights reserved.
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
// Licensed under the MIT license.
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Snap.Hutao.Core;
|
using Snap.Hutao.Core;
|
||||||
using Snap.Hutao.Core.Database;
|
|
||||||
using Snap.Hutao.Core.ExceptionService;
|
using Snap.Hutao.Core.ExceptionService;
|
||||||
using Snap.Hutao.Core.IO.Ini;
|
using Snap.Hutao.Core.IO.Ini;
|
||||||
using Snap.Hutao.Model.Entity;
|
using Snap.Hutao.Model.Entity;
|
||||||
using Snap.Hutao.Model.Entity.Database;
|
|
||||||
using Snap.Hutao.Service.Game.Locator;
|
using Snap.Hutao.Service.Game.Locator;
|
||||||
using Snap.Hutao.Service.Game.Package;
|
using Snap.Hutao.Service.Game.Package;
|
||||||
using Snap.Hutao.View.Dialog;
|
using Snap.Hutao.View.Dialog;
|
||||||
@@ -32,7 +29,7 @@ internal sealed partial class GameService : IGameService
|
|||||||
private readonly IServiceProvider serviceProvider;
|
private readonly IServiceProvider serviceProvider;
|
||||||
private readonly IGameDbService gameDbService;
|
private readonly IGameDbService gameDbService;
|
||||||
private readonly LaunchOptions launchOptions;
|
private readonly LaunchOptions launchOptions;
|
||||||
private readonly RuntimeOptions hutaoOptions;
|
private readonly RuntimeOptions runtimeOptions;
|
||||||
private readonly ITaskContext taskContext;
|
private readonly ITaskContext taskContext;
|
||||||
private readonly AppOptions appOptions;
|
private readonly AppOptions appOptions;
|
||||||
|
|
||||||
@@ -48,48 +45,45 @@ internal sealed partial class GameService : IGameService
|
|||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public async ValueTask<ValueResult<bool, string>> GetGamePathAsync()
|
public async ValueTask<ValueResult<bool, string>> GetGamePathAsync()
|
||||||
{
|
{
|
||||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
// Cannot find in setting
|
||||||
|
if (string.IsNullOrEmpty(appOptions.GamePath))
|
||||||
{
|
{
|
||||||
// Cannot find in setting
|
IGameLocatorFactory locatorFactory = serviceProvider.GetRequiredService<IGameLocatorFactory>();
|
||||||
if (string.IsNullOrEmpty(appOptions.GamePath))
|
|
||||||
{
|
|
||||||
IGameLocatorFactory locatorFactory = scope.ServiceProvider.GetRequiredService<IGameLocatorFactory>();
|
|
||||||
|
|
||||||
// Try locate by unity log
|
// Try locate by unity log
|
||||||
ValueResult<bool, string> result = await locatorFactory
|
ValueResult<bool, string> result = await locatorFactory
|
||||||
.Create(GameLocationSource.UnityLog)
|
.Create(GameLocationSource.UnityLog)
|
||||||
|
.LocateGamePathAsync()
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (!result.IsOk)
|
||||||
|
{
|
||||||
|
// Try locate by registry
|
||||||
|
result = await locatorFactory
|
||||||
|
.Create(GameLocationSource.Registry)
|
||||||
.LocateGamePathAsync()
|
.LocateGamePathAsync()
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
if (!result.IsOk)
|
|
||||||
{
|
|
||||||
// Try locate by registry
|
|
||||||
result = await locatorFactory
|
|
||||||
.Create(GameLocationSource.Registry)
|
|
||||||
.LocateGamePathAsync()
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result.IsOk)
|
|
||||||
{
|
|
||||||
// Save result.
|
|
||||||
appOptions.GamePath = result.Value;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return new(false, SH.ServiceGamePathLocateFailed);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(appOptions.GamePath))
|
if (result.IsOk)
|
||||||
{
|
{
|
||||||
return new(true, appOptions.GamePath);
|
// Save result.
|
||||||
|
appOptions.GamePath = result.Value;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return new(false, null!);
|
return new(false, SH.ServiceGamePathLocateFailed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(appOptions.GamePath))
|
||||||
|
{
|
||||||
|
return new(true, appOptions.GamePath);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return new(false, null!);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
@@ -107,8 +101,8 @@ internal sealed partial class GameService : IGameService
|
|||||||
using (FileStream stream = File.OpenRead(configPath))
|
using (FileStream stream = File.OpenRead(configPath))
|
||||||
{
|
{
|
||||||
List<IniParameter> parameters = IniSerializer.Deserialize(stream).OfType<IniParameter>().ToList();
|
List<IniParameter> parameters = IniSerializer.Deserialize(stream).OfType<IniParameter>().ToList();
|
||||||
string? channel = parameters.FirstOrDefault(p => p.Key == "channel")?.Value;
|
string? channel = parameters.FirstOrDefault(p => p.Key == ChannelOptions.ChannelName)?.Value;
|
||||||
string? subChannel = parameters.FirstOrDefault(p => p.Key == "sub_channel")?.Value;
|
string? subChannel = parameters.FirstOrDefault(p => p.Key == ChannelOptions.SubChannelName)?.Value;
|
||||||
|
|
||||||
return new(channel, subChannel, isOversea);
|
return new(channel, subChannel, isOversea);
|
||||||
}
|
}
|
||||||
@@ -178,14 +172,10 @@ internal sealed partial class GameService : IGameService
|
|||||||
string gameFileName = Path.GetFileName(gamePath);
|
string gameFileName = Path.GetFileName(gamePath);
|
||||||
|
|
||||||
progress.Report(new(SH.ServiceGameEnsureGameResourceQueryResourceInformation));
|
progress.Report(new(SH.ServiceGameEnsureGameResourceQueryResourceInformation));
|
||||||
Response<GameResource> response;
|
Response<GameResource> response = await serviceProvider
|
||||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
.GetRequiredService<ResourceClient>()
|
||||||
{
|
.GetResourceAsync(launchScheme)
|
||||||
response = await scope.ServiceProvider
|
.ConfigureAwait(false);
|
||||||
.GetRequiredService<ResourceClient>()
|
|
||||||
.GetResourceAsync(launchScheme)
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (response.IsOk())
|
if (response.IsOk())
|
||||||
{
|
{
|
||||||
@@ -257,7 +247,7 @@ internal sealed partial class GameService : IGameService
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Process game = ProcessInterop.PrepareGameProcess(launchOptions, gamePath);
|
Process game = ProcessInterop.InitializeGameProcess(launchOptions, gamePath);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -265,7 +255,7 @@ internal sealed partial class GameService : IGameService
|
|||||||
|
|
||||||
game.Start();
|
game.Start();
|
||||||
|
|
||||||
bool isAdvancedOptionsAllowed = hutaoOptions.IsElevated && appOptions.IsAdvancedLaunchOptionsEnabled;
|
bool isAdvancedOptionsAllowed = runtimeOptions.IsElevated && appOptions.IsAdvancedLaunchOptionsEnabled;
|
||||||
if (isAdvancedOptionsAllowed && launchOptions.MultipleInstances && !isFirstInstance)
|
if (isAdvancedOptionsAllowed && launchOptions.MultipleInstances && !isFirstInstance)
|
||||||
{
|
{
|
||||||
ProcessInterop.DisableProtection(game, gamePath);
|
ProcessInterop.DisableProtection(game, gamePath);
|
||||||
@@ -317,14 +307,7 @@ internal sealed partial class GameService : IGameService
|
|||||||
|
|
||||||
// sync database
|
// sync database
|
||||||
await taskContext.SwitchToBackgroundAsync();
|
await taskContext.SwitchToBackgroundAsync();
|
||||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
await gameDbService.AddGameAccountAsync(account).ConfigureAwait(false);
|
||||||
{
|
|
||||||
await scope.ServiceProvider
|
|
||||||
.GetRequiredService<AppDbContext>()
|
|
||||||
.GameAccounts
|
|
||||||
.AddAndSaveAsync(account)
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// sync cache
|
// sync cache
|
||||||
await taskContext.SwitchToMainThreadAsync();
|
await taskContext.SwitchToMainThreadAsync();
|
||||||
@@ -365,11 +348,8 @@ internal sealed partial class GameService : IGameService
|
|||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void AttachGameAccountToUid(GameAccount gameAccount, string uid)
|
public void AttachGameAccountToUid(GameAccount gameAccount, string uid)
|
||||||
{
|
{
|
||||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
gameAccount.UpdateAttachUid(uid);
|
||||||
{
|
gameDbService.UpdateGameAccount(gameAccount);
|
||||||
gameAccount.UpdateAttachUid(uid);
|
|
||||||
scope.ServiceProvider.GetRequiredService<AppDbContext>().GameAccounts.UpdateAndSave(gameAccount);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
@@ -385,11 +365,7 @@ internal sealed partial class GameService : IGameService
|
|||||||
|
|
||||||
// sync database
|
// sync database
|
||||||
await taskContext.SwitchToBackgroundAsync();
|
await taskContext.SwitchToBackgroundAsync();
|
||||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
await gameDbService.UpdateGameAccountAsync(gameAccount).ConfigureAwait(false);
|
||||||
{
|
|
||||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
|
||||||
await appDbContext.GameAccounts.UpdateAndSaveAsync(gameAccount).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -400,10 +376,7 @@ internal sealed partial class GameService : IGameService
|
|||||||
gameAccounts!.Remove(gameAccount);
|
gameAccounts!.Remove(gameAccount);
|
||||||
|
|
||||||
await taskContext.SwitchToBackgroundAsync();
|
await taskContext.SwitchToBackgroundAsync();
|
||||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
await gameDbService.DeleteGameAccountByIdAsync(gameAccount.InnerId).ConfigureAwait(false);
|
||||||
{
|
|
||||||
await scope.ServiceProvider.GetRequiredService<AppDbContext>().GameAccounts.RemoveAndSaveAsync(gameAccount).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool LaunchSchemeMatchesExecutable(LaunchScheme launchScheme, string gameFileName)
|
private static bool LaunchSchemeMatchesExecutable(LaunchScheme launchScheme, string gameFileName)
|
||||||
@@ -416,24 +389,3 @@ internal sealed partial class GameService : IGameService
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[ConstructorGenerated]
|
|
||||||
[Injection(InjectAs.Singleton, typeof(IGameDbService))]
|
|
||||||
internal sealed partial class GameDbService : IGameDbService
|
|
||||||
{
|
|
||||||
private readonly IServiceProvider serviceProvider;
|
|
||||||
|
|
||||||
public ObservableCollection<GameAccount> GetGameAccountCollection()
|
|
||||||
{
|
|
||||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
|
||||||
{
|
|
||||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
|
||||||
return appDbContext.GameAccounts.AsNoTracking().ToObservableCollection();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal interface IGameDbService
|
|
||||||
{
|
|
||||||
ObservableCollection<GameAccount> GetGameAccountCollection();
|
|
||||||
}
|
|
||||||
20
src/Snap.Hutao/Snap.Hutao/Service/Game/IGameDbService.cs
Normal file
20
src/Snap.Hutao/Snap.Hutao/Service/Game/IGameDbService.cs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
using Snap.Hutao.Model.Entity;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
|
||||||
|
namespace Snap.Hutao.Service.Game;
|
||||||
|
|
||||||
|
internal interface IGameDbService
|
||||||
|
{
|
||||||
|
ValueTask AddGameAccountAsync(GameAccount gameAccount);
|
||||||
|
|
||||||
|
ValueTask DeleteGameAccountByIdAsync(Guid id);
|
||||||
|
|
||||||
|
ObservableCollection<GameAccount> GetGameAccountCollection();
|
||||||
|
|
||||||
|
void UpdateGameAccount(GameAccount gameAccount);
|
||||||
|
|
||||||
|
ValueTask UpdateGameAccountAsync(GameAccount gameAccount);
|
||||||
|
}
|
||||||
@@ -43,16 +43,7 @@ internal sealed class LaunchOptions : DbStoreOptions
|
|||||||
primaryScreenWidth = primaryRect.Width;
|
primaryScreenWidth = primaryRect.Width;
|
||||||
primaryScreenHeight = primaryRect.Height;
|
primaryScreenHeight = primaryRect.Height;
|
||||||
|
|
||||||
// This list can't use foreach
|
InitializeMonitors(Monitors);
|
||||||
// https://github.com/microsoft/microsoft-ui-xaml/issues/6454
|
|
||||||
IReadOnlyList<DisplayArea> displayAreas = DisplayArea.FindAll();
|
|
||||||
for (int i = 0; i < displayAreas.Count; i++)
|
|
||||||
{
|
|
||||||
DisplayArea displayArea = displayAreas[i];
|
|
||||||
int index = i + 1;
|
|
||||||
Monitors.Add(new($"{displayArea.DisplayId.Value:X8}:{index}", index));
|
|
||||||
}
|
|
||||||
|
|
||||||
InitializeScreenFps(out primaryScreenFps);
|
InitializeScreenFps(out primaryScreenFps);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,6 +159,19 @@ internal sealed class LaunchOptions : DbStoreOptions
|
|||||||
set => SetOption(ref multipleInstances, SettingEntry.MultipleInstances, value);
|
set => SetOption(ref multipleInstances, SettingEntry.MultipleInstances, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void InitializeMonitors(List<NameValue<int>> monitors)
|
||||||
|
{
|
||||||
|
// This list can't use foreach
|
||||||
|
// https://github.com/microsoft/microsoft-ui-xaml/issues/6454
|
||||||
|
IReadOnlyList<DisplayArea> displayAreas = DisplayArea.FindAll();
|
||||||
|
for (int i = 0; i < displayAreas.Count; i++)
|
||||||
|
{
|
||||||
|
DisplayArea displayArea = displayAreas[i];
|
||||||
|
int index = i + 1;
|
||||||
|
monitors.Add(new($"{displayArea.DisplayId.Value:X8}:{index}", index));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void InitializeScreenFps(out int fps)
|
private static void InitializeScreenFps(out int fps)
|
||||||
{
|
{
|
||||||
HDC hDC = GetDC(HWND.Null);
|
HDC hDC = GetDC(HWND.Null);
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ internal static class ProcessInterop
|
|||||||
/// <param name="options">启动选项</param>
|
/// <param name="options">启动选项</param>
|
||||||
/// <param name="gamePath">游戏路径</param>
|
/// <param name="gamePath">游戏路径</param>
|
||||||
/// <returns>初始化后的游戏进程</returns>
|
/// <returns>初始化后的游戏进程</returns>
|
||||||
public static Process PrepareGameProcess(LaunchOptions options, string gamePath)
|
public static Process InitializeGameProcess(LaunchOptions options, string gamePath)
|
||||||
{
|
{
|
||||||
// https://docs.unity.cn/cn/current/Manual/PlayerCommandLineArguments.html
|
// https://docs.unity.cn/cn/current/Manual/PlayerCommandLineArguments.html
|
||||||
string commandLine = new CommandLineBuilder()
|
string commandLine = new CommandLineBuilder()
|
||||||
|
|||||||
@@ -95,21 +95,7 @@ internal sealed partial class HutaoCache : IHutaoCache
|
|||||||
Dictionary<AvatarId, Avatar> idAvatarMap = await GetIdAvatarMapExtendedAsync().ConfigureAwait(false);
|
Dictionary<AvatarId, Avatar> idAvatarMap = await GetIdAvatarMapExtendedAsync().ConfigureAwait(false);
|
||||||
Dictionary<WeaponId, Weapon> idWeaponMap = await metadataService.GetIdToWeaponMapAsync().ConfigureAwait(false);
|
Dictionary<WeaponId, Weapon> idWeaponMap = await metadataService.GetIdToWeaponMapAsync().ConfigureAwait(false);
|
||||||
Dictionary<EquipAffixId, Model.Metadata.Reliquary.ReliquarySet> idReliquarySetMap = await metadataService.GetEquipAffixIdToReliquarySetMapAsync().ConfigureAwait(false);
|
Dictionary<EquipAffixId, Model.Metadata.Reliquary.ReliquarySet> idReliquarySetMap = await metadataService.GetEquipAffixIdToReliquarySetMapAsync().ConfigureAwait(false);
|
||||||
|
await AvatarCollocationsAsync(idAvatarMap, idWeaponMap, idReliquarySetMap).ConfigureAwait(false);
|
||||||
List<AvatarCollocation> avatarCollocationsRaw;
|
|
||||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
|
||||||
{
|
|
||||||
IHutaoService hutaoService = scope.ServiceProvider.GetRequiredService<IHutaoService>();
|
|
||||||
avatarCollocationsRaw = await hutaoService.GetAvatarCollocationsAsync().ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
AvatarCollocations = avatarCollocationsRaw.Select(co => new AvatarCollocationView()
|
|
||||||
{
|
|
||||||
AvatarId = co.AvatarId,
|
|
||||||
Avatars = co.Avatars.Select(a => new AvatarView(idAvatarMap[a.Item], a.Rate)).ToList(),
|
|
||||||
Weapons = co.Weapons.Select(w => new WeaponView(idWeaponMap[w.Item], w.Rate)).ToList(),
|
|
||||||
ReliquarySets = co.Reliquaries.Select(r => new ReliquarySetView(r, idReliquarySetMap)).ToList(),
|
|
||||||
}).ToList();
|
|
||||||
|
|
||||||
wikiAvatarViewModelTaskSource.TrySetResult(true);
|
wikiAvatarViewModelTaskSource.TrySetResult(true);
|
||||||
return true;
|
return true;
|
||||||
@@ -131,19 +117,7 @@ internal sealed partial class HutaoCache : IHutaoCache
|
|||||||
if (await metadataService.InitializeAsync().ConfigureAwait(false))
|
if (await metadataService.InitializeAsync().ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
Dictionary<AvatarId, Avatar> idAvatarMap = await GetIdAvatarMapExtendedAsync().ConfigureAwait(false);
|
Dictionary<AvatarId, Avatar> idAvatarMap = await GetIdAvatarMapExtendedAsync().ConfigureAwait(false);
|
||||||
|
await WeaponCollocationsAsync(idAvatarMap).ConfigureAwait(false);
|
||||||
List<WeaponCollocation> weaponCollocationsRaw;
|
|
||||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
|
||||||
{
|
|
||||||
IHutaoService hutaoService = scope.ServiceProvider.GetRequiredService<IHutaoService>();
|
|
||||||
weaponCollocationsRaw = await hutaoService.GetWeaponCollocationsAsync().ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
WeaponCollocations = weaponCollocationsRaw.Select(co => new WeaponCollocationView()
|
|
||||||
{
|
|
||||||
WeaponId = co.WeaponId,
|
|
||||||
Avatars = co.Avatars.Select(a => new AvatarView(idAvatarMap[a.Item], a.Rate)).ToList(),
|
|
||||||
}).ToList();
|
|
||||||
|
|
||||||
wikiWeaponViewModelTaskSource.TrySetResult(true);
|
wikiWeaponViewModelTaskSource.TrySetResult(true);
|
||||||
return true;
|
return true;
|
||||||
@@ -164,6 +138,41 @@ internal sealed partial class HutaoCache : IHutaoCache
|
|||||||
return idAvatarExtendedMap;
|
return idAvatarExtendedMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async ValueTask AvatarCollocationsAsync(Dictionary<AvatarId, Avatar> idAvatarMap, Dictionary<WeaponId, Weapon> idWeaponMap, Dictionary<EquipAffixId, Model.Metadata.Reliquary.ReliquarySet> idReliquarySetMap)
|
||||||
|
{
|
||||||
|
List<AvatarCollocation> avatarCollocationsRaw;
|
||||||
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
|
{
|
||||||
|
IHutaoService hutaoService = scope.ServiceProvider.GetRequiredService<IHutaoService>();
|
||||||
|
avatarCollocationsRaw = await hutaoService.GetAvatarCollocationsAsync().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
AvatarCollocations = avatarCollocationsRaw.SelectList(co => new AvatarCollocationView()
|
||||||
|
{
|
||||||
|
AvatarId = co.AvatarId,
|
||||||
|
Avatars = co.Avatars.SelectList(a => new AvatarView(idAvatarMap[a.Item], a.Rate)),
|
||||||
|
Weapons = co.Weapons.SelectList(w => new WeaponView(idWeaponMap[w.Item], w.Rate)),
|
||||||
|
ReliquarySets = co.Reliquaries.SelectList(r => new ReliquarySetView(r, idReliquarySetMap)),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private async ValueTask WeaponCollocationsAsync(Dictionary<AvatarId, Avatar> idAvatarMap)
|
||||||
|
{
|
||||||
|
List<WeaponCollocation> weaponCollocationsRaw;
|
||||||
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
|
{
|
||||||
|
IHutaoService hutaoService = scope.ServiceProvider.GetRequiredService<IHutaoService>();
|
||||||
|
weaponCollocationsRaw = await hutaoService.GetWeaponCollocationsAsync().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
WeaponCollocations = weaponCollocationsRaw.SelectList(co => new WeaponCollocationView()
|
||||||
|
{
|
||||||
|
WeaponId = co.WeaponId,
|
||||||
|
Avatars = co.Avatars.SelectList(a => new AvatarView(idAvatarMap[a.Item], a.Rate)),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[SuppressMessage("", "SH003")]
|
||||||
private async Task AvatarAppearanceRankAsync(Dictionary<AvatarId, Avatar> idAvatarMap)
|
private async Task AvatarAppearanceRankAsync(Dictionary<AvatarId, Avatar> idAvatarMap)
|
||||||
{
|
{
|
||||||
List<AvatarAppearanceRank> avatarAppearanceRanksRaw;
|
List<AvatarAppearanceRank> avatarAppearanceRanksRaw;
|
||||||
@@ -173,13 +182,14 @@ internal sealed partial class HutaoCache : IHutaoCache
|
|||||||
avatarAppearanceRanksRaw = await hutaoService.GetAvatarAppearanceRanksAsync().ConfigureAwait(false);
|
avatarAppearanceRanksRaw = await hutaoService.GetAvatarAppearanceRanksAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
AvatarAppearanceRanks = avatarAppearanceRanksRaw.OrderByDescending(r => r.Floor).Select(rank => new AvatarRankView
|
AvatarAppearanceRanks = avatarAppearanceRanksRaw.SortByDescending(r => r.Floor).SelectList(rank => new AvatarRankView
|
||||||
{
|
{
|
||||||
Floor = string.Format(SH.ModelBindingHutaoComplexRankFloor, rank.Floor),
|
Floor = string.Format(SH.ModelBindingHutaoComplexRankFloor, rank.Floor),
|
||||||
Avatars = rank.Ranks.OrderByDescending(r => r.Rate).Select(rank => new AvatarView(idAvatarMap[rank.Item], rank.Rate)).ToList(),
|
Avatars = rank.Ranks.SortByDescending(r => r.Rate).SelectList(rank => new AvatarView(idAvatarMap[rank.Item], rank.Rate)),
|
||||||
}).ToList();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[SuppressMessage("", "SH003")]
|
||||||
private async Task AvatarUsageRanksAsync(Dictionary<AvatarId, Avatar> idAvatarMap)
|
private async Task AvatarUsageRanksAsync(Dictionary<AvatarId, Avatar> idAvatarMap)
|
||||||
{
|
{
|
||||||
List<AvatarUsageRank> avatarUsageRanksRaw;
|
List<AvatarUsageRank> avatarUsageRanksRaw;
|
||||||
@@ -189,13 +199,14 @@ internal sealed partial class HutaoCache : IHutaoCache
|
|||||||
avatarUsageRanksRaw = await hutaoService.GetAvatarUsageRanksAsync().ConfigureAwait(false);
|
avatarUsageRanksRaw = await hutaoService.GetAvatarUsageRanksAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
AvatarUsageRanks = avatarUsageRanksRaw.OrderByDescending(r => r.Floor).Select(rank => new AvatarRankView
|
AvatarUsageRanks = avatarUsageRanksRaw.SortByDescending(r => r.Floor).SelectList(rank => new AvatarRankView
|
||||||
{
|
{
|
||||||
Floor = string.Format(SH.ModelBindingHutaoComplexRankFloor, rank.Floor),
|
Floor = string.Format(SH.ModelBindingHutaoComplexRankFloor, rank.Floor),
|
||||||
Avatars = rank.Ranks.OrderByDescending(r => r.Rate).Select(rank => new AvatarView(idAvatarMap[rank.Item], rank.Rate)).ToList(),
|
Avatars = rank.Ranks.SortByDescending(r => r.Rate).SelectList(rank => new AvatarView(idAvatarMap[rank.Item], rank.Rate)),
|
||||||
}).ToList();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[SuppressMessage("", "SH003")]
|
||||||
private async Task AvatarConstellationInfosAsync(Dictionary<AvatarId, Avatar> idAvatarMap)
|
private async Task AvatarConstellationInfosAsync(Dictionary<AvatarId, Avatar> idAvatarMap)
|
||||||
{
|
{
|
||||||
List<AvatarConstellationInfo> avatarConstellationInfosRaw;
|
List<AvatarConstellationInfo> avatarConstellationInfosRaw;
|
||||||
@@ -205,12 +216,13 @@ internal sealed partial class HutaoCache : IHutaoCache
|
|||||||
avatarConstellationInfosRaw = await hutaoService.GetAvatarConstellationInfosAsync().ConfigureAwait(false);
|
avatarConstellationInfosRaw = await hutaoService.GetAvatarConstellationInfosAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
AvatarConstellationInfos = avatarConstellationInfosRaw.OrderBy(i => i.HoldingRate).Select(info =>
|
AvatarConstellationInfos = avatarConstellationInfosRaw.SortBy(i => i.HoldingRate).SelectList(info =>
|
||||||
{
|
{
|
||||||
return new AvatarConstellationInfoView(idAvatarMap[info.AvatarId], info.HoldingRate, info.Constellations.SelectList(x => x.Rate));
|
return new AvatarConstellationInfoView(idAvatarMap[info.AvatarId], info.HoldingRate, info.Constellations.SelectList(x => x.Rate));
|
||||||
}).ToList();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[SuppressMessage("", "SH003")]
|
||||||
private async Task TeamAppearancesAsync(Dictionary<AvatarId, Avatar> idAvatarMap)
|
private async Task TeamAppearancesAsync(Dictionary<AvatarId, Avatar> idAvatarMap)
|
||||||
{
|
{
|
||||||
List<TeamAppearance> teamAppearancesRaw;
|
List<TeamAppearance> teamAppearancesRaw;
|
||||||
@@ -220,9 +232,10 @@ internal sealed partial class HutaoCache : IHutaoCache
|
|||||||
teamAppearancesRaw = await hutaoService.GetTeamAppearancesAsync().ConfigureAwait(false);
|
teamAppearancesRaw = await hutaoService.GetTeamAppearancesAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
TeamAppearances = teamAppearancesRaw.OrderByDescending(t => t.Floor).Select(team => new TeamAppearanceView(team, idAvatarMap)).ToList();
|
TeamAppearances = teamAppearancesRaw.SortByDescending(t => t.Floor).SelectList(team => new TeamAppearanceView(team, idAvatarMap));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[SuppressMessage("", "SH003")]
|
||||||
private async Task OverviewAsync()
|
private async Task OverviewAsync()
|
||||||
{
|
{
|
||||||
using (IServiceScope scope = serviceProvider.CreateScope())
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
|
|||||||
@@ -108,8 +108,6 @@ internal sealed partial class HutaoService : IHutaoService
|
|||||||
await appDbContext.ObjectCache.AddAndSaveAsync(new()
|
await appDbContext.ObjectCache.AddAndSaveAsync(new()
|
||||||
{
|
{
|
||||||
Key = key,
|
Key = key,
|
||||||
|
|
||||||
// We hold the cache for 4 hours
|
|
||||||
ExpireTime = DateTimeOffset.Now.Add(CacheExpireTime),
|
ExpireTime = DateTimeOffset.Now.Add(CacheExpireTime),
|
||||||
Value = JsonSerializer.Serialize(data, options),
|
Value = JsonSerializer.Serialize(data, options),
|
||||||
}).ConfigureAwait(false);
|
}).ConfigureAwait(false);
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ internal sealed class HutaoUserOptions : ObservableObject, IOptions<HutaoUserOpt
|
|||||||
public void UpdateUserInfo(UserInfo userInfo)
|
public void UpdateUserInfo(UserInfo userInfo)
|
||||||
{
|
{
|
||||||
IsLicensedDeveloper = userInfo.IsLicensedDeveloper;
|
IsLicensedDeveloper = userInfo.IsLicensedDeveloper;
|
||||||
IsCloudServiceAllowed = userInfo.GachaLogExpireAt > DateTimeOffset.Now;
|
|
||||||
GachaLogExpireAt = string.Format(Regex.Unescape(SH.ServiceHutaoUserGachaLogExpiredAt), userInfo.GachaLogExpireAt);
|
GachaLogExpireAt = string.Format(Regex.Unescape(SH.ServiceHutaoUserGachaLogExpiredAt), userInfo.GachaLogExpireAt);
|
||||||
|
IsCloudServiceAllowed = IsLicensedDeveloper || userInfo.GachaLogExpireAt > DateTimeOffset.Now;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -97,11 +97,8 @@
|
|||||||
<None Remove="Resource\Icon\UI_Icon_None.png" />
|
<None Remove="Resource\Icon\UI_Icon_None.png" />
|
||||||
<None Remove="Resource\Icon\UI_Icon_Tower_Star.png" />
|
<None Remove="Resource\Icon\UI_Icon_Tower_Star.png" />
|
||||||
<None Remove="Resource\Icon\UI_ItemIcon_201.png" />
|
<None Remove="Resource\Icon\UI_ItemIcon_201.png" />
|
||||||
<None Remove="Resource\Icon\UI_ItemIcon_204.png" />
|
|
||||||
<None Remove="Resource\Icon\UI_ItemIcon_210.png" />
|
<None Remove="Resource\Icon\UI_ItemIcon_210.png" />
|
||||||
<None Remove="Resource\Icon\UI_ItemIcon_220021.png" />
|
|
||||||
<None Remove="Resource\Icon\UI_MarkCustom_TagMonster.png" />
|
<None Remove="Resource\Icon\UI_MarkCustom_TagMonster.png" />
|
||||||
<None Remove="Resource\Icon\UI_MarkQuest_Events_Proce.png" />
|
|
||||||
<None Remove="Resource\Icon\UI_MarkTower.png" />
|
<None Remove="Resource\Icon\UI_MarkTower.png" />
|
||||||
<None Remove="Resource\Icon\UI_MarkTower_Tower.png" />
|
<None Remove="Resource\Icon\UI_MarkTower_Tower.png" />
|
||||||
<None Remove="Resource\Segoe Fluent Icons.ttf" />
|
<None Remove="Resource\Segoe Fluent Icons.ttf" />
|
||||||
@@ -227,11 +224,8 @@
|
|||||||
<Content Include="Resource\Icon\UI_Icon_None.png" />
|
<Content Include="Resource\Icon\UI_Icon_None.png" />
|
||||||
<Content Include="Resource\Icon\UI_Icon_Tower_Star.png" />
|
<Content Include="Resource\Icon\UI_Icon_Tower_Star.png" />
|
||||||
<Content Include="Resource\Icon\UI_ItemIcon_201.png" />
|
<Content Include="Resource\Icon\UI_ItemIcon_201.png" />
|
||||||
<Content Include="Resource\Icon\UI_ItemIcon_204.png" />
|
|
||||||
<Content Include="Resource\Icon\UI_ItemIcon_210.png" />
|
<Content Include="Resource\Icon\UI_ItemIcon_210.png" />
|
||||||
<Content Include="Resource\Icon\UI_ItemIcon_220021.png" />
|
|
||||||
<Content Include="Resource\Icon\UI_MarkCustom_TagMonster.png" />
|
<Content Include="Resource\Icon\UI_MarkCustom_TagMonster.png" />
|
||||||
<Content Include="Resource\Icon\UI_MarkQuest_Events_Proce.png" />
|
|
||||||
<Content Include="Resource\Icon\UI_MarkTower.png" />
|
<Content Include="Resource\Icon\UI_MarkTower.png" />
|
||||||
<Content Include="Resource\Icon\UI_MarkTower_Tower.png" />
|
<Content Include="Resource\Icon\UI_MarkTower_Tower.png" />
|
||||||
<Content Include="Resource\WelcomeView_Background.png" />
|
<Content Include="Resource\WelcomeView_Background.png" />
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:mxi="using:Microsoft.Xaml.Interactivity"
|
xmlns:mxi="using:Microsoft.Xaml.Interactivity"
|
||||||
xmlns:shcb="using:Snap.Hutao.Control.Behavior"
|
xmlns:shcb="using:Snap.Hutao.Control.Behavior"
|
||||||
|
xmlns:shci="using:Snap.Hutao.Control.Image"
|
||||||
xmlns:shvc="using:Snap.Hutao.View.Control"
|
xmlns:shvc="using:Snap.Hutao.View.Control"
|
||||||
xmlns:shvd="using:Snap.Hutao.ViewModel.DailyNote"
|
xmlns:shvd="using:Snap.Hutao.ViewModel.DailyNote"
|
||||||
Padding="0"
|
Padding="0"
|
||||||
@@ -75,7 +76,7 @@
|
|||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<Border Style="{StaticResource BorderCardStyle}">
|
<Border Style="{StaticResource BorderCardStyle}">
|
||||||
<StackPanel VerticalAlignment="Center">
|
<StackPanel VerticalAlignment="Center">
|
||||||
<Image Width="32" Source="ms-appx:///Resource/Icon/UI_ItemIcon_204.png"/>
|
<shci:CachedImage Width="32" Source="{StaticResource UI_ItemIcon_204}"/>
|
||||||
<TextBlock
|
<TextBlock
|
||||||
HorizontalAlignment="Center"
|
HorizontalAlignment="Center"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
|
|||||||
@@ -229,7 +229,7 @@
|
|||||||
Width="40"
|
Width="40"
|
||||||
Height="40"
|
Height="40"
|
||||||
VerticalAlignment="Center">
|
VerticalAlignment="Center">
|
||||||
<Image Width="32" Source="ms-appx:///Resource/Icon/UI_ItemIcon_204.png"/>
|
<shci:CachedImage Width="32" Source="{StaticResource UI_ItemIcon_204}"/>
|
||||||
<ProgressRing
|
<ProgressRing
|
||||||
Width="40"
|
Width="40"
|
||||||
Height="40"
|
Height="40"
|
||||||
|
|||||||
13
src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Images.cs
Normal file
13
src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Images.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
namespace Snap.Hutao.Web.Hoyolab;
|
||||||
|
|
||||||
|
internal static class Images
|
||||||
|
{
|
||||||
|
public const string UIItemIcon204 = $"https://smms.app/image/x9psnPrcbYoCl6U";
|
||||||
|
public const string UIItemIcon210 = $"https://smms.app/image/n4gwxlFGPTX2j8p";
|
||||||
|
public const string UIItemIcon220021 = $"https://smms.app/image/kbh1a2YVXpxWuez";
|
||||||
|
public const string UIIconInteeExplore1 = $"https://smms.app/image/zJ4UYqKiD6uQlLc";
|
||||||
|
public const string UIMarkQuestEventsProce = $"https://smms.app/image/DQyTF3rv4aA8MZV";
|
||||||
|
}
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
// Copyright (c) DGP Studio. All rights reserved.
|
|
||||||
// Licensed under the MIT license.
|
|
||||||
|
|
||||||
namespace Snap.Hutao.Web.Hoyolab;
|
|
||||||
|
|
||||||
internal static class OssImages
|
|
||||||
{
|
|
||||||
public const string UIMarkQuestEventsProce = "https://upload-bbs.miyoushe.com/upload/2023/07/26/184872832/4b9ba51caa13e5516d507d64c7234b0c_7636696921807680614.png";
|
|
||||||
public const string UIItemIcon220021 = "https://upload-bbs.miyoushe.com/upload/2023/07/26/184872832/7cd02abbf20727ec4fd0dae777b65748_6274739470729303254.png";
|
|
||||||
public const string UIItemIcon210 = "https://upload-bbs.miyoushe.com/upload/2023/07/26/184872832/75dbb40f46380efbdbc23bd3a251c83a_538508470291955954.png";
|
|
||||||
public const string UIItemIcon204 = "https://upload-bbs.miyoushe.com/upload/2023/07/26/184872832/4a3cbdd778648b8aee5c4ebe9672c68b_5158859174407167834.png";
|
|
||||||
public const string UIIconInteeExplore1 = "https://upload-bbs.miyoushe.com/upload/2023/07/26/184872832/830fcd53539be4aa7faa02391f5384c5_8996801294815343498.png";
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user