mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
impl #117
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
|
||||
using Microsoft.Win32;
|
||||
using Snap.Hutao.Core.Json;
|
||||
using Snap.Hutao.Core.Setting;
|
||||
using Snap.Hutao.Extension;
|
||||
using Snap.Hutao.Web.Hoyolab.DynamicSecret;
|
||||
using System.Collections.Immutable;
|
||||
@@ -123,16 +124,25 @@ internal static class CoreEnvironment
|
||||
|
||||
private static string GetDatafolderPath()
|
||||
{
|
||||
string myDocument = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
|
||||
string preferredPath = LocalSetting.Get(SettingKeys.DataFolderPath, string.Empty);
|
||||
|
||||
if (string.IsNullOrEmpty(preferredPath))
|
||||
{
|
||||
string myDocument = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
|
||||
#if RELEASE
|
||||
// 将测试版与正式版的文件目录分离
|
||||
string folderName = Package.Current.PublisherDisplayName == "DGP Studio CI" ? "HutaoAlpha" : "Hutao";
|
||||
// 将测试版与正式版的文件目录分离
|
||||
string folderName = Package.Current.PublisherDisplayName == "DGP Studio CI" ? "HutaoAlpha" : "Hutao";
|
||||
#else
|
||||
// 使得迁移能正常生成
|
||||
string folderName = "Hutao";
|
||||
// 使得迁移能正常生成
|
||||
string folderName = "Hutao";
|
||||
#endif
|
||||
string path = Path.GetFullPath(Path.Combine(myDocument, folderName));
|
||||
Directory.CreateDirectory(path);
|
||||
return path;
|
||||
string path = Path.GetFullPath(Path.Combine(myDocument, folderName));
|
||||
Directory.CreateDirectory(path);
|
||||
return path;
|
||||
}
|
||||
else
|
||||
{
|
||||
return preferredPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -63,6 +63,32 @@ internal static class PickerExtension
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="FolderPicker.PickSingleFolderAsync"/>
|
||||
public static async Task<ValueResult<bool, string>> TryPickSingleFolderAsync(this FolderPicker picker)
|
||||
{
|
||||
StorageFolder? folder;
|
||||
Exception? exception = null;
|
||||
try
|
||||
{
|
||||
folder = await picker.PickSingleFolderAsync().AsTask().ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
exception = ex;
|
||||
folder = null;
|
||||
}
|
||||
|
||||
if (folder != null)
|
||||
{
|
||||
return new(true, folder.Path);
|
||||
}
|
||||
else
|
||||
{
|
||||
InfoBarWaringPickerException(exception);
|
||||
return new(false, null!);
|
||||
}
|
||||
}
|
||||
|
||||
private static void InfoBarWaringPickerException(Exception? exception)
|
||||
{
|
||||
if (exception != null)
|
||||
|
||||
@@ -77,6 +77,12 @@ internal static class LocalSetting
|
||||
return Get<char>(key, defaultValue);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Get{T}(string, T)"/>
|
||||
public static string Get(string key, string defaultValue)
|
||||
{
|
||||
return Get<string>(key, defaultValue);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Get{T}(string, T)"/>
|
||||
public static DateTimeOffset Get(string key, DateTimeOffset defaultValue)
|
||||
{
|
||||
@@ -173,6 +179,12 @@ internal static class LocalSetting
|
||||
Set<char>(key, value);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Set{T}(string, T)"/>
|
||||
public static void Set(string key, string value)
|
||||
{
|
||||
Set<string>(key, value);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Set{T}(string, T)"/>
|
||||
public static void Set(string key, DateTimeOffset value)
|
||||
{
|
||||
@@ -216,8 +228,7 @@ internal static class LocalSetting
|
||||
/// <param name="key">键</param>
|
||||
/// <param name="defaultValue">默认值</param>
|
||||
/// <returns>获取的值</returns>
|
||||
private static T Get<T>(string key, T defaultValue = default)
|
||||
where T : struct
|
||||
private static T Get<T>(string key, T defaultValue = default!)
|
||||
{
|
||||
if (Container.Values.TryGetValue(key, out object? value))
|
||||
{
|
||||
@@ -238,7 +249,6 @@ internal static class LocalSetting
|
||||
/// <param name="key">键</param>
|
||||
/// <param name="value">值</param>
|
||||
private static void Set<T>(string key, T value)
|
||||
where T : struct
|
||||
{
|
||||
Container.Values[key] = value;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,11 @@ internal static class SettingKeys
|
||||
/// </summary>
|
||||
public const string LaunchTimes = "LaunchTimes";
|
||||
|
||||
/// <summary>
|
||||
/// 数据文件夹
|
||||
/// </summary>
|
||||
public const string DataFolderPath = "DataFolderPath";
|
||||
|
||||
/// <summary>
|
||||
/// 静态资源合约
|
||||
/// 新增合约时 请注意
|
||||
|
||||
@@ -1761,6 +1761,15 @@ namespace Snap.Hutao.Resource.Localization {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 设置数据目录成功,重启以应用更改 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string ViewModelSettingSetDataFolderSuccess {
|
||||
get {
|
||||
return ResourceManager.GetString("ViewModelSettingSetDataFolderSuccess", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 用户 [{0}] 添加成功 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -3327,6 +3336,24 @@ namespace Snap.Hutao.Resource.Localization {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 更改目录后需要手动移动目录内的数据,否则会重新创建用户数据 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string ViewPageSettingSetDataFolderDescription {
|
||||
get {
|
||||
return ResourceManager.GetString("ViewPageSettingSetDataFolderDescription", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 更改数据目录 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string ViewPageSettingSetDataFolderHeader {
|
||||
get {
|
||||
return ResourceManager.GetString("ViewPageSettingSetDataFolderHeader", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 设置路径 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -3372,6 +3399,15 @@ namespace Snap.Hutao.Resource.Localization {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 更改 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string ViewPageSettingStorageSetAction {
|
||||
get {
|
||||
return ResourceManager.GetString("ViewPageSettingStorageSetAction", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 前往商店 的本地化字符串。
|
||||
/// </summary>
|
||||
|
||||
@@ -684,6 +684,9 @@
|
||||
<data name="ViewModelSettingClearWebCacheSuccess" xml:space="preserve">
|
||||
<value>清除完成</value>
|
||||
</data>
|
||||
<data name="ViewModelSettingSetDataFolderSuccess" xml:space="preserve">
|
||||
<value>设置数据目录成功,重启以应用更改</value>
|
||||
</data>
|
||||
<data name="ViewModelUserAdded" xml:space="preserve">
|
||||
<value>用户 [{0}] 添加成功</value>
|
||||
</data>
|
||||
@@ -1206,6 +1209,12 @@
|
||||
<data name="ViewPageSettingGameHeader" xml:space="preserve">
|
||||
<value>游戏</value>
|
||||
</data>
|
||||
<data name="ViewPageSettingSetDataFolderDescription" xml:space="preserve">
|
||||
<value>更改目录后需要手动移动目录内的数据,否则会重新创建用户数据</value>
|
||||
</data>
|
||||
<data name="ViewPageSettingSetDataFolderHeader" xml:space="preserve">
|
||||
<value>更改数据目录</value>
|
||||
</data>
|
||||
<data name="ViewPageSettingSetGamePathAction" xml:space="preserve">
|
||||
<value>设置路径</value>
|
||||
</data>
|
||||
@@ -1221,6 +1230,9 @@
|
||||
<data name="ViewPageSettingStorageOpenAction" xml:space="preserve">
|
||||
<value>打开</value>
|
||||
</data>
|
||||
<data name="ViewPageSettingStorageSetAction" xml:space="preserve">
|
||||
<value>更改</value>
|
||||
</data>
|
||||
<data name="ViewPageSettingUpdateCheckAction" xml:space="preserve">
|
||||
<value>前往商店</value>
|
||||
</data>
|
||||
|
||||
@@ -139,8 +139,16 @@
|
||||
<Button Command="{Binding Experimental.OpenDataFolderCommand}" Content="{shcm:ResourceString Name=ViewPageSettingStorageOpenAction}"/>
|
||||
</wsc:Setting.ActionContent>
|
||||
</wsc:Setting>
|
||||
|
||||
<wsc:Setting
|
||||
Description="{shcm:ResourceString Name=ViewPageSettingSetDataFolderDescription}"
|
||||
Header="{shcm:ResourceString Name=ViewPageSettingSetDataFolderHeader}"
|
||||
Icon="">
|
||||
<wsc:Setting.ActionContent>
|
||||
<Button Command="{Binding SetDataFolderCommand}" Content="{shcm:ResourceString Name=ViewPageSettingStorageSetAction}"/>
|
||||
</wsc:Setting.ActionContent>
|
||||
</wsc:Setting>
|
||||
<wsc:Setting
|
||||
Margin="0,4,0,0"
|
||||
Description="{shcm:ResourceString Name=ViewPageSettingCacheFolderDescription}"
|
||||
Header="{shcm:ResourceString Name=ViewPageSettingCacheFolderHeader}"
|
||||
Icon="">
|
||||
|
||||
@@ -4,17 +4,22 @@
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using Snap.Hutao.Core.Database;
|
||||
using Snap.Hutao.Core.IO;
|
||||
using Snap.Hutao.Core.Setting;
|
||||
using Snap.Hutao.Core.Windowing;
|
||||
using Snap.Hutao.Factory.Abstraction;
|
||||
using Snap.Hutao.Model;
|
||||
using Snap.Hutao.Model.Entity;
|
||||
using Snap.Hutao.Model.Entity.Database;
|
||||
using Snap.Hutao.Service.Abstraction;
|
||||
using Snap.Hutao.Service.GachaLog;
|
||||
using Snap.Hutao.Service.GachaLog.QueryProvider;
|
||||
using Snap.Hutao.Service.Game;
|
||||
using Snap.Hutao.Service.Game.Locator;
|
||||
using Snap.Hutao.View.Dialog;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using Windows.Storage;
|
||||
using Windows.Storage.Pickers;
|
||||
|
||||
namespace Snap.Hutao.ViewModel;
|
||||
|
||||
@@ -75,6 +80,7 @@ internal class SettingViewModel : Abstraction.ViewModel
|
||||
UpdateCheckCommand = new AsyncRelayCommand(CheckUpdateAsync);
|
||||
DeleteGameWebCacheCommand = new RelayCommand(DeleteGameWebCache);
|
||||
ShowSignInWebViewDialogCommand = new AsyncRelayCommand(ShowSignInWebViewDialogAsync);
|
||||
SetDataFolderCommand = new AsyncRelayCommand(SetDataFolderAsync);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -178,6 +184,11 @@ internal class SettingViewModel : Abstraction.ViewModel
|
||||
/// </summary>
|
||||
public ICommand ShowSignInWebViewDialogCommand { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 设置数据目录命令
|
||||
/// </summary>
|
||||
public ICommand SetDataFolderCommand { get; }
|
||||
|
||||
private async Task SetGamePathAsync()
|
||||
{
|
||||
IGameLocator locator = Ioc.Default.GetRequiredService<IEnumerable<IGameLocator>>()
|
||||
@@ -242,4 +253,18 @@ internal class SettingViewModel : Abstraction.ViewModel
|
||||
await Windows.System.Launcher.LaunchUriAsync(new(@"ms-windows-store://pdp/?productid=9PH4NXJ2JN52"));
|
||||
#endif
|
||||
}
|
||||
|
||||
private async Task SetDataFolderAsync()
|
||||
{
|
||||
IPickerFactory pickerFactory = Ioc.Default.GetRequiredService<IPickerFactory>();
|
||||
FolderPicker picker = pickerFactory.GetFolderPicker();
|
||||
(bool isOk, string folder) = await picker.TryPickSingleFolderAsync().ConfigureAwait(false);
|
||||
|
||||
IInfoBarService infoBarService = Ioc.Default.GetRequiredService<IInfoBarService>();
|
||||
if (isOk)
|
||||
{
|
||||
LocalSetting.Set(SettingKeys.DataFolderPath, folder);
|
||||
infoBarService.Success(SH.ViewModelSettingSetDataFolderSuccess);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
using Snap.Hutao.Service.Abstraction;
|
||||
using Snap.Hutao.Web.Bridge.Model;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Snap.Hutao.Web.Response;
|
||||
|
||||
@@ -43,24 +44,12 @@ public class Response
|
||||
/// </summary>
|
||||
/// <typeparam name="TData">类型</typeparam>
|
||||
/// <param name="response">本体</param>
|
||||
/// <param name="callerName">调用方法名称</param>
|
||||
/// <returns>本体或默认值,当本体为 null 时 返回默认值</returns>
|
||||
public static Response<TData> DefaultIfNull<TData>(Response<TData>? response)
|
||||
public static Response<TData> DefaultIfNull<TData>(Response<TData>? response, [CallerMemberName] string callerName = default!)
|
||||
{
|
||||
// 0x26F19335 is a magic number that hashed from "Snap.Hutao"
|
||||
return response ?? new(0x26F19335, $"[{typeof(TData).Name}] 请求异常", default);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回本体或带有消息提示的默认值
|
||||
/// </summary>
|
||||
/// <typeparam name="TData">类型</typeparam>
|
||||
/// <param name="response">本体</param>
|
||||
/// <param name="message">消息</param>
|
||||
/// <returns>本体或默认值,当本体为 null 时 返回默认值</returns>
|
||||
public static Response<TData> DefaultIfNull<TData>(Response<TData>? response, string message)
|
||||
{
|
||||
// 0x26F19335 is a magic number that hashed from "Snap.Hutao"
|
||||
return response ?? new(0x26F19335, message, default);
|
||||
return response ?? new(0x26F19335, $"[{callerName}] 中的 [{typeof(TData).Name}] 请求异常", default);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
||||
Reference in New Issue
Block a user