mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
UI - Tweaked monospace font sizing
This commit is contained in:
parent
2ee170b803
commit
fcde1d4ecc
@ -67,6 +67,7 @@
|
|||||||
<TextBlock Grid.Column="1"
|
<TextBlock Grid.Column="1"
|
||||||
Text="{CompiledBinding DisplayValue}"
|
Text="{CompiledBinding DisplayValue}"
|
||||||
FontFamily="{StaticResource RobotoMono}"
|
FontFamily="{StaticResource RobotoMono}"
|
||||||
|
FontSize="13"
|
||||||
HorizontalAlignment="Right"
|
HorizontalAlignment="Right"
|
||||||
Margin="0 0 10 0" />
|
Margin="0 0 10 0" />
|
||||||
</Grid>
|
</Grid>
|
||||||
@ -81,7 +82,7 @@
|
|||||||
IsVisible="{CompiledBinding IsEventPicker, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type dataModelPicker:DataModelPicker}}}"/>
|
IsVisible="{CompiledBinding IsEventPicker, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type dataModelPicker:DataModelPicker}}}"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
<ContentControl Grid.Column="1" Content="{CompiledBinding DisplayViewModel}" FontFamily="{StaticResource RobotoMono}" Margin="0 0 10 0" />
|
<ContentControl Grid.Column="1" Content="{CompiledBinding DisplayViewModel}" FontFamily="{StaticResource RobotoMono}" FontSize="13" Margin="0 0 10 0" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</TreeDataTemplate>
|
</TreeDataTemplate>
|
||||||
|
|
||||||
@ -91,6 +92,7 @@
|
|||||||
<TextBlock Grid.Column="1"
|
<TextBlock Grid.Column="1"
|
||||||
Text="{CompiledBinding CountDisplay, Mode=OneWay}"
|
Text="{CompiledBinding CountDisplay, Mode=OneWay}"
|
||||||
FontFamily="{StaticResource RobotoMono}"
|
FontFamily="{StaticResource RobotoMono}"
|
||||||
|
FontSize="13"
|
||||||
HorizontalAlignment="Right"
|
HorizontalAlignment="Right"
|
||||||
Margin="0 0 10 0" />
|
Margin="0 0 10 0" />
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@ -52,8 +52,8 @@
|
|||||||
<TextBlock Grid.Column="1" Text="{CompiledBinding PropertyDescription.Name}" ToolTip.Tip="{CompiledBinding PropertyDescription.Description}" />
|
<TextBlock Grid.Column="1" Text="{CompiledBinding PropertyDescription.Name}" ToolTip.Tip="{CompiledBinding PropertyDescription.Description}" />
|
||||||
<TextBlock Grid.Column="2"
|
<TextBlock Grid.Column="2"
|
||||||
Text="{CompiledBinding DisplayValue}"
|
Text="{CompiledBinding DisplayValue}"
|
||||||
FontSize="13"
|
|
||||||
FontFamily="{StaticResource RobotoMono}"
|
FontFamily="{StaticResource RobotoMono}"
|
||||||
|
FontSize="13"
|
||||||
HorizontalAlignment="Right" />
|
HorizontalAlignment="Right" />
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
|
|||||||
@ -10,8 +10,8 @@
|
|||||||
<SelectableTextBlock
|
<SelectableTextBlock
|
||||||
Inlines="{CompiledBinding Lines}"
|
Inlines="{CompiledBinding Lines}"
|
||||||
FontFamily="{StaticResource RobotoMono}"
|
FontFamily="{StaticResource RobotoMono}"
|
||||||
|
FontSize="12"
|
||||||
SizeChanged="Control_OnSizeChanged"
|
SizeChanged="Control_OnSizeChanged"
|
||||||
SelectionBrush="{StaticResource TextControlSelectionHighlightColor}"
|
SelectionBrush="{StaticResource TextControlSelectionHighlightColor}"/>
|
||||||
/>
|
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
@ -20,6 +20,7 @@
|
|||||||
<SelectableTextBlock
|
<SelectableTextBlock
|
||||||
Inlines="{CompiledBinding Lines}"
|
Inlines="{CompiledBinding Lines}"
|
||||||
FontFamily="{StaticResource RobotoMono}"
|
FontFamily="{StaticResource RobotoMono}"
|
||||||
|
FontSize="12"
|
||||||
SizeChanged="Control_OnSizeChanged"
|
SizeChanged="Control_OnSizeChanged"
|
||||||
SelectionBrush="{StaticResource TextControlSelectionHighlightColor}" />
|
SelectionBrush="{StaticResource TextControlSelectionHighlightColor}" />
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
|
|||||||
@ -41,7 +41,8 @@
|
|||||||
Text="{CompiledBinding Converter={StaticResource SKColorToStringConverter}, Mode=OneWay}"
|
Text="{CompiledBinding Converter={StaticResource SKColorToStringConverter}, Mode=OneWay}"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
FontFamily="{StaticResource RobotoMono}" />
|
FontFamily="{StaticResource RobotoMono}"
|
||||||
|
FontSize="13"/>
|
||||||
<Border Margin="5 0 0 0"
|
<Border Margin="5 0 0 0"
|
||||||
VerticalAlignment="Bottom"
|
VerticalAlignment="Bottom"
|
||||||
HorizontalAlignment="Right"
|
HorizontalAlignment="Right"
|
||||||
@ -61,16 +62,16 @@
|
|||||||
</StackPanel>
|
</StackPanel>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
<DataTemplate DataType="core:ColorGradient">
|
<DataTemplate DataType="core:ColorGradient">
|
||||||
<TextBlock Text="Color gradient" FontFamily="{StaticResource RobotoMono}" />
|
<TextBlock Text="Color gradient" FontFamily="{StaticResource RobotoMono}" FontSize="13"/>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
<DataTemplate DataType="core:Numeric">
|
<DataTemplate DataType="core:Numeric">
|
||||||
<TextBlock Text="{CompiledBinding Mode=OneWay}" FontFamily="{StaticResource RobotoMono}" />
|
<TextBlock Text="{CompiledBinding Mode=OneWay}" FontFamily="{StaticResource RobotoMono}" FontSize="13"/>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
<DataTemplate DataType="collections:IList">
|
<DataTemplate DataType="collections:IList">
|
||||||
<TextBlock Text="{CompiledBinding Count, StringFormat='List - {0} item(s)', Mode=OneWay}" FontFamily="{StaticResource RobotoMono}" />
|
<TextBlock Text="{CompiledBinding Count, StringFormat='List - {0} item(s)', Mode=OneWay}" FontFamily="{StaticResource RobotoMono}" FontSize="13"/>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
<DataTemplate DataType="system:Object">
|
<DataTemplate DataType="system:Object">
|
||||||
<TextBlock Text="{CompiledBinding Mode=OneWay}" FontFamily="{StaticResource RobotoMono}" />
|
<TextBlock Text="{CompiledBinding Mode=OneWay}" FontFamily="{StaticResource RobotoMono}" FontSize="13"/>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ContentControl.DataTemplates>
|
</ContentControl.DataTemplates>
|
||||||
</ContentControl>
|
</ContentControl>
|
||||||
|
|||||||
@ -12,7 +12,7 @@
|
|||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="800"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="800"
|
||||||
x:Class="Artemis.UI.Screens.Workshop.Entries.EntrySpecificationsView"
|
x:Class="Artemis.UI.Screens.Workshop.Entries.EntrySpecificationsView"
|
||||||
x:DataType="entries:EntrySpecificationsViewModel">
|
x:DataType="entries:EntrySpecificationsViewModel">
|
||||||
<Grid RowDefinitions="Auto,*,Auto">
|
<Grid RowDefinitions="Auto,Auto,*,Auto">
|
||||||
<StackPanel>
|
<StackPanel>
|
||||||
<StackPanel.Styles>
|
<StackPanel.Styles>
|
||||||
<Styles>
|
<Styles>
|
||||||
@ -25,8 +25,8 @@
|
|||||||
</Styles>
|
</Styles>
|
||||||
</StackPanel.Styles>
|
</StackPanel.Styles>
|
||||||
|
|
||||||
<Grid ColumnDefinitions="103,*">
|
<Grid ColumnDefinitions="105,*">
|
||||||
<StackPanel Grid.Column="0" Width="95">
|
<StackPanel Grid.Column="0" Width="95" HorizontalAlignment="Left">
|
||||||
<Label Target="Name" Margin="0">Icon</Label>
|
<Label Target="Name" Margin="0">Icon</Label>
|
||||||
<Button Width="95"
|
<Button Width="95"
|
||||||
Height="95"
|
Height="95"
|
||||||
@ -92,12 +92,22 @@
|
|||||||
|
|
||||||
<Label>Tags</Label>
|
<Label>Tags</Label>
|
||||||
<tagsInput:TagsInput Tags="{CompiledBinding Tags}" />
|
<tagsInput:TagsInput Tags="{CompiledBinding Tags}" />
|
||||||
|
|
||||||
<Label Target="DescriptionEditor" Margin="0 28 0 0">Description</Label>
|
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
|
<Grid Row="1" ColumnDefinitions="Auto,*">
|
||||||
|
<Label Grid.Column="0" Target="DescriptionEditor" Margin="0 28 0 0">Description</Label>
|
||||||
|
|
||||||
|
<StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Right">
|
||||||
|
<CheckBox Name="SynchronizedScrolling" IsChecked="True" VerticalAlignment="Bottom">Synchronized scrolling</CheckBox>
|
||||||
|
<controls:HyperlinkButton
|
||||||
|
Margin="0 0 0 -20"
|
||||||
|
Content="Markdown supported"
|
||||||
|
NavigateUri="https://wiki.artemis-rgb.com/guides/user/markdown?mtm_campaign=artemis&mtm_kwd=markdown-editor"
|
||||||
|
HorizontalAlignment="Right"/>
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Grid Grid.Row="2" ColumnDefinitions="*,Auto,*">
|
||||||
<Grid Grid.Row="1" ColumnDefinitions="*,Auto,*">
|
|
||||||
<Border Grid.Column="0" BorderThickness="1"
|
<Border Grid.Column="0" BorderThickness="1"
|
||||||
BorderBrush="{DynamicResource TextControlBorderBrush}"
|
BorderBrush="{DynamicResource TextControlBorderBrush}"
|
||||||
CornerRadius="{DynamicResource ControlCornerRadius}"
|
CornerRadius="{DynamicResource ControlCornerRadius}"
|
||||||
@ -105,6 +115,7 @@
|
|||||||
Padding="{DynamicResource TextControlThemePadding}">
|
Padding="{DynamicResource TextControlThemePadding}">
|
||||||
<avaloniaEdit:TextEditor
|
<avaloniaEdit:TextEditor
|
||||||
FontFamily="{StaticResource RobotoMono}"
|
FontFamily="{StaticResource RobotoMono}"
|
||||||
|
FontSize="13"
|
||||||
Name="DescriptionEditor"
|
Name="DescriptionEditor"
|
||||||
Document="{CompiledBinding MarkdownDocument}"
|
Document="{CompiledBinding MarkdownDocument}"
|
||||||
WordWrap="True" />
|
WordWrap="True" />
|
||||||
@ -123,17 +134,12 @@
|
|||||||
</mdxaml:MarkdownScrollViewer>
|
</mdxaml:MarkdownScrollViewer>
|
||||||
</Border>
|
</Border>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
|
<TextBlock Grid.Row="3"
|
||||||
<StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Right">
|
Foreground="{DynamicResource SystemFillColorCriticalBrush}"
|
||||||
<CheckBox Name="SynchronizedScrolling" IsChecked="True" VerticalAlignment="Bottom">Synchronized scrolling</CheckBox>
|
Margin="2 8 0 0"
|
||||||
<controls:HyperlinkButton
|
IsVisible="{CompiledBinding !DescriptionValid}">
|
||||||
Margin="0 5 0 0"
|
A description is required
|
||||||
Content="Learn more about Markdown on the wiki"
|
</TextBlock>
|
||||||
NavigateUri="https://wiki.artemis-rgb.com/guides/user/markdown?mtm_campaign=artemis&mtm_kwd=markdown-editor"
|
|
||||||
HorizontalAlignment="Right"
|
|
||||||
VerticalAlignment="Top" />
|
|
||||||
</StackPanel>
|
|
||||||
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
@ -11,6 +11,7 @@ using Artemis.UI.Screens.Workshop.Categories;
|
|||||||
using Artemis.UI.Shared;
|
using Artemis.UI.Shared;
|
||||||
using Artemis.UI.Shared.Services;
|
using Artemis.UI.Shared.Services;
|
||||||
using Artemis.WebClient.Workshop;
|
using Artemis.WebClient.Workshop;
|
||||||
|
using Avalonia.Media.Imaging;
|
||||||
using AvaloniaEdit.Document;
|
using AvaloniaEdit.Document;
|
||||||
using DynamicData;
|
using DynamicData;
|
||||||
using DynamicData.Aggregation;
|
using DynamicData.Aggregation;
|
||||||
@ -19,32 +20,55 @@ using ReactiveUI;
|
|||||||
using ReactiveUI.Validation.Extensions;
|
using ReactiveUI.Validation.Extensions;
|
||||||
using ReactiveUI.Validation.Helpers;
|
using ReactiveUI.Validation.Helpers;
|
||||||
using StrawberryShake;
|
using StrawberryShake;
|
||||||
using Bitmap = Avalonia.Media.Imaging.Bitmap;
|
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.Workshop.Entries;
|
namespace Artemis.UI.Screens.Workshop.Entries;
|
||||||
|
|
||||||
public class EntrySpecificationsViewModel : ValidatableViewModelBase
|
public class EntrySpecificationsViewModel : ValidatableViewModelBase
|
||||||
{
|
{
|
||||||
|
private readonly ObservableAsPropertyHelper<bool> _categoriesValid;
|
||||||
|
private readonly ObservableAsPropertyHelper<bool> _iconValid;
|
||||||
|
private readonly ObservableAsPropertyHelper<bool> _descriptionValid;
|
||||||
|
private readonly IWorkshopClient _workshopClient;
|
||||||
private readonly IWindowService _windowService;
|
private readonly IWindowService _windowService;
|
||||||
private ObservableAsPropertyHelper<bool>? _categoriesValid;
|
|
||||||
private ObservableAsPropertyHelper<bool>? _iconValid;
|
|
||||||
private string _description = string.Empty;
|
private string _description = string.Empty;
|
||||||
private string _name = string.Empty;
|
|
||||||
private string _summary = string.Empty;
|
|
||||||
private Bitmap? _iconBitmap;
|
private Bitmap? _iconBitmap;
|
||||||
private TextDocument? _markdownDocument;
|
private TextDocument? _markdownDocument;
|
||||||
|
private string _name = string.Empty;
|
||||||
|
private string _summary = string.Empty;
|
||||||
|
private bool _iconChanged;
|
||||||
|
|
||||||
public EntrySpecificationsViewModel(IWorkshopClient workshopClient, IWindowService windowService)
|
public EntrySpecificationsViewModel(IWorkshopClient workshopClient, IWindowService windowService)
|
||||||
{
|
{
|
||||||
|
_workshopClient = workshopClient;
|
||||||
_windowService = windowService;
|
_windowService = windowService;
|
||||||
SelectIcon = ReactiveCommand.CreateFromTask(ExecuteSelectIcon);
|
SelectIcon = ReactiveCommand.CreateFromTask(ExecuteSelectIcon);
|
||||||
|
|
||||||
|
Categories.ToObservableChangeSet()
|
||||||
|
.AutoRefresh(c => c.IsSelected)
|
||||||
|
.Filter(c => c.IsSelected)
|
||||||
|
.Transform(c => c.Id)
|
||||||
|
.Bind(out ReadOnlyObservableCollection<int> selectedCategories)
|
||||||
|
.Subscribe();
|
||||||
|
SelectedCategories = selectedCategories;
|
||||||
|
|
||||||
this.WhenActivated(d =>
|
this.ValidationRule(vm => vm.Name, s => !string.IsNullOrWhiteSpace(s), "Name is required");
|
||||||
|
this.ValidationRule(vm => vm.Summary, s => !string.IsNullOrWhiteSpace(s), "Summary is required");
|
||||||
|
ValidationHelper descriptionRule = 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).IsNotEmpty(),
|
||||||
|
"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);
|
||||||
|
_descriptionValid = descriptionRule.ValidationChanged.Select(c => c.IsValid).ToProperty(this, vm => vm.DescriptionValid);
|
||||||
|
|
||||||
|
this.WhenActivatedAsync(async d =>
|
||||||
{
|
{
|
||||||
// Load categories
|
// Load categories
|
||||||
Observable.FromAsync(workshopClient.GetCategories.ExecuteAsync).Subscribe(PopulateCategories).DisposeWith(d);
|
await PopulateCategories();
|
||||||
|
|
||||||
this.ClearValidationRules();
|
|
||||||
|
|
||||||
MarkdownDocument = new TextDocument(new StringTextSource(Description));
|
MarkdownDocument = new TextDocument(new StringTextSource(Description));
|
||||||
MarkdownDocument.TextChanged += MarkdownDocumentOnTextChanged;
|
MarkdownDocument.TextChanged += MarkdownDocumentOnTextChanged;
|
||||||
@ -57,17 +81,15 @@ public class EntrySpecificationsViewModel : ValidatableViewModelBase
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MarkdownDocumentOnTextChanged(object? sender, EventArgs e)
|
|
||||||
{
|
|
||||||
Description = MarkdownDocument?.Text ?? string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ReactiveCommand<Unit, Unit> SelectIcon { get; }
|
public ReactiveCommand<Unit, Unit> SelectIcon { get; }
|
||||||
|
|
||||||
public ObservableCollection<CategoryViewModel> Categories { get; } = new();
|
public ObservableCollection<CategoryViewModel> Categories { get; } = new();
|
||||||
public ObservableCollection<string> Tags { get; } = new();
|
public ObservableCollection<string> Tags { get; } = new();
|
||||||
public bool CategoriesValid => _categoriesValid?.Value ?? true;
|
public ReadOnlyObservableCollection<int> SelectedCategories { get; }
|
||||||
public bool IconValid => _iconValid?.Value ?? true;
|
|
||||||
|
public bool CategoriesValid => _categoriesValid.Value ;
|
||||||
|
public bool IconValid => _iconValid.Value;
|
||||||
|
public bool DescriptionValid => _descriptionValid.Value;
|
||||||
|
|
||||||
public string Name
|
public string Name
|
||||||
{
|
{
|
||||||
@ -99,23 +121,17 @@ public class EntrySpecificationsViewModel : ValidatableViewModelBase
|
|||||||
set => RaiseAndSetIfChanged(ref _markdownDocument, value);
|
set => RaiseAndSetIfChanged(ref _markdownDocument, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<int> PreselectedCategories { get; set; } = new List<int>();
|
public bool IconChanged
|
||||||
|
|
||||||
public void SetupDataValidation()
|
|
||||||
{
|
{
|
||||||
// Hopefully this can be avoided in the future
|
get => _iconChanged;
|
||||||
// https://github.com/reactiveui/ReactiveUI.Validation/discussions/558
|
private set => RaiseAndSetIfChanged(ref _iconChanged, value);
|
||||||
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
|
public List<int> PreselectedCategories { get; set; } = new();
|
||||||
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).IsNotEmpty(),
|
private void MarkdownDocumentOnTextChanged(object? sender, EventArgs e)
|
||||||
"At least one category must be selected"
|
{
|
||||||
);
|
Description = MarkdownDocument?.Text ?? string.Empty;
|
||||||
_iconValid = iconRule.ValidationChanged.Select(c => c.IsValid).ToProperty(this, vm => vm.IconValid);
|
|
||||||
_categoriesValid = categoriesRule.ValidationChanged.Select(c => c.IsValid).ToProperty(this, vm => vm.CategoriesValid);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ExecuteSelectIcon()
|
private async Task ExecuteSelectIcon()
|
||||||
@ -129,6 +145,7 @@ public class EntrySpecificationsViewModel : ValidatableViewModelBase
|
|||||||
|
|
||||||
IconBitmap?.Dispose();
|
IconBitmap?.Dispose();
|
||||||
IconBitmap = BitmapExtensions.LoadAndResize(result[0], 128);
|
IconBitmap = BitmapExtensions.LoadAndResize(result[0], 128);
|
||||||
|
IconChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ClearIcon()
|
private void ClearIcon()
|
||||||
@ -137,10 +154,11 @@ public class EntrySpecificationsViewModel : ValidatableViewModelBase
|
|||||||
IconBitmap = null;
|
IconBitmap = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PopulateCategories(IOperationResult<IGetCategoriesResult> result)
|
private async Task PopulateCategories()
|
||||||
{
|
{
|
||||||
|
IOperationResult<IGetCategoriesResult> categories = await _workshopClient.GetCategories.ExecuteAsync();
|
||||||
Categories.Clear();
|
Categories.Clear();
|
||||||
if (result.Data != null)
|
if (categories.Data != null)
|
||||||
Categories.AddRange(result.Data.Categories.Select(c => new CategoryViewModel(c) {IsSelected = PreselectedCategories.Contains(c.Id)}));
|
Categories.AddRange(categories.Data.Categories.Select(c => new CategoryViewModel(c) {IsSelected = PreselectedCategories.Contains(c.Id)}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -12,8 +12,8 @@
|
|||||||
<UserControl.Resources>
|
<UserControl.Resources>
|
||||||
<converters:DateTimeConverter x:Key="DateTimeConverter" />
|
<converters:DateTimeConverter x:Key="DateTimeConverter" />
|
||||||
</UserControl.Resources>
|
</UserControl.Resources>
|
||||||
<Grid ColumnDefinitions="300,*">
|
<Grid ColumnDefinitions="300,*" RowDefinitions="*, Auto">
|
||||||
<StackPanel Grid.Column="0" Spacing="10">
|
<StackPanel Grid.Column="0" Grid.RowSpan="2" Spacing="10">
|
||||||
<Border Classes="card" VerticalAlignment="Top" Margin="0 0 10 0">
|
<Border Classes="card" VerticalAlignment="Top" Margin="0 0 10 0">
|
||||||
<StackPanel>
|
<StackPanel>
|
||||||
<TextBlock Theme="{StaticResource SubtitleTextBlockStyle}">Management</TextBlock>
|
<TextBlock Theme="{StaticResource SubtitleTextBlockStyle}">Management</TextBlock>
|
||||||
@ -48,7 +48,11 @@
|
|||||||
View workshop page
|
View workshop page
|
||||||
</controls:HyperlinkButton>
|
</controls:HyperlinkButton>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<ContentControl Grid.Column="1" Content="{CompiledBinding EntrySpecificationsViewModel}"></ContentControl>
|
<ContentControl Grid.Column="1" Grid.Row="0" Content="{CompiledBinding EntrySpecificationsViewModel}"></ContentControl>
|
||||||
|
<StackPanel Grid.Column="1" Grid.Row="1" HorizontalAlignment="Right" Spacing="5" Orientation="Horizontal" Margin="0 10 0 0">
|
||||||
|
<Button Command="{CompiledBinding DiscardChanges}">Discard changes</Button>
|
||||||
|
<Button Command="{CompiledBinding SaveChanges}">Save</Button>
|
||||||
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
</UserControl>
|
</UserControl>
|
||||||
@ -1,7 +1,9 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Specialized;
|
||||||
|
using System.ComponentModel;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Http;
|
|
||||||
using System.Reactive;
|
using System.Reactive;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -10,8 +12,11 @@ using Artemis.UI.Screens.Workshop.Parameters;
|
|||||||
using Artemis.UI.Screens.Workshop.SubmissionWizard;
|
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.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.Services;
|
||||||
|
using Artemis.WebClient.Workshop.UploadHandlers;
|
||||||
using Avalonia.Media.Imaging;
|
using Avalonia.Media.Imaging;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
using StrawberryShake;
|
using StrawberryShake;
|
||||||
@ -21,37 +26,33 @@ namespace Artemis.UI.Screens.Workshop.Library;
|
|||||||
public class SubmissionDetailViewModel : RoutableScreen<WorkshopDetailParameters>
|
public class SubmissionDetailViewModel : RoutableScreen<WorkshopDetailParameters>
|
||||||
{
|
{
|
||||||
private readonly IWorkshopClient _client;
|
private readonly IWorkshopClient _client;
|
||||||
private readonly IHttpClientFactory _httpClientFactory;
|
private readonly Func<EntrySpecificationsViewModel> _getGetSpecificationsVm;
|
||||||
private readonly Func<EntrySpecificationsViewModel> _getEntrySpecificationsViewModel;
|
private readonly IRouter _router;
|
||||||
private readonly IWindowService _windowService;
|
private readonly IWindowService _windowService;
|
||||||
private readonly IWorkshopService _workshopService;
|
private readonly IWorkshopService _workshopService;
|
||||||
private readonly IRouter _router;
|
|
||||||
private IGetSubmittedEntryById_Entry? _entry;
|
private IGetSubmittedEntryById_Entry? _entry;
|
||||||
private EntrySpecificationsViewModel? _entrySpecificationsViewModel;
|
private EntrySpecificationsViewModel? _entrySpecificationsViewModel;
|
||||||
|
private bool _hasChanges;
|
||||||
|
|
||||||
public SubmissionDetailViewModel(IWorkshopClient client,
|
public SubmissionDetailViewModel(IWorkshopClient client, IWindowService windowService, IWorkshopService workshopService, IRouter router, Func<EntrySpecificationsViewModel> getSpecificationsVm) {
|
||||||
IHttpClientFactory httpClientFactory,
|
|
||||||
IWindowService windowService,
|
|
||||||
IWorkshopService workshopService,
|
|
||||||
IRouter router,
|
|
||||||
Func<EntrySpecificationsViewModel> entrySpecificationsViewModel)
|
|
||||||
{
|
|
||||||
_client = client;
|
_client = client;
|
||||||
_httpClientFactory = httpClientFactory;
|
|
||||||
_windowService = windowService;
|
_windowService = windowService;
|
||||||
_workshopService = workshopService;
|
_workshopService = workshopService;
|
||||||
_router = router;
|
_router = router;
|
||||||
_getEntrySpecificationsViewModel = entrySpecificationsViewModel;
|
_getGetSpecificationsVm = getSpecificationsVm;
|
||||||
|
|
||||||
Save = ReactiveCommand.CreateFromTask(ExecuteSave);
|
|
||||||
CreateRelease = ReactiveCommand.CreateFromTask(ExecuteCreateRelease);
|
CreateRelease = ReactiveCommand.CreateFromTask(ExecuteCreateRelease);
|
||||||
DeleteSubmission = ReactiveCommand.CreateFromTask(ExecuteDeleteSubmission);
|
DeleteSubmission = ReactiveCommand.CreateFromTask(ExecuteDeleteSubmission);
|
||||||
ViewWorkshopPage = ReactiveCommand.CreateFromTask(ExecuteViewWorkshopPage);
|
ViewWorkshopPage = ReactiveCommand.CreateFromTask(ExecuteViewWorkshopPage);
|
||||||
|
DiscardChanges = ReactiveCommand.CreateFromTask(ExecuteDiscardChanges, this.WhenAnyValue(vm => vm.HasChanges));
|
||||||
|
SaveChanges = ReactiveCommand.CreateFromTask(ExecuteSaveChanges, this.WhenAnyValue(vm => vm.HasChanges));
|
||||||
}
|
}
|
||||||
|
|
||||||
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; }
|
||||||
|
public ReactiveCommand<Unit, Unit> ViewWorkshopPage { get; }
|
||||||
|
public ReactiveCommand<Unit, Unit> SaveChanges { get; }
|
||||||
|
public ReactiveCommand<Unit, Unit> DiscardChanges { get; }
|
||||||
|
|
||||||
public EntrySpecificationsViewModel? EntrySpecificationsViewModel
|
public EntrySpecificationsViewModel? EntrySpecificationsViewModel
|
||||||
{
|
{
|
||||||
@ -65,8 +66,12 @@ public class SubmissionDetailViewModel : RoutableScreen<WorkshopDetailParameters
|
|||||||
set => RaiseAndSetIfChanged(ref _entry, value);
|
set => RaiseAndSetIfChanged(ref _entry, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReactiveCommand<Unit, Unit> ViewWorkshopPage { get; }
|
public bool HasChanges
|
||||||
|
{
|
||||||
|
get => _hasChanges;
|
||||||
|
private set => RaiseAndSetIfChanged(ref _hasChanges, value);
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
||||||
@ -77,12 +82,29 @@ public class SubmissionDetailViewModel : RoutableScreen<WorkshopDetailParameters
|
|||||||
await ApplyFromEntry(cancellationToken);
|
await ApplyFromEntry(cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override async Task OnClosing(NavigationArguments args)
|
||||||
|
{
|
||||||
|
if (!HasChanges)
|
||||||
|
return;
|
||||||
|
|
||||||
|
bool confirmed = await _windowService.ShowConfirmContentDialog("You have unsaved changes", "Do you want to discard your unsaved changes?");
|
||||||
|
if (!confirmed)
|
||||||
|
args.Cancel();
|
||||||
|
}
|
||||||
|
|
||||||
private async Task ApplyFromEntry(CancellationToken cancellationToken)
|
private async Task ApplyFromEntry(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (Entry == null)
|
if (Entry == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
EntrySpecificationsViewModel viewModel = _getEntrySpecificationsViewModel();
|
if (EntrySpecificationsViewModel != null)
|
||||||
|
{
|
||||||
|
EntrySpecificationsViewModel.PropertyChanged -= EntrySpecificationsViewModelOnPropertyChanged;
|
||||||
|
((INotifyCollectionChanged) EntrySpecificationsViewModel.SelectedCategories).CollectionChanged -= SelectedCategoriesOnCollectionChanged;
|
||||||
|
EntrySpecificationsViewModel.Tags.CollectionChanged -= TagsOnCollectionChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
EntrySpecificationsViewModel viewModel = _getGetSpecificationsVm();
|
||||||
|
|
||||||
viewModel.IconBitmap = await GetEntryIcon(cancellationToken);
|
viewModel.IconBitmap = await GetEntryIcon(cancellationToken);
|
||||||
viewModel.Name = Entry.Name;
|
viewModel.Name = Entry.Name;
|
||||||
@ -95,6 +117,9 @@ public class SubmissionDetailViewModel : RoutableScreen<WorkshopDetailParameters
|
|||||||
viewModel.Tags.Add(tag);
|
viewModel.Tags.Add(tag);
|
||||||
|
|
||||||
EntrySpecificationsViewModel = viewModel;
|
EntrySpecificationsViewModel = viewModel;
|
||||||
|
EntrySpecificationsViewModel.PropertyChanged += EntrySpecificationsViewModelOnPropertyChanged;
|
||||||
|
((INotifyCollectionChanged) EntrySpecificationsViewModel.SelectedCategories).CollectionChanged += SelectedCategoriesOnCollectionChanged;
|
||||||
|
EntrySpecificationsViewModel.Tags.CollectionChanged += TagsOnCollectionChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<Bitmap?> GetEntryIcon(CancellationToken cancellationToken)
|
private async Task<Bitmap?> GetEntryIcon(CancellationToken cancellationToken)
|
||||||
@ -102,26 +127,59 @@ public class SubmissionDetailViewModel : RoutableScreen<WorkshopDetailParameters
|
|||||||
if (Entry == null)
|
if (Entry == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
HttpClient client = _httpClientFactory.CreateClient(WorkshopConstants.WORKSHOP_CLIENT_NAME);
|
Stream? stream = await _workshopService.GetEntryIcon(Entry.Id, cancellationToken);
|
||||||
try
|
return stream != null ? new Bitmap(stream) : null;
|
||||||
{
|
|
||||||
HttpResponseMessage response = await client.GetAsync($"entries/{Entry.Id}/icon", cancellationToken);
|
|
||||||
response.EnsureSuccessStatusCode();
|
|
||||||
Stream data = await response.Content.ReadAsStreamAsync(cancellationToken);
|
|
||||||
return new Bitmap(data);
|
|
||||||
}
|
|
||||||
catch (HttpRequestException)
|
|
||||||
{
|
|
||||||
// ignored
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ExecuteSave(CancellationToken cancellationToken)
|
private void UpdateHasChanges()
|
||||||
{
|
{
|
||||||
UpdateEntryInput input = new();
|
if (EntrySpecificationsViewModel == null || Entry == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
List<int> categories = EntrySpecificationsViewModel.Categories.Where(c => c.IsSelected).Select(c => c.Id).OrderBy(c => c).ToList();
|
||||||
|
List<string> tags = EntrySpecificationsViewModel.Tags.OrderBy(t => t).ToList();
|
||||||
|
|
||||||
|
HasChanges = EntrySpecificationsViewModel.Name != Entry.Name ||
|
||||||
|
EntrySpecificationsViewModel.Description != Entry.Description ||
|
||||||
|
EntrySpecificationsViewModel.Summary != Entry.Summary ||
|
||||||
|
EntrySpecificationsViewModel.IconChanged ||
|
||||||
|
!tags.SequenceEqual(Entry.Tags.Select(t => t.Name).OrderBy(t => t)) ||
|
||||||
|
!categories.SequenceEqual(Entry.Categories.Select(c => c.Id).OrderBy(c => c));
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ExecuteDiscardChanges()
|
||||||
|
{
|
||||||
|
await ApplyFromEntry(CancellationToken.None);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ExecuteSaveChanges(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
if (Entry == null || EntrySpecificationsViewModel == null || !EntrySpecificationsViewModel.ValidationContext.GetIsValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
UpdateEntryInput input = new()
|
||||||
|
{
|
||||||
|
Id = Entry.Id,
|
||||||
|
Name = EntrySpecificationsViewModel.Name,
|
||||||
|
Summary = EntrySpecificationsViewModel.Summary,
|
||||||
|
Description = EntrySpecificationsViewModel.Description,
|
||||||
|
Categories = EntrySpecificationsViewModel.SelectedCategories,
|
||||||
|
Tags = EntrySpecificationsViewModel.Tags
|
||||||
|
};
|
||||||
|
|
||||||
IOperationResult<IUpdateEntryResult> result = await _client.UpdateEntry.ExecuteAsync(input, cancellationToken);
|
IOperationResult<IUpdateEntryResult> result = await _client.UpdateEntry.ExecuteAsync(input, cancellationToken);
|
||||||
result.EnsureNoErrors();
|
result.EnsureNoErrors();
|
||||||
|
|
||||||
|
if (EntrySpecificationsViewModel.IconChanged && EntrySpecificationsViewModel.IconBitmap != null)
|
||||||
|
{
|
||||||
|
using MemoryStream stream = new();
|
||||||
|
EntrySpecificationsViewModel.IconBitmap.Save(stream);
|
||||||
|
ImageUploadResult imageResult = await _workshopService.SetEntryIcon(Entry.Id, new Progress<StreamProgress>(), stream, cancellationToken);
|
||||||
|
if (!imageResult.IsSuccess)
|
||||||
|
throw new ArtemisWorkshopException("Failed to upload image. " + imageResult.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
HasChanges = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ExecuteCreateRelease(CancellationToken cancellationToken)
|
private async Task ExecuteCreateRelease(CancellationToken cancellationToken)
|
||||||
@ -152,4 +210,19 @@ public class SubmissionDetailViewModel : RoutableScreen<WorkshopDetailParameters
|
|||||||
if (Entry != null)
|
if (Entry != null)
|
||||||
await _workshopService.NavigateToEntry(Entry.Id, Entry.EntryType);
|
await _workshopService.NavigateToEntry(Entry.Id, Entry.EntryType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void TagsOnCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
|
||||||
|
{
|
||||||
|
UpdateHasChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SelectedCategoriesOnCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
|
||||||
|
{
|
||||||
|
UpdateHasChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void EntrySpecificationsViewModelOnPropertyChanged(object? sender, PropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
UpdateHasChanges();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -1,6 +1,4 @@
|
|||||||
using System.Reactive;
|
|
||||||
using System.Reactive.Linq;
|
using System.Reactive.Linq;
|
||||||
using Artemis.UI.Screens.Workshop.SubmissionWizard.Steps.Profile;
|
|
||||||
using Artemis.WebClient.Workshop;
|
using Artemis.WebClient.Workshop;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
|
|
||||||
@ -23,12 +21,6 @@ public class EntryTypeStepViewModel : SubmissionViewModel
|
|||||||
set => RaiseAndSetIfChanged(ref _selectedEntryType, value);
|
set => RaiseAndSetIfChanged(ref _selectedEntryType, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override ReactiveCommand<Unit, Unit> Continue { get; }
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override ReactiveCommand<Unit, Unit> GoBack { get; }
|
|
||||||
|
|
||||||
private void ExecuteContinue()
|
private void ExecuteContinue()
|
||||||
{
|
{
|
||||||
if (SelectedEntryType == null)
|
if (SelectedEntryType == null)
|
||||||
|
|||||||
@ -1,6 +1,4 @@
|
|||||||
using System;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reactive;
|
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -29,12 +27,6 @@ public class LoginStepViewModel : SubmissionViewModel
|
|||||||
ContinueText = "Log In";
|
ContinueText = "Log In";
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override ReactiveCommand<Unit, Unit> Continue { get; }
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override ReactiveCommand<Unit, Unit> GoBack { get; } = null!;
|
|
||||||
|
|
||||||
private async Task ExecuteLogin(CancellationToken ct)
|
private async Task ExecuteLogin(CancellationToken ct)
|
||||||
{
|
{
|
||||||
ContentDialogResult result = await _windowService.CreateContentDialog().WithViewModel(out WorkshopLoginViewModel _).WithTitle("Workshop login").ShowAsync();
|
ContentDialogResult result = await _windowService.CreateContentDialog().WithViewModel(out WorkshopLoginViewModel _).WithTitle("Workshop login").ShowAsync();
|
||||||
|
|||||||
@ -6,31 +6,30 @@ using Artemis.Core.Services;
|
|||||||
using Artemis.UI.Screens.ProfileEditor.ProfileTree.Dialogs;
|
using Artemis.UI.Screens.ProfileEditor.ProfileTree.Dialogs;
|
||||||
using Artemis.UI.Shared;
|
using Artemis.UI.Shared;
|
||||||
using Artemis.UI.Shared.Services;
|
using Artemis.UI.Shared.Services;
|
||||||
using FluentAvalonia.Core;
|
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.Workshop.SubmissionWizard.Steps.Profile;
|
namespace Artemis.UI.Screens.Workshop.SubmissionWizard.Steps.Profile;
|
||||||
|
|
||||||
public class ProfileAdaptionHintsLayerViewModel : ViewModelBase
|
public class ProfileAdaptionHintsLayerViewModel : ViewModelBase
|
||||||
{
|
{
|
||||||
private readonly IWindowService _windowService;
|
|
||||||
private readonly IProfileService _profileService;
|
|
||||||
private readonly ObservableAsPropertyHelper<string> _adaptionHintText;
|
private readonly ObservableAsPropertyHelper<string> _adaptionHintText;
|
||||||
|
private readonly IProfileService _profileService;
|
||||||
|
private readonly IWindowService _windowService;
|
||||||
private int _adaptionHintCount;
|
private int _adaptionHintCount;
|
||||||
|
|
||||||
public Layer Layer { get; }
|
|
||||||
|
|
||||||
public ProfileAdaptionHintsLayerViewModel(Layer layer, IWindowService windowService, IProfileService profileService)
|
public ProfileAdaptionHintsLayerViewModel(Layer layer, IWindowService windowService, IProfileService profileService)
|
||||||
{
|
{
|
||||||
_windowService = windowService;
|
_windowService = windowService;
|
||||||
_profileService = profileService;
|
_profileService = profileService;
|
||||||
_adaptionHintText = this.WhenAnyValue(vm => vm.AdaptionHintCount).Select(c => c == 1 ? "1 adaption hint" : $"{c} adaption hints").ToProperty(this, vm => vm.AdaptionHintText);
|
_adaptionHintText = this.WhenAnyValue(vm => vm.AdaptionHintCount).Select(c => c == 1 ? "1 adaption hint" : $"{c} adaption hints").ToProperty(this, vm => vm.AdaptionHintText);
|
||||||
|
|
||||||
Layer = layer;
|
Layer = layer;
|
||||||
EditAdaptionHints = ReactiveCommand.CreateFromTask(ExecuteEditAdaptionHints);
|
EditAdaptionHints = ReactiveCommand.CreateFromTask(ExecuteEditAdaptionHints);
|
||||||
AdaptionHintCount = layer.Adapter.AdaptionHints.Count;
|
AdaptionHintCount = layer.Adapter.AdaptionHints.Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Layer Layer { get; }
|
||||||
|
|
||||||
public ReactiveCommand<Unit, Unit> EditAdaptionHints { get; }
|
public ReactiveCommand<Unit, Unit> EditAdaptionHints { get; }
|
||||||
|
|
||||||
public int AdaptionHintCount
|
public int AdaptionHintCount
|
||||||
|
|||||||
@ -3,23 +3,22 @@ using System.Collections.ObjectModel;
|
|||||||
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.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using Artemis.Core.Services;
|
using Artemis.Core.Services;
|
||||||
using Artemis.UI.Screens.ProfileEditor.ProfileTree.Dialogs;
|
using Artemis.UI.Screens.ProfileEditor.ProfileTree.Dialogs;
|
||||||
using Artemis.UI.Shared.Services;
|
using Artemis.UI.Shared.Services;
|
||||||
using DynamicData;
|
using DynamicData;
|
||||||
using ReactiveUI;
|
|
||||||
using DynamicData.Aggregation;
|
using DynamicData.Aggregation;
|
||||||
|
using ReactiveUI;
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.Workshop.SubmissionWizard.Steps.Profile;
|
namespace Artemis.UI.Screens.Workshop.SubmissionWizard.Steps.Profile;
|
||||||
|
|
||||||
public class ProfileAdaptionHintsStepViewModel : SubmissionViewModel
|
public class ProfileAdaptionHintsStepViewModel : SubmissionViewModel
|
||||||
{
|
{
|
||||||
private readonly IWindowService _windowService;
|
|
||||||
private readonly IProfileService _profileService;
|
|
||||||
private readonly SourceList<ProfileAdaptionHintsLayerViewModel> _layers;
|
private readonly SourceList<ProfileAdaptionHintsLayerViewModel> _layers;
|
||||||
|
private readonly IProfileService _profileService;
|
||||||
|
private readonly IWindowService _windowService;
|
||||||
|
|
||||||
public ProfileAdaptionHintsStepViewModel(IWindowService windowService, IProfileService profileService, Func<Layer, ProfileAdaptionHintsLayerViewModel> getLayerViewModel)
|
public ProfileAdaptionHintsStepViewModel(IWindowService windowService, IProfileService profileService, Func<Layer, ProfileAdaptionHintsLayerViewModel> getLayerViewModel)
|
||||||
{
|
{
|
||||||
@ -36,18 +35,14 @@ public class ProfileAdaptionHintsStepViewModel : SubmissionViewModel
|
|||||||
this.WhenActivated((CompositeDisposable _) =>
|
this.WhenActivated((CompositeDisposable _) =>
|
||||||
{
|
{
|
||||||
if (State.EntrySource is ProfileConfiguration profileConfiguration && profileConfiguration.Profile != null)
|
if (State.EntrySource is ProfileConfiguration profileConfiguration && profileConfiguration.Profile != null)
|
||||||
{
|
|
||||||
_layers.Edit(l =>
|
_layers.Edit(l =>
|
||||||
{
|
{
|
||||||
l.Clear();
|
l.Clear();
|
||||||
l.AddRange(profileConfiguration.Profile.GetAllLayers().Select(getLayerViewModel));
|
l.AddRange(profileConfiguration.Profile.GetAllLayers().Select(getLayerViewModel));
|
||||||
});
|
});
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public override ReactiveCommand<Unit, Unit> Continue { get; }
|
|
||||||
public override ReactiveCommand<Unit, Unit> GoBack { get; }
|
|
||||||
public ReactiveCommand<Layer, Unit> EditAdaptionHints { get; }
|
public ReactiveCommand<Layer, Unit> EditAdaptionHints { get; }
|
||||||
public ReadOnlyObservableCollection<ProfileAdaptionHintsLayerViewModel> Layers { get; }
|
public ReadOnlyObservableCollection<ProfileAdaptionHintsLayerViewModel> Layers { get; }
|
||||||
|
|
||||||
@ -61,7 +56,7 @@ public class ProfileAdaptionHintsStepViewModel : SubmissionViewModel
|
|||||||
{
|
{
|
||||||
if (Layers.Any(l => l.AdaptionHintCount == 0))
|
if (Layers.Any(l => l.AdaptionHintCount == 0))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (State.EntryId == null)
|
if (State.EntryId == null)
|
||||||
State.ChangeScreen<SpecificationsStepViewModel>();
|
State.ChangeScreen<SpecificationsStepViewModel>();
|
||||||
else
|
else
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
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;
|
||||||
@ -52,12 +51,6 @@ public class ProfileSelectionStepViewModel : SubmissionViewModel
|
|||||||
set => RaiseAndSetIfChanged(ref _selectedProfile, value);
|
set => RaiseAndSetIfChanged(ref _selectedProfile, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override ReactiveCommand<Unit, Unit> Continue { get; }
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override ReactiveCommand<Unit, Unit> GoBack { get; }
|
|
||||||
|
|
||||||
private void Update(ProfileConfiguration? profileConfiguration)
|
private void Update(ProfileConfiguration? profileConfiguration)
|
||||||
{
|
{
|
||||||
ProfilePreview.ProfileConfiguration = null;
|
ProfilePreview.ProfileConfiguration = null;
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
using Avalonia;
|
|
||||||
using Avalonia.Controls;
|
|
||||||
using Avalonia.Markup.Xaml;
|
using Avalonia.Markup.Xaml;
|
||||||
using Avalonia.ReactiveUI;
|
using Avalonia.ReactiveUI;
|
||||||
|
|
||||||
|
|||||||
@ -2,41 +2,38 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reactive;
|
|
||||||
using System.Reactive.Disposables;
|
using System.Reactive.Disposables;
|
||||||
using Artemis.UI.Extensions;
|
using Artemis.UI.Extensions;
|
||||||
using Artemis.UI.Screens.Workshop.Entries;
|
using Artemis.UI.Screens.Workshop.Entries;
|
||||||
using Artemis.UI.Screens.Workshop.SubmissionWizard.Steps.Profile;
|
using Artemis.UI.Screens.Workshop.SubmissionWizard.Steps.Profile;
|
||||||
using Artemis.WebClient.Workshop;
|
using Artemis.WebClient.Workshop;
|
||||||
using Avalonia.Threading;
|
|
||||||
using DynamicData;
|
using DynamicData;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
using ReactiveUI.Validation.Extensions;
|
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.Workshop.SubmissionWizard.Steps;
|
namespace Artemis.UI.Screens.Workshop.SubmissionWizard.Steps;
|
||||||
|
|
||||||
public class SpecificationsStepViewModel : SubmissionViewModel
|
public class SpecificationsStepViewModel : SubmissionViewModel
|
||||||
{
|
{
|
||||||
public SpecificationsStepViewModel(EntrySpecificationsViewModel entrySpecificationsViewModel)
|
private readonly Func<EntrySpecificationsViewModel> _getEntrySpecificationsViewModel;
|
||||||
{
|
private EntrySpecificationsViewModel? _entrySpecificationsViewModel;
|
||||||
EntrySpecificationsViewModel = entrySpecificationsViewModel;
|
|
||||||
GoBack = ReactiveCommand.Create(ExecuteGoBack);
|
|
||||||
Continue = ReactiveCommand.Create(ExecuteContinue, EntrySpecificationsViewModel.ValidationContext.Valid);
|
|
||||||
|
|
||||||
|
public SpecificationsStepViewModel(Func<EntrySpecificationsViewModel> getEntrySpecificationsViewModel)
|
||||||
|
{
|
||||||
|
_getEntrySpecificationsViewModel = getEntrySpecificationsViewModel;
|
||||||
|
|
||||||
|
GoBack = ReactiveCommand.Create(ExecuteGoBack);
|
||||||
this.WhenActivated((CompositeDisposable d) =>
|
this.WhenActivated((CompositeDisposable d) =>
|
||||||
{
|
{
|
||||||
DisplayName = $"{State.EntryType} Information";
|
DisplayName = $"{State.EntryType} Information";
|
||||||
|
|
||||||
// Apply the state
|
|
||||||
ApplyFromState();
|
ApplyFromState();
|
||||||
|
|
||||||
EntrySpecificationsViewModel.ClearValidationRules();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public EntrySpecificationsViewModel EntrySpecificationsViewModel { get; }
|
public EntrySpecificationsViewModel? EntrySpecificationsViewModel
|
||||||
public override ReactiveCommand<Unit, Unit> Continue { get; }
|
{
|
||||||
public override ReactiveCommand<Unit, Unit> GoBack { get; }
|
get => _entrySpecificationsViewModel;
|
||||||
|
set => RaiseAndSetIfChanged(ref _entrySpecificationsViewModel, value);
|
||||||
|
}
|
||||||
|
|
||||||
private void ExecuteGoBack()
|
private void ExecuteGoBack()
|
||||||
{
|
{
|
||||||
@ -59,46 +56,45 @@ public class SpecificationsStepViewModel : SubmissionViewModel
|
|||||||
|
|
||||||
private void ExecuteContinue()
|
private void ExecuteContinue()
|
||||||
{
|
{
|
||||||
if (!EntrySpecificationsViewModel.ValidationContext.Validations.Any())
|
if (EntrySpecificationsViewModel == null || !EntrySpecificationsViewModel.ValidationContext.GetIsValid())
|
||||||
{
|
|
||||||
// The ValidationContext seems to update asynchronously, so stop and schedule a retry
|
|
||||||
EntrySpecificationsViewModel.SetupDataValidation();
|
|
||||||
Dispatcher.UIThread.Post(ExecuteContinue);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
ApplyToState();
|
ApplyToState();
|
||||||
|
|
||||||
if (!EntrySpecificationsViewModel.ValidationContext.GetIsValid())
|
|
||||||
return;
|
|
||||||
|
|
||||||
State.ChangeScreen<SubmitStepViewModel>();
|
State.ChangeScreen<SubmitStepViewModel>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ApplyFromState()
|
private void ApplyFromState()
|
||||||
{
|
{
|
||||||
|
EntrySpecificationsViewModel viewModel = _getEntrySpecificationsViewModel();
|
||||||
|
|
||||||
// Basic fields
|
// Basic fields
|
||||||
EntrySpecificationsViewModel.Name = State.Name;
|
viewModel.Name = State.Name;
|
||||||
EntrySpecificationsViewModel.Summary = State.Summary;
|
viewModel.Summary = State.Summary;
|
||||||
EntrySpecificationsViewModel.Description = State.Description;
|
viewModel.Description = State.Description;
|
||||||
|
|
||||||
// Tags
|
// Tags
|
||||||
EntrySpecificationsViewModel.Tags.Clear();
|
viewModel.Tags.Clear();
|
||||||
EntrySpecificationsViewModel.Tags.AddRange(State.Tags);
|
viewModel.Tags.AddRange(State.Tags);
|
||||||
|
|
||||||
// Categories
|
// Categories
|
||||||
EntrySpecificationsViewModel.PreselectedCategories = State.Categories;
|
viewModel.PreselectedCategories = State.Categories;
|
||||||
|
|
||||||
// Icon
|
// Icon
|
||||||
if (State.Icon != null)
|
if (State.Icon != null)
|
||||||
{
|
{
|
||||||
State.Icon.Seek(0, SeekOrigin.Begin);
|
State.Icon.Seek(0, SeekOrigin.Begin);
|
||||||
EntrySpecificationsViewModel.IconBitmap = BitmapExtensions.LoadAndResize(State.Icon, 128);
|
viewModel.IconBitmap = BitmapExtensions.LoadAndResize(State.Icon, 128);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EntrySpecificationsViewModel = viewModel;
|
||||||
|
Continue = ReactiveCommand.Create(ExecuteContinue, EntrySpecificationsViewModel.ValidationContext.Valid);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ApplyToState()
|
private void ApplyToState()
|
||||||
{
|
{
|
||||||
|
if (EntrySpecificationsViewModel == null)
|
||||||
|
return;
|
||||||
|
|
||||||
// Basic fields
|
// Basic fields
|
||||||
State.Name = EntrySpecificationsViewModel.Name;
|
State.Name = EntrySpecificationsViewModel.Name;
|
||||||
State.Summary = EntrySpecificationsViewModel.Summary;
|
State.Summary = EntrySpecificationsViewModel.Summary;
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
using Avalonia;
|
|
||||||
using Avalonia.Controls;
|
|
||||||
using Avalonia.Markup.Xaml;
|
using Avalonia.Markup.Xaml;
|
||||||
using Avalonia.ReactiveUI;
|
using Avalonia.ReactiveUI;
|
||||||
|
|
||||||
|
|||||||
@ -1,17 +1,16 @@
|
|||||||
|
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.Disposables;
|
using System.Reactive.Disposables;
|
||||||
using System.Reactive.Linq;
|
using System.Reactive.Linq;
|
||||||
using Artemis.UI.Screens.Workshop.Categories;
|
using Artemis.UI.Screens.Workshop.Categories;
|
||||||
using Artemis.WebClient.Workshop;
|
using Artemis.WebClient.Workshop;
|
||||||
using Artemis.WebClient.Workshop.Services;
|
using Artemis.WebClient.Workshop.Services;
|
||||||
|
using Avalonia.Media.Imaging;
|
||||||
using IdentityModel;
|
using IdentityModel;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
using StrawberryShake;
|
using StrawberryShake;
|
||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using Avalonia.Media.Imaging;
|
|
||||||
|
|
||||||
namespace Artemis.UI.Screens.Workshop.SubmissionWizard.Steps;
|
namespace Artemis.UI.Screens.Workshop.SubmissionWizard.Steps;
|
||||||
|
|
||||||
@ -26,9 +25,9 @@ public class SubmitStepViewModel : SubmissionViewModel
|
|||||||
CurrentUser = authenticationService.Claims.FirstOrDefault(c => c.Type == JwtClaimTypes.Name)?.Value;
|
CurrentUser = authenticationService.Claims.FirstOrDefault(c => c.Type == JwtClaimTypes.Name)?.Value;
|
||||||
GoBack = ReactiveCommand.Create(() => State.ChangeScreen<SpecificationsStepViewModel>());
|
GoBack = ReactiveCommand.Create(() => State.ChangeScreen<SpecificationsStepViewModel>());
|
||||||
Continue = ReactiveCommand.Create(() => State.ChangeScreen<UploadStepViewModel>());
|
Continue = ReactiveCommand.Create(() => State.ChangeScreen<UploadStepViewModel>());
|
||||||
|
|
||||||
ContinueText = "Submit";
|
ContinueText = "Submit";
|
||||||
|
|
||||||
this.WhenActivated(d =>
|
this.WhenActivated(d =>
|
||||||
{
|
{
|
||||||
if (State.Icon != null)
|
if (State.Icon != null)
|
||||||
@ -37,6 +36,7 @@ public class SubmitStepViewModel : SubmissionViewModel
|
|||||||
IconBitmap = new Bitmap(State.Icon);
|
IconBitmap = new Bitmap(State.Icon);
|
||||||
IconBitmap.DisposeWith(d);
|
IconBitmap.DisposeWith(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
Observable.FromAsync(workshopClient.GetCategories.ExecuteAsync).Subscribe(PopulateCategories).DisposeWith(d);
|
Observable.FromAsync(workshopClient.GetCategories.ExecuteAsync).Subscribe(PopulateCategories).DisposeWith(d);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -55,19 +55,13 @@ public class SubmitStepViewModel : SubmissionViewModel
|
|||||||
set => RaiseAndSetIfChanged(ref _categories, value);
|
set => RaiseAndSetIfChanged(ref _categories, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override ReactiveCommand<Unit, Unit> Continue { get; }
|
|
||||||
|
|
||||||
public override ReactiveCommand<Unit, Unit> GoBack { get; }
|
|
||||||
|
|
||||||
private void PopulateCategories(IOperationResult<IGetCategoriesResult> result)
|
private void PopulateCategories(IOperationResult<IGetCategoriesResult> result)
|
||||||
{
|
{
|
||||||
if (result.Data == null)
|
if (result.Data == null)
|
||||||
Categories = null;
|
Categories = null;
|
||||||
else
|
else
|
||||||
{
|
|
||||||
Categories = new ReadOnlyObservableCollection<CategoryViewModel>(
|
Categories = new ReadOnlyObservableCollection<CategoryViewModel>(
|
||||||
new ObservableCollection<CategoryViewModel>(result.Data.Categories.Where(c => State.Categories.Contains(c.Id)).Select(c => new CategoryViewModel(c)))
|
new ObservableCollection<CategoryViewModel>(result.Data.Categories.Where(c => State.Categories.Contains(c.Id)).Select(c => new CategoryViewModel(c)))
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,5 +1,3 @@
|
|||||||
using Avalonia;
|
|
||||||
using Avalonia.Controls;
|
|
||||||
using Avalonia.Markup.Xaml;
|
using Avalonia.Markup.Xaml;
|
||||||
using Avalonia.ReactiveUI;
|
using Avalonia.ReactiveUI;
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Reactive;
|
|
||||||
using System.Reactive.Disposables;
|
using System.Reactive.Disposables;
|
||||||
using System.Reactive.Linq;
|
using System.Reactive.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
@ -55,12 +54,6 @@ public class UploadStepViewModel : SubmissionViewModel
|
|||||||
this.WhenActivated(d => Observable.FromAsync(ExecuteUpload).Subscribe().DisposeWith(d));
|
this.WhenActivated(d => Observable.FromAsync(ExecuteUpload).Subscribe().DisposeWith(d));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override ReactiveCommand<Unit, Unit> Continue { get; }
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override ReactiveCommand<Unit, Unit> GoBack { get; } = null!;
|
|
||||||
|
|
||||||
public int ProgressPercentage => _progressPercentage.Value;
|
public int ProgressPercentage => _progressPercentage.Value;
|
||||||
public bool ProgressIndeterminate => _progressIndeterminate.Value;
|
public bool ProgressIndeterminate => _progressIndeterminate.Value;
|
||||||
|
|
||||||
|
|||||||
@ -27,7 +27,7 @@ public class ValidateEmailStepViewModel : SubmissionViewModel
|
|||||||
Continue = ReactiveCommand.Create(ExecuteContinue);
|
Continue = ReactiveCommand.Create(ExecuteContinue);
|
||||||
Refresh = ReactiveCommand.CreateFromTask(ExecuteRefresh);
|
Refresh = ReactiveCommand.CreateFromTask(ExecuteRefresh);
|
||||||
Resend = ReactiveCommand.Create(() => Utilities.OpenUrl(WorkshopConstants.AUTHORITY_URL + "/account/confirm/resend"));
|
Resend = ReactiveCommand.Create(() => Utilities.OpenUrl(WorkshopConstants.AUTHORITY_URL + "/account/confirm/resend"));
|
||||||
|
|
||||||
ShowGoBack = false;
|
ShowGoBack = false;
|
||||||
ShowHeader = false;
|
ShowHeader = false;
|
||||||
|
|
||||||
@ -43,12 +43,6 @@ public class ValidateEmailStepViewModel : SubmissionViewModel
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override ReactiveCommand<Unit, Unit> Continue { get; }
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override ReactiveCommand<Unit, Unit> GoBack { get; } = null!;
|
|
||||||
|
|
||||||
public ReactiveCommand<Unit, Unit> Refresh { get; }
|
public ReactiveCommand<Unit, Unit> Refresh { get; }
|
||||||
public ReactiveCommand<Unit, Process?> Resend { get; }
|
public ReactiveCommand<Unit, Process?> Resend { get; }
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,4 @@
|
|||||||
using System;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reactive;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Artemis.WebClient.Workshop.Services;
|
using Artemis.WebClient.Workshop.Services;
|
||||||
using IdentityModel;
|
using IdentityModel;
|
||||||
@ -21,12 +19,6 @@ public class WelcomeStepViewModel : SubmissionViewModel
|
|||||||
ShowGoBack = false;
|
ShowGoBack = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override ReactiveCommand<Unit, Unit> Continue { get; }
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public override ReactiveCommand<Unit, Unit> GoBack { get; } = null!;
|
|
||||||
|
|
||||||
private async Task ExecuteContinue()
|
private async Task ExecuteContinue()
|
||||||
{
|
{
|
||||||
bool loggedIn = await _authenticationService.AutoLogin(true);
|
bool loggedIn = await _authenticationService.AutoLogin(true);
|
||||||
|
|||||||
@ -6,15 +6,26 @@ namespace Artemis.UI.Screens.Workshop.SubmissionWizard;
|
|||||||
|
|
||||||
public abstract class SubmissionViewModel : ValidatableViewModelBase
|
public abstract class SubmissionViewModel : ValidatableViewModelBase
|
||||||
{
|
{
|
||||||
|
private ReactiveCommand<Unit, Unit>? _continue;
|
||||||
|
private ReactiveCommand<Unit, Unit>? _goBack;
|
||||||
private string _continueText = "Continue";
|
private string _continueText = "Continue";
|
||||||
private bool _showFinish;
|
private bool _showFinish;
|
||||||
private bool _showGoBack = true;
|
private bool _showGoBack = true;
|
||||||
private bool _showHeader = true;
|
private bool _showHeader = true;
|
||||||
|
|
||||||
public SubmissionWizardState State { get; set; } = null!;
|
public SubmissionWizardState State { get; set; } = null!;
|
||||||
|
|
||||||
public abstract ReactiveCommand<Unit, Unit> Continue { get; }
|
public ReactiveCommand<Unit, Unit>? Continue
|
||||||
public abstract ReactiveCommand<Unit, Unit> GoBack { get; }
|
{
|
||||||
|
get => _continue;
|
||||||
|
set => RaiseAndSetIfChanged(ref _continue, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReactiveCommand<Unit, Unit>? GoBack
|
||||||
|
{
|
||||||
|
get => _goBack;
|
||||||
|
set => RaiseAndSetIfChanged(ref _goBack, value);
|
||||||
|
}
|
||||||
|
|
||||||
public bool ShowHeader
|
public bool ShowHeader
|
||||||
{
|
{
|
||||||
|
|||||||
@ -46,7 +46,7 @@
|
|||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
<DataTemplate DataType="system:Object">
|
<DataTemplate DataType="system:Object">
|
||||||
<Border Classes="card-condensed" Margin="0,5,5,5 ">
|
<Border Classes="card-condensed" Margin="0,5,5,5 ">
|
||||||
<TextBlock Text="{CompiledBinding Converter={StaticResource JsonConverter}}" FontFamily="{StaticResource RobotoMono}"/>
|
<TextBlock Text="{CompiledBinding Converter={StaticResource JsonConverter}}" FontFamily="{StaticResource RobotoMono}" FontSize="12"/>
|
||||||
</Border>
|
</Border>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ContentControl.DataTemplates>
|
</ContentControl.DataTemplates>
|
||||||
|
|||||||
@ -16,6 +16,22 @@ public class WorkshopService : IWorkshopService
|
|||||||
_router = router;
|
_router = router;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<Stream?> GetEntryIcon(Guid entryId, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
HttpClient client = _httpClientFactory.CreateClient(WorkshopConstants.WORKSHOP_CLIENT_NAME);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
HttpResponseMessage response = await client.GetAsync($"entries/{entryId}/icon", cancellationToken);
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
return await response.Content.ReadAsStreamAsync(cancellationToken);
|
||||||
|
}
|
||||||
|
catch (HttpRequestException)
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<ImageUploadResult> SetEntryIcon(Guid entryId, Progress<StreamProgress> progress, Stream icon, CancellationToken cancellationToken)
|
public async Task<ImageUploadResult> SetEntryIcon(Guid entryId, Progress<StreamProgress> progress, Stream icon, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
icon.Seek(0, SeekOrigin.Begin);
|
icon.Seek(0, SeekOrigin.Begin);
|
||||||
@ -55,7 +71,7 @@ public class WorkshopService : IWorkshopService
|
|||||||
return new IWorkshopService.WorkshopStatus(false, e.Message);
|
return new IWorkshopService.WorkshopStatus(false, e.Message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async Task<bool> ValidateWorkshopStatus(CancellationToken cancellationToken)
|
public async Task<bool> ValidateWorkshopStatus(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
@ -86,10 +102,11 @@ public class WorkshopService : IWorkshopService
|
|||||||
|
|
||||||
public interface IWorkshopService
|
public interface IWorkshopService
|
||||||
{
|
{
|
||||||
|
Task<Stream?> GetEntryIcon(Guid entryId, CancellationToken cancellationToken);
|
||||||
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);
|
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