ValueResult struct & new Icon
|
Before Width: | Height: | Size: 7.9 KiB After Width: | Height: | Size: 7.8 KiB |
|
Before Width: | Height: | Size: 254 KiB After Width: | Height: | Size: 209 KiB |
|
Before Width: | Height: | Size: 123 KiB After Width: | Height: | Size: 125 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 8.3 KiB |
|
Before Width: | Height: | Size: 87 KiB After Width: | Height: | Size: 71 KiB |
@@ -0,0 +1,19 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Core.Abstraction;
|
||||
|
||||
/// <summary>
|
||||
/// 指示该类可以解构为元组
|
||||
/// </summary>
|
||||
/// <typeparam name="T1">元组的第一个类型</typeparam>
|
||||
/// <typeparam name="T2">元组的第二个类型</typeparam>
|
||||
internal interface IDeconstructable<T1, T2>
|
||||
{
|
||||
/// <summary>
|
||||
/// 解构
|
||||
/// </summary>
|
||||
/// <param name="t1">第一个元素</param>
|
||||
/// <param name="t2">第二个元素</param>
|
||||
void Deconstruct(out T1 t1, out T2 t2);
|
||||
}
|
||||
@@ -66,7 +66,7 @@ internal sealed partial class DatebaseLogger : ILogger
|
||||
/// <summary>
|
||||
/// An empty scope without any logic
|
||||
/// </summary>
|
||||
private class NullScope : IDisposable
|
||||
private struct NullScope : IDisposable
|
||||
{
|
||||
public NullScope()
|
||||
{
|
||||
|
||||
@@ -1,38 +1,41 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Core.Abstraction;
|
||||
|
||||
namespace Snap.Hutao.Core.Threading;
|
||||
|
||||
/// <summary>
|
||||
/// 用于包装异步操作的结果
|
||||
/// 结构类型,在栈上分配
|
||||
/// </summary>
|
||||
/// <typeparam name="TResult"></typeparam>
|
||||
/// <typeparam name="TValue"></typeparam>
|
||||
public record Result<TResult, TValue>
|
||||
/// <typeparam name="TResult">结果类型</typeparam>
|
||||
/// <typeparam name="TValue">值类型</typeparam>
|
||||
public readonly struct ValueResult<TResult, TValue> : IDeconstructable<TResult, TValue>
|
||||
where TResult : notnull
|
||||
where TValue : notnull
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否成功
|
||||
/// </summary>
|
||||
public readonly TResult IsOk;
|
||||
|
||||
/// <summary>
|
||||
/// 值
|
||||
/// </summary>
|
||||
public readonly TValue Value;
|
||||
|
||||
/// <summary>
|
||||
/// 构造一个新的结果
|
||||
/// </summary>
|
||||
/// <param name="isOk">是否成功</param>
|
||||
/// <param name="value">值</param>
|
||||
public Result(TResult isOk, TValue value)
|
||||
public ValueResult(TResult isOk, TValue value)
|
||||
{
|
||||
IsOk = isOk;
|
||||
Value = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否成功
|
||||
/// </summary>
|
||||
public TResult IsOk { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 值
|
||||
/// </summary>
|
||||
public TValue Value { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 用于元组析构
|
||||
/// </summary>
|
||||
@@ -9,7 +9,7 @@
|
||||
<Identity
|
||||
Name="7f0db578-026f-4e0b-a75b-d5d06bb0a74d"
|
||||
Publisher="CN=DGP Studio"
|
||||
Version="1.0.31.0" />
|
||||
Version="1.0.32.0" />
|
||||
|
||||
<Properties>
|
||||
<DisplayName>胡桃</DisplayName>
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Core.Threading;
|
||||
|
||||
namespace Snap.Hutao.Service.GachaLog;
|
||||
|
||||
/// <summary>
|
||||
/// 浏览器缓存方法
|
||||
/// </summary>
|
||||
[Injection(InjectAs.Transient, typeof(IGachaLogUrlProvider))]
|
||||
internal class GachaLogUrlWebCacheProvider : IGachaLogUrlProvider
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public async Task<ValueResult<bool, string>> GetQueryAsync()
|
||||
{
|
||||
throw Must.NeverHappen();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Core.Threading;
|
||||
|
||||
namespace Snap.Hutao.Service.GachaLog;
|
||||
|
||||
/// <summary>
|
||||
/// 祈愿记录Url提供器
|
||||
/// </summary>
|
||||
public interface IGachaLogUrlProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// 异步获取包含验证密钥的查询语句
|
||||
/// </summary>
|
||||
/// <returns>包含验证密钥的查询语句</returns>
|
||||
Task<ValueResult<bool, string>> GetQueryAsync();
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Core.Threading;
|
||||
|
||||
namespace Snap.Hutao.Service.Game.Locator;
|
||||
|
||||
/// <summary>
|
||||
/// 游戏位置定位器
|
||||
/// </summary>
|
||||
internal interface IGameLocator
|
||||
{
|
||||
/// <summary>
|
||||
/// 异步获取游戏位置
|
||||
/// 路径应当包含游戏文件名称
|
||||
/// </summary>
|
||||
/// <returns>游戏位置</returns>
|
||||
Task<ValueResult<bool, string>> LocateGamePathAsync();
|
||||
|
||||
/// <summary>
|
||||
/// 异步获取游戏启动器位置
|
||||
/// 路径应当包含启动器文件名称
|
||||
/// </summary>
|
||||
/// <returns>游戏启动器位置</returns>
|
||||
Task<ValueResult<bool, string>> LocateLauncherPathAsync();
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Core.Threading;
|
||||
using Snap.Hutao.Factory.Abstraction;
|
||||
using Windows.Storage;
|
||||
using Windows.Storage.Pickers;
|
||||
|
||||
namespace Snap.Hutao.Service.Game.Locator;
|
||||
|
||||
/// <summary>
|
||||
/// 手动模式
|
||||
/// </summary>
|
||||
internal class ManualGameLocator : IGameLocator
|
||||
{
|
||||
private readonly IPickerFactory pickerFactory;
|
||||
|
||||
/// <summary>
|
||||
/// 构造一个新的手动模式提供器
|
||||
/// </summary>
|
||||
/// <param name="pickerFactory">选择器工厂</param>
|
||||
public ManualGameLocator(IPickerFactory pickerFactory)
|
||||
{
|
||||
this.pickerFactory = pickerFactory;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task<ValueResult<bool, string>> LocateGamePathAsync()
|
||||
{
|
||||
return LocateInternalAsync("YuanShen.exe");
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task<ValueResult<bool, string>> LocateLauncherPathAsync()
|
||||
{
|
||||
return LocateInternalAsync("launcher.exe");
|
||||
}
|
||||
|
||||
private async Task<ValueResult<bool, string>> LocateInternalAsync(string fileName)
|
||||
{
|
||||
FileOpenPicker picker = pickerFactory.GetFileOpenPicker();
|
||||
picker.FileTypeFilter.Add(".exe");
|
||||
picker.SuggestedStartLocation = PickerLocationId.ComputerFolder;
|
||||
|
||||
if (await picker.PickSingleFileAsync() is StorageFile file)
|
||||
{
|
||||
string path = file.Path;
|
||||
if (path.Contains(fileName))
|
||||
{
|
||||
return new(true, path);
|
||||
}
|
||||
}
|
||||
|
||||
return new(false, null!);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.Win32;
|
||||
using Snap.Hutao.Core.Threading;
|
||||
using System.IO;
|
||||
|
||||
namespace Snap.Hutao.Service.Game.Locator;
|
||||
|
||||
/// <summary>
|
||||
/// 注册表启动器位置定位器
|
||||
/// </summary>
|
||||
internal class RegistryLauncherLocator : IGameLocator
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public Task<ValueResult<bool, string>> LocateGamePathAsync()
|
||||
{
|
||||
return Task.FromResult(LocateInternal("InstallPath", "YuanShen.exe"));
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task<ValueResult<bool, string>> LocateLauncherPathAsync()
|
||||
{
|
||||
return Task.FromResult(LocateInternal("DisplayIcon"));
|
||||
}
|
||||
|
||||
private static ValueResult<bool, string> LocateInternal(string key, string? combine = null)
|
||||
{
|
||||
RegistryKey? uninstallKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\原神");
|
||||
if (uninstallKey != null)
|
||||
{
|
||||
if (uninstallKey.GetValue(key) is string path)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(combine))
|
||||
{
|
||||
path = Path.Combine(combine);
|
||||
}
|
||||
|
||||
return new(true, path);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new(false, null!);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return new(false, null!);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,7 @@ public sealed partial class AchievementArchiveCreateDialog : ContentDialog
|
||||
/// 获取输入的字符串
|
||||
/// </summary>
|
||||
/// <returns>输入的结果</returns>
|
||||
public async Task<Result<bool, string>> GetInputAsync()
|
||||
public async Task<ValueResult<bool, string>> GetInputAsync()
|
||||
{
|
||||
ContentDialogResult result = await ShowAsync();
|
||||
string text = InputText.Text ?? string.Empty;
|
||||
|
||||
@@ -42,11 +42,11 @@ public sealed partial class AchievementImportDialog : ContentDialog
|
||||
/// 异步获取导入选项
|
||||
/// </summary>
|
||||
/// <returns>导入选项</returns>
|
||||
public async Task<Result<bool, ImportOption>> GetImportOptionAsync()
|
||||
public async Task<ValueResult<bool, ImportOption>> GetImportOptionAsync()
|
||||
{
|
||||
ContentDialogResult result = await ShowAsync();
|
||||
ImportOption option = (ImportOption)ImportModeSelector.SelectedIndex;
|
||||
|
||||
return new Result<bool, ImportOption>(result == ContentDialogResult.Primary, option);
|
||||
return new(result == ContentDialogResult.Primary, option);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ public sealed partial class UserDialog : ContentDialog
|
||||
/// 获取输入的Cookie
|
||||
/// </summary>
|
||||
/// <returns>输入的结果</returns>
|
||||
public async Task<Result<bool, string>> GetInputCookieAsync()
|
||||
public async Task<ValueResult<bool, string>> GetInputCookieAsync()
|
||||
{
|
||||
ContentDialogResult result = await ShowAsync();
|
||||
string cookie = InputText.Text;
|
||||
|
||||
@@ -19,8 +19,32 @@
|
||||
</Page.Resources>
|
||||
<ScrollViewer>
|
||||
<StackPanel Margin="32,0,24,0">
|
||||
|
||||
<sc:SettingsGroup Header="关于 胡桃">
|
||||
<Grid Margin="0,4,0,16">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
<ColumnDefinition/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Image
|
||||
Grid.Column="0"
|
||||
Width="80"
|
||||
Source="ms-appx:///Assets/Square150x150Logo.scale-200.png"/>
|
||||
<Grid
|
||||
Margin="16,0,0,0"
|
||||
Grid.Column="1">
|
||||
<TextBlock TextWrapping="Wrap">
|
||||
<Run>胡桃 图标由 </Run>
|
||||
<Hyperlink NavigateUri="https://dieqi32894.lofter.com/post/4b58ce16_2b6b2d365">LOFTER@夙夜</Hyperlink>
|
||||
<Run>纸绘,并由 </Run>
|
||||
<Hyperlink NavigateUri="https://github.com/DGP-Studio">DGP Studio</Hyperlink>
|
||||
<Run> 后期处理后,授权使用。</Run>
|
||||
</TextBlock>
|
||||
<TextBlock
|
||||
VerticalAlignment="Bottom"
|
||||
Text="Copyright © 2022 DGP Studio. All Rights Reserved."/>
|
||||
</Grid>
|
||||
|
||||
</Grid>
|
||||
<sc:Setting
|
||||
Icon=""
|
||||
Header="胡桃"
|
||||
|
||||