mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
refactor wiki avatar page
This commit is contained in:
@@ -45,12 +45,19 @@ public partial class App : Application
|
||||
public static Window? Window { get => window; set => window = value; }
|
||||
|
||||
/// <inheritdoc cref="Application"/>
|
||||
public static new App Current => (App)Application.Current;
|
||||
public static new App Current
|
||||
{
|
||||
get => (App)Application.Current;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <inheritdoc cref="Windows.Storage.ApplicationData.Current"/>
|
||||
/// </summary>
|
||||
public static Windows.Storage.ApplicationData AppData => Windows.Storage.ApplicationData.Current;
|
||||
[SuppressMessage("", "CA1822")]
|
||||
public Windows.Storage.ApplicationData AppData
|
||||
{
|
||||
get => Windows.Storage.ApplicationData.Current;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when the application is launched.
|
||||
@@ -60,12 +67,13 @@ public partial class App : Application
|
||||
protected override async void OnLaunched(LaunchActivatedEventArgs args)
|
||||
{
|
||||
AppActivationArguments activatedEventArgs = AppInstance.GetCurrent().GetActivatedEventArgs();
|
||||
AppInstance mainInstance = AppInstance.FindOrRegisterForKey("main");
|
||||
AppInstance firstInstance = AppInstance.FindOrRegisterForKey("main");
|
||||
firstInstance.Activated += OnActivated;
|
||||
|
||||
if (!mainInstance.IsCurrent)
|
||||
if (!firstInstance.IsCurrent)
|
||||
{
|
||||
// Redirect the activation (and args) to the "main" instance, and exit.
|
||||
await mainInstance.RedirectActivationToAsync(activatedEventArgs);
|
||||
await firstInstance.RedirectActivationToAsync(activatedEventArgs);
|
||||
Process.GetCurrentProcess().Kill();
|
||||
}
|
||||
else
|
||||
@@ -73,11 +81,6 @@ public partial class App : Application
|
||||
Window = Ioc.Default.GetRequiredService<MainWindow>();
|
||||
Window.Activate();
|
||||
|
||||
if (activatedEventArgs.TryGetProtocolActivatedUri(out Uri? uri))
|
||||
{
|
||||
Ioc.Default.GetRequiredService<IInfoBarService>().Information(uri.ToString());
|
||||
}
|
||||
|
||||
logger.LogInformation(EventIds.CommonLog, "Cache folder : {folder}", AppData.TemporaryFolder.Path);
|
||||
|
||||
Ioc.Default
|
||||
@@ -117,6 +120,14 @@ public partial class App : Application
|
||||
logger.LogError(EventIds.UnhandledException, e.Exception, "未经处理的异常");
|
||||
}
|
||||
|
||||
private void OnActivated(object? sender, AppActivationArguments args)
|
||||
{
|
||||
if (args.TryGetProtocolActivatedUri(out Uri? uri))
|
||||
{
|
||||
Ioc.Default.GetRequiredService<IInfoBarService>().Information(uri.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
private void XamlBindingFailed(object sender, BindingFailedEventArgs e)
|
||||
{
|
||||
logger.LogCritical(EventIds.XamlBindingError, "XAML绑定失败: {message}", e.Message);
|
||||
|
||||
@@ -31,6 +31,7 @@ public class CachedImage : ImageEx
|
||||
|
||||
try
|
||||
{
|
||||
Verify.Operation(imageUri.Host != string.Empty, "可能是空绑定产生的 [ms-appx:///]");
|
||||
StorageFile file = await imageCache.GetFileFromCacheAsync(imageUri);
|
||||
|
||||
// check token state to determine whether the operation should be canceled.
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Snap.Hutao.Core.Logging;
|
||||
using Snap.Hutao.Extension;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@@ -236,25 +237,17 @@ public abstract class CacheBase<T>
|
||||
return;
|
||||
}
|
||||
|
||||
await cacheFolderSemaphore.WaitAsync().ConfigureAwait(false);
|
||||
|
||||
baseFolder ??= ApplicationData.Current.TemporaryFolder;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(cacheFolderName))
|
||||
using (await cacheFolderSemaphore.EnterAsync().ConfigureAwait(false))
|
||||
{
|
||||
cacheFolderName = GetType().Name;
|
||||
}
|
||||
baseFolder ??= ApplicationData.Current.TemporaryFolder;
|
||||
|
||||
try
|
||||
{
|
||||
cacheFolder = await baseFolder
|
||||
.CreateFolderAsync(cacheFolderName, CreationCollisionOption.OpenIfExists)
|
||||
.AsTask()
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
finally
|
||||
{
|
||||
cacheFolderSemaphore.Release();
|
||||
if (string.IsNullOrWhiteSpace(cacheFolderName))
|
||||
{
|
||||
cacheFolderName = GetType().Name;
|
||||
}
|
||||
|
||||
cacheFolder = await baseFolder.CreateFolderAsync(cacheFolderName, CreationCollisionOption.OpenIfExists)
|
||||
.AsTask().ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.UI.Xaml.Media.Imaging;
|
||||
using System.Collections.Generic;
|
||||
using Windows.Storage;
|
||||
|
||||
|
||||
@@ -13,11 +13,12 @@ namespace Snap.Hutao.Core.Logging;
|
||||
/// The provider for the <see cref="DebugLogger"/>.
|
||||
/// </summary>
|
||||
[ProviderAlias("Database")]
|
||||
public class DatebaseLoggerProvider : ILoggerProvider
|
||||
public sealed class DatebaseLoggerProvider : ILoggerProvider
|
||||
{
|
||||
private static readonly object LogDbContextLock = new();
|
||||
|
||||
// the provider is created per logger, we don't want to create to much
|
||||
private static volatile LogDbContext? logDbContext;
|
||||
private static readonly object logDbContextLock = new();
|
||||
|
||||
private static LogDbContext LogDbContext
|
||||
{
|
||||
@@ -25,7 +26,7 @@ public class DatebaseLoggerProvider : ILoggerProvider
|
||||
{
|
||||
if (logDbContext == null)
|
||||
{
|
||||
lock (logDbContextLock)
|
||||
lock (LogDbContextLock)
|
||||
{
|
||||
// prevent re-entry call
|
||||
if (logDbContext == null)
|
||||
@@ -34,7 +35,7 @@ public class DatebaseLoggerProvider : ILoggerProvider
|
||||
logDbContext = LogDbContext.Create($"Data Source={myDocument.Locate("Log.db")}");
|
||||
if (logDbContext.Database.GetPendingMigrations().Any())
|
||||
{
|
||||
Debug.WriteLine("Performing LogDbContext Migrations");
|
||||
Debug.WriteLine("[Debug] Performing LogDbContext Migrations");
|
||||
logDbContext.Database.Migrate();
|
||||
}
|
||||
|
||||
@@ -51,11 +52,12 @@ public class DatebaseLoggerProvider : ILoggerProvider
|
||||
/// <inheritdoc/>
|
||||
public ILogger CreateLogger(string name)
|
||||
{
|
||||
return new DatebaseLogger(name, LogDbContext, logDbContextLock);
|
||||
return new DatebaseLogger(name, LogDbContext, LogDbContextLock);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Dispose()
|
||||
{
|
||||
LogDbContext.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Extension;
|
||||
|
||||
/// <summary>
|
||||
/// 信号量扩展
|
||||
/// </summary>
|
||||
public static class SemaphoreSlimExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 异步进入信号量
|
||||
/// </summary>
|
||||
/// <param name="semaphoreSlim">信号量</param>
|
||||
/// <returns>可释放的对象,用于释放信号量</returns>
|
||||
public static async Task<IDisposable> EnterAsync(this SemaphoreSlim semaphoreSlim)
|
||||
{
|
||||
await semaphoreSlim.WaitAsync();
|
||||
return new SemaphoreSlimReleaser(semaphoreSlim);
|
||||
}
|
||||
|
||||
private struct SemaphoreSlimReleaser : IDisposable
|
||||
{
|
||||
private readonly SemaphoreSlim semaphoreSlim;
|
||||
|
||||
public SemaphoreSlimReleaser(SemaphoreSlim semaphoreSlim)
|
||||
{
|
||||
this.semaphoreSlim = semaphoreSlim;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
semaphoreSlim.Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -51,7 +51,7 @@ internal static class IocConfiguration
|
||||
{
|
||||
if (context.Database.GetPendingMigrations().Any())
|
||||
{
|
||||
Debug.WriteLine("Performing AppDbContext Migrations");
|
||||
Debug.WriteLine("[Debug] Performing AppDbContext Migrations");
|
||||
context.Database.Migrate();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Snap.Hutao.Core.Caching;
|
||||
using Snap.Hutao.Service.Metadata;
|
||||
using Snap.Hutao.Web.Enka;
|
||||
using Snap.Hutao.Web.Hoyolab.Bbs.User;
|
||||
@@ -29,7 +30,7 @@ internal static class IocHttpClientConfiguration
|
||||
{
|
||||
// services
|
||||
services.AddHttpClient<MetadataService>(DefaultConfiguration);
|
||||
// services.AddHttpClient<ImageCache>(DefaultConfiguration);
|
||||
services.AddHttpClient<ImageCache>(DefaultConfiguration).ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler() { MaxConnectionsPerServer = 20 });
|
||||
|
||||
// normal clients
|
||||
services.AddHttpClient<AnnouncementClient>(DefaultConfiguration);
|
||||
|
||||
@@ -7,7 +7,6 @@ using Snap.Hutao.Control.HostBackdrop;
|
||||
using Snap.Hutao.Core.Logging;
|
||||
using Snap.Hutao.Core.Setting;
|
||||
using Snap.Hutao.Core.Win32;
|
||||
using System.Runtime.InteropServices;
|
||||
using WinRT.Interop;
|
||||
|
||||
namespace Snap.Hutao;
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
namespace Snap.Hutao.Model.Metadata.Annotation;
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Model.Metadata.Annotation;
|
||||
|
||||
/// <summary>
|
||||
/// 格式化方法
|
||||
|
||||
@@ -13,10 +13,10 @@ public class DescParam
|
||||
/// <summary>
|
||||
/// 描述
|
||||
/// </summary>
|
||||
public IEnumerable<string> Descriptions { get; set; } = default!;
|
||||
public IList<string> Descriptions { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 参数
|
||||
/// </summary>
|
||||
public IEnumerable<LevelParam<int, double>> Parameters { get; set; } = default!;
|
||||
}
|
||||
public IList<LevelParam<int, double>> Parameters { get; set; } = default!;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Snap.Hutao.Model.Metadata.Avatar;
|
||||
|
||||
@@ -13,7 +14,7 @@ public class SkillDepot
|
||||
/// <summary>
|
||||
/// 技能天赋
|
||||
/// </summary>
|
||||
public IEnumerable<ProudableSkill> Skills { get; set; } = default!;
|
||||
public IList<ProudableSkill> Skills { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 大招
|
||||
@@ -23,10 +24,30 @@ public class SkillDepot
|
||||
/// <summary>
|
||||
/// 固有天赋
|
||||
/// </summary>
|
||||
public IEnumerable<ProudableSkill> Inherents { get; set; } = default!;
|
||||
public IList<ProudableSkill> Inherents { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 全部天赋
|
||||
/// </summary>
|
||||
public IList<ProudableSkill> CompositeSkills => GetCompositeSkills().ToList();
|
||||
|
||||
/// <summary>
|
||||
/// 命之座
|
||||
/// </summary>
|
||||
public IEnumerable<SkillBase> Talents { get; set; } = default!;
|
||||
public IList<SkillBase> Talents { get; set; } = default!;
|
||||
|
||||
private IEnumerable<ProudableSkill> GetCompositeSkills()
|
||||
{
|
||||
foreach (ProudableSkill skill in Skills)
|
||||
{
|
||||
yield return skill;
|
||||
}
|
||||
|
||||
yield return EnergySkill;
|
||||
|
||||
foreach (ProudableSkill skill in Inherents)
|
||||
{
|
||||
yield return skill;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,4 +23,4 @@ internal class AvatarIconConverter : IValueConverter
|
||||
{
|
||||
throw Must.NeverHappen();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,25 +17,26 @@ internal class DescParamDescriptor : IValueConverter
|
||||
/// <inheritdoc/>
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
DescParam descParam = (DescParam)value;
|
||||
IEnumerable<DescFormat> parsedDescriptions = descParam.Descriptions.Select(desc =>
|
||||
{
|
||||
string[] parts = desc.Split('|', 2);
|
||||
return new DescFormat(parts[0], parts[1]);
|
||||
});
|
||||
DescParam rawDescParam = (DescParam)value;
|
||||
|
||||
IList<IList<string>> parameters = descParam.Parameters
|
||||
.Select(param =>
|
||||
// Spilt rawDesc into two parts: desc and format
|
||||
IList<DescFormat> parsedDescriptions = rawDescParam.Descriptions
|
||||
.Select(desc =>
|
||||
{
|
||||
IList<string> parameters = GetFormattedParameters(parsedDescriptions, param.Parameters);
|
||||
parameters.Insert(0, param.Level.ToString());
|
||||
return parameters;
|
||||
string[] parts = desc.Split('|', 2);
|
||||
return new DescFormat(parts[0], parts[1]);
|
||||
})
|
||||
.ToList();
|
||||
|
||||
List<string> descList = parsedDescriptions.Select(p => p.Description).ToList();
|
||||
descList.Insert(0, "等级");
|
||||
return new DescParamInternal(descList, parameters);
|
||||
IList<LevelParam<string, ParameterInfo>> parameters = rawDescParam.Parameters
|
||||
.Select(param =>
|
||||
{
|
||||
IList<ParameterInfo> parameters = GetFormattedParameters(parsedDescriptions, param.Parameters);
|
||||
return new LevelParam<string, ParameterInfo>() { Level = param.Level.ToString(), Parameters = parameters };
|
||||
})
|
||||
.ToList();
|
||||
|
||||
return parameters;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -44,6 +45,22 @@ internal class DescParamDescriptor : IValueConverter
|
||||
throw Must.NeverHappen();
|
||||
}
|
||||
|
||||
private static IList<ParameterInfo> GetFormattedParameters(IList<DescFormat> formats, IList<double> param)
|
||||
{
|
||||
List<ParameterInfo> results = new();
|
||||
|
||||
for (int index = 0; index < formats.Count; index++)
|
||||
{
|
||||
DescFormat descFormat = formats[index];
|
||||
|
||||
string format = descFormat.Format;
|
||||
string resultFormatted = Regex.Replace(format, @"{param\d+.*?}", match => EvaluateMatch(match, param));
|
||||
results.Add(new ParameterInfo { Description = descFormat.Description, Parameter = resultFormatted });
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
private static string EvaluateMatch(Match match, IList<double> param)
|
||||
{
|
||||
if (match.Success)
|
||||
@@ -74,19 +91,6 @@ internal class DescParamDescriptor : IValueConverter
|
||||
}
|
||||
}
|
||||
|
||||
private IList<string> GetFormattedParameters(IEnumerable<DescFormat> formats, IList<double> param)
|
||||
{
|
||||
List<string> results = new();
|
||||
foreach (DescFormat descFormat in formats)
|
||||
{
|
||||
string format = descFormat.Format;
|
||||
string resultFormatted = Regex.Replace(format, @"{param\d+.*?}", match => EvaluateMatch(match, param));
|
||||
results.Add(resultFormatted);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
private class DescFormat
|
||||
{
|
||||
public DescFormat(string description, string format)
|
||||
@@ -99,17 +103,4 @@ internal class DescParamDescriptor : IValueConverter
|
||||
|
||||
public string Format { get; set; }
|
||||
}
|
||||
|
||||
private class DescParamInternal
|
||||
{
|
||||
public DescParamInternal(IList<string> descriptions, IList<IList<string>> parameters)
|
||||
{
|
||||
Descriptions = descriptions;
|
||||
Parameters = parameters;
|
||||
}
|
||||
|
||||
public IList<string> Descriptions { get; set; }
|
||||
|
||||
public IList<IList<string>> Parameters { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
using Snap.Hutao.Extension;
|
||||
using Snap.Hutao.Model.Intrinsic;
|
||||
|
||||
namespace Snap.Hutao.Model.Metadata.Converter;
|
||||
|
||||
/// <summary>
|
||||
/// 战斗属性转换器
|
||||
/// </summary>
|
||||
internal class FightPropertyConverter : IValueConverter
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
return ((FightProperty)value).GetDescription();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
throw Must.NeverHappen();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
using Snap.Hutao.Extension;
|
||||
using Snap.Hutao.Model.Intrinsic;
|
||||
using Snap.Hutao.Model.Metadata.Annotation;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Snap.Hutao.Model.Metadata.Converter;
|
||||
|
||||
/// <summary>
|
||||
/// 基础属性翻译器
|
||||
/// </summary>
|
||||
internal class PropertyInfoDescriptor : IValueConverter
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
PropertyInfo rawDescParam = (PropertyInfo)value;
|
||||
|
||||
IList<LevelParam<string, ParameterInfo>> parameters = rawDescParam.Parameters
|
||||
.Select(param =>
|
||||
{
|
||||
IList<ParameterInfo> parameters = GetFormattedParameters(param.Parameters, rawDescParam.Properties);
|
||||
return new LevelParam<string, ParameterInfo>() { Level = param.Level, Parameters = parameters };
|
||||
})
|
||||
.ToList();
|
||||
|
||||
return parameters;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
throw Must.NeverHappen();
|
||||
}
|
||||
|
||||
private static IList<ParameterInfo> GetFormattedParameters(IList<double> parameters, IList<FightProperty> properties)
|
||||
{
|
||||
List<ParameterInfo> results = new();
|
||||
|
||||
for (int index = 0; index < parameters.Count; index++)
|
||||
{
|
||||
double param = parameters[index];
|
||||
FormatMethod method = properties[index].GetFormat();
|
||||
|
||||
string valueFormatted = method switch
|
||||
{
|
||||
FormatMethod.Integer => Math.Round((double)param, MidpointRounding.AwayFromZero).ToString(),
|
||||
FormatMethod.Percent => string.Format("{0:P1}", param),
|
||||
_ => param.ToString(),
|
||||
};
|
||||
|
||||
results.Add(new ParameterInfo { Description = properties[index].GetDescription(), Parameter = valueFormatted });
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
}
|
||||
@@ -2,27 +2,30 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
using Snap.Hutao.Model.Intrinsic;
|
||||
using Snap.Hutao.Model.Metadata.Annotation;
|
||||
|
||||
namespace Snap.Hutao.Model.Metadata.Converter;
|
||||
|
||||
/// <summary>
|
||||
/// 战斗属性数值格式化器
|
||||
/// 技能图标转换器
|
||||
/// </summary>
|
||||
internal class FightPropertyValueFormatter : IValueConverter
|
||||
internal class SkillIconConverter : IValueConverter
|
||||
{
|
||||
private const string SkillUrl = "https://static.snapgenshin.com/Skill/{0}.png";
|
||||
private const string TalentUrl = "https://static.snapgenshin.com/Talent/{0}.png";
|
||||
|
||||
/// <inheritdoc/>
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
FormatMethod method = ((FightProperty)parameter).GetFormat();
|
||||
string target = (string)value;
|
||||
|
||||
return method switch
|
||||
if (target.StartsWith("UI_Talent_"))
|
||||
{
|
||||
FormatMethod.Integer => Math.Round((double)value, MidpointRounding.AwayFromZero),
|
||||
FormatMethod.Percent => string.Format("{0:P1}", value),
|
||||
_ => value,
|
||||
};
|
||||
return new Uri(string.Format(TalentUrl, target));
|
||||
}
|
||||
else
|
||||
{
|
||||
return new Uri(string.Format(SkillUrl, target));
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
21
src/Snap.Hutao/Snap.Hutao/Model/Metadata/ParameterInfo.cs
Normal file
21
src/Snap.Hutao/Snap.Hutao/Model/Metadata/ParameterInfo.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Model.Metadata;
|
||||
|
||||
/// <summary>
|
||||
/// 包装一个描述参数
|
||||
/// 专用于绑定
|
||||
/// </summary>
|
||||
public class ParameterInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 描述
|
||||
/// </summary>
|
||||
public string Description { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 参数
|
||||
/// </summary>
|
||||
public string Parameter { get; set; } = default!;
|
||||
}
|
||||
@@ -14,10 +14,10 @@ public class PropertyInfo
|
||||
/// <summary>
|
||||
/// 提升的属性
|
||||
/// </summary>
|
||||
public IEnumerable<FightProperty> Properties { get; set; } = default!;
|
||||
public IList<FightProperty> Properties { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 参数
|
||||
/// </summary>
|
||||
public IEnumerable<LevelParam<string, double>> Parameters { get; set; } = default!;
|
||||
public IList<LevelParam<string, double>> Parameters { get; set; } = default!;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<Identity
|
||||
Name="7f0db578-026f-4e0b-a75b-d5d06bb0a74d"
|
||||
Publisher="CN=DGP Studio"
|
||||
Version="1.0.16.0" />
|
||||
Version="1.0.18.0" />
|
||||
|
||||
<Properties>
|
||||
<DisplayName>胡桃</DisplayName>
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
{
|
||||
"profiles": {
|
||||
"Snap.Hutao (Package)": {
|
||||
"commandName": "MsixPackage"
|
||||
"commandName": "MsixPackage",
|
||||
"nativeDebugging": false
|
||||
},
|
||||
"Snap.Hutao (Unpackaged)": {
|
||||
"commandName": "Project"
|
||||
|
||||
@@ -34,7 +34,9 @@
|
||||
<None Remove="Resource\Icon\UI_Icon_Achievement.png" />
|
||||
<None Remove="Resource\Segoe Fluent Icons.ttf" />
|
||||
<None Remove="stylecop.json" />
|
||||
<None Remove="View\Control\DescParamComboBox.xaml" />
|
||||
<None Remove="View\Control\ItemIcon.xaml" />
|
||||
<None Remove="View\Control\SkillPivot.xaml" />
|
||||
<None Remove="View\Dialog\UserDialog.xaml" />
|
||||
<None Remove="View\MainView.xaml" />
|
||||
<None Remove="View\Page\AchievementPage.xaml" />
|
||||
@@ -104,6 +106,16 @@
|
||||
<ItemGroup>
|
||||
<None Include="..\.editorconfig" Link=".editorconfig" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="View\Control\DescParamComboBox.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="View\Control\SkillPivot.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="View\UserView.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
<UserControl
|
||||
x:Class="Snap.Hutao.View.Control.DescParamComboBox"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:sc="using:SettingsUI.Controls"
|
||||
mc:Ignorable="d">
|
||||
<UserControl.Resources>
|
||||
<Style TargetType="ComboBox" BasedOn="{StaticResource DefaultComboBoxStyle}">
|
||||
<Setter Property="MinWidth" Value="120"/>
|
||||
</Style>
|
||||
</UserControl.Resources>
|
||||
<StackPanel>
|
||||
<sc:SettingsGroup VerticalAlignment="Top" Margin="0,-64,0,0">
|
||||
<sc:Setting Header="等级" Padding="12,0,6,0">
|
||||
<sc:Setting.ActionContent>
|
||||
<ComboBox
|
||||
x:Name="ItemHost"
|
||||
SelectionChanged="ItemHostSelectionChanged">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Level}"/>
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
</sc:Setting.ActionContent>
|
||||
</sc:Setting>
|
||||
</sc:SettingsGroup>
|
||||
|
||||
<ItemsControl
|
||||
x:Name="DetailsHost"
|
||||
VerticalAlignment="Top">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<sc:Setting Margin="0,2,0,0" Header="{Binding Description}" Padding="12,0">
|
||||
<sc:Setting.ActionContent>
|
||||
<TextBlock Text="{Binding Parameter}"/>
|
||||
</sc:Setting.ActionContent>
|
||||
</sc:Setting>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,61 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Snap.Hutao.Core;
|
||||
using Snap.Hutao.Model.Metadata;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Snap.Hutao.View.Control;
|
||||
|
||||
/// <summary>
|
||||
/// 描述参数组合框
|
||||
/// </summary>
|
||||
public sealed partial class DescParamComboBox : UserControl
|
||||
{
|
||||
private static readonly DependencyProperty SourceProperty = Property<DescParamComboBox>
|
||||
.Depend<IList<LevelParam<string, ParameterInfo>>>(nameof(Source), default!, OnSourceChanged);
|
||||
|
||||
/// <summary>
|
||||
/// 构造一个新的描述参数组合框
|
||||
/// </summary>
|
||||
public DescParamComboBox()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 技能列表
|
||||
/// </summary>
|
||||
public IList<LevelParam<string, ParameterInfo>> Source
|
||||
{
|
||||
get { return (IList<LevelParam<string, ParameterInfo>>)GetValue(SourceProperty); }
|
||||
set { SetValue(SourceProperty, value); }
|
||||
}
|
||||
|
||||
private static void OnSourceChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
|
||||
{
|
||||
// Some of the {x:Bind} feature is not working properly,
|
||||
// so we use this simple code behind approach to achieve selection function
|
||||
if (sender is DescParamComboBox descParamComboBox)
|
||||
{
|
||||
if (args.NewValue != args.OldValue && args.NewValue is IList<LevelParam<string, ParameterInfo>> list)
|
||||
{
|
||||
descParamComboBox.ItemHost.ItemsSource = list;
|
||||
descParamComboBox.ItemHost.SelectedIndex = 0;
|
||||
|
||||
descParamComboBox.DetailsHost.ItemsSource = list.FirstOrDefault()?.Parameters;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ItemHostSelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (sender is ComboBox comboBox && comboBox.SelectedIndex >= 0)
|
||||
{
|
||||
DetailsHost.ItemsSource = Source[comboBox.SelectedIndex]?.Parameters;
|
||||
}
|
||||
}
|
||||
}
|
||||
48
src/Snap.Hutao/Snap.Hutao/View/Control/SkillPivot.xaml
Normal file
48
src/Snap.Hutao/Snap.Hutao/View/Control/SkillPivot.xaml
Normal file
@@ -0,0 +1,48 @@
|
||||
<UserControl
|
||||
x:Class="Snap.Hutao.View.Control.SkillPivot"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:cwuc="using:CommunityToolkit.WinUI.UI.Controls"
|
||||
xmlns:shci="using:Snap.Hutao.Control.Image"
|
||||
xmlns:shct="using:Snap.Hutao.Control.Text"
|
||||
xmlns:shmmc="using:Snap.Hutao.Model.Metadata.Converter"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<UserControl.Resources>
|
||||
<shmmc:SkillIconConverter x:Key="SkillIconConverter"/>
|
||||
<shmmc:DescParamDescriptor x:Key="DescParamDescriptor"/>
|
||||
|
||||
<Thickness x:Key="PivotHeaderItemMargin">0,0,16,0</Thickness>
|
||||
<Thickness x:Key="PivotItemMargin">0</Thickness>
|
||||
|
||||
<Style TargetType="PivotHeaderItem" BasedOn="{StaticResource DefaultPivotHeaderItemStyle}">
|
||||
<Setter Property="Height" Value="80"/>
|
||||
</Style>
|
||||
</UserControl.Resources>
|
||||
|
||||
<Pivot
|
||||
x:Name="ItemHost"
|
||||
ItemsSource="{x:Bind Skills,Mode=OneWay}"
|
||||
SelectedItem="{x:Bind Selected}"
|
||||
ItemTemplate="{x:Bind ItemTemplate}"
|
||||
Style="{StaticResource DefaultPivotStyle}"
|
||||
>
|
||||
<Pivot.HeaderTemplate>
|
||||
<DataTemplate>
|
||||
<StackPanel>
|
||||
<shci:MonoChrome
|
||||
Width="36"
|
||||
Height="36"
|
||||
Source="{Binding Icon,Converter={StaticResource SkillIconConverter}}"/>
|
||||
<TextBlock
|
||||
Margin="0,8,0,0"
|
||||
Text="{Binding Name}"
|
||||
HorizontalAlignment="Center"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"/>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</Pivot.HeaderTemplate>
|
||||
</Pivot>
|
||||
</UserControl>
|
||||
54
src/Snap.Hutao/Snap.Hutao/View/Control/SkillPivot.xaml.cs
Normal file
54
src/Snap.Hutao/Snap.Hutao/View/Control/SkillPivot.xaml.cs
Normal file
@@ -0,0 +1,54 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Snap.Hutao.Core;
|
||||
using System.Collections;
|
||||
|
||||
namespace Snap.Hutao.View.Control;
|
||||
|
||||
/// <summary>
|
||||
/// 技能展柜
|
||||
/// </summary>
|
||||
public sealed partial class SkillPivot : UserControl
|
||||
{
|
||||
private static readonly DependencyProperty SkillsProperty = Property<SkillPivot>.Depend<IList>(nameof(Skills));
|
||||
private static readonly DependencyProperty SelectedProperty = Property<SkillPivot>.Depend<object>(nameof(Selected));
|
||||
private static readonly DependencyProperty ItemTemplateProperty = Property<SkillPivot>.Depend<DataTemplate>(nameof(ItemTemplate));
|
||||
|
||||
/// <summary>
|
||||
/// 创建一个新的技能展柜
|
||||
/// </summary>
|
||||
public SkillPivot()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 技能列表
|
||||
/// </summary>
|
||||
public IList Skills
|
||||
{
|
||||
get { return (IList)GetValue(SkillsProperty); }
|
||||
set { SetValue(SkillsProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 选中的项
|
||||
/// </summary>
|
||||
public object Selected
|
||||
{
|
||||
get { return GetValue(SelectedProperty); }
|
||||
set { SetValue(SelectedProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 项目模板
|
||||
/// </summary>
|
||||
public DataTemplate ItemTemplate
|
||||
{
|
||||
get { return (DataTemplate)GetValue(ItemTemplateProperty); }
|
||||
set { SetValue(ItemTemplateProperty, value); }
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,7 @@ public sealed partial class MainView : UserControl
|
||||
|
||||
navigationService = Ioc.Default.GetRequiredService<INavigationService>();
|
||||
navigationService.Initialize(NavView, ContentFrame);
|
||||
|
||||
navigationService.Navigate<AnnouncementPage>(INavigationAwaiter.Default, true);
|
||||
}
|
||||
}
|
||||
@@ -4,9 +4,10 @@
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Navigation;
|
||||
using Microsoft.VisualStudio.Threading;
|
||||
using Snap.Hutao.Core;
|
||||
using Microsoft.Web.WebView2.Core;
|
||||
using Snap.Hutao.Extension;
|
||||
using Snap.Hutao.Service.Navigation;
|
||||
using Windows.System;
|
||||
|
||||
namespace Snap.Hutao.View.Page;
|
||||
|
||||
@@ -55,31 +56,7 @@ openInWebview: function(url){ location.href = url }}";
|
||||
}
|
||||
}
|
||||
|
||||
private async Task LoadAnnouncementAsync(INavigationData data)
|
||||
{
|
||||
try
|
||||
{
|
||||
await WebView.EnsureCoreWebView2Async();
|
||||
|
||||
await WebView.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync(MihoyoSDKDefinition);
|
||||
WebView.CoreWebView2.WebMessageReceived += (_, e) => Browser.Open(e.TryGetWebMessageAsString());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
data.NotifyNavigationException(ex);
|
||||
return;
|
||||
}
|
||||
|
||||
WebView.NavigateToString(ReplaceForeground(targetContent, ActualTheme));
|
||||
data.NotifyNavigationCompleted();
|
||||
}
|
||||
|
||||
private void PageActualThemeChanged(FrameworkElement sender, object args)
|
||||
{
|
||||
WebView.NavigateToString(ReplaceForeground(targetContent, ActualTheme));
|
||||
}
|
||||
|
||||
private string? ReplaceForeground(string? rawContent, ElementTheme theme)
|
||||
private static string? ReplaceForeground(string? rawContent, ElementTheme theme)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(rawContent))
|
||||
{
|
||||
@@ -105,4 +82,39 @@ openInWebview: function(url){ location.href = url }}";
|
||||
// wrap a default color body around
|
||||
return $@"<body style=""{(isDarkMode ? LightColor1 : DarkColor1)}"">{rawContent}</body>";
|
||||
}
|
||||
|
||||
private async Task LoadAnnouncementAsync(INavigationData data)
|
||||
{
|
||||
try
|
||||
{
|
||||
await WebView.EnsureCoreWebView2Async();
|
||||
|
||||
await WebView.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync(MihoyoSDKDefinition);
|
||||
WebView.CoreWebView2.WebMessageReceived += OnWebMessageReceived;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
data.NotifyNavigationException(ex);
|
||||
return;
|
||||
}
|
||||
|
||||
WebView.NavigateToString(ReplaceForeground(targetContent, ActualTheme));
|
||||
data.NotifyNavigationCompleted();
|
||||
}
|
||||
|
||||
private void PageActualThemeChanged(FrameworkElement sender, object args)
|
||||
{
|
||||
WebView.NavigateToString(ReplaceForeground(targetContent, ActualTheme));
|
||||
}
|
||||
|
||||
[SuppressMessage("", "VSTHRD100")]
|
||||
private async void OnWebMessageReceived(CoreWebView2 coreWebView2, CoreWebView2WebMessageReceivedEventArgs args)
|
||||
{
|
||||
string url = args.TryGetWebMessageAsString();
|
||||
|
||||
if (Uri.TryCreate(url, UriKind.RelativeOrAbsolute, out Uri? uri))
|
||||
{
|
||||
await Launcher.LaunchUriAsync(uri).AsTask().ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,6 @@
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:cwuc="using:CommunityToolkit.WinUI.UI.Controls"
|
||||
xmlns:mxi="using:Microsoft.Xaml.Interactivity"
|
||||
xmlns:shc="using:Snap.Hutao.Control"
|
||||
xmlns:shcb="using:Snap.Hutao.Control.Behavior"
|
||||
xmlns:shci="using:Snap.Hutao.Control.Image"
|
||||
xmlns:shct="using:Snap.Hutao.Control.Text"
|
||||
@@ -26,30 +25,14 @@
|
||||
<shmmc:WeaponTypeIconConverter x:Key="WeaponTypeIconConverter"/>
|
||||
<shmmc:AvatarNameCardPicConverter x:Key="AvatarNameCardPicConverter"/>
|
||||
|
||||
<shmmc:FightPropertyConverter x:Key="FightPropertyConverter"/>
|
||||
<shmmc:FightPropertyValueFormatter x:Key="FightPropertyValueFormatter"/>
|
||||
|
||||
<shmmc:DescParamDescriptor x:Key="DescParamDescriptor"/>
|
||||
|
||||
<shc:BindingProxy
|
||||
x:Key="FightPropertyBindingProxy"
|
||||
DataContext="{Binding Selected.Property.Properties}"/>
|
||||
<shmmc:PropertyInfoDescriptor x:Key="PropertyDescriptor"/>
|
||||
|
||||
<DataTemplate x:Key="SkillDataTemplate">
|
||||
<Expander
|
||||
Margin="16,16,0,0"
|
||||
Header="{Binding Name}"
|
||||
HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Stretch">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
<ColumnDefinition/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid Margin="0,12,0,0">
|
||||
<StackPanel Grid.Column="0">
|
||||
<shct:DescriptionTextBlock
|
||||
Grid.Column="0"
|
||||
MaxWidth="280"
|
||||
Margin="16"
|
||||
Margin="0,0,0,16"
|
||||
Description="{Binding Description}">
|
||||
<shct:DescriptionTextBlock.Resources>
|
||||
<Style
|
||||
@@ -59,87 +42,33 @@
|
||||
</Style>
|
||||
</shct:DescriptionTextBlock.Resources>
|
||||
</shct:DescriptionTextBlock>
|
||||
<ScrollViewer
|
||||
Grid.Column="1"
|
||||
VerticalScrollMode="Disabled"
|
||||
HorizontalScrollBarVisibility="Auto">
|
||||
<Grid
|
||||
Margin="16"
|
||||
DataContext="{Binding Proud,Converter={StaticResource DescParamDescriptor}}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="auto"/>
|
||||
<RowDefinition/>
|
||||
</Grid.RowDefinitions>
|
||||
<ItemsControl
|
||||
Grid.Row="0"
|
||||
ItemsSource="{Binding Descriptions}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<cwuc:UniformGrid
|
||||
ColumnSpacing="16"
|
||||
Columns="{Binding Descriptions.Count}"/>
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock
|
||||
Text="{Binding}"
|
||||
TextWrapping="NoWrap"
|
||||
TextTrimming="CharacterEllipsis"
|
||||
Style="{StaticResource BaseTextBlockStyle}"/>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
<shvc:DescParamComboBox
|
||||
Grid.Column="0"
|
||||
HorizontalAlignment="Stretch"
|
||||
Source="{Binding Proud,Converter={StaticResource DescParamDescriptor}}"/>
|
||||
|
||||
<ItemsControl
|
||||
Margin="0,16,0,0"
|
||||
Grid.Row="2"
|
||||
ItemsSource="{Binding Parameters}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<ItemsControl ItemsSource="{Binding}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<cwuc:UniformGrid
|
||||
ColumnSpacing="16"
|
||||
Columns="{Binding Count}"/>
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock
|
||||
Text="{Binding}"
|
||||
TextTrimming="CharacterEllipsis"/>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
</Expander>
|
||||
|
||||
</StackPanel>
|
||||
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate x:Key="InherentDataTemplate">
|
||||
<Expander
|
||||
Margin="16,16,0,0"
|
||||
Header="{Binding Name}"
|
||||
<DataTemplate x:Key="PropertyDataTemplate">
|
||||
<shvc:DescParamComboBox
|
||||
HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Stretch">
|
||||
<shct:DescriptionTextBlock
|
||||
Margin="16"
|
||||
Description="{Binding Description}">
|
||||
<shct:DescriptionTextBlock.Resources>
|
||||
<Style
|
||||
TargetType="TextBlock"
|
||||
BasedOn="{StaticResource BodyTextBlockStyle}">
|
||||
<Setter Property="TextWrapping" Value="Wrap"/>
|
||||
</Style>
|
||||
</shct:DescriptionTextBlock.Resources>
|
||||
</shct:DescriptionTextBlock>
|
||||
</Expander>
|
||||
Source="{Binding Property,Converter={StaticResource PropertyDescriptor}}"/>
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate x:Key="TalentDataTemplate">
|
||||
<shct:DescriptionTextBlock
|
||||
Margin="0,12,0,0"
|
||||
Description="{Binding Description}">
|
||||
<shct:DescriptionTextBlock.Resources>
|
||||
<Style TargetType="TextBlock" BasedOn="{StaticResource BodyTextBlockStyle}">
|
||||
<Setter Property="TextWrapping" Value="Wrap"/>
|
||||
</Style>
|
||||
</shct:DescriptionTextBlock.Resources>
|
||||
</shct:DescriptionTextBlock>
|
||||
</DataTemplate>
|
||||
</Page.Resources>
|
||||
|
||||
@@ -180,12 +109,13 @@
|
||||
</SplitView.Pane>
|
||||
<SplitView.Content>
|
||||
<Grid>
|
||||
<!--渐变背景-->
|
||||
<shci:Gradient
|
||||
VerticalAlignment="Top"
|
||||
Source="{Binding Selected,Converter={StaticResource AvatarNameCardPicConverter}}"/>
|
||||
|
||||
<ScrollViewer>
|
||||
<StackPanel Margin="0,0,16,16">
|
||||
<StackPanel Margin="0,0,20,16">
|
||||
<!--简介-->
|
||||
<Grid
|
||||
Margin="16,16,0,16"
|
||||
@@ -321,111 +251,34 @@
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<!--属性-->
|
||||
<Expander
|
||||
Margin="16,0,0,0"
|
||||
Header="基础数值"
|
||||
HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Stretch">
|
||||
<ScrollViewer
|
||||
VerticalScrollMode="Disabled"
|
||||
HorizontalScrollBarVisibility="Auto">
|
||||
<Grid Margin="16">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="auto"/>
|
||||
<RowDefinition/>
|
||||
</Grid.RowDefinitions>
|
||||
<cwuc:UniformGrid
|
||||
Grid.Row="0"
|
||||
Columns="5"
|
||||
ColumnSpacing="16"
|
||||
DataContext="{Binding Selected.Property}">
|
||||
<TextBlock
|
||||
Style="{StaticResource BaseTextBlockStyle}"
|
||||
TextWrapping="NoWrap"
|
||||
Text="等级"/>
|
||||
<TextBlock
|
||||
TextWrapping="NoWrap"
|
||||
Style="{StaticResource BaseTextBlockStyle}"
|
||||
Text="{Binding Properties[0], Converter={StaticResource FightPropertyConverter}}"/>
|
||||
<TextBlock
|
||||
TextWrapping="NoWrap"
|
||||
Style="{StaticResource BaseTextBlockStyle}"
|
||||
Text="{Binding Properties[1], Converter={StaticResource FightPropertyConverter}}"/>
|
||||
<TextBlock
|
||||
TextWrapping="NoWrap"
|
||||
Style="{StaticResource BaseTextBlockStyle}"
|
||||
Text="{Binding Properties[2], Converter={StaticResource FightPropertyConverter}}"/>
|
||||
<TextBlock
|
||||
TextWrapping="NoWrap"
|
||||
Style="{StaticResource BaseTextBlockStyle}"
|
||||
Text="{Binding Properties[3], Converter={StaticResource FightPropertyConverter}}"/>
|
||||
</cwuc:UniformGrid>
|
||||
<ItemsControl
|
||||
Margin="0,16,0,0"
|
||||
Grid.Row="1"
|
||||
ItemsSource="{Binding Selected.Property.Parameters}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<cwuc:UniformGrid
|
||||
Columns="5"
|
||||
ColumnSpacing="16">
|
||||
<TextBlock
|
||||
Text="{Binding Level}"/>
|
||||
<TextBlock
|
||||
Text="{Binding Parameters[0],
|
||||
Converter={StaticResource FightPropertyValueFormatter},
|
||||
ConverterParameter={Binding DataContext[0],Source={StaticResource FightPropertyBindingProxy}}}"/>
|
||||
<TextBlock
|
||||
Text="{Binding Parameters[1],
|
||||
Converter={StaticResource FightPropertyValueFormatter},
|
||||
ConverterParameter={Binding DataContext[1],Source={StaticResource FightPropertyBindingProxy}}}"/>
|
||||
<TextBlock
|
||||
Text="{Binding Parameters[2],
|
||||
Converter={StaticResource FightPropertyValueFormatter},
|
||||
ConverterParameter={Binding DataContext[2],Source={StaticResource FightPropertyBindingProxy}}}"/>
|
||||
<TextBlock
|
||||
Text="{Binding Parameters[3],
|
||||
Converter={StaticResource FightPropertyValueFormatter},
|
||||
ConverterParameter={Binding DataContext[3],Source={StaticResource FightPropertyBindingProxy}}}"/>
|
||||
</cwuc:UniformGrid>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
|
||||
</Expander>
|
||||
|
||||
<TextBlock Text="天赋" Style="{StaticResource BaseTextBlockStyle}" Margin="16,16,0,0"/>
|
||||
<ItemsControl
|
||||
ItemsSource="{Binding Selected.SkillDepot.Skills}"
|
||||
ItemTemplate="{StaticResource SkillDataTemplate}"/>
|
||||
|
||||
<ContentControl
|
||||
Margin="16,16,0,0"
|
||||
HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
Content="{Binding Selected.SkillDepot.EnergySkill}"
|
||||
ContentTemplate="{StaticResource SkillDataTemplate}"/>
|
||||
Content="{Binding Selected,Mode=OneWay}"
|
||||
ContentTemplate="{StaticResource PropertyDataTemplate}"/>
|
||||
|
||||
<ItemsControl
|
||||
ItemsSource="{Binding Selected.SkillDepot.Inherents}"
|
||||
ItemTemplate="{StaticResource InherentDataTemplate}"/>
|
||||
<TextBlock Text="天赋" Style="{StaticResource BaseTextBlockStyle}" Margin="16,32,0,0"/>
|
||||
<shvc:SkillPivot
|
||||
Margin="16,16,0,0"
|
||||
Skills="{Binding Selected.SkillDepot.CompositeSkills}"
|
||||
ItemTemplate="{StaticResource SkillDataTemplate}"/>
|
||||
|
||||
<TextBlock Text="命之座" Style="{StaticResource BaseTextBlockStyle}" Margin="16,16,0,0"/>
|
||||
<TextBlock Text="命之座" Style="{StaticResource BaseTextBlockStyle}" Margin="16,32,0,0"/>
|
||||
<shvc:SkillPivot
|
||||
Grid.Column="1"
|
||||
Margin="16,16,0,0"
|
||||
Skills="{Binding Selected.SkillDepot.Talents}"
|
||||
ItemTemplate="{StaticResource TalentDataTemplate}"/>
|
||||
|
||||
<ItemsControl
|
||||
ItemsSource="{Binding Selected.SkillDepot.Talents}"
|
||||
ItemTemplate="{StaticResource InherentDataTemplate}"/>
|
||||
|
||||
<TextBlock Text="其他" Style="{StaticResource BaseTextBlockStyle}" Margin="16,16,0,0"/>
|
||||
<TextBlock Text="其他" Style="{StaticResource BaseTextBlockStyle}" Margin="16,32,0,0"/>
|
||||
<!--衣装-->
|
||||
<Expander
|
||||
Margin="16,16,0,0"
|
||||
HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
Header="衣装">
|
||||
<ItemsControl
|
||||
ItemsSource="{Binding Selected.Costumes}">
|
||||
<ItemsControl ItemsSource="{Binding Selected.Costumes}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<StackPanel Margin="0,0,0,-4">
|
||||
@@ -448,8 +301,7 @@
|
||||
HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
Header="资料">
|
||||
<ItemsControl
|
||||
ItemsSource="{Binding Selected.FetterInfo.Fetters}">
|
||||
<ItemsControl ItemsSource="{Binding Selected.FetterInfo.Fetters}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<StackPanel Margin="0,0,0,-4">
|
||||
@@ -460,9 +312,7 @@
|
||||
Margin="16,8,16,16"
|
||||
Description="{Binding Context}">
|
||||
<shct:DescriptionTextBlock.Resources>
|
||||
<Style
|
||||
TargetType="TextBlock"
|
||||
BasedOn="{StaticResource CaptionTextBlockStyle}"/>
|
||||
<Style TargetType="TextBlock" BasedOn="{StaticResource CaptionTextBlockStyle}"/>
|
||||
</shct:DescriptionTextBlock.Resources>
|
||||
</shct:DescriptionTextBlock>
|
||||
<MenuFlyoutSeparator Margin="16,0"/>
|
||||
@@ -473,12 +323,12 @@
|
||||
</Expander>
|
||||
<!--故事-->
|
||||
<Expander
|
||||
Margin="16,16,0,0"
|
||||
HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
Header="故事">
|
||||
Margin="16,16,0,0"
|
||||
HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
Header="故事">
|
||||
<ItemsControl
|
||||
ItemsSource="{Binding Selected.FetterInfo.FetterStories}">
|
||||
ItemsSource="{Binding Selected.FetterInfo.FetterStories}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<StackPanel Margin="0,0,0,-4">
|
||||
|
||||
@@ -14,34 +14,10 @@
|
||||
<mxic:InvokeCommandAction Command="{Binding OpenUICommand}"/>
|
||||
</mxic:EventTriggerBehavior>
|
||||
</mxi:Interaction.Behaviors>
|
||||
<Grid Height="58">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition />
|
||||
<RowDefinition Height="auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<PersonPicture
|
||||
ProfilePicture="{Binding SelectedUser.UserInfo.AvatarUrl,Mode=OneWay}"
|
||||
HorizontalAlignment="Left"
|
||||
Margin="6,2"
|
||||
Height="36"
|
||||
Width="36"/>
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
Margin="0,0,0,2"
|
||||
Grid.Column="1"
|
||||
Text="{Binding SelectedUser.UserInfo.Nickname,Mode=OneWay}"
|
||||
TextTrimming="CharacterEllipsis"/>
|
||||
<StackPanel>
|
||||
<Button
|
||||
Background="Transparent"
|
||||
BorderBrush="{x:Null}"
|
||||
Height="38.4"
|
||||
Content=""
|
||||
FontFamily="{StaticResource SymbolThemeFontFamily}"
|
||||
Grid.Column="2"
|
||||
Margin="4">
|
||||
<Button.Resources>
|
||||
@@ -49,9 +25,36 @@
|
||||
x:Key="ViewModelBindingProxy"
|
||||
DataContext="{Binding}"/>
|
||||
</Button.Resources>
|
||||
<Button.Content>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
<ColumnDefinition/>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<PersonPicture
|
||||
ProfilePicture="{Binding SelectedUser.UserInfo.AvatarUrl,Mode=OneWay}"
|
||||
HorizontalAlignment="Left"
|
||||
Margin="1,1,6,1"
|
||||
Height="36"
|
||||
Width="36"/>
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
Margin="0,0,0,2"
|
||||
Grid.Column="1"
|
||||
Text="{Binding SelectedUser.UserInfo.Nickname,Mode=OneWay}"
|
||||
TextTrimming="CharacterEllipsis"/>
|
||||
<FontIcon
|
||||
Grid.Column="2"
|
||||
Glyph=""
|
||||
FontSize="12"
|
||||
VerticalAlignment="Center"
|
||||
Margin="0,0,8,0"/>
|
||||
</Grid>
|
||||
</Button.Content>
|
||||
<Button.Flyout>
|
||||
<Flyout
|
||||
Placement="TopEdgeAlignedRight"
|
||||
Placement="LeftEdgeAlignedBottom"
|
||||
LightDismissOverlayMode="On">
|
||||
<Flyout.FlyoutPresenterStyle>
|
||||
<Style
|
||||
@@ -173,7 +176,7 @@
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</Grid.Resources>
|
||||
|
||||
|
||||
<mxi:Interaction.Behaviors>
|
||||
<mxic:EventTriggerBehavior EventName="PointerEntered">
|
||||
<mxim:ControlStoryboardAction Storyboard="{StaticResource ButtonPanelVisibleStoryboard}"/>
|
||||
@@ -183,7 +186,7 @@
|
||||
</mxic:EventTriggerBehavior>
|
||||
</mxi:Interaction.Behaviors>
|
||||
</Grid>
|
||||
|
||||
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
@@ -196,11 +199,14 @@
|
||||
</StackPanel>
|
||||
</Flyout>
|
||||
</Button.Flyout>
|
||||
<Button.Style>
|
||||
<Style TargetType="Button" BasedOn="{StaticResource DefaultButtonStyle}">
|
||||
<Setter Property="Padding" Value="0"/>
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch"/>
|
||||
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
|
||||
</Style>
|
||||
</Button.Style>
|
||||
</Button>
|
||||
<NavigationViewItemSeparator
|
||||
Margin="0,4,0,0"
|
||||
Grid.Row="1"
|
||||
Grid.ColumnSpan="3"
|
||||
VerticalAlignment="Bottom"/>
|
||||
</Grid>
|
||||
<NavigationViewItemSeparator/>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
|
||||
@@ -34,14 +34,14 @@ internal class ExperimentalFeaturesViewModel : ObservableObject
|
||||
/// </summary>
|
||||
public ICommand OpenDataFolderCommand { get; }
|
||||
|
||||
private Task OpenCacheFolderAsync()
|
||||
private Task OpenCacheFolderAsync(CancellationToken token)
|
||||
{
|
||||
return Launcher.LaunchFolderAsync(App.AppData.TemporaryFolder).AsTask();
|
||||
return Launcher.LaunchFolderAsync(App.Current.AppData.TemporaryFolder).AsTask(token);
|
||||
}
|
||||
|
||||
private async Task OpenDataFolderAsync()
|
||||
private async Task OpenDataFolderAsync(CancellationToken token)
|
||||
{
|
||||
StorageFolder folder = await KnownFolders.DocumentsLibrary.GetFolderAsync("Hutao").AsTask().ConfigureAwait(false);
|
||||
await Launcher.LaunchFolderAsync(folder).AsTask().ConfigureAwait(false);
|
||||
StorageFolder folder = await KnownFolders.DocumentsLibrary.GetFolderAsync("Hutao").AsTask(token).ConfigureAwait(false);
|
||||
await Launcher.LaunchFolderAsync(folder).AsTask(token).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user