Workshop - Improve child navigation performance

This commit is contained in:
Robert committed 2024-04-12 22:53:40 +02:00
1 parent cac44d748d
commit 62057d657a
27 files changed
+309 -212

No files matched your search

@@ -2,7 +2,6 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:mdxaml="https://github.com/whistyun/Markdown.Avalonia.Tight"
xmlns:plugins="clr-namespace:Artemis.UI.Screens.Workshop.Plugins"
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
@@ -17,21 +16,32 @@
</Border>
<Border Classes="card" VerticalAlignment="Top" IsVisible="{CompiledBinding Entry.PluginInfo, Converter={x:Static ObjectConverters.IsNotNull}}">
<StackPanel>
<TextBlock>Admin required</TextBlock>
<TextBlock Text="Yes" IsVisible="{CompiledBinding Entry.PluginInfo.RequiresAdmin}" />
<TextBlock Text="No" IsVisible="{CompiledBinding !Entry.PluginInfo.RequiresAdmin}" />
<TextBlock Margin="0 15 0 5">Supported platforms</TextBlock>
<StackPanel Orientation="Horizontal" Spacing="10">
<avalonia:MaterialIcon Kind="MicrosoftWindows" IsVisible="{CompiledBinding Entry.PluginInfo.SupportsWindows}" />
<avalonia:MaterialIcon Kind="Linux" IsVisible="{CompiledBinding Entry.PluginInfo.SupportsLinux}" />
<avalonia:MaterialIcon Kind="Apple" IsVisible="{CompiledBinding Entry.PluginInfo.SupportsOSX}" />
<Panel>
<StackPanel IsVisible="{CompiledBinding Entry, Converter={x:Static ObjectConverters.IsNull}}">
<Border Width="110" Classes="skeleton-text"></Border>
<Border Width="35" Classes="skeleton-text"></Border>
<Border Margin="0 16 0 3" Width="130" Classes="skeleton-text"></Border>
<Border Width="60" Classes="skeleton-text"></Border>
</StackPanel>
</StackPanel>
<StackPanel IsVisible="{CompiledBinding Entry, Converter={x:Static ObjectConverters.IsNotNull}}">
<TextBlock>Admin required</TextBlock>
<TextBlock Text="Yes" IsVisible="{CompiledBinding Entry.PluginInfo.RequiresAdmin}" />
<TextBlock Text="No" IsVisible="{CompiledBinding !Entry.PluginInfo.RequiresAdmin}" />
<TextBlock Margin="0 15 0 5">Supported platforms</TextBlock>
<StackPanel Orientation="Horizontal" Spacing="10">
<avalonia:MaterialIcon Kind="MicrosoftWindows" IsVisible="{CompiledBinding Entry.PluginInfo.SupportsWindows}" />
<avalonia:MaterialIcon Kind="Linux" IsVisible="{CompiledBinding Entry.PluginInfo.SupportsLinux}" />
<avalonia:MaterialIcon Kind="Apple" IsVisible="{CompiledBinding Entry.PluginInfo.SupportsOSX}" />
</StackPanel>
</StackPanel>
</Panel>
</Border>
<Border Classes="card" VerticalAlignment="Top" IsVisible="{CompiledBinding Entry.Releases.Count}">
<Border Classes="card" VerticalAlignment="Top" IsVisible="{CompiledBinding Entry.Releases.Count, FallbackValue=False}">
<ContentControl Content="{CompiledBinding EntryReleasesViewModel}" />
</Border>
</StackPanel>
@@ -44,6 +54,6 @@
</controls:Frame>
</ScrollViewer>
<ContentControl Grid.Row="1" Grid.Column="2" IsVisible="{CompiledBinding Entry.Images.Count}" Content="{CompiledBinding EntryImagesViewModel}" />
<ContentControl Grid.Row="1" Grid.Column="2" IsVisible="{CompiledBinding Entry.Images.Count, FallbackValue=False}" Content="{CompiledBinding EntryImagesViewModel}" />
</Grid>
</UserControl>
@@ -11,7 +11,8 @@ public partial class PluginDetailsView : ReactiveUserControl<PluginDetailsViewMo
{
InitializeComponent();
this.WhenActivated(d => ViewModel.WhenAnyValue(vm => vm.Screen)
.Subscribe(screen => RouterFrame.NavigateFromObject(screen ?? ViewModel?.PluginDescriptionViewModel))
.WhereNotNull()
.Subscribe(screen => RouterFrame.NavigateFromObject(screen))
.DisposeWith(d));
}
}
@@ -16,32 +16,32 @@ namespace Artemis.UI.Screens.Workshop.Plugins;
public partial class PluginDetailsViewModel : RoutableHostScreen<RoutableScreen, WorkshopDetailParameters>
{
private readonly IWorkshopClient _client;
private readonly Func<IEntryDetails, EntryInfoViewModel> _getEntryInfoViewModel;
private readonly PluginDescriptionViewModel _pluginDescriptionViewModel;
private readonly Func<IEntryDetails, EntryReleasesViewModel> _getEntryReleasesViewModel;
private readonly Func<IEntryDetails, EntryImagesViewModel> _getEntryImagesViewModel;
[Notify] private IGetPluginEntryById_Entry? _entry;
[Notify] private EntryInfoViewModel? _entryInfoViewModel;
[Notify] private EntryReleasesViewModel? _entryReleasesViewModel;
[Notify] private EntryImagesViewModel? _entryImagesViewModel;
[Notify] private ReadOnlyObservableCollection<EntryListItemViewModel>? _dependants;
public PluginDetailsViewModel(IWorkshopClient client,
PluginDescriptionViewModel pluginDescriptionViewModel,
Func<IEntryDetails, EntryInfoViewModel> getEntryInfoViewModel,
EntryInfoViewModel entryInfoViewModel,
Func<IEntryDetails, EntryReleasesViewModel> getEntryReleasesViewModel,
Func<IEntryDetails, EntryImagesViewModel> getEntryImagesViewModel)
{
_client = client;
_getEntryInfoViewModel = getEntryInfoViewModel;
_pluginDescriptionViewModel = pluginDescriptionViewModel;
_getEntryReleasesViewModel = getEntryReleasesViewModel;
_getEntryImagesViewModel = getEntryImagesViewModel;
PluginDescriptionViewModel = pluginDescriptionViewModel;
EntryInfoViewModel = entryInfoViewModel;
RecycleScreen = false;
}
public PluginDescriptionViewModel PluginDescriptionViewModel { get; }
public override RoutableScreen DefaultScreen => _pluginDescriptionViewModel;
public EntryInfoViewModel EntryInfoViewModel { get; }
public override async Task OnNavigating(WorkshopDetailParameters parameters, NavigationArguments args, CancellationToken cancellationToken)
{
if (Entry?.Id != parameters.EntryId)
@@ -50,15 +50,19 @@ public partial class PluginDetailsViewModel : RoutableHostScreen<RoutableScreen,
private async Task GetEntry(long entryId, CancellationToken cancellationToken)
{
Task grace = Task.Delay(300, cancellationToken);
IOperationResult<IGetPluginEntryByIdResult> result = await _client.GetPluginEntryById.ExecuteAsync(entryId, cancellationToken);
if (result.IsErrorResult())
return;
// Let the UI settle to avoid lag when deep linking
await grace;
Entry = result.Data?.Entry;
EntryInfoViewModel = Entry != null ? _getEntryInfoViewModel(Entry) : null;
EntryInfoViewModel.SetEntry(Entry);
EntryReleasesViewModel = Entry != null ? _getEntryReleasesViewModel(Entry) : null;
EntryImagesViewModel = Entry != null ? _getEntryImagesViewModel(Entry) : null;
await PluginDescriptionViewModel.SetEntry(Entry, cancellationToken);
await _pluginDescriptionViewModel.SetEntry(Entry, cancellationToken);
}
}
@@ -11,7 +11,8 @@ public partial class PluginListView : ReactiveUserControl<PluginListViewModel>
{
InitializeComponent();
this.WhenActivated(d => ViewModel.WhenAnyValue(vm => vm.Screen)
.Subscribe(screen => RouterFrame.NavigateFromObject(screen ?? ViewModel?.EntryListViewModel))
.WhereNotNull()
.Subscribe(screen => RouterFrame.NavigateFromObject(screen))
.DisposeWith(d));
}
}
@@ -6,11 +6,12 @@ namespace Artemis.UI.Screens.Workshop.Plugins;
public class PluginListViewModel : RoutableHostScreen<RoutableScreen>
{
public EntryListViewModel EntryListViewModel { get; }
private readonly EntryListViewModel _entryListViewModel;
public override RoutableScreen DefaultScreen => _entryListViewModel;
public PluginListViewModel(EntryListViewModel entryListViewModel)
{
EntryListViewModel = entryListViewModel;
EntryListViewModel.EntryType = EntryType.Plugin;
_entryListViewModel = entryListViewModel;
_entryListViewModel.EntryType = EntryType.Plugin;
}
}