Skip to content

Commit 36b1f31

Browse files
committed
Gallery renovation
1 parent 173b61c commit 36b1f31

File tree

2 files changed

+100
-62
lines changed

2 files changed

+100
-62
lines changed

src/Lucide.Avalonia.Gallery/ViewModels/MainWindowViewModel.cs

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,18 @@
33
[Reactive]
44
public partial class MainWindowViewModel : ReactiveViewModel
55
{
6-
private readonly Lazy<IconViewModel[]> _icons = new(IconViewModel.CreateIconCollection);
6+
private readonly Lazy<IconViewModel[]> _allIconsLazy = new(IconViewModel.CreateIconCollection);
77
private readonly Lazy<FrozenDictionary<LucideIconKind, LucideIconInfo>> _iconsInfo = new(CreateIconCollectionInfo);
88

9+
public partial bool IsBusy { get; set; }
10+
911
public partial double Size { get; set; } = 24;
1012

1113
public partial float StrokeWidth { get; set; } = 1.5f;
1214

1315
public partial string? SearchText { get; set; }
1416

15-
public partial IEnumerable<IconViewModel>? Icons { get; set; }
17+
public partial IconViewModel[]? Icons { get; set; }
1618

1719
public MainWindowViewModel()
1820
{
@@ -21,10 +23,13 @@ public MainWindowViewModel()
2123
.Subscribe(_ => UpdateIcons());
2224

2325
this.WhenAnyValue(x => x.SearchText)
24-
.Throttle(TimeSpan.FromSeconds(.2))
25-
.Subscribe(async x => Icons = await FilterIconsAsync(x));
26+
.Throttle(TimeSpan.FromSeconds(.4))
27+
.Subscribe(FilterIconsAsync);
2628

27-
Task.Run(() => Icons = _icons.Value);
29+
Task.Run(() =>
30+
{
31+
Icons = _allIconsLazy.Value;
32+
});
2833
}
2934

3035
public void ResetCommand()
@@ -49,14 +54,17 @@ private void UpdateIcons()
4954
}
5055
}
5156

52-
private IconViewModel[] FilterIcons(string? value)
57+
private void FilterIcons(string? value)
5358
{
54-
var icons = _icons.Value;
55-
var result = new List<IconViewModel>(icons.Length);
59+
var icons = _allIconsLazy.Value;
60+
61+
var queue = new PriorityQueue<IconViewModel, int>(icons.Length);
5662

5763
if (string.IsNullOrWhiteSpace(value))
5864
{
59-
return icons;
65+
Icons = icons;
66+
67+
return;
6068
}
6169

6270
value = value.ToLower();
@@ -65,16 +73,35 @@ private IconViewModel[] FilterIcons(string? value)
6573
{
6674
var info = _iconsInfo.Value[icon.Kind];
6775

68-
if (info.Contains(value))
76+
if (info.Contains(value, out var priority))
6977
{
70-
result.Add(icon);
78+
queue.Enqueue(icon, priority);
7179
}
7280
}
7381

74-
return [.. result];
82+
var list = new List<IconViewModel>(queue.Count);
83+
84+
while (queue.Count > 0)
85+
{
86+
list.Add(queue.Dequeue());
87+
}
88+
89+
Icons = [.. list];
7590
}
7691

77-
private Task<IconViewModel[]> FilterIconsAsync(string? filter) => Task.Run(() => FilterIcons(filter));
92+
private async void FilterIconsAsync(string? filter)
93+
{
94+
IsBusy = true;
95+
96+
await Task.Delay(100);
97+
98+
await Task.Run(() =>
99+
{
100+
FilterIcons(filter);
101+
});
102+
103+
IsBusy = false;
104+
}
78105

79106
private static FrozenDictionary<LucideIconKind, LucideIconInfo> CreateIconCollectionInfo()
80107
{

src/Lucide.Avalonia.Gallery/Views/MainWindow.axaml

Lines changed: 60 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
<DockPanel>
4949
<Slider DockPanel.Dock="Bottom"
5050
Margin="-8 8"
51-
Minimum="16"
51+
Minimum="14"
5252
Maximum="48"
5353
TickFrequency="1"
5454
IsSnapToTickEnabled="True"
@@ -75,12 +75,19 @@
7575
<TextBlock Text="Stroke width:" FontWeight="SemiBold" DockPanel.Dock="Left"/>
7676
</DockPanel>
7777

78-
<Button Content="Reset" Classes="Basic" Cursor="Hand" Command="{Binding ResetCommand}"/>
78+
<Button Content="Reset"
79+
Classes="Basic"
80+
Cursor="Hand"
81+
Command="{Binding ResetCommand}"/>
7982

8083
</StackPanel>
8184

8285
<StackPanel DockPanel.Dock="Bottom">
83-
<Button Content="Switch Theme" Cursor="Hand" Command="{Binding SwitchBaseThemeCommand}"/>
86+
<Button Content="{LucideIconContent SunMoon, StrokeWidth=1}"
87+
Classes="Icon"
88+
Cursor="Hand"
89+
HorizontalAlignment="Left"
90+
Command="{Binding SwitchBaseThemeCommand}"/>
8491
</StackPanel>
8592

8693
</DockPanel>
@@ -98,52 +105,56 @@
98105
theme:TextBoxExtensions.AddDeleteButton="True">
99106
</TextBox>
100107

101-
<ScrollViewer Margin="0 20 0 0">
102-
103-
<ItemsControl ItemsSource="{Binding Icons}">
104-
<ItemsControl.ItemTemplate>
105-
<DataTemplate x:DataType="vm:IconViewModel">
106-
<suki:GlassCard Margin="6"
107-
Padding="10"
108-
CornerRadius="8"
109-
Cursor="Hand"
110-
IsAnimated="False"
111-
ToolTip.Tip="{Binding Tip}">
112-
113-
<LucideIcon Kind="{Binding Kind}"
114-
Size="{Binding Size}"
115-
StrokeWidth="{Binding StrokeWidth}"/>
116-
117-
<suki:GlassCard.ContextMenu>
118-
<ContextMenu>
119-
<MenuItem Header="Copy name"
120-
Command="{Binding CopyNameCommand}"
121-
Icon="{LucideIconContent Copy, 16, 2}"/>
122-
<MenuItem Header="Copy control"
123-
Command="{Binding CopyControlCommand}"
124-
Icon="{LucideIconContent Copy, 16, 2}"/>
125-
<MenuItem Header="Copy content extension"
126-
Command="{Binding CopyExtensionCommand}"
127-
Icon="{LucideIconContent Copy, 16, 2}"/>
128-
<ContextMenu.Styles>
129-
<Style Selector="LucideIcon">
130-
<Setter Property="StrokeWidth" Value="1.5"/>
131-
</Style>
132-
</ContextMenu.Styles>
133-
</ContextMenu>
134-
</suki:GlassCard.ContextMenu>
135-
136-
</suki:GlassCard>
137-
</DataTemplate>
138-
</ItemsControl.ItemTemplate>
139-
<ItemsControl.ItemsPanel>
140-
<ItemsPanelTemplate>
141-
<WrapPanel/>
142-
</ItemsPanelTemplate>
143-
</ItemsControl.ItemsPanel>
144-
</ItemsControl>
145-
146-
</ScrollViewer>
108+
<suki:BusyArea BusyText="Loading..." IsBusy="{Binding IsBusy}">
109+
110+
<ScrollViewer Margin="0 20 0 0">
111+
112+
<ItemsControl ItemsSource="{Binding Icons}">
113+
<ItemsControl.ItemTemplate>
114+
<DataTemplate x:DataType="vm:IconViewModel">
115+
<suki:GlassCard Margin="6"
116+
Padding="10"
117+
CornerRadius="8"
118+
Cursor="Hand"
119+
IsAnimated="False"
120+
ToolTip.Tip="{Binding Tip}">
121+
122+
<LucideIcon Kind="{Binding Kind}"
123+
Size="{Binding Size}"
124+
StrokeWidth="{Binding StrokeWidth}"/>
125+
126+
<suki:GlassCard.ContextMenu>
127+
<ContextMenu>
128+
<MenuItem Header="Copy name"
129+
Command="{Binding CopyNameCommand}"
130+
Icon="{LucideIconContent Copy, 16, 2}"/>
131+
<MenuItem Header="Copy control"
132+
Command="{Binding CopyControlCommand}"
133+
Icon="{LucideIconContent Copy, 16, 2}"/>
134+
<MenuItem Header="Copy content extension"
135+
Command="{Binding CopyExtensionCommand}"
136+
Icon="{LucideIconContent Copy, 16, 2}"/>
137+
<ContextMenu.Styles>
138+
<Style Selector="LucideIcon">
139+
<Setter Property="StrokeWidth" Value="1.5"/>
140+
</Style>
141+
</ContextMenu.Styles>
142+
</ContextMenu>
143+
</suki:GlassCard.ContextMenu>
144+
145+
</suki:GlassCard>
146+
</DataTemplate>
147+
</ItemsControl.ItemTemplate>
148+
<ItemsControl.ItemsPanel>
149+
<ItemsPanelTemplate>
150+
<WrapPanel/>
151+
</ItemsPanelTemplate>
152+
</ItemsControl.ItemsPanel>
153+
</ItemsControl>
154+
155+
</ScrollViewer>
156+
157+
</suki:BusyArea>
147158

148159
</DockPanel>
149160

0 commit comments

Comments
 (0)