Workshop Library - Added library pages

UI - Tweaked design to more closely match WinUI 3 gallery examples
This commit is contained in:
Robert committed 2023-09-01 20:33:50 +02:00
1 parent e545d2f3da
commit 9c6d7329a6
25 files changed
+519 -288

No files matched your search

@@ -2,7 +2,67 @@
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"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Artemis.UI.Screens.Workshop.Library.Tabs.LibrarySubmissionsView">
Submission management here 😗
</UserControl>
xmlns:tabs="clr-namespace:Artemis.UI.Screens.Workshop.Library.Tabs"
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
xmlns:workshop="clr-namespace:Artemis.WebClient.Workshop;assembly=Artemis.WebClient.Workshop"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="650"
x:Class="Artemis.UI.Screens.Workshop.Library.Tabs.LibrarySubmissionsView"
x:DataType="tabs:LibrarySubmissionsViewModel">
<UserControl.Resources>
<controls:SymbolIconSource x:Key="GoIcon" Symbol="ChevronRight" />
</UserControl.Resources>
<UserControl.Styles>
<Styles>
<Style Selector="StackPanel.empty-state > TextBlock">
<Setter Property="TextAlignment" Value="Center"></Setter>
<Setter Property="TextWrapping" Value="Wrap"></Setter>
</Style>
</Styles>
</UserControl.Styles>
<Panel IsVisible="{CompiledBinding !IsLoading}">
<StackPanel IsVisible="{CompiledBinding !IsLoggedIn^}" Margin="0 50 0 0" Classes="empty-state">
<TextBlock Theme="{StaticResource TitleTextBlockStyle}">You are not logged in</TextBlock>
<TextBlock>
<Run>In order to manage your submissions you must be logged in.</Run>
</TextBlock>
<Lottie Path="/Assets/Animations/login-pending.json" RepeatCount="1" Width="350" Height="350"></Lottie>
<Button HorizontalAlignment="Center" Command="{CompiledBinding Login}">Log in</Button>
</StackPanel>
<Panel IsVisible="{CompiledBinding IsLoggedIn^}">
<StackPanel IsVisible="{CompiledBinding !Entries.Count}" Margin="0 50 0 0" Classes="empty-state">
<TextBlock Theme="{StaticResource TitleTextBlockStyle}">Oh boy, it's empty here 🤔</TextBlock>
<TextBlock>
<Run>Any entries you submit to the workshop you can later manage here</Run>
</TextBlock>
<Lottie Path="/Assets/Animations/empty.json" RepeatCount="1" Width="350" Height="350"></Lottie>
<Button HorizontalAlignment="Center" Command="{CompiledBinding AddSubmission}">Submit new entry</Button>
</StackPanel>
<ItemsRepeater IsVisible="{CompiledBinding Entries.Count}" ItemsSource="{CompiledBinding Entries}">
<ItemsRepeater.ItemTemplate>
<DataTemplate DataType="workshop:IGetSubmittedEntries_SubmittedEntries">
<controls:SettingsExpander
Header="{CompiledBinding Name}"
Description="{CompiledBinding Summary}"
IsClickEnabled="True"
ActionIconSource="{StaticResource GoIcon}"
Command="{Binding $parent[tabs:LibrarySubmissionsView].DataContext.NavigateToEntry}"
CommandParameter="{CompiledBinding}">
<controls:SettingsExpander.FooterTemplate>
<DataTemplate x:DataType="workshop:IGetSubmittedEntries_SubmittedEntries">
<Border Classes="badge" VerticalAlignment="Top" Margin="0 5 0 0">
<TextBlock Text="{CompiledBinding EntryType}"></TextBlock>
</Border>
</DataTemplate>
</controls:SettingsExpander.FooterTemplate>
</controls:SettingsExpander>
</DataTemplate>
</ItemsRepeater.ItemTemplate>
</ItemsRepeater>
</Panel>
</Panel>
</UserControl>
@@ -1,8 +1,108 @@
using System;
using System.Collections.ObjectModel;
using System.Reactive;
using System.Threading;
using System.Threading.Tasks;
using Artemis.UI.Extensions;
using Artemis.UI.Screens.Workshop.CurrentUser;
using Artemis.UI.Screens.Workshop.SubmissionWizard;
using Artemis.UI.Shared;
using Artemis.UI.Shared.Routing;
using Artemis.UI.Shared.Services;
using Artemis.WebClient.Workshop;
using Artemis.WebClient.Workshop.Services;
using DynamicData;
using ReactiveUI;
using StrawberryShake;
namespace Artemis.UI.Screens.Workshop.Library.Tabs;
public class LibrarySubmissionsViewModel : ActivatableViewModelBase
public class LibrarySubmissionsViewModel : ActivatableViewModelBase, IWorkshopViewModel
{
private readonly IWorkshopClient _client;
private readonly SourceCache<IGetSubmittedEntries_SubmittedEntries, Guid> _entries;
private readonly IWindowService _windowService;
private bool _isLoading = true;
private bool _workshopReachable;
public LibrarySubmissionsViewModel(IWorkshopClient client, IAuthenticationService authenticationService, IWindowService windowService, IWorkshopService workshopService, IRouter router)
{
_client = client;
_windowService = windowService;
_entries = new SourceCache<IGetSubmittedEntries_SubmittedEntries, Guid>(e => e.Id);
_entries.Connect().Bind(out ReadOnlyObservableCollection<IGetSubmittedEntries_SubmittedEntries> entries).Subscribe();
AddSubmission = ReactiveCommand.CreateFromTask(ExecuteAddSubmission, this.WhenAnyValue(vm => vm.WorkshopReachable));
Login = ReactiveCommand.CreateFromTask(ExecuteLogin, this.WhenAnyValue(vm => vm.WorkshopReachable));
NavigateToEntry = ReactiveCommand.CreateFromTask<IGetSubmittedEntries_SubmittedEntries>(ExecuteNavigateToEntry);
IsLoggedIn = authenticationService.IsLoggedIn;
Entries = entries;
this.WhenActivatedAsync(async d =>
{
WorkshopReachable = await workshopService.ValidateWorkshopStatus(d.AsCancellationToken());
if (WorkshopReachable)
await GetEntries(d.AsCancellationToken());
});
}
public ReactiveCommand<Unit, Unit> Login { get; }
public ReactiveCommand<Unit, Unit> AddSubmission { get; }
public ReactiveCommand<IGetSubmittedEntries_SubmittedEntries, Unit> NavigateToEntry { get; }
public IObservable<bool> IsLoggedIn { get; }
public ReadOnlyObservableCollection<IGetSubmittedEntries_SubmittedEntries> Entries { get; }
public bool WorkshopReachable
{
get => _workshopReachable;
set => RaiseAndSetIfChanged(ref _workshopReachable, value);
}
public bool IsLoading
{
get => _isLoading;
set => RaiseAndSetIfChanged(ref _isLoading, value);
}
private async Task ExecuteLogin(CancellationToken ct)
{
await _windowService.CreateContentDialog().WithViewModel(out WorkshopLoginViewModel _).WithTitle("Workshop login").ShowAsync();
}
private async Task ExecuteAddSubmission(CancellationToken arg)
{
await _windowService.ShowDialogAsync<SubmissionWizardViewModel, bool>();
}
private Task ExecuteNavigateToEntry(IGetSubmittedEntries_SubmittedEntries entry, CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
private async Task GetEntries(CancellationToken ct)
{
IsLoading = true;
try
{
IOperationResult<IGetSubmittedEntriesResult> result = await _client.GetSubmittedEntries.ExecuteAsync(null, ct);
if (result.Data?.SubmittedEntries == null)
_entries.Clear();
else
_entries.Edit(e =>
{
e.Clear();
e.AddOrUpdate(result.Data.SubmittedEntries);
});
}
finally
{
IsLoading = false;
}
}
public EntryType? EntryType => null;
}
@@ -2,26 +2,25 @@
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:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
xmlns:library="clr-namespace:Artemis.UI.Screens.Workshop.Library"
xmlns:routing="clr-namespace:Artemis.UI.Routing"
xmlns:ui1="clr-namespace:Artemis.UI"
xmlns:ui="clr-namespace:Artemis.UI"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Artemis.UI.Screens.Workshop.Library.WorkshopLibraryView"
x:DataType="library:WorkshopLibraryViewModel">
<ui:NavigationView PaneDisplayMode="Top" MenuItemsSource="{CompiledBinding Tabs}" SelectedItem="{CompiledBinding SelectedTab}">
<ui:NavigationView.Styles>
<controls:NavigationView PaneDisplayMode="Top" MenuItemsSource="{CompiledBinding Tabs}" SelectedItem="{CompiledBinding SelectedTab}">
<controls:NavigationView.Styles>
<Styles>
<Style Selector="ui|NavigationView:topnavminimal /template/ SplitView Border#ContentGridBorder">
<Style Selector="controls|NavigationView:topnavminimal /template/ SplitView Border#ContentGridBorder">
<Setter Property="CornerRadius" Value="8 0 0 0" />
</Style>
</Styles>
</ui:NavigationView.Styles>
</controls:NavigationView.Styles>
<ui:Frame Name="TabFrame" IsNavigationStackEnabled="False" CacheSize="0">
<ui:Frame.NavigationPageFactory>
<ui1:PageFactory/>
</ui:Frame.NavigationPageFactory>
</ui:Frame>
</ui:NavigationView>
<controls:Frame Name="TabFrame" IsNavigationStackEnabled="False" CacheSize="0" Padding="20">
<controls:Frame.NavigationPageFactory>
<ui:PageFactory/>
</controls:Frame.NavigationPageFactory>
</controls:Frame>
</controls:NavigationView>
</UserControl>
@@ -21,17 +21,18 @@ public partial class WorkshopLibraryView : ReactiveUserControl<WorkshopLibraryVi
private void Navigate(ViewModelBase viewModel)
{
Dispatcher.UIThread.Invoke(() =>
{
if (ViewModel == null)
return;
SlideNavigationTransitionInfo transitionInfo = new()
{
Effect = ViewModel.Tabs.IndexOf(ViewModel.SelectedTab) > _lastIndex ? SlideNavigationTransitionEffect.FromRight : SlideNavigationTransitionEffect.FromLeft
};
TabFrame.NavigateFromObject(viewModel, new FrameNavigationOptions {TransitionInfoOverride = transitionInfo});
_lastIndex = ViewModel.Tabs.IndexOf(ViewModel.SelectedTab);
});
Dispatcher.UIThread.Invoke(() => TabFrame.NavigateFromObject(viewModel, new FrameNavigationOptions {TransitionInfoOverride = GetTransitionInfo()}));
}
private SlideNavigationTransitionInfo GetTransitionInfo()
{
if (ViewModel?.SelectedTab == null)
return new SlideNavigationTransitionInfo();
SlideNavigationTransitionEffect effect = ViewModel.Tabs.IndexOf(ViewModel.SelectedTab) > _lastIndex ? SlideNavigationTransitionEffect.FromRight : SlideNavigationTransitionEffect.FromLeft;
SlideNavigationTransitionInfo info = new() {Effect = effect};
_lastIndex = ViewModel.Tabs.IndexOf(ViewModel.SelectedTab);
return info;
}
}