mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
refactor cached image
This commit is contained in:
@@ -23,13 +23,10 @@ internal sealed class CachedImage : Implementation.ImageEx
|
|||||||
{
|
{
|
||||||
DefaultStyleKey = typeof(CachedImage);
|
DefaultStyleKey = typeof(CachedImage);
|
||||||
DefaultStyleResourceUri = "ms-appx:///Control/Image/CachedImage.xaml".ToUri();
|
DefaultStyleResourceUri = "ms-appx:///Control/Image/CachedImage.xaml".ToUri();
|
||||||
|
|
||||||
IsCacheEnabled = true;
|
|
||||||
EnableLazyLoading = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
protected override async Task<ImageSource?> ProvideCachedResourceAsync(Uri imageUri, CancellationToken token)
|
protected override async Task<Uri?> ProvideCachedResourceAsync(Uri imageUri, CancellationToken token)
|
||||||
{
|
{
|
||||||
IImageCache imageCache = this.ServiceProvider().GetRequiredService<IImageCache>();
|
IImageCache imageCache = this.ServiceProvider().GetRequiredService<IImageCache>();
|
||||||
|
|
||||||
@@ -38,10 +35,7 @@ internal sealed class CachedImage : Implementation.ImageEx
|
|||||||
HutaoException.ThrowIf(string.IsNullOrEmpty(imageUri.Host), SH.ControlImageCachedImageInvalidResourceUri);
|
HutaoException.ThrowIf(string.IsNullOrEmpty(imageUri.Host), SH.ControlImageCachedImageInvalidResourceUri);
|
||||||
string file = await imageCache.GetFileFromCacheAsync(imageUri).ConfigureAwait(true); // BitmapImage need to be created by main thread.
|
string file = await imageCache.GetFileFromCacheAsync(imageUri).ConfigureAwait(true); // BitmapImage need to be created by main thread.
|
||||||
token.ThrowIfCancellationRequested(); // check token state to determine whether the operation should be canceled.
|
token.ThrowIfCancellationRequested(); // check token state to determine whether the operation should be canceled.
|
||||||
|
return file.ToUri();
|
||||||
// https://learn.microsoft.com/en-us/windows/uwp/debug-test-perf/optimize-animations-and-media#optimize-image-resources
|
|
||||||
// BitmapImage initialize with a uri will increase image quality and loading speed.
|
|
||||||
return new BitmapImage(file.ToUri());
|
|
||||||
}
|
}
|
||||||
catch (COMException)
|
catch (COMException)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
<Setter Property="Background" Value="Transparent"/>
|
<Setter Property="Background" Value="Transparent"/>
|
||||||
<Setter Property="Foreground" Value="{ThemeResource ApplicationForegroundThemeBrush}"/>
|
<Setter Property="Foreground" Value="{ThemeResource ApplicationForegroundThemeBrush}"/>
|
||||||
<Setter Property="IsTabStop" Value="False"/>
|
<Setter Property="IsTabStop" Value="False"/>
|
||||||
<Setter Property="LazyLoadingThreshold" Value="256"/>
|
|
||||||
<Setter Property="Template">
|
<Setter Property="Template">
|
||||||
<Setter.Value>
|
<Setter.Value>
|
||||||
<ControlTemplate TargetType="shci:CachedImage">
|
<ControlTemplate TargetType="shci:CachedImage">
|
||||||
|
|||||||
@@ -21,12 +21,6 @@ namespace Snap.Hutao.Control.Image.Implementation;
|
|||||||
[TemplatePart(Name = PartImage, Type = typeof(object))]
|
[TemplatePart(Name = PartImage, Type = typeof(object))]
|
||||||
[TemplatePart(Name = PartPlaceholderImage, Type = typeof(object))]
|
[TemplatePart(Name = PartPlaceholderImage, Type = typeof(object))]
|
||||||
[DependencyProperty("Stretch", typeof(Stretch), Stretch.Uniform)]
|
[DependencyProperty("Stretch", typeof(Stretch), Stretch.Uniform)]
|
||||||
[DependencyProperty("DecodePixelHeight", typeof(int), 0)]
|
|
||||||
[DependencyProperty("DecodePixelWidth", typeof(int), 0)]
|
|
||||||
[DependencyProperty("DecodePixelType", typeof(DecodePixelType), DecodePixelType.Physical)]
|
|
||||||
[DependencyProperty("IsCacheEnabled", typeof(bool), false)]
|
|
||||||
[DependencyProperty("EnableLazyLoading", typeof(bool), false, nameof(EnableLazyLoadingChanged))]
|
|
||||||
[DependencyProperty("LazyLoadingThreshold", typeof(double), default(double), nameof(LazyLoadingThresholdChanged))]
|
|
||||||
[DependencyProperty("PlaceholderSource", typeof(object), default(object))]
|
[DependencyProperty("PlaceholderSource", typeof(object), default(object))]
|
||||||
[DependencyProperty("PlaceholderStretch", typeof(Stretch), Stretch.Uniform)]
|
[DependencyProperty("PlaceholderStretch", typeof(Stretch), Stretch.Uniform)]
|
||||||
[DependencyProperty("PlaceholderMargin", typeof(Thickness))]
|
[DependencyProperty("PlaceholderMargin", typeof(Thickness))]
|
||||||
@@ -42,8 +36,6 @@ internal abstract partial class ImageExBase : Microsoft.UI.Xaml.Controls.Control
|
|||||||
protected const string FailedState = "Failed";
|
protected const string FailedState = "Failed";
|
||||||
|
|
||||||
private CancellationTokenSource? tokenSource;
|
private CancellationTokenSource? tokenSource;
|
||||||
private object? lazyLoadingSource;
|
|
||||||
private bool isInViewport;
|
|
||||||
|
|
||||||
public bool IsInitialized { get; private set; }
|
public bool IsInitialized { get; private set; }
|
||||||
|
|
||||||
@@ -58,10 +50,10 @@ internal abstract partial class ImageExBase : Microsoft.UI.Xaml.Controls.Control
|
|||||||
|
|
||||||
public abstract CompositionBrush GetAlphaMask();
|
public abstract CompositionBrush GetAlphaMask();
|
||||||
|
|
||||||
protected virtual Task<ImageSource?> ProvideCachedResourceAsync(Uri imageUri, CancellationToken token)
|
protected virtual Task<Uri?> ProvideCachedResourceAsync(Uri imageUri, CancellationToken token)
|
||||||
{
|
{
|
||||||
// By default we just use the built-in UWP image cache provided within the Image control.
|
// By default we just use the built-in UWP image cache provided within the Image control.
|
||||||
return Task.FromResult<ImageSource?>(new BitmapImage(imageUri));
|
return Task.FromResult<Uri?>(imageUri);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void OnImageOpened(object sender, RoutedEventArgs e)
|
protected virtual void OnImageOpened(object sender, RoutedEventArgs e)
|
||||||
@@ -80,19 +72,10 @@ internal abstract partial class ImageExBase : Microsoft.UI.Xaml.Controls.Control
|
|||||||
RemoveImageFailed(OnImageFailed);
|
RemoveImageFailed(OnImageFailed);
|
||||||
|
|
||||||
Image = GetTemplateChild(PartImage);
|
Image = GetTemplateChild(PartImage);
|
||||||
PlaceholderImage = GetTemplateChild(PartPlaceholderImage);
|
|
||||||
|
|
||||||
IsInitialized = true;
|
IsInitialized = true;
|
||||||
|
|
||||||
if (Source is null || !EnableLazyLoading || isInViewport)
|
SetSource(Source);
|
||||||
{
|
|
||||||
lazyLoadingSource = null;
|
|
||||||
SetSource(Source);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lazyLoadingSource = Source;
|
|
||||||
}
|
|
||||||
|
|
||||||
AttachImageOpened(OnImageOpened);
|
AttachImageOpened(OnImageOpened);
|
||||||
AttachImageFailed(OnImageFailed);
|
AttachImageFailed(OnImageFailed);
|
||||||
@@ -148,33 +131,6 @@ internal abstract partial class ImageExBase : Microsoft.UI.Xaml.Controls.Control
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void EnableLazyLoadingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
|
||||||
{
|
|
||||||
if (d is not ImageExBase control)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool value = (bool)e.NewValue;
|
|
||||||
if (value)
|
|
||||||
{
|
|
||||||
control.LayoutUpdated += control.OnImageExBaseLayoutUpdated;
|
|
||||||
control.InvalidateLazyLoading();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
control.LayoutUpdated -= control.OnImageExBaseLayoutUpdated;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void LazyLoadingThresholdChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
|
||||||
{
|
|
||||||
if (d is ImageExBase { EnableLazyLoading: true } control)
|
|
||||||
{
|
|
||||||
control.InvalidateLazyLoading();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void SourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
private static void SourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||||
{
|
{
|
||||||
if (d is not ImageExBase control)
|
if (d is not ImageExBase control)
|
||||||
@@ -187,15 +143,7 @@ internal abstract partial class ImageExBase : Microsoft.UI.Xaml.Controls.Control
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e.NewValue is null || !control.EnableLazyLoading || control.isInViewport)
|
control.SetSource(e.NewValue);
|
||||||
{
|
|
||||||
control.lazyLoadingSource = null;
|
|
||||||
control.SetSource(e.NewValue);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
control.lazyLoadingSource = e.NewValue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsHttpUri(Uri uri)
|
private static bool IsHttpUri(Uri uri)
|
||||||
@@ -203,11 +151,8 @@ internal abstract partial class ImageExBase : Microsoft.UI.Xaml.Controls.Control
|
|||||||
return uri.IsAbsoluteUri && (uri.Scheme == "http" || uri.Scheme == "https");
|
return uri.IsAbsoluteUri && (uri.Scheme == "http" || uri.Scheme == "https");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AttachSource(ImageSource? source)
|
private void AttachSource(BitmapImage? source, Uri? uri)
|
||||||
{
|
{
|
||||||
// Setting the source at this point should call ImageExOpened/VisualStateManager.GoToState
|
|
||||||
// as we register to both the ImageOpened/ImageFailed events of the underlying control.
|
|
||||||
// We only need to call those methods if we fail in other cases before we get here.
|
|
||||||
if (Image is Microsoft.UI.Xaml.Controls.Image image)
|
if (Image is Microsoft.UI.Xaml.Controls.Image image)
|
||||||
{
|
{
|
||||||
image.Source = source;
|
image.Source = source;
|
||||||
@@ -221,13 +166,15 @@ internal abstract partial class ImageExBase : Microsoft.UI.Xaml.Controls.Control
|
|||||||
{
|
{
|
||||||
VisualStateManager.GoToState(this, UnloadedState, true);
|
VisualStateManager.GoToState(this, UnloadedState, true);
|
||||||
}
|
}
|
||||||
else if (source is BitmapSource { PixelHeight: > 0, PixelWidth: > 0 })
|
else
|
||||||
{
|
{
|
||||||
|
// https://learn.microsoft.com/en-us/windows/uwp/debug-test-perf/optimize-animations-and-media#optimize-image-resources
|
||||||
|
source.UriSource = uri;
|
||||||
VisualStateManager.GoToState(this, LoadedState, true);
|
VisualStateManager.GoToState(this, LoadedState, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AttachPlaceholderSource(ImageSource? source)
|
private void AttachPlaceholderSource(BitmapImage? source, Uri? uri)
|
||||||
{
|
{
|
||||||
if (PlaceholderImage is Microsoft.UI.Xaml.Controls.Image image)
|
if (PlaceholderImage is Microsoft.UI.Xaml.Controls.Image image)
|
||||||
{
|
{
|
||||||
@@ -242,8 +189,10 @@ internal abstract partial class ImageExBase : Microsoft.UI.Xaml.Controls.Control
|
|||||||
{
|
{
|
||||||
VisualStateManager.GoToState(this, UnloadedState, true);
|
VisualStateManager.GoToState(this, UnloadedState, true);
|
||||||
}
|
}
|
||||||
else if (source is BitmapSource { PixelHeight: > 0, PixelWidth: > 0 })
|
else
|
||||||
{
|
{
|
||||||
|
// https://learn.microsoft.com/en-us/windows/uwp/debug-test-perf/optimize-animations-and-media#optimize-image-resources
|
||||||
|
source.UriSource = uri;
|
||||||
VisualStateManager.GoToState(this, LoadedState, true);
|
VisualStateManager.GoToState(this, LoadedState, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -256,10 +205,9 @@ internal abstract partial class ImageExBase : Microsoft.UI.Xaml.Controls.Control
|
|||||||
}
|
}
|
||||||
|
|
||||||
tokenSource?.Cancel();
|
tokenSource?.Cancel();
|
||||||
|
|
||||||
tokenSource = new CancellationTokenSource();
|
tokenSource = new CancellationTokenSource();
|
||||||
|
|
||||||
AttachSource(null);
|
AttachSource(default, default);
|
||||||
|
|
||||||
if (source is null)
|
if (source is null)
|
||||||
{
|
{
|
||||||
@@ -268,13 +216,6 @@ internal abstract partial class ImageExBase : Microsoft.UI.Xaml.Controls.Control
|
|||||||
|
|
||||||
VisualStateManager.GoToState(this, LoadingState, true);
|
VisualStateManager.GoToState(this, LoadingState, true);
|
||||||
|
|
||||||
if (source as ImageSource is { } imageSource)
|
|
||||||
{
|
|
||||||
AttachSource(imageSource);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (source as Uri is not { } uri)
|
if (source as Uri is not { } uri)
|
||||||
{
|
{
|
||||||
string? url = source as string ?? source.ToString();
|
string? url = source as string ?? source.ToString();
|
||||||
@@ -319,20 +260,13 @@ internal abstract partial class ImageExBase : Microsoft.UI.Xaml.Controls.Control
|
|||||||
tokenSource?.Cancel();
|
tokenSource?.Cancel();
|
||||||
tokenSource = new();
|
tokenSource = new();
|
||||||
|
|
||||||
AttachPlaceholderSource(null);
|
AttachPlaceholderSource(default, default);
|
||||||
|
|
||||||
if (source is null)
|
if (source is null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (source as ImageSource is { } imageSource)
|
|
||||||
{
|
|
||||||
AttachPlaceholderSource(imageSource);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (source as Uri is not { } uri)
|
if (source as Uri is not { } uri)
|
||||||
{
|
{
|
||||||
string? url = source as string ?? source.ToString();
|
string? url = source as string ?? source.ToString();
|
||||||
@@ -354,13 +288,13 @@ internal abstract partial class ImageExBase : Microsoft.UI.Xaml.Controls.Control
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageSource? img = await ProvideCachedResourceAsync(uri, tokenSource.Token).ConfigureAwait(true);
|
Uri? actualUri = await ProvideCachedResourceAsync(uri, tokenSource.Token).ConfigureAwait(true);
|
||||||
|
|
||||||
ArgumentNullException.ThrowIfNull(tokenSource);
|
ArgumentNullException.ThrowIfNull(tokenSource);
|
||||||
if (!tokenSource.IsCancellationRequested)
|
if (!tokenSource.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
// Only attach our image if we still have a valid request.
|
// Only attach our image if we still have a valid request.
|
||||||
AttachPlaceholderSource(img);
|
AttachPlaceholderSource(new BitmapImage(), actualUri);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (OperationCanceledException)
|
catch (OperationCanceledException)
|
||||||
@@ -379,99 +313,13 @@ internal abstract partial class ImageExBase : Microsoft.UI.Xaml.Controls.Control
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsCacheEnabled)
|
Uri? actualUri = await ProvideCachedResourceAsync(imageUri, token).ConfigureAwait(true);
|
||||||
|
|
||||||
|
ArgumentNullException.ThrowIfNull(tokenSource);
|
||||||
|
if (!tokenSource.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
ImageSource? img = await ProvideCachedResourceAsync(imageUri, token).ConfigureAwait(true);
|
// Only attach our image if we still have a valid request.
|
||||||
|
AttachSource(new BitmapImage(), actualUri);
|
||||||
ArgumentNullException.ThrowIfNull(tokenSource);
|
|
||||||
if (!tokenSource.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
// Only attach our image if we still have a valid request.
|
|
||||||
AttachSource(img);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (string.Equals(imageUri.Scheme, "data", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
string source = imageUri.OriginalString;
|
|
||||||
const string base64Head = "base64,";
|
|
||||||
int index = source.IndexOf(base64Head, StringComparison.Ordinal);
|
|
||||||
if (index >= 0)
|
|
||||||
{
|
|
||||||
byte[] bytes = Convert.FromBase64String(source[(index + base64Head.Length)..]);
|
|
||||||
BitmapImage bitmap = new();
|
|
||||||
await bitmap.SetSourceAsync(new MemoryStream(bytes).AsRandomAccessStream());
|
|
||||||
|
|
||||||
ArgumentNullException.ThrowIfNull(tokenSource);
|
|
||||||
if (!tokenSource.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
AttachSource(bitmap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
AttachSource(new BitmapImage(imageUri)
|
|
||||||
{
|
|
||||||
CreateOptions = BitmapCreateOptions.IgnoreImageCache,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnImageExBaseLayoutUpdated(object? sender, object e)
|
|
||||||
{
|
|
||||||
InvalidateLazyLoading();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void InvalidateLazyLoading()
|
|
||||||
{
|
|
||||||
if (!IsLoaded)
|
|
||||||
{
|
|
||||||
isInViewport = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the first ascendant ScrollViewer, if not found, use the root element.
|
|
||||||
FrameworkElement? hostElement = default;
|
|
||||||
IEnumerable<FrameworkElement> ascendants = this.FindAscendants().OfType<FrameworkElement>();
|
|
||||||
foreach (FrameworkElement ascendant in ascendants)
|
|
||||||
{
|
|
||||||
hostElement = ascendant;
|
|
||||||
if (hostElement is Microsoft.UI.Xaml.Controls.ScrollViewer)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hostElement is null)
|
|
||||||
{
|
|
||||||
isInViewport = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Rect controlRect = TransformToVisual(hostElement).TransformBounds(StructMarshal.Rect(ActualSize));
|
|
||||||
double lazyLoadingThreshold = LazyLoadingThreshold;
|
|
||||||
|
|
||||||
// Left/Top 1 Threshold, Right/Bottom 2 Threshold
|
|
||||||
Rect hostRect = new(
|
|
||||||
0 - lazyLoadingThreshold,
|
|
||||||
0 - lazyLoadingThreshold,
|
|
||||||
hostElement.ActualWidth + (2 * lazyLoadingThreshold),
|
|
||||||
hostElement.ActualHeight + (2 * lazyLoadingThreshold));
|
|
||||||
|
|
||||||
if (controlRect.IntersectsWith(hostRect))
|
|
||||||
{
|
|
||||||
isInViewport = true;
|
|
||||||
|
|
||||||
if (lazyLoadingSource is not null)
|
|
||||||
{
|
|
||||||
object source = lazyLoadingSource;
|
|
||||||
lazyLoadingSource = null;
|
|
||||||
SetSource(source);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
isInViewport = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -15,15 +15,14 @@
|
|||||||
<Grid>
|
<Grid>
|
||||||
<Grid CornerRadius="{StaticResource ControlCornerRadius}">
|
<Grid CornerRadius="{StaticResource ControlCornerRadius}">
|
||||||
<!-- Disable some CachedImage's LazyLoading function here can increase response speed -->
|
<!-- Disable some CachedImage's LazyLoading function here can increase response speed -->
|
||||||
<shci:CachedImage EnableLazyLoading="False" Source="{x:Bind Quality, Converter={StaticResource QualityConverter}, Mode=OneWay}"/>
|
<shci:CachedImage Source="{x:Bind Quality, Converter={StaticResource QualityConverter}, Mode=OneWay}"/>
|
||||||
<shci:CachedImage EnableLazyLoading="False" Source="{StaticResource UI_ImgSign_ItemIcon}"/>
|
<shci:CachedImage Source="{StaticResource UI_ImgSign_ItemIcon}"/>
|
||||||
<shci:CachedImage Source="{x:Bind Icon, Mode=OneWay}"/>
|
<shci:CachedImage Source="{x:Bind Icon, Mode=OneWay}"/>
|
||||||
<shci:CachedImage
|
<shci:CachedImage
|
||||||
Margin="2"
|
Margin="2"
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
VerticalAlignment="Top"
|
VerticalAlignment="Top"
|
||||||
shch:FrameworkElementHelper.SquareLength="16"
|
shch:FrameworkElementHelper.SquareLength="16"
|
||||||
EnableLazyLoading="False"
|
|
||||||
Source="{x:Bind Badge, Mode=OneWay}"/>
|
Source="{x:Bind Badge, Mode=OneWay}"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
<shci:CachedImage
|
<shci:CachedImage
|
||||||
Width="120"
|
Width="120"
|
||||||
Height="120"
|
Height="120"
|
||||||
EnableLazyLoading="False"
|
|
||||||
Source="{StaticResource UI_EmotionIcon272}"/>
|
Source="{StaticResource UI_EmotionIcon272}"/>
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Margin="0,16,0,0"
|
Margin="0,16,0,0"
|
||||||
|
|||||||
@@ -251,7 +251,6 @@
|
|||||||
<shci:CachedImage
|
<shci:CachedImage
|
||||||
Height="120"
|
Height="120"
|
||||||
MinWidth="{ThemeResource SettingsCardContentControlMinWidth}"
|
MinWidth="{ThemeResource SettingsCardContentControlMinWidth}"
|
||||||
EnableLazyLoading="False"
|
|
||||||
Source="{StaticResource UI_EmotionIcon52}"/>
|
Source="{StaticResource UI_EmotionIcon52}"/>
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Margin="0,5,0,21"
|
Margin="0,5,0,21"
|
||||||
|
|||||||
@@ -415,7 +415,6 @@
|
|||||||
<shci:CachedImage
|
<shci:CachedImage
|
||||||
Height="120"
|
Height="120"
|
||||||
MinWidth="{ThemeResource SettingsCardContentControlMinWidth}"
|
MinWidth="{ThemeResource SettingsCardContentControlMinWidth}"
|
||||||
EnableLazyLoading="False"
|
|
||||||
Source="{StaticResource UI_EmotionIcon445}"/>
|
Source="{StaticResource UI_EmotionIcon445}"/>
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Margin="0,5,0,21"
|
Margin="0,5,0,21"
|
||||||
|
|||||||
@@ -369,7 +369,6 @@
|
|||||||
<shci:CachedImage
|
<shci:CachedImage
|
||||||
Height="120"
|
Height="120"
|
||||||
MinWidth="{ThemeResource SettingsCardContentControlMinWidth}"
|
MinWidth="{ThemeResource SettingsCardContentControlMinWidth}"
|
||||||
EnableLazyLoading="False"
|
|
||||||
Source="{StaticResource UI_EmotionIcon89}"/>
|
Source="{StaticResource UI_EmotionIcon89}"/>
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Margin="0,5,0,21"
|
Margin="0,5,0,21"
|
||||||
@@ -754,7 +753,6 @@
|
|||||||
<shci:CachedImage
|
<shci:CachedImage
|
||||||
Height="120"
|
Height="120"
|
||||||
MinWidth="{ThemeResource SettingsCardContentControlMinWidth}"
|
MinWidth="{ThemeResource SettingsCardContentControlMinWidth}"
|
||||||
EnableLazyLoading="False"
|
|
||||||
Source="{StaticResource UI_EmotionIcon89}"/>
|
Source="{StaticResource UI_EmotionIcon89}"/>
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Margin="0,5,0,21"
|
Margin="0,5,0,21"
|
||||||
|
|||||||
@@ -238,7 +238,6 @@
|
|||||||
<shci:CachedImage
|
<shci:CachedImage
|
||||||
Height="120"
|
Height="120"
|
||||||
MinWidth="{ThemeResource SettingsCardContentControlMinWidth}"
|
MinWidth="{ThemeResource SettingsCardContentControlMinWidth}"
|
||||||
EnableLazyLoading="False"
|
|
||||||
Source="{StaticResource UI_EmotionIcon89}"/>
|
Source="{StaticResource UI_EmotionIcon89}"/>
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Margin="0,5,0,21"
|
Margin="0,5,0,21"
|
||||||
@@ -365,7 +364,6 @@
|
|||||||
<shci:CachedImage
|
<shci:CachedImage
|
||||||
Height="120"
|
Height="120"
|
||||||
MinWidth="{ThemeResource SettingsCardContentControlMinWidth}"
|
MinWidth="{ThemeResource SettingsCardContentControlMinWidth}"
|
||||||
EnableLazyLoading="False"
|
|
||||||
Source="{StaticResource UI_EmotionIcon89}"/>
|
Source="{StaticResource UI_EmotionIcon89}"/>
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Margin="0,5,0,21"
|
Margin="0,5,0,21"
|
||||||
|
|||||||
Reference in New Issue
Block a user