diff --git a/StabilityMatrix.Avalonia/Controls/BetterImage.cs b/StabilityMatrix.Avalonia/Controls/BetterImage.cs
new file mode 100644
index 00000000..8eb77eee
--- /dev/null
+++ b/StabilityMatrix.Avalonia/Controls/BetterImage.cs
@@ -0,0 +1,140 @@
+using Avalonia;
+using Avalonia.Automation;
+using Avalonia.Automation.Peers;
+using Avalonia.Controls;
+using Avalonia.Controls.Automation.Peers;
+using Avalonia.Media;
+using Avalonia.Metadata;
+
+namespace StabilityMatrix.Avalonia.Controls;
+
+public class BetterImage : Control
+{
+ ///
+ /// Defines the property.
+ ///
+ public static readonly StyledProperty SourceProperty =
+ AvaloniaProperty.Register(nameof(Source));
+
+ ///
+ /// Defines the property.
+ ///
+ public static readonly StyledProperty StretchProperty =
+ AvaloniaProperty.Register(nameof(Stretch), Stretch.Uniform);
+
+ ///
+ /// Defines the property.
+ ///
+ public static readonly StyledProperty StretchDirectionProperty =
+ AvaloniaProperty.Register(
+ nameof(StretchDirection),
+ StretchDirection.Both);
+
+ static BetterImage()
+ {
+ AffectsRender(SourceProperty, StretchProperty, StretchDirectionProperty);
+ AffectsMeasure(SourceProperty, StretchProperty, StretchDirectionProperty);
+ AutomationProperties.ControlTypeOverrideProperty.OverrideDefaultValue(
+ AutomationControlType.Image);
+ }
+
+ ///
+ /// Gets or sets the image that will be displayed.
+ ///
+ [Content]
+ public IImage? Source
+ {
+ get { return GetValue(SourceProperty); }
+ set { SetValue(SourceProperty, value); }
+ }
+
+ ///
+ /// Gets or sets a value controlling how the image will be stretched.
+ ///
+ public Stretch Stretch
+ {
+ get { return GetValue(StretchProperty); }
+ set { SetValue(StretchProperty, value); }
+ }
+
+ ///
+ /// Gets or sets a value controlling in what direction the image will be stretched.
+ ///
+ public StretchDirection StretchDirection
+ {
+ get { return GetValue(StretchDirectionProperty); }
+ set { SetValue(StretchDirectionProperty, value); }
+ }
+
+ ///
+ protected override bool BypassFlowDirectionPolicies => true;
+
+ ///
+ /// Renders the control.
+ ///
+ /// The drawing context.
+ public sealed override void Render(DrawingContext context)
+ {
+ var source = Source;
+
+ if (source != null && Bounds.Width > 0 && Bounds.Height > 0)
+ {
+ Rect viewPort = new Rect(Bounds.Size);
+ Size sourceSize = source.Size;
+
+ Vector scale = Stretch.CalculateScaling(Bounds.Size, sourceSize, StretchDirection);
+ Size scaledSize = sourceSize * scale;
+ Rect destRect = viewPort
+ .CenterRect(new Rect(scaledSize))
+ .WithX(0)
+ .WithY(0)
+ .Intersect(viewPort);
+ Rect sourceRect = new Rect(sourceSize)
+ .CenterRect(new Rect(destRect.Size / scale))
+ .WithX(0)
+ .WithY(0);
+
+ context.DrawImage(source, sourceRect, destRect);
+ }
+ }
+
+ ///
+ /// Measures the control.
+ ///
+ /// The available size.
+ /// The desired size of the control.
+ protected override Size MeasureOverride(Size availableSize)
+ {
+ var source = Source;
+ var result = new Size();
+
+ if (source != null)
+ {
+ result = Stretch.CalculateSize(availableSize, source.Size, StretchDirection);
+ }
+
+ return result;
+ }
+
+ ///
+ protected override Size ArrangeOverride(Size finalSize)
+ {
+ var source = Source;
+
+ if (source != null)
+ {
+ var sourceSize = source.Size;
+ var result = Stretch.CalculateSize(finalSize, sourceSize);
+ return result;
+ }
+ else
+ {
+ return new Size();
+ }
+ }
+
+ protected override AutomationPeer OnCreateAutomationPeer()
+ {
+ return new ImageAutomationPeer(this);
+ }
+}
diff --git a/StabilityMatrix.Avalonia/Styles/ButtonStyles.axaml b/StabilityMatrix.Avalonia/Styles/ButtonStyles.axaml
index c8347362..a0aa7133 100644
--- a/StabilityMatrix.Avalonia/Styles/ButtonStyles.axaml
+++ b/StabilityMatrix.Avalonia/Styles/ButtonStyles.axaml
@@ -6,7 +6,8 @@
-
+
+
@@ -92,4 +93,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/StabilityMatrix.Avalonia/Styles/ThemeColors.axaml b/StabilityMatrix.Avalonia/Styles/ThemeColors.axaml
index a26fe96a..1e73f96f 100644
--- a/StabilityMatrix.Avalonia/Styles/ThemeColors.axaml
+++ b/StabilityMatrix.Avalonia/Styles/ThemeColors.axaml
@@ -9,6 +9,7 @@
#9C27B0
#673AB7
#3F51B5
+ #1A72BD
#2196F3
#03A9F4
#00BCD4
diff --git a/StabilityMatrix.Avalonia/ViewModels/CheckpointBrowserCardViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/CheckpointBrowserCardViewModel.cs
index 6eae9db1..b55bd779 100644
--- a/StabilityMatrix.Avalonia/ViewModels/CheckpointBrowserCardViewModel.cs
+++ b/StabilityMatrix.Avalonia/ViewModels/CheckpointBrowserCardViewModel.cs
@@ -5,8 +5,10 @@ using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using AsyncAwaitBestPractices;
+using Avalonia;
using Avalonia.Controls;
using Avalonia.Media.Imaging;
+using Avalonia.Platform;
using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
@@ -51,8 +53,6 @@ public partial class CheckpointBrowserCardViewModel : ProgressViewModel
return;
}
- if (Design.IsDesignMode) return;
-
UpdateImage().SafeFireAndForget();
// Update image when nsfw setting changes
@@ -79,10 +79,12 @@ public partial class CheckpointBrowserCardViewModel : ProgressViewModel
return;
}
+ var assetStream = AssetLoader.Open(new Uri("avares://StabilityMatrix.Avalonia/Assets/noimage.png"));
+
// Otherwise Default image
Dispatcher.UIThread.Invoke(() =>
{
- CardImage = new Bitmap("Assets/noimage.png");
+ CardImage = new Bitmap(assetStream);
});
}
@@ -173,6 +175,8 @@ public partial class CheckpointBrowserCardViewModel : ProgressViewModel
Text = $"Downloading... {report.Percentage}%";
});
}));
+
+ await downloadTask;
// var downloadResult = await snackbarService.TryAsync(downloadTask, "Could not download file");
diff --git a/StabilityMatrix.Avalonia/ViewModels/CheckpointBrowserViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/CheckpointBrowserViewModel.cs
index e974cd66..c5af8b35 100644
--- a/StabilityMatrix.Avalonia/ViewModels/CheckpointBrowserViewModel.cs
+++ b/StabilityMatrix.Avalonia/ViewModels/CheckpointBrowserViewModel.cs
@@ -55,6 +55,8 @@ public partial class CheckpointBrowserViewModel : PageViewModelBase
[ObservableProperty] private bool noResultsFound;
[ObservableProperty] private string noResultsText;
+ private List allModelCards = new();
+
public IEnumerable AllCivitPeriods => Enum.GetValues(typeof(CivitPeriod)).Cast();
public IEnumerable AllSortModes => Enum.GetValues(typeof(CivitSortMode)).Cast();
@@ -202,9 +204,12 @@ public partial class CheckpointBrowserViewModel : PageViewModelBase
else
{
var updateCards = models
- .Select(model => new CheckpointBrowserCardViewModel(model,
- downloadService, settingsManager));
- ModelCards = new ObservableCollection(updateCards);
+ .Select(model => new CheckpointBrowserCardViewModel(model,
+ downloadService, settingsManager)).ToList();
+ allModelCards = updateCards;
+ ModelCards =
+ new ObservableCollection(
+ updateCards.Where(FilterModelCardsPredicate));
}
TotalPages = metadata?.TotalPages ?? 1;
CanGoToPreviousPage = CurrentPageNumber > 1;
@@ -310,22 +315,27 @@ public partial class CheckpointBrowserViewModel : PageViewModelBase
// On changes to ModelCards, update the view source
partial void OnModelCardsChanged(ObservableCollection? value)
{
- if (value is null)
- {
- ModelCardsView = null;
- }
- // Create new view
- var view = new DataGridCollectionView(value)
- {
- Filter = FilterModelCardsPredicate,
- };
- ModelCardsView = view;
+ // if (value is null)
+ // {
+ // ModelCardsView = null;
+ // }
+ // // Create new view
+ // var view = new DataGridCollectionView(value)
+ // {
+ // Filter = FilterModelCardsPredicate,
+ // };
+ // ModelCardsView = view;
}
partial void OnShowNsfwChanged(bool value)
{
settingsManager.Transaction(s => s.ModelBrowserNsfwEnabled = value);
- ModelCardsView?.Refresh();
+ // ModelCardsView?.Refresh();
+ var updateCards = allModelCards
+ .Select(model => new CheckpointBrowserCardViewModel(model.CivitModel,
+ downloadService, settingsManager))
+ .Where(FilterModelCardsPredicate);
+ ModelCards = new ObservableCollection(updateCards);
if (!HasSearched)
return;
@@ -370,9 +380,9 @@ public partial class CheckpointBrowserViewModel : PageViewModelBase
private void UpdateResultsText()
{
- NoResultsFound = (ModelCards?.Count ?? 0) <= 0;
- NoResultsText = ModelCards?.Count > 0
- ? $"{ModelCards.Count} results hidden by filters"
+ NoResultsFound = ModelCards?.Count <= 0;
+ NoResultsText = allModelCards?.Count > 0
+ ? $"{allModelCards.Count} results hidden by filters"
: "No results found";
}
diff --git a/StabilityMatrix.Avalonia/Views/CheckpointBrowserPage.axaml b/StabilityMatrix.Avalonia/Views/CheckpointBrowserPage.axaml
index a7218874..a62f6ddd 100644
--- a/StabilityMatrix.Avalonia/Views/CheckpointBrowserPage.axaml
+++ b/StabilityMatrix.Avalonia/Views/CheckpointBrowserPage.axaml
@@ -6,7 +6,7 @@
xmlns:controls1="clr-namespace:StabilityMatrix.Avalonia.Controls"
xmlns:viewModels="clr-namespace:StabilityMatrix.Avalonia.ViewModels"
xmlns:designData="clr-namespace:StabilityMatrix.Avalonia.DesignData"
- mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
+ mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="600"
x:DataType="viewModels:CheckpointBrowserViewModel"
d:DataContext="{x:Static designData:DesignData.CheckpointBrowserViewModel}"
x:CompileBindings="True"
@@ -17,7 +17,7 @@
@@ -34,17 +34,17 @@
Text="{Binding CivitModel.ModelVersions[0].Name, FallbackValue=''}"
VerticalAlignment="Center" />
-
+ Stretch="UniformToFill"/>
-
@@ -154,18 +158,18 @@
Margin="8,0,8,0"
VerticalAlignment="Stretch"
Width="80">
-
+
+ MinWidth="16" />
-
+
@@ -195,21 +199,21 @@
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+