mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
Compare commits
1 Commits
fix/hotkey
...
ci/cake_up
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4ded6dc9bf |
19
.github/workflows/alpha.yml
vendored
19
.github/workflows/alpha.yml
vendored
@@ -13,18 +13,6 @@ on:
|
||||
- '**.md'
|
||||
- 'LICENSE'
|
||||
- '**.yml'
|
||||
pull_request:
|
||||
branches:
|
||||
- develop
|
||||
paths-ignore:
|
||||
- '.gitattributes'
|
||||
- '.github/**'
|
||||
- '.gitignore'
|
||||
- '.gitmodules'
|
||||
- '**.md'
|
||||
- 'LICENSE'
|
||||
- '**.yml'
|
||||
- '**.resx'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
@@ -46,21 +34,20 @@ jobs:
|
||||
VERSION_API_TOKEN: ${{ secrets.VERSION_API_TOKEN }}
|
||||
|
||||
- name: Sign Msix
|
||||
if: success() && github.event_name != 'pull_request'
|
||||
shell: pwsh
|
||||
run: |
|
||||
[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
|
||||
|
||||
- name: Upload signed msix
|
||||
if: success() && github.event_name != 'pull_request'
|
||||
uses: actions/upload-artifact@v4
|
||||
if: success()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: Snap.Hutao.Alpha-${{ steps.cake.outputs.version }}
|
||||
path: ${{ github.workspace }}/src/output/Snap.Hutao.Alpha-${{ steps.cake.outputs.version }}.msix
|
||||
|
||||
- name: Add summary
|
||||
if: success() && github.event_name != 'pull_request'
|
||||
if: success()
|
||||
shell: pwsh
|
||||
run: |
|
||||
$summary = "
|
||||
|
||||
32
build.cake
32
build.cake
@@ -33,28 +33,18 @@ if (GitHubActions.IsRunningOnGitHubActions)
|
||||
repoDir = GitHubActions.Environment.Workflow.Workspace.FullPath;
|
||||
outputPath = System.IO.Path.Combine(repoDir, "src", "output");
|
||||
|
||||
if (GitHubActions.Environment.PullRequest.IsPullRequest)
|
||||
{
|
||||
version = System.DateTime.Now.ToString("yyyy.M.d.0");
|
||||
|
||||
Information("Is Pull Request. Skip version.");
|
||||
}
|
||||
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>
|
||||
{
|
||||
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 }
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
Information($"Version: {version}");
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
Information($"Version: {version}");
|
||||
|
||||
GitHubActions.Commands.SetOutputParameter("version", version);
|
||||
}
|
||||
|
||||
@@ -23,12 +23,10 @@ internal static class ControlAnimationConstants
|
||||
/// <summary>
|
||||
/// 图像淡入
|
||||
/// </summary>
|
||||
public static readonly TimeSpan ImageScaleFadeIn = TimeSpan.FromSeconds(0.3);
|
||||
public static readonly TimeSpan ImageFadeIn = TimeSpan.FromSeconds(0.3);
|
||||
|
||||
/// <summary>
|
||||
/// 图像淡出
|
||||
/// </summary>
|
||||
public static readonly TimeSpan ImageScaleFadeOut = TimeSpan.FromSeconds(0.2);
|
||||
|
||||
public static readonly TimeSpan ImageOpacityFadeInOut = TimeSpan.FromSeconds(1);
|
||||
public static readonly TimeSpan ImageFadeOut = TimeSpan.FromSeconds(0.2);
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using CommunityToolkit.WinUI.Behaviors;
|
||||
using Microsoft.UI.Xaml;
|
||||
|
||||
namespace Snap.Hutao.Control.Behavior;
|
||||
|
||||
[DependencyProperty("Period", typeof(TimeSpan))]
|
||||
[DependencyProperty("Command", typeof(ICommand))]
|
||||
[DependencyProperty("CommandParameter", typeof(object))]
|
||||
internal sealed partial class PeriodicInvokeCommandOrOnActualThemeChangedBehavior : BehaviorBase<FrameworkElement>, IDisposable
|
||||
{
|
||||
private TaskCompletionSource acutalThemeChangedTaskCompletionSource = new();
|
||||
private CancellationTokenSource periodicTimerCancellationTokenSource = new();
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
periodicTimerCancellationTokenSource.Dispose();
|
||||
}
|
||||
|
||||
protected override bool Initialize()
|
||||
{
|
||||
AssociatedObject.ActualThemeChanged += OnActualThemeChanged;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void OnAssociatedObjectLoaded()
|
||||
{
|
||||
RunCoreAsync().SafeForget();
|
||||
}
|
||||
|
||||
protected override bool Uninitialize()
|
||||
{
|
||||
AssociatedObject.ActualThemeChanged -= OnActualThemeChanged;
|
||||
return true;
|
||||
}
|
||||
|
||||
private void OnActualThemeChanged(FrameworkElement sender, object args)
|
||||
{
|
||||
acutalThemeChangedTaskCompletionSource.TrySetResult();
|
||||
periodicTimerCancellationTokenSource.Cancel();
|
||||
}
|
||||
|
||||
private void TryExecuteCommand()
|
||||
{
|
||||
if (AssociatedObject is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (Command is not null && Command.CanExecute(CommandParameter))
|
||||
{
|
||||
Command.Execute(CommandParameter);
|
||||
}
|
||||
}
|
||||
|
||||
private async ValueTask RunCoreAsync()
|
||||
{
|
||||
using (PeriodicTimer timer = new(Period))
|
||||
{
|
||||
do
|
||||
{
|
||||
if (!IsAttached)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
ITaskContext taskContext = Ioc.Default.GetRequiredService<ITaskContext>();
|
||||
await taskContext.SwitchToMainThreadAsync();
|
||||
TryExecuteCommand();
|
||||
|
||||
await taskContext.SwitchToBackgroundAsync();
|
||||
try
|
||||
{
|
||||
Task nextTickTask = timer.WaitForNextTickAsync(periodicTimerCancellationTokenSource.Token).AsTask();
|
||||
await Task.WhenAny(nextTickTask, acutalThemeChangedTaskCompletionSource.Task).ConfigureAwait(false);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
}
|
||||
|
||||
acutalThemeChangedTaskCompletionSource = new();
|
||||
periodicTimerCancellationTokenSource = new();
|
||||
}
|
||||
while (true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -192,7 +192,7 @@ internal abstract partial class CompositionImage : Microsoft.UI.Xaml.Controls.Co
|
||||
{
|
||||
await AnimationBuilder
|
||||
.Create()
|
||||
.Opacity(from: 0D, to: 1D, duration: ControlAnimationConstants.ImageScaleFadeIn)
|
||||
.Opacity(from: 0D, to: 1D, duration: ControlAnimationConstants.ImageFadeIn)
|
||||
.StartAsync(this, token)
|
||||
.ConfigureAwait(true);
|
||||
}
|
||||
@@ -213,7 +213,7 @@ internal abstract partial class CompositionImage : Microsoft.UI.Xaml.Controls.Co
|
||||
{
|
||||
await AnimationBuilder
|
||||
.Create()
|
||||
.Opacity(from: 1D, to: 0D, duration: ControlAnimationConstants.ImageScaleFadeOut)
|
||||
.Opacity(from: 1D, to: 0D, duration: ControlAnimationConstants.ImageFadeOut)
|
||||
.StartAsync(this, token)
|
||||
.ConfigureAwait(true);
|
||||
}
|
||||
|
||||
@@ -18,12 +18,6 @@ internal sealed class HutaoException : Exception
|
||||
|
||||
public HutaoExceptionKind Kind { get; private set; }
|
||||
|
||||
[DoesNotReturn]
|
||||
public static HutaoException Throw(HutaoExceptionKind kind, string message, Exception? innerException = default)
|
||||
{
|
||||
throw new HutaoException(kind, message, innerException);
|
||||
}
|
||||
|
||||
public static void ThrowIf(bool condition, HutaoExceptionKind kind, string message, Exception? innerException = default)
|
||||
{
|
||||
if (condition)
|
||||
@@ -31,10 +25,4 @@ internal sealed class HutaoException : Exception
|
||||
throw new HutaoException(kind, message, innerException);
|
||||
}
|
||||
}
|
||||
|
||||
public static HutaoException ServiceTypeCastFailed<TFrom, TTo>(string name, Exception? innerException = default)
|
||||
{
|
||||
string message = $"This instance of '{typeof(TFrom).FullName}' '{name}' doesn't implement '{typeof(TTo).FullName}'";
|
||||
throw new HutaoException(HutaoExceptionKind.ServiceTypeCastFailed, message, innerException);
|
||||
}
|
||||
}
|
||||
@@ -6,5 +6,4 @@ namespace Snap.Hutao.Core.ExceptionService;
|
||||
internal enum HutaoExceptionKind
|
||||
{
|
||||
None,
|
||||
ServiceTypeCastFailed,
|
||||
}
|
||||
@@ -5,7 +5,6 @@ using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Snap.Hutao.Core.LifeCycle;
|
||||
using Snap.Hutao.Core.Setting;
|
||||
using Snap.Hutao.Model;
|
||||
using Snap.Hutao.Service.Notification;
|
||||
using Snap.Hutao.Win32.Foundation;
|
||||
using Snap.Hutao.Win32.UI.Input.KeyboardAndMouse;
|
||||
using System.Text;
|
||||
@@ -18,7 +17,6 @@ namespace Snap.Hutao.Core.Windowing.HotKey;
|
||||
internal sealed class HotKeyCombination : ObservableObject
|
||||
{
|
||||
private readonly ICurrentWindowReference currentWindowReference;
|
||||
private readonly IInfoBarService infoBarService;
|
||||
private readonly RuntimeOptions runtimeOptions;
|
||||
|
||||
private readonly string settingKey;
|
||||
@@ -39,7 +37,6 @@ internal sealed class HotKeyCombination : ObservableObject
|
||||
public HotKeyCombination(IServiceProvider serviceProvider, string settingKey, int hotKeyId, HOT_KEY_MODIFIERS defaultModifiers, VirtualKey defaultKey)
|
||||
{
|
||||
currentWindowReference = serviceProvider.GetRequiredService<ICurrentWindowReference>();
|
||||
infoBarService = serviceProvider.GetRequiredService<IInfoBarService>();
|
||||
runtimeOptions = serviceProvider.GetRequiredService<RuntimeOptions>();
|
||||
|
||||
this.settingKey = settingKey;
|
||||
@@ -189,12 +186,6 @@ internal sealed class HotKeyCombination : ObservableObject
|
||||
HWND hwnd = currentWindowReference.GetWindowHandle();
|
||||
BOOL result = RegisterHotKey(hwnd, hotKeyId, Modifiers, (uint)Key);
|
||||
registered = result;
|
||||
|
||||
if (!result)
|
||||
{
|
||||
infoBarService.Warning(SH.FormatCoreWindowHotkeyCombinationRegisterFailed(SH.ViewPageSettingKeyShortcutAutoClickingHeader, DisplayName));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,16 +11,10 @@ internal static class CollectionsNameValue
|
||||
return [.. Enum.GetValues<TEnum>().Select(x => new NameValue<TEnum>(x.ToString(), x))];
|
||||
}
|
||||
|
||||
public static List<NameValue<TEnum>> FromEnum<TEnum>(Func<TEnum, bool> condition)
|
||||
public static List<NameValue<TEnum>> FromEnum<TEnum>(Func<TEnum, bool> codiction)
|
||||
where TEnum : struct, Enum
|
||||
{
|
||||
return [.. Enum.GetValues<TEnum>().Where(condition).Select(x => new NameValue<TEnum>(x.ToString(), x))];
|
||||
}
|
||||
|
||||
public static List<NameValue<TEnum>> FromEnum<TEnum>(Func<TEnum, string> nameSelector)
|
||||
where TEnum : struct, Enum
|
||||
{
|
||||
return [.. Enum.GetValues<TEnum>().Select(x => new NameValue<TEnum>(nameSelector(x), x))];
|
||||
return [.. Enum.GetValues<TEnum>().Where(codiction).Select(x => new NameValue<TEnum>(x.ToString(), x))];
|
||||
}
|
||||
|
||||
public static List<NameValue<TSource>> From<TSource>(IEnumerable<TSource> sources, Func<TSource, string> nameSelector)
|
||||
|
||||
@@ -13,7 +13,6 @@ internal sealed partial class SettingEntry
|
||||
public const string Culture = "Culture";
|
||||
|
||||
public const string SystemBackdropType = "SystemBackdropType";
|
||||
public const string BackgroundImageType = "BackgroundImageType";
|
||||
|
||||
public const string AnnouncementRegion = "AnnouncementRegion";
|
||||
|
||||
|
||||
@@ -186,9 +186,6 @@
|
||||
<data name="CoreWebView2HelperVersionUndetected" xml:space="preserve">
|
||||
<value>未检测到 WebView2 运行时</value>
|
||||
</data>
|
||||
<data name="CoreWindowHotkeyCombinationRegisterFailed" xml:space="preserve">
|
||||
<value>[{0}] 热键 [{1}] 注册失败</value>
|
||||
</data>
|
||||
<data name="FilePickerExportCommit" xml:space="preserve">
|
||||
<value>导出</value>
|
||||
</data>
|
||||
@@ -770,21 +767,6 @@
|
||||
<data name="ServiceAvatarInfoSummaryShowcaseRefreshTimeFormat" xml:space="preserve">
|
||||
<value>角色橱窗:{0:MM-dd HH:mm}</value>
|
||||
</data>
|
||||
<data name="ServiceBackgroundImageTypeBing" xml:space="preserve">
|
||||
<value>必应每日一图</value>
|
||||
</data>
|
||||
<data name="ServiceBackgroundImageTypeDaily" xml:space="preserve">
|
||||
<value>胡桃每日一图</value>
|
||||
</data>
|
||||
<data name="ServiceBackgroundImageTypeLauncher" xml:space="preserve">
|
||||
<value>官方启动器壁纸</value>
|
||||
</data>
|
||||
<data name="ServiceBackgroundImageTypeLocalFolder" xml:space="preserve">
|
||||
<value>本地随机图片</value>
|
||||
</data>
|
||||
<data name="ServiceBackgroundImageTypeNone" xml:space="preserve">
|
||||
<value>无背景图片</value>
|
||||
</data>
|
||||
<data name="ServiceCultivationProjectCurrentUserdataCourrpted" xml:space="preserve">
|
||||
<value>保存养成计划状态失败</value>
|
||||
</data>
|
||||
@@ -1694,9 +1676,6 @@
|
||||
<data name="ViewModelWelcomeDownloadSummaryComplete" xml:space="preserve">
|
||||
<value>完成</value>
|
||||
</data>
|
||||
<data name="ViewModelWelcomeDownloadSummaryContentTypeNotMatch" xml:space="preserve">
|
||||
<value>响应内容不是有效的文件字节流</value>
|
||||
</data>
|
||||
<data name="ViewModelWelcomeDownloadSummaryDefault" xml:space="preserve">
|
||||
<value>等待中</value>
|
||||
</data>
|
||||
@@ -2360,15 +2339,6 @@
|
||||
<data name="ViewPageSettingBackdropMaterialHeader" xml:space="preserve">
|
||||
<value>背景材质</value>
|
||||
</data>
|
||||
<data name="ViewPageSettingBackgroundImageCopyrightHeader" xml:space="preserve">
|
||||
<value>图片版权信息</value>
|
||||
</data>
|
||||
<data name="ViewPageSettingBackgroundImageDescription" xml:space="preserve">
|
||||
<value>更改窗体的背景图片来源,重启胡桃以尽快生效</value>
|
||||
</data>
|
||||
<data name="ViewPageSettingBackgroundImageHeader" xml:space="preserve">
|
||||
<value>背景图片</value>
|
||||
</data>
|
||||
<data name="ViewPageSettingCacheFolderDescription" xml:space="preserve">
|
||||
<value>图片缓存 在此处存放</value>
|
||||
</data>
|
||||
|
||||
@@ -5,7 +5,6 @@ using Snap.Hutao.Core.Windowing;
|
||||
using Snap.Hutao.Model;
|
||||
using Snap.Hutao.Model.Entity;
|
||||
using Snap.Hutao.Service.Abstraction;
|
||||
using Snap.Hutao.Service.BackgroundImage;
|
||||
using Snap.Hutao.Web.Hoyolab;
|
||||
|
||||
namespace Snap.Hutao.Service;
|
||||
@@ -16,7 +15,6 @@ internal sealed partial class AppOptions : DbStoreOptions
|
||||
{
|
||||
private bool? isEmptyHistoryWishVisible;
|
||||
private BackdropType? backdropType;
|
||||
private BackgroundImageType? backgroundImageType;
|
||||
private Region? region;
|
||||
private string? geetestCustomCompositeUrl;
|
||||
|
||||
@@ -30,16 +28,8 @@ internal sealed partial class AppOptions : DbStoreOptions
|
||||
|
||||
public BackdropType BackdropType
|
||||
{
|
||||
get => GetOption(ref backdropType, SettingEntry.SystemBackdropType, EnumParse<BackdropType>, BackdropType.Mica).Value;
|
||||
set => SetOption(ref backdropType, SettingEntry.SystemBackdropType, value, EnumToStringOrEmpty);
|
||||
}
|
||||
|
||||
public List<NameValue<BackgroundImageType>> BackgroundImageTypes { get; } = CollectionsNameValue.FromEnum<BackgroundImageType>(type => type.GetLocalizedDescription());
|
||||
|
||||
public BackgroundImageType BackgroundImageType
|
||||
{
|
||||
get => GetOption(ref backgroundImageType, SettingEntry.BackgroundImageType, EnumParse<BackgroundImageType>, BackgroundImageType.None).Value;
|
||||
set => SetOption(ref backgroundImageType, SettingEntry.BackgroundImageType, value, EnumToStringOrEmpty);
|
||||
get => GetOption(ref backdropType, SettingEntry.SystemBackdropType, v => Enum.Parse<BackdropType>(v), BackdropType.Mica).Value;
|
||||
set => SetOption(ref backdropType, SettingEntry.SystemBackdropType, value, value => value.ToStringOrEmpty());
|
||||
}
|
||||
|
||||
public Lazy<List<NameValue<Region>>> LazyRegions { get; } = new(KnownRegions.Get);
|
||||
@@ -55,16 +45,4 @@ internal sealed partial class AppOptions : DbStoreOptions
|
||||
get => GetOption(ref geetestCustomCompositeUrl, SettingEntry.GeetestCustomCompositeUrl);
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -2,14 +2,17 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.UI.Xaml.Media.Imaging;
|
||||
using Snap.Hutao.Control.Media;
|
||||
using Snap.Hutao.Core;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using Windows.Graphics.Imaging;
|
||||
using Windows.UI;
|
||||
|
||||
namespace Snap.Hutao.Service.BackgroundImage;
|
||||
|
||||
internal sealed class BackgroundImage
|
||||
{
|
||||
public string Path { get; set; } = default!;
|
||||
|
||||
public BitmapImage ImageSource { get; set; } = default!;
|
||||
|
||||
public Color AccentColor { get; set; }
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Snap.Hutao.Web.Hutao.Wallpaper;
|
||||
|
||||
namespace Snap.Hutao.Service.BackgroundImage;
|
||||
|
||||
[Injection(InjectAs.Singleton)]
|
||||
internal sealed partial class BackgroundImageOptions : ObservableObject
|
||||
{
|
||||
private Wallpaper? wallpaper;
|
||||
|
||||
public Wallpaper? Wallpaper { get => wallpaper; set => SetProperty(ref wallpaper, value); }
|
||||
}
|
||||
@@ -5,11 +5,11 @@ using Snap.Hutao.Control.Media;
|
||||
using Snap.Hutao.Core;
|
||||
using Snap.Hutao.Core.Caching;
|
||||
using Snap.Hutao.Core.IO;
|
||||
using Snap.Hutao.Web.Hutao.Wallpaper;
|
||||
using Snap.Hutao.Service.Game.Scheme;
|
||||
using Snap.Hutao.Web.Hoyolab.SdkStatic.Hk4e.Launcher;
|
||||
using Snap.Hutao.Web.Hoyolab.SdkStatic.Hk4e.Launcher.Content;
|
||||
using Snap.Hutao.Web.Response;
|
||||
using Snap.Hutao.Win32.Foundation;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using Windows.Graphics.Imaging;
|
||||
|
||||
namespace Snap.Hutao.Service.BackgroundImage;
|
||||
@@ -20,13 +20,11 @@ internal sealed partial class BackgroundImageService : IBackgroundImageService
|
||||
{
|
||||
private static readonly HashSet<string> AllowedFormats = [".bmp", ".gif", ".ico", ".jpg", ".jpeg", ".png", ".tiff", ".webp"];
|
||||
|
||||
private readonly BackgroundImageOptions backgroundImageOptions;
|
||||
private readonly IServiceProvider serviceProvider;
|
||||
private readonly RuntimeOptions runtimeOptions;
|
||||
private readonly ITaskContext taskContext;
|
||||
private readonly AppOptions appOptions;
|
||||
|
||||
private HashSet<string> currentBackgroundPathSet;
|
||||
private HashSet<string> backgroundPathSet;
|
||||
|
||||
public async ValueTask<ValueResult<bool, BackgroundImage>> GetNextBackgroundImageAsync(BackgroundImage? previous)
|
||||
{
|
||||
@@ -37,31 +35,18 @@ internal sealed partial class BackgroundImageService : IBackgroundImageService
|
||||
return new(false, default!);
|
||||
}
|
||||
|
||||
string path = System.Random.Shared.GetItems([..backgroundSet], 1)[0];
|
||||
string path = System.Random.Shared.GetItems(backgroundSet.ToArray(), 1)[0];
|
||||
backgroundSet.Remove(path);
|
||||
|
||||
if (string.Equals(path, previous?.Path, StringComparison.OrdinalIgnoreCase))
|
||||
await taskContext.SwitchToMainThreadAsync();
|
||||
if (string.Equals(path, previous?.ImageSource.UriSource.ToString(), StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return new(false, default!);
|
||||
}
|
||||
|
||||
using (FileStream fileStream = File.OpenRead(path))
|
||||
{
|
||||
BitmapDecoder decoder;
|
||||
try
|
||||
{
|
||||
decoder = await BitmapDecoder.CreateAsync(fileStream.AsRandomAccessStream());
|
||||
}
|
||||
catch (COMException comException)
|
||||
{
|
||||
if (comException.HResult != HRESULT.E_FAIL)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
return new(false, default!);
|
||||
}
|
||||
|
||||
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(fileStream.AsRandomAccessStream());
|
||||
SoftwareBitmap softwareBitmap = await decoder.GetSoftwareBitmapAsync(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Straight);
|
||||
Bgra32 accentColor = softwareBitmap.GetAccentColor();
|
||||
|
||||
@@ -69,7 +54,6 @@ internal sealed partial class BackgroundImageService : IBackgroundImageService
|
||||
|
||||
BackgroundImage background = new()
|
||||
{
|
||||
Path = path,
|
||||
ImageSource = new(path.ToUri()),
|
||||
AccentColor = accentColor,
|
||||
Luminance = accentColor.Luminance,
|
||||
@@ -81,55 +65,32 @@ internal sealed partial class BackgroundImageService : IBackgroundImageService
|
||||
|
||||
private async ValueTask<HashSet<string>> SkipOrInitBackgroundAsync()
|
||||
{
|
||||
switch (appOptions.BackgroundImageType)
|
||||
if (backgroundPathSet is null || backgroundPathSet.Count <= 0)
|
||||
{
|
||||
case BackgroundImageType.LocalFolder:
|
||||
{
|
||||
if (currentBackgroundPathSet is not { Count: > 0 })
|
||||
{
|
||||
string backgroundFolder = runtimeOptions.GetDataFolderBackgroundFolder();
|
||||
Directory.CreateDirectory(backgroundFolder);
|
||||
string backgroundFolder = runtimeOptions.GetDataFolderBackgroundFolder();
|
||||
Directory.CreateDirectory(backgroundFolder);
|
||||
backgroundPathSet = Directory
|
||||
.GetFiles(backgroundFolder, "*.*", SearchOption.AllDirectories)
|
||||
.Where(path => AllowedFormats.Contains(Path.GetExtension(path)))
|
||||
.ToHashSet();
|
||||
|
||||
currentBackgroundPathSet = Directory
|
||||
.GetFiles(backgroundFolder, "*.*", SearchOption.AllDirectories)
|
||||
.Where(path => AllowedFormats.Contains(Path.GetExtension(path)))
|
||||
.ToHashSet();
|
||||
}
|
||||
|
||||
backgroundImageOptions.Wallpaper = default;
|
||||
break;
|
||||
}
|
||||
|
||||
case BackgroundImageType.HutaoBing:
|
||||
await SetCurrentBackgroundPathSetAsync(client => client.GetBingWallpaperAsync()).ConfigureAwait(false);
|
||||
break;
|
||||
case BackgroundImageType.HutaoDaily:
|
||||
await SetCurrentBackgroundPathSetAsync(client => client.GetTodayWallpaperAsync()).ConfigureAwait(false);
|
||||
break;
|
||||
case BackgroundImageType.HutaoOfficialLauncher:
|
||||
await SetCurrentBackgroundPathSetAsync(client => client.GetLauncherWallpaperAsync()).ConfigureAwait(false);
|
||||
break;
|
||||
}
|
||||
|
||||
currentBackgroundPathSet ??= [];
|
||||
return currentBackgroundPathSet;
|
||||
|
||||
async Task SetCurrentBackgroundPathSetAsync(Func<HutaoWallpaperClient, ValueTask<Response<Wallpaper>>> responseFactory)
|
||||
{
|
||||
HutaoWallpaperClient wallpaperClient = serviceProvider.GetRequiredService<HutaoWallpaperClient>();
|
||||
Response<Wallpaper> response = await responseFactory(wallpaperClient).ConfigureAwait(false);
|
||||
if (response is { Data: Wallpaper wallpaper })
|
||||
// No image found
|
||||
if (backgroundPathSet.Count <= 0)
|
||||
{
|
||||
await taskContext.SwitchToMainThreadAsync();
|
||||
backgroundImageOptions.Wallpaper = wallpaper;
|
||||
|
||||
await taskContext.SwitchToBackgroundAsync();
|
||||
if (wallpaper.Url is { } url)
|
||||
ResourceClient resourceClient = serviceProvider.GetRequiredService<ResourceClient>();
|
||||
string launguageCode = serviceProvider.GetRequiredService<CultureOptions>().LanguageCode;
|
||||
LaunchScheme scheme = launguageCode is "zh-cn"
|
||||
? KnownLaunchSchemes.Get().First(scheme => !scheme.IsOversea && scheme.IsNotCompatOnly)
|
||||
: KnownLaunchSchemes.Get().First(scheme => scheme.IsOversea && scheme.IsNotCompatOnly);
|
||||
Response<GameContent> response = await resourceClient.GetContentAsync(scheme, launguageCode).ConfigureAwait(false);
|
||||
if (response is { Data.Advertisement.Background: string url })
|
||||
{
|
||||
ValueFile file = await serviceProvider.GetRequiredService<IImageCache>().GetFileFromCacheAsync(url).ConfigureAwait(false);
|
||||
currentBackgroundPathSet = [file];
|
||||
ValueFile file = await serviceProvider.GetRequiredService<IImageCache>().GetFileFromCacheAsync(url.ToUri()).ConfigureAwait(false);
|
||||
backgroundPathSet = [file];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return backgroundPathSet;
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Service.BackgroundImage;
|
||||
|
||||
[Localization]
|
||||
internal enum BackgroundImageType
|
||||
{
|
||||
[LocalizationKey(nameof(SH.ServiceBackgroundImageTypeNone))]
|
||||
None,
|
||||
|
||||
[LocalizationKey(nameof(SH.ServiceBackgroundImageTypeLocalFolder))]
|
||||
LocalFolder,
|
||||
|
||||
[LocalizationKey(nameof(SH.ServiceBackgroundImageTypeBing))]
|
||||
HutaoBing,
|
||||
|
||||
[LocalizationKey(nameof(SH.ServiceBackgroundImageTypeDaily))]
|
||||
HutaoDaily,
|
||||
|
||||
[LocalizationKey(nameof(SH.ServiceBackgroundImageTypeLauncher))]
|
||||
HutaoOfficialLauncher,
|
||||
}
|
||||
@@ -7,7 +7,7 @@ using Snap.Hutao.Model.Entity;
|
||||
using Snap.Hutao.Model.Entity.Database;
|
||||
using Snap.Hutao.Model.Entity.Primitive;
|
||||
using Snap.Hutao.Model.Metadata.Item;
|
||||
using Snap.Hutao.Service.Inventory;
|
||||
using Snap.Hutao.Service.Inventroy;
|
||||
using Snap.Hutao.Service.Metadata.ContextAbstraction;
|
||||
using Snap.Hutao.ViewModel.Cultivation;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
@@ -23,9 +23,6 @@ internal sealed class LaunchExecutionBetterGenshinImpactAutomationHandlder : ILa
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -24,9 +24,9 @@ internal sealed class LaunchExecutionInvoker
|
||||
handlers.Enqueue(new LaunchExecutionGameProcessInitializationHandler());
|
||||
handlers.Enqueue(new LaunchExecutionSetDiscordActivityHandler());
|
||||
handlers.Enqueue(new LaunchExecutionGameProcessStartHandler());
|
||||
handlers.Enqueue(new LaunchExecutionUnlockFpsHandler());
|
||||
handlers.Enqueue(new LaunchExecutionStarwardPlayTimeStatisticsHandler());
|
||||
handlers.Enqueue(new LaunchExecutionBetterGenshinImpactAutomationHandlder());
|
||||
handlers.Enqueue(new LaunchExecutionUnlockFpsHandler());
|
||||
handlers.Enqueue(new LaunchExecutionGameProcessExitHandler());
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
using Snap.Hutao.Model.Entity;
|
||||
|
||||
namespace Snap.Hutao.Service.Inventory;
|
||||
namespace Snap.Hutao.Service.Inventroy;
|
||||
|
||||
internal interface IInventoryDbService
|
||||
{
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Service.Inventory;
|
||||
namespace Snap.Hutao.Service.Inventroy;
|
||||
|
||||
internal interface IInventoryService
|
||||
{
|
||||
@@ -6,7 +6,7 @@ using Snap.Hutao.Core.Database;
|
||||
using Snap.Hutao.Model.Entity;
|
||||
using Snap.Hutao.Model.Entity.Database;
|
||||
|
||||
namespace Snap.Hutao.Service.Inventory;
|
||||
namespace Snap.Hutao.Service.Inventroy;
|
||||
|
||||
[ConstructorGenerated]
|
||||
[Injection(InjectAs.Singleton, typeof(IInventoryDbService))]
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Service.Inventory;
|
||||
namespace Snap.Hutao.Service.Inventroy;
|
||||
|
||||
[Injection(InjectAs.Transient)]
|
||||
internal sealed class InventoryService : IInventoryService
|
||||
@@ -12,19 +12,12 @@ internal static class SupportedCultures
|
||||
[
|
||||
ToNameValue(CultureInfo.GetCultureInfo("zh-Hans")),
|
||||
ToNameValue(CultureInfo.GetCultureInfo("zh-Hant")),
|
||||
/*ToNameValue(CultureInfo.GetCultureInfo("de")),*/
|
||||
ToNameValue(CultureInfo.GetCultureInfo("en")),
|
||||
/*ToNameValue(CultureInfo.GetCultureInfo("es")),*/
|
||||
/*ToNameValue(CultureInfo.GetCultureInfo("fr")),*/
|
||||
ToNameValue(CultureInfo.GetCultureInfo("id")),
|
||||
/*ToNameValue(CultureInfo.GetCultureInfo("it")),*/
|
||||
ToNameValue(CultureInfo.GetCultureInfo("ja")),
|
||||
ToNameValue(CultureInfo.GetCultureInfo("ko")),
|
||||
ToNameValue(CultureInfo.GetCultureInfo("pt")),
|
||||
ToNameValue(CultureInfo.GetCultureInfo("ko")),
|
||||
ToNameValue(CultureInfo.GetCultureInfo("ru")),
|
||||
/*ToNameValue(CultureInfo.GetCultureInfo("th")),*/
|
||||
/*ToNameValue(CultureInfo.GetCultureInfo("tr")),*/
|
||||
/*ToNameValue(CultureInfo.GetCultureInfo("vi")),*/
|
||||
];
|
||||
|
||||
public static List<NameValue<CultureInfo>> Get()
|
||||
|
||||
@@ -4,24 +4,12 @@
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:mxi="using:Microsoft.Xaml.Interactivity"
|
||||
xmlns:shcb="using:Snap.Hutao.Control.Behavior"
|
||||
xmlns:shch="using:Snap.Hutao.Control.Helper"
|
||||
xmlns:shcm="using:Snap.Hutao.Control.Markup"
|
||||
xmlns:shv="using:Snap.Hutao.View"
|
||||
xmlns:shvh="using:Snap.Hutao.View.Helper"
|
||||
xmlns:shvm="using:Snap.Hutao.ViewModel"
|
||||
xmlns:shvp="using:Snap.Hutao.View.Page"
|
||||
d:DataContext="{d:DesignInstance Type=shvm:MainViewModel}"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<mxi:Interaction.Behaviors>
|
||||
<shcb:PeriodicInvokeCommandOrOnActualThemeChangedBehavior
|
||||
Command="{Binding UpdateBackgroundCommand}"
|
||||
CommandParameter="{x:Bind BackdroundImagePresenter}"
|
||||
Period="0:5:0"/>
|
||||
</mxi:Interaction.Behaviors>
|
||||
|
||||
<UserControl.Resources>
|
||||
<Thickness x:Key="NavigationViewContentMargin">0,44,0,0</Thickness>
|
||||
<Thickness x:Key="NavigationViewContentGridBorderThickness">0,1,0,0</Thickness>
|
||||
@@ -31,8 +19,8 @@
|
||||
<Grid Background="{ThemeResource SolidBackgroundFillColorBaseBrush}" Transitions="{ThemeResource EntranceThemeTransitions}">
|
||||
<Image
|
||||
x:Name="BackdroundImagePresenter"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
Opacity="0"
|
||||
Stretch="UniformToFill"/>
|
||||
|
||||
|
||||
@@ -5,12 +5,10 @@ using CommunityToolkit.WinUI.Animations;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Media.Animation;
|
||||
using Snap.Hutao.Control.Animation;
|
||||
using Snap.Hutao.Control.Theme;
|
||||
using Snap.Hutao.Service.BackgroundImage;
|
||||
using Snap.Hutao.Service.Navigation;
|
||||
using Snap.Hutao.View.Page;
|
||||
using Snap.Hutao.ViewModel;
|
||||
|
||||
namespace Snap.Hutao.View;
|
||||
|
||||
@@ -21,23 +19,80 @@ namespace Snap.Hutao.View;
|
||||
internal sealed partial class MainView : UserControl
|
||||
{
|
||||
private readonly INavigationService navigationService;
|
||||
private readonly IBackgroundImageService backgroundImageService;
|
||||
private TaskCompletionSource acutalThemeChangedTaskCompletionSource = new();
|
||||
private CancellationTokenSource periodicTimerCancellationTokenSource = new();
|
||||
private BackgroundImage? previousBackgroundImage;
|
||||
|
||||
/// <summary>
|
||||
/// 构造一个新的主视图
|
||||
/// </summary>
|
||||
public MainView()
|
||||
{
|
||||
DataContext = Ioc.Default.GetRequiredService<MainViewModel>();
|
||||
InitializeComponent();
|
||||
|
||||
ActualThemeChanged += OnActualThemeChanged;
|
||||
|
||||
IServiceProvider serviceProvider = Ioc.Default;
|
||||
|
||||
backgroundImageService = serviceProvider.GetRequiredService<IBackgroundImageService>();
|
||||
RunBackgroundImageLoopAsync(serviceProvider.GetRequiredService<ITaskContext>()).SafeForget();
|
||||
|
||||
navigationService = serviceProvider.GetRequiredService<INavigationService>();
|
||||
if (navigationService is INavigationInitialization navigationInitialization)
|
||||
{
|
||||
navigationInitialization.Initialize(NavView, ContentFrame);
|
||||
}
|
||||
navigationService
|
||||
.As<INavigationInitialization>()?
|
||||
.Initialize(NavView, ContentFrame);
|
||||
|
||||
navigationService.Navigate<AnnouncementPage>(INavigationAwaiter.Default, true);
|
||||
}
|
||||
|
||||
private async ValueTask RunBackgroundImageLoopAsync(ITaskContext taskContext)
|
||||
{
|
||||
using (PeriodicTimer timer = new(TimeSpan.FromMinutes(5)))
|
||||
{
|
||||
do
|
||||
{
|
||||
(bool isOk, BackgroundImage backgroundImage) = await backgroundImageService.GetNextBackgroundImageAsync(previousBackgroundImage).ConfigureAwait(false);
|
||||
|
||||
if (isOk)
|
||||
{
|
||||
previousBackgroundImage = backgroundImage;
|
||||
await taskContext.SwitchToMainThreadAsync();
|
||||
|
||||
await AnimationBuilder
|
||||
.Create()
|
||||
.Opacity(to: 0D, duration: TimeSpan.FromMilliseconds(1000), easingType: EasingType.Sine, easingMode: EasingMode.EaseIn)
|
||||
.StartAsync(BackdroundImagePresenter)
|
||||
.ConfigureAwait(true);
|
||||
|
||||
BackdroundImagePresenter.Source = backgroundImage.ImageSource;
|
||||
double targetOpacity = ThemeHelper.IsDarkMode(ActualTheme) ? 1 - backgroundImage.Luminance : backgroundImage.Luminance;
|
||||
|
||||
await AnimationBuilder
|
||||
.Create()
|
||||
.Opacity(to: targetOpacity, duration: TimeSpan.FromMilliseconds(1000), easingType: EasingType.Sine, easingMode: EasingMode.EaseOut)
|
||||
.StartAsync(BackdroundImagePresenter)
|
||||
.ConfigureAwait(true);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
await Task.WhenAny(timer.WaitForNextTickAsync(periodicTimerCancellationTokenSource.Token).AsTask(), acutalThemeChangedTaskCompletionSource.Task).ConfigureAwait(false);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
}
|
||||
|
||||
acutalThemeChangedTaskCompletionSource = new();
|
||||
periodicTimerCancellationTokenSource = new();
|
||||
}
|
||||
while (true);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnActualThemeChanged(FrameworkElement frameworkElement, object args)
|
||||
{
|
||||
acutalThemeChangedTaskCompletionSource.TrySetResult();
|
||||
periodicTimerCancellationTokenSource.Cancel();
|
||||
}
|
||||
}
|
||||
@@ -3,12 +3,10 @@
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:cw="using:CommunityToolkit.WinUI"
|
||||
xmlns:cwb="using:CommunityToolkit.WinUI.Behaviors"
|
||||
xmlns:cwc="using:CommunityToolkit.WinUI.Controls"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:mxi="using:Microsoft.Xaml.Interactivity"
|
||||
xmlns:mxic="using:Microsoft.Xaml.Interactions.Core"
|
||||
xmlns:shc="using:Snap.Hutao.Control"
|
||||
xmlns:shcb="using:Snap.Hutao.Control.Behavior"
|
||||
xmlns:shch="using:Snap.Hutao.Control.Helper"
|
||||
@@ -314,92 +312,6 @@
|
||||
SelectedItem="{Binding SelectedBackdropType, Mode=TwoWay}"/>
|
||||
</shc:SizeRestrictedContentControl>
|
||||
</cwc:SettingsCard>
|
||||
<cwc:SettingsExpander
|
||||
Description="{shcm:ResourceString Name=ViewPageSettingBackgroundImageDescription}"
|
||||
Header="{shcm:ResourceString Name=ViewPageSettingBackgroundImageHeader}"
|
||||
HeaderIcon="{shcm:FontIcon Glyph=}"
|
||||
IsExpanded="{Binding BackgroundImageOptions.Wallpaper, Converter={StaticResource EmptyObjectToBoolConverter}}">
|
||||
<shc:SizeRestrictedContentControl VerticalAlignment="Center">
|
||||
<ComboBox
|
||||
DisplayMemberPath="Name"
|
||||
ItemsSource="{Binding AppOptions.BackgroundImageTypes}"
|
||||
SelectedItem="{Binding SelectedBackgroundImageType, Mode=TwoWay}"/>
|
||||
</shc:SizeRestrictedContentControl>
|
||||
<cwc:SettingsExpander.Items>
|
||||
<cwc:SettingsCard
|
||||
Description="{Binding BackgroundImageOptions.Wallpaper.Author}"
|
||||
Header="{shcm:ResourceString Name=ViewPageSettingBackgroundImageCopyrightHeader}"
|
||||
IsClickEnabled="True"
|
||||
Visibility="{Binding BackgroundImageOptions.Wallpaper, Converter={StaticResource EmptyObjectToVisibilityConverter}}">
|
||||
<mxi:Interaction.Behaviors>
|
||||
<mxic:EventTriggerBehavior EventName="Click">
|
||||
<cwb:NavigateToUriAction NavigateUri="{Binding BackgroundImageOptions.Wallpaper.SourceUrl}"/>
|
||||
</mxic:EventTriggerBehavior>
|
||||
</mxi:Interaction.Behaviors>
|
||||
</cwc:SettingsCard>
|
||||
</cwc:SettingsExpander.Items>
|
||||
</cwc:SettingsExpander>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</Border>
|
||||
|
||||
<Border cw:Effects.Shadow="{ThemeResource CompatCardShadow}">
|
||||
<Border Padding="16" Style="{ThemeResource AcrylicBorderCardStyle}">
|
||||
<StackPanel Spacing="{ThemeResource SettingsCardSpacing}">
|
||||
<TextBlock Style="{StaticResource SettingsCardHeaderTextBlockStyle}" Text="{shcm:ResourceString Name=ViewPageSettingStorageHeader}"/>
|
||||
<cwc:SettingsExpander
|
||||
Description="{Binding DataFolderView.Size}"
|
||||
Header="{shcm:ResourceString Name=ViewPageSettingDataFolderHeader}"
|
||||
HeaderIcon="{shcm:FontIcon Glyph=}"
|
||||
IsExpanded="True">
|
||||
<cwc:SettingsExpander.Content>
|
||||
<Button
|
||||
Command="{Binding DataFolderView.OpenFolderCommand}"
|
||||
Content="{shcm:ResourceString Name=ViewSettingFolderViewOpenFolderAction}"
|
||||
Style="{ThemeResource SettingButtonStyle}"/>
|
||||
</cwc:SettingsExpander.Content>
|
||||
<cwc:SettingsExpander.Items>
|
||||
<cwc:SettingsCard
|
||||
Command="{Binding OpenBackgroundImageFolderCommand}"
|
||||
Description="{shcm:ResourceString Name=ViewPageSettingOpenBackgroundImageFolderDescription}"
|
||||
Header="{shcm:ResourceString Name=ViewPageSettingOpenBackgroundImageFolderHeader}"
|
||||
IsClickEnabled="True"/>
|
||||
<cwc:SettingsCard
|
||||
ActionIcon="{shcm:FontIcon Glyph=}"
|
||||
ActionIconToolTip="{shcm:ResourceString Name=ViewPageSettingStorageSetAction}"
|
||||
Command="{Binding SetDataFolderCommand}"
|
||||
Description="{shcm:ResourceString Name=ViewPageSettingSetDataFolderDescription}"
|
||||
Header="{shcm:ResourceString Name=ViewPageSettingSetDataFolderHeader}"
|
||||
IsClickEnabled="True"/>
|
||||
<cwc:SettingsCard
|
||||
ActionIcon="{shcm:FontIcon Glyph=}"
|
||||
Command="{Binding DeleteServerCacheFolderCommand}"
|
||||
Description="{shcm:ResourceString Name=ViewSettingDeleteServerCacheFolderDescription}"
|
||||
Header="{shcm:ResourceString Name=ViewSettingDeleteServerCacheFolderHeader}"
|
||||
IsClickEnabled="True"/>
|
||||
</cwc:SettingsExpander.Items>
|
||||
</cwc:SettingsExpander>
|
||||
<cwc:SettingsExpander
|
||||
Description="{Binding CacheFolderView.Size}"
|
||||
Header="{shcm:ResourceString Name=ViewPageSettingCacheFolderHeader}"
|
||||
HeaderIcon="{shcm:FontIcon Glyph=}"
|
||||
IsExpanded="True">
|
||||
<cwc:SettingsExpander.Content>
|
||||
<Button
|
||||
Command="{Binding CacheFolderView.OpenFolderCommand}"
|
||||
Content="{shcm:ResourceString Name=ViewSettingFolderViewOpenFolderAction}"
|
||||
Style="{ThemeResource SettingButtonStyle}"/>
|
||||
</cwc:SettingsExpander.Content>
|
||||
<cwc:SettingsExpander.Items>
|
||||
<cwc:SettingsCard
|
||||
ActionIcon="{shcm:FontIcon Glyph=}"
|
||||
ActionIconToolTip="{shcm:ResourceString Name=ViewPageSettingResetAction}"
|
||||
Command="{Binding ResetStaticResourceCommand}"
|
||||
Description="{shcm:ResourceString Name=ViewPageSettingResetStaticResourceDescription}"
|
||||
Header="{shcm:ResourceString Name=ViewPageSettingResetStaticResourceHeader}"
|
||||
IsClickEnabled="True"/>
|
||||
</cwc:SettingsExpander.Items>
|
||||
</cwc:SettingsExpander>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</Border>
|
||||
@@ -554,6 +466,67 @@
|
||||
</Border>
|
||||
</Border>
|
||||
|
||||
<Border cw:Effects.Shadow="{ThemeResource CompatCardShadow}">
|
||||
<Border Padding="16" Style="{ThemeResource AcrylicBorderCardStyle}">
|
||||
<StackPanel Spacing="{ThemeResource SettingsCardSpacing}">
|
||||
<TextBlock Style="{StaticResource SettingsCardHeaderTextBlockStyle}" Text="{shcm:ResourceString Name=ViewPageSettingStorageHeader}"/>
|
||||
<cwc:SettingsExpander
|
||||
Description="{Binding DataFolderView.Size}"
|
||||
Header="{shcm:ResourceString Name=ViewPageSettingDataFolderHeader}"
|
||||
HeaderIcon="{shcm:FontIcon Glyph=}"
|
||||
IsExpanded="True">
|
||||
<cwc:SettingsExpander.Content>
|
||||
<Button
|
||||
Command="{Binding DataFolderView.OpenFolderCommand}"
|
||||
Content="{shcm:ResourceString Name=ViewSettingFolderViewOpenFolderAction}"
|
||||
Style="{ThemeResource SettingButtonStyle}"/>
|
||||
</cwc:SettingsExpander.Content>
|
||||
<cwc:SettingsExpander.Items>
|
||||
<cwc:SettingsCard
|
||||
Command="{Binding OpenBackgroundImageFolderCommand}"
|
||||
Description="{shcm:ResourceString Name=ViewPageSettingOpenBackgroundImageFolderDescription}"
|
||||
Header="{shcm:ResourceString Name=ViewPageSettingOpenBackgroundImageFolderHeader}"
|
||||
IsClickEnabled="True"/>
|
||||
<cwc:SettingsCard
|
||||
ActionIcon="{shcm:FontIcon Glyph=}"
|
||||
ActionIconToolTip="{shcm:ResourceString Name=ViewPageSettingStorageSetAction}"
|
||||
Command="{Binding SetDataFolderCommand}"
|
||||
Description="{shcm:ResourceString Name=ViewPageSettingSetDataFolderDescription}"
|
||||
Header="{shcm:ResourceString Name=ViewPageSettingSetDataFolderHeader}"
|
||||
IsClickEnabled="True"/>
|
||||
<cwc:SettingsCard
|
||||
ActionIcon="{shcm:FontIcon Glyph=}"
|
||||
Command="{Binding DeleteServerCacheFolderCommand}"
|
||||
Description="{shcm:ResourceString Name=ViewSettingDeleteServerCacheFolderDescription}"
|
||||
Header="{shcm:ResourceString Name=ViewSettingDeleteServerCacheFolderHeader}"
|
||||
IsClickEnabled="True"/>
|
||||
</cwc:SettingsExpander.Items>
|
||||
</cwc:SettingsExpander>
|
||||
<cwc:SettingsExpander
|
||||
Description="{Binding CacheFolderView.Size}"
|
||||
Header="{shcm:ResourceString Name=ViewPageSettingCacheFolderHeader}"
|
||||
HeaderIcon="{shcm:FontIcon Glyph=}"
|
||||
IsExpanded="True">
|
||||
<cwc:SettingsExpander.Content>
|
||||
<Button
|
||||
Command="{Binding CacheFolderView.OpenFolderCommand}"
|
||||
Content="{shcm:ResourceString Name=ViewSettingFolderViewOpenFolderAction}"
|
||||
Style="{ThemeResource SettingButtonStyle}"/>
|
||||
</cwc:SettingsExpander.Content>
|
||||
<cwc:SettingsExpander.Items>
|
||||
<cwc:SettingsCard
|
||||
ActionIcon="{shcm:FontIcon Glyph=}"
|
||||
ActionIconToolTip="{shcm:ResourceString Name=ViewPageSettingResetAction}"
|
||||
Command="{Binding ResetStaticResourceCommand}"
|
||||
Description="{shcm:ResourceString Name=ViewPageSettingResetStaticResourceDescription}"
|
||||
Header="{shcm:ResourceString Name=ViewPageSettingResetStaticResourceHeader}"
|
||||
IsClickEnabled="True"/>
|
||||
</cwc:SettingsExpander.Items>
|
||||
</cwc:SettingsExpander>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</Border>
|
||||
|
||||
<Border cw:Effects.Shadow="{ThemeResource CompatCardShadow}">
|
||||
<Border Padding="16" Style="{ThemeResource AcrylicBorderCardStyle}">
|
||||
<StackPanel Spacing="{ThemeResource SettingsCardSpacing}">
|
||||
|
||||
@@ -5,7 +5,6 @@ using CommunityToolkit.Common;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Snap.Hutao.Core;
|
||||
using Snap.Hutao.Core.Caching;
|
||||
using Snap.Hutao.Core.ExceptionService;
|
||||
using Snap.Hutao.Core.IO;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
@@ -75,14 +74,6 @@ internal sealed class DownloadSummary : ObservableObject
|
||||
try
|
||||
{
|
||||
HttpResponseMessage response = await httpClient.GetAsync(fileUrl, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false);
|
||||
|
||||
if (response.Content.Headers.ContentType?.MediaType is not "application/octet-stream")
|
||||
{
|
||||
logger.LogWarning("Download Static Zip failed, Content-Type is {Type}", response.Content.Headers.ContentType);
|
||||
Description = SH.ViewModelWelcomeDownloadSummaryContentTypeNotMatch;
|
||||
return false;
|
||||
}
|
||||
|
||||
long contentLength = response.Content.Headers.ContentLength ?? 0;
|
||||
logger.LogInformation("Begin download, length: {length}", contentLength);
|
||||
using (Stream content = await response.Content.ReadAsStreamAsync().ConfigureAwait(false))
|
||||
@@ -104,7 +95,7 @@ internal sealed class DownloadSummary : ObservableObject
|
||||
logger.LogError(ex, "Download Static Zip failed");
|
||||
await taskContext.SwitchToMainThreadAsync();
|
||||
Description = ex is HttpRequestException httpRequestException
|
||||
? $"{SH.ViewModelWelcomeDownloadSummaryException} - [HTTP '{httpRequestException.StatusCode:D}'] [Error '{httpRequestException.HttpRequestError}']"
|
||||
? $"{SH.ViewModelWelcomeDownloadSummaryException} - HTTP {httpRequestException.HttpRequestError} {httpRequestException.StatusCode:D}"
|
||||
: ex.Message;
|
||||
return false;
|
||||
}
|
||||
@@ -118,10 +109,8 @@ internal sealed class DownloadSummary : ObservableObject
|
||||
|
||||
private void ExtractFiles(Stream stream)
|
||||
{
|
||||
if (imageCache is not IImageCacheFilePathOperation imageCacheFilePathOperation)
|
||||
{
|
||||
throw HutaoException.ServiceTypeCastFailed<IImageCache, IImageCacheFilePathOperation>(nameof(imageCache));
|
||||
}
|
||||
IImageCacheFilePathOperation? imageCacheFilePathOperation = imageCache.As<IImageCacheFilePathOperation>();
|
||||
ArgumentNullException.ThrowIfNull(imageCacheFilePathOperation);
|
||||
|
||||
using (ZipArchive archive = new(stream))
|
||||
{
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using CommunityToolkit.WinUI.Animations;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Media.Animation;
|
||||
using Snap.Hutao.Control.Animation;
|
||||
using Snap.Hutao.Control.Theme;
|
||||
using Snap.Hutao.Service.BackgroundImage;
|
||||
|
||||
namespace Snap.Hutao.ViewModel;
|
||||
|
||||
[ConstructorGenerated]
|
||||
[Injection(InjectAs.Singleton)]
|
||||
internal sealed partial class MainViewModel : Abstraction.ViewModel
|
||||
{
|
||||
private readonly IBackgroundImageService backgroundImageService;
|
||||
private readonly ITaskContext taskContext;
|
||||
|
||||
private BackgroundImage? previousBackgroundImage;
|
||||
|
||||
[Command("UpdateBackgroundCommand")]
|
||||
private async Task UpdateBackgroundAsync(Image presenter)
|
||||
{
|
||||
(bool isOk, BackgroundImage backgroundImage) = await backgroundImageService.GetNextBackgroundImageAsync(previousBackgroundImage).ConfigureAwait(false);
|
||||
|
||||
if (isOk)
|
||||
{
|
||||
previousBackgroundImage = backgroundImage;
|
||||
await taskContext.SwitchToMainThreadAsync();
|
||||
|
||||
await AnimationBuilder
|
||||
.Create()
|
||||
.Opacity(
|
||||
to: 0D,
|
||||
duration: ControlAnimationConstants.ImageOpacityFadeInOut,
|
||||
easingType: EasingType.Quartic,
|
||||
easingMode: EasingMode.EaseInOut)
|
||||
.StartAsync(presenter)
|
||||
.ConfigureAwait(true);
|
||||
|
||||
presenter.Source = backgroundImage.ImageSource;
|
||||
double targetOpacity = ThemeHelper.IsDarkMode(presenter.ActualTheme) ? 1 - backgroundImage.Luminance : backgroundImage.Luminance;
|
||||
|
||||
await AnimationBuilder
|
||||
.Create()
|
||||
.Opacity(
|
||||
to: targetOpacity,
|
||||
duration: ControlAnimationConstants.ImageOpacityFadeInOut,
|
||||
easingType: EasingType.Quartic,
|
||||
easingMode: EasingMode.EaseInOut)
|
||||
.StartAsync(presenter)
|
||||
.ConfigureAwait(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,6 @@ using Snap.Hutao.Factory.ContentDialog;
|
||||
using Snap.Hutao.Factory.Picker;
|
||||
using Snap.Hutao.Model;
|
||||
using Snap.Hutao.Service;
|
||||
using Snap.Hutao.Service.BackgroundImage;
|
||||
using Snap.Hutao.Service.GachaLog.QueryProvider;
|
||||
using Snap.Hutao.Service.Game;
|
||||
using Snap.Hutao.Service.Hutao;
|
||||
@@ -41,7 +40,6 @@ internal sealed partial class SettingViewModel : Abstraction.ViewModel
|
||||
|
||||
private readonly IFileSystemPickerInteraction fileSystemPickerInteraction;
|
||||
private readonly HutaoPassportViewModel hutaoPassportViewModel;
|
||||
private readonly BackgroundImageOptions backgroundImageOptions;
|
||||
private readonly IContentDialogFactory contentDialogFactory;
|
||||
private readonly INavigationService navigationService;
|
||||
private readonly IShellLinkInterop shellLinkInterop;
|
||||
@@ -56,7 +54,6 @@ internal sealed partial class SettingViewModel : Abstraction.ViewModel
|
||||
private readonly AppOptions appOptions;
|
||||
|
||||
private NameValue<BackdropType>? selectedBackdropType;
|
||||
private NameValue<BackgroundImageType>? selectedBackgroundImageType;
|
||||
private NameValue<CultureInfo>? selectedCulture;
|
||||
private NameValue<Region>? selectedRegion;
|
||||
private FolderViewModel? cacheFolderView;
|
||||
@@ -76,8 +73,6 @@ internal sealed partial class SettingViewModel : Abstraction.ViewModel
|
||||
|
||||
public LaunchOptions LaunchOptions { get => launchOptions; }
|
||||
|
||||
public BackgroundImageOptions BackgroundImageOptions { get => backgroundImageOptions; }
|
||||
|
||||
public HutaoPassportViewModel Passport { get => hutaoPassportViewModel; }
|
||||
|
||||
public NameValue<BackdropType>? SelectedBackdropType
|
||||
@@ -92,18 +87,6 @@ internal sealed partial class SettingViewModel : Abstraction.ViewModel
|
||||
}
|
||||
}
|
||||
|
||||
public NameValue<BackgroundImageType>? SelectedBackgroundImageType
|
||||
{
|
||||
get => selectedBackgroundImageType ??= AppOptions.BackgroundImageTypes.Single(t => t.Value == AppOptions.BackgroundImageType);
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref selectedBackgroundImageType, value) && value is not null)
|
||||
{
|
||||
AppOptions.BackgroundImageType = value.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public NameValue<CultureInfo>? SelectedCulture
|
||||
{
|
||||
get => selectedCulture ??= CultureOptions.GetCurrentCultureForSelectionOrDefault();
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
// 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 Uri 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,9 +10,8 @@ namespace Snap.Hutao.Web;
|
||||
/// 胡桃 API 端点
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
[SuppressMessage("", "SA1124")]
|
||||
[SuppressMessage("", "SA1201")]
|
||||
[SuppressMessage("", "SA1203")]
|
||||
[SuppressMessage("", "SA1124")]
|
||||
internal static class HutaoEndpoints
|
||||
{
|
||||
#region HomaAPI
|
||||
@@ -272,15 +271,6 @@ internal static class HutaoEndpoints
|
||||
}
|
||||
#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
|
||||
|
||||
private const string ApiSnapGenshin = "https://api.snapgenshin.com";
|
||||
|
||||
Reference in New Issue
Block a user