ContentDialogFactory

This commit is contained in:
DismissedLight
2023-01-09 12:15:11 +08:00
parent 4a027a8d3f
commit 23f3e5df77
41 changed files with 330 additions and 399 deletions

View File

@@ -1,7 +1,6 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
namespace Snap.Hutao.Control.Extension;
@@ -11,19 +10,6 @@ namespace Snap.Hutao.Control.Extension;
/// </summary>
internal static class ContentDialogExtensions
{
/// <summary>
/// 针对窗口进行初始化
/// </summary>
/// <param name="contentDialog">对话框</param>
/// <param name="window">窗口</param>
/// <returns>初始化完成的对话框</returns>
public static ContentDialog InitializeWithWindow(this ContentDialog contentDialog, Window window)
{
contentDialog.XamlRoot = window.Content.XamlRoot;
return contentDialog;
}
/// <summary>
/// 阻止用户交互
/// </summary>

View File

@@ -77,4 +77,32 @@ public static partial class EnumerableExtension
return false;
}
/// <inheritdoc cref="Enumerable.ToDictionary{TSource, TKey}(IEnumerable{TSource}, Func{TSource, TKey})"/>
public static Dictionary<TKey, TSource> ToDictionaryOverride<TKey, TSource>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
where TKey : notnull
{
Dictionary<TKey, TSource> dictionary = new();
foreach (TSource value in source)
{
dictionary[keySelector(value)] = value;
}
return dictionary;
}
/// <inheritdoc cref="Enumerable.ToDictionary{TSource, TKey, TElement}(IEnumerable{TSource}, Func{TSource, TKey}, Func{TSource, TElement})"/>
public static Dictionary<TKey, TValue> ToDictionaryOverride<TKey, TValue, TSource>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TValue> valueSelector)
where TKey : notnull
{
Dictionary<TKey, TValue> dictionary = new();
foreach (TSource value in source)
{
dictionary[keySelector(value)] = valueSelector(value);
}
return dictionary;
}
}

View File

@@ -1,6 +1,8 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using System.Collections.ObjectModel;
namespace Snap.Hutao.Extension;
/// <summary>
@@ -8,26 +10,6 @@ namespace Snap.Hutao.Extension;
/// </summary>
public static partial class EnumerableExtension
{
/// <summary>
/// 计数
/// </summary>
/// <typeparam name="TSource">源类型</typeparam>
/// <typeparam name="TKey">计数的键类型</typeparam>
/// <param name="source">源</param>
/// <param name="keySelector">键选择器</param>
/// <returns>计数表</returns>
public static IEnumerable<KeyValuePair<TKey, int>> CountBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
where TKey : notnull, IEquatable<TKey>
{
CounterInt32<TKey> counter = new();
foreach (TSource item in source)
{
counter.Increase(keySelector(item));
}
return counter;
}
/// <summary>
/// 如果传入集合不为空则原路返回,
/// 如果传入集合为空返回一个集合的空集
@@ -64,56 +46,14 @@ public static partial class EnumerableExtension
return source.FirstOrDefault(predicate) ?? source.FirstOrDefault();
}
/// <inheritdoc cref="Enumerable.ToDictionary{TSource, TKey}(IEnumerable{TSource}, Func{TSource, TKey})"/>
public static Dictionary<TKey, TSource> ToDictionaryOverride<TKey, TSource>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
where TKey : notnull
{
Dictionary<TKey, TSource> dictionary = new();
foreach (TSource value in source)
{
dictionary[keySelector(value)] = value;
}
return dictionary;
}
/// <inheritdoc cref="Enumerable.ToDictionary{TSource, TKey, TElement}(IEnumerable{TSource}, Func{TSource, TKey}, Func{TSource, TElement})"/>
public static Dictionary<TKey, TValue> ToDictionaryOverride<TKey, TValue, TSource>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TValue> valueSelector)
where TKey : notnull
{
Dictionary<TKey, TValue> dictionary = new();
foreach (TSource value in source)
{
dictionary[keySelector(value)] = valueSelector(value);
}
return dictionary;
}
/// <summary>
/// 表示一个对 <see cref="TItem"/> 类型的计数器
/// 转换到 <see cref="ObservableCollection{T}"/>
/// </summary>
/// <typeparam name="TItem">待计数的类型</typeparam>
private class CounterInt32<TItem> : Dictionary<TItem, int>
where TItem : notnull, IEquatable<TItem>
/// <typeparam name="T">类型</typeparam>
/// <param name="source">源</param>
/// <returns><see cref="ObservableCollection{T}"/></returns>
public static ObservableCollection<T> ToObservableCollection<T>(this IEnumerable<T> source)
{
/// <summary>
/// 增加计数器
/// </summary>
/// <param name="item">物品</param>
public void Increase(TItem? item)
{
if (item != null)
{
if (!ContainsKey(item))
{
this[item] = 0;
}
this[item] += 1;
}
}
return new ObservableCollection<T>(source);
}
}

View File

@@ -0,0 +1,36 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Microsoft.UI.Xaml.Controls;
namespace Snap.Hutao.Factory.Abstraction;
/// <summary>
/// 内容对话框工厂
/// </summary>
internal interface IContentDialogFactory
{
/// <summary>
/// 创建一个新的内容对话框,用于确认
/// </summary>
/// <param name="title">标题</param>
/// <param name="content">内容</param>
/// <returns>内容对话框</returns>
ContentDialog CreateForConfirm(string title, string content);
/// <summary>
/// 创建一个新的内容对话框,用于确认或取消
/// </summary>
/// <param name="title">标题</param>
/// <param name="content">内容</param>
/// <param name="defaultButton">默认按钮</param>
/// <returns>内容对话框</returns>
ContentDialog CreateForConfirmCancel(string title, string content, ContentDialogButton defaultButton = ContentDialogButton.Close);
/// <summary>
/// 创建一个新的内容对话框,用于提示未知的进度
/// </summary>
/// <param name="title">标题</param>
/// <returns>内容对话框</returns>
ContentDialog CreateForIndeterminateProgress(string title);
}

View File

@@ -0,0 +1,67 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Microsoft.UI.Xaml.Controls;
using Snap.Hutao.Factory.Abstraction;
namespace Snap.Hutao.Factory;
/// <inheritdoc cref="IContentDialogFactory"/>
[Injection(InjectAs.Transient, typeof(IContentDialogFactory))]
internal class ContentDialogFactory : IContentDialogFactory
{
private readonly MainWindow mainWindow;
/// <summary>
/// 构造一个新的内容对话框工厂
/// </summary>
/// <param name="mainWindow">主窗体</param>
public ContentDialogFactory(MainWindow mainWindow)
{
this.mainWindow = mainWindow;
}
/// <inheritdoc/>
public ContentDialog CreateForConfirm(string title, string content)
{
ContentDialog dialog = new()
{
XamlRoot = mainWindow.Content.XamlRoot,
Title = title,
Content = content,
DefaultButton = ContentDialogButton.Primary,
PrimaryButtonText = "确认",
};
return dialog;
}
/// <inheritdoc/>
public ContentDialog CreateForConfirmCancel(string title, string content, ContentDialogButton defaultButton = ContentDialogButton.Close)
{
ContentDialog dialog = new()
{
XamlRoot = mainWindow.Content.XamlRoot,
Title = title,
Content = content,
DefaultButton = defaultButton,
PrimaryButtonText = "确认",
CloseButtonText = "取消",
};
return dialog;
}
/// <inheritdoc/>
public ContentDialog CreateForIndeterminateProgress(string title)
{
ContentDialog dialog = new()
{
XamlRoot = mainWindow.Content.XamlRoot,
Title = title,
Content = new ProgressBar() { IsIndeterminate = true },
};
return dialog;
}
}

View File

@@ -41,4 +41,22 @@ public class UserAndRole
{
return new UserAndRole(user.Entity, user.SelectedUserGameRole!);
}
/// <summary>
/// 尝试转换到用户与角色
/// </summary>
/// <param name="user">用户</param>
/// <param name="userAndRole">用户与角色</param>
/// <returns>是否转换成功</returns>
public static bool TryFromUser(User? user, [NotNullWhen(true)]out UserAndRole? userAndRole)
{
if (user != null && user.SelectedUserGameRole != null)
{
userAndRole = FromUser(user);
return true;
}
userAndRole = null;
return false;
}
}

View File

@@ -17,8 +17,7 @@ internal class GachaLogUrlManualInputProvider : IGachaLogUrlProvider
/// <inheritdoc/>
public async Task<ValueResult<bool, string>> GetQueryAsync()
{
MainWindow mainWindow = Ioc.Default.GetRequiredService<MainWindow>();
ValueResult<bool, string> result = await new GachaLogUrlDialog(mainWindow).GetInputUrlAsync().ConfigureAwait(false);
ValueResult<bool, string> result = await new GachaLogUrlDialog().GetInputUrlAsync().ConfigureAwait(false);
if (result.IsOk)
{

View File

@@ -304,8 +304,7 @@ internal class GameService : IGameService, IDisposable
if (account == null)
{
MainWindow mainWindow = Ioc.Default.GetRequiredService<MainWindow>();
(bool isOk, string name) = await new GameAccountNameDialog(mainWindow).GetInputNameAsync().ConfigureAwait(false);
(bool isOk, string name) = await new GameAccountNameDialog().GetInputNameAsync().ConfigureAwait(false);
if (isOk)
{
@@ -349,8 +348,7 @@ internal class GameService : IGameService, IDisposable
/// <inheritdoc/>
public async ValueTask ModifyGameAccountAsync(GameAccount gameAccount)
{
MainWindow mainWindow = Ioc.Default.GetRequiredService<MainWindow>();
(bool isOk, string name) = await new GameAccountNameDialog(mainWindow).GetInputNameAsync().ConfigureAwait(true);
(bool isOk, string name) = await new GameAccountNameDialog().GetInputNameAsync().ConfigureAwait(true);
if (isOk)
{

View File

@@ -75,7 +75,6 @@
<None Remove="View\Dialog\AchievementArchiveCreateDialog.xaml" />
<None Remove="View\Dialog\AchievementImportDialog.xaml" />
<None Remove="View\Dialog\AdoptCalculatorDialog.xaml" />
<None Remove="View\Dialog\AvatarInfoQueryDialog.xaml" />
<None Remove="View\Dialog\CommunityGameRecordDialog.xaml" />
<None Remove="View\Dialog\CultivateProjectDialog.xaml" />
<None Remove="View\Dialog\CultivatePromotionDeltaDialog.xaml" />
@@ -306,11 +305,6 @@
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<Page Update="View\Dialog\AvatarInfoQueryDialog.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<Page Update="View\Page\AvatarPropertyPage.xaml">
<Generator>MSBuild:Compile</Generator>

View File

@@ -15,10 +15,10 @@ public sealed partial class AchievementArchiveCreateDialog : ContentDialog
/// 构造一个新的成就存档创建对话框
/// </summary>
/// <param name="window">窗体</param>
public AchievementArchiveCreateDialog(Window window)
public AchievementArchiveCreateDialog()
{
InitializeComponent();
XamlRoot = window.Content.XamlRoot;
XamlRoot = Ioc.Default.GetRequiredService<MainWindow>().Content.XamlRoot;
}
/// <summary>
@@ -27,6 +27,7 @@ public sealed partial class AchievementArchiveCreateDialog : ContentDialog
/// <returns>输入的结果</returns>
public async Task<ValueResult<bool, string>> GetInputAsync()
{
await ThreadHelper.SwitchToMainThreadAsync();
ContentDialogResult result = await ShowAsync();
string text = InputText.Text ?? string.Empty;

View File

@@ -19,12 +19,11 @@ public sealed partial class AchievementImportDialog : ContentDialog
/// <summary>
/// 构造一个新的成就对话框
/// </summary>
/// <param name="window">呈现的父窗口</param>
/// <param name="uiaf">uiaf数据</param>
public AchievementImportDialog(Window window, UIAF uiaf)
public AchievementImportDialog(UIAF uiaf)
{
InitializeComponent();
XamlRoot = window.Content.XamlRoot;
XamlRoot = Ioc.Default.GetRequiredService<MainWindow>().Content.XamlRoot;
UIAF = uiaf;
}
@@ -43,6 +42,7 @@ public sealed partial class AchievementImportDialog : ContentDialog
/// <returns>导入选项</returns>
public async Task<ValueResult<bool, ImportStrategy>> GetImportStrategyAsync()
{
await ThreadHelper.SwitchToMainThreadAsync();
ContentDialogResult result = await ShowAsync();
ImportStrategy strategy = (ImportStrategy)ImportModeSelector.SelectedIndex;

View File

@@ -24,11 +24,11 @@ public sealed partial class AdoptCalculatorDialog : ContentDialog
/// 构造一个新的养成计算器对话框
/// </summary>
/// <param name="window">窗体</param>
public AdoptCalculatorDialog(Window window)
public AdoptCalculatorDialog()
{
InitializeComponent();
XamlRoot = window.Content.XamlRoot;
scope = Ioc.Default.CreateScope();
XamlRoot = scope.ServiceProvider.GetRequiredService<MainWindow>().Content.XamlRoot;
}
private void OnGridLoaded(object sender, RoutedEventArgs e)

View File

@@ -1,21 +0,0 @@
<ContentDialog
x:Class="Snap.Hutao.View.Dialog.AvatarInfoQueryDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
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"
Title="查询UID对应的橱窗"
CloseButtonText="取消"
DefaultButton="Primary"
IsPrimaryButtonEnabled="False"
PrimaryButtonText="请输入UID"
Style="{StaticResource DefaultContentDialogStyle}"
mc:Ignorable="d">
<Grid>
<TextBox
x:Name="InputText"
PlaceholderText="请输入UID"
TextChanged="InputTextChanged"/>
</Grid>
</ContentDialog>

View File

@@ -1,53 +0,0 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Snap.Hutao.Web.Hoyolab;
namespace Snap.Hutao.View.Dialog;
/// <summary>
/// 角色信息查询UID对话框
/// </summary>
public sealed partial class AvatarInfoQueryDialog : ContentDialog
{
/// <summary>
/// 构造一个新的角色信息查询UID对话框
/// </summary>
/// <param name="window">窗口</param>
public AvatarInfoQueryDialog(Window window)
{
InitializeComponent();
XamlRoot = window.Content.XamlRoot;
}
/// <summary>
/// 获取玩家UID
/// </summary>
/// <returns>玩家UID</returns>
public async Task<ValueResult<bool, PlayerUid>> GetPlayerUidAsync()
{
ContentDialogResult result = await ShowAsync();
bool isOk = result == ContentDialogResult.Primary;
if (InputText.Text.Length != 9)
{
return new(false, default);
}
return new(isOk, isOk && InputText.Text.Length == 9 ? new(InputText.Text) : default);
}
private void InputTextChanged(object sender, TextChangedEventArgs e)
{
bool inputValid = string.IsNullOrEmpty(InputText.Text) && InputText.Text.Length == 9;
(PrimaryButtonText, IsPrimaryButtonEnabled) = inputValid switch
{
true => ("请输入正确的UID", false),
false => ("确认", true),
};
}
}

View File

@@ -24,11 +24,11 @@ public sealed partial class CommunityGameRecordDialog : ContentDialog
/// 构造一个新的社区游戏记录对话框
/// </summary>
/// <param name="window">窗体</param>
public CommunityGameRecordDialog(MainWindow window)
public CommunityGameRecordDialog()
{
InitializeComponent();
XamlRoot = window.Content.XamlRoot;
scope = Ioc.Default.CreateScope();
XamlRoot = scope.ServiceProvider.GetRequiredService<MainWindow>().Content.XamlRoot;
}
private void OnGridLoaded(object sender, RoutedEventArgs e)

View File

@@ -17,10 +17,10 @@ public sealed partial class CultivateProjectDialog : ContentDialog
/// 构造一个新的养成计划对话框
/// </summary>
/// <param name="window">窗体</param>
public CultivateProjectDialog(Window window)
public CultivateProjectDialog()
{
InitializeComponent();
XamlRoot = window.Content.XamlRoot;
XamlRoot = Ioc.Default.GetRequiredService<MainWindow>().Content.XamlRoot;
}
/// <summary>

View File

@@ -19,13 +19,12 @@ public sealed partial class CultivatePromotionDeltaDialog : ContentDialog
/// <summary>
/// 构造一个新的养成计算对话框
/// </summary>
/// <param name="window">窗体</param>
/// <param name="avatar">角色</param>
/// <param name="weapon">武器</param>
public CultivatePromotionDeltaDialog(Window window, ICalculableAvatar? avatar, ICalculableWeapon? weapon)
public CultivatePromotionDeltaDialog(ICalculableAvatar? avatar, ICalculableWeapon? weapon)
{
InitializeComponent();
XamlRoot = window.Content.XamlRoot;
XamlRoot = Ioc.Default.GetRequiredService<MainWindow>().Content.XamlRoot;
DataContext = this;
Avatar = avatar;
Weapon = weapon;
@@ -55,6 +54,7 @@ public sealed partial class CultivatePromotionDeltaDialog : ContentDialog
/// <returns>提升差异</returns>
public async Task<ValueResult<bool, AvatarPromotionDelta>> GetPromotionDeltaAsync()
{
await ThreadHelper.SwitchToMainThreadAsync();
ContentDialogResult result = await ShowAsync();
if (result == ContentDialogResult.Primary)

View File

@@ -15,12 +15,11 @@ public sealed partial class DailyNoteNotificationDialog : ContentDialog
/// <summary>
/// 构造一个新的实时便笺通知设置对话框
/// </summary>
/// <param name="window">窗口</param>
/// <param name="entry">实时便笺</param>
public DailyNoteNotificationDialog(Window window, DailyNoteEntry entry)
public DailyNoteNotificationDialog(DailyNoteEntry entry)
{
InitializeComponent();
XamlRoot = window.Content.XamlRoot;
XamlRoot = Ioc.Default.GetRequiredService<MainWindow>().Content.XamlRoot;
DataContext = entry;
}
}

View File

@@ -5,9 +5,8 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.Web.WebView2.Core;
using Snap.Hutao.Model.Entity;
using Snap.Hutao.Model.Binding.User;
using Snap.Hutao.Web.Bridge;
using Snap.Hutao.Web.Hoyolab;
namespace Snap.Hutao.View.Dialog;
@@ -17,23 +16,20 @@ namespace Snap.Hutao.View.Dialog;
public sealed partial class DailyNoteVerificationDialog : ContentDialog
{
private readonly IServiceScope scope;
private readonly User user;
private readonly PlayerUid uid;
private readonly UserAndRole userAndRole;
[SuppressMessage("", "IDE0052")]
private DailyNoteJsInterface? dailyNoteJsInterface;
/// <summary>
/// 构造一个新的实时便笺认证对话框
/// </summary>
/// <param name="window">窗口</param>
/// <param name="user">用户</param>
/// <param name="uid">uid</param>
public DailyNoteVerificationDialog(Window window, User user, PlayerUid uid)
/// <param name="userAndRole">用户与角色</param>
public DailyNoteVerificationDialog(UserAndRole userAndRole)
{
InitializeComponent();
XamlRoot = window.Content.XamlRoot;
this.user = user;
this.uid = uid;
XamlRoot = Ioc.Default.GetRequiredService<MainWindow>().Content.XamlRoot;
this.userAndRole = userAndRole;
scope = Ioc.Default.CreateScope();
}
@@ -47,10 +43,11 @@ public sealed partial class DailyNoteVerificationDialog : ContentDialog
await WebView.EnsureCoreWebView2Async();
CoreWebView2 coreWebView2 = WebView.CoreWebView2;
Model.Entity.User user = userAndRole.User;
coreWebView2.SetCookie(user.CookieToken, user.Ltoken, null).SetMobileUserAgent();
dailyNoteJsInterface = new(coreWebView2, scope.ServiceProvider);
string query = $"?role_id={uid.Value}&server={uid.Region}";
string query = $"?role_id={userAndRole.Role.GameUid}&server={userAndRole.Role.Region}";
coreWebView2.Navigate($"https://webstatic.mihoyo.com/app/community-game-records/index.html?bbs_presentation_style=fullscreen#/ys/daily/{query}");
}

View File

@@ -18,12 +18,12 @@ public sealed partial class GachaLogImportDialog : ContentDialog
/// <summary>
/// 构造一个新的祈愿记录导入对话框
/// </summary>
/// <param name="window">呈现的父窗口</param>
/// <param name="uigf">uigf数据</param>
public GachaLogImportDialog(Window window, UIGF uigf)
///
public GachaLogImportDialog(UIGF uigf)
{
InitializeComponent();
XamlRoot = window.Content.XamlRoot;
XamlRoot = Ioc.Default.GetRequiredService<MainWindow>().Content.XamlRoot;
UIGF = uigf;
}
@@ -42,6 +42,7 @@ public sealed partial class GachaLogImportDialog : ContentDialog
/// <returns>是否导入</returns>
public async Task<bool> GetShouldImportAsync()
{
await ThreadHelper.SwitchToMainThreadAsync();
return await ShowAsync() == ContentDialogResult.Primary;
}
}

View File

@@ -22,10 +22,10 @@ public sealed partial class GachaLogRefreshProgressDialog : ContentDialog
/// 构造一个新的对话框
/// </summary>
/// <param name="window">窗体</param>
public GachaLogRefreshProgressDialog(Window window)
public GachaLogRefreshProgressDialog()
{
InitializeComponent();
XamlRoot = window.Content.XamlRoot;
XamlRoot = Ioc.Default.GetRequiredService<MainWindow>().Content.XamlRoot;
}
/// <summary>

View File

@@ -15,10 +15,10 @@ public sealed partial class GachaLogUrlDialog : ContentDialog
/// 初始化一个新的祈愿记录Url对话框
/// </summary>
/// <param name="window">窗体</param>
public GachaLogUrlDialog(Window window)
public GachaLogUrlDialog()
{
InitializeComponent();
XamlRoot = window.Content.XamlRoot;
XamlRoot = Ioc.Default.GetRequiredService<MainWindow>().Content.XamlRoot;
}
/// <summary>

View File

@@ -15,10 +15,10 @@ public sealed partial class GameAccountNameDialog : ContentDialog
/// 构造一个新的游戏账号命名对话框
/// </summary>
/// <param name="window">窗体</param>
public GameAccountNameDialog(Window window)
public GameAccountNameDialog()
{
InitializeComponent();
XamlRoot = window.Content.XamlRoot;
XamlRoot = Ioc.Default.GetRequiredService<MainWindow>().Content.XamlRoot;
}
/// <summary>

View File

@@ -15,10 +15,10 @@ public sealed partial class LoginMihoyoBBSDialog : ContentDialog
/// 构造一个新的登录到米游社对话框
/// </summary>
/// <param name="window">窗体</param>
public LoginMihoyoBBSDialog(MainWindow window)
public LoginMihoyoBBSDialog()
{
InitializeComponent();
XamlRoot = window.Content.XamlRoot;
XamlRoot = Ioc.Default.GetRequiredService<MainWindow>().Content.XamlRoot;
}
/// <summary>
@@ -27,6 +27,7 @@ public sealed partial class LoginMihoyoBBSDialog : ContentDialog
/// <returns>账号密码</returns>
public async Task<ValueResult<bool, Dictionary<string, string>>> GetInputAccountPasswordAsync()
{
await ThreadHelper.SwitchToMainThreadAsync();
bool result = await ShowAsync() == ContentDialogResult.Primary;
Dictionary<string, string> data = new()

View File

@@ -23,11 +23,11 @@ public sealed partial class SignInWebViewDialog : ContentDialog
/// 构造一个新的签到网页视图对话框
/// </summary>
/// <param name="window">窗口</param>
public SignInWebViewDialog(MainWindow window)
public SignInWebViewDialog()
{
InitializeComponent();
XamlRoot = window.Content.XamlRoot;
scope = Ioc.Default.CreateScope();
XamlRoot = scope.ServiceProvider.GetRequiredService<MainWindow>().Content.XamlRoot;
}
private void OnGridLoaded(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)

View File

@@ -15,10 +15,10 @@ public sealed partial class UserDialog : ContentDialog
/// 构造一个新的添加用户对话框
/// </summary>
/// <param name="window">呈现的父窗口</param>
public UserDialog(Window window)
public UserDialog()
{
InitializeComponent();
XamlRoot = window.Content.XamlRoot;
XamlRoot = Ioc.Default.GetRequiredService<MainWindow>().Content.XamlRoot;
}
/// <summary>
@@ -27,6 +27,7 @@ public sealed partial class UserDialog : ContentDialog
/// <returns>输入的结果</returns>
public async Task<ValueResult<bool, string>> GetInputCookieAsync()
{
await ThreadHelper.SwitchToMainThreadAsync();
ContentDialogResult result = await ShowAsync();
string cookie = InputText.Text;

View File

@@ -144,8 +144,6 @@
Style="{StaticResource CaptionTextBlockStyle}"
Text="{Binding FinishDescription}"/>
<ProgressBar
Height="1"
MinHeight="1"
Margin="0,4,0,0"
Maximum="1"
Value="{Binding FinishPercent}"/>

View File

@@ -62,7 +62,7 @@
<AppBarButton
Command="{Binding CultivateCommand}"
CommandParameter="{Binding SelectedAvatar}"
Icon="{shcm:FontIcon Glyph=&#xE91B;}"
Icon="{shcm:FontIcon Glyph=&#xE8EF;}"
Label="养成计算"/>
<AppBarSeparator/>
<AppBarButton Icon="{shcm:FontIcon Glyph=&#xE72C;}" Label="同步角色信息">
@@ -141,12 +141,7 @@
MaxWidth="800"
HorizontalAlignment="Left"
Background="Transparent">
<Border
Margin="16"
Background="{StaticResource CardBackgroundFillColorDefault}"
BorderBrush="{StaticResource CardStrokeColorDefault}"
BorderThickness="1"
CornerRadius="{StaticResource CompatCornerRadius}">
<Border Margin="16" Style="{StaticResource BorderCardStyle}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
@@ -483,35 +478,63 @@
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="4*"/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="2*"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0">
<TextBlock Style="{StaticResource BaseTextBlockStyle}" Text="{Binding MainProperty.Key}"/>
<TextBlock Text="{Binding MainProperty.Value}"/>
<!-- 主属性 -->
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<TextBlock
Style="{StaticResource BaseTextBlockStyle}"
Text="{Binding MainProperty.Key}"
TextTrimming="CharacterEllipsis"/>
<TextBlock Grid.Column="1" Text="{Binding MainProperty.Value}"/>
</Grid>
<!-- 评分 -->
<Grid Margin="0,8,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<TextBlock
Style="{StaticResource BaseTextBlockStyle}"
Text="评分"
TextTrimming="CharacterEllipsis"
TextWrapping="NoWrap"/>
<TextBlock Grid.Column="1" Text="{Binding ScoreFormatted}"/>
</Grid>
</StackPanel>
<AppBarSeparator Grid.Column="1"/>
<ItemsControl Grid.Column="2" ItemsSource="{Binding ComposedSubProperties}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<cwucont:UniformGrid Columns="4"/>
<cwucont:UniformGrid
ColumnSpacing="16"
Columns="2"
RowSpacing="8"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Style="{StaticResource BaseTextBlockStyle}" Text="{Binding Name}"/>
<TextBlock Text="{Binding Value}"/>
</StackPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<TextBlock
Style="{StaticResource BaseTextBlockStyle}"
Text="{Binding Name}"
TextTrimming="CharacterEllipsis"
TextWrapping="NoWrap"/>
<TextBlock Grid.Column="1" Text="{Binding Value}"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<AppBarSeparator Grid.Column="3"/>
<StackPanel Grid.Column="4">
<TextBlock Style="{StaticResource BaseTextBlockStyle}" Text="评分"/>
<TextBlock Text="{Binding ScoreFormatted}"/>
</StackPanel>
</Grid>
</Grid>
</Expander.Header>
@@ -526,9 +549,16 @@
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Padding="2" Opacity="{Binding Opacity}">
<TextBlock Text="{Binding Name}"/>
<TextBlock HorizontalAlignment="Right" Text="{Binding Value}"/>
<Grid Opacity="{Binding Opacity}">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<TextBlock
Text="{Binding Name}"
TextTrimming="CharacterEllipsis"
TextWrapping="NoWrap"/>
<TextBlock Grid.Column="1" Text="{Binding Value}"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
@@ -545,9 +575,16 @@
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Padding="2" Opacity="{Binding Opacity}">
<TextBlock Text="{Binding Name}"/>
<TextBlock HorizontalAlignment="Right" Text="{Binding Value}"/>
<Grid Opacity="{Binding Opacity}">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<TextBlock
Text="{Binding Name}"
TextTrimming="CharacterEllipsis"
TextWrapping="NoWrap"/>
<TextBlock Grid.Column="1" Text="{Binding Value}"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>

View File

@@ -143,11 +143,8 @@
<Border
Margin="16,16,16,0"
Padding="8"
Background="{StaticResource CardBackgroundFillColorSecondary}"
BorderBrush="{StaticResource CardStrokeColorDefaultBrush}"
BorderThickness="1"
CornerRadius="{StaticResource CompatCornerRadius}">
<Grid Background="Transparent">
Style="{StaticResource BorderCardStyle}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>

View File

@@ -25,6 +25,10 @@
<Button Command="{Binding ShowCommunityGameRecordDialogCommand}" Content="Open"/>
</wsc:Setting>
<wsc:Setting Header="AdoptCalculatorDialogTest">
<Button Command="{Binding ShowAdoptCalculatorDialogCommand}" Content="Open"/>
</wsc:Setting>
<wsc:Setting Header="DownloadStaticFileTest">
<Button Command="{Binding DownloadStaticFileCommand}" Content="Download"/>
</wsc:Setting>

View File

@@ -42,6 +42,7 @@ internal class AchievementViewModel
private readonly IAchievementService achievementService;
private readonly IMetadataService metadataService;
private readonly IInfoBarService infoBarService;
private readonly IContentDialogFactory contentDialogFactory;
private readonly JsonSerializerOptions options;
private readonly TaskCompletionSource<bool> openUICompletionSource = new();
@@ -64,7 +65,7 @@ internal class AchievementViewModel
/// <param name="infoBarService">信息条服务</param>
/// <param name="options">Json序列化选项</param>
/// <param name="asyncRelayCommandFactory">异步命令工厂</param>
/// <param name="scopeFactory">范围工厂</param>
/// <param name="contentDialogFactory">内容对话框工厂</param>
/// <param name="messenger">消息器</param>
public AchievementViewModel(
IMetadataService metadataService,
@@ -72,11 +73,13 @@ internal class AchievementViewModel
IInfoBarService infoBarService,
JsonSerializerOptions options,
IAsyncRelayCommandFactory asyncRelayCommandFactory,
IContentDialogFactory contentDialogFactory,
IMessenger messenger)
{
this.metadataService = metadataService;
this.achievementService = achievementService;
this.infoBarService = infoBarService;
this.contentDialogFactory = contentDialogFactory;
this.options = options;
OpenUICommand = asyncRelayCommandFactory.Create(OpenUIAsync);
@@ -241,36 +244,6 @@ internal class AchievementViewModel
return false;
}
private static Task<ContentDialogResult> ShowImportResultDialogAsync(string title, string message)
{
MainWindow mainWindow = Ioc.Default.GetRequiredService<MainWindow>();
ContentDialog dialog = new()
{
Title = title,
Content = message,
PrimaryButtonText = "确认",
DefaultButton = ContentDialogButton.Primary,
XamlRoot = mainWindow.Content.XamlRoot,
};
return dialog.ShowAsync().AsTask();
}
private static Task<ContentDialogResult> ShowImportFailDialogAsync(string message)
{
MainWindow mainWindow = Ioc.Default.GetRequiredService<MainWindow>();
ContentDialog dialog = new()
{
Title = "导入失败",
Content = message,
PrimaryButtonText = "确认",
DefaultButton = ContentDialogButton.Primary,
XamlRoot = mainWindow.Content.XamlRoot,
};
return dialog.ShowAsync().AsTask();
}
private async Task OpenUIAsync()
{
bool metaInitialized = await metadataService.InitializeAsync().ConfigureAwait(false);
@@ -303,8 +276,7 @@ internal class AchievementViewModel
{
if (Archives != null)
{
MainWindow mainWindow = Ioc.Default.GetRequiredService<MainWindow>();
(bool isOk, string name) = await new AchievementArchiveCreateDialog(mainWindow).GetInputAsync().ConfigureAwait(false);
(bool isOk, string name) = await new AchievementArchiveCreateDialog().GetInputAsync().ConfigureAwait(false);
if (isOk)
{
@@ -335,17 +307,9 @@ internal class AchievementViewModel
{
if (Archives != null && SelectedArchive != null)
{
ContentDialog dialog = new()
{
Title = $"确定要删除存档 {SelectedArchive.Name} 吗?",
Content = "该操作是不可逆的,该存档和其内的所有成就状态会丢失。",
PrimaryButtonText = "确认",
CloseButtonText = "取消",
DefaultButton = ContentDialogButton.Close,
};
MainWindow mainWindow = Ioc.Default.GetRequiredService<MainWindow>();
ContentDialogResult result = await dialog.InitializeWithWindow(mainWindow).ShowAsync();
ContentDialogResult result = await contentDialogFactory
.CreateForConfirmCancel($"确定要删除存档 {SelectedArchive.Name} 吗?", "该操作是不可逆的,该存档和其内的所有成就状态会丢失。")
.ShowAsync();
if (result == ContentDialogResult.Primary)
{
@@ -408,11 +372,11 @@ internal class AchievementViewModel
await ThreadHelper.SwitchToMainThreadAsync();
if (isOk)
{
await ShowImportResultDialogAsync("导出成功", "成功保存到指定位置").ConfigureAwait(false);
await contentDialogFactory.CreateForConfirm("导出成功", "成功保存到指定位置").ShowAsync();
}
else
{
await ShowImportResultDialogAsync("导出失败", "写入文件时遇到问题").ConfigureAwait(false);
await contentDialogFactory.CreateForConfirm("导出失败", "写入文件时遇到问题").ShowAsync();
}
}
}
@@ -432,7 +396,7 @@ internal class AchievementViewModel
else
{
await ThreadHelper.SwitchToMainThreadAsync();
await ShowImportFailDialogAsync("数据格式不正确").ConfigureAwait(false);
await contentDialogFactory.CreateForConfirm("导入失败", "数据格式不正确").ShowAsync();
}
}
@@ -444,8 +408,8 @@ internal class AchievementViewModel
return;
}
IPickerFactory pickerFactory = Ioc.Default.GetRequiredService<IPickerFactory>();
FileOpenPicker picker = pickerFactory.GetFileOpenPicker(PickerLocationId.Desktop, "导入", ".json");
FileOpenPicker picker = Ioc.Default.GetRequiredService<IPickerFactory>()
.GetFileOpenPicker(PickerLocationId.Desktop, "导入", ".json");
if (await picker.PickSingleFileAsync() is StorageFile file)
{
@@ -459,7 +423,7 @@ internal class AchievementViewModel
else
{
await ThreadHelper.SwitchToMainThreadAsync();
await ShowImportFailDialogAsync("文件的数据格式不正确").ConfigureAwait(false);
await contentDialogFactory.CreateForConfirm("导入失败", "文件的数据格式不正确").ShowAsync();
}
}
}
@@ -481,20 +445,12 @@ internal class AchievementViewModel
{
if (uiaf.IsCurrentVersionSupported())
{
MainWindow mainWindow = Ioc.Default.GetRequiredService<MainWindow>();
await ThreadHelper.SwitchToMainThreadAsync();
(bool isOk, ImportStrategy strategy) = await new AchievementImportDialog(mainWindow, uiaf).GetImportStrategyAsync().ConfigureAwait(true);
(bool isOk, ImportStrategy strategy) = await new AchievementImportDialog(uiaf).GetImportStrategyAsync().ConfigureAwait(true);
if (isOk)
{
ContentDialog importingDialog = new()
{
Title = "导入成就中",
Content = new ProgressBar() { IsIndeterminate = true },
};
ImportResult result;
await using (await importingDialog.InitializeWithWindow(mainWindow).BlockAsync().ConfigureAwait(false))
await using (await contentDialogFactory.CreateForIndeterminateProgress("导入成就中").BlockAsync().ConfigureAwait(false))
{
result = await achievementService.ImportFromUIAFAsync(archive, uiaf.List, strategy).ConfigureAwait(false);
}
@@ -507,7 +463,7 @@ internal class AchievementViewModel
else
{
await ThreadHelper.SwitchToMainThreadAsync();
await ShowImportFailDialogAsync("数据的 UIAF 版本过低,无法导入").ConfigureAwait(false);
await contentDialogFactory.CreateForConfirm("导入失败", "数据的 UIAF 版本过低,无法导入").ShowAsync();
}
return false;

View File

@@ -204,8 +204,7 @@ internal class AvatarPropertyViewModel : ObservableObject, ISupportCancellation
if (userService.Current != null)
{
MainWindow mainWindow = Ioc.Default.GetRequiredService<MainWindow>();
(bool isOk, CalcAvatarPromotionDelta delta) = await new CultivatePromotionDeltaDialog(mainWindow, avatar.ToCalculable(), avatar.Weapon.ToCalculable())
(bool isOk, CalcAvatarPromotionDelta delta) = await new CultivatePromotionDeltaDialog(avatar.ToCalculable(), avatar.Weapon.ToCalculable())
.GetPromotionDeltaAsync()
.ConfigureAwait(false);

View File

@@ -150,8 +150,7 @@ internal class CultivationViewModel : ObservableObject, ISupportCancellation
private async Task AddProjectAsync()
{
MainWindow mainWindow = Ioc.Default.GetRequiredService<MainWindow>();
(bool isOk, CultivateProject project) = await new CultivateProjectDialog(mainWindow).CreateProjectAsync().ConfigureAwait(false);
(bool isOk, CultivateProject project) = await new CultivateProjectDialog().CreateProjectAsync().ConfigureAwait(false);
if (isOk)
{

View File

@@ -220,18 +220,16 @@ internal class DailyNoteViewModel : ObservableObject, ISupportCancellation
{
if (entry != null)
{
MainWindow mainWindow = Ioc.Default.GetRequiredService<MainWindow>();
await new DailyNoteNotificationDialog(mainWindow, entry).ShowAsync();
await new DailyNoteNotificationDialog(entry).ShowAsync();
appDbContext.DailyNotes.UpdateAndSave(entry);
}
}
private async Task VerifyDailyNoteVerificationAsync()
{
if (userService.Current != null && userService.Current.SelectedUserGameRole != null)
if (UserAndRole.TryFromUser(userService.Current, out UserAndRole? userAndRole))
{
MainWindow mainWindow = Ioc.Default.GetRequiredService<MainWindow>();
await new DailyNoteVerificationDialog(mainWindow, userService.Current.Entity, userService.Current.SelectedUserGameRole).ShowAsync();
await new DailyNoteVerificationDialog(userAndRole).ShowAsync();
}
else
{

View File

@@ -6,7 +6,6 @@ using Microsoft.UI.Xaml.Controls;
using Snap.Hutao.Control;
using Snap.Hutao.Control.Extension;
using Snap.Hutao.Core.IO;
using Snap.Hutao.Core.Threading.CodeAnalysis;
using Snap.Hutao.Factory.Abstraction;
using Snap.Hutao.Model.Binding.Gacha;
using Snap.Hutao.Model.Entity;
@@ -29,6 +28,7 @@ internal class GachaLogViewModel : ObservableObject, ISupportCancellation
private readonly IGachaLogService gachaLogService;
private readonly IInfoBarService infoBarService;
private readonly IPickerFactory pickerFactory;
private readonly IContentDialogFactory contentDialogFactory;
private readonly JsonSerializerOptions options;
private ObservableCollection<GachaArchive>? archives;
@@ -45,26 +45,27 @@ internal class GachaLogViewModel : ObservableObject, ISupportCancellation
/// <param name="infoBarService">信息</param>
/// <param name="options">Json序列化选项</param>
/// <param name="asyncRelayCommandFactory">异步命令工厂</param>
/// <param name="contentDialogFactory">内容对话框工厂</param>
/// <param name="pickerFactory">文件选择器工厂</param>
public GachaLogViewModel(
IGachaLogService gachaLogService,
IInfoBarService infoBarService,
JsonSerializerOptions options,
IAsyncRelayCommandFactory asyncRelayCommandFactory,
IContentDialogFactory contentDialogFactory,
IPickerFactory pickerFactory)
{
this.gachaLogService = gachaLogService;
this.infoBarService = infoBarService;
this.pickerFactory = pickerFactory;
this.contentDialogFactory = contentDialogFactory;
this.options = options;
OpenUICommand = asyncRelayCommandFactory.Create(OpenUIAsync);
RefreshByWebCacheCommand = asyncRelayCommandFactory.Create(RefreshByWebCacheAsync);
RefreshByStokenCommand = asyncRelayCommandFactory.Create(RefreshByStokenAsync);
RefreshByManualInputCommand = asyncRelayCommandFactory.Create(RefreshByManualInputAsync);
ImportFromUIGFExcelCommand = asyncRelayCommandFactory.Create(ImportFromUIGFExcelAsync);
ImportFromUIGFJsonCommand = asyncRelayCommandFactory.Create(ImportFromUIGFJsonAsync);
ExportToUIGFExcelCommand = asyncRelayCommandFactory.Create(ExportToUIGFExcelAsync);
ExportToUIGFJsonCommand = asyncRelayCommandFactory.Create(ExportToUIGFJsonAsync);
RemoveArchiveCommand = asyncRelayCommandFactory.Create(RemoveArchiveAsync);
}
@@ -137,21 +138,11 @@ internal class GachaLogViewModel : ObservableObject, ISupportCancellation
/// </summary>
public ICommand RefreshByManualInputCommand { get; }
/// <summary>
/// 从 UIGF Excel 导入命令
/// </summary>
public ICommand ImportFromUIGFExcelCommand { get; }
/// <summary>
/// 从 UIGF Json 导入命令
/// </summary>
public ICommand ImportFromUIGFJsonCommand { get; }
/// <summary>
/// 导出到 UIGF Excel 命令
/// </summary>
public ICommand ExportToUIGFExcelCommand { get; }
/// <summary>
/// 导出到 UIGF Json 命令
/// </summary>
@@ -162,21 +153,6 @@ internal class GachaLogViewModel : ObservableObject, ISupportCancellation
/// </summary>
public ICommand RemoveArchiveCommand { get; }
[ThreadAccess(ThreadAccessState.MainThread)]
private static Task<ContentDialogResult> ShowImportResultDialogAsync(string title, string message)
{
ContentDialog dialog = new()
{
Title = title,
Content = message,
PrimaryButtonText = "确认",
DefaultButton = ContentDialogButton.Primary,
};
MainWindow mainWindow = Ioc.Default.GetRequiredService<MainWindow>();
return dialog.InitializeWithWindow(mainWindow).ShowAsync().AsTask();
}
private async Task OpenUIAsync()
{
if (await gachaLogService.InitializeAsync().ConfigureAwait(true))
@@ -216,9 +192,7 @@ internal class GachaLogViewModel : ObservableObject, ISupportCancellation
{
RefreshStrategy strategy = IsAggressiveRefresh ? RefreshStrategy.AggressiveMerge : RefreshStrategy.LazyMerge;
MainWindow mainWindow = Ioc.Default.GetRequiredService<MainWindow>();
await ThreadHelper.SwitchToMainThreadAsync();
GachaLogRefreshProgressDialog dialog = new(mainWindow);
GachaLogRefreshProgressDialog dialog = new();
IAsyncDisposable dialogHider = await dialog.BlockAsync().ConfigureAwait(false);
Progress<FetchState> progress = new(dialog.OnReport);
bool authkeyValid = await gachaLogService.RefreshGachaLogAsync(query, strategy, progress, default).ConfigureAwait(false);
@@ -246,11 +220,6 @@ internal class GachaLogViewModel : ObservableObject, ISupportCancellation
}
}
private async Task ImportFromUIGFExcelAsync()
{
await Task.Yield();
}
private async Task ImportFromUIGFJsonAsync()
{
FileOpenPicker picker = pickerFactory.GetFileOpenPicker(PickerLocationId.Desktop, "导入", ".json");
@@ -266,16 +235,11 @@ internal class GachaLogViewModel : ObservableObject, ISupportCancellation
else
{
await ThreadHelper.SwitchToMainThreadAsync();
await ShowImportResultDialogAsync("导入失败", "文件的数据格式不正确").ConfigureAwait(false);
await contentDialogFactory.CreateForConfirm("导入失败", "文件的数据格式不正确").ShowAsync();
}
}
}
private async Task ExportToUIGFExcelAsync()
{
await Task.Yield();
}
private async Task ExportToUIGFJsonAsync()
{
if (SelectedArchive == null)
@@ -297,11 +261,11 @@ internal class GachaLogViewModel : ObservableObject, ISupportCancellation
await ThreadHelper.SwitchToMainThreadAsync();
if (isOk)
{
await ShowImportResultDialogAsync("导出成功", "成功保存到指定位置").ConfigureAwait(false);
await contentDialogFactory.CreateForConfirm("导出成功", "成功保存到指定位置").ShowAsync();
}
else
{
await ShowImportResultDialogAsync("导出失败", "写入文件时遇到问题").ConfigureAwait(false);
await contentDialogFactory.CreateForConfirm("导出失败", "写入文件时遇到问题").ShowAsync();
}
}
}
@@ -310,17 +274,9 @@ internal class GachaLogViewModel : ObservableObject, ISupportCancellation
{
if (Archives != null && SelectedArchive != null)
{
ContentDialog dialog = new()
{
Title = $"确定要删除存档 {SelectedArchive.Uid} 吗?",
Content = "该操作是不可逆的,该存档和其内的所有祈愿数据会丢失。",
PrimaryButtonText = "确认",
CloseButtonText = "取消",
DefaultButton = ContentDialogButton.Close,
};
MainWindow mainWindow = Ioc.Default.GetRequiredService<MainWindow>();
ContentDialogResult result = await dialog.InitializeWithWindow(mainWindow).ShowAsync();
ContentDialogResult result = await contentDialogFactory
.CreateForConfirmCancel($"确定要删除存档 {SelectedArchive.Uid} 吗?", "该操作是不可逆的,该存档和其内的所有祈愿数据会丢失。")
.ShowAsync();
if (result == ContentDialogResult.Primary)
{
@@ -332,7 +288,6 @@ internal class GachaLogViewModel : ObservableObject, ISupportCancellation
}
}
[ThreadAccess(ThreadAccessState.MainThread)]
private void SetSelectedArchiveAndUpdateStatistics(GachaArchive? archive, bool forceUpdate = false)
{
bool changed = false;
@@ -357,7 +312,6 @@ internal class GachaLogViewModel : ObservableObject, ISupportCancellation
}
}
[ThreadAccess(ThreadAccessState.MainThread)]
private async Task UpdateStatisticsAsync(GachaArchive? archive)
{
GachaStatistics temp = await gachaLogService.GetStatisticsAsync(archive).ConfigureAwait(false);
@@ -365,22 +319,13 @@ internal class GachaLogViewModel : ObservableObject, ISupportCancellation
Statistics = temp;
}
[ThreadAccess(ThreadAccessState.AnyThread)]
private async Task<bool> TryImportUIGFInternalAsync(UIGF uigf)
{
if (uigf.IsCurrentVersionSupported())
{
MainWindow mainWindow = Ioc.Default.GetRequiredService<MainWindow>();
await ThreadHelper.SwitchToMainThreadAsync();
if (await new GachaLogImportDialog(mainWindow, uigf).GetShouldImportAsync().ConfigureAwait(true))
if (await new GachaLogImportDialog(uigf).GetShouldImportAsync().ConfigureAwait(true))
{
ContentDialog importingDialog = new()
{
Title = "导入祈愿记录中",
Content = new ProgressBar() { IsIndeterminate = true },
};
await using (await importingDialog.InitializeWithWindow(mainWindow).BlockAsync().ConfigureAwait(false))
await using (await contentDialogFactory.CreateForIndeterminateProgress("导入祈愿记录中").BlockAsync().ConfigureAwait(false))
{
await gachaLogService.ImportFromUIGFAsync(uigf.List, uigf.Info.Uid).ConfigureAwait(false);
}
@@ -394,7 +339,7 @@ internal class GachaLogViewModel : ObservableObject, ISupportCancellation
else
{
await ThreadHelper.SwitchToMainThreadAsync();
await ShowImportResultDialogAsync("导入失败", "数据的 UIGF 版本过低,无法导入").ConfigureAwait(false);
await contentDialogFactory.CreateForConfirm("导入失败", "数据的 UIGF 版本过低,无法导入").ShowAsync();
}
return false;

View File

@@ -207,10 +207,9 @@ internal class SettingViewModel : ObservableObject
}
}
private async Task ShowSignInWebViewDialogAsync()
private Task ShowSignInWebViewDialogAsync()
{
MainWindow mainWindow = Ioc.Default.GetRequiredService<MainWindow>();
await new SignInWebViewDialog(mainWindow).ShowAsync();
return new SignInWebViewDialog().ShowAsync().AsTask();
}
private async Task DebugThrowExceptionAsync()

View File

@@ -29,6 +29,7 @@ internal class TestViewModel : ObservableObject, ISupportCancellation
public TestViewModel(IAsyncRelayCommandFactory asyncRelayCommandFactory)
{
ShowCommunityGameRecordDialogCommand = asyncRelayCommandFactory.Create(ShowCommunityGameRecordDialogAsync);
ShowAdoptCalculatorDialogCommand = asyncRelayCommandFactory.Create(ShowAdoptCalculatorDialogAsync);
DangerousLoginMihoyoBbsCommand = asyncRelayCommandFactory.Create(DangerousLoginMihoyoBbsAsync);
DownloadStaticFileCommand = asyncRelayCommandFactory.Create(DownloadStaticFileAsync);
}
@@ -41,6 +42,11 @@ internal class TestViewModel : ObservableObject, ISupportCancellation
/// </summary>
public ICommand ShowCommunityGameRecordDialogCommand { get; }
/// <summary>
/// 打开养成计算对话框命令
/// </summary>
public ICommand ShowAdoptCalculatorDialogCommand { get; }
/// <summary>
/// Dangerous 登录米游社命令
/// </summary>
@@ -53,14 +59,17 @@ internal class TestViewModel : ObservableObject, ISupportCancellation
private async Task ShowCommunityGameRecordDialogAsync()
{
CommunityGameRecordDialog dialog = ActivatorUtilities.CreateInstance<CommunityGameRecordDialog>(Ioc.Default);
await dialog.ShowAsync();
await new CommunityGameRecordDialog().ShowAsync();
}
private async Task ShowAdoptCalculatorDialogAsync()
{
await new AdoptCalculatorDialog().ShowAsync();
}
private async Task DangerousLoginMihoyoBbsAsync()
{
LoginMihoyoBBSDialog dialog = ActivatorUtilities.CreateInstance<LoginMihoyoBBSDialog>(Ioc.Default);
(bool isOk, Dictionary<string, string>? data) = await dialog.GetInputAccountPasswordAsync().ConfigureAwait(false);
(bool isOk, Dictionary<string, string>? data) = await new LoginMihoyoBBSDialog().GetInputAccountPasswordAsync().ConfigureAwait(false);
if (isOk)
{

View File

@@ -107,8 +107,7 @@ internal class UserViewModel : ObservableObject
private async Task AddUserAsync()
{
// Get cookie from user input
MainWindow mainWindow = Ioc.Default.GetRequiredService<MainWindow>();
ValueResult<bool, string> result = await new UserDialog(mainWindow).GetInputCookieAsync().ConfigureAwait(false);
ValueResult<bool, string> result = await new UserDialog().GetInputCookieAsync().ConfigureAwait(false);
// User confirms the input
if (result.IsOk)

View File

@@ -71,6 +71,7 @@ internal class WelcomeViewModel : ObservableObject
downloadSummaries.Add(new(serviceProvider, "成就图标", "AchievementIcon"));
downloadSummaries.Add(new(serviceProvider, "物品图标", "ItemIcon"));
downloadSummaries.Add(new(serviceProvider, "元素图标", "IconElement"));
downloadSummaries.Add(new(serviceProvider, "圣遗物图标", "RelicIcon"));
}
DownloadSummaries = new(downloadSummaries);

View File

@@ -129,8 +129,7 @@ internal class WikiAvatarViewModel : ObservableObject
if (userService.Current != null)
{
MainWindow mainWindow = Ioc.Default.GetRequiredService<MainWindow>();
(bool isOk, CalcAvatarPromotionDelta delta) = await new CultivatePromotionDeltaDialog(mainWindow, avatar.ToCalculable(), null)
(bool isOk, CalcAvatarPromotionDelta delta) = await new CultivatePromotionDeltaDialog(avatar.ToCalculable(), null)
.GetPromotionDeltaAsync()
.ConfigureAwait(false);

View File

@@ -132,8 +132,7 @@ internal class WikiWeaponViewModel : ObservableObject, ISupportCancellation
if (userService.Current != null)
{
MainWindow mainWindow = Ioc.Default.GetRequiredService<MainWindow>();
(bool isOk, CalcAvatarPromotionDelta delta) = await new CultivatePromotionDeltaDialog(mainWindow, null, weapon.ToCalculable())
(bool isOk, CalcAvatarPromotionDelta delta) = await new CultivatePromotionDeltaDialog(null, weapon.ToCalculable())
.GetPromotionDeltaAsync()
.ConfigureAwait(false);