Skip to content

Commit 6e62a96

Browse files
committed
app catalog as grid cards
1 parent eafe632 commit 6e62a96

1 file changed

Lines changed: 68 additions & 64 deletions

File tree

‎MainWindow.axaml.cs‎

Lines changed: 68 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
using System.Text.Json;
2222
using System.Runtime.InteropServices;
2323
using Avalonia.Platform;
24+
using Avalonia.Markup.Xaml.Converters;
25+
2426

2527
#if WINDOWS
2628
using NAudio.Wave;
@@ -4448,85 +4450,82 @@ private void RenderCatalogCategories(StackPanel container, List<(string Category
44484450
};
44494451
container.Children.Add(categoryHeader);
44504452

4453+
var wrapPanel = new WrapPanel { Margin = new Thickness(0, 8, 0, 0), VerticalAlignment = VerticalAlignment.Top };
44514454
foreach (var entry in entries)
44524455
{
44534456
bool alreadyAdded = installedRepos.Contains(entry.Repository);
44544457
var card = BuildCatalogCard(entry, alreadyAdded);
4455-
container.Children.Add(card);
4458+
wrapPanel.Children.Add(card);
44564459
}
4460+
container.Children.Add(wrapPanel);
44574461
}
44584462
}
44594463

4460-
private Border BuildCatalogCard(CatalogEntry entry, bool alreadyAdded)
4464+
private Border BuildCatalogCard(CatalogEntry entry, bool alreadyAdded)
44614465
{
4466+
var image = new Border
4467+
{
4468+
Height = 200,
4469+
Background = this.FindResource("ThemeLighter") as IBrush,
4470+
};
4471+
4472+
if (!string.IsNullOrEmpty(entry.AppIconUrl))
4473+
{
4474+
var img = new Image
4475+
{
4476+
Stretch = Stretch.UniformToFill,
4477+
};
4478+
image.Child = img;
4479+
4480+
_ = Task.Run(async () =>
4481+
{
4482+
try
4483+
{
4484+
using var client = new System.Net.Http.HttpClient();
4485+
var imageData = await client.GetByteArrayAsync(entry.AppIconUrl);
4486+
var bitmap = new Avalonia.Media.Imaging.Bitmap(new System.IO.MemoryStream(imageData));
4487+
4488+
await Dispatcher.UIThread.InvokeAsync(() =>
4489+
{
4490+
img.Source = bitmap;
4491+
});
4492+
}
4493+
catch
4494+
{
4495+
}
4496+
});
4497+
}
4498+
44624499
var nameBlock = new TextBlock
44634500
{
44644501
Text = entry.Name,
4465-
FontSize = 14,
4502+
FontSize = 13,
44664503
FontWeight = FontWeight.Bold,
44674504
Foreground = this.FindResource("ThemeText") as IBrush,
4505+
TextWrapping = TextWrapping.Wrap,
4506+
Margin = new Thickness(0, 8, 0, 2),
44684507
};
44694508

44704509
var repoBlock = new TextBlock
44714510
{
44724511
Text = entry.Repository,
4473-
FontSize = 12,
4512+
FontSize = 11,
44744513
Foreground = this.FindResource("ThemeTextSecondary") as IBrush,
4514+
TextWrapping = TextWrapping.Wrap,
44754515
};
44764516

4477-
var infoStack = new StackPanel { Spacing = 4, VerticalAlignment = VerticalAlignment.Center };
4517+
var infoStack = new StackPanel();
44784518
infoStack.Children.Add(nameBlock);
44794519
infoStack.Children.Add(repoBlock);
44804520

4481-
// Catalog icon
4482-
Control? iconControl = null;
4483-
if (!string.IsNullOrEmpty(entry.AppIconUrl))
4484-
{
4485-
try
4486-
{
4487-
var image = new Image
4488-
{
4489-
Width = 48,
4490-
Height = 48,
4491-
VerticalAlignment = VerticalAlignment.Center,
4492-
Margin = new Thickness(0, 0, 12, 0)
4493-
};
4494-
4495-
// try load remote image asynchronously
4496-
_ = Task.Run(async () =>
4497-
{
4498-
try
4499-
{
4500-
using var client = new System.Net.Http.HttpClient();
4501-
var imageData = await client.GetByteArrayAsync(entry.AppIconUrl);
4502-
var bitmap = new Avalonia.Media.Imaging.Bitmap(new System.IO.MemoryStream(imageData));
4503-
4504-
await Dispatcher.UIThread.InvokeAsync(() =>
4505-
{
4506-
image.Source = bitmap;
4507-
});
4508-
}
4509-
catch
4510-
{
4511-
// can't be loaded
4512-
}
4513-
});
4514-
4515-
iconControl = image;
4516-
}
4517-
catch
4518-
{
4519-
// skip on fail
4520-
}
4521-
}
4522-
45234521
var addButton = new Button
45244522
{
45254523
Content = alreadyAdded ? "Added" : "Add",
4526-
FontSize = 12,
4527-
Width = 80,
4524+
FontSize = 11,
4525+
Margin = new Thickness(2, 2, 2, 2),
4526+
Width = 70,
4527+
Height = 48,
45284528
IsEnabled = !alreadyAdded,
4529-
VerticalAlignment = VerticalAlignment.Center,
45304529
};
45314530
addButton.Classes.Add("options");
45324531

@@ -4536,29 +4535,34 @@ await Dispatcher.UIThread.InvokeAsync(() =>
45364535
addButton.Click += CatalogAddEntry_Click;
45374536
}
45384537

4539-
var contentStack = new StackPanel { Orientation = Orientation.Horizontal, Spacing = 12, VerticalAlignment = VerticalAlignment.Center };
4540-
if (iconControl != null)
4541-
contentStack.Children.Add(iconControl);
4542-
contentStack.Children.Add(infoStack);
4543-
4544-
var grid = new Grid
4538+
var footerGrid = new Grid
45454539
{
4546-
ColumnDefinitions = new ColumnDefinitions("*,Auto"),
4540+
Margin = new Thickness(8, 4, 8, 8),
45474541
};
4548-
Grid.SetColumn(contentStack, 0);
4542+
footerGrid.ColumnDefinitions.Add(new ColumnDefinition(GridLength.Star));
4543+
footerGrid.ColumnDefinitions.Add(new ColumnDefinition(GridLength.Auto));
4544+
Grid.SetColumn(infoStack, 0);
45494545
Grid.SetColumn(addButton, 1);
4550-
grid.Children.Add(contentStack);
4551-
grid.Children.Add(addButton);
4546+
footerGrid.Children.Add(infoStack);
4547+
footerGrid.Children.Add(addButton);
4548+
4549+
var cardGrid = new Grid();
4550+
cardGrid.RowDefinitions.Add(new RowDefinition(GridLength.Auto));
4551+
cardGrid.RowDefinitions.Add(new RowDefinition(GridLength.Star));
4552+
Grid.SetRow(image, 0);
4553+
Grid.SetRow(footerGrid, 1);
4554+
cardGrid.Children.Add(image);
4555+
cardGrid.Children.Add(footerGrid);
45524556

45534557
return new Border
45544558
{
4559+
Width = 200,
4560+
Margin = new Thickness(6),
45554561
Background = this.FindResource("ThemeBase") as IBrush,
45564562
BorderBrush = this.FindResource("ThemeBorder") as IBrush,
45574563
BorderThickness = new Thickness(1),
4558-
CornerRadius = new CornerRadius(6),
4559-
Padding = new Thickness(12),
4560-
Margin = new Thickness(0, 4, 0, 0),
4561-
Child = grid,
4564+
CornerRadius = new CornerRadius(8),
4565+
Child = cardGrid,
45624566
};
45634567
}
45644568

0 commit comments

Comments
 (0)