mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
fix QA issue
This commit is contained in:
@@ -10,6 +10,7 @@ using Snap.Hutao.Core.Caching;
|
||||
using Snap.Hutao.Core.Graphics;
|
||||
using Snap.Hutao.Service.Notification;
|
||||
using Snap.Hutao.UI.Xaml.Media.Animation;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Runtime.InteropServices;
|
||||
@@ -17,11 +18,6 @@ using Windows.Foundation;
|
||||
|
||||
namespace Snap.Hutao.UI.Xaml.Control.Image;
|
||||
|
||||
/// <summary>
|
||||
/// 合成图像控件
|
||||
/// 为其他图像类控件提供基类
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
[DependencyProperty("EnableShowHideAnimation", typeof(bool), true)]
|
||||
[DependencyProperty("Source", typeof(Uri), default!, nameof(OnSourceChanged))]
|
||||
internal abstract partial class CompositionImage : Microsoft.UI.Xaml.Controls.Control
|
||||
@@ -30,48 +26,38 @@ internal abstract partial class CompositionImage : Microsoft.UI.Xaml.Controls.Co
|
||||
|
||||
private readonly IServiceProvider serviceProvider;
|
||||
|
||||
private readonly SizeChangedEventHandler sizeChangedEventHandler;
|
||||
private readonly TypedEventHandler<LoadedImageSurface, LoadedImageSourceLoadCompletedEventArgs> loadedImageSourceLoadCompletedEventHandler;
|
||||
|
||||
private TaskCompletionSource? surfaceLoadTaskCompletionSource;
|
||||
private SpriteVisual? spriteVisual;
|
||||
private bool isShow = true;
|
||||
|
||||
/// <summary>
|
||||
/// 构造一个新的单色图像
|
||||
/// </summary>
|
||||
protected CompositionImage()
|
||||
{
|
||||
serviceProvider = this.ServiceProvider();
|
||||
this.DisableInteraction();
|
||||
|
||||
sizeChangedEventHandler = OnSizeChanged;
|
||||
SizeChanged += sizeChangedEventHandler;
|
||||
|
||||
loadedImageSourceLoadCompletedEventHandler = OnLoadImageSurfaceLoadCompleted;
|
||||
SizeChanged += OnSizeChanged;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 合成组合视觉
|
||||
/// </summary>
|
||||
/// <param name="compositor">合成器</param>
|
||||
/// <param name="imageSurface">图像表面</param>
|
||||
/// <returns>拼合视觉</returns>
|
||||
protected abstract SpriteVisual CompositeSpriteVisual(Compositor compositor, LoadedImageSurface imageSurface);
|
||||
|
||||
protected virtual void LoadImageSurfaceCompleted(LoadedImageSurface surface)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新视觉对象
|
||||
/// </summary>
|
||||
/// <param name="spriteVisual">拼合视觉</param>
|
||||
protected virtual void UpdateVisual(SpriteVisual spriteVisual)
|
||||
{
|
||||
spriteVisual.Size = ActualSize;
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate()
|
||||
{
|
||||
base.OnApplyTemplate();
|
||||
if (!string.IsNullOrEmpty(Source.OriginalString))
|
||||
{
|
||||
OnSourceChangedCore(Source);
|
||||
}
|
||||
}
|
||||
|
||||
private static void OnSourceChanged(DependencyObject sender, DependencyPropertyChangedEventArgs arg)
|
||||
{
|
||||
CompositionImage image = (CompositionImage)sender;
|
||||
@@ -87,9 +73,7 @@ internal abstract partial class CompositionImage : Microsoft.UI.Xaml.Controls.Co
|
||||
// value is different from old one
|
||||
if (inner != (arg.OldValue as Uri))
|
||||
{
|
||||
image
|
||||
.ApplyImageAsync(inner, token)
|
||||
.SafeForget(logger, ex => OnApplyImageFailed(serviceProvider, inner, ex));
|
||||
image.OnSourceChangedCore(inner);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -101,6 +85,7 @@ internal abstract partial class CompositionImage : Microsoft.UI.Xaml.Controls.Co
|
||||
|
||||
private static void OnApplyImageFailed(IServiceProvider serviceProvider, Uri? uri, Exception exception)
|
||||
{
|
||||
Debugger.Break();
|
||||
IInfoBarService infoBarService = serviceProvider.GetRequiredService<IInfoBarService>();
|
||||
|
||||
if (exception is HttpRequestException httpRequestException)
|
||||
@@ -117,6 +102,13 @@ internal abstract partial class CompositionImage : Microsoft.UI.Xaml.Controls.Co
|
||||
}
|
||||
}
|
||||
|
||||
private void OnSourceChangedCore(Uri? uri)
|
||||
{
|
||||
CancellationToken token = loadingTokenSource.Register();
|
||||
ILogger<CompositionImage> logger = serviceProvider.GetRequiredService<ILogger<CompositionImage>>();
|
||||
ApplyImageAsync(uri, token).SafeForget(logger, ex => OnApplyImageFailed(serviceProvider, uri, ex));
|
||||
}
|
||||
|
||||
private async ValueTask ApplyImageAsync(Uri? uri, CancellationToken token)
|
||||
{
|
||||
await HideAsync(token).ConfigureAwait(true);
|
||||
@@ -154,21 +146,28 @@ internal abstract partial class CompositionImage : Microsoft.UI.Xaml.Controls.Co
|
||||
await ShowAsync(token).ConfigureAwait(true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debugger.Break();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async ValueTask<LoadedImageSurface> LoadImageSurfaceAsync(string file, CancellationToken token)
|
||||
{
|
||||
token.ThrowIfCancellationRequested();
|
||||
TaskCompletionSource cancelTcs = new();
|
||||
CancellationTokenRegistration registration = token.Register(() => cancelTcs.TrySetResult(), false);
|
||||
|
||||
surfaceLoadTaskCompletionSource = new();
|
||||
LoadedImageSurface? surface = default;
|
||||
try
|
||||
{
|
||||
surface = LoadedImageSurface.StartLoadFromUri(file.ToUri());
|
||||
surface.LoadCompleted += loadedImageSourceLoadCompletedEventHandler;
|
||||
surface.LoadCompleted += OnLoadImageSurfaceLoadCompleted;
|
||||
if (surface.DecodedPhysicalSize.Size() <= 0D)
|
||||
{
|
||||
await Task.WhenAny(surfaceLoadTaskCompletionSource.Task, Task.Delay(5000, token)).ConfigureAwait(true);
|
||||
await Task.Delay(50, token).ConfigureAwait(true);
|
||||
await Task.WhenAny(surfaceLoadTaskCompletionSource.Task, cancelTcs.Task).ConfigureAwait(true);
|
||||
}
|
||||
|
||||
LoadImageSurfaceCompleted(surface);
|
||||
@@ -178,8 +177,10 @@ internal abstract partial class CompositionImage : Microsoft.UI.Xaml.Controls.Co
|
||||
{
|
||||
if (surface is not null)
|
||||
{
|
||||
surface.LoadCompleted -= loadedImageSourceLoadCompletedEventHandler;
|
||||
surface.LoadCompleted -= OnLoadImageSurfaceLoadCompleted;
|
||||
}
|
||||
|
||||
registration.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,26 +12,15 @@ using Windows.Foundation;
|
||||
|
||||
namespace Snap.Hutao.UI.Xaml.Control.Image;
|
||||
|
||||
/// <summary>
|
||||
/// 支持单色的图像
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
internal sealed class MonoChrome : CompositionImage
|
||||
{
|
||||
private readonly TypedEventHandler<FrameworkElement, object> actualThemeChangedEventHandler;
|
||||
|
||||
private CompositionColorBrush? backgroundBrush;
|
||||
|
||||
/// <summary>
|
||||
/// 构造一个新的单色图像
|
||||
/// </summary>
|
||||
public MonoChrome()
|
||||
{
|
||||
actualThemeChangedEventHandler = OnActualThemeChanged;
|
||||
ActualThemeChanged += actualThemeChangedEventHandler;
|
||||
ActualThemeChanged += OnActualThemeChanged;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override SpriteVisual CompositeSpriteVisual(Compositor compositor, LoadedImageSurface imageSurface)
|
||||
{
|
||||
CompositionColorBrush blackLayerBrush = compositor.CreateColorBrush(Colors.Black);
|
||||
|
||||
@@ -188,6 +188,7 @@ internal sealed partial class UniformStaggeredLayout : VirtualizingLayout
|
||||
}
|
||||
|
||||
UniformStaggeredLayoutState state = (UniformStaggeredLayoutState)context.LayoutState;
|
||||
int virtualColumnCount = (int)(finalSize.Width / state.ColumnWidth);
|
||||
|
||||
// Cycle through each column and arrange the items that are within the realization bounds
|
||||
for (int columnIndex = 0; columnIndex < state.NumberOfColumns; columnIndex++)
|
||||
@@ -204,9 +205,9 @@ internal sealed partial class UniformStaggeredLayout : VirtualizingLayout
|
||||
// Partial or fully in the view
|
||||
if (item.Top <= context.RealizationRect.Bottom)
|
||||
{
|
||||
double itemHorizontalOffset = (state.ColumnWidth * columnIndex) + (MinColumnSpacing * columnIndex);
|
||||
double itemHorizontalOffset = (state.ColumnWidth + MinColumnSpacing) * columnIndex;
|
||||
|
||||
double width = columnIndex == state.NumberOfColumns - 1
|
||||
double width = columnIndex == virtualColumnCount - 1
|
||||
? finalSize.Width - itemHorizontalOffset
|
||||
: state.ColumnWidth;
|
||||
|
||||
|
||||
@@ -20,9 +20,20 @@ internal sealed partial class SizeRestrictedContentControl : ContentControl
|
||||
{
|
||||
element.Measure(availableSize);
|
||||
Size contentDesiredSize = element.DesiredSize;
|
||||
|
||||
Size contentActualOrDesiredSize = new(
|
||||
Math.Min(Math.Max(element.ActualWidth, contentDesiredSize.Width), availableSize.Width),
|
||||
Math.Min(Math.Max(element.ActualHeight, contentDesiredSize.Height), availableSize.Height));
|
||||
Math.Clamp(element.ActualWidth, contentDesiredSize.Width, availableSize.Width),
|
||||
Math.Clamp(element.ActualHeight, contentDesiredSize.Height, availableSize.Height));
|
||||
|
||||
if (minContentWidth > availableSize.Width)
|
||||
{
|
||||
minContentWidth = 0;
|
||||
}
|
||||
|
||||
if (minContentHeight > availableSize.Height)
|
||||
{
|
||||
minContentHeight = 0;
|
||||
}
|
||||
|
||||
if (IsWidthRestricted)
|
||||
{
|
||||
|
||||
@@ -154,7 +154,7 @@
|
||||
ItemsSource="{Binding List}">
|
||||
<ItemsRepeater.Layout>
|
||||
<UniformGridLayout
|
||||
ItemsJustification="SpaceBetween"
|
||||
ItemsJustification="Start"
|
||||
ItemsStretch="Fill"
|
||||
MinColumnSpacing="12"
|
||||
MinItemWidth="300"
|
||||
|
||||
@@ -484,7 +484,10 @@
|
||||
ItemsSource="{Binding DailyNoteOptions.RefreshTimes}"
|
||||
SelectedItem="{Binding DailyNoteOptions.SelectedRefreshTime, Mode=TwoWay}">
|
||||
<RadioButtons.Header>
|
||||
<TextBlock Style="{StaticResource BaseTextBlockStyle}" Text="{shuxm:ResourceString Name=ViewPageDailyNoteRefreshTime}"/>
|
||||
<TextBlock
|
||||
Margin="1,0,0,0"
|
||||
Style="{StaticResource BaseTextBlockStyle}"
|
||||
Text="{shuxm:ResourceString Name=ViewPageDailyNoteRefreshTime}"/>
|
||||
</RadioButtons.Header>
|
||||
<RadioButtons.ItemTemplate>
|
||||
<DataTemplate>
|
||||
@@ -547,7 +550,7 @@
|
||||
ItemsSource="{Binding DailyNoteEntries}">
|
||||
<ItemsRepeater.Layout>
|
||||
<UniformGridLayout
|
||||
ItemsJustification="SpaceBetween"
|
||||
ItemsJustification="Start"
|
||||
ItemsStretch="Fill"
|
||||
MinColumnSpacing="12"
|
||||
MinItemWidth="300"
|
||||
|
||||
@@ -426,11 +426,14 @@
|
||||
Height="32"
|
||||
Source="{Binding Selected.Weapon, Converter={StaticResource WeaponTypeIconConverter}}"/>
|
||||
</Grid>
|
||||
<shuxc:ItemIcon
|
||||
Width="128"
|
||||
Height="128"
|
||||
Icon="{Binding Selected.Icon, Converter={StaticResource AvatarIconConverter}, Mode=OneWay}"
|
||||
Quality="{Binding Selected.Quality, Mode=OneWay}"/>
|
||||
<Border Style="{ThemeResource BorderCardStyle}">
|
||||
<shuxc:ItemIcon
|
||||
Width="128"
|
||||
Height="128"
|
||||
Icon="{Binding Selected.Icon, Converter={StaticResource AvatarIconConverter}, Mode=OneWay}"
|
||||
Quality="{Binding Selected.Quality, Mode=OneWay}"/>
|
||||
</Border>
|
||||
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Grid.Column="1" Margin="16">
|
||||
@@ -524,19 +527,21 @@
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Grid.Row="1" Grid.ColumnSpan="2">
|
||||
<ItemsControl
|
||||
Margin="16,0,16,16"
|
||||
ItemTemplate="{StaticResource CultivationItemTemplate}"
|
||||
ItemsSource="{Binding Selected.CultivationItemsView}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<cwc:UniformGrid
|
||||
ColumnSpacing="8"
|
||||
Columns="3"
|
||||
RowSpacing="8"/>
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
</ItemsControl>
|
||||
<ScrollViewer>
|
||||
<ItemsRepeater
|
||||
Margin="16,0,16,16"
|
||||
ItemTemplate="{StaticResource CultivationItemTemplate}"
|
||||
ItemsSource="{Binding Selected.CultivationItemsView}">
|
||||
<ItemsRepeater.Layout>
|
||||
<UniformGridLayout
|
||||
ItemsJustification="Start"
|
||||
ItemsStretch="Fill"
|
||||
MaximumRowsOrColumns="3"
|
||||
MinColumnSpacing="8"
|
||||
MinRowSpacing="8"/>
|
||||
</ItemsRepeater.Layout>
|
||||
</ItemsRepeater>
|
||||
</ScrollViewer>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate x:Key="CultivateItemTemplate">
|
||||
<DataTemplate x:Key="CultivationItemTemplate">
|
||||
<shuxcc:HorizontalCard>
|
||||
<shuxcc:HorizontalCard.Left>
|
||||
<shuxc:ItemIcon
|
||||
@@ -257,63 +257,61 @@
|
||||
</StackPanel>
|
||||
<ScrollViewer Visibility="{Binding Weapons.Count, Converter={StaticResource Int32ToVisibilityConverter}}">
|
||||
<StackPanel Padding="16" Spacing="16">
|
||||
<Border cw:Effects.Shadow="{ThemeResource CompatCardShadow}">
|
||||
<Border Style="{ThemeResource AcrylicBorderCardStyle}">
|
||||
<Border.Background>
|
||||
<ImageBrush ImageSource="ms-appx:///Resource/Icon/UI_GachaShowPanel_Bg_Weapon.png"/>
|
||||
</Border.Background>
|
||||
<cwc:ConstrainedBox AspectRatio="2048:1024">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
<ColumnDefinition/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Border Grid.ColumnSpan="2" Background="{ThemeResource DarkOnlyOverlayMaskColorBrush}"/>
|
||||
<Border Style="{ThemeResource BorderCardStyle}">
|
||||
<Border.Background>
|
||||
<ImageBrush ImageSource="ms-appx:///Resource/Icon/UI_GachaShowPanel_Bg_Weapon.png"/>
|
||||
</Border.Background>
|
||||
<cwc:ConstrainedBox AspectRatio="2048:1024">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
<ColumnDefinition/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Border Grid.ColumnSpan="2" Background="{ThemeResource DarkOnlyOverlayMaskColorBrush}"/>
|
||||
|
||||
<Grid Grid.ColumnSpan="2">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="176*"/>
|
||||
<ColumnDefinition Width="848*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<shuxci:CachedImage
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Stretch"
|
||||
Source="{Binding Selected.Icon, Converter={StaticResource GachaEquipIconConverter}}"/>
|
||||
</Grid>
|
||||
<ScrollViewer
|
||||
Grid.Column="0"
|
||||
Margin="16"
|
||||
VerticalScrollBarVisibility="Hidden">
|
||||
<StackPanel Spacing="16">
|
||||
<shuxcc:VerticalCard MaxWidth="80">
|
||||
<shuxcc:VerticalCard.Top>
|
||||
<shuxc:ItemIcon Icon="{Binding Selected.Icon, Converter={StaticResource EquipIconConverter}}" Quality="{Binding Selected.RankLevel}"/>
|
||||
</shuxcc:VerticalCard.Top>
|
||||
<shuxcc:VerticalCard.Bottom>
|
||||
<TextBlock Text="{shuxm:ResourceString Name=ViewPageWiKiWeaponBeforeAscensionTitle}"/>
|
||||
</shuxcc:VerticalCard.Bottom>
|
||||
</shuxcc:VerticalCard>
|
||||
<shuxcc:VerticalCard MaxWidth="80">
|
||||
<shuxcc:VerticalCard.Top>
|
||||
<shuxc:ItemIcon Icon="{Binding Selected.AwakenIcon, Converter={StaticResource EquipIconConverter}}" Quality="{Binding Selected.RankLevel}"/>
|
||||
</shuxcc:VerticalCard.Top>
|
||||
<shuxcc:VerticalCard.Bottom>
|
||||
<TextBlock Text="{shuxm:ResourceString Name=ViewPageWiKiWeaponAfterAscensionTitle}"/>
|
||||
</shuxcc:VerticalCard.Bottom>
|
||||
</shuxcc:VerticalCard>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
<TextBlock
|
||||
<Grid Grid.ColumnSpan="2">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="176*"/>
|
||||
<ColumnDefinition Width="848*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<shuxci:CachedImage
|
||||
Grid.Column="1"
|
||||
Margin="16"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Bottom"
|
||||
Style="{StaticResource SubtitleTextBlockStyle}"
|
||||
Text="{Binding Selected.Name}"/>
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Stretch"
|
||||
Source="{Binding Selected.Icon, Converter={StaticResource GachaEquipIconConverter}}"/>
|
||||
</Grid>
|
||||
</cwc:ConstrainedBox>
|
||||
</Border>
|
||||
<ScrollViewer
|
||||
Grid.Column="0"
|
||||
Margin="16"
|
||||
VerticalScrollBarVisibility="Hidden">
|
||||
<StackPanel Spacing="16">
|
||||
<shuxcc:VerticalCard MaxWidth="80">
|
||||
<shuxcc:VerticalCard.Top>
|
||||
<shuxc:ItemIcon Icon="{Binding Selected.Icon, Converter={StaticResource EquipIconConverter}}" Quality="{Binding Selected.RankLevel}"/>
|
||||
</shuxcc:VerticalCard.Top>
|
||||
<shuxcc:VerticalCard.Bottom>
|
||||
<TextBlock Text="{shuxm:ResourceString Name=ViewPageWiKiWeaponBeforeAscensionTitle}"/>
|
||||
</shuxcc:VerticalCard.Bottom>
|
||||
</shuxcc:VerticalCard>
|
||||
<shuxcc:VerticalCard MaxWidth="80">
|
||||
<shuxcc:VerticalCard.Top>
|
||||
<shuxc:ItemIcon Icon="{Binding Selected.AwakenIcon, Converter={StaticResource EquipIconConverter}}" Quality="{Binding Selected.RankLevel}"/>
|
||||
</shuxcc:VerticalCard.Top>
|
||||
<shuxcc:VerticalCard.Bottom>
|
||||
<TextBlock Text="{shuxm:ResourceString Name=ViewPageWiKiWeaponAfterAscensionTitle}"/>
|
||||
</shuxcc:VerticalCard.Bottom>
|
||||
</shuxcc:VerticalCard>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
<TextBlock
|
||||
Grid.Column="1"
|
||||
Margin="16"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Bottom"
|
||||
Style="{StaticResource SubtitleTextBlockStyle}"
|
||||
Text="{Binding Selected.Name}"/>
|
||||
</Grid>
|
||||
</cwc:ConstrainedBox>
|
||||
</Border>
|
||||
|
||||
<TextBlock
|
||||
@@ -332,16 +330,18 @@
|
||||
Margin="0,0,0,0"
|
||||
Style="{StaticResource BaseTextBlockStyle}"
|
||||
Text="{shuxm:ResourceString Name=ViewPageWiKiAvatarAscensionMaterialsHeader}"/>
|
||||
<ItemsControl ItemTemplate="{StaticResource CultivateItemTemplate}" ItemsSource="{Binding Selected.CultivationItemsView}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<cwc:UniformGrid
|
||||
ColumnSpacing="8"
|
||||
Columns="3"
|
||||
RowSpacing="8"/>
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
</ItemsControl>
|
||||
<ScrollViewer>
|
||||
<ItemsRepeater ItemTemplate="{StaticResource CultivationItemTemplate}" ItemsSource="{Binding Selected.CultivationItemsView}">
|
||||
<ItemsRepeater.Layout>
|
||||
<UniformGridLayout
|
||||
ItemsJustification="Start"
|
||||
ItemsStretch="Fill"
|
||||
MaximumRowsOrColumns="3"
|
||||
MinColumnSpacing="8"
|
||||
MinRowSpacing="8"/>
|
||||
</ItemsRepeater.Layout>
|
||||
</ItemsRepeater>
|
||||
</ScrollViewer>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
|
||||
@@ -104,9 +104,10 @@ internal sealed class UserInfo
|
||||
{
|
||||
get
|
||||
{
|
||||
string source = AvatarUrl.OriginalString;
|
||||
string? source = AvatarUrl?.OriginalString;
|
||||
if (!string.IsNullOrEmpty(source))
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(AvatarUrl);
|
||||
return AvatarUrl;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user