mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-12 13:28:33 +00:00
Submission wizard - Added entry specifications step
This commit is contained in:
parent
56abc48ab3
commit
e52faf1c9f
@ -15,6 +15,7 @@
|
||||
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<MergeResourceInclude Source="/Controls/Pagination/PaginationStyles.axaml" />
|
||||
<MergeResourceInclude Source="/Controls/TagsInput/TagsInputStyles.axaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</Styles.Resources>
|
||||
|
||||
@ -39,11 +39,6 @@
|
||||
<Button Classes="title-bar-button">
|
||||
<avalonia:MaterialIcon Kind="WindowMinimize" />
|
||||
</Button>
|
||||
|
||||
<TextBlock Margin="0 5 0 0">ToggleButton.window-button</TextBlock>
|
||||
<ToggleButton Classes="icon-button">
|
||||
<avalonia:MaterialIcon Kind="BlockChain" />
|
||||
</ToggleButton>
|
||||
|
||||
<Button Classes="icon-button">
|
||||
<avalonia:MaterialIcon Kind="Cog" />
|
||||
@ -109,28 +104,4 @@
|
||||
<Style Selector="Button.title-bar-button:pointerover">
|
||||
<Setter Property="Background" Value="Red"></Setter>
|
||||
</Style>
|
||||
|
||||
<Style Selector="ToggleButton:checked:pointerover /template/ Border#BorderElement">
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ToggleButtonBorderBrushCheckedPointerOver}" />
|
||||
</Style>
|
||||
<Style Selector="ToggleButton:checked:pointerover /template/ ContentPresenter#PART_ContentPresenter">
|
||||
<Setter Property="Background" Value="{DynamicResource ToggleButtonBackgroundCheckedPointerOver}" />
|
||||
<Setter Property="TextBlock.Foreground" Value="{DynamicResource ToggleButtonForegroundCheckedPointerOver}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="ToggleButton:checked:pressed /template/ Border#BorderElement">
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ToggleButtonBorderBrushCheckedPressed}" />
|
||||
</Style>
|
||||
<Style Selector="ToggleButton:checked:pressed /template/ ContentPresenter#PART_ContentPresenter">
|
||||
<Setter Property="Background" Value="{DynamicResource ToggleButtonBackgroundCheckedPressed}" />
|
||||
<Setter Property="TextBlock.Foreground" Value="{DynamicResource ToggleButtonForegroundCheckedPressed}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="ToggleButton:checked:disabled /template/ Border#BorderElement">
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource ToggleButtonBorderBrushCheckedDisabled}" />
|
||||
</Style>
|
||||
<Style Selector="ToggleButton:checked:disabled /template/ ContentPresenter#PART_ContentPresenter">
|
||||
<Setter Property="Background" Value="{DynamicResource ToggleButtonBackgroundCheckedDisabled}" />
|
||||
<Setter Property="TextBlock.Foreground" Value="{DynamicResource ToggleButtonForegroundCheckedDisabled}" />
|
||||
</Style>
|
||||
</Styles>
|
||||
35
src/Artemis.UI/Extensions/MaterialIconKindExtensions.cs
Normal file
35
src/Artemis.UI/Extensions/MaterialIconKindExtensions.cs
Normal file
@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using Material.Icons;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Artemis.UI.Extensions;
|
||||
|
||||
public static class MaterialIconKindExtensions
|
||||
{
|
||||
public static Stream EncodeToBitmap(this MaterialIconKind icon, int size, int margin, SKColor color)
|
||||
{
|
||||
string geometrySource = MaterialIconDataProvider.GetData(icon);
|
||||
|
||||
SKBitmap bitmap = new(size, size);
|
||||
using (SKCanvas canvas = new(bitmap))
|
||||
{
|
||||
canvas.Clear(SKColors.Transparent);
|
||||
|
||||
// Parse and render the geometry data using SkiaSharp's SKPath
|
||||
using SKPath path = SKPath.ParseSvgPathData(geometrySource);
|
||||
using SKPaint paint = new() {Color = color, IsAntialias = true,};
|
||||
|
||||
// Calculate scaling and translation to fit the icon in the 100x100 area with 14 pixels margin
|
||||
float scale = Math.Min(size / path.Bounds.Width, size / path.Bounds.Height);
|
||||
path.Transform(SKMatrix.CreateTranslation(path.Bounds.Left * -1, path.Bounds.Top * -1));
|
||||
path.Transform(SKMatrix.CreateScale(scale, scale));
|
||||
canvas.Scale((size - margin * 2) / (float) size, (size - margin * 2) / (float) size, size / 2f, size / 2f);
|
||||
canvas.DrawPath(path, paint);
|
||||
}
|
||||
|
||||
MemoryStream stream = new();
|
||||
bitmap.Encode(stream, SKEncodedImageFormat.Png, 100);
|
||||
return stream;
|
||||
}
|
||||
}
|
||||
@ -3,31 +3,125 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:steps="clr-namespace:Artemis.UI.Screens.Workshop.SubmissionWizard.Steps"
|
||||
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||
xmlns:categories="clr-namespace:Artemis.UI.Screens.Workshop.Categories"
|
||||
xmlns:tagsInput="clr-namespace:Artemis.UI.Shared.TagsInput;assembly=Artemis.UI.Shared"
|
||||
mc:Ignorable="d" d:DesignWidth="970" d:DesignHeight="625"
|
||||
x:Class="Artemis.UI.Screens.Workshop.SubmissionWizard.Steps.EntrySpecificationsStepView"
|
||||
x:DataType="steps:EntrySpecificationsStepViewModel">
|
||||
<StackPanel>
|
||||
<StackPanel.Styles>
|
||||
<Styles>
|
||||
<Style Selector="TextBlock">
|
||||
<Setter Property="TextWrapping" Value="Wrap"></Setter>
|
||||
</Style>
|
||||
</Styles>
|
||||
</StackPanel.Styles>
|
||||
<TextBlock Theme="{StaticResource TitleTextBlockStyle}" TextWrapping="Wrap" Text="{CompiledBinding DisplayName, FallbackValue=Information}"/>
|
||||
<TextBlock TextWrapping="Wrap">
|
||||
Provide some general information on your submission below.
|
||||
</TextBlock>
|
||||
|
||||
<Label Target="Name" Margin="0 15 0 0">Name</Label>
|
||||
<TextBox Name="Name" Text="{CompiledBinding Name}"></TextBox>
|
||||
|
||||
<Label Target="Summary" Margin="0 5 0 0">Summary</Label>
|
||||
<TextBox Name="Summary" Text="{CompiledBinding Summary}"></TextBox>
|
||||
<TextBlock Theme="{StaticResource CaptionTextBlockStyle}">A short summary of your submission's description</TextBlock>
|
||||
|
||||
<Label Target="Description" Margin="0 5 0 0">Description</Label>
|
||||
<TextBox AcceptsReturn="True" Name="Description" Text="{CompiledBinding Description}" Height="250"></TextBox>
|
||||
<TextBlock Theme="{StaticResource CaptionTextBlockStyle}">The main description, Markdown supported. (A better editor planned)</TextBlock>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
<Grid RowDefinitions="Auto,*">
|
||||
<StackPanel Grid.Row="0">
|
||||
<StackPanel.Styles>
|
||||
<Styles>
|
||||
<Style Selector="TextBlock">
|
||||
<Setter Property="TextWrapping" Value="Wrap"></Setter>
|
||||
</Style>
|
||||
</Styles>
|
||||
</StackPanel.Styles>
|
||||
<TextBlock Theme="{StaticResource TitleTextBlockStyle}" TextWrapping="Wrap" Text="{CompiledBinding DisplayName, FallbackValue=Information}" />
|
||||
<TextBlock TextWrapping="Wrap">
|
||||
Provide some general information on your submission below.
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
|
||||
<ScrollViewer Grid.Row="1" Padding="0 0 20 0">
|
||||
<StackPanel>
|
||||
<StackPanel.Styles>
|
||||
<Styles>
|
||||
<Style Selector="TextBlock">
|
||||
<Setter Property="TextWrapping" Value="Wrap"></Setter>
|
||||
</Style>
|
||||
<Style Selector="Label">
|
||||
<Setter Property="Margin" Value="0 8 0 0"></Setter>
|
||||
</Style>
|
||||
</Styles>
|
||||
</StackPanel.Styles>
|
||||
|
||||
<Grid ColumnDefinitions="103,*">
|
||||
<StackPanel Grid.Column="0" Width="95">
|
||||
<DockPanel>
|
||||
<Button DockPanel.Dock="Right"
|
||||
VerticalAlignment="Bottom"
|
||||
Classes="icon-button"
|
||||
Command="{CompiledBinding ClearIcon}"
|
||||
IsVisible="{CompiledBinding IconBitmap, Converter={x:Static ObjectConverters.IsNotNull}}"
|
||||
Width="22"
|
||||
Height="22">
|
||||
<avalonia:MaterialIcon Kind="Trash"></avalonia:MaterialIcon>
|
||||
</Button>
|
||||
<Label DockPanel.Dock="Left" Target="Name" Margin="0 15 0 0">Icon</Label>
|
||||
</DockPanel>
|
||||
|
||||
<Button Width="95"
|
||||
Height="95"
|
||||
Command="{CompiledBinding SelectIcon}"
|
||||
IsVisible="{CompiledBinding IconBitmap, Converter={x:Static ObjectConverters.IsNull}}">
|
||||
<avalonia:MaterialIcon Kind="FolderOpen"
|
||||
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
|
||||
Width="30"
|
||||
Height="30" />
|
||||
</Button>
|
||||
<Border IsVisible="{CompiledBinding IconBitmap, Converter={x:Static ObjectConverters.IsNotNull}}"
|
||||
ClipToBounds="True"
|
||||
CornerRadius="12"
|
||||
Background="{StaticResource ControlStrokeColorOnAccentDefault}"
|
||||
VerticalAlignment="Center"
|
||||
Width="95"
|
||||
Height="95">
|
||||
<Image Source="{CompiledBinding IconBitmap}" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"></Image>
|
||||
</Border>
|
||||
<TextBlock Foreground="{DynamicResource SystemFillColorCriticalBrush}" Margin="2 0"
|
||||
IsVisible="{CompiledBinding !IconValid}"
|
||||
TextWrapping="Wrap">
|
||||
Icon required
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Column="1">
|
||||
<Label Target="Name" Margin="0 15 0 0">Name</Label>
|
||||
<TextBox Name="Name" Text="{CompiledBinding Name}"></TextBox>
|
||||
|
||||
<Label Target="Summary" Margin="0 5 0 0">Summary</Label>
|
||||
<TextBox Name="Summary" Text="{CompiledBinding Summary}"></TextBox>
|
||||
</StackPanel>
|
||||
|
||||
</Grid>
|
||||
|
||||
|
||||
<!-- <TextBlock Theme="{StaticResource CaptionTextBlockStyle}">A short summary of your submission's description</TextBlock> -->
|
||||
|
||||
<Label Margin="0 28 0 0">Categories</Label>
|
||||
<ItemsControl ItemsSource="{CompiledBinding Categories}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<WrapPanel />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate DataType="categories:CategoryViewModel">
|
||||
<ToggleButton IsChecked="{CompiledBinding IsSelected}" Margin="0 0 5 5">
|
||||
<StackPanel Orientation="Horizontal" Spacing="5">
|
||||
<avalonia:MaterialIcon Kind="{CompiledBinding Icon}" />
|
||||
<TextBlock Text="{CompiledBinding Name}" VerticalAlignment="Center" />
|
||||
</StackPanel>
|
||||
</ToggleButton>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
<TextBlock Foreground="{DynamicResource SystemFillColorCriticalBrush}" Margin="2 0" IsVisible="{CompiledBinding !CategoriesValid}">
|
||||
At least one category is required
|
||||
</TextBlock>
|
||||
<!-- <TextBlock Theme="{StaticResource CaptionTextBlockStyle}" Margin="0 -5 0 0">Pick one or more categories that suit your submission</TextBlock> -->
|
||||
|
||||
<Label>Tags</Label>
|
||||
<tagsInput:TagsInput Tags="{CompiledBinding Tags}" />
|
||||
<!-- <TextBlock Theme="{StaticResource CaptionTextBlockStyle}" Margin="0 -5 0 0">Tags are used by the search engine, use keywords that match your submission</TextBlock> -->
|
||||
|
||||
<Label Target="Description" Margin="0 28 0 0">Description</Label>
|
||||
<TextBox AcceptsReturn="True" Name="Description" Text="{CompiledBinding Description}" Height="250"></TextBox>
|
||||
<TextBlock Theme="{StaticResource CaptionTextBlockStyle}">Markdown supported, a better editor planned</TextBlock>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
|
||||
</Grid>
|
||||
|
||||
</UserControl>
|
||||
@ -1,37 +1,103 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reactive;
|
||||
using System.Reactive.Disposables;
|
||||
using System.Reactive.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Artemis.UI.Extensions;
|
||||
using Artemis.UI.Screens.Workshop.Categories;
|
||||
using Artemis.UI.Screens.Workshop.SubmissionWizard.Steps.Profile;
|
||||
using Artemis.UI.Shared.Services;
|
||||
using Artemis.WebClient.Workshop;
|
||||
using Artemis.WebClient.Workshop.Extensions;
|
||||
using Avalonia.Threading;
|
||||
using DynamicData;
|
||||
using DynamicData.Aggregation;
|
||||
using DynamicData.Binding;
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Validation.Extensions;
|
||||
using ReactiveUI.Validation.Helpers;
|
||||
using StrawberryShake;
|
||||
using Bitmap = Avalonia.Media.Imaging.Bitmap;
|
||||
|
||||
namespace Artemis.UI.Screens.Workshop.SubmissionWizard.Steps;
|
||||
|
||||
public class EntrySpecificationsStepViewModel : SubmissionViewModel
|
||||
{
|
||||
private readonly IWindowService _windowService;
|
||||
private ObservableAsPropertyHelper<bool>? _categoriesValid;
|
||||
private ObservableAsPropertyHelper<bool>? _iconValid;
|
||||
private string _description = string.Empty;
|
||||
private Bitmap? _iconBitmap;
|
||||
private bool _isDirty;
|
||||
private string _name = string.Empty;
|
||||
private string _summary = string.Empty;
|
||||
private string _description = string.Empty;
|
||||
|
||||
public EntrySpecificationsStepViewModel()
|
||||
public EntrySpecificationsStepViewModel(IWorkshopClient workshopClient, IWindowService windowService)
|
||||
{
|
||||
_windowService = windowService;
|
||||
GoBack = ReactiveCommand.Create(ExecuteGoBack);
|
||||
Continue = ReactiveCommand.Create(ExecuteContinue, ValidationContext.Valid);
|
||||
|
||||
this.WhenActivated((CompositeDisposable _) =>
|
||||
SelectIcon = ReactiveCommand.CreateFromTask(ExecuteSelectIcon);
|
||||
ClearIcon = ReactiveCommand.Create(ExecuteClearIcon);
|
||||
|
||||
workshopClient.GetCategories
|
||||
.Watch(ExecutionStrategy.CacheFirst)
|
||||
.SelectOperationResult(c => c.Categories)
|
||||
.ToObservableChangeSet(c => c.Id)
|
||||
.Transform(c => new CategoryViewModel(c))
|
||||
.Bind(out ReadOnlyObservableCollection<CategoryViewModel> categoryViewModels)
|
||||
.Subscribe();
|
||||
Categories = categoryViewModels;
|
||||
|
||||
this.WhenActivated(d =>
|
||||
{
|
||||
this.ClearValidationRules();
|
||||
|
||||
DisplayName = $"{State.EntryType} Information";
|
||||
|
||||
// Basic fields
|
||||
Name = State.Name;
|
||||
Summary = State.Summary;
|
||||
Description = State.Description;
|
||||
|
||||
// Categories
|
||||
foreach (CategoryViewModel categoryViewModel in Categories)
|
||||
categoryViewModel.IsSelected = State.Categories.Contains(categoryViewModel.Id);
|
||||
|
||||
// Tags
|
||||
Tags.Clear();
|
||||
Tags.AddRange(State.Tags);
|
||||
|
||||
// Icon
|
||||
if (State.Icon != null)
|
||||
{
|
||||
State.Icon.Seek(0, SeekOrigin.Begin);
|
||||
IconBitmap = BitmapExtensions.LoadAndResize(State.Icon, 128);
|
||||
}
|
||||
|
||||
IsDirty = false;
|
||||
this.ClearValidationRules();
|
||||
|
||||
Disposable.Create(() =>
|
||||
{
|
||||
IconBitmap?.Dispose();
|
||||
IconBitmap = null;
|
||||
}).DisposeWith(d);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public override ReactiveCommand<Unit, Unit> Continue { get; }
|
||||
public override ReactiveCommand<Unit, Unit> GoBack { get; }
|
||||
public ReactiveCommand<Unit, Unit> SelectIcon { get; }
|
||||
public ReactiveCommand<Unit, Unit> ClearIcon { get; }
|
||||
|
||||
public ReadOnlyObservableCollection<CategoryViewModel> Categories { get; }
|
||||
public ObservableCollection<string> Tags { get; } = new();
|
||||
public bool CategoriesValid => _categoriesValid?.Value ?? true;
|
||||
public bool IconValid => _iconValid?.Value ?? true;
|
||||
|
||||
public string Name
|
||||
{
|
||||
@ -51,6 +117,18 @@ public class EntrySpecificationsStepViewModel : SubmissionViewModel
|
||||
set => RaiseAndSetIfChanged(ref _description, value);
|
||||
}
|
||||
|
||||
public bool IsDirty
|
||||
{
|
||||
get => _isDirty;
|
||||
set => RaiseAndSetIfChanged(ref _isDirty, value);
|
||||
}
|
||||
|
||||
public Bitmap? IconBitmap
|
||||
{
|
||||
get => _iconBitmap;
|
||||
set => RaiseAndSetIfChanged(ref _iconBitmap, value);
|
||||
}
|
||||
|
||||
private void ExecuteGoBack()
|
||||
{
|
||||
switch (State.EntryType)
|
||||
@ -66,18 +144,77 @@ public class EntrySpecificationsStepViewModel : SubmissionViewModel
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void ExecuteContinue()
|
||||
{
|
||||
this.ValidationRule(vm => vm.Name, s => !string.IsNullOrWhiteSpace(s), "Name cannot be empty.");
|
||||
this.ValidationRule(vm => vm.Summary, s => !string.IsNullOrWhiteSpace(s), "Summary cannot be empty.");
|
||||
this.ValidationRule(vm => vm.Description, s => !string.IsNullOrWhiteSpace(s), "Description cannot be empty.");
|
||||
|
||||
if (!ValidationContext.IsValid)
|
||||
if (!IsDirty)
|
||||
{
|
||||
SetupDataValidation();
|
||||
IsDirty = true;
|
||||
|
||||
// The ValidationContext seems to update asynchronously, so stop and schedule a retry
|
||||
Dispatcher.UIThread.Post(ExecuteContinue);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
if (!ValidationContext.GetIsValid())
|
||||
return;
|
||||
|
||||
State.Name = Name;
|
||||
State.Summary = Summary;
|
||||
State.Description = Description;
|
||||
State.Categories = Categories.Where(c => c.IsSelected).Select(c => c.Id).ToList();
|
||||
State.Tags = new List<string>(Tags);
|
||||
|
||||
State.Icon?.Dispose();
|
||||
if (IconBitmap != null)
|
||||
{
|
||||
State.Icon = new MemoryStream();
|
||||
IconBitmap.Save(State.Icon);
|
||||
}
|
||||
else
|
||||
{
|
||||
State.Icon = null;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ExecuteSelectIcon()
|
||||
{
|
||||
string[]? result = await _windowService.CreateOpenFileDialog()
|
||||
.HavingFilter(f => f.WithExtension("png").WithExtension("jpg").WithExtension("bmp").WithName("Bitmap image"))
|
||||
.ShowAsync();
|
||||
|
||||
if (result == null)
|
||||
return;
|
||||
|
||||
IconBitmap?.Dispose();
|
||||
IconBitmap = BitmapExtensions.LoadAndResize(result[0], 128);
|
||||
}
|
||||
|
||||
private void ExecuteClearIcon()
|
||||
{
|
||||
IconBitmap?.Dispose();
|
||||
IconBitmap = null;
|
||||
}
|
||||
|
||||
private void SetupDataValidation()
|
||||
{
|
||||
// Hopefully this can be avoided in the future
|
||||
// https://github.com/reactiveui/ReactiveUI.Validation/discussions/558
|
||||
this.ValidationRule(vm => vm.Name, s => !string.IsNullOrWhiteSpace(s), "Name is required");
|
||||
this.ValidationRule(vm => vm.Summary, s => !string.IsNullOrWhiteSpace(s), "Summary is required");
|
||||
this.ValidationRule(vm => vm.Description, s => !string.IsNullOrWhiteSpace(s), "Description is required");
|
||||
|
||||
// These don't use inputs that support validation messages, do so manually
|
||||
ValidationHelper iconRule = this.ValidationRule(vm => vm.IconBitmap, s => s != null, "Icon required");
|
||||
ValidationHelper categoriesRule = this.ValidationRule(vm => vm.Categories, Categories.ToObservableChangeSet()
|
||||
.AutoRefresh(c => c.IsSelected)
|
||||
.Filter(c => c.IsSelected)
|
||||
.IsEmpty()
|
||||
.CombineLatest(this.WhenAnyValue(vm => vm.IsDirty), (empty, dirty) => !dirty || !empty),
|
||||
"At least one category must be selected"
|
||||
);
|
||||
_iconValid = iconRule.ValidationChanged.Select(c => c.IsValid).ToProperty(this, vm => vm.IconValid);
|
||||
_categoriesValid = categoriesRule.ValidationChanged.Select(c => c.IsValid).ToProperty(this, vm => vm.CategoriesValid);
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reactive;
|
||||
using System.Reactive.Disposables;
|
||||
@ -8,8 +9,19 @@ using Artemis.Core;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.Storage.Entities.Profile;
|
||||
using Artemis.Storage.Repositories.Interfaces;
|
||||
using Artemis.UI.Extensions;
|
||||
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.Avalonia;
|
||||
using ReactiveUI;
|
||||
using SkiaSharp;
|
||||
using Path = Avalonia.Controls.Shapes.Path;
|
||||
|
||||
namespace Artemis.UI.Screens.Workshop.SubmissionWizard.Steps.Profile;
|
||||
|
||||
@ -23,12 +35,12 @@ public class ProfileSelectionStepViewModel : SubmissionViewModel
|
||||
public ProfileSelectionStepViewModel(IProfileService profileService, ProfilePreviewViewModel profilePreviewViewModel)
|
||||
{
|
||||
_profileService = profileService;
|
||||
|
||||
|
||||
// Use copies of the profiles, the originals are used by the core and could be disposed
|
||||
Profiles = new ObservableCollection<ProfileConfiguration>(_profileService.ProfileConfigurations.Select(_profileService.CloneProfileConfiguration));
|
||||
foreach (ProfileConfiguration profileConfiguration in Profiles)
|
||||
_profileService.LoadProfileConfigurationIcon(profileConfiguration);
|
||||
|
||||
|
||||
ProfilePreview = profilePreviewViewModel;
|
||||
|
||||
GoBack = ReactiveCommand.Create(() => State.ChangeScreen<EntryTypeViewModel>());
|
||||
@ -45,7 +57,7 @@ public class ProfileSelectionStepViewModel : SubmissionViewModel
|
||||
private void Update(ProfileConfiguration? profileConfiguration)
|
||||
{
|
||||
ProfilePreview.ProfileConfiguration = null;
|
||||
|
||||
|
||||
foreach (ProfileConfiguration configuration in Profiles)
|
||||
{
|
||||
if (configuration == profileConfiguration)
|
||||
@ -81,6 +93,10 @@ public class ProfileSelectionStepViewModel : SubmissionViewModel
|
||||
State.Name = SelectedProfile.Name;
|
||||
State.Icon = SelectedProfile.Icon.GetIconStream();
|
||||
|
||||
// Render the material icon of the profile
|
||||
if (State.Icon == null && SelectedProfile.Icon.IconName != null)
|
||||
State.Icon = Enum.Parse<MaterialIconKind>(SelectedProfile.Icon.IconName).EncodeToBitmap(128, 14, SKColors.White);
|
||||
|
||||
State.ChangeScreen<ProfileAdaptionHintsStepViewModel>();
|
||||
}
|
||||
}
|
||||
@ -28,7 +28,7 @@ public class SubmissionWizardState
|
||||
public string Description { get; set; } = string.Empty;
|
||||
|
||||
public List<int> Categories { get; set; } = new();
|
||||
public List<int> Tags { get; set; } = new();
|
||||
public List<string> Tags { get; set; } = new();
|
||||
public List<Stream> Images { get; set; } = new();
|
||||
|
||||
public object? EntrySource { get; set; }
|
||||
|
||||
@ -2,6 +2,6 @@ namespace Artemis.WebClient.Workshop;
|
||||
|
||||
public static class WorkshopConstants
|
||||
{
|
||||
public const string AUTHORITY_URL = "https://localhost:5001";
|
||||
public const string WORKSHOP_URL = "https://localhost:7281";
|
||||
public const string AUTHORITY_URL = "https://identity.artemis-rgb.com";
|
||||
public const string WORKSHOP_URL = "https://workshop.artemis-rgb.com";
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user