mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
fix several issues
This commit is contained in:
@@ -5,5 +5,5 @@ namespace Snap.Hutao.Core.Shell;
|
||||
|
||||
internal interface IShellLinkInterop
|
||||
{
|
||||
void CreateDesktopShoutcutForElevatedLaunch();
|
||||
bool TryCreateDesktopShoutcutForElevatedLaunch();
|
||||
}
|
||||
@@ -15,11 +15,20 @@ internal sealed partial class ShellLinkInterop : IShellLinkInterop
|
||||
{
|
||||
private readonly RuntimeOptions runtimeOptions;
|
||||
|
||||
public void CreateDesktopShoutcutForElevatedLaunch()
|
||||
public bool TryCreateDesktopShoutcutForElevatedLaunch()
|
||||
{
|
||||
string sourceLogoPath = Path.Combine(runtimeOptions.InstalledLocation, "Assets/Logo.ico");
|
||||
string targetLogoPath = Path.Combine(runtimeOptions.DataFolder, "ShellLinkLogo.ico");
|
||||
File.Copy(sourceLogoPath, targetLogoPath, true);
|
||||
|
||||
try
|
||||
{
|
||||
// System.IO.IOException: 无法加密指定的文件。
|
||||
File.Copy(sourceLogoPath, targetLogoPath, true);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
IShellLinkW shellLink = (IShellLinkW)new ShellLink();
|
||||
shellLink.SetPath("powershell");
|
||||
@@ -34,5 +43,7 @@ internal sealed partial class ShellLinkInterop : IShellLinkInterop
|
||||
|
||||
IPersistFile persistFile = (IPersistFile)shellLink;
|
||||
persistFile.Save(target, false);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@ internal sealed class UIGF
|
||||
/// <summary>
|
||||
/// 信息
|
||||
/// </summary>
|
||||
[JsonRequired]
|
||||
[JsonPropertyName("info")]
|
||||
public UIGFInfo Info { get; set; } = default!;
|
||||
|
||||
|
||||
@@ -3741,6 +3741,15 @@ namespace Snap.Hutao.Resource.Localization {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 创建桌面快捷方式失败 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string ViewModelSettingCreateDesktopShortcutFailed {
|
||||
get {
|
||||
return ResourceManager.GetString("ViewModelSettingCreateDesktopShortcutFailed", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 设置数据目录成功,重启以应用更改 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -5325,6 +5334,15 @@ namespace Snap.Hutao.Resource.Localization {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 版本更新前需要提前转换至与启动器匹配的服务器 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string ViewPageLaunchGameSwitchSchemeWarning {
|
||||
get {
|
||||
return ResourceManager.GetString("ViewPageLaunchGameSwitchSchemeWarning", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 请在游戏内关闭垂直同步选项,需要高性能的显卡以支持更高的帧率 的本地化字符串。
|
||||
/// </summary>
|
||||
|
||||
@@ -1400,6 +1400,9 @@
|
||||
<data name="ViewModelSettingCopyDeviceIdSuccess" xml:space="preserve">
|
||||
<value>复制成功</value>
|
||||
</data>
|
||||
<data name="ViewModelSettingCreateDesktopShortcutFailed" xml:space="preserve">
|
||||
<value>创建桌面快捷方式失败</value>
|
||||
</data>
|
||||
<data name="ViewModelSettingSetDataFolderSuccess" xml:space="preserve">
|
||||
<value>设置数据目录成功,重启以应用更改</value>
|
||||
</data>
|
||||
@@ -1928,6 +1931,9 @@
|
||||
<data name="ViewPageLaunchGameSwitchSchemeHeader" xml:space="preserve">
|
||||
<value>服务器</value>
|
||||
</data>
|
||||
<data name="ViewPageLaunchGameSwitchSchemeWarning" xml:space="preserve">
|
||||
<value>版本更新前需要提前转换至与启动器匹配的服务器</value>
|
||||
</data>
|
||||
<data name="ViewPageLaunchGameUnlockFpsDescription" xml:space="preserve">
|
||||
<value>请在游戏内关闭垂直同步选项,需要高性能的显卡以支持更高的帧率</value>
|
||||
</data>
|
||||
|
||||
@@ -99,9 +99,17 @@ internal sealed partial class GachaLogHutaoCloudService : IGachaLogHutaoCloudSer
|
||||
HutaoStatisticsFactoryMetadataContext context = new(idAvatarMap, idWeaponMap, gachaEvents);
|
||||
|
||||
GachaEventStatistics raw = response.Data;
|
||||
HutaoStatisticsFactory factory = new(context);
|
||||
HutaoStatistics statistics = factory.Create(raw);
|
||||
return new(true, statistics);
|
||||
try
|
||||
{
|
||||
HutaoStatisticsFactory factory = new(context);
|
||||
HutaoStatistics statistics = factory.Create(raw);
|
||||
return new(true, statistics);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// 元数据未能即时更新导致异常?
|
||||
return new(false, default!);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -147,4 +147,4 @@ internal sealed partial class LaunchScheme
|
||||
ServerGlobalChannelOfficialSubChannelGoogle,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -194,6 +194,7 @@ internal sealed partial class UserService : IUserService, IUserServiceUnsafe
|
||||
|
||||
private static bool TryGetUser(ObservableCollection<BindingUser> users, string mid, [NotNullWhen(true)] out BindingUser? user)
|
||||
{
|
||||
// TODO: System.InvalidOperationException: Sequence contains more than one matching element
|
||||
user = users.SingleOrDefault(u => u.Entity.Mid == mid);
|
||||
return user is not null;
|
||||
}
|
||||
|
||||
@@ -260,7 +260,7 @@
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Validation" Version="17.6.11" />
|
||||
<PackageReference Include="Microsoft.Windows.CsWin32" Version="0.3.18-beta">
|
||||
<PackageReference Include="Microsoft.Windows.CsWin32" Version="0.3.46-beta">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
||||
@@ -67,10 +67,18 @@
|
||||
Severity="Informational"/>
|
||||
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" Text="{shcm:ResourceString Name=ViewPageLaunchGameCommonHeader}"/>
|
||||
<cwc:SettingsCard
|
||||
Description="{shcm:ResourceString Name=ViewPageLaunchGameSwitchSchemeDescription}"
|
||||
Header="{shcm:ResourceString Name=ViewPageLaunchGameSwitchSchemeHeader}"
|
||||
HeaderIcon="{shcm:FontIcon Glyph=}"
|
||||
IsEnabled="{Binding HutaoOptions.IsElevated}">
|
||||
<cwc:SettingsCard.Description>
|
||||
<StackPanel>
|
||||
<TextBlock Style="{StaticResource CaptionTextBlockStyle}" Text="{shcm:ResourceString Name=ViewPageLaunchGameSwitchSchemeDescription}"/>
|
||||
<TextBlock
|
||||
Foreground="{ThemeResource SystemControlErrorTextForegroundBrush}"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
Text="{shcm:ResourceString Name=ViewPageLaunchGameSwitchSchemeWarning}"/>
|
||||
</StackPanel>
|
||||
</cwc:SettingsCard.Description>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<shvc:Elevation Margin="0,0,36,0" Visibility="{Binding HutaoOptions.IsElevated, Converter={StaticResource BoolToVisibilityRevertConverter}}"/>
|
||||
<shccs:ComboBox2
|
||||
|
||||
@@ -40,12 +40,7 @@ internal sealed partial class LoginHoyoverseUserPage : Microsoft.UI.Xaml.Control
|
||||
.TryCatchGetFromJsonAsync<WebApiResponse<AccountInfoWrapper>>(ApiOsEndpoints.WebApiOsAccountLoginByCookie, options, logger, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (resp is not null)
|
||||
{
|
||||
return $"{resp.Data?.AccountInfo?.AccountId}";
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
return $"{resp?.Data?.AccountInfo?.AccountId}";
|
||||
}
|
||||
|
||||
private async void OnRootLoaded(object sender, RoutedEventArgs e)
|
||||
@@ -81,6 +76,11 @@ internal sealed partial class LoginHoyoverseUserPage : Microsoft.UI.Xaml.Control
|
||||
IInfoBarService infoBarService = Ioc.Default.GetRequiredService<IInfoBarService>();
|
||||
|
||||
Cookie loginTicketCookie = Cookie.FromCoreWebView2Cookies(cookies);
|
||||
if (loginTicketCookie.IsEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string uid = await GetUidFromCookieAsync(Ioc.Default, loginTicketCookie).ConfigureAwait(false);
|
||||
loginTicketCookie[Cookie.LOGIN_UID] = uid;
|
||||
|
||||
|
||||
@@ -255,6 +255,12 @@ internal sealed partial class AvatarPropertyViewModel : Abstraction.ViewModel, I
|
||||
{
|
||||
baseline.AvatarId = avatar.Id;
|
||||
baseline.AvatarLevelCurrent = Math.Min(avatar.LevelNumber, baseline.AvatarLevelTarget);
|
||||
|
||||
if (avatar.Skills.Count < 3)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
baseline.SkillList[0].Id = avatar.Skills[0].GroupId;
|
||||
baseline.SkillList[0].LevelCurrent = Math.Min(avatar.Skills[0].LevelNumber, baseline.SkillList[0].LevelTarget);
|
||||
baseline.SkillList[1].Id = avatar.Skills[1].GroupId;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Service.GachaLog;
|
||||
using Snap.Hutao.Service.Notification;
|
||||
|
||||
namespace Snap.Hutao.ViewModel.GachaLog;
|
||||
|
||||
@@ -12,6 +13,7 @@ namespace Snap.Hutao.ViewModel.GachaLog;
|
||||
[ConstructorGenerated(CallBaseConstructor = true)]
|
||||
internal sealed partial class GachaLogViewModelSlim : Abstraction.ViewModelSlim<View.Page.GachaLogPage>
|
||||
{
|
||||
private readonly IInfoBarService infoBarService;
|
||||
private readonly ITaskContext taskContext;
|
||||
|
||||
private List<GachaStatisticsSlim>? statisticsList;
|
||||
@@ -30,11 +32,18 @@ internal sealed partial class GachaLogViewModelSlim : Abstraction.ViewModelSlim<
|
||||
|
||||
if (await gachaLogService.InitializeAsync().ConfigureAwait(false))
|
||||
{
|
||||
List<GachaStatisticsSlim> list = await gachaLogService.GetStatisticsSlimListAsync().ConfigureAwait(false);
|
||||
try
|
||||
{
|
||||
List<GachaStatisticsSlim> list = await gachaLogService.GetStatisticsSlimListAsync().ConfigureAwait(false);
|
||||
|
||||
await taskContext.SwitchToMainThreadAsync();
|
||||
StatisticsList = list;
|
||||
IsInitialized = true;
|
||||
await taskContext.SwitchToMainThreadAsync();
|
||||
StatisticsList = list;
|
||||
IsInitialized = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
infoBarService.Error(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -270,7 +270,14 @@ internal sealed partial class SettingViewModel : Abstraction.ViewModel
|
||||
[Command("CreateDesktopShortcutCommand")]
|
||||
private void CreateDesktopShortcutForElevatedLaunch()
|
||||
{
|
||||
shellLinkInterop.CreateDesktopShoutcutForElevatedLaunch();
|
||||
infoBarService.Information(SH.ViewModelSettingActionComplete);
|
||||
bool created = shellLinkInterop.TryCreateDesktopShoutcutForElevatedLaunch();
|
||||
if (created)
|
||||
{
|
||||
infoBarService.Information(SH.ViewModelSettingActionComplete);
|
||||
}
|
||||
else
|
||||
{
|
||||
infoBarService.Warning(SH.ViewModelSettingCreateDesktopShortcutFailed);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -37,6 +37,11 @@ internal sealed partial class Cookie
|
||||
set => inner[key] = value;
|
||||
}
|
||||
|
||||
public bool IsEmpty()
|
||||
{
|
||||
return inner.Count <= 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 解析Cookie字符串
|
||||
/// </summary>
|
||||
|
||||
@@ -54,16 +54,20 @@ internal sealed partial class AuthClient
|
||||
/// <returns>包含token的字典</returns>
|
||||
public async ValueTask<Response<ListWrapper<NameToken>>> GetMultiTokenByLoginTicketAsync(Cookie cookie, bool isOversea, CancellationToken token = default)
|
||||
{
|
||||
string loginTicket = cookie[Cookie.LOGIN_TICKET];
|
||||
string loginUid = cookie[Cookie.LOGIN_UID];
|
||||
Response<ListWrapper<NameToken>>? resp = null;
|
||||
if (cookie.TryGetLoginTicket(out Cookie? loginTicketCookie))
|
||||
{
|
||||
string loginTicket = loginTicketCookie[Cookie.LOGIN_TICKET];
|
||||
string loginUid = loginTicketCookie[Cookie.LOGIN_UID];
|
||||
|
||||
string url = isOversea
|
||||
? ApiOsEndpoints.AuthMultiToken(loginTicket, loginUid)
|
||||
: ApiEndpoints.AuthMultiToken(loginTicket, loginUid);
|
||||
string url = isOversea
|
||||
? ApiOsEndpoints.AuthMultiToken(loginTicket, loginUid)
|
||||
: ApiEndpoints.AuthMultiToken(loginTicket, loginUid);
|
||||
|
||||
Response<ListWrapper<NameToken>>? resp = await httpClient
|
||||
.TryCatchGetFromJsonAsync<Response<ListWrapper<NameToken>>>(url, options, logger, token)
|
||||
.ConfigureAwait(false);
|
||||
resp = await httpClient
|
||||
.TryCatchGetFromJsonAsync<Response<ListWrapper<NameToken>>>(url, options, logger, token)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return Response.Response.DefaultIfNull(resp);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ namespace Snap.Hutao.Web.Hutao.Geetest;
|
||||
|
||||
internal sealed class GeetestResponse
|
||||
{
|
||||
public static GeetestResponse InternalFailure { get; } = new() { Code = Response.Response.InternalFailure };
|
||||
|
||||
[JsonPropertyName("code")]
|
||||
public int Code { get; set; }
|
||||
|
||||
|
||||
@@ -22,14 +22,18 @@ internal sealed partial class HomaGeetestClient
|
||||
|
||||
if (string.IsNullOrEmpty(template))
|
||||
{
|
||||
return new() { Code = Response.Response.InternalFailure };
|
||||
return GeetestResponse.InternalFailure;
|
||||
}
|
||||
|
||||
GeetestResponse? resp = await httpClient
|
||||
.TryCatchGetFromJsonAsync<GeetestResponse>(template.Format(gt, challenge), options, logger, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
ArgumentNullException.ThrowIfNull(resp);
|
||||
if (resp is null)
|
||||
{
|
||||
return GeetestResponse.InternalFailure;
|
||||
}
|
||||
|
||||
return resp;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user