mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-12 21:38:38 +00:00
Workshop - Fixed deep linking to an entry
Workshop - Added the ability to upload new releases to existing submissions
This commit is contained in:
parent
bf3d5fc75d
commit
2ee170b803
@ -118,11 +118,9 @@ internal class Navigation
|
|||||||
Completed = true;
|
Completed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool PathEquals(string path, bool allowPartialMatch)
|
public bool PathEquals(string path, RouterNavigationOptions options)
|
||||||
{
|
{
|
||||||
if (allowPartialMatch)
|
return options.PathEquals(_resolution.Path, path);
|
||||||
return _resolution.Path.StartsWith(path, StringComparison.InvariantCultureIgnoreCase);
|
|
||||||
return string.Equals(_resolution.Path, path, StringComparison.InvariantCultureIgnoreCase);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool CancelIfRequested(NavigationArguments args, string stage, object screen)
|
private bool CancelIfRequested(NavigationArguments args, string stage, object screen)
|
||||||
|
|||||||
@ -58,11 +58,9 @@ internal class Router : CorePropertyChanged, IRouter, IDisposable
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool PathEquals(string path, bool allowPartialMatch)
|
private bool PathEquals(string path, RouterNavigationOptions options)
|
||||||
{
|
{
|
||||||
if (allowPartialMatch)
|
return _currentRouteSubject.Value != null && options.PathEquals(_currentRouteSubject.Value, path);
|
||||||
return _currentRouteSubject.Value != null && _currentRouteSubject.Value.StartsWith(path, StringComparison.InvariantCultureIgnoreCase);
|
|
||||||
return string.Equals(_currentRouteSubject.Value, path, StringComparison.InvariantCultureIgnoreCase);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@ -84,7 +82,7 @@ internal class Router : CorePropertyChanged, IRouter, IDisposable
|
|||||||
{
|
{
|
||||||
if (_root == null)
|
if (_root == null)
|
||||||
throw new ArtemisRoutingException("Cannot navigate without a root having been set");
|
throw new ArtemisRoutingException("Cannot navigate without a root having been set");
|
||||||
if (PathEquals(path, options.IgnoreOnPartialMatch) || (_currentNavigation != null && _currentNavigation.PathEquals(path, options.IgnoreOnPartialMatch)))
|
if (PathEquals(path, options) || (_currentNavigation != null && _currentNavigation.PathEquals(path, options)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
string? previousPath = _currentRouteSubject.Value;
|
string? previousPath = _currentRouteSubject.Value;
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
namespace Artemis.UI.Shared.Routing;
|
namespace Artemis.UI.Shared.Routing;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -21,9 +23,31 @@ public class RouterNavigationOptions
|
|||||||
/// <example>If set to true, a route change from <c>page/subpage1/subpage2</c> to <c>page/subpage1</c> will be ignored.</example>
|
/// <example>If set to true, a route change from <c>page/subpage1/subpage2</c> to <c>page/subpage1</c> will be ignored.</example>
|
||||||
public bool IgnoreOnPartialMatch { get; set; } = false;
|
public bool IgnoreOnPartialMatch { get; set; } = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the path to use when determining whether the path is a partial match,
|
||||||
|
/// only has any effect if <see cref="IgnoreOnPartialMatch"/> is <see langword="true"/>.
|
||||||
|
/// </summary>
|
||||||
|
public string? PartialMatchOverride { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a boolean value indicating whether logging should be enabled.
|
/// Gets or sets a boolean value indicating whether logging should be enabled.
|
||||||
/// <remarks>Errors and warnings are always logged.</remarks>
|
/// <remarks>Errors and warnings are always logged.</remarks>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool EnableLogging { get; set; } = true;
|
public bool EnableLogging { get; set; } = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines whether the given two paths are considered equal using these navigation options.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="current">The current path.</param>
|
||||||
|
/// <param name="target">The target path.</param>
|
||||||
|
/// <returns><see langword="true"/> if the paths are considered equal; otherwise <see langword="false"/>.</returns>
|
||||||
|
internal bool PathEquals(string current, string target)
|
||||||
|
{
|
||||||
|
if (PartialMatchOverride != null && IgnoreOnPartialMatch)
|
||||||
|
target = PartialMatchOverride;
|
||||||
|
|
||||||
|
if (IgnoreOnPartialMatch)
|
||||||
|
return current.StartsWith(target, StringComparison.InvariantCultureIgnoreCase);
|
||||||
|
return string.Equals(current, target, StringComparison.InvariantCultureIgnoreCase);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -4,20 +4,20 @@ namespace Artemis.UI.Routing;
|
|||||||
|
|
||||||
public class RouteViewModel
|
public class RouteViewModel
|
||||||
{
|
{
|
||||||
public RouteViewModel(string name, string path, string? mathPath = null)
|
public RouteViewModel(string name, string path, string? matchPath = null)
|
||||||
{
|
{
|
||||||
Path = path;
|
Path = path;
|
||||||
Name = name;
|
Name = name;
|
||||||
MathPath = mathPath;
|
MatchPath = matchPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Path { get; }
|
public string Path { get; }
|
||||||
public string Name { get; }
|
public string Name { get; }
|
||||||
public string? MathPath { get; }
|
public string? MatchPath { get; }
|
||||||
|
|
||||||
public bool Matches(string path)
|
public bool Matches(string path)
|
||||||
{
|
{
|
||||||
return path.StartsWith(MathPath ?? Path, StringComparison.InvariantCultureIgnoreCase);
|
return path.StartsWith(MatchPath ?? Path, StringComparison.InvariantCultureIgnoreCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
@ -34,7 +34,7 @@ public class EntriesViewModel : RoutableHostScreen<RoutableScreen>
|
|||||||
// Navigate on tab change
|
// Navigate on tab change
|
||||||
this.WhenAnyValue(vm => vm.SelectedTab)
|
this.WhenAnyValue(vm => vm.SelectedTab)
|
||||||
.WhereNotNull()
|
.WhereNotNull()
|
||||||
.Subscribe(s => router.Navigate(s.Path, new RouterNavigationOptions {IgnoreOnPartialMatch = true}))
|
.Subscribe(s => router.Navigate(s.Path, new RouterNavigationOptions {IgnoreOnPartialMatch = true, PartialMatchOverride = s.MatchPath}))
|
||||||
.DisposeWith(d);
|
.DisposeWith(d);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,15 +1,11 @@
|
|||||||
using System.Reactive;
|
using System.Reactive;
|
||||||
using System.Reactive.Disposables;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Artemis.UI.Extensions;
|
using Artemis.UI.Extensions;
|
||||||
using Artemis.UI.Screens.Workshop.SubmissionWizard;
|
using Artemis.UI.Screens.Workshop.SubmissionWizard;
|
||||||
using Artemis.UI.Shared;
|
|
||||||
using Artemis.UI.Shared.Routing;
|
using Artemis.UI.Shared.Routing;
|
||||||
using Artemis.UI.Shared.Services;
|
using Artemis.UI.Shared.Services;
|
||||||
using Artemis.WebClient.Workshop;
|
|
||||||
using Artemis.WebClient.Workshop.Services;
|
using Artemis.WebClient.Workshop.Services;
|
||||||
using Avalonia.Threading;
|
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.Workshop.Home;
|
namespace Artemis.UI.Screens.Workshop.Home;
|
||||||
@ -17,13 +13,11 @@ namespace Artemis.UI.Screens.Workshop.Home;
|
|||||||
public class WorkshopHomeViewModel : RoutableScreen
|
public class WorkshopHomeViewModel : RoutableScreen
|
||||||
{
|
{
|
||||||
private readonly IWindowService _windowService;
|
private readonly IWindowService _windowService;
|
||||||
private readonly IWorkshopService _workshopService;
|
|
||||||
private bool _workshopReachable;
|
private bool _workshopReachable;
|
||||||
|
|
||||||
public WorkshopHomeViewModel(IRouter router, IWindowService windowService, IWorkshopService workshopService)
|
public WorkshopHomeViewModel(IRouter router, IWindowService windowService, IWorkshopService workshopService)
|
||||||
{
|
{
|
||||||
_windowService = windowService;
|
_windowService = windowService;
|
||||||
_workshopService = workshopService;
|
|
||||||
|
|
||||||
AddSubmission = ReactiveCommand.CreateFromTask(ExecuteAddSubmission, this.WhenAnyValue(vm => vm.WorkshopReachable));
|
AddSubmission = ReactiveCommand.CreateFromTask(ExecuteAddSubmission, this.WhenAnyValue(vm => vm.WorkshopReachable));
|
||||||
Navigate = ReactiveCommand.CreateFromTask<string>(async r => await router.Navigate(r), this.WhenAnyValue(vm => vm.WorkshopReachable));
|
Navigate = ReactiveCommand.CreateFromTask<string>(async r => await router.Navigate(r), this.WhenAnyValue(vm => vm.WorkshopReachable));
|
||||||
@ -42,6 +36,6 @@ public class WorkshopHomeViewModel : RoutableScreen
|
|||||||
|
|
||||||
private async Task ExecuteAddSubmission(CancellationToken arg)
|
private async Task ExecuteAddSubmission(CancellationToken arg)
|
||||||
{
|
{
|
||||||
await _windowService.ShowDialogAsync<SubmissionWizardViewModel, bool>();
|
await _windowService.ShowDialogAsync<SubmissionWizardViewModel>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -5,6 +5,7 @@
|
|||||||
xmlns:library="clr-namespace:Artemis.UI.Screens.Workshop.Library"
|
xmlns:library="clr-namespace:Artemis.UI.Screens.Workshop.Library"
|
||||||
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||||
xmlns:converters="clr-namespace:Artemis.UI.Converters"
|
xmlns:converters="clr-namespace:Artemis.UI.Converters"
|
||||||
|
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Artemis.UI.Screens.Workshop.Library.SubmissionDetailView"
|
x:Class="Artemis.UI.Screens.Workshop.Library.SubmissionDetailView"
|
||||||
x:DataType="library:SubmissionDetailViewModel">
|
x:DataType="library:SubmissionDetailViewModel">
|
||||||
@ -43,6 +44,9 @@
|
|||||||
</StackPanel>
|
</StackPanel>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Border>
|
</Border>
|
||||||
|
<controls:HyperlinkButton Command="{CompiledBinding ViewWorkshopPage}" HorizontalAlignment="Center">
|
||||||
|
View workshop page
|
||||||
|
</controls:HyperlinkButton>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<ContentControl Grid.Column="1" Content="{CompiledBinding EntrySpecificationsViewModel}"></ContentControl>
|
<ContentControl Grid.Column="1" Content="{CompiledBinding EntrySpecificationsViewModel}"></ContentControl>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@ -7,9 +7,11 @@ using System.Threading;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Artemis.UI.Screens.Workshop.Entries;
|
using Artemis.UI.Screens.Workshop.Entries;
|
||||||
using Artemis.UI.Screens.Workshop.Parameters;
|
using Artemis.UI.Screens.Workshop.Parameters;
|
||||||
|
using Artemis.UI.Screens.Workshop.SubmissionWizard;
|
||||||
using Artemis.UI.Shared.Routing;
|
using Artemis.UI.Shared.Routing;
|
||||||
using Artemis.UI.Shared.Services;
|
using Artemis.UI.Shared.Services;
|
||||||
using Artemis.WebClient.Workshop;
|
using Artemis.WebClient.Workshop;
|
||||||
|
using Artemis.WebClient.Workshop.Services;
|
||||||
using Avalonia.Media.Imaging;
|
using Avalonia.Media.Imaging;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
using StrawberryShake;
|
using StrawberryShake;
|
||||||
@ -22,26 +24,32 @@ public class SubmissionDetailViewModel : RoutableScreen<WorkshopDetailParameters
|
|||||||
private readonly IHttpClientFactory _httpClientFactory;
|
private readonly IHttpClientFactory _httpClientFactory;
|
||||||
private readonly Func<EntrySpecificationsViewModel> _getEntrySpecificationsViewModel;
|
private readonly Func<EntrySpecificationsViewModel> _getEntrySpecificationsViewModel;
|
||||||
private readonly IWindowService _windowService;
|
private readonly IWindowService _windowService;
|
||||||
|
private readonly IWorkshopService _workshopService;
|
||||||
private readonly IRouter _router;
|
private readonly IRouter _router;
|
||||||
private IGetSubmittedEntryById_Entry? _entry;
|
private IGetSubmittedEntryById_Entry? _entry;
|
||||||
private EntrySpecificationsViewModel? _entrySpecificationsViewModel;
|
private EntrySpecificationsViewModel? _entrySpecificationsViewModel;
|
||||||
|
|
||||||
public SubmissionDetailViewModel(IWorkshopClient client,
|
public SubmissionDetailViewModel(IWorkshopClient client,
|
||||||
IHttpClientFactory httpClientFactory,
|
IHttpClientFactory httpClientFactory,
|
||||||
Func<EntrySpecificationsViewModel> entrySpecificationsViewModel,
|
|
||||||
IWindowService windowService,
|
IWindowService windowService,
|
||||||
IRouter router)
|
IWorkshopService workshopService,
|
||||||
|
IRouter router,
|
||||||
|
Func<EntrySpecificationsViewModel> entrySpecificationsViewModel)
|
||||||
{
|
{
|
||||||
_client = client;
|
_client = client;
|
||||||
_httpClientFactory = httpClientFactory;
|
_httpClientFactory = httpClientFactory;
|
||||||
_getEntrySpecificationsViewModel = entrySpecificationsViewModel;
|
|
||||||
_windowService = windowService;
|
_windowService = windowService;
|
||||||
|
_workshopService = workshopService;
|
||||||
_router = router;
|
_router = router;
|
||||||
|
_getEntrySpecificationsViewModel = entrySpecificationsViewModel;
|
||||||
|
|
||||||
|
Save = ReactiveCommand.CreateFromTask(ExecuteSave);
|
||||||
CreateRelease = ReactiveCommand.CreateFromTask(ExecuteCreateRelease);
|
CreateRelease = ReactiveCommand.CreateFromTask(ExecuteCreateRelease);
|
||||||
DeleteSubmission = ReactiveCommand.CreateFromTask(ExecuteDeleteSubmission);
|
DeleteSubmission = ReactiveCommand.CreateFromTask(ExecuteDeleteSubmission);
|
||||||
|
ViewWorkshopPage = ReactiveCommand.CreateFromTask(ExecuteViewWorkshopPage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ReactiveCommand<Unit, Unit> Save { get; }
|
||||||
public ReactiveCommand<Unit, Unit> CreateRelease { get; }
|
public ReactiveCommand<Unit, Unit> CreateRelease { get; }
|
||||||
public ReactiveCommand<Unit, Unit> DeleteSubmission { get; }
|
public ReactiveCommand<Unit, Unit> DeleteSubmission { get; }
|
||||||
|
|
||||||
@ -57,6 +65,8 @@ public class SubmissionDetailViewModel : RoutableScreen<WorkshopDetailParameters
|
|||||||
set => RaiseAndSetIfChanged(ref _entry, value);
|
set => RaiseAndSetIfChanged(ref _entry, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ReactiveCommand<Unit, Unit> ViewWorkshopPage { get; }
|
||||||
|
|
||||||
public override async Task OnNavigating(WorkshopDetailParameters parameters, NavigationArguments args, CancellationToken cancellationToken)
|
public override async Task OnNavigating(WorkshopDetailParameters parameters, NavigationArguments args, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
IOperationResult<IGetSubmittedEntryByIdResult> result = await _client.GetSubmittedEntryById.ExecuteAsync(parameters.EntryId, cancellationToken);
|
IOperationResult<IGetSubmittedEntryByIdResult> result = await _client.GetSubmittedEntryById.ExecuteAsync(parameters.EntryId, cancellationToken);
|
||||||
@ -107,16 +117,24 @@ public class SubmissionDetailViewModel : RoutableScreen<WorkshopDetailParameters
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task ExecuteCreateRelease(CancellationToken cancellationToken)
|
private async Task ExecuteSave(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
UpdateEntryInput input = new();
|
||||||
|
IOperationResult<IUpdateEntryResult> result = await _client.UpdateEntry.ExecuteAsync(input, cancellationToken);
|
||||||
|
result.EnsureNoErrors();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ExecuteCreateRelease(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
if (Entry != null)
|
||||||
|
await _windowService.ShowDialogAsync<ReleaseWizardViewModel>(Entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ExecuteDeleteSubmission(CancellationToken cancellationToken)
|
private async Task ExecuteDeleteSubmission(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (Entry == null)
|
if (Entry == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
bool confirmed = await _windowService.ShowConfirmContentDialog(
|
bool confirmed = await _windowService.ShowConfirmContentDialog(
|
||||||
"Delete submission?",
|
"Delete submission?",
|
||||||
"You cannot undo this by yourself.\r\n" +
|
"You cannot undo this by yourself.\r\n" +
|
||||||
@ -128,4 +146,10 @@ public class SubmissionDetailViewModel : RoutableScreen<WorkshopDetailParameters
|
|||||||
result.EnsureNoErrors();
|
result.EnsureNoErrors();
|
||||||
await _router.Navigate("workshop/library/submissions");
|
await _router.Navigate("workshop/library/submissions");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task ExecuteViewWorkshopPage()
|
||||||
|
{
|
||||||
|
if (Entry != null)
|
||||||
|
await _workshopService.NavigateToEntry(Entry.Id, Entry.EntryType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -75,7 +75,7 @@ public class SubmissionsTabViewModel : RoutableScreen
|
|||||||
|
|
||||||
private async Task ExecuteAddSubmission(CancellationToken arg)
|
private async Task ExecuteAddSubmission(CancellationToken arg)
|
||||||
{
|
{
|
||||||
await _windowService.ShowDialogAsync<SubmissionWizardViewModel, bool>();
|
await _windowService.ShowDialogAsync<SubmissionWizardViewModel>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ExecuteNavigateToEntry(IGetSubmittedEntries_SubmittedEntries entry, CancellationToken cancellationToken)
|
private async Task ExecuteNavigateToEntry(IGetSubmittedEntries_SubmittedEntries entry, CancellationToken cancellationToken)
|
||||||
|
|||||||
@ -0,0 +1,7 @@
|
|||||||
|
namespace Artemis.UI.Screens.Workshop.SubmissionWizard;
|
||||||
|
|
||||||
|
public interface IWorkshopWizardViewModel
|
||||||
|
{
|
||||||
|
SubmissionViewModel Screen { get; set; }
|
||||||
|
bool ShouldClose { get; set; }
|
||||||
|
}
|
||||||
@ -0,0 +1,61 @@
|
|||||||
|
<Window xmlns="https://github.com/avaloniaui"
|
||||||
|
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:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||||
|
xmlns:submissionWizard="clr-namespace:Artemis.UI.Screens.Workshop.SubmissionWizard"
|
||||||
|
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||||
|
xmlns:ui="clr-namespace:Artemis.UI"
|
||||||
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
|
x:Class="Artemis.UI.Screens.Workshop.SubmissionWizard.ReleaseWizardView"
|
||||||
|
x:DataType="submissionWizard:ReleaseWizardViewModel"
|
||||||
|
Icon="/Assets/Images/Logo/application.ico"
|
||||||
|
Title="Artemis | Workshop release wizard"
|
||||||
|
Width="1000"
|
||||||
|
Height="950"
|
||||||
|
WindowStartupLocation="CenterOwner">
|
||||||
|
<Grid Margin="15" RowDefinitions="Auto,*,Auto">
|
||||||
|
<Grid RowDefinitions="*,*" ColumnDefinitions="Auto,*,Auto" Margin="0 0 0 15">
|
||||||
|
<ContentControl Grid.Column="0" Grid.RowSpan="2" Width="65" Height="65" VerticalAlignment="Center" Margin="0 0 20 0" Content="{CompiledBinding CurrentUserViewModel}"/>
|
||||||
|
<TextBlock Grid.Row="0" Grid.Column="1" FontSize="36" VerticalAlignment="Bottom" Text="{CompiledBinding CurrentUserViewModel.Name}" IsVisible="{CompiledBinding !CurrentUserViewModel.IsAnonymous}"/>
|
||||||
|
<TextBlock Grid.Row="0" Grid.Column="1" FontSize="36" VerticalAlignment="Bottom" Text="Not logged in" IsVisible="{CompiledBinding CurrentUserViewModel.IsAnonymous}"/>
|
||||||
|
|
||||||
|
<StackPanel Grid.Row="0" Grid.Column="2" HorizontalAlignment="Right" VerticalAlignment="Bottom" Orientation="Horizontal">
|
||||||
|
<controls:HyperlinkButton Classes="icon-button" ToolTip.Tip="View Wiki" NavigateUri="https://wiki.artemis-rgb.com?mtm_campaign=artemis&mtm_kwd=workshop-wizard">
|
||||||
|
<avalonia:MaterialIcon Kind="BookOpenOutline" />
|
||||||
|
</controls:HyperlinkButton>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<TextBlock Grid.Row="1"
|
||||||
|
Grid.Column="1"
|
||||||
|
VerticalAlignment="Top"
|
||||||
|
Classes="subtitle"
|
||||||
|
Text="New workshop release" />
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Border Classes="card" Grid.Row="1" Grid.Column="0">
|
||||||
|
<controls:Frame Name="Frame" IsNavigationStackEnabled="False" CacheSize="0">
|
||||||
|
<controls:Frame.NavigationPageFactory>
|
||||||
|
<ui:PageFactory/>
|
||||||
|
</controls:Frame.NavigationPageFactory>
|
||||||
|
</controls:Frame>
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
<StackPanel IsVisible="{CompiledBinding Screen, Converter={x:Static ObjectConverters.IsNotNull}}"
|
||||||
|
Grid.Row="2"
|
||||||
|
Grid.Column="0"
|
||||||
|
HorizontalAlignment="Right"
|
||||||
|
Orientation="Horizontal"
|
||||||
|
Spacing="5"
|
||||||
|
Margin="0 15 0 0">
|
||||||
|
<Button Command="{CompiledBinding Screen.GoBack}" IsVisible="{CompiledBinding Screen.ShowGoBack}">
|
||||||
|
Back
|
||||||
|
</Button>
|
||||||
|
<Button Command="{CompiledBinding Screen.Continue}" IsVisible="{CompiledBinding !Screen.ShowFinish}" Width="80" Content="{CompiledBinding Screen.ContinueText}"/>
|
||||||
|
<Button Command="{CompiledBinding Screen.Continue}" IsVisible="{CompiledBinding Screen.ShowFinish}" Width="80">
|
||||||
|
Finish
|
||||||
|
</Button>
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
</Window>
|
||||||
@ -0,0 +1,35 @@
|
|||||||
|
using System;
|
||||||
|
using System.Reactive.Disposables;
|
||||||
|
using System.Reactive.Linq;
|
||||||
|
using Artemis.UI.Shared;
|
||||||
|
using Avalonia;
|
||||||
|
using Avalonia.Threading;
|
||||||
|
using ReactiveUI;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Screens.Workshop.SubmissionWizard;
|
||||||
|
|
||||||
|
public partial class ReleaseWizardView: ReactiveAppWindow<ReleaseWizardViewModel>
|
||||||
|
{
|
||||||
|
public ReleaseWizardView()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
#if DEBUG
|
||||||
|
this.AttachDevTools();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
this.WhenActivated(d => ViewModel.WhenAnyValue(vm => vm.Screen).WhereNotNull().Subscribe(Navigate).DisposeWith(d));
|
||||||
|
this.WhenActivated(d => ViewModel.WhenAnyValue(vm => vm.ShouldClose).Where(c => c).Subscribe(_ => Close()).DisposeWith(d));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Navigate(SubmissionViewModel viewModel)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Dispatcher.UIThread.Invoke(() => Frame.NavigateFromObject(viewModel));
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ViewModel?.WindowService.ShowExceptionDialog("Wizard screen failed to activate", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,51 @@
|
|||||||
|
using Artemis.UI.Screens.Workshop.CurrentUser;
|
||||||
|
using Artemis.UI.Shared;
|
||||||
|
using Artemis.UI.Shared.Services;
|
||||||
|
using Artemis.WebClient.Workshop;
|
||||||
|
using DryIoc;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Screens.Workshop.SubmissionWizard;
|
||||||
|
|
||||||
|
public class ReleaseWizardViewModel : ActivatableViewModelBase, IWorkshopWizardViewModel
|
||||||
|
{
|
||||||
|
private readonly SubmissionWizardState _state;
|
||||||
|
private SubmissionViewModel? _screen;
|
||||||
|
private bool _shouldClose;
|
||||||
|
|
||||||
|
public ReleaseWizardViewModel(IContainer container, IWindowService windowService, CurrentUserViewModel currentUserViewModel, IGetSubmittedEntryById_Entry entry)
|
||||||
|
{
|
||||||
|
_state = new SubmissionWizardState(this, container, windowService)
|
||||||
|
{
|
||||||
|
EntryType = entry.EntryType,
|
||||||
|
EntryId = entry.Id
|
||||||
|
};
|
||||||
|
|
||||||
|
WindowService = windowService;
|
||||||
|
CurrentUserViewModel = currentUserViewModel;
|
||||||
|
CurrentUserViewModel.AllowLogout = false;
|
||||||
|
Entry = entry;
|
||||||
|
|
||||||
|
_state.StartForCurrentEntry();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IWindowService WindowService { get; }
|
||||||
|
public IGetSubmittedEntryById_Entry Entry { get; }
|
||||||
|
public CurrentUserViewModel CurrentUserViewModel { get; }
|
||||||
|
|
||||||
|
public SubmissionViewModel? Screen
|
||||||
|
{
|
||||||
|
get => _screen;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value != null)
|
||||||
|
value.State = _state;
|
||||||
|
RaiseAndSetIfChanged(ref _screen, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ShouldClose
|
||||||
|
{
|
||||||
|
get => _shouldClose;
|
||||||
|
set => RaiseAndSetIfChanged(ref _shouldClose, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -35,7 +35,6 @@ public class EntryTypeStepViewModel : SubmissionViewModel
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
State.EntryType = SelectedEntryType.Value;
|
State.EntryType = SelectedEntryType.Value;
|
||||||
if (State.EntryType == EntryType.Profile)
|
State.StartForCurrentEntry();
|
||||||
State.ChangeScreen<ProfileSelectionStepViewModel>();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -62,6 +62,9 @@ public class ProfileAdaptionHintsStepViewModel : SubmissionViewModel
|
|||||||
if (Layers.Any(l => l.AdaptionHintCount == 0))
|
if (Layers.Any(l => l.AdaptionHintCount == 0))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
State.ChangeScreen<SpecificationsStepViewModel>();
|
if (State.EntryId == null)
|
||||||
|
State.ChangeScreen<SpecificationsStepViewModel>();
|
||||||
|
else
|
||||||
|
State.ChangeScreen<UploadStepViewModel>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,34 +1,22 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reactive;
|
using System.Reactive;
|
||||||
using System.Reactive.Disposables;
|
using System.Reactive.Disposables;
|
||||||
using System.Reactive.Linq;
|
using System.Reactive.Linq;
|
||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using Artemis.Core.Services;
|
using Artemis.Core.Services;
|
||||||
using Artemis.Storage.Entities.Profile;
|
|
||||||
using Artemis.Storage.Repositories.Interfaces;
|
|
||||||
using Artemis.UI.Extensions;
|
using Artemis.UI.Extensions;
|
||||||
using Artemis.UI.Screens.Workshop.Profile;
|
using Artemis.UI.Screens.Workshop.Profile;
|
||||||
using Avalonia;
|
|
||||||
using Avalonia.Controls;
|
|
||||||
using Avalonia.Controls.Shapes;
|
|
||||||
using Avalonia.Layout;
|
|
||||||
using Avalonia.Media;
|
|
||||||
using Avalonia.Media.Imaging;
|
|
||||||
using Material.Icons;
|
using Material.Icons;
|
||||||
using Material.Icons.Avalonia;
|
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
using SkiaSharp;
|
using SkiaSharp;
|
||||||
using Path = Avalonia.Controls.Shapes.Path;
|
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.Workshop.SubmissionWizard.Steps.Profile;
|
namespace Artemis.UI.Screens.Workshop.SubmissionWizard.Steps.Profile;
|
||||||
|
|
||||||
public class ProfileSelectionStepViewModel : SubmissionViewModel
|
public class ProfileSelectionStepViewModel : SubmissionViewModel
|
||||||
{
|
{
|
||||||
private readonly IProfileService _profileService;
|
private readonly IProfileService _profileService;
|
||||||
private readonly IProfileCategoryRepository _profileCategoryRepository;
|
|
||||||
private ProfileConfiguration? _selectedProfile;
|
private ProfileConfiguration? _selectedProfile;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@ -49,26 +37,12 @@ public class ProfileSelectionStepViewModel : SubmissionViewModel
|
|||||||
this.WhenAnyValue(vm => vm.SelectedProfile).Subscribe(p => Update(p));
|
this.WhenAnyValue(vm => vm.SelectedProfile).Subscribe(p => Update(p));
|
||||||
this.WhenActivated((CompositeDisposable _) =>
|
this.WhenActivated((CompositeDisposable _) =>
|
||||||
{
|
{
|
||||||
|
ShowGoBack = State.EntryId == null;
|
||||||
if (State.EntrySource is ProfileConfiguration profileConfiguration)
|
if (State.EntrySource is ProfileConfiguration profileConfiguration)
|
||||||
SelectedProfile = Profiles.FirstOrDefault(p => p.ProfileId == profileConfiguration.ProfileId);
|
SelectedProfile = Profiles.FirstOrDefault(p => p.ProfileId == profileConfiguration.ProfileId);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Update(ProfileConfiguration? profileConfiguration)
|
|
||||||
{
|
|
||||||
ProfilePreview.ProfileConfiguration = null;
|
|
||||||
|
|
||||||
foreach (ProfileConfiguration configuration in Profiles)
|
|
||||||
{
|
|
||||||
if (configuration == profileConfiguration)
|
|
||||||
_profileService.ActivateProfile(configuration);
|
|
||||||
else
|
|
||||||
_profileService.DeactivateProfile(configuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
ProfilePreview.ProfileConfiguration = profileConfiguration;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ObservableCollection<ProfileConfiguration> Profiles { get; }
|
public ObservableCollection<ProfileConfiguration> Profiles { get; }
|
||||||
public ProfilePreviewViewModel ProfilePreview { get; }
|
public ProfilePreviewViewModel ProfilePreview { get; }
|
||||||
|
|
||||||
@ -84,6 +58,21 @@ public class ProfileSelectionStepViewModel : SubmissionViewModel
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override ReactiveCommand<Unit, Unit> GoBack { get; }
|
public override ReactiveCommand<Unit, Unit> GoBack { get; }
|
||||||
|
|
||||||
|
private void Update(ProfileConfiguration? profileConfiguration)
|
||||||
|
{
|
||||||
|
ProfilePreview.ProfileConfiguration = null;
|
||||||
|
|
||||||
|
foreach (ProfileConfiguration configuration in Profiles)
|
||||||
|
{
|
||||||
|
if (configuration == profileConfiguration)
|
||||||
|
_profileService.ActivateProfile(configuration);
|
||||||
|
else
|
||||||
|
_profileService.DeactivateProfile(configuration);
|
||||||
|
}
|
||||||
|
|
||||||
|
ProfilePreview.ProfileConfiguration = profileConfiguration;
|
||||||
|
}
|
||||||
|
|
||||||
private void ExecuteContinue()
|
private void ExecuteContinue()
|
||||||
{
|
{
|
||||||
if (SelectedProfile == null)
|
if (SelectedProfile == null)
|
||||||
|
|||||||
@ -1,37 +1,36 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Reactive;
|
using System.Reactive;
|
||||||
|
using System.Reactive.Disposables;
|
||||||
using System.Reactive.Linq;
|
using System.Reactive.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Artemis.UI.Shared.Routing;
|
||||||
using Artemis.UI.Shared.Services;
|
using Artemis.UI.Shared.Services;
|
||||||
|
using Artemis.UI.Shared.Utilities;
|
||||||
using Artemis.WebClient.Workshop;
|
using Artemis.WebClient.Workshop;
|
||||||
|
using Artemis.WebClient.Workshop.Exceptions;
|
||||||
|
using Artemis.WebClient.Workshop.Services;
|
||||||
using Artemis.WebClient.Workshop.UploadHandlers;
|
using Artemis.WebClient.Workshop.UploadHandlers;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
using StrawberryShake;
|
using StrawberryShake;
|
||||||
using System.Reactive.Disposables;
|
|
||||||
using Artemis.Core;
|
|
||||||
using Artemis.UI.Shared.Routing;
|
|
||||||
using System;
|
|
||||||
using Artemis.UI.Shared.Utilities;
|
|
||||||
using Artemis.WebClient.Workshop.Services;
|
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.Workshop.SubmissionWizard.Steps;
|
namespace Artemis.UI.Screens.Workshop.SubmissionWizard.Steps;
|
||||||
|
|
||||||
public class UploadStepViewModel : SubmissionViewModel
|
public class UploadStepViewModel : SubmissionViewModel
|
||||||
{
|
{
|
||||||
|
private readonly EntryUploadHandlerFactory _entryUploadHandlerFactory;
|
||||||
|
private readonly Progress<StreamProgress> _progress = new();
|
||||||
|
private readonly ObservableAsPropertyHelper<bool> _progressIndeterminate;
|
||||||
|
private readonly ObservableAsPropertyHelper<int> _progressPercentage;
|
||||||
|
private readonly IRouter _router;
|
||||||
|
private readonly IWindowService _windowService;
|
||||||
private readonly IWorkshopClient _workshopClient;
|
private readonly IWorkshopClient _workshopClient;
|
||||||
private readonly IWorkshopService _workshopService;
|
private readonly IWorkshopService _workshopService;
|
||||||
private readonly EntryUploadHandlerFactory _entryUploadHandlerFactory;
|
|
||||||
private readonly IWindowService _windowService;
|
|
||||||
private readonly IRouter _router;
|
|
||||||
private readonly Progress<StreamProgress> _progress = new();
|
|
||||||
private readonly ObservableAsPropertyHelper<int> _progressPercentage;
|
|
||||||
private readonly ObservableAsPropertyHelper<bool> _progressIndeterminate;
|
|
||||||
|
|
||||||
private Guid? _entryId;
|
private Guid? _entryId;
|
||||||
|
private bool _failed;
|
||||||
private bool _finished;
|
private bool _finished;
|
||||||
private bool _succeeded;
|
private bool _succeeded;
|
||||||
private bool _failed;
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public UploadStepViewModel(IWorkshopClient workshopClient, IWorkshopService workshopService, EntryUploadHandlerFactory entryUploadHandlerFactory, IWindowService windowService, IRouter router)
|
public UploadStepViewModel(IWorkshopClient workshopClient, IWorkshopService workshopService, EntryUploadHandlerFactory entryUploadHandlerFactory, IWindowService windowService, IRouter router)
|
||||||
@ -83,7 +82,45 @@ public class UploadStepViewModel : SubmissionViewModel
|
|||||||
set => RaiseAndSetIfChanged(ref _failed, value);
|
set => RaiseAndSetIfChanged(ref _failed, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task ExecuteUpload(CancellationToken cancellationToken)
|
private async Task ExecuteUpload(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
// Use the existing entry or create a new one
|
||||||
|
_entryId = State.EntryId ?? await CreateEntry(cancellationToken);
|
||||||
|
|
||||||
|
// If a new entry had to be created but that failed, stop here, CreateEntry will send the user back
|
||||||
|
if (_entryId == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IEntryUploadHandler uploadHandler = _entryUploadHandlerFactory.CreateHandler(State.EntryType);
|
||||||
|
EntryUploadResult uploadResult = await uploadHandler.CreateReleaseAsync(_entryId.Value, State.EntrySource!, _progress, cancellationToken);
|
||||||
|
if (!uploadResult.IsSuccess)
|
||||||
|
{
|
||||||
|
string? message = uploadResult.Message;
|
||||||
|
if (message != null)
|
||||||
|
message += "\r\n\r\n";
|
||||||
|
else
|
||||||
|
message = "";
|
||||||
|
message += "Your submission has still been saved, you may try to upload a new release";
|
||||||
|
await _windowService.ShowConfirmContentDialog("Failed to upload workshop entry", message, "Close", null);
|
||||||
|
}
|
||||||
|
|
||||||
|
Succeeded = true;
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
// Something went wrong when creating a release :c
|
||||||
|
// We'll keep the workshop entry so that the user can make changes and try again
|
||||||
|
Failed = true;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Finished = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<Guid?> CreateEntry(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
IOperationResult<IAddEntryResult> result = await _workshopClient.AddEntry.ExecuteAsync(new CreateEntryInput
|
IOperationResult<IAddEntryResult> result = await _workshopClient.AddEntry.ExecuteAsync(new CreateEntryInput
|
||||||
{
|
{
|
||||||
@ -100,68 +137,45 @@ public class UploadStepViewModel : SubmissionViewModel
|
|||||||
{
|
{
|
||||||
await _windowService.ShowConfirmContentDialog("Failed to create workshop entry", result.Errors.ToString() ?? "Not even an error message", "Close", null);
|
await _windowService.ShowConfirmContentDialog("Failed to create workshop entry", result.Errors.ToString() ?? "Not even an error message", "Close", null);
|
||||||
State.ChangeScreen<SubmitStepViewModel>();
|
State.ChangeScreen<SubmitStepViewModel>();
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (cancellationToken.IsCancellationRequested)
|
||||||
return;
|
{
|
||||||
|
State.ChangeScreen<SubmitStepViewModel>();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (State.Icon == null)
|
||||||
|
return entryId;
|
||||||
|
|
||||||
// Upload image
|
// Upload image
|
||||||
if (State.Icon != null)
|
|
||||||
await _workshopService.SetEntryIcon(entryId.Value, _progress, State.Icon, cancellationToken);
|
|
||||||
|
|
||||||
// Create the workshop entry
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
IEntryUploadHandler uploadHandler = _entryUploadHandlerFactory.CreateHandler(State.EntryType);
|
ImageUploadResult imageUploadResult = await _workshopService.SetEntryIcon(entryId.Value, _progress, State.Icon, cancellationToken);
|
||||||
EntryUploadResult uploadResult = await uploadHandler.CreateReleaseAsync(entryId.Value, State.EntrySource!, _progress, cancellationToken);
|
if (!imageUploadResult.IsSuccess)
|
||||||
if (!uploadResult.IsSuccess)
|
throw new ArtemisWorkshopException(imageUploadResult.Message);
|
||||||
{
|
|
||||||
string? message = uploadResult.Message;
|
|
||||||
if (message != null)
|
|
||||||
message += "\r\n\r\n";
|
|
||||||
else
|
|
||||||
message = "";
|
|
||||||
message += "Your submission has still been saved, you may try to upload a new release";
|
|
||||||
await _windowService.ShowConfirmContentDialog("Failed to upload workshop entry", message, "Close", null);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_entryId = entryId;
|
|
||||||
Succeeded = true;
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
// Something went wrong when creating a release :c
|
// It's not critical if this fails
|
||||||
// We'll keep the workshop entry so that the user can make changes and try again
|
await _windowService.ShowConfirmContentDialog(
|
||||||
Failed = true;
|
"Failed to upload icon",
|
||||||
}
|
"Your submission will continue, you can try upload a new image afterwards\r\n" + e.Message,
|
||||||
finally
|
"Continue",
|
||||||
{
|
null
|
||||||
Finished = true;
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return entryId;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ExecuteContinue()
|
private async Task ExecuteContinue()
|
||||||
{
|
{
|
||||||
State.Finish();
|
State.Close();
|
||||||
|
|
||||||
if (_entryId == null)
|
if (_entryId != null)
|
||||||
return;
|
await _router.Navigate($"workshop/library/submissions/{_entryId.Value}");
|
||||||
|
|
||||||
switch (State.EntryType)
|
|
||||||
{
|
|
||||||
case EntryType.Layout:
|
|
||||||
await _router.Navigate($"workshop/entries/layouts/{_entryId.Value}");
|
|
||||||
break;
|
|
||||||
case EntryType.Plugin:
|
|
||||||
await _router.Navigate($"workshop/entries/plugins/{_entryId.Value}");
|
|
||||||
break;
|
|
||||||
case EntryType.Profile:
|
|
||||||
await _router.Navigate($"workshop/entries/profiles/{_entryId.Value}");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new ArgumentOutOfRangeException();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -11,7 +11,6 @@ public abstract class SubmissionViewModel : ValidatableViewModelBase
|
|||||||
private bool _showGoBack = true;
|
private bool _showGoBack = true;
|
||||||
private bool _showHeader = true;
|
private bool _showHeader = true;
|
||||||
|
|
||||||
public SubmissionWizardViewModel WizardViewModel { get; set; } = null!;
|
|
||||||
public SubmissionWizardState State { get; set; } = null!;
|
public SubmissionWizardState State { get; set; } = null!;
|
||||||
|
|
||||||
public abstract ReactiveCommand<Unit, Unit> Continue { get; }
|
public abstract ReactiveCommand<Unit, Unit> Continue { get; }
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using Artemis.UI.Screens.Workshop.SubmissionWizard.Steps.Profile;
|
||||||
using Artemis.UI.Shared.Services;
|
using Artemis.UI.Shared.Services;
|
||||||
using Artemis.WebClient.Workshop;
|
using Artemis.WebClient.Workshop;
|
||||||
using DryIoc;
|
using DryIoc;
|
||||||
@ -11,9 +12,9 @@ public class SubmissionWizardState
|
|||||||
{
|
{
|
||||||
private readonly IContainer _container;
|
private readonly IContainer _container;
|
||||||
private readonly IWindowService _windowService;
|
private readonly IWindowService _windowService;
|
||||||
private readonly SubmissionWizardViewModel _wizardViewModel;
|
private readonly IWorkshopWizardViewModel _wizardViewModel;
|
||||||
|
|
||||||
public SubmissionWizardState(SubmissionWizardViewModel wizardViewModel, IContainer container, IWindowService windowService)
|
public SubmissionWizardState(IWorkshopWizardViewModel wizardViewModel, IContainer container, IWindowService windowService)
|
||||||
{
|
{
|
||||||
_wizardViewModel = wizardViewModel;
|
_wizardViewModel = wizardViewModel;
|
||||||
_container = container;
|
_container = container;
|
||||||
@ -21,6 +22,7 @@ public class SubmissionWizardState
|
|||||||
}
|
}
|
||||||
|
|
||||||
public EntryType EntryType { get; set; }
|
public EntryType EntryType { get; set; }
|
||||||
|
public Guid? EntryId { get; set; }
|
||||||
|
|
||||||
public string Name { get; set; } = string.Empty;
|
public string Name { get; set; } = string.Empty;
|
||||||
public Stream? Icon { get; set; }
|
public Stream? Icon { get; set; }
|
||||||
@ -45,13 +47,16 @@ public class SubmissionWizardState
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Finish()
|
public void Close()
|
||||||
{
|
{
|
||||||
_wizardViewModel.Close(true);
|
_wizardViewModel.ShouldClose = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Cancel()
|
public void StartForCurrentEntry()
|
||||||
{
|
{
|
||||||
_wizardViewModel.Close(false);
|
if (EntryType == EntryType.Profile)
|
||||||
|
ChangeScreen<ProfileSelectionStepViewModel>();
|
||||||
|
else
|
||||||
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -18,7 +18,7 @@
|
|||||||
<Grid RowDefinitions="*,*" ColumnDefinitions="Auto,*,Auto" Margin="0 0 0 15">
|
<Grid RowDefinitions="*,*" ColumnDefinitions="Auto,*,Auto" Margin="0 0 0 15">
|
||||||
<ContentControl Grid.Column="0" Grid.RowSpan="2" Width="65" Height="65" VerticalAlignment="Center" Margin="0 0 20 0" Content="{CompiledBinding CurrentUserViewModel}"/>
|
<ContentControl Grid.Column="0" Grid.RowSpan="2" Width="65" Height="65" VerticalAlignment="Center" Margin="0 0 20 0" Content="{CompiledBinding CurrentUserViewModel}"/>
|
||||||
<TextBlock Grid.Row="0" Grid.Column="1" FontSize="36" VerticalAlignment="Bottom" Text="{CompiledBinding CurrentUserViewModel.Name}" IsVisible="{CompiledBinding !CurrentUserViewModel.IsAnonymous}"/>
|
<TextBlock Grid.Row="0" Grid.Column="1" FontSize="36" VerticalAlignment="Bottom" Text="{CompiledBinding CurrentUserViewModel.Name}" IsVisible="{CompiledBinding !CurrentUserViewModel.IsAnonymous}"/>
|
||||||
<TextBlock Grid.Row="0" Grid.Column="1" FontSize="36" VerticalAlignment="Bottom" Text="Anon 🕵️" IsVisible="{CompiledBinding CurrentUserViewModel.IsAnonymous}"/>
|
<TextBlock Grid.Row="0" Grid.Column="1" FontSize="36" VerticalAlignment="Bottom" Text="Not logged in" IsVisible="{CompiledBinding CurrentUserViewModel.IsAnonymous}"/>
|
||||||
|
|
||||||
<StackPanel Grid.Row="0" Grid.Column="2" HorizontalAlignment="Right" VerticalAlignment="Bottom" Orientation="Horizontal">
|
<StackPanel Grid.Row="0" Grid.Column="2" HorizontalAlignment="Right" VerticalAlignment="Bottom" Orientation="Horizontal">
|
||||||
<controls:HyperlinkButton Classes="icon-button" ToolTip.Tip="View Wiki" NavigateUri="https://wiki.artemis-rgb.com?mtm_campaign=artemis&mtm_kwd=workshop-wizard">
|
<controls:HyperlinkButton Classes="icon-button" ToolTip.Tip="View Wiki" NavigateUri="https://wiki.artemis-rgb.com?mtm_campaign=artemis&mtm_kwd=workshop-wizard">
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Reactive.Disposables;
|
using System.Reactive.Disposables;
|
||||||
|
using System.Reactive.Linq;
|
||||||
using Artemis.UI.Shared;
|
using Artemis.UI.Shared;
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
@ -17,6 +18,7 @@ public partial class SubmissionWizardView : ReactiveAppWindow<SubmissionWizardVi
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
this.WhenActivated(d => ViewModel.WhenAnyValue(vm => vm.Screen).Subscribe(Navigate).DisposeWith(d));
|
this.WhenActivated(d => ViewModel.WhenAnyValue(vm => vm.Screen).Subscribe(Navigate).DisposeWith(d));
|
||||||
|
this.WhenActivated(d => ViewModel.WhenAnyValue(vm => vm.ShouldClose).Where(c => c).Subscribe(_ => Close()).DisposeWith(d));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Navigate(SubmissionViewModel viewModel)
|
private void Navigate(SubmissionViewModel viewModel)
|
||||||
|
|||||||
@ -6,16 +6,19 @@ using DryIoc;
|
|||||||
|
|
||||||
namespace Artemis.UI.Screens.Workshop.SubmissionWizard;
|
namespace Artemis.UI.Screens.Workshop.SubmissionWizard;
|
||||||
|
|
||||||
public class SubmissionWizardViewModel : DialogViewModelBase<bool>
|
public class SubmissionWizardViewModel : ActivatableViewModelBase, IWorkshopWizardViewModel
|
||||||
{
|
{
|
||||||
private readonly SubmissionWizardState _state;
|
private readonly SubmissionWizardState _state;
|
||||||
private SubmissionViewModel _screen;
|
private SubmissionViewModel _screen;
|
||||||
|
private bool _shouldClose;
|
||||||
|
|
||||||
public SubmissionWizardViewModel(IContainer container, IWindowService windowService, CurrentUserViewModel currentUserViewModel, WelcomeStepViewModel welcomeStepViewModel)
|
public SubmissionWizardViewModel(IContainer container,
|
||||||
|
IWindowService windowService,
|
||||||
|
CurrentUserViewModel currentUserViewModel,
|
||||||
|
WelcomeStepViewModel welcomeStepViewModel)
|
||||||
{
|
{
|
||||||
_state = new SubmissionWizardState(this, container, windowService);
|
_state = new SubmissionWizardState(this, container, windowService);
|
||||||
_screen = welcomeStepViewModel;
|
_screen = welcomeStepViewModel;
|
||||||
_screen.WizardViewModel = this;
|
|
||||||
_screen.State = _state;
|
_screen.State = _state;
|
||||||
|
|
||||||
WindowService = windowService;
|
WindowService = windowService;
|
||||||
@ -31,9 +34,14 @@ public class SubmissionWizardViewModel : DialogViewModelBase<bool>
|
|||||||
get => _screen;
|
get => _screen;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
value.WizardViewModel = this;
|
|
||||||
value.State = _state;
|
value.State = _state;
|
||||||
RaiseAndSetIfChanged(ref _screen, value);
|
RaiseAndSetIfChanged(ref _screen, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool ShouldClose
|
||||||
|
{
|
||||||
|
get => _shouldClose;
|
||||||
|
set => RaiseAndSetIfChanged(ref _shouldClose, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -44,5 +44,8 @@
|
|||||||
<GraphQL Update="Queries\RemoveEntry.graphql">
|
<GraphQL Update="Queries\RemoveEntry.graphql">
|
||||||
<Generator>MSBuild:GenerateGraphQLCode</Generator>
|
<Generator>MSBuild:GenerateGraphQLCode</Generator>
|
||||||
</GraphQL>
|
</GraphQL>
|
||||||
|
<GraphQL Update="Queries\UpdateEntry.graphql">
|
||||||
|
<Generator>MSBuild:GenerateGraphQLCode</Generator>
|
||||||
|
</GraphQL>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@ -0,0 +1,5 @@
|
|||||||
|
mutation UpdateEntry ($input: UpdateEntryInput!) {
|
||||||
|
updateEntry(input: $input) {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -64,6 +64,24 @@ public class WorkshopService : IWorkshopService
|
|||||||
await _router.Navigate($"workshop/offline/{status.Message}");
|
await _router.Navigate($"workshop/offline/{status.Message}");
|
||||||
return status.IsReachable;
|
return status.IsReachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task NavigateToEntry(Guid entryId, EntryType entryType)
|
||||||
|
{
|
||||||
|
switch (entryType)
|
||||||
|
{
|
||||||
|
case EntryType.Profile:
|
||||||
|
await _router.Navigate($"workshop/entries/profiles/details/{entryId}");
|
||||||
|
break;
|
||||||
|
case EntryType.Layout:
|
||||||
|
await _router.Navigate($"workshop/entries/layouts/details/{entryId}");
|
||||||
|
break;
|
||||||
|
case EntryType.Plugin:
|
||||||
|
await _router.Navigate($"workshop/entries/plugins/details/{entryId}");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(entryType));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IWorkshopService
|
public interface IWorkshopService
|
||||||
@ -71,6 +89,7 @@ public interface IWorkshopService
|
|||||||
Task<ImageUploadResult> SetEntryIcon(Guid entryId, Progress<StreamProgress> progress, Stream icon, CancellationToken cancellationToken);
|
Task<ImageUploadResult> SetEntryIcon(Guid entryId, Progress<StreamProgress> progress, Stream icon, CancellationToken cancellationToken);
|
||||||
Task<WorkshopStatus> GetWorkshopStatus(CancellationToken cancellationToken);
|
Task<WorkshopStatus> GetWorkshopStatus(CancellationToken cancellationToken);
|
||||||
Task<bool> ValidateWorkshopStatus(CancellationToken cancellationToken);
|
Task<bool> ValidateWorkshopStatus(CancellationToken cancellationToken);
|
||||||
|
Task NavigateToEntry(Guid entryId, EntryType entryType);
|
||||||
|
|
||||||
public record WorkshopStatus(bool IsReachable, string Message);
|
public record WorkshopStatus(bool IsReachable, string Message);
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user