Refinements

This commit is contained in:
Michael Bucari-Tovo 2022-07-12 00:18:56 -06:00
parent f8e9c16bc1
commit 5f45d28b9f
11 changed files with 115 additions and 107 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 747 B

View File

@ -1,52 +1,9 @@
using Avalonia.Controls; namespace LibationWinForms.AvaloniaUI.ViewModels
using Avalonia.Media.Imaging;
using System;
using System.ComponentModel;
namespace LibationWinForms.AvaloniaUI.ViewModels
{ {
public class BookTags public class BookTags
{ {
private static Bitmap _buttonImage;
static BookTags()
{
var memoryStream = new System.IO.MemoryStream();
Properties.Resources.edit_25x25.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Png);
memoryStream.Position = 0;
_buttonImage = new Bitmap(memoryStream);
}
public string Tags { get; init; } public string Tags { get; init; }
public bool IsSeries { get; init; } public bool IsSeries { get; init; }
public bool HasTags => !string.IsNullOrEmpty(Tags);
public Control Control
{
get
{
if (IsSeries)
return null;
if (string.IsNullOrEmpty(Tags))
{
return new Image
{
Stretch = Avalonia.Media.Stretch.None,
Source = _buttonImage
};
}
else
{
return new TextBlock
{
Text = Tags,
Margin = new Avalonia.Thickness(0, 0),
TextWrapping = Avalonia.Media.TextWrapping.WrapWithOverflow
};
}
}
}
} }
} }

View File

@ -81,7 +81,7 @@ namespace LibationWinForms.AvaloniaUI.ViewModels
Category = string.Join(" > ", Book.CategoriesNames()); Category = string.Join(" > ", Book.CategoriesNames());
Misc = GetMiscDisplay(libraryBook); Misc = GetMiscDisplay(libraryBook);
LongDescription = GetDescriptionDisplay(Book); LongDescription = GetDescriptionDisplay(Book);
Description = LongDescription; Description = TrimTextToWord(LongDescription, 62);
SeriesIndex = Book.SeriesLink.FirstOrDefault()?.Index ?? 0; SeriesIndex = Book.SeriesLink.FirstOrDefault()?.Index ?? 0;
NotifyPropertyChanged(nameof(Title)); NotifyPropertyChanged(nameof(Title));

View File

@ -53,8 +53,8 @@ namespace LibationWinForms.AvaloniaUI.ViewModels
private Bitmap _cover; private Bitmap _cover;
#region Properties exposed to the view #region Properties exposed to the view
public ProcessBookResult Result { get => _result; private set { _result = value; NotifyPropertyChanged(); NotifyPropertyChanged(nameof(StatusText)); } } public ProcessBookResult Result { get => _result; set { _result = value; NotifyPropertyChanged(); NotifyPropertyChanged(nameof(StatusText)); } }
public ProcessBookStatus Status { get => _status; private set { _status = value; NotifyPropertyChanged(); NotifyPropertyChanged(nameof(BackgroundColor)); NotifyPropertyChanged(nameof(IsFinished)); NotifyPropertyChanged(nameof(IsDownloading)); NotifyPropertyChanged(nameof(Queued)); } } public ProcessBookStatus Status { get => _status; set { _status = value; NotifyPropertyChanged(); NotifyPropertyChanged(nameof(BackgroundColor)); NotifyPropertyChanged(nameof(IsFinished)); NotifyPropertyChanged(nameof(IsDownloading)); NotifyPropertyChanged(nameof(Queued)); } }
public string Narrator { get => _narrator; set { _narrator = value; NotifyPropertyChanged(); } } public string Narrator { get => _narrator; set { _narrator = value; NotifyPropertyChanged(); } }
public string Author { get => _author; set { _author = value; NotifyPropertyChanged(); } } public string Author { get => _author; set { _author = value; NotifyPropertyChanged(); } }
public string Title { get => _title; set { _title = value; NotifyPropertyChanged(); } } public string Title { get => _title; set { _title = value; NotifyPropertyChanged(); } }

View File

@ -1,14 +1,11 @@
using ReactiveUI; using Avalonia.Threading;
using ReactiveUI;
using System; using System;
using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LibationWinForms.AvaloniaUI.ViewModels namespace LibationWinForms.AvaloniaUI.ViewModels
{ {
public class ProcessQueueViewModel : ViewModelBase public class ProcessQueueViewModel : ViewModelBase, ProcessQueue.ILogForm
{ {
public string QueueHeader => "this is a header!"; public string QueueHeader => "this is a header!";
@ -24,6 +21,17 @@ namespace LibationWinForms.AvaloniaUI.ViewModels
public ObservableCollection<LogEntry> LogEntries { get; } = new(); public ObservableCollection<LogEntry> LogEntries { get; } = new();
public ProcessBook2 SelectedItem { get; set; } public ProcessBook2 SelectedItem { get; set; }
public void WriteLine(string text)
{
Dispatcher.UIThread.Post(() =>
LogEntries.Add(new()
{
LogDate = DateTime.Now,
LogMessage = text.Trim()
}));
}
} }
public class LogEntry public class LogEntry

View File

@ -91,13 +91,11 @@ namespace LibationWinForms.AvaloniaUI.ViewModels
Category = string.Join(" > ", Book.CategoriesNames()); Category = string.Join(" > ", Book.CategoriesNames());
Misc = GetMiscDisplay(LibraryBook); Misc = GetMiscDisplay(LibraryBook);
LongDescription = GetDescriptionDisplay(Book); LongDescription = GetDescriptionDisplay(Book);
Description = LongDescription; Description = TrimTextToWord(LongDescription, 62);
int bookLenMins = Children.Sum(c => c.LibraryBook.Book.LengthInMinutes); int bookLenMins = Children.Sum(c => c.LibraryBook.Book.LengthInMinutes);
Length = bookLenMins == 0 ? "" : $"{bookLenMins / 60} hr {bookLenMins % 60} min"; Length = bookLenMins == 0 ? "" : $"{bookLenMins / 60} hr {bookLenMins % 60} min";
NotifyPropertyChanged(nameof(Title)); NotifyPropertyChanged(nameof(Title));
NotifyPropertyChanged(nameof(Series)); NotifyPropertyChanged(nameof(Series));
NotifyPropertyChanged(nameof(Length)); NotifyPropertyChanged(nameof(Length));
@ -110,8 +108,6 @@ namespace LibationWinForms.AvaloniaUI.ViewModels
NotifyPropertyChanged(nameof(Misc)); NotifyPropertyChanged(nameof(Misc));
NotifyPropertyChanged(nameof(LongDescription)); NotifyPropertyChanged(nameof(LongDescription));
NotifyPropertyChanged(nameof(Description)); NotifyPropertyChanged(nameof(Description));
NotifyPropertyChanged();
} }
#region Data Sorting #region Data Sorting

View File

@ -5,7 +5,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:views="clr-namespace:LibationWinForms.AvaloniaUI.Views" xmlns:views="clr-namespace:LibationWinForms.AvaloniaUI.Views"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
mc:Ignorable="d" d:DesignWidth="450" d:DesignHeight="700" mc:Ignorable="d" d:DesignWidth="450" d:DesignHeight="850"
x:Class="LibationWinForms.AvaloniaUI.Views.ProcessQueueControl2"> x:Class="LibationWinForms.AvaloniaUI.Views.ProcessQueueControl2">
<UserControl.Resources> <UserControl.Resources>

View File

@ -4,6 +4,7 @@ using Avalonia.Controls;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
using Avalonia.Threading; using Avalonia.Threading;
using DataLayer;
using LibationWinForms.AvaloniaUI.ViewModels; using LibationWinForms.AvaloniaUI.ViewModels;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -13,7 +14,7 @@ using System.Threading.Tasks;
namespace LibationWinForms.AvaloniaUI.Views namespace LibationWinForms.AvaloniaUI.Views
{ {
public partial class ProcessQueueControl2 : UserControl, ProcessQueue.ILogForm public partial class ProcessQueueControl2 : UserControl
{ {
private readonly ProcessQueueViewModel _viewModel; private readonly ProcessQueueViewModel _viewModel;
private ItemsRepeater _repeater; private ItemsRepeater _repeater;
@ -65,6 +66,7 @@ namespace LibationWinForms.AvaloniaUI.Views
_repeater.PointerPressed += RepeaterClick; _repeater.PointerPressed += RepeaterClick;
_repeater.KeyDown += RepeaterOnKeyDown; _repeater.KeyDown += RepeaterOnKeyDown;
DataContext = _viewModel = new ProcessQueueViewModel(); DataContext = _viewModel = new ProcessQueueViewModel();
Logger = ProcessQueue.LogMe.RegisterForm(_viewModel);
ProcessBookControl2.PositionButtonClicked += ProcessBookControl2_ButtonClicked; ProcessBookControl2.PositionButtonClicked += ProcessBookControl2_ButtonClicked;
ProcessBookControl2.CancelButtonClicked += ProcessBookControl2_CancelButtonClicked; ProcessBookControl2.CancelButtonClicked += ProcessBookControl2_CancelButtonClicked;
@ -81,19 +83,68 @@ namespace LibationWinForms.AvaloniaUI.Views
toolStripProgressBar1 = this.FindControl<ProgressBar>(nameof(toolStripProgressBar1)); toolStripProgressBar1 = this.FindControl<ProgressBar>(nameof(toolStripProgressBar1));
Logger = ProcessQueue.LogMe.RegisterForm(this);
Queue.QueuededCountChanged += Queue_QueuededCountChanged; Queue.QueuededCountChanged += Queue_QueuededCountChanged;
Queue.CompletedCountChanged += Queue_CompletedCountChanged; Queue.CompletedCountChanged += Queue_CompletedCountChanged;
#region Design Mode Testing
if (Design.IsDesignMode) if (Design.IsDesignMode)
return; {
using var context = DbContexts.GetContext();
var book = context.GetLibraryBook_Flat_NoTracking("B017V4IM1G");
List<ProcessBook2> testList = new()
{
new ProcessBook2(book, Logger)
{
Result = ProcessBookResult.FailedAbort,
Status = ProcessBookStatus.Failed,
},
new ProcessBook2(book, Logger)
{
Result = ProcessBookResult.FailedSkip,
Status = ProcessBookStatus.Failed,
},
new ProcessBook2(book, Logger)
{
Result = ProcessBookResult.FailedRetry,
Status = ProcessBookStatus.Failed,
},
new ProcessBook2(book, Logger)
{
Result = ProcessBookResult.ValidationFail,
Status = ProcessBookStatus.Failed,
},
new ProcessBook2(book, Logger)
{
Result = ProcessBookResult.Cancelled,
Status = ProcessBookStatus.Cancelled,
},
new ProcessBook2(book, Logger)
{
Result = ProcessBookResult.Success,
Status = ProcessBookStatus.Completed,
},
new ProcessBook2(book, Logger)
{
Result = ProcessBookResult.None,
Status = ProcessBookStatus.Working,
},
new ProcessBook2(book, Logger)
{
Result = ProcessBookResult.None,
Status = ProcessBookStatus.Queued,
},
};
runningTimeLbl.Text = string.Empty; _viewModel.Items.Enqueue(testList);
QueuedCount = 0; return;
ErrorCount = 0; }
CompletedCount = 0; #endregion
runningTimeLbl.Text = string.Empty;
QueuedCount = 0;
ErrorCount = 0;
CompletedCount = 0;
} }
private void InitializeComponent() private void InitializeComponent()
@ -156,19 +207,19 @@ namespace LibationWinForms.AvaloniaUI.Views
} }
private bool isBookInQueue(DataLayer.LibraryBook libraryBook) private bool isBookInQueue(LibraryBook libraryBook)
=> Queue.Any(b => b?.LibraryBook?.Book?.AudibleProductId == libraryBook.Book.AudibleProductId); => Queue.Any(b => b?.LibraryBook?.Book?.AudibleProductId == libraryBook.Book.AudibleProductId);
public void AddDownloadPdf(DataLayer.LibraryBook libraryBook) public void AddDownloadPdf(LibraryBook libraryBook)
=> AddDownloadPdf(new List<DataLayer.LibraryBook>() { libraryBook }); => AddDownloadPdf(new List<LibraryBook>() { libraryBook });
public void AddDownloadDecrypt(DataLayer.LibraryBook libraryBook) public void AddDownloadDecrypt(LibraryBook libraryBook)
=> AddDownloadDecrypt(new List<DataLayer.LibraryBook>() { libraryBook }); => AddDownloadDecrypt(new List<LibraryBook>() { libraryBook });
public void AddConvertMp3(DataLayer.LibraryBook libraryBook) public void AddConvertMp3(LibraryBook libraryBook)
=> AddConvertMp3(new List<DataLayer.LibraryBook>() { libraryBook }); => AddConvertMp3(new List<LibraryBook>() { libraryBook });
public void AddDownloadPdf(IEnumerable<DataLayer.LibraryBook> entries) public void AddDownloadPdf(IEnumerable<LibraryBook> entries)
{ {
List<ProcessBook2> procs = new(); List<ProcessBook2> procs = new();
foreach (var entry in entries) foreach (var entry in entries)
@ -185,7 +236,7 @@ namespace LibationWinForms.AvaloniaUI.Views
AddToQueue(procs); AddToQueue(procs);
} }
public void AddDownloadDecrypt(IEnumerable<DataLayer.LibraryBook> entries) public void AddDownloadDecrypt(IEnumerable<LibraryBook> entries)
{ {
List<ProcessBook2> procs = new(); List<ProcessBook2> procs = new();
foreach (var entry in entries) foreach (var entry in entries)
@ -203,7 +254,7 @@ namespace LibationWinForms.AvaloniaUI.Views
AddToQueue(procs); AddToQueue(procs);
} }
public void AddConvertMp3(IEnumerable<DataLayer.LibraryBook> entries) public void AddConvertMp3(IEnumerable<LibraryBook> entries)
{ {
List<ProcessBook2> procs = new(); List<ProcessBook2> procs = new();
foreach (var entry in entries) foreach (var entry in entries)
@ -266,17 +317,6 @@ namespace LibationWinForms.AvaloniaUI.Views
Serilog.Log.Logger.Error(ex, "An error was encountered while processing queued items"); Serilog.Log.Logger.Error(ex, "An error was encountered while processing queued items");
} }
} }
public void WriteLine(string text)
{
Dispatcher.UIThread.Post(() =>
_viewModel.LogEntries.Add(new()
{
LogDate = DateTime.Now,
LogMessage = text.Trim()
}));
}
#region Control event handlers #region Control event handlers
private void Queue_CompletedCountChanged(object sender, int e) private void Queue_CompletedCountChanged(object sender, int e)

View File

@ -6,13 +6,11 @@
xmlns:controls="clr-namespace:LibationWinForms.AvaloniaUI.Controls" xmlns:controls="clr-namespace:LibationWinForms.AvaloniaUI.Controls"
mc:Ignorable="d" d:DesignWidth="1560" d:DesignHeight="400" mc:Ignorable="d" d:DesignWidth="1560" d:DesignHeight="400"
x:Class="LibationWinForms.AvaloniaUI.Views.ProductsDisplay2"> x:Class="LibationWinForms.AvaloniaUI.Views.ProductsDisplay2">
<Grid> <Grid>
<DataGrid Name="productsGrid" AutoGenerateColumns="False" Items="{Binding GridEntries}"> <DataGrid Name="productsGrid" AutoGenerateColumns="False" Items="{Binding GridEntries}">
<DataGrid.Columns> <DataGrid.Columns>
<controls:DataGridCheckBoxColumnExt IsVisible="False" Header="Remove" IsThreeState="True" IsReadOnly="False" CanUserSort="True" Binding="{Binding Remove, Mode=TwoWay}" Width="70" SortMemberPath="Remove"/> <controls:DataGridCheckBoxColumnExt IsVisible="False" Header="Remove" IsThreeState="True" IsReadOnly="False" CanUserSort="True" Binding="{Binding Remove, Mode=TwoWay}" Width="70" SortMemberPath="Remove"/>
<DataGridTemplateColumn CanUserSort="True" Width="75" Header="Liberate" SortMemberPath="Liberate"> <DataGridTemplateColumn CanUserSort="True" Width="75" Header="Liberate" SortMemberPath="Liberate">
@ -25,8 +23,7 @@
</StackPanel> </StackPanel>
</DataTemplate> </DataTemplate>
</DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn> </DataGridTemplateColumn>
<DataGridTemplateColumn Width="80" Header="Cover"> <DataGridTemplateColumn Width="80" Header="Cover">
<DataGridTemplateColumn.CellTemplate> <DataGridTemplateColumn.CellTemplate>
@ -36,7 +33,7 @@
</DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn> </DataGridTemplateColumn>
<DataGridTemplateColumn Width="200" Header="Title" CanUserSort="True" SortMemberPath="Title"> <DataGridTemplateColumn MinWidth="150" Width="2*" Header="Title" CanUserSort="True" SortMemberPath="Title">
<DataGridTemplateColumn.CellTemplate> <DataGridTemplateColumn.CellTemplate>
<DataTemplate> <DataTemplate>
<Border BorderThickness="3" Height="80"> <Border BorderThickness="3" Height="80">
@ -46,7 +43,7 @@
</DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn> </DataGridTemplateColumn>
<DataGridTemplateColumn Width="100" Header="Authors" CanUserSort="True" SortMemberPath="Authors"> <DataGridTemplateColumn MinWidth="80" Width="1*" Header="Authors" CanUserSort="True" SortMemberPath="Authors">
<DataGridTemplateColumn.CellTemplate> <DataGridTemplateColumn.CellTemplate>
<DataTemplate> <DataTemplate>
<Border BorderThickness="3" Height="80"> <Border BorderThickness="3" Height="80">
@ -56,7 +53,7 @@
</DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn> </DataGridTemplateColumn>
<DataGridTemplateColumn Width="100" Header="Narrators" CanUserSort="True" SortMemberPath="Narrators"> <DataGridTemplateColumn MinWidth="80" Width="1*" Header="Narrators" CanUserSort="True" SortMemberPath="Narrators">
<DataGridTemplateColumn.CellTemplate> <DataGridTemplateColumn.CellTemplate>
<DataTemplate> <DataTemplate>
<Border BorderThickness="3" Height="80"> <Border BorderThickness="3" Height="80">
@ -66,7 +63,7 @@
</DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn> </DataGridTemplateColumn>
<DataGridTemplateColumn Width="100" Header="Length" CanUserSort="True" SortMemberPath="Length"> <DataGridTemplateColumn MinWidth="80" Width="1*" Header="Length" CanUserSort="True" SortMemberPath="Length">
<DataGridTemplateColumn.CellTemplate> <DataGridTemplateColumn.CellTemplate>
<DataTemplate> <DataTemplate>
<Border BorderThickness="3" Height="80"> <Border BorderThickness="3" Height="80">
@ -76,7 +73,7 @@
</DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn> </DataGridTemplateColumn>
<DataGridTemplateColumn Width="100" Header="Series" CanUserSort="True" SortMemberPath="Series"> <DataGridTemplateColumn MinWidth="80" Width="1*" Header="Series" CanUserSort="True" SortMemberPath="Series">
<DataGridTemplateColumn.CellTemplate> <DataGridTemplateColumn.CellTemplate>
<DataTemplate> <DataTemplate>
<Border BorderThickness="3" Height="80"> <Border BorderThickness="3" Height="80">
@ -150,7 +147,12 @@
<DataGridTemplateColumn.CellTemplate> <DataGridTemplateColumn.CellTemplate>
<DataTemplate> <DataTemplate>
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<Button Width="100" Height="80" Click="OnTagsButtonClick" ToolTip.Tip="Click to edit tags" Content="{Binding BookTags.Control}" /> <Button IsVisible="{Binding !BookTags.IsSeries}" Width="100" Height="80" Click="OnTagsButtonClick" ToolTip.Tip="Click to edit tags" >
<Panel>
<Image IsVisible="{Binding !BookTags.HasTags}" Stretch="None" Source="/AvaloniaUI/Assets/edit_25x25.png" />
<TextBlock IsVisible="{Binding BookTags.HasTags}" FontSize="12" TextWrapping="WrapWithOverflow" Text="{Binding BookTags.Tags}"/>
</Panel>
</Button>
</StackPanel> </StackPanel>
</DataTemplate> </DataTemplate>
</DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn.CellTemplate>

View File

@ -3,6 +3,7 @@ using AudibleUtilities;
using Avalonia; using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
using Avalonia.Media;
using DataLayer; using DataLayer;
using Dinah.Core.DataBinding; using Dinah.Core.DataBinding;
using FileLiberator; using FileLiberator;
@ -26,7 +27,7 @@ namespace LibationWinForms.AvaloniaUI.Views
public event EventHandler InitialLoaded; public event EventHandler InitialLoaded;
private ProductsDisplayViewModel _viewModel; private ProductsDisplayViewModel _viewModel;
private GridEntryBindingList2 bindingList => productsGrid.Items as GridEntryBindingList2; private GridEntryBindingList2 bindingList => _viewModel.GridEntries;
private IEnumerable<LibraryBookEntry2> GetAllBookEntries() private IEnumerable<LibraryBookEntry2> GetAllBookEntries()
=> bindingList.AllItems().BookEntries(); => bindingList.AllItems().BookEntries();
@ -46,12 +47,14 @@ namespace LibationWinForms.AvaloniaUI.Views
productsGrid.CanUserSortColumns = true; productsGrid.CanUserSortColumns = true;
removeGVColumn = productsGrid.Columns[0]; removeGVColumn = productsGrid.Columns[0];
}
public override void EndInit()
{
base.EndInit();
}
if (Design.IsDesignMode)
{
using var context = DbContexts.GetContext();
var book = context.GetLibraryBook_Flat_NoTracking("B017V4IM1G");
productsGrid.DataContext = _viewModel = new ProductsDisplayViewModel(new List<LibraryBook> { book });
}
}
private void InitializeComponent() private void InitializeComponent()
{ {
AvaloniaXamlLoader.Load(this); AvaloniaXamlLoader.Load(this);
@ -325,7 +328,8 @@ namespace LibationWinForms.AvaloniaUI.Views
InitialLoaded?.Invoke(this, EventArgs.Empty); InitialLoaded?.Invoke(this, EventArgs.Empty);
VisibleCountChanged?.Invoke(this, bindingList.BookEntries().Count()); VisibleCountChanged?.Invoke(this, bindingList.BookEntries().Count());
} }
UpdateGrid(dbBooks); else
UpdateGrid(dbBooks);
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@ -43,6 +43,7 @@
<None Remove="AvaloniaUI\Assets\cancel.png" /> <None Remove="AvaloniaUI\Assets\cancel.png" />
<None Remove="AvaloniaUI\Assets\completed.png" /> <None Remove="AvaloniaUI\Assets\completed.png" />
<None Remove="AvaloniaUI\Assets\down.png" /> <None Remove="AvaloniaUI\Assets\down.png" />
<None Remove="AvaloniaUI\Assets\edit_25x25.png" />
<None Remove="AvaloniaUI\Assets\errored.png" /> <None Remove="AvaloniaUI\Assets\errored.png" />
<None Remove="AvaloniaUI\Assets\first.png" /> <None Remove="AvaloniaUI\Assets\first.png" />
<None Remove="AvaloniaUI\Assets\import_16x16.png" /> <None Remove="AvaloniaUI\Assets\import_16x16.png" />