mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
Compare commits
26 Commits
fix/1379
...
fix/launch
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
51c4e66472 | ||
|
|
48875195bf | ||
|
|
a179e0e838 | ||
|
|
00c3e94e97 | ||
|
|
eec7224c07 | ||
|
|
11620816ec | ||
|
|
c5b75d6f82 | ||
|
|
a9295c0a37 | ||
|
|
29cd690032 | ||
|
|
78d8539ae2 | ||
|
|
7dec87586b | ||
|
|
d169f355f3 | ||
|
|
32b1b698df | ||
|
|
d6c7df1593 | ||
|
|
904fdf7fc9 | ||
|
|
b3e4ebb5d3 | ||
|
|
09b9af4575 | ||
|
|
8930548f44 | ||
|
|
34dbcc6f5d | ||
|
|
75c25cec53 | ||
|
|
22251ca937 | ||
|
|
57c9531db8 | ||
|
|
fd73743159 | ||
|
|
6594d9032d | ||
|
|
ae1b452697 | ||
|
|
bc3df782e4 |
16
.github/workflows/alpha.yml
vendored
16
.github/workflows/alpha.yml
vendored
@@ -13,6 +13,15 @@ on:
|
|||||||
- '**.md'
|
- '**.md'
|
||||||
- 'LICENSE'
|
- 'LICENSE'
|
||||||
- '**.yml'
|
- '**.yml'
|
||||||
|
pull_request:
|
||||||
|
paths-ignore:
|
||||||
|
- '.gitattributes'
|
||||||
|
- '.github/**'
|
||||||
|
- '.gitignore'
|
||||||
|
- '.gitmodules'
|
||||||
|
- '**.md'
|
||||||
|
- 'LICENSE'
|
||||||
|
- '**.yml'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
@@ -34,20 +43,21 @@ jobs:
|
|||||||
VERSION_API_TOKEN: ${{ secrets.VERSION_API_TOKEN }}
|
VERSION_API_TOKEN: ${{ secrets.VERSION_API_TOKEN }}
|
||||||
|
|
||||||
- name: Sign Msix
|
- name: Sign Msix
|
||||||
|
if: success() && github.event_name != 'pull_request'
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
run: |
|
run: |
|
||||||
[System.Convert]::FromBase64String("${{ secrets.CERTIFICATE }}") | Set-Content -AsByteStream temp.pfx
|
[System.Convert]::FromBase64String("${{ secrets.CERTIFICATE }}") | Set-Content -AsByteStream temp.pfx
|
||||||
signtool.exe sign /debug /v /a /fd SHA256 /f temp.pfx /p ${{ secrets.PW }} ${{ github.workspace }}\src\output\Snap.Hutao.Alpha-${{ steps.cake.outputs.version }}.msix
|
signtool.exe sign /debug /v /a /fd SHA256 /f temp.pfx /p ${{ secrets.PW }} ${{ github.workspace }}\src\output\Snap.Hutao.Alpha-${{ steps.cake.outputs.version }}.msix
|
||||||
|
|
||||||
- name: Upload signed msix
|
- name: Upload signed msix
|
||||||
if: success()
|
if: success() && github.event_name != 'pull_request'
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: Snap.Hutao.Alpha-${{ steps.cake.outputs.version }}
|
name: Snap.Hutao.Alpha-${{ steps.cake.outputs.version }}
|
||||||
path: ${{ github.workspace }}/src/output/Snap.Hutao.Alpha-${{ steps.cake.outputs.version }}.msix
|
path: ${{ github.workspace }}/src/output/Snap.Hutao.Alpha-${{ steps.cake.outputs.version }}.msix
|
||||||
|
|
||||||
- name: Add summary
|
- name: Add summary
|
||||||
if: success()
|
if: success() && github.event_name != 'pull_request'
|
||||||
shell: pwsh
|
shell: pwsh
|
||||||
run: |
|
run: |
|
||||||
$summary = "
|
$summary = "
|
||||||
|
|||||||
36
build.cake
36
build.cake
@@ -1,5 +1,5 @@
|
|||||||
#tool "nuget:?package=nuget.commandline&version=6.5.0"
|
#tool "nuget:?package=nuget.commandline&version=6.9.1"
|
||||||
#addin nuget:?package=Cake.Http&version=3.0.2
|
#addin nuget:?package=Cake.Http&version=4.0.0
|
||||||
|
|
||||||
var target = Argument("target", "Build");
|
var target = Argument("target", "Build");
|
||||||
var configuration = Argument("configuration", "Release");
|
var configuration = Argument("configuration", "Release");
|
||||||
@@ -33,18 +33,28 @@ if (GitHubActions.IsRunningOnGitHubActions)
|
|||||||
repoDir = GitHubActions.Environment.Workflow.Workspace.FullPath;
|
repoDir = GitHubActions.Environment.Workflow.Workspace.FullPath;
|
||||||
outputPath = System.IO.Path.Combine(repoDir, "src", "output");
|
outputPath = System.IO.Path.Combine(repoDir, "src", "output");
|
||||||
|
|
||||||
var versionAuth = HasEnvironmentVariable("VERSION_API_TOKEN") ? EnvironmentVariable("VERSION_API_TOKEN") : throw new Exception("Cannot find VERSION_API_TOKEN");
|
if (GitHubActions.Environment.PullRequest.IsPullRequest)
|
||||||
version = HttpGet(
|
{
|
||||||
"https://internal.snapgenshin.cn/BuildIntergration/RequestNewVersion",
|
version = System.DateTime.Now.ToString("yyyy.M.d.0");
|
||||||
new HttpSettings
|
|
||||||
{
|
Information("Is Pull Request. Skip version.");
|
||||||
Headers = new Dictionary<string, string>
|
}
|
||||||
{
|
else
|
||||||
|
{
|
||||||
|
var versionAuth = HasEnvironmentVariable("VERSION_API_TOKEN") ? EnvironmentVariable("VERSION_API_TOKEN") : throw new Exception("Cannot find VERSION_API_TOKEN");
|
||||||
|
version = HttpGet(
|
||||||
|
"https://internal.snapgenshin.cn/BuildIntergration/RequestNewVersion",
|
||||||
|
new HttpSettings
|
||||||
|
{
|
||||||
|
Headers = new Dictionary<string, string>
|
||||||
|
{
|
||||||
{ "Authorization", versionAuth }
|
{ "Authorization", versionAuth }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
Information($"Version: {version}");
|
|
||||||
|
Information($"Version: {version}");
|
||||||
|
}
|
||||||
|
|
||||||
GitHubActions.Commands.SetOutputParameter("version", version);
|
GitHubActions.Commands.SetOutputParameter("version", version);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,9 +12,9 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
||||||
<PackageReference Include="MSTest.TestAdapter" Version="3.2.0" />
|
<PackageReference Include="MSTest.TestAdapter" Version="3.2.1" />
|
||||||
<PackageReference Include="MSTest.TestFramework" Version="3.2.0" />
|
<PackageReference Include="MSTest.TestFramework" Version="3.2.1" />
|
||||||
<PackageReference Include="coverlet.collector" Version="6.0.0">
|
<PackageReference Include="coverlet.collector" Version="6.0.0">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
namespace Snap.Hutao.Control.Brush;
|
||||||
|
|
||||||
|
internal sealed class ColorSegmentCollection : List<IColorSegment>
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -9,5 +9,5 @@ internal interface IColorSegment
|
|||||||
{
|
{
|
||||||
Color Color { get; }
|
Color Color { get; }
|
||||||
|
|
||||||
double Value { get; }
|
double Value { get; set; }
|
||||||
}
|
}
|
||||||
@@ -5,40 +5,53 @@ using Microsoft.UI.Xaml;
|
|||||||
using Microsoft.UI.Xaml.Controls;
|
using Microsoft.UI.Xaml.Controls;
|
||||||
using Microsoft.UI.Xaml.Media;
|
using Microsoft.UI.Xaml.Media;
|
||||||
using Microsoft.UI.Xaml.Shapes;
|
using Microsoft.UI.Xaml.Shapes;
|
||||||
|
using System.Collections.Specialized;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace Snap.Hutao.Control.Brush;
|
namespace Snap.Hutao.Control.Brush;
|
||||||
|
|
||||||
[DependencyProperty("Source", typeof(List<IColorSegment>), default!, nameof(OnSourceChanged))]
|
[DependencyProperty("Source", typeof(ColorSegmentCollection), default!, nameof(OnSourceChanged))]
|
||||||
internal sealed partial class SegmentedBar : ContentControl
|
internal sealed partial class SegmentedBar : ContentControl
|
||||||
{
|
{
|
||||||
private readonly LinearGradientBrush brush = new() { StartPoint = new(0, 0), EndPoint = new(1, 0), };
|
private readonly LinearGradientBrush brush = new() { StartPoint = new(0, 0), EndPoint = new(1, 0), };
|
||||||
|
|
||||||
public SegmentedBar()
|
public SegmentedBar()
|
||||||
{
|
{
|
||||||
|
HorizontalContentAlignment = HorizontalAlignment.Stretch;
|
||||||
|
VerticalContentAlignment = VerticalAlignment.Stretch;
|
||||||
|
|
||||||
Content = new Rectangle()
|
Content = new Rectangle()
|
||||||
{
|
{
|
||||||
Fill = brush,
|
Fill = brush,
|
||||||
|
HorizontalAlignment = HorizontalAlignment.Stretch,
|
||||||
|
VerticalAlignment = VerticalAlignment.Stretch,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void OnSourceChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
|
private static void OnSourceChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
|
||||||
{
|
{
|
||||||
SegmentedBar segmentedBar = (SegmentedBar)obj;
|
UpdateLinearGradientBrush((SegmentedBar)obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void UpdateLinearGradientBrush(SegmentedBar segmentedBar)
|
||||||
|
{
|
||||||
GradientStopCollection collection = segmentedBar.brush.GradientStops;
|
GradientStopCollection collection = segmentedBar.brush.GradientStops;
|
||||||
collection.Clear();
|
collection.Clear();
|
||||||
|
|
||||||
if (args.NewValue as List<IColorSegment> is [_, ..] list)
|
ColorSegmentCollection segmentCollection = segmentedBar.Source;
|
||||||
|
|
||||||
|
double total = segmentCollection.Sum(seg => seg.Value);
|
||||||
|
if (total is 0D)
|
||||||
{
|
{
|
||||||
double total = list.Sum(seg => seg.Value);
|
return;
|
||||||
double offset = 0;
|
}
|
||||||
foreach (ref readonly IColorSegment segment in CollectionsMarshal.AsSpan(list))
|
|
||||||
{
|
double offset = 0;
|
||||||
collection.Add(new() { Color = segment.Color, Offset = offset, });
|
foreach (ref readonly IColorSegment segment in CollectionsMarshal.AsSpan(segmentCollection))
|
||||||
offset += segment.Value / total;
|
{
|
||||||
collection.Add(new() { Color = segment.Color, Offset = offset, });
|
collection.Add(new() { Color = segment.Color, Offset = offset, });
|
||||||
}
|
offset += segment.Value / total;
|
||||||
|
collection.Add(new() { Color = segment.Color, Offset = offset, });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
14
src/Snap.Hutao/Snap.Hutao/Control/Theme/KnownColors.cs
Normal file
14
src/Snap.Hutao/Snap.Hutao/Control/Theme/KnownColors.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
using Snap.Hutao.Win32;
|
||||||
|
using Windows.UI;
|
||||||
|
|
||||||
|
namespace Snap.Hutao.Control.Theme;
|
||||||
|
|
||||||
|
internal static class KnownColors
|
||||||
|
{
|
||||||
|
public static readonly Color Orange = StructMarshal.Color(0xFFBC6932);
|
||||||
|
public static readonly Color Purple = StructMarshal.Color(0xFFA156E0);
|
||||||
|
public static readonly Color Blue = StructMarshal.Color(0xFF5180CB);
|
||||||
|
}
|
||||||
@@ -42,10 +42,20 @@ internal sealed partial class ImageCache : IImageCache, IImageCacheFilePathOpera
|
|||||||
private string? baseFolder;
|
private string? baseFolder;
|
||||||
private string? cacheFolder;
|
private string? cacheFolder;
|
||||||
|
|
||||||
|
private string CacheFolder
|
||||||
|
{
|
||||||
|
get => LazyInitializer.EnsureInitialized(ref cacheFolder, () =>
|
||||||
|
{
|
||||||
|
baseFolder ??= serviceProvider.GetRequiredService<RuntimeOptions>().LocalCache;
|
||||||
|
DirectoryInfo info = Directory.CreateDirectory(Path.Combine(baseFolder, CacheFolderName));
|
||||||
|
return info.FullName;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void RemoveInvalid()
|
public void RemoveInvalid()
|
||||||
{
|
{
|
||||||
RemoveInternal(Directory.GetFiles(GetCacheFolder()).Where(file => IsFileInvalid(file, false)));
|
RemoveCore(Directory.GetFiles(CacheFolder).Where(file => IsFileInvalid(file, false)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
@@ -62,7 +72,7 @@ internal sealed partial class ImageCache : IImageCache, IImageCacheFilePathOpera
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
string folder = GetCacheFolder();
|
string folder = CacheFolder;
|
||||||
string[] files = Directory.GetFiles(folder);
|
string[] files = Directory.GetFiles(folder);
|
||||||
|
|
||||||
List<string> filesToDelete = [];
|
List<string> filesToDelete = [];
|
||||||
@@ -75,16 +85,16 @@ internal sealed partial class ImageCache : IImageCache, IImageCacheFilePathOpera
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RemoveInternal(filesToDelete);
|
RemoveCore(filesToDelete);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public async ValueTask<ValueFile> GetFileFromCacheAsync(Uri uri)
|
public async ValueTask<ValueFile> GetFileFromCacheAsync(Uri uri)
|
||||||
{
|
{
|
||||||
string fileName = GetCacheFileName(uri);
|
string fileName = GetCacheFileName(uri);
|
||||||
string filePath = Path.Combine(GetCacheFolder(), fileName);
|
string filePath = Path.Combine(CacheFolder, fileName);
|
||||||
|
|
||||||
if (File.Exists(filePath) && new FileInfo(filePath).Length != 0)
|
if (!IsFileInvalid(filePath))
|
||||||
{
|
{
|
||||||
return filePath;
|
return filePath;
|
||||||
}
|
}
|
||||||
@@ -94,10 +104,12 @@ internal sealed partial class ImageCache : IImageCache, IImageCacheFilePathOpera
|
|||||||
{
|
{
|
||||||
if (concurrentTasks.TryAdd(fileName, taskCompletionSource.Task))
|
if (concurrentTasks.TryAdd(fileName, taskCompletionSource.Task))
|
||||||
{
|
{
|
||||||
|
logger.LogDebug("Begin downloading image file from '{Uri}' to '{File}'", uri, filePath);
|
||||||
await DownloadFileAsync(uri, filePath).ConfigureAwait(false);
|
await DownloadFileAsync(uri, filePath).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
else if (concurrentTasks.TryGetValue(fileName, out Task? task))
|
else if (concurrentTasks.TryGetValue(fileName, out Task? task))
|
||||||
{
|
{
|
||||||
|
logger.LogDebug("Waiting for a queued image download task to complete for '{Uri}'", uri);
|
||||||
await task.ConfigureAwait(false);
|
await task.ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,7 +127,7 @@ internal sealed partial class ImageCache : IImageCache, IImageCacheFilePathOpera
|
|||||||
public ValueFile GetFileFromCategoryAndName(string category, string fileName)
|
public ValueFile GetFileFromCategoryAndName(string category, string fileName)
|
||||||
{
|
{
|
||||||
Uri dummyUri = Web.HutaoEndpoints.StaticRaw(category, fileName).ToUri();
|
Uri dummyUri = Web.HutaoEndpoints.StaticRaw(category, fileName).ToUri();
|
||||||
return Path.Combine(GetCacheFolder(), GetCacheFileName(dummyUri));
|
return Path.Combine(CacheFolder, GetCacheFileName(dummyUri));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetCacheFileName(Uri uri)
|
private static string GetCacheFileName(Uri uri)
|
||||||
@@ -137,17 +149,18 @@ internal sealed partial class ImageCache : IImageCache, IImageCacheFilePathOpera
|
|||||||
return fileInfo.Length == 0;
|
return fileInfo.Length == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RemoveInternal(IEnumerable<string> filePaths)
|
private void RemoveCore(IEnumerable<string> filePaths)
|
||||||
{
|
{
|
||||||
foreach (string filePath in filePaths)
|
foreach (string filePath in filePaths)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
File.Delete(filePath);
|
File.Delete(filePath);
|
||||||
|
logger.LogInformation("Remove cached image succeed:{File}", filePath);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.LogWarning(ex, "Remove Cache Image Failed:{File}", filePath);
|
logger.LogWarning(ex, "Remove cached image failed:{File}", filePath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -155,14 +168,17 @@ internal sealed partial class ImageCache : IImageCache, IImageCacheFilePathOpera
|
|||||||
[SuppressMessage("", "SH003")]
|
[SuppressMessage("", "SH003")]
|
||||||
private async Task DownloadFileAsync(Uri uri, string baseFile)
|
private async Task DownloadFileAsync(Uri uri, string baseFile)
|
||||||
{
|
{
|
||||||
logger.LogInformation("Begin downloading for {Uri}", uri);
|
|
||||||
|
|
||||||
int retryCount = 0;
|
int retryCount = 0;
|
||||||
HttpClient httpClient = httpClientFactory.CreateClient(nameof(ImageCache));
|
HttpClient httpClient = httpClientFactory.CreateClient(nameof(ImageCache));
|
||||||
while (retryCount < 3)
|
while (retryCount < 3)
|
||||||
{
|
{
|
||||||
using (HttpResponseMessage message = await httpClient.GetAsync(uri, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false))
|
using (HttpResponseMessage message = await httpClient.GetAsync(uri, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
|
if (message.RequestMessage is { RequestUri: { } target } && target != uri)
|
||||||
|
{
|
||||||
|
logger.LogDebug("The Request '{Source}' has been redirected to '{Target}'", uri, target);
|
||||||
|
}
|
||||||
|
|
||||||
if (message.IsSuccessStatusCode)
|
if (message.IsSuccessStatusCode)
|
||||||
{
|
{
|
||||||
using (Stream httpStream = await message.Content.ReadAsStreamAsync().ConfigureAwait(false))
|
using (Stream httpStream = await message.Content.ReadAsStreamAsync().ConfigureAwait(false))
|
||||||
@@ -181,7 +197,7 @@ internal sealed partial class ImageCache : IImageCache, IImageCacheFilePathOpera
|
|||||||
{
|
{
|
||||||
retryCount++;
|
retryCount++;
|
||||||
TimeSpan delay = message.Headers.RetryAfter?.Delta ?? retryCountToDelay[retryCount];
|
TimeSpan delay = message.Headers.RetryAfter?.Delta ?? retryCountToDelay[retryCount];
|
||||||
logger.LogInformation("Retry {Uri} after {Delay}.", uri, delay);
|
logger.LogInformation("Retry download '{Uri}' after {Delay}.", uri, delay);
|
||||||
await Task.Delay(delay).ConfigureAwait(false);
|
await Task.Delay(delay).ConfigureAwait(false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -192,18 +208,4 @@ internal sealed partial class ImageCache : IImageCache, IImageCacheFilePathOpera
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetCacheFolder()
|
|
||||||
{
|
|
||||||
if (cacheFolder is not null)
|
|
||||||
{
|
|
||||||
return cacheFolder;
|
|
||||||
}
|
|
||||||
|
|
||||||
baseFolder ??= serviceProvider.GetRequiredService<RuntimeOptions>().LocalCache;
|
|
||||||
DirectoryInfo info = Directory.CreateDirectory(Path.Combine(baseFolder, CacheFolderName));
|
|
||||||
cacheFolder = info.FullName;
|
|
||||||
|
|
||||||
return cacheFolder;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -14,7 +14,7 @@ namespace Snap.Hutao.Core.Database;
|
|||||||
internal static class QueryableExtension
|
internal static class QueryableExtension
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// source.Where(predicate).ExecuteDelete()
|
/// <code>source.Where(predicate).ExecuteDelete()</code>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TSource">源类型</typeparam>
|
/// <typeparam name="TSource">源类型</typeparam>
|
||||||
/// <param name="source">源</param>
|
/// <param name="source">源</param>
|
||||||
@@ -27,7 +27,7 @@ internal static class QueryableExtension
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// source.Where(predicate).ExecuteDeleteAsync(token)
|
/// <code>source.Where(predicate).ExecuteDeleteAsync(token)</code>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TSource">源类型</typeparam>
|
/// <typeparam name="TSource">源类型</typeparam>
|
||||||
/// <param name="source">源</param>
|
/// <param name="source">源</param>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ namespace Snap.Hutao.Core.DependencyInjection.Abstraction;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 可转换类型服务
|
/// 可转换类型服务
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[Obsolete("Not useful anymore")]
|
||||||
internal interface ICastService
|
internal interface ICastService
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
// Copyright (c) DGP Studio. All rights reserved.
|
|
||||||
// Licensed under the MIT license.
|
|
||||||
|
|
||||||
namespace Snap.Hutao.Core.DependencyInjection.Abstraction;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 有名称的对象
|
|
||||||
/// 指示该对象可通过名称区分
|
|
||||||
/// </summary>
|
|
||||||
[Obsolete("无意义的接口")]
|
|
||||||
[HighQuality]
|
|
||||||
internal interface INamedService
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 名称
|
|
||||||
/// </summary>
|
|
||||||
string Name { get; }
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
// Copyright (c) DGP Studio. All rights reserved.
|
|
||||||
// Licensed under the MIT license.
|
|
||||||
|
|
||||||
namespace Snap.Hutao.Core.DependencyInjection.Abstraction;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 海外服/HoYoLAB 可区分
|
|
||||||
/// </summary>
|
|
||||||
[Obsolete("Use IOverseaSupportFactory instead")]
|
|
||||||
internal interface IOverseaSupport
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 是否为 海外服/HoYoLAB
|
|
||||||
/// </summary>
|
|
||||||
public bool IsOversea { get; }
|
|
||||||
}
|
|
||||||
@@ -17,6 +17,7 @@ internal static class CastServiceExtension
|
|||||||
/// <typeparam name="T">目标转换类型</typeparam>
|
/// <typeparam name="T">目标转换类型</typeparam>
|
||||||
/// <param name="service">对象</param>
|
/// <param name="service">对象</param>
|
||||||
/// <returns>转换类型后的对象</returns>
|
/// <returns>转换类型后的对象</returns>
|
||||||
|
[Obsolete("Not useful anymore")]
|
||||||
public static T? As<T>(this ICastService service)
|
public static T? As<T>(this ICastService service)
|
||||||
where T : class
|
where T : class
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -51,8 +51,13 @@ internal static class DependencyInjection
|
|||||||
CultureOptions cultureOptions = serviceProvider.GetRequiredService<CultureOptions>();
|
CultureOptions cultureOptions = serviceProvider.GetRequiredService<CultureOptions>();
|
||||||
cultureOptions.SystemCulture = CultureInfo.CurrentCulture;
|
cultureOptions.SystemCulture = CultureInfo.CurrentCulture;
|
||||||
|
|
||||||
|
ILogger<CultureOptions> logger = serviceProvider.GetRequiredService<ILogger<CultureOptions>>();
|
||||||
|
logger.LogDebug("System Culture: {System}", cultureOptions.SystemCulture);
|
||||||
|
|
||||||
CultureInfo cultureInfo = cultureOptions.CurrentCulture;
|
CultureInfo cultureInfo = cultureOptions.CurrentCulture;
|
||||||
|
|
||||||
|
logger.LogDebug("Current Culture: {Current}", cultureInfo);
|
||||||
|
|
||||||
CultureInfo.DefaultThreadCurrentCulture = cultureInfo;
|
CultureInfo.DefaultThreadCurrentCulture = cultureInfo;
|
||||||
CultureInfo.DefaultThreadCurrentUICulture = cultureInfo;
|
CultureInfo.DefaultThreadCurrentUICulture = cultureInfo;
|
||||||
CultureInfo.CurrentCulture = cultureInfo;
|
CultureInfo.CurrentCulture = cultureInfo;
|
||||||
@@ -63,6 +68,7 @@ internal static class DependencyInjection
|
|||||||
SH.Culture = cultureInfo;
|
SH.Culture = cultureInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static void InitializeConsoleWindow(this IServiceProvider serviceProvider)
|
private static void InitializeConsoleWindow(this IServiceProvider serviceProvider)
|
||||||
{
|
{
|
||||||
_ = serviceProvider.GetRequiredService<ConsoleWindowLifeTime>();
|
_ = serviceProvider.GetRequiredService<ConsoleWindowLifeTime>();
|
||||||
|
|||||||
@@ -47,17 +47,13 @@ internal static class IocConfiguration
|
|||||||
{
|
{
|
||||||
if (context.Database.GetPendingMigrations().Any())
|
if (context.Database.GetPendingMigrations().Any())
|
||||||
{
|
{
|
||||||
#if DEBUG
|
|
||||||
System.Diagnostics.Debug.WriteLine("[Database] Performing AppDbContext Migrations");
|
System.Diagnostics.Debug.WriteLine("[Database] Performing AppDbContext Migrations");
|
||||||
#endif
|
|
||||||
context.Database.Migrate();
|
context.Database.Migrate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
builder
|
builder
|
||||||
#if DEBUG
|
|
||||||
.EnableSensitiveDataLogging()
|
.EnableSensitiveDataLogging()
|
||||||
#endif
|
|
||||||
.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking)
|
.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking)
|
||||||
.UseSqlite(sqlConnectionString);
|
.UseSqlite(sqlConnectionString);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,6 @@ internal readonly struct MeasureExecutionToken : IDisposable
|
|||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
logger.LogInformation("{Caller} toke {Time} ms", callerName, stopwatch.GetElapsedTime().TotalMilliseconds);
|
logger.LogDebug("{Caller} toke {Time} ms", callerName, stopwatch.GetElapsedTime().TotalMilliseconds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7,6 +7,7 @@ namespace Snap.Hutao.Core.ExceptionService;
|
|||||||
/// 数据库损坏异常
|
/// 数据库损坏异常
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[HighQuality]
|
[HighQuality]
|
||||||
|
[Obsolete("Use HutaoException instead")]
|
||||||
internal sealed class DatabaseCorruptedException : Exception
|
internal sealed class DatabaseCorruptedException : Exception
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ namespace Snap.Hutao.Core.ExceptionService;
|
|||||||
/// 用户的计算机中的某些设置不符合要求
|
/// 用户的计算机中的某些设置不符合要求
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[HighQuality]
|
[HighQuality]
|
||||||
|
[Obsolete("Use HutaoException instead")]
|
||||||
internal sealed class RuntimeEnvironmentException : Exception
|
internal sealed class RuntimeEnvironmentException : Exception
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ namespace Snap.Hutao.Core.ExceptionService;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[HighQuality]
|
[HighQuality]
|
||||||
[System.Diagnostics.StackTraceHidden]
|
[System.Diagnostics.StackTraceHidden]
|
||||||
|
[Obsolete("Use HutaoException instead")]
|
||||||
internal static class ThrowHelper
|
internal static class ThrowHelper
|
||||||
{
|
{
|
||||||
[DoesNotReturn]
|
[DoesNotReturn]
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ namespace Snap.Hutao.Core.ExceptionService;
|
|||||||
/// 用户数据损坏异常
|
/// 用户数据损坏异常
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[HighQuality]
|
[HighQuality]
|
||||||
|
[Obsolete("Use HutaoException instead")]
|
||||||
internal sealed class UserdataCorruptedException : Exception
|
internal sealed class UserdataCorruptedException : Exception
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -29,17 +29,19 @@ internal sealed unsafe class LoopbackManager : ObservableObject
|
|||||||
INET_FIREWALL_APP_CONTAINER* pContainers = default;
|
INET_FIREWALL_APP_CONTAINER* pContainers = default;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
WIN32_ERROR error = NetworkIsolationEnumAppContainers(NETISO_FLAG.NETISO_FLAG_MAX, out uint acCount, out pContainers);
|
|
||||||
Marshal.ThrowExceptionForHR(HRESULT_FROM_WIN32(error));
|
|
||||||
for (uint i = 0; i < acCount; i++)
|
|
||||||
{
|
{
|
||||||
INET_FIREWALL_APP_CONTAINER* pContainer = pContainers + i;
|
WIN32_ERROR error = NetworkIsolationEnumAppContainers(NETISO_FLAG.NETISO_FLAG_MAX, out uint acCount, out pContainers);
|
||||||
ReadOnlySpan<char> appContainerName = MemoryMarshal.CreateReadOnlySpanFromNullTerminated(pContainer->appContainerName);
|
Marshal.ThrowExceptionForHR(HRESULT_FROM_WIN32(error));
|
||||||
if (appContainerName.Equals(runtimeOptions.FamilyName, StringComparison.Ordinal))
|
for (uint i = 0; i < acCount; i++)
|
||||||
{
|
{
|
||||||
ConvertSidToStringSidW(pContainer->appContainerSid, out PWSTR stringSid);
|
INET_FIREWALL_APP_CONTAINER* pContainer = pContainers + i;
|
||||||
hutaoContainerStringSID = MemoryMarshal.CreateReadOnlySpanFromNullTerminated(stringSid).ToString();
|
ReadOnlySpan<char> appContainerName = MemoryMarshal.CreateReadOnlySpanFromNullTerminated(pContainer->appContainerName);
|
||||||
break;
|
if (appContainerName.Equals(runtimeOptions.FamilyName, StringComparison.Ordinal))
|
||||||
|
{
|
||||||
|
ConvertSidToStringSidW(pContainer->appContainerSid, out PWSTR stringSid);
|
||||||
|
hutaoContainerStringSID = MemoryMarshal.CreateReadOnlySpanFromNullTerminated(stringSid).ToString();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -49,16 +51,18 @@ internal sealed unsafe class LoopbackManager : ObservableObject
|
|||||||
_ = NetworkIsolationFreeAppContainers(pContainers);
|
_ = NetworkIsolationFreeAppContainers(pContainers);
|
||||||
}
|
}
|
||||||
|
|
||||||
WIN32_ERROR error2 = NetworkIsolationGetAppContainerConfig(out uint accCount, out SID_AND_ATTRIBUTES* pSids);
|
|
||||||
Marshal.ThrowExceptionForHR(HRESULT_FROM_WIN32(error2));
|
|
||||||
for (uint i = 0; i < accCount; i++)
|
|
||||||
{
|
{
|
||||||
ConvertSidToStringSidW((pSids + i)->Sid, out PWSTR stringSid);
|
WIN32_ERROR error = NetworkIsolationGetAppContainerConfig(out uint accCount, out SID_AND_ATTRIBUTES* pSids);
|
||||||
ReadOnlySpan<char> stringSidSpan = MemoryMarshal.CreateReadOnlySpanFromNullTerminated(stringSid);
|
Marshal.ThrowExceptionForHR(HRESULT_FROM_WIN32(error));
|
||||||
if (stringSidSpan.Equals(hutaoContainerStringSID, StringComparison.Ordinal))
|
for (uint i = 0; i < accCount; i++)
|
||||||
{
|
{
|
||||||
IsLoopbackEnabled = true;
|
ConvertSidToStringSidW((pSids + i)->Sid, out PWSTR stringSid);
|
||||||
break;
|
ReadOnlySpan<char> stringSidSpan = MemoryMarshal.CreateReadOnlySpanFromNullTerminated(stringSid);
|
||||||
|
if (stringSidSpan.Equals(hutaoContainerStringSID, StringComparison.Ordinal))
|
||||||
|
{
|
||||||
|
IsLoopbackEnabled = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
627
src/Snap.Hutao/Snap.Hutao/Migrations/20240219020258_AddPerferredUidOnUser.Designer.cs
generated
Normal file
627
src/Snap.Hutao/Snap.Hutao/Migrations/20240219020258_AddPerferredUidOnUser.Designer.cs
generated
Normal file
@@ -0,0 +1,627 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Snap.Hutao.Model.Entity.Database;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Snap.Hutao.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(AppDbContext))]
|
||||||
|
[Migration("20240219020258_AddPerferredUidOnUser")]
|
||||||
|
partial class AddPerferredUidOnUser
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder.HasAnnotation("ProductVersion", "8.0.2");
|
||||||
|
|
||||||
|
modelBuilder.Entity("Snap.Hutao.Model.Entity.Achievement", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("InnerId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<Guid>("ArchiveId")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<uint>("Current")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<uint>("Id")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<int>("Status")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset>("Time")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.HasKey("InnerId");
|
||||||
|
|
||||||
|
b.HasIndex("ArchiveId");
|
||||||
|
|
||||||
|
b.ToTable("achievements");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Snap.Hutao.Model.Entity.AchievementArchive", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("InnerId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<bool>("IsSelected")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.HasKey("InnerId");
|
||||||
|
|
||||||
|
b.ToTable("achievement_archives");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Snap.Hutao.Model.Entity.AvatarInfo", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("InnerId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset>("CalculatorRefreshTime")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset>("GameRecordRefreshTime")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("Info")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset>("ShowcaseRefreshTime")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("Uid")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.HasKey("InnerId");
|
||||||
|
|
||||||
|
b.ToTable("avatar_infos");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Snap.Hutao.Model.Entity.CultivateEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("InnerId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<uint>("Id")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<Guid>("ProjectId")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<int>("Type")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.HasKey("InnerId");
|
||||||
|
|
||||||
|
b.HasIndex("ProjectId");
|
||||||
|
|
||||||
|
b.ToTable("cultivate_entries");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Snap.Hutao.Model.Entity.CultivateEntryLevelInformation", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("InnerId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<uint>("AvatarLevelFrom")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<uint>("AvatarLevelTo")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<Guid>("EntryId")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<uint>("SkillALevelFrom")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<uint>("SkillALevelTo")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<uint>("SkillELevelFrom")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<uint>("SkillELevelTo")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<uint>("SkillQLevelFrom")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<uint>("SkillQLevelTo")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<uint>("WeaponLevelFrom")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<uint>("WeaponLevelTo")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.HasKey("InnerId");
|
||||||
|
|
||||||
|
b.HasIndex("EntryId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("cultivate_entry_level_informations");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Snap.Hutao.Model.Entity.CultivateItem", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("InnerId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<uint>("Count")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<Guid>("EntryId")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<bool>("IsFinished")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<uint>("ItemId")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.HasKey("InnerId");
|
||||||
|
|
||||||
|
b.HasIndex("EntryId");
|
||||||
|
|
||||||
|
b.ToTable("cultivate_items");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Snap.Hutao.Model.Entity.CultivateProject", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("InnerId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("AttachedUid")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<bool>("IsSelected")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.HasKey("InnerId");
|
||||||
|
|
||||||
|
b.ToTable("cultivate_projects");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Snap.Hutao.Model.Entity.DailyNoteEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("InnerId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("DailyNote")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<bool>("DailyTaskNotify")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<bool>("DailyTaskNotifySuppressed")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<bool>("ExpeditionNotify")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<bool>("ExpeditionNotifySuppressed")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<bool>("HomeCoinNotifySuppressed")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<int>("HomeCoinNotifyThreshold")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset>("RefreshTime")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<bool>("ResinNotifySuppressed")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<int>("ResinNotifyThreshold")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<bool>("TransformerNotify")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<bool>("TransformerNotifySuppressed")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<string>("Uid")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<Guid>("UserId")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.HasKey("InnerId");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("daily_notes");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Snap.Hutao.Model.Entity.GachaArchive", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("InnerId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<bool>("IsSelected")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<string>("Uid")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.HasKey("InnerId");
|
||||||
|
|
||||||
|
b.ToTable("gacha_archives");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Snap.Hutao.Model.Entity.GachaItem", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("InnerId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<Guid>("ArchiveId")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<int>("GachaType")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<long>("Id")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<uint>("ItemId")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<int>("QueryType")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset>("Time")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.HasKey("InnerId");
|
||||||
|
|
||||||
|
b.HasIndex("ArchiveId");
|
||||||
|
|
||||||
|
b.ToTable("gacha_items");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Snap.Hutao.Model.Entity.GameAccount", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("InnerId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("AttachUid")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<int>("Index")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<string>("MihoyoSDK")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<int>("Type")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.HasKey("InnerId");
|
||||||
|
|
||||||
|
b.ToTable("game_accounts");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Snap.Hutao.Model.Entity.InventoryItem", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("InnerId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<uint>("Count")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<uint>("ItemId")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<Guid>("ProjectId")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.HasKey("InnerId");
|
||||||
|
|
||||||
|
b.HasIndex("ProjectId");
|
||||||
|
|
||||||
|
b.ToTable("inventory_items");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Snap.Hutao.Model.Entity.InventoryReliquary", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("InnerId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("AppendPropIdList")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<int>("ItemId")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<int>("Level")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<int>("MainPropId")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<Guid>("ProjectId")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.HasKey("InnerId");
|
||||||
|
|
||||||
|
b.HasIndex("ProjectId");
|
||||||
|
|
||||||
|
b.ToTable("inventory_reliquaries");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Snap.Hutao.Model.Entity.InventoryWeapon", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("InnerId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<int>("ItemId")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<int>("Level")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<Guid>("ProjectId")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<int>("PromoteLevel")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.HasKey("InnerId");
|
||||||
|
|
||||||
|
b.HasIndex("ProjectId");
|
||||||
|
|
||||||
|
b.ToTable("inventory_weapons");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Snap.Hutao.Model.Entity.ObjectCacheEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Key")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset>("ExpireTime")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("Value")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.HasKey("Key");
|
||||||
|
|
||||||
|
b.ToTable("object_cache");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Snap.Hutao.Model.Entity.SettingEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Key")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("Value")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.HasKey("Key");
|
||||||
|
|
||||||
|
b.ToTable("settings");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Snap.Hutao.Model.Entity.SpiralAbyssEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("InnerId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<uint>("ScheduleId")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<string>("SpiralAbyss")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("Uid")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.HasKey("InnerId");
|
||||||
|
|
||||||
|
b.ToTable("spiral_abysses");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Snap.Hutao.Model.Entity.User", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("InnerId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("Aid")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("CookieToken")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset>("CookieTokenLastUpdateTime")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("Fingerprint")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset>("FingerprintLastUpdateTime")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<int>("Index")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<bool>("IsOversea")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<bool>("IsSelected")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<string>("LToken")
|
||||||
|
.HasColumnType("TEXT")
|
||||||
|
.HasColumnName("Ltoken");
|
||||||
|
|
||||||
|
b.Property<string>("Mid")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("PreferredUid")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("SToken")
|
||||||
|
.HasColumnType("TEXT")
|
||||||
|
.HasColumnName("Stoken");
|
||||||
|
|
||||||
|
b.HasKey("InnerId");
|
||||||
|
|
||||||
|
b.ToTable("users");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Snap.Hutao.Model.Entity.Achievement", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Snap.Hutao.Model.Entity.AchievementArchive", "Archive")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ArchiveId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Archive");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Snap.Hutao.Model.Entity.CultivateEntry", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Snap.Hutao.Model.Entity.CultivateProject", "Project")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ProjectId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Project");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Snap.Hutao.Model.Entity.CultivateEntryLevelInformation", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Snap.Hutao.Model.Entity.CultivateEntry", "Entry")
|
||||||
|
.WithOne("LevelInformation")
|
||||||
|
.HasForeignKey("Snap.Hutao.Model.Entity.CultivateEntryLevelInformation", "EntryId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Entry");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Snap.Hutao.Model.Entity.CultivateItem", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Snap.Hutao.Model.Entity.CultivateEntry", "Entry")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("EntryId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Entry");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Snap.Hutao.Model.Entity.DailyNoteEntry", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Snap.Hutao.Model.Entity.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Snap.Hutao.Model.Entity.GachaItem", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Snap.Hutao.Model.Entity.GachaArchive", "Archive")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ArchiveId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Archive");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Snap.Hutao.Model.Entity.InventoryItem", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Snap.Hutao.Model.Entity.CultivateProject", "Project")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ProjectId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Project");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Snap.Hutao.Model.Entity.InventoryReliquary", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Snap.Hutao.Model.Entity.CultivateProject", "Project")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ProjectId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Project");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Snap.Hutao.Model.Entity.InventoryWeapon", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Snap.Hutao.Model.Entity.CultivateProject", "Project")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ProjectId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Project");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Snap.Hutao.Model.Entity.CultivateEntry", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("LevelInformation");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Snap.Hutao.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class AddPerferredUidOnUser : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "PreferredUid",
|
||||||
|
table: "users",
|
||||||
|
type: "TEXT",
|
||||||
|
nullable: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "PreferredUid",
|
||||||
|
table: "users");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,7 +15,7 @@ namespace Snap.Hutao.Migrations
|
|||||||
protected override void BuildModel(ModelBuilder modelBuilder)
|
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||||
{
|
{
|
||||||
#pragma warning disable 612, 618
|
#pragma warning disable 612, 618
|
||||||
modelBuilder.HasAnnotation("ProductVersion", "8.0.1");
|
modelBuilder.HasAnnotation("ProductVersion", "8.0.2");
|
||||||
|
|
||||||
modelBuilder.Entity("Snap.Hutao.Model.Entity.Achievement", b =>
|
modelBuilder.Entity("Snap.Hutao.Model.Entity.Achievement", b =>
|
||||||
{
|
{
|
||||||
@@ -503,6 +503,9 @@ namespace Snap.Hutao.Migrations
|
|||||||
b.Property<string>("Mid")
|
b.Property<string>("Mid")
|
||||||
.HasColumnType("TEXT");
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("PreferredUid")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
b.Property<string>("SToken")
|
b.Property<string>("SToken")
|
||||||
.HasColumnType("TEXT")
|
.HasColumnType("TEXT")
|
||||||
.HasColumnName("Stoken");
|
.HasColumnName("Stoken");
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ internal sealed partial class SettingEntry
|
|||||||
public const string Culture = "Culture";
|
public const string Culture = "Culture";
|
||||||
|
|
||||||
public const string SystemBackdropType = "SystemBackdropType";
|
public const string SystemBackdropType = "SystemBackdropType";
|
||||||
|
public const string BackgroundImageType = "BackgroundImageType";
|
||||||
|
|
||||||
public const string AnnouncementRegion = "AnnouncementRegion";
|
public const string AnnouncementRegion = "AnnouncementRegion";
|
||||||
|
|
||||||
@@ -42,6 +43,7 @@ internal sealed partial class SettingEntry
|
|||||||
public const string LaunchIsUseCloudThirdPartyMobile = "Launch.IsUseCloudThirdPartyMobile";
|
public const string LaunchIsUseCloudThirdPartyMobile = "Launch.IsUseCloudThirdPartyMobile";
|
||||||
public const string LaunchIsWindowsHDREnabled = "Launch.IsWindowsHDREnabled";
|
public const string LaunchIsWindowsHDREnabled = "Launch.IsWindowsHDREnabled";
|
||||||
public const string LaunchUseStarwardPlayTimeStatistics = "Launch.UseStarwardPlayTimeStatistics";
|
public const string LaunchUseStarwardPlayTimeStatistics = "Launch.UseStarwardPlayTimeStatistics";
|
||||||
|
public const string LaunchUseBetterGenshinImpactAutomation = "Launch.UseBetterGenshinImpactAutomation";
|
||||||
public const string LaunchSetDiscordActivityWhenPlaying = "Launch.SetDiscordActivityWhenPlaying";
|
public const string LaunchSetDiscordActivityWhenPlaying = "Launch.SetDiscordActivityWhenPlaying";
|
||||||
|
|
||||||
[Obsolete("不再支持多开")]
|
[Obsolete("不再支持多开")]
|
||||||
@@ -49,4 +51,4 @@ internal sealed partial class SettingEntry
|
|||||||
|
|
||||||
[Obsolete("不再使用 PowerShell")]
|
[Obsolete("不再使用 PowerShell")]
|
||||||
public const string PowerShellPath = "PowerShellPath";
|
public const string PowerShellPath = "PowerShellPath";
|
||||||
}
|
}
|
||||||
@@ -71,6 +71,8 @@ internal sealed class User : ISelectable, IReorderable, IMappingFrom<User, Cooki
|
|||||||
|
|
||||||
public int Index { get; set; }
|
public int Index { get; set; }
|
||||||
|
|
||||||
|
public string? PreferredUid { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 创建一个新的用户
|
/// 创建一个新的用户
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -824,6 +824,9 @@
|
|||||||
<data name="ServiceDailyNoteNotifierTransformerHint" xml:space="preserve">
|
<data name="ServiceDailyNoteNotifierTransformerHint" xml:space="preserve">
|
||||||
<value>参量质变仪已准备完成</value>
|
<value>参量质变仪已准备完成</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ServiceDiscordActivityElevationRequiredHint" xml:space="preserve">
|
||||||
|
<value>权限不足,将无法为您设置 Discord Activity 状态</value>
|
||||||
|
</data>
|
||||||
<data name="ServiceDiscordGameActivityDetails" xml:space="preserve">
|
<data name="ServiceDiscordGameActivityDetails" xml:space="preserve">
|
||||||
<value>正在提瓦特大陆中探索</value>
|
<value>正在提瓦特大陆中探索</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -2189,6 +2192,12 @@
|
|||||||
<data name="ViewPageLaunchGameArgumentsHeader" xml:space="preserve">
|
<data name="ViewPageLaunchGameArgumentsHeader" xml:space="preserve">
|
||||||
<value>启动参数</value>
|
<value>启动参数</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ViewPageLaunchGameBetterGIDescription" xml:space="preserve">
|
||||||
|
<value>在游戏启动后尝试启动并使用 Better GI 进行自动化任务</value>
|
||||||
|
</data>
|
||||||
|
<data name="ViewPageLaunchGameBetterGIHeader" xml:space="preserve">
|
||||||
|
<value>Better GI</value>
|
||||||
|
</data>
|
||||||
<data name="ViewPageLaunchGameCommonHeader" xml:space="preserve">
|
<data name="ViewPageLaunchGameCommonHeader" xml:space="preserve">
|
||||||
<value>常规</value>
|
<value>常规</value>
|
||||||
</data>
|
</data>
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using Snap.Hutao.Core.Windowing;
|
|||||||
using Snap.Hutao.Model;
|
using Snap.Hutao.Model;
|
||||||
using Snap.Hutao.Model.Entity;
|
using Snap.Hutao.Model.Entity;
|
||||||
using Snap.Hutao.Service.Abstraction;
|
using Snap.Hutao.Service.Abstraction;
|
||||||
|
using Snap.Hutao.Service.BackgroundImage;
|
||||||
using Snap.Hutao.Web.Hoyolab;
|
using Snap.Hutao.Web.Hoyolab;
|
||||||
|
|
||||||
namespace Snap.Hutao.Service;
|
namespace Snap.Hutao.Service;
|
||||||
@@ -15,6 +16,7 @@ internal sealed partial class AppOptions : DbStoreOptions
|
|||||||
{
|
{
|
||||||
private bool? isEmptyHistoryWishVisible;
|
private bool? isEmptyHistoryWishVisible;
|
||||||
private BackdropType? backdropType;
|
private BackdropType? backdropType;
|
||||||
|
private BackgroundImageType? backgroundImageType;
|
||||||
private Region? region;
|
private Region? region;
|
||||||
private string? geetestCustomCompositeUrl;
|
private string? geetestCustomCompositeUrl;
|
||||||
|
|
||||||
@@ -28,8 +30,14 @@ internal sealed partial class AppOptions : DbStoreOptions
|
|||||||
|
|
||||||
public BackdropType BackdropType
|
public BackdropType BackdropType
|
||||||
{
|
{
|
||||||
get => GetOption(ref backdropType, SettingEntry.SystemBackdropType, v => Enum.Parse<BackdropType>(v), BackdropType.Mica).Value;
|
get => GetOption(ref backdropType, SettingEntry.SystemBackdropType, EnumParse<BackdropType>, BackdropType.Mica).Value;
|
||||||
set => SetOption(ref backdropType, SettingEntry.SystemBackdropType, value, value => value.ToStringOrEmpty());
|
set => SetOption(ref backdropType, SettingEntry.SystemBackdropType, value, EnumToStringOrEmpty);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BackgroundImageType BackgroundImageType
|
||||||
|
{
|
||||||
|
get => GetOption(ref backgroundImageType, SettingEntry.BackgroundImageType, EnumParse<BackgroundImageType>, BackgroundImageType.HutaoOfficialLauncher).Value;
|
||||||
|
set => SetOption(ref backgroundImageType, SettingEntry.BackgroundImageType, value, EnumToStringOrEmpty);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Lazy<List<NameValue<Region>>> LazyRegions { get; } = new(KnownRegions.Get);
|
public Lazy<List<NameValue<Region>>> LazyRegions { get; } = new(KnownRegions.Get);
|
||||||
@@ -45,4 +53,16 @@ internal sealed partial class AppOptions : DbStoreOptions
|
|||||||
get => GetOption(ref geetestCustomCompositeUrl, SettingEntry.GeetestCustomCompositeUrl);
|
get => GetOption(ref geetestCustomCompositeUrl, SettingEntry.GeetestCustomCompositeUrl);
|
||||||
set => SetOption(ref geetestCustomCompositeUrl, SettingEntry.GeetestCustomCompositeUrl, value);
|
set => SetOption(ref geetestCustomCompositeUrl, SettingEntry.GeetestCustomCompositeUrl, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static T? EnumParse<T>(string input)
|
||||||
|
where T : struct, Enum
|
||||||
|
{
|
||||||
|
return Enum.Parse<T>(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string EnumToStringOrEmpty<T>(T? input)
|
||||||
|
where T : struct, Enum
|
||||||
|
{
|
||||||
|
return input.ToStringOrEmpty();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -13,6 +13,8 @@ namespace Snap.Hutao.Service.BackgroundImage;
|
|||||||
|
|
||||||
internal sealed class BackgroundImage
|
internal sealed class BackgroundImage
|
||||||
{
|
{
|
||||||
|
public string Path { get; set; } = default!;
|
||||||
|
|
||||||
public BitmapImage ImageSource { get; set; } = default!;
|
public BitmapImage ImageSource { get; set; } = default!;
|
||||||
|
|
||||||
public Color AccentColor { get; set; }
|
public Color AccentColor { get; set; }
|
||||||
|
|||||||
@@ -38,8 +38,7 @@ internal sealed partial class BackgroundImageService : IBackgroundImageService
|
|||||||
string path = System.Random.Shared.GetItems(backgroundSet.ToArray(), 1)[0];
|
string path = System.Random.Shared.GetItems(backgroundSet.ToArray(), 1)[0];
|
||||||
backgroundSet.Remove(path);
|
backgroundSet.Remove(path);
|
||||||
|
|
||||||
await taskContext.SwitchToMainThreadAsync();
|
if (string.Equals(path, previous?.Path, StringComparison.OrdinalIgnoreCase))
|
||||||
if (string.Equals(path, previous?.ImageSource.UriSource.ToString(), StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
{
|
||||||
return new(false, default!);
|
return new(false, default!);
|
||||||
}
|
}
|
||||||
@@ -54,6 +53,7 @@ internal sealed partial class BackgroundImageService : IBackgroundImageService
|
|||||||
|
|
||||||
BackgroundImage background = new()
|
BackgroundImage background = new()
|
||||||
{
|
{
|
||||||
|
Path = path,
|
||||||
ImageSource = new(path.ToUri()),
|
ImageSource = new(path.ToUri()),
|
||||||
AccentColor = accentColor,
|
AccentColor = accentColor,
|
||||||
Luminance = accentColor.Luminance,
|
Luminance = accentColor.Luminance,
|
||||||
@@ -65,7 +65,7 @@ internal sealed partial class BackgroundImageService : IBackgroundImageService
|
|||||||
|
|
||||||
private async ValueTask<HashSet<string>> SkipOrInitBackgroundAsync()
|
private async ValueTask<HashSet<string>> SkipOrInitBackgroundAsync()
|
||||||
{
|
{
|
||||||
if (backgroundPathSet is null || backgroundPathSet.Count <= 0)
|
if (backgroundPathSet is not { Count: > 0 })
|
||||||
{
|
{
|
||||||
string backgroundFolder = runtimeOptions.GetDataFolderBackgroundFolder();
|
string backgroundFolder = runtimeOptions.GetDataFolderBackgroundFolder();
|
||||||
Directory.CreateDirectory(backgroundFolder);
|
Directory.CreateDirectory(backgroundFolder);
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
namespace Snap.Hutao.Service.BackgroundImage;
|
||||||
|
|
||||||
|
internal enum BackgroundImageType
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
LocalFolder,
|
||||||
|
HutaoBing,
|
||||||
|
HutaoDaily,
|
||||||
|
HutaoOfficialLauncher,
|
||||||
|
}
|
||||||
@@ -7,7 +7,7 @@ using Snap.Hutao.Model.Entity;
|
|||||||
using Snap.Hutao.Model.Entity.Database;
|
using Snap.Hutao.Model.Entity.Database;
|
||||||
using Snap.Hutao.Model.Entity.Primitive;
|
using Snap.Hutao.Model.Entity.Primitive;
|
||||||
using Snap.Hutao.Model.Metadata.Item;
|
using Snap.Hutao.Model.Metadata.Item;
|
||||||
using Snap.Hutao.Service.Inventroy;
|
using Snap.Hutao.Service.Inventory;
|
||||||
using Snap.Hutao.Service.Metadata.ContextAbstraction;
|
using Snap.Hutao.Service.Metadata.ContextAbstraction;
|
||||||
using Snap.Hutao.ViewModel.Cultivation;
|
using Snap.Hutao.ViewModel.Cultivation;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
|
|||||||
@@ -132,13 +132,6 @@ internal static class DiscordController
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actually requires a discord client to be running on Windows platform.
|
|
||||||
// If not, the following creation code will throw.
|
|
||||||
if (System.Diagnostics.Process.GetProcessesByName("Discord").Length <= 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
lock (SyncRoot)
|
lock (SyncRoot)
|
||||||
{
|
{
|
||||||
DiscordCreateParams @params = default;
|
DiscordCreateParams @params = default;
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
// Licensed under the MIT license.
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
using Snap.Hutao.Core;
|
using Snap.Hutao.Core;
|
||||||
|
using Snap.Hutao.Service.Notification;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace Snap.Hutao.Service.Discord;
|
namespace Snap.Hutao.Service.Discord;
|
||||||
|
|
||||||
@@ -9,22 +11,69 @@ namespace Snap.Hutao.Service.Discord;
|
|||||||
[Injection(InjectAs.Singleton, typeof(IDiscordService))]
|
[Injection(InjectAs.Singleton, typeof(IDiscordService))]
|
||||||
internal sealed partial class DiscordService : IDiscordService, IDisposable
|
internal sealed partial class DiscordService : IDiscordService, IDisposable
|
||||||
{
|
{
|
||||||
|
private readonly IInfoBarService infoBarService;
|
||||||
private readonly RuntimeOptions runtimeOptions;
|
private readonly RuntimeOptions runtimeOptions;
|
||||||
|
|
||||||
|
private bool isInitialized;
|
||||||
|
|
||||||
public async ValueTask SetPlayingActivityAsync(bool isOversea)
|
public async ValueTask SetPlayingActivityAsync(bool isOversea)
|
||||||
{
|
{
|
||||||
_ = isOversea
|
if (IsSupported())
|
||||||
? await DiscordController.SetPlayingGenshinImpactAsync().ConfigureAwait(false)
|
{
|
||||||
: await DiscordController.SetPlayingYuanShenAsync().ConfigureAwait(false);
|
_ = isOversea
|
||||||
|
? await DiscordController.SetPlayingGenshinImpactAsync().ConfigureAwait(false)
|
||||||
|
: await DiscordController.SetPlayingYuanShenAsync().ConfigureAwait(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async ValueTask SetNormalActivityAsync()
|
public async ValueTask SetNormalActivityAsync()
|
||||||
{
|
{
|
||||||
_ = await DiscordController.SetDefaultActivityAsync(runtimeOptions.AppLaunchTime).ConfigureAwait(false);
|
if (IsSupported())
|
||||||
|
{
|
||||||
|
_ = await DiscordController.SetDefaultActivityAsync(runtimeOptions.AppLaunchTime).ConfigureAwait(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
DiscordController.Stop();
|
DiscordController.Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool IsSupported()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Actually requires a discord client to be running on Windows platform.
|
||||||
|
// If not, discord core creation code will throw.
|
||||||
|
Process[] discordProcesses = Process.GetProcessesByName("Discord");
|
||||||
|
|
||||||
|
if (discordProcesses.Length <= 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (Process process in discordProcesses)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_ = process.Handle;
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
if (!isInitialized)
|
||||||
|
{
|
||||||
|
infoBarService.Warning(SH.ServiceDiscordActivityElevationRequiredHint);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
isInitialized = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -45,6 +45,7 @@ internal sealed class LaunchOptions : DbStoreOptions
|
|||||||
private bool? isWindowsHDREnabled;
|
private bool? isWindowsHDREnabled;
|
||||||
private AspectRatio? selectedAspectRatio;
|
private AspectRatio? selectedAspectRatio;
|
||||||
private bool? useStarwardPlayTimeStatistics;
|
private bool? useStarwardPlayTimeStatistics;
|
||||||
|
private bool? useBetterGenshinImpactAutomation;
|
||||||
private bool? setDiscordActivityWhenPlaying;
|
private bool? setDiscordActivityWhenPlaying;
|
||||||
|
|
||||||
public LaunchOptions(IServiceProvider serviceProvider)
|
public LaunchOptions(IServiceProvider serviceProvider)
|
||||||
@@ -219,7 +220,7 @@ internal sealed class LaunchOptions : DbStoreOptions
|
|||||||
get => selectedAspectRatio;
|
get => selectedAspectRatio;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (SetProperty(ref selectedAspectRatio, value) && value is AspectRatio aspectRatio)
|
if (SetProperty(ref selectedAspectRatio, value) && value is { } aspectRatio)
|
||||||
{
|
{
|
||||||
(ScreenWidth, ScreenHeight) = ((int)aspectRatio.Width, (int)aspectRatio.Height);
|
(ScreenWidth, ScreenHeight) = ((int)aspectRatio.Width, (int)aspectRatio.Height);
|
||||||
}
|
}
|
||||||
@@ -232,6 +233,12 @@ internal sealed class LaunchOptions : DbStoreOptions
|
|||||||
set => SetOption(ref useStarwardPlayTimeStatistics, SettingEntry.LaunchUseStarwardPlayTimeStatistics, value);
|
set => SetOption(ref useStarwardPlayTimeStatistics, SettingEntry.LaunchUseStarwardPlayTimeStatistics, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool UseBetterGenshinImpactAutomation
|
||||||
|
{
|
||||||
|
get => GetOption(ref useBetterGenshinImpactAutomation, SettingEntry.LaunchUseBetterGenshinImpactAutomation, false);
|
||||||
|
set => SetOption(ref useBetterGenshinImpactAutomation, SettingEntry.LaunchUseBetterGenshinImpactAutomation, value);
|
||||||
|
}
|
||||||
|
|
||||||
public bool SetDiscordActivityWhenPlaying
|
public bool SetDiscordActivityWhenPlaying
|
||||||
{
|
{
|
||||||
get => GetOption(ref setDiscordActivityWhenPlaying, SettingEntry.LaunchSetDiscordActivityWhenPlaying, true);
|
get => GetOption(ref setDiscordActivityWhenPlaying, SettingEntry.LaunchSetDiscordActivityWhenPlaying, true);
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
using Windows.System;
|
||||||
|
|
||||||
|
namespace Snap.Hutao.Service.Game.Launching.Handler;
|
||||||
|
|
||||||
|
internal sealed class LaunchExecutionBetterGenshinImpactAutomationHandlder : ILaunchExecutionDelegateHandler
|
||||||
|
{
|
||||||
|
public async ValueTask OnExecutionAsync(LaunchExecutionContext context, LaunchExecutionDelegate next)
|
||||||
|
{
|
||||||
|
if (context.Options.UseBetterGenshinImpactAutomation)
|
||||||
|
{
|
||||||
|
context.Logger.LogInformation("Using BetterGI to automate gameplay");
|
||||||
|
await LaunchBetterGenshinImpactAsync(context).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
await next().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async ValueTask LaunchBetterGenshinImpactAsync(LaunchExecutionContext context)
|
||||||
|
{
|
||||||
|
Uri betterGenshinImpactUri = "bettergi://start".ToUri();
|
||||||
|
if (await Launcher.QueryUriSupportAsync(betterGenshinImpactUri, LaunchQuerySupportType.Uri) is LaunchQuerySupportStatus.Available)
|
||||||
|
{
|
||||||
|
context.Logger.LogInformation("Waiting game window to be ready");
|
||||||
|
context.Process.WaitForInputIdle();
|
||||||
|
|
||||||
|
context.Logger.LogInformation("Launching BetterGI");
|
||||||
|
await Launcher.LaunchUriAsync(betterGenshinImpactUri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,7 +11,7 @@ internal sealed class LaunchExecutionStarwardPlayTimeStatisticsHandler : ILaunch
|
|||||||
{
|
{
|
||||||
if (context.Options.UseStarwardPlayTimeStatistics)
|
if (context.Options.UseStarwardPlayTimeStatistics)
|
||||||
{
|
{
|
||||||
context.Logger.LogInformation("Using starward to count game time");
|
context.Logger.LogInformation("Using Starward to count game time");
|
||||||
await LaunchStarwardForPlayTimeStatisticsAsync(context).ConfigureAwait(false);
|
await LaunchStarwardForPlayTimeStatisticsAsync(context).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -24,7 +24,7 @@ internal sealed class LaunchExecutionStarwardPlayTimeStatisticsHandler : ILaunch
|
|||||||
Uri starwardPlayTimeUri = $"starward://playtime/{gameBiz}".ToUri();
|
Uri starwardPlayTimeUri = $"starward://playtime/{gameBiz}".ToUri();
|
||||||
if (await Launcher.QueryUriSupportAsync(starwardPlayTimeUri, LaunchQuerySupportType.Uri) is LaunchQuerySupportStatus.Available)
|
if (await Launcher.QueryUriSupportAsync(starwardPlayTimeUri, LaunchQuerySupportType.Uri) is LaunchQuerySupportStatus.Available)
|
||||||
{
|
{
|
||||||
context.Logger.LogInformation("Launching starward");
|
context.Logger.LogInformation("Launching Starward");
|
||||||
await Launcher.LaunchUriAsync(starwardPlayTimeUri);
|
await Launcher.LaunchUriAsync(starwardPlayTimeUri);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ internal sealed class LaunchExecutionUnlockFpsHandler : ILaunchExecutionDelegate
|
|||||||
|
|
||||||
// The Unlocker can't unlock the process
|
// The Unlocker can't unlock the process
|
||||||
context.Process.Kill();
|
context.Process.Kill();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ internal sealed class LaunchExecutionInvoker
|
|||||||
handlers.Enqueue(new LaunchExecutionSetDiscordActivityHandler());
|
handlers.Enqueue(new LaunchExecutionSetDiscordActivityHandler());
|
||||||
handlers.Enqueue(new LaunchExecutionGameProcessStartHandler());
|
handlers.Enqueue(new LaunchExecutionGameProcessStartHandler());
|
||||||
handlers.Enqueue(new LaunchExecutionStarwardPlayTimeStatisticsHandler());
|
handlers.Enqueue(new LaunchExecutionStarwardPlayTimeStatisticsHandler());
|
||||||
|
handlers.Enqueue(new LaunchExecutionBetterGenshinImpactAutomationHandlder());
|
||||||
handlers.Enqueue(new LaunchExecutionUnlockFpsHandler());
|
handlers.Enqueue(new LaunchExecutionUnlockFpsHandler());
|
||||||
handlers.Enqueue(new LaunchExecutionGameProcessExitHandler());
|
handlers.Enqueue(new LaunchExecutionGameProcessExitHandler());
|
||||||
}
|
}
|
||||||
@@ -40,9 +41,9 @@ internal sealed class LaunchExecutionInvoker
|
|||||||
if (handlers.TryDequeue(out ILaunchExecutionDelegateHandler? handler))
|
if (handlers.TryDequeue(out ILaunchExecutionDelegateHandler? handler))
|
||||||
{
|
{
|
||||||
string typeName = TypeNameHelper.GetTypeDisplayName(handler, false);
|
string typeName = TypeNameHelper.GetTypeDisplayName(handler, false);
|
||||||
context.Logger.LogInformation("Handler[{Handler}] begin execution", typeName);
|
context.Logger.LogInformation("Handler [{Handler}] begin execution", typeName);
|
||||||
await handler.OnExecutionAsync(context, () => InvokeHandlerAsync(context)).ConfigureAwait(false);
|
await handler.OnExecutionAsync(context, () => InvokeHandlerAsync(context)).ConfigureAwait(false);
|
||||||
context.Logger.LogInformation("Handler[{Handler}] end execution", typeName);
|
context.Logger.LogInformation("Handler [{Handler}] end execution", typeName);
|
||||||
}
|
}
|
||||||
|
|
||||||
return context;
|
return context;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
using Snap.Hutao.Model.Entity;
|
using Snap.Hutao.Model.Entity;
|
||||||
|
|
||||||
namespace Snap.Hutao.Service.Inventroy;
|
namespace Snap.Hutao.Service.Inventory;
|
||||||
|
|
||||||
internal interface IInventoryDbService
|
internal interface IInventoryDbService
|
||||||
{
|
{
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
// Copyright (c) DGP Studio. All rights reserved.
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
// Licensed under the MIT license.
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
namespace Snap.Hutao.Service.Inventroy;
|
namespace Snap.Hutao.Service.Inventory;
|
||||||
|
|
||||||
internal interface IInventoryService
|
internal interface IInventoryService
|
||||||
{
|
{
|
||||||
@@ -6,7 +6,7 @@ using Snap.Hutao.Core.Database;
|
|||||||
using Snap.Hutao.Model.Entity;
|
using Snap.Hutao.Model.Entity;
|
||||||
using Snap.Hutao.Model.Entity.Database;
|
using Snap.Hutao.Model.Entity.Database;
|
||||||
|
|
||||||
namespace Snap.Hutao.Service.Inventroy;
|
namespace Snap.Hutao.Service.Inventory;
|
||||||
|
|
||||||
[ConstructorGenerated]
|
[ConstructorGenerated]
|
||||||
[Injection(InjectAs.Singleton, typeof(IInventoryDbService))]
|
[Injection(InjectAs.Singleton, typeof(IInventoryDbService))]
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
// Copyright (c) DGP Studio. All rights reserved.
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
// Licensed under the MIT license.
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
namespace Snap.Hutao.Service.Inventroy;
|
namespace Snap.Hutao.Service.Inventory;
|
||||||
|
|
||||||
[Injection(InjectAs.Transient)]
|
[Injection(InjectAs.Transient)]
|
||||||
internal sealed class InventoryService : IInventoryService
|
internal sealed class InventoryService : IInventoryService
|
||||||
@@ -90,8 +90,6 @@ internal sealed partial class UserInitializationService : IUserInitializationSer
|
|||||||
|
|
||||||
await userFingerprintService.TryInitializeAsync(user, token).ConfigureAwait(false);
|
await userFingerprintService.TryInitializeAsync(user, token).ConfigureAwait(false);
|
||||||
|
|
||||||
// Should not raise propery changed event here
|
|
||||||
user.SetSelectedUserGameRole(user.UserGameRoles.FirstOrFirstOrDefault(role => role.IsChosen), false);
|
|
||||||
return user.IsInitialized = true;
|
return user.IsInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -300,8 +300,8 @@
|
|||||||
<PackageReference Include="CommunityToolkit.WinUI.Controls.SettingsControls" Version="8.0.240109" />
|
<PackageReference Include="CommunityToolkit.WinUI.Controls.SettingsControls" Version="8.0.240109" />
|
||||||
<PackageReference Include="CommunityToolkit.WinUI.Media" Version="8.0.240109" />
|
<PackageReference Include="CommunityToolkit.WinUI.Media" Version="8.0.240109" />
|
||||||
<PackageReference Include="CommunityToolkit.WinUI.Notifications" Version="7.1.2" />
|
<PackageReference Include="CommunityToolkit.WinUI.Notifications" Version="7.1.2" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.1" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.2" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.1">
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.2">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
@@ -316,7 +316,7 @@
|
|||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Microsoft.VisualStudio.Validation" Version="17.8.8" />
|
<PackageReference Include="Microsoft.VisualStudio.Validation" Version="17.8.8" />
|
||||||
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.22621.2428" />
|
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.22621.2428" />
|
||||||
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.4.231219000" />
|
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.4.240211001" />
|
||||||
<PackageReference Include="QRCoder" Version="1.4.3" />
|
<PackageReference Include="QRCoder" Version="1.4.3" />
|
||||||
<PackageReference Include="Snap.Discord.GameSDK" Version="1.6.0" />
|
<PackageReference Include="Snap.Discord.GameSDK" Version="1.6.0" />
|
||||||
<PackageReference Include="Snap.Hutao.Deployment.Runtime" Version="1.15.3">
|
<PackageReference Include="Snap.Hutao.Deployment.Runtime" Version="1.15.3">
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
xmlns:cwconv="using:CommunityToolkit.WinUI.Converters"
|
xmlns:cwconv="using:CommunityToolkit.WinUI.Converters"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:shcb="using:Snap.Hutao.Control.Brush"
|
||||||
xmlns:shch="using:Snap.Hutao.Control.Helper"
|
xmlns:shch="using:Snap.Hutao.Control.Helper"
|
||||||
xmlns:shci="using:Snap.Hutao.Control.Image"
|
xmlns:shci="using:Snap.Hutao.Control.Image"
|
||||||
xmlns:shcm="using:Snap.Hutao.Control.Markup"
|
xmlns:shcm="using:Snap.Hutao.Control.Markup"
|
||||||
@@ -221,101 +222,172 @@
|
|||||||
IsPredictPullAvailable="{Binding IsPredictPullAvailable}"
|
IsPredictPullAvailable="{Binding IsPredictPullAvailable}"
|
||||||
SelectedIndex="0"/>
|
SelectedIndex="0"/>
|
||||||
<cwcont:SwitchPresenter
|
<cwcont:SwitchPresenter
|
||||||
Height="85"
|
Height="96"
|
||||||
Padding="0,12"
|
Padding="0,12"
|
||||||
Value="{x:Bind StatisticsSegmented.SelectedIndex, Mode=OneWay}">
|
Value="{x:Bind StatisticsSegmented.SelectedIndex, Mode=OneWay}">
|
||||||
<cwcont:Case Value="{shcm:Int32 Value=0}">
|
<cwcont:Case Value="{shcm:Int32 Value=0}">
|
||||||
<StackPanel Spacing="2">
|
<Grid ColumnSpacing="2">
|
||||||
<Grid>
|
<Grid.ColumnDefinitions>
|
||||||
<TextBlock
|
<ColumnDefinition/>
|
||||||
HorizontalAlignment="Left"
|
<ColumnDefinition/>
|
||||||
Style="{StaticResource BodyTextBlockStyle}"
|
<ColumnDefinition/>
|
||||||
Text="{shcm:ResourceString Name=ViewControlStatisticsCardOrangeAveragePullText}"/>
|
</Grid.ColumnDefinitions>
|
||||||
<TextBlock
|
<Border Grid.Column="0" Style="{ThemeResource BorderCardStyle}">
|
||||||
HorizontalAlignment="Right"
|
<Viewbox Margin="8,0" StretchDirection="DownOnly">
|
||||||
Style="{StaticResource BodyTextBlockStyle}"
|
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||||
Text="{Binding AverageOrangePullFormatted}"/>
|
<TextBlock
|
||||||
|
Opacity="0.8"
|
||||||
|
Style="{StaticResource CaptionTextBlockStyle}"
|
||||||
|
Text="{shcm:ResourceString Name=ViewControlStatisticsCardOrangeAveragePullText}"/>
|
||||||
|
<TextBlock Style="{StaticResource BodyTextBlockStyle}" Text="{Binding AverageOrangePullFormatted}"/>
|
||||||
|
</StackPanel>
|
||||||
|
</Viewbox>
|
||||||
|
</Border>
|
||||||
|
<Border Grid.Column="1" Style="{ThemeResource BorderCardStyle}">
|
||||||
|
<Viewbox Margin="8,0" StretchDirection="DownOnly">
|
||||||
|
<Grid>
|
||||||
|
<StackPanel
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Visibility="{x:Bind ShowUpPull, Converter={StaticResource BoolToVisibilityConverter}}">
|
||||||
|
<TextBlock
|
||||||
|
Opacity="0.8"
|
||||||
|
Style="{StaticResource CaptionTextBlockStyle}"
|
||||||
|
Text="{shcm:ResourceString Name=ViewControlStatisticsCardUpAveragePullText}"/>
|
||||||
|
<TextBlock Style="{StaticResource BodyTextBlockStyle}" Text="{Binding AverageUpOrangePullFormatted}"/>
|
||||||
|
</StackPanel>
|
||||||
|
<TextBlock
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Style="{StaticResource SubtitleTextBlockStyle}"
|
||||||
|
Text="N/A"
|
||||||
|
Visibility="{x:Bind ShowUpPull, Converter={StaticResource BoolToVisibilityRevertConverter}}"/>
|
||||||
|
</Grid>
|
||||||
|
</Viewbox>
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
<Grid Grid.Column="2" RowSpacing="2">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition/>
|
||||||
|
<RowDefinition/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Border Grid.Row="0" Style="{ThemeResource BorderCardStyle}">
|
||||||
|
<Viewbox Margin="8,0" StretchDirection="DownOnly">
|
||||||
|
<TextBlock
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Style="{StaticResource BodyTextBlockStyle}"
|
||||||
|
Text="{Binding MaxOrangePullFormatted}"/>
|
||||||
|
</Viewbox>
|
||||||
|
</Border>
|
||||||
|
<Border Grid.Row="1" Style="{ThemeResource BorderCardStyle}">
|
||||||
|
<Viewbox Margin="8,0" StretchDirection="DownOnly">
|
||||||
|
<TextBlock
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Style="{StaticResource BodyTextBlockStyle}"
|
||||||
|
Text="{Binding MinOrangePullFormatted}"/>
|
||||||
|
</Viewbox>
|
||||||
|
</Border>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid>
|
</Grid>
|
||||||
<!-- 高度占位符 -->
|
|
||||||
<TextBlock/>
|
|
||||||
<TextBlock
|
|
||||||
HorizontalAlignment="Left"
|
|
||||||
Style="{StaticResource BodyTextBlockStyle}"
|
|
||||||
Text="{shcm:ResourceString Name=ViewControlStatisticsCardUpAveragePullText}"
|
|
||||||
Visibility="{x:Bind ShowUpPull, Converter={StaticResource BoolToVisibilityConverter}}"/>
|
|
||||||
<TextBlock
|
|
||||||
HorizontalAlignment="Right"
|
|
||||||
Style="{StaticResource BodyTextBlockStyle}"
|
|
||||||
Text="{Binding AverageUpOrangePullFormatted}"
|
|
||||||
Visibility="{x:Bind ShowUpPull, Converter={StaticResource BoolToVisibilityConverter}}"/>
|
|
||||||
</Grid>
|
|
||||||
<Grid>
|
|
||||||
<TextBlock
|
|
||||||
HorizontalAlignment="Left"
|
|
||||||
Style="{StaticResource BodyTextBlockStyle}"
|
|
||||||
Text="{Binding MaxOrangePullFormatted}"/>
|
|
||||||
<TextBlock
|
|
||||||
HorizontalAlignment="Right"
|
|
||||||
Style="{StaticResource BodyTextBlockStyle}"
|
|
||||||
Text="{Binding MinOrangePullFormatted}"/>
|
|
||||||
</Grid>
|
|
||||||
<Grid/>
|
|
||||||
</StackPanel>
|
|
||||||
</cwcont:Case>
|
</cwcont:Case>
|
||||||
<cwcont:Case Value="{shcm:Int32 Value=1}">
|
<cwcont:Case Value="{shcm:Int32 Value=1}">
|
||||||
<StackPanel Spacing="2">
|
<Grid RowSpacing="4">
|
||||||
<Grid>
|
<Grid.RowDefinitions>
|
||||||
<TextBlock
|
<RowDefinition/>
|
||||||
HorizontalAlignment="Left"
|
<RowDefinition Height="auto"/>
|
||||||
Foreground="{StaticResource OrangeColorBrush}"
|
</Grid.RowDefinitions>
|
||||||
Style="{StaticResource BodyTextBlockStyle}"
|
<Grid ColumnSpacing="2">
|
||||||
Text="{shcm:ResourceString Name=ViewControlStatisticsCardOrangeText}"/>
|
<Grid.ColumnDefinitions>
|
||||||
<TextBlock
|
<ColumnDefinition/>
|
||||||
HorizontalAlignment="Right"
|
<ColumnDefinition/>
|
||||||
FontFamily="{StaticResource CascadiaMonoAndMiSans}"
|
<ColumnDefinition/>
|
||||||
Foreground="{StaticResource OrangeColorBrush}"
|
</Grid.ColumnDefinitions>
|
||||||
Style="{StaticResource BodyTextBlockStyle}"
|
<Grid Grid.Column="0" Style="{ThemeResource GridCardStyle}">
|
||||||
Text="{Binding TotalOrangeFormatted}"/>
|
<StackPanel
|
||||||
|
Margin="8,0"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
VerticalAlignment="Center">
|
||||||
|
<TextBlock
|
||||||
|
Foreground="{StaticResource OrangeColorBrush}"
|
||||||
|
Style="{StaticResource CaptionTextBlockStyle}"
|
||||||
|
Text="{shcm:ResourceString Name=ViewControlStatisticsCardOrangeText}"/>
|
||||||
|
<Viewbox StretchDirection="DownOnly">
|
||||||
|
<TextBlock Foreground="{StaticResource OrangeColorBrush}" Text="{Binding TotalOrangeFormatted}"/>
|
||||||
|
</Viewbox>
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
<Grid Grid.Column="1" Style="{ThemeResource GridCardStyle}">
|
||||||
|
<StackPanel
|
||||||
|
Margin="8,0"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
VerticalAlignment="Center">
|
||||||
|
<TextBlock
|
||||||
|
Foreground="{StaticResource PurpleColorBrush}"
|
||||||
|
Style="{StaticResource CaptionTextBlockStyle}"
|
||||||
|
Text="{shcm:ResourceString Name=ViewControlStatisticsCardPurpleText}"/>
|
||||||
|
<Viewbox StretchDirection="DownOnly">
|
||||||
|
<TextBlock Foreground="{StaticResource PurpleColorBrush}" Text="{Binding TotalPurpleFormatted}"/>
|
||||||
|
</Viewbox>
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
<Grid Grid.Column="2" Style="{ThemeResource GridCardStyle}">
|
||||||
|
<StackPanel
|
||||||
|
Margin="8,0"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
VerticalAlignment="Center">
|
||||||
|
<TextBlock
|
||||||
|
Foreground="{StaticResource BlueColorBrush}"
|
||||||
|
Style="{StaticResource CaptionTextBlockStyle}"
|
||||||
|
Text="{shcm:ResourceString Name=ViewControlStatisticsCardBlueText}"/>
|
||||||
|
<Viewbox StretchDirection="DownOnly">
|
||||||
|
<TextBlock Foreground="{StaticResource BlueColorBrush}" Text="{Binding TotalBlueFormatted}"/>
|
||||||
|
</Viewbox>
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid>
|
|
||||||
<TextBlock
|
<shcb:SegmentedBar
|
||||||
HorizontalAlignment="Left"
|
Grid.Row="1"
|
||||||
Foreground="{StaticResource PurpleColorBrush}"
|
Height="2"
|
||||||
Style="{StaticResource BodyTextBlockStyle}"
|
Margin="2,0"
|
||||||
Text="{shcm:ResourceString Name=ViewControlStatisticsCardPurpleText}"/>
|
HorizontalAlignment="Stretch"
|
||||||
<TextBlock
|
VerticalAlignment="Stretch"
|
||||||
HorizontalAlignment="Right"
|
Opacity="0.7"
|
||||||
FontFamily="{StaticResource CascadiaMonoAndMiSans}"
|
Source="{Binding PullPercentSegmentSource}"/>
|
||||||
Foreground="{StaticResource PurpleColorBrush}"
|
</Grid>
|
||||||
Style="{StaticResource BodyTextBlockStyle}"
|
|
||||||
Text="{Binding TotalPurpleFormatted}"/>
|
|
||||||
</Grid>
|
|
||||||
<Grid>
|
|
||||||
<TextBlock
|
|
||||||
HorizontalAlignment="Left"
|
|
||||||
Foreground="{StaticResource BlueColorBrush}"
|
|
||||||
Style="{StaticResource BodyTextBlockStyle}"
|
|
||||||
Text="{shcm:ResourceString Name=ViewControlStatisticsCardBlueText}"/>
|
|
||||||
<TextBlock
|
|
||||||
HorizontalAlignment="Right"
|
|
||||||
FontFamily="{StaticResource CascadiaMonoAndMiSans}"
|
|
||||||
Foreground="{StaticResource BlueColorBrush}"
|
|
||||||
Style="{StaticResource BodyTextBlockStyle}"
|
|
||||||
Text="{Binding TotalBlueFormatted}"/>
|
|
||||||
</Grid>
|
|
||||||
</StackPanel>
|
|
||||||
</cwcont:Case>
|
</cwcont:Case>
|
||||||
<cwcont:Case Value="{shcm:Int32 Value=2}">
|
<cwcont:Case Value="{shcm:Int32 Value=2}">
|
||||||
<StackPanel Spacing="2">
|
<Grid RowSpacing="2">
|
||||||
<TextBlock Style="{StaticResource BodyTextBlockStyle}" Text="{Binding PredictedPullLeftToOrangeFormatted}"/>
|
<Grid.RowDefinitions>
|
||||||
<TextBlock Style="{StaticResource BodyTextBlockStyle}" Text="{Binding ProbabilityOfNextPullIsOrangeFormatted}"/>
|
<RowDefinition/>
|
||||||
</StackPanel>
|
<RowDefinition/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Border Grid.Row="0" Style="{ThemeResource BorderCardStyle}">
|
||||||
|
<Viewbox StretchDirection="DownOnly">
|
||||||
|
<TextBlock
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Style="{StaticResource BodyTextBlockStyle}"
|
||||||
|
Text="{Binding PredictedPullLeftToOrangeFormatted}"/>
|
||||||
|
</Viewbox>
|
||||||
|
</Border>
|
||||||
|
<Border Grid.Row="1" Style="{ThemeResource BorderCardStyle}">
|
||||||
|
<Viewbox StretchDirection="DownOnly">
|
||||||
|
<TextBlock
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Style="{StaticResource BodyTextBlockStyle}"
|
||||||
|
Text="{Binding ProbabilityOfNextPullIsOrangeFormatted}"/>
|
||||||
|
</Viewbox>
|
||||||
|
</Border>
|
||||||
|
</Grid>
|
||||||
</cwcont:Case>
|
</cwcont:Case>
|
||||||
</cwcont:SwitchPresenter>
|
</cwcont:SwitchPresenter>
|
||||||
<MenuFlyoutSeparator Margin="-12,0"/>
|
<MenuFlyoutSeparator Margin="-12,0"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
</Expander>
|
</Expander>
|
||||||
|
|
||||||
<cwcont:SwitchPresenter
|
<cwcont:SwitchPresenter
|
||||||
|
|||||||
@@ -149,20 +149,22 @@
|
|||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
|
|
||||||
<DataTemplate x:Key="AnnouncementPivotItemContentTemplate">
|
<DataTemplate x:Key="AnnouncementPivotItemContentTemplate">
|
||||||
<ItemsRepeater
|
<ScrollViewer>
|
||||||
Margin="16,16,16,16"
|
<ItemsRepeater
|
||||||
HorizontalAlignment="Stretch"
|
Margin="16,16,16,16"
|
||||||
ItemTemplate="{StaticResource AnnouncementTemplate}"
|
HorizontalAlignment="Stretch"
|
||||||
ItemsSource="{Binding List}">
|
ItemTemplate="{StaticResource AnnouncementTemplate}"
|
||||||
<ItemsRepeater.Layout>
|
ItemsSource="{Binding List}">
|
||||||
<UniformGridLayout
|
<ItemsRepeater.Layout>
|
||||||
ItemsJustification="Start"
|
<UniformGridLayout
|
||||||
ItemsStretch="Fill"
|
ItemsJustification="Start"
|
||||||
MinColumnSpacing="12"
|
ItemsStretch="Fill"
|
||||||
MinItemWidth="300"
|
MinColumnSpacing="12"
|
||||||
MinRowSpacing="12"/>
|
MinItemWidth="300"
|
||||||
</ItemsRepeater.Layout>
|
MinRowSpacing="12"/>
|
||||||
</ItemsRepeater>
|
</ItemsRepeater.Layout>
|
||||||
|
</ItemsRepeater>
|
||||||
|
</ScrollViewer>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
|
|
||||||
<DataTemplate x:Key="HutaoAnnouncementTemplate">
|
<DataTemplate x:Key="HutaoAnnouncementTemplate">
|
||||||
|
|||||||
@@ -346,6 +346,12 @@
|
|||||||
HeaderIcon="{shcm:FontIcon Glyph=}">
|
HeaderIcon="{shcm:FontIcon Glyph=}">
|
||||||
<ToggleSwitch MinWidth="{ThemeResource SettingsCardContentControlMinWidth}" IsOn="{Binding LaunchOptions.UseStarwardPlayTimeStatistics, Mode=TwoWay}"/>
|
<ToggleSwitch MinWidth="{ThemeResource SettingsCardContentControlMinWidth}" IsOn="{Binding LaunchOptions.UseStarwardPlayTimeStatistics, Mode=TwoWay}"/>
|
||||||
</cwc:SettingsCard>
|
</cwc:SettingsCard>
|
||||||
|
<cwc:SettingsCard
|
||||||
|
Description="{shcm:ResourceString Name=ViewPageLaunchGameBetterGIDescription}"
|
||||||
|
Header="{shcm:ResourceString Name=ViewPageLaunchGameBetterGIHeader}"
|
||||||
|
HeaderIcon="{shcm:FontIcon Glyph=}">
|
||||||
|
<ToggleSwitch MinWidth="{ThemeResource SettingsCardContentControlMinWidth}" IsOn="{Binding LaunchOptions.UseBetterGenshinImpactAutomation, Mode=TwoWay}"/>
|
||||||
|
</cwc:SettingsCard>
|
||||||
<cwc:SettingsCard
|
<cwc:SettingsCard
|
||||||
Description="{shcm:ResourceString Name=ViewPageLaunchGameDiscordActivityDescription}"
|
Description="{shcm:ResourceString Name=ViewPageLaunchGameDiscordActivityDescription}"
|
||||||
Header="{shcm:ResourceString Name=ViewPageLaunchGameDiscordActivityHeader}"
|
Header="{shcm:ResourceString Name=ViewPageLaunchGameDiscordActivityHeader}"
|
||||||
|
|||||||
@@ -221,7 +221,7 @@
|
|||||||
<shct:DescriptionTextBlock
|
<shct:DescriptionTextBlock
|
||||||
Margin="0,8,0,16"
|
Margin="0,8,0,16"
|
||||||
Description="{Binding Description}"
|
Description="{Binding Description}"
|
||||||
Style="{StaticResource CaptionTextBlockStyle}"/>
|
TextStyle="{StaticResource CaptionTextBlockStyle}"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
|
|||||||
@@ -291,7 +291,7 @@
|
|||||||
ProfilePicture="{Binding UserInfo.AvatarUrl, Mode=OneWay}"/>
|
ProfilePicture="{Binding UserInfo.AvatarUrl, Mode=OneWay}"/>
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
Margin="10,0,0,0"
|
Margin="12,0,0,0"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Text="{Binding UserInfo.Nickname}"/>
|
Text="{Binding UserInfo.Nickname}"/>
|
||||||
<TextBlock
|
<TextBlock
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
// Licensed under the MIT license.
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
using Snap.Hutao.Control.Brush;
|
||||||
|
using Snap.Hutao.Control.Theme;
|
||||||
|
|
||||||
namespace Snap.Hutao.ViewModel.GachaLog;
|
namespace Snap.Hutao.ViewModel.GachaLog;
|
||||||
|
|
||||||
@@ -83,6 +85,16 @@ internal sealed partial class TypedWishSummary : Wish
|
|||||||
get => $"{TotalBluePull} [{TotalBluePercent,6:p2}]";
|
get => $"{TotalBluePull} [{TotalBluePercent,6:p2}]";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ColorSegmentCollection PullPercentSegmentSource
|
||||||
|
{
|
||||||
|
get =>
|
||||||
|
[
|
||||||
|
new ColorSegment(KnownColors.Orange, TotalOrangePull),
|
||||||
|
new ColorSegment(KnownColors.Purple, TotalPurplePull),
|
||||||
|
new ColorSegment(KnownColors.Blue, TotalBluePull),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 平均五星抽数
|
/// 平均五星抽数
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -167,13 +167,13 @@ internal sealed partial class SettingViewModel : Abstraction.ViewModel
|
|||||||
if (await dialog.ConfirmAsync(SH.ViewPageSettingIsAdvancedLaunchOptionsEnabledHeader).ConfigureAwait(true))
|
if (await dialog.ConfirmAsync(SH.ViewPageSettingIsAdvancedLaunchOptionsEnabledHeader).ConfigureAwait(true))
|
||||||
{
|
{
|
||||||
launchOptions.IsAdvancedLaunchOptionsEnabled = true;
|
launchOptions.IsAdvancedLaunchOptionsEnabled = true;
|
||||||
OnPropertyChanged(nameof(IsAllocConsoleDebugModeEnabled));
|
OnPropertyChanged(nameof(IsAdvancedLaunchOptionsEnabled));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
launchOptions.IsAdvancedLaunchOptionsEnabled = false;
|
launchOptions.IsAdvancedLaunchOptionsEnabled = false;
|
||||||
OnPropertyChanged(nameof(IsAllocConsoleDebugModeEnabled));
|
OnPropertyChanged(nameof(IsAdvancedLaunchOptionsEnabled));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using CommunityToolkit.Mvvm.Messaging;
|
|||||||
using Snap.Hutao.Core.Abstraction;
|
using Snap.Hutao.Core.Abstraction;
|
||||||
using Snap.Hutao.Core.Database;
|
using Snap.Hutao.Core.Database;
|
||||||
using Snap.Hutao.Model;
|
using Snap.Hutao.Model;
|
||||||
|
using Snap.Hutao.Model.Entity.Database;
|
||||||
using Snap.Hutao.Web.Hoyolab;
|
using Snap.Hutao.Web.Hoyolab;
|
||||||
using Snap.Hutao.Web.Hoyolab.Bbs.User;
|
using Snap.Hutao.Web.Hoyolab.Bbs.User;
|
||||||
using Snap.Hutao.Web.Hoyolab.Takumi.Binding;
|
using Snap.Hutao.Web.Hoyolab.Takumi.Binding;
|
||||||
@@ -20,18 +21,14 @@ namespace Snap.Hutao.ViewModel.User;
|
|||||||
internal sealed class User : ObservableObject, IEntityOnly<EntityUser>, IMappingFrom<User, EntityUser, IServiceProvider>, ISelectable
|
internal sealed class User : ObservableObject, IEntityOnly<EntityUser>, IMappingFrom<User, EntityUser, IServiceProvider>, ISelectable
|
||||||
{
|
{
|
||||||
private readonly EntityUser inner;
|
private readonly EntityUser inner;
|
||||||
private readonly IMessenger messenger;
|
private readonly IServiceProvider serviceProvider;
|
||||||
|
|
||||||
private UserGameRole? selectedUserGameRole;
|
private UserGameRole? selectedUserGameRole;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 构造一个新的绑定视图用户
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="user">用户实体</param>
|
|
||||||
private User(EntityUser user, IServiceProvider serviceProvider)
|
private User(EntityUser user, IServiceProvider serviceProvider)
|
||||||
{
|
{
|
||||||
inner = user;
|
inner = user;
|
||||||
messenger = serviceProvider.GetRequiredService<IMessenger>();
|
this.serviceProvider = serviceProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsInitialized { get; set; }
|
public bool IsInitialized { get; set; }
|
||||||
@@ -99,6 +96,8 @@ internal sealed class User : ObservableObject, IEntityOnly<EntityUser>, IMapping
|
|||||||
|
|
||||||
public bool NeedDbUpdateAfterResume { get; set; }
|
public bool NeedDbUpdateAfterResume { get; set; }
|
||||||
|
|
||||||
|
public string? PreferredUid { get => inner.PreferredUid; }
|
||||||
|
|
||||||
public static User From(EntityUser user, IServiceProvider provider)
|
public static User From(EntityUser user, IServiceProvider provider)
|
||||||
{
|
{
|
||||||
return new(user, provider);
|
return new(user, provider);
|
||||||
@@ -106,9 +105,21 @@ internal sealed class User : ObservableObject, IEntityOnly<EntityUser>, IMapping
|
|||||||
|
|
||||||
public void SetSelectedUserGameRole(UserGameRole? value, bool raiseMessage = true)
|
public void SetSelectedUserGameRole(UserGameRole? value, bool raiseMessage = true)
|
||||||
{
|
{
|
||||||
if (SetProperty(ref selectedUserGameRole, value, nameof(SelectedUserGameRole)) && raiseMessage)
|
if (SetProperty(ref selectedUserGameRole, value, nameof(SelectedUserGameRole)))
|
||||||
{
|
{
|
||||||
messenger.Send(Message.UserChangedMessage.CreateOnlyRoleChanged(this));
|
if (value is not null && inner.PreferredUid != value.GameUid)
|
||||||
|
{
|
||||||
|
inner.PreferredUid = value.GameUid;
|
||||||
|
using (IServiceScope scope = serviceProvider.CreateScope())
|
||||||
|
{
|
||||||
|
scope.ServiceProvider.GetRequiredService<AppDbContext>().Users.UpdateAndSave(inner);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (raiseMessage)
|
||||||
|
{
|
||||||
|
serviceProvider.GetRequiredService<IMessenger>().Send(Message.UserChangedMessage.CreateOnlyRoleChanged(this));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -53,10 +53,18 @@ internal sealed partial class UserViewModel : ObservableObject
|
|||||||
get => selectedUser ??= userService.Current;
|
get => selectedUser ??= userService.Current;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (value is { SelectedUserGameRole: null })
|
if (value is not null)
|
||||||
{
|
{
|
||||||
// Pre select the chosen role to avoid multiple UserChangedMessage
|
// Should not raise propery changed event below
|
||||||
value.SetSelectedUserGameRole(value.UserGameRoles.FirstOrFirstOrDefault(role => role.IsChosen), false);
|
if (value.PreferredUid is not null)
|
||||||
|
{
|
||||||
|
value.SetSelectedUserGameRole(value.UserGameRoles.FirstOrDefault(role => role.GameUid == value.PreferredUid), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value.SelectedUserGameRole is null)
|
||||||
|
{
|
||||||
|
value.SetSelectedUserGameRole(value.UserGameRoles.FirstOrFirstOrDefault(role => role.IsChosen), false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SetProperty(ref selectedUser, value))
|
if (SetProperty(ref selectedUser, value))
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
// 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 System.Web;
|
||||||
|
|
||||||
namespace Snap.Hutao.Web.Hutao.Algolia;
|
namespace Snap.Hutao.Web.Hutao.Algolia;
|
||||||
|
|
||||||
internal sealed class AlgoliaHierarchy
|
internal sealed class AlgoliaHierarchy
|
||||||
@@ -35,42 +37,42 @@ internal sealed class AlgoliaHierarchy
|
|||||||
yield break;
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
yield return Lvl1;
|
yield return HttpUtility.HtmlDecode(Lvl1);
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(Lvl2))
|
if (string.IsNullOrEmpty(Lvl2))
|
||||||
{
|
{
|
||||||
yield break;
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
yield return Lvl2;
|
yield return HttpUtility.HtmlDecode(Lvl2);
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(Lvl3))
|
if (string.IsNullOrEmpty(Lvl3))
|
||||||
{
|
{
|
||||||
yield break;
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
yield return Lvl3;
|
yield return HttpUtility.HtmlDecode(Lvl3);
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(Lvl4))
|
if (string.IsNullOrEmpty(Lvl4))
|
||||||
{
|
{
|
||||||
yield break;
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
yield return Lvl4;
|
yield return HttpUtility.HtmlDecode(Lvl4);
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(Lvl5))
|
if (string.IsNullOrEmpty(Lvl5))
|
||||||
{
|
{
|
||||||
yield break;
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
yield return Lvl5;
|
yield return HttpUtility.HtmlDecode(Lvl5);
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(Lvl6))
|
if (string.IsNullOrEmpty(Lvl6))
|
||||||
{
|
{
|
||||||
yield break;
|
yield break;
|
||||||
}
|
}
|
||||||
|
|
||||||
yield return Lvl6;
|
yield return HttpUtility.HtmlDecode(Lvl6);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
using Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient;
|
||||||
|
using Snap.Hutao.Web.Request.Builder;
|
||||||
|
using Snap.Hutao.Web.Request.Builder.Abstraction;
|
||||||
|
using Snap.Hutao.Web.Response;
|
||||||
|
using System.Net.Http;
|
||||||
|
|
||||||
|
namespace Snap.Hutao.Web.Hutao.Wallpaper;
|
||||||
|
|
||||||
|
[HttpClient(HttpClientConfiguration.Default)]
|
||||||
|
[ConstructorGenerated(ResolveHttpClient = true)]
|
||||||
|
internal sealed partial class HutaoWallpaperClient
|
||||||
|
{
|
||||||
|
private readonly IHttpRequestMessageBuilderFactory httpRequestMessageBuilderFactory;
|
||||||
|
private readonly ILogger<HutaoWallpaperClient> logger;
|
||||||
|
private readonly HttpClient httpClient;
|
||||||
|
|
||||||
|
public ValueTask<Response<Wallpaper>> GetBingWallpaperAsync(CancellationToken token = default)
|
||||||
|
{
|
||||||
|
return GetWallpaperAsync(HutaoEndpoints.WallpaperBing, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueTask<Response<Wallpaper>> GetLauncherWallpaperAsync(CancellationToken token = default)
|
||||||
|
{
|
||||||
|
return GetWallpaperAsync(HutaoEndpoints.WallpaperGenshinLauncher, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueTask<Response<Wallpaper>> GetTodayWallpaperAsync(CancellationToken token = default)
|
||||||
|
{
|
||||||
|
return GetWallpaperAsync(HutaoEndpoints.WallpaperToday, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async ValueTask<Response<Wallpaper>> GetWallpaperAsync(string url, CancellationToken token = default)
|
||||||
|
{
|
||||||
|
HttpRequestMessageBuilder builder = httpRequestMessageBuilderFactory.Create()
|
||||||
|
.SetRequestUri(url)
|
||||||
|
.Get();
|
||||||
|
|
||||||
|
Response<Wallpaper>? resp = await builder.TryCatchSendAsync<Response<Wallpaper>>(httpClient, logger, token).ConfigureAwait(false);
|
||||||
|
return Web.Response.Response.DefaultIfNull(resp);
|
||||||
|
}
|
||||||
|
}
|
||||||
19
src/Snap.Hutao/Snap.Hutao/Web/Hutao/Wallpaper/Wallpaper.cs
Normal file
19
src/Snap.Hutao/Snap.Hutao/Web/Hutao/Wallpaper/Wallpaper.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
// Copyright (c) DGP Studio. All rights reserved.
|
||||||
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
|
namespace Snap.Hutao.Web.Hutao.Wallpaper;
|
||||||
|
|
||||||
|
internal sealed class Wallpaper
|
||||||
|
{
|
||||||
|
[JsonPropertyName("url")]
|
||||||
|
public string Url { get; set; } = default!;
|
||||||
|
|
||||||
|
[JsonPropertyName("source_url")]
|
||||||
|
public string SourceUrl { get; set; } = default!;
|
||||||
|
|
||||||
|
[JsonPropertyName("author")]
|
||||||
|
public string Author { get; set; } = default!;
|
||||||
|
|
||||||
|
[JsonPropertyName("uploader")]
|
||||||
|
public string Uploader { get; set; } = default!;
|
||||||
|
}
|
||||||
@@ -10,8 +10,9 @@ namespace Snap.Hutao.Web;
|
|||||||
/// 胡桃 API 端点
|
/// 胡桃 API 端点
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[HighQuality]
|
[HighQuality]
|
||||||
[SuppressMessage("", "SA1201")]
|
|
||||||
[SuppressMessage("", "SA1124")]
|
[SuppressMessage("", "SA1124")]
|
||||||
|
[SuppressMessage("", "SA1201")]
|
||||||
|
[SuppressMessage("", "SA1203")]
|
||||||
internal static class HutaoEndpoints
|
internal static class HutaoEndpoints
|
||||||
{
|
{
|
||||||
#region HomaAPI
|
#region HomaAPI
|
||||||
@@ -271,6 +272,15 @@ internal static class HutaoEndpoints
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region Wallpaper
|
||||||
|
|
||||||
|
public const string WallpaperBing = $"{ApiSnapGenshin}/wallpaper/bing";
|
||||||
|
|
||||||
|
public const string WallpaperGenshinLauncher = $"{ApiSnapGenshin}/wallpaper/genshin-launcher";
|
||||||
|
|
||||||
|
public const string WallpaperToday = $"{ApiSnapGenshin}/wallpaper/today";
|
||||||
|
#endregion
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private const string ApiSnapGenshin = "https://api.snapgenshin.com";
|
private const string ApiSnapGenshin = "https://api.snapgenshin.com";
|
||||||
|
|||||||
Reference in New Issue
Block a user