diff --git a/src/Artemis.UI/Controls/SplitMarkdownEditor.axaml b/src/Artemis.UI/Controls/SplitMarkdownEditor.axaml
new file mode 100644
index 000000000..f99eba062
--- /dev/null
+++ b/src/Artemis.UI/Controls/SplitMarkdownEditor.axaml
@@ -0,0 +1,51 @@
+
+
+
+
+
+ Synchronized scrolling
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Artemis.UI/Controls/SplitMarkdownEditor.axaml.cs b/src/Artemis.UI/Controls/SplitMarkdownEditor.axaml.cs
new file mode 100644
index 000000000..ec50e2e0a
--- /dev/null
+++ b/src/Artemis.UI/Controls/SplitMarkdownEditor.axaml.cs
@@ -0,0 +1,150 @@
+using System;
+using System.Linq;
+using System.Threading.Tasks;
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Data;
+using Avalonia.Media;
+using Avalonia.Media.Immutable;
+using Avalonia.Threading;
+using AvaloniaEdit.TextMate;
+using TextMateSharp.Grammars;
+using VisualExtensions = Artemis.UI.Shared.Extensions.VisualExtensions;
+
+namespace Artemis.UI.Controls;
+
+public partial class SplitMarkdownEditor : UserControl
+{
+ public static readonly StyledProperty TitleProperty = AvaloniaProperty.Register(nameof(Title), string.Empty);
+ public static readonly StyledProperty MarkdownProperty = AvaloniaProperty.Register(nameof(Markdown), string.Empty, defaultBindingMode: BindingMode.TwoWay);
+
+ private ScrollViewer? _editorScrollViewer;
+ private ScrollViewer? _previewScrollViewer;
+ private bool _scrolling;
+ private bool _updating;
+
+ public string Title
+ {
+ get => GetValue(TitleProperty);
+ set => SetValue(TitleProperty, value);
+ }
+
+ public string Markdown
+ {
+ get => GetValue(MarkdownProperty);
+ set => SetValue(MarkdownProperty, value);
+ }
+
+ public SplitMarkdownEditor()
+ {
+ InitializeComponent();
+ PropertyChanged += OnPropertyChanged;
+
+ DescriptionEditorLabel.Content = Title;
+ DescriptionEditor.Options.AllowScrollBelowDocument = false;
+ }
+
+ protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
+ {
+ if (this.TryFindResource("SystemAccentColorLight3", out object? resource) && resource is Color color)
+ DescriptionEditor.TextArea.TextView.LinkTextForegroundBrush = new ImmutableSolidColorBrush(color);
+
+ SetupScrollSync();
+
+ Dispatcher.UIThread.InvokeAsync(async () =>
+ {
+ // Installing is slow, wait for UI to settle
+ await Task.Delay(300);
+
+ RegistryOptions options = new(ThemeName.Dark);
+ TextMate.Installation? install = DescriptionEditor.InstallTextMate(options);
+ install.SetGrammar(options.GetScopeByExtension(".md"));
+ }, DispatcherPriority.ApplicationIdle);
+ }
+
+ private void SetupScrollSync()
+ {
+ if (_editorScrollViewer != null)
+ _editorScrollViewer.PropertyChanged -= EditorScrollViewerOnPropertyChanged;
+ if (_previewScrollViewer != null)
+ _previewScrollViewer.PropertyChanged -= PreviewScrollViewerOnPropertyChanged;
+
+ _editorScrollViewer = VisualExtensions.GetVisualChildrenOfType(DescriptionEditor).FirstOrDefault();
+ _previewScrollViewer = VisualExtensions.GetVisualChildrenOfType(DescriptionPreview).FirstOrDefault();
+
+ if (_editorScrollViewer != null)
+ _editorScrollViewer.PropertyChanged += EditorScrollViewerOnPropertyChanged;
+ if (_previewScrollViewer != null)
+ _previewScrollViewer.PropertyChanged += PreviewScrollViewerOnPropertyChanged;
+ }
+
+ private void EditorScrollViewerOnPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e)
+ {
+ if (e.Property.Name != nameof(ScrollViewer.Offset) || _scrolling || SynchronizedScrolling.IsChecked != true)
+ return;
+
+ try
+ {
+ _scrolling = true;
+ SynchronizeScrollViewers(_editorScrollViewer, _previewScrollViewer);
+ }
+ finally
+ {
+ _scrolling = false;
+ }
+ }
+
+ private void PreviewScrollViewerOnPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e)
+ {
+ if (e.Property.Name != nameof(ScrollViewer.Offset) || _scrolling || SynchronizedScrolling.IsChecked != true)
+ return;
+
+ try
+ {
+ _scrolling = true;
+ SynchronizeScrollViewers(_previewScrollViewer, _editorScrollViewer);
+ }
+ finally
+ {
+ _scrolling = false;
+ }
+ }
+
+ private void SynchronizeScrollViewers(ScrollViewer? source, ScrollViewer? target)
+ {
+ if (source == null || target == null)
+ return;
+
+ double sourceScrollableHeight = source.Extent.Height - source.Viewport.Height;
+ double targetScrollableHeight = target.Extent.Height - target.Viewport.Height;
+
+ if (sourceScrollableHeight != 0)
+ target.Offset = new Vector(target.Offset.X, targetScrollableHeight * (source.Offset.Y / sourceScrollableHeight));
+ }
+
+ private void OnPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e)
+ {
+ if (e.Property == TitleProperty)
+ DescriptionEditorLabel.Content = Title;
+ else if (e.Property == MarkdownProperty && DescriptionEditor.Text != Markdown)
+ {
+ try
+ {
+ _updating = true;
+ DescriptionEditor.Clear();
+ DescriptionEditor.AppendText(Markdown);
+ }
+ finally
+ {
+ _updating = false;
+ }
+
+ }
+ }
+
+ private void DescriptionEditor_OnTextChanged(object? sender, EventArgs e)
+ {
+ if (!_updating && Markdown != DescriptionEditor.Text)
+ Markdown = DescriptionEditor.Text;
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Workshop/Entries/Details/EntrySpecificationsView.axaml b/src/Artemis.UI/Screens/Workshop/Entries/Details/EntrySpecificationsView.axaml
index 8b7fb56e6..16a0b4b5a 100644
--- a/src/Artemis.UI/Screens/Workshop/Entries/Details/EntrySpecificationsView.axaml
+++ b/src/Artemis.UI/Screens/Workshop/Entries/Details/EntrySpecificationsView.axaml
@@ -2,18 +2,15 @@
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:entries="clr-namespace:Artemis.UI.Screens.Workshop.Entries"
xmlns:tagsInput="clr-namespace:Artemis.UI.Shared.TagsInput;assembly=Artemis.UI.Shared"
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
xmlns:categories="clr-namespace:Artemis.UI.Screens.Workshop.Categories"
- xmlns:avaloniaEdit="https://github.com/avaloniaui/avaloniaedit"
- xmlns:mdxaml="https://github.com/whistyun/Markdown.Avalonia.Tight"
- xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
xmlns:details="clr-namespace:Artemis.UI.Screens.Workshop.Entries.Details"
+ xmlns:controls="clr-namespace:Artemis.UI.Controls"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="800"
x:Class="Artemis.UI.Screens.Workshop.Entries.Details.EntrySpecificationsView"
x:DataType="details:EntrySpecificationsViewModel">
-
+
@@ -95,48 +92,9 @@
-
-
-
-
- Synchronized scrolling
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
diff --git a/src/Artemis.UI/Screens/Workshop/Entries/Details/EntrySpecificationsView.axaml.cs b/src/Artemis.UI/Screens/Workshop/Entries/Details/EntrySpecificationsView.axaml.cs
index 37c85d118..1374349e9 100644
--- a/src/Artemis.UI/Screens/Workshop/Entries/Details/EntrySpecificationsView.axaml.cs
+++ b/src/Artemis.UI/Screens/Workshop/Entries/Details/EntrySpecificationsView.axaml.cs
@@ -1,100 +1,11 @@
-using System.Linq;
-using Avalonia;
-using Avalonia.Controls;
-using Avalonia.Media;
-using Avalonia.Media.Immutable;
using Avalonia.ReactiveUI;
-using AvaloniaEdit.TextMate;
-using ReactiveUI;
-using TextMateSharp.Grammars;
-using VisualExtensions = Artemis.UI.Shared.Extensions.VisualExtensions;
namespace Artemis.UI.Screens.Workshop.Entries.Details;
public partial class EntrySpecificationsView : ReactiveUserControl
{
- private ScrollViewer? _editorScrollViewer;
- private ScrollViewer? _previewScrollViewer;
- private bool _updating;
-
public EntrySpecificationsView()
{
InitializeComponent();
-
- DescriptionEditor.Options.AllowScrollBelowDocument = false;
- RegistryOptions options = new(ThemeName.Dark);
- TextMate.Installation? install = TextMate.InstallTextMate(DescriptionEditor, options);
-
- install.SetGrammar(options.GetScopeByExtension(".md"));
-
- this.WhenActivated(_ => SetupScrollSync());
- }
-
- protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
- {
- if (this.TryFindResource("SystemAccentColorLight3", out object? resource) && resource is Color color)
- DescriptionEditor.TextArea.TextView.LinkTextForegroundBrush = new ImmutableSolidColorBrush(color);
-
- base.OnAttachedToVisualTree(e);
- }
-
- private void SetupScrollSync()
- {
- if (_editorScrollViewer != null)
- _editorScrollViewer.PropertyChanged -= EditorScrollViewerOnPropertyChanged;
- if (_previewScrollViewer != null)
- _previewScrollViewer.PropertyChanged -= PreviewScrollViewerOnPropertyChanged;
-
- _editorScrollViewer = VisualExtensions.GetVisualChildrenOfType(DescriptionEditor).FirstOrDefault();
- _previewScrollViewer = VisualExtensions.GetVisualChildrenOfType(DescriptionPreview).FirstOrDefault();
-
- if (_editorScrollViewer != null)
- _editorScrollViewer.PropertyChanged += EditorScrollViewerOnPropertyChanged;
- if (_previewScrollViewer != null)
- _previewScrollViewer.PropertyChanged += PreviewScrollViewerOnPropertyChanged;
- }
-
- private void EditorScrollViewerOnPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e)
- {
- if (e.Property.Name != nameof(ScrollViewer.Offset) || _updating || SynchronizedScrolling.IsChecked != true)
- return;
-
- try
- {
- _updating = true;
- SynchronizeScrollViewers(_editorScrollViewer, _previewScrollViewer);
- }
- finally
- {
- _updating = false;
- }
- }
-
- private void PreviewScrollViewerOnPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e)
- {
- if (e.Property.Name != nameof(ScrollViewer.Offset) || _updating || SynchronizedScrolling.IsChecked != true)
- return;
-
- try
- {
- _updating = true;
- SynchronizeScrollViewers(_previewScrollViewer, _editorScrollViewer);
- }
- finally
- {
- _updating = false;
- }
- }
-
- private void SynchronizeScrollViewers(ScrollViewer? source, ScrollViewer? target)
- {
- if (source == null || target == null)
- return;
-
- double sourceScrollableHeight = source.Extent.Height - source.Viewport.Height;
- double targetScrollableHeight = target.Extent.Height - target.Viewport.Height;
-
- if (sourceScrollableHeight != 0)
- target.Offset = new Vector(target.Offset.X, targetScrollableHeight * (source.Offset.Y / sourceScrollableHeight));
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Workshop/Entries/Details/EntrySpecificationsViewModel.cs b/src/Artemis.UI/Screens/Workshop/Entries/Details/EntrySpecificationsViewModel.cs
index f06262a3f..d277f9f62 100644
--- a/src/Artemis.UI/Screens/Workshop/Entries/Details/EntrySpecificationsViewModel.cs
+++ b/src/Artemis.UI/Screens/Workshop/Entries/Details/EntrySpecificationsViewModel.cs
@@ -35,7 +35,6 @@ public partial class EntrySpecificationsViewModel : ValidatableViewModelBase
[Notify] private string _summary = string.Empty;
[Notify] private string _description = string.Empty;
[Notify] private Bitmap? _iconBitmap;
- [Notify] private TextDocument? _markdownDocument;
[Notify(Setter.Private)] private bool _iconChanged;
public EntrySpecificationsViewModel(IWorkshopClient workshopClient, IWindowService windowService)
@@ -69,15 +68,7 @@ public EntrySpecificationsViewModel(IWorkshopClient workshopClient, IWindowServi
{
// Load categories
await PopulateCategories();
-
- MarkdownDocument = new TextDocument(new StringTextSource(Description));
- MarkdownDocument.TextChanged += MarkdownDocumentOnTextChanged;
- Disposable.Create(() =>
- {
- MarkdownDocument.TextChanged -= MarkdownDocumentOnTextChanged;
- MarkdownDocument = null;
- ClearIcon();
- }).DisposeWith(d);
+ Disposable.Create(ClearIcon).DisposeWith(d);
});
}
@@ -92,12 +83,7 @@ public EntrySpecificationsViewModel(IWorkshopClient workshopClient, IWindowServi
public bool DescriptionValid => _descriptionValid.Value;
public List PreselectedCategories { get; set; } = new();
-
- private void MarkdownDocumentOnTextChanged(object? sender, EventArgs e)
- {
- Description = MarkdownDocument?.Text ?? string.Empty;
- }
-
+
private async Task ExecuteSelectIcon()
{
string[]? result = await _windowService.CreateOpenFileDialog()
diff --git a/src/Artemis.UI/Screens/Workshop/Library/SubmissionManagementViewModel.cs b/src/Artemis.UI/Screens/Workshop/Library/SubmissionManagementViewModel.cs
index 3b1feb76a..7146f6307 100644
--- a/src/Artemis.UI/Screens/Workshop/Library/SubmissionManagementViewModel.cs
+++ b/src/Artemis.UI/Screens/Workshop/Library/SubmissionManagementViewModel.cs
@@ -36,6 +36,8 @@ public SubmissionManagementViewModel(IWorkshopClient client, IRouter router, IWi
_windowService = windowService;
_workshopService = workshopService;
+ RecycleScreen = false;
+
this.WhenActivated(d =>
{
this.WhenAnyValue(vm => vm.SelectedRelease)
diff --git a/src/Artemis.UI/Screens/Workshop/Library/SubmissionReleaseView.axaml b/src/Artemis.UI/Screens/Workshop/Library/SubmissionReleaseView.axaml
index 105417bf4..691e767a1 100644
--- a/src/Artemis.UI/Screens/Workshop/Library/SubmissionReleaseView.axaml
+++ b/src/Artemis.UI/Screens/Workshop/Library/SubmissionReleaseView.axaml
@@ -4,13 +4,11 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:library="clr-namespace:Artemis.UI.Screens.Workshop.Library"
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
- xmlns:avaloniaEdit="https://github.com/avaloniaui/avaloniaedit"
- xmlns:mdxaml="https://github.com/whistyun/Markdown.Avalonia.Tight"
- xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
+ xmlns:controls1="clr-namespace:Artemis.UI.Controls"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Artemis.UI.Screens.Workshop.Library.SubmissionReleaseView"
x:DataType="library:SubmissionReleaseViewModel">
-
+
-
-
-
- Synchronized scrolling
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
diff --git a/src/Artemis.UI/Screens/Workshop/Library/SubmissionReleaseView.axaml.cs b/src/Artemis.UI/Screens/Workshop/Library/SubmissionReleaseView.axaml.cs
index 503c3cb87..de58a90f6 100644
--- a/src/Artemis.UI/Screens/Workshop/Library/SubmissionReleaseView.axaml.cs
+++ b/src/Artemis.UI/Screens/Workshop/Library/SubmissionReleaseView.axaml.cs
@@ -1,100 +1,11 @@
-using System.Linq;
-using Avalonia;
-using Avalonia.Controls;
-using Avalonia.Media;
-using Avalonia.Media.Immutable;
using Avalonia.ReactiveUI;
-using AvaloniaEdit.TextMate;
-using ReactiveUI;
-using TextMateSharp.Grammars;
-using VisualExtensions = Artemis.UI.Shared.Extensions.VisualExtensions;
namespace Artemis.UI.Screens.Workshop.Library;
public partial class SubmissionReleaseView : ReactiveUserControl
{
- private ScrollViewer? _editorScrollViewer;
- private ScrollViewer? _previewScrollViewer;
- private bool _updating;
-
public SubmissionReleaseView()
{
InitializeComponent();
-
- DescriptionEditor.Options.AllowScrollBelowDocument = false;
- RegistryOptions options = new(ThemeName.Dark);
- TextMate.Installation? install = DescriptionEditor.InstallTextMate(options);
-
- install.SetGrammar(options.GetScopeByExtension(".md"));
-
- this.WhenActivated(_ => SetupScrollSync());
- }
-
- protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
- {
- if (this.TryFindResource("SystemAccentColorLight3", out object? resource) && resource is Color color)
- DescriptionEditor.TextArea.TextView.LinkTextForegroundBrush = new ImmutableSolidColorBrush(color);
-
- base.OnAttachedToVisualTree(e);
- }
-
- private void SetupScrollSync()
- {
- if (_editorScrollViewer != null)
- _editorScrollViewer.PropertyChanged -= EditorScrollViewerOnPropertyChanged;
- if (_previewScrollViewer != null)
- _previewScrollViewer.PropertyChanged -= PreviewScrollViewerOnPropertyChanged;
-
- _editorScrollViewer = VisualExtensions.GetVisualChildrenOfType(DescriptionEditor).FirstOrDefault();
- _previewScrollViewer = VisualExtensions.GetVisualChildrenOfType(DescriptionPreview).FirstOrDefault();
-
- if (_editorScrollViewer != null)
- _editorScrollViewer.PropertyChanged += EditorScrollViewerOnPropertyChanged;
- if (_previewScrollViewer != null)
- _previewScrollViewer.PropertyChanged += PreviewScrollViewerOnPropertyChanged;
- }
-
- private void EditorScrollViewerOnPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e)
- {
- if (e.Property.Name != nameof(ScrollViewer.Offset) || _updating || SynchronizedScrolling.IsChecked != true)
- return;
-
- try
- {
- _updating = true;
- SynchronizeScrollViewers(_editorScrollViewer, _previewScrollViewer);
- }
- finally
- {
- _updating = false;
- }
- }
-
- private void PreviewScrollViewerOnPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e)
- {
- if (e.Property.Name != nameof(ScrollViewer.Offset) || _updating || SynchronizedScrolling.IsChecked != true)
- return;
-
- try
- {
- _updating = true;
- SynchronizeScrollViewers(_previewScrollViewer, _editorScrollViewer);
- }
- finally
- {
- _updating = false;
- }
- }
-
- private void SynchronizeScrollViewers(ScrollViewer? source, ScrollViewer? target)
- {
- if (source == null || target == null)
- return;
-
- double sourceScrollableHeight = source.Extent.Height - source.Viewport.Height;
- double targetScrollableHeight = target.Extent.Height - target.Viewport.Height;
-
- if (sourceScrollableHeight != 0)
- target.Offset = new Vector(target.Offset.X, targetScrollableHeight * (source.Offset.Y / sourceScrollableHeight));
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Workshop/Library/SubmissionReleaseViewModel.cs b/src/Artemis.UI/Screens/Workshop/Library/SubmissionReleaseViewModel.cs
index eb02f12b6..025d2ce5a 100644
--- a/src/Artemis.UI/Screens/Workshop/Library/SubmissionReleaseViewModel.cs
+++ b/src/Artemis.UI/Screens/Workshop/Library/SubmissionReleaseViewModel.cs
@@ -22,11 +22,10 @@ public partial class SubmissionReleaseViewModel : RoutableScreen _hasChanges;
[Notify] private IGetReleaseById_Release? _release;
- [Notify] private string _changelog = string.Empty;
- [Notify] private TextDocument? _markdownDocument;
+ [Notify] private string? _changelog;
+ [Notify] private bool _hasChanges;
public SubmissionReleaseViewModel(IWorkshopClient client, IRouter router, IWindowService windowService, INotificationService notificationService)
{
@@ -34,22 +33,12 @@ public SubmissionReleaseViewModel(IWorkshopClient client, IRouter router, IWindo
_router = router;
_windowService = windowService;
_notificationService = notificationService;
- _hasChanges = this.WhenAnyValue(vm => vm.Changelog, vm => vm.Release, (current, release) => current != release?.Changelog).ToProperty(this, vm => vm.HasChanges);
+ this.WhenAnyValue(vm => vm.Changelog, vm => vm.Release, (current, release) => current != release?.Changelog).Subscribe(hasChanges => HasChanges = hasChanges);
Discard = ReactiveCommand.Create(ExecuteDiscard, this.WhenAnyValue(vm => vm.HasChanges));
Save = ReactiveCommand.CreateFromTask(ExecuteSave, this.WhenAnyValue(vm => vm.HasChanges));
-
- this.WhenActivated(d =>
- {
- Disposable.Create(() =>
- {
- if (MarkdownDocument != null)
- MarkdownDocument.TextChanged -= MarkdownDocumentOnTextChanged;
- }).DisposeWith(d);
- });
}
- public bool HasChanges => _hasChanges.Value;
public ReactiveCommand Discard { get; set; }
public ReactiveCommand Save { get; set; }
@@ -57,9 +46,17 @@ public override async Task OnNavigating(ReleaseDetailParameters parameters, Navi
{
IOperationResult result = await _client.GetReleaseById.ExecuteAsync(parameters.ReleaseId, cancellationToken);
Release = result.Data?.Release;
- Changelog = Release?.Changelog ?? string.Empty;
+ Changelog = Release?.Changelog;
+ }
+
+ public override async Task OnClosing(NavigationArguments args)
+ {
+ if (!HasChanges)
+ return;
- SetupMarkdownDocument();
+ bool confirmed = await _windowService.ShowConfirmContentDialog("You have unsaved changes", "Do you want to discard your unsaved changes?");
+ if (!confirmed)
+ args.Cancel();
}
public async Task DeleteRelease()
@@ -81,6 +78,7 @@ public async Task DeleteRelease()
.WithHorizontalPosition(HorizontalAlignment.Left)
.Show();
+ HasChanges = false;
await Close();
}
@@ -100,25 +98,13 @@ private async Task ExecuteSave(CancellationToken cancellationToken)
.WithSeverity(NotificationSeverity.Success)
.WithHorizontalPosition(HorizontalAlignment.Left)
.Show();
- }
- private void ExecuteDiscard()
- {
- Changelog = Release?.Changelog ?? string.Empty;
- SetupMarkdownDocument();
+ HasChanges = false;
}
- private void SetupMarkdownDocument()
- {
- if (MarkdownDocument != null)
- MarkdownDocument.TextChanged -= MarkdownDocumentOnTextChanged;
-
- MarkdownDocument = new TextDocument(new StringTextSource(Changelog));
- MarkdownDocument.TextChanged += MarkdownDocumentOnTextChanged;
- }
-
- private void MarkdownDocumentOnTextChanged(object? sender, EventArgs e)
+ private void ExecuteDiscard()
{
- Changelog = MarkdownDocument?.Text ?? string.Empty;
+ Changelog = Release?.Changelog;
+ HasChanges = false;
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Workshop/Library/WorkshopLibraryViewModel.cs b/src/Artemis.UI/Screens/Workshop/Library/WorkshopLibraryViewModel.cs
index 413914803..af02fa985 100644
--- a/src/Artemis.UI/Screens/Workshop/Library/WorkshopLibraryViewModel.cs
+++ b/src/Artemis.UI/Screens/Workshop/Library/WorkshopLibraryViewModel.cs
@@ -53,7 +53,7 @@ public override async Task OnNavigating(NavigationArguments args, CancellationTo
public void GoBack()
{
if (ViewingDetails)
- _router.GoBack();
+ _router.Navigate("workshop/library/submissions");
else
_router.Navigate("workshop");
}
diff --git a/src/Artemis.UI/Screens/Workshop/Profile/ProfileDescriptionView.axaml b/src/Artemis.UI/Screens/Workshop/Profile/ProfileDescriptionView.axaml
index ff076cdb6..5b29dc430 100644
--- a/src/Artemis.UI/Screens/Workshop/Profile/ProfileDescriptionView.axaml
+++ b/src/Artemis.UI/Screens/Workshop/Profile/ProfileDescriptionView.axaml
@@ -9,7 +9,7 @@
x:DataType="profile:ProfileDescriptionViewModel">
-
+
diff --git a/src/Artemis.UI/Screens/Workshop/SubmissionWizard/Models/SubmissionWizardState.cs b/src/Artemis.UI/Screens/Workshop/SubmissionWizard/Models/SubmissionWizardState.cs
index c92f6290b..aaf688ef6 100644
--- a/src/Artemis.UI/Screens/Workshop/SubmissionWizard/Models/SubmissionWizardState.cs
+++ b/src/Artemis.UI/Screens/Workshop/SubmissionWizard/Models/SubmissionWizardState.cs
@@ -38,6 +38,7 @@ public SubmissionWizardState(IWorkshopWizardViewModel wizardViewModel, IContaine
public List Images { get; set; } = new();
public IEntrySource? EntrySource { get; set; }
+ public string? Changelog { get; set; }
public void ChangeScreen() where TSubmissionViewModel : SubmissionViewModel
{
diff --git a/src/Artemis.UI/Screens/Workshop/SubmissionWizard/Steps/ChangelogStepView.axaml b/src/Artemis.UI/Screens/Workshop/SubmissionWizard/Steps/ChangelogStepView.axaml
new file mode 100644
index 000000000..ff6ddd67d
--- /dev/null
+++ b/src/Artemis.UI/Screens/Workshop/SubmissionWizard/Steps/ChangelogStepView.axaml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+ Changelog
+
+ If you want to inform your users what has changed in this release, you can provide a changelog. This is optional but recommended.
+
+
+
+
+
+
diff --git a/src/Artemis.UI/Screens/Workshop/SubmissionWizard/Steps/ChangelogStepView.axaml.cs b/src/Artemis.UI/Screens/Workshop/SubmissionWizard/Steps/ChangelogStepView.axaml.cs
new file mode 100644
index 000000000..2733746f7
--- /dev/null
+++ b/src/Artemis.UI/Screens/Workshop/SubmissionWizard/Steps/ChangelogStepView.axaml.cs
@@ -0,0 +1,14 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+using Avalonia.ReactiveUI;
+
+namespace Artemis.UI.Screens.Workshop.SubmissionWizard.Steps;
+
+public partial class ChangelogStepView : ReactiveUserControl
+{
+ public ChangelogStepView()
+ {
+ InitializeComponent();
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Workshop/SubmissionWizard/Steps/ChangelogStepViewModel.cs b/src/Artemis.UI/Screens/Workshop/SubmissionWizard/Steps/ChangelogStepViewModel.cs
new file mode 100644
index 000000000..0333e5a56
--- /dev/null
+++ b/src/Artemis.UI/Screens/Workshop/SubmissionWizard/Steps/ChangelogStepViewModel.cs
@@ -0,0 +1,39 @@
+using System.Reactive.Disposables;
+using Artemis.UI.Screens.Workshop.SubmissionWizard.Steps.Layout;
+using Artemis.UI.Screens.Workshop.SubmissionWizard.Steps.Profile;
+using Artemis.WebClient.Workshop;
+using PropertyChanged.SourceGenerator;
+using ReactiveUI;
+
+namespace Artemis.UI.Screens.Workshop.SubmissionWizard.Steps;
+
+public partial class ChangelogStepViewModel : SubmissionViewModel
+{
+ [Notify] private string? _changelog;
+
+ public ChangelogStepViewModel()
+ {
+ GoBack = ReactiveCommand.Create(ExecuteGoBack);
+ Continue = ReactiveCommand.Create(ExecuteContinue);
+ ContinueText = "Submit";
+
+ this.WhenActivated((CompositeDisposable _) => Changelog = State.Changelog);
+ }
+
+ private void ExecuteContinue()
+ {
+ State.Changelog = Changelog;
+ State.ChangeScreen();
+ }
+
+ private void ExecuteGoBack()
+ {
+ State.Changelog = Changelog;
+ if (State.EntryType == EntryType.Layout)
+ State.ChangeScreen();
+ else if (State.EntryType == EntryType.Plugin)
+ State.ChangeScreen();
+ else if (State.EntryType == EntryType.Profile)
+ State.ChangeScreen();
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Workshop/SubmissionWizard/Steps/Layout/LayoutInfoStepViewModel.cs b/src/Artemis.UI/Screens/Workshop/SubmissionWizard/Steps/Layout/LayoutInfoStepViewModel.cs
index 23c3b293e..3ebe3b748 100644
--- a/src/Artemis.UI/Screens/Workshop/SubmissionWizard/Steps/Layout/LayoutInfoStepViewModel.cs
+++ b/src/Artemis.UI/Screens/Workshop/SubmissionWizard/Steps/Layout/LayoutInfoStepViewModel.cs
@@ -98,6 +98,6 @@ private void ExecuteContinue()
if (State.EntryId == null)
State.ChangeScreen();
else
- State.ChangeScreen();
+ State.ChangeScreen();
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Workshop/SubmissionWizard/Steps/Plugin/PluginSelectionStepViewModel.cs b/src/Artemis.UI/Screens/Workshop/SubmissionWizard/Steps/Plugin/PluginSelectionStepViewModel.cs
index 2d8cc45d9..4008c5f57 100644
--- a/src/Artemis.UI/Screens/Workshop/SubmissionWizard/Steps/Plugin/PluginSelectionStepViewModel.cs
+++ b/src/Artemis.UI/Screens/Workshop/SubmissionWizard/Steps/Plugin/PluginSelectionStepViewModel.cs
@@ -78,6 +78,6 @@ private void ExecuteContinue()
if (State.EntryId == null)
State.ChangeScreen();
else
- State.ChangeScreen();
+ State.ChangeScreen();
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Workshop/SubmissionWizard/Steps/Profile/ProfileAdaptionHintsStepViewModel.cs b/src/Artemis.UI/Screens/Workshop/SubmissionWizard/Steps/Profile/ProfileAdaptionHintsStepViewModel.cs
index 0e3556a96..87d7872dc 100644
--- a/src/Artemis.UI/Screens/Workshop/SubmissionWizard/Steps/Profile/ProfileAdaptionHintsStepViewModel.cs
+++ b/src/Artemis.UI/Screens/Workshop/SubmissionWizard/Steps/Profile/ProfileAdaptionHintsStepViewModel.cs
@@ -64,6 +64,6 @@ private void ExecuteContinue()
if (State.EntryId == null)
State.ChangeScreen();
else
- State.ChangeScreen();
+ State.ChangeScreen();
}
}
\ No newline at end of file
diff --git a/src/Artemis.UI/Screens/Workshop/SubmissionWizard/Steps/UploadStepViewModel.cs b/src/Artemis.UI/Screens/Workshop/SubmissionWizard/Steps/UploadStepViewModel.cs
index 81e464311..c205e24aa 100644
--- a/src/Artemis.UI/Screens/Workshop/SubmissionWizard/Steps/UploadStepViewModel.cs
+++ b/src/Artemis.UI/Screens/Workshop/SubmissionWizard/Steps/UploadStepViewModel.cs
@@ -70,7 +70,7 @@ private async Task ExecuteUpload(CancellationToken cancellationToken)
// Create a release for the new entry
IEntryUploadHandler uploadHandler = _entryUploadHandlerFactory.CreateHandler(State.EntryType);
- EntryUploadResult uploadResult = await uploadHandler.CreateReleaseAsync(_entryId.Value, State.EntrySource!, cancellationToken);
+ EntryUploadResult uploadResult = await uploadHandler.CreateReleaseAsync(_entryId.Value, State.EntrySource!, State.Changelog, cancellationToken);
if (!uploadResult.IsSuccess)
throw new ArtemisWorkshopException(uploadResult.Message);
diff --git a/src/Artemis.WebClient.Workshop/Handlers/UploadHandlers/IEntryUploadHandler.cs b/src/Artemis.WebClient.Workshop/Handlers/UploadHandlers/IEntryUploadHandler.cs
index c0bc829be..a25dc689b 100644
--- a/src/Artemis.WebClient.Workshop/Handlers/UploadHandlers/IEntryUploadHandler.cs
+++ b/src/Artemis.WebClient.Workshop/Handlers/UploadHandlers/IEntryUploadHandler.cs
@@ -1,8 +1,6 @@
-using Artemis.UI.Shared.Utilities;
-
-namespace Artemis.WebClient.Workshop.Handlers.UploadHandlers;
+namespace Artemis.WebClient.Workshop.Handlers.UploadHandlers;
public interface IEntryUploadHandler
{
- Task CreateReleaseAsync(long entryId, IEntrySource entrySource, CancellationToken cancellationToken);
+ Task CreateReleaseAsync(long entryId, IEntrySource entrySource, string? changelog, CancellationToken cancellationToken);
}
\ No newline at end of file
diff --git a/src/Artemis.WebClient.Workshop/Handlers/UploadHandlers/Implementations/LayoutEntryUploadHandler.cs b/src/Artemis.WebClient.Workshop/Handlers/UploadHandlers/Implementations/LayoutEntryUploadHandler.cs
index 38e2c9789..0ed8edfc6 100644
--- a/src/Artemis.WebClient.Workshop/Handlers/UploadHandlers/Implementations/LayoutEntryUploadHandler.cs
+++ b/src/Artemis.WebClient.Workshop/Handlers/UploadHandlers/Implementations/LayoutEntryUploadHandler.cs
@@ -18,7 +18,7 @@ public LayoutEntryUploadHandler(IHttpClientFactory httpClientFactory)
}
///
- public async Task CreateReleaseAsync(long entryId, IEntrySource entrySource, CancellationToken cancellationToken)
+ public async Task CreateReleaseAsync(long entryId, IEntrySource entrySource, string? changelog, CancellationToken cancellationToken)
{
if (entrySource is not LayoutEntrySource source)
throw new InvalidOperationException("Can only create releases for layouts");
@@ -62,6 +62,8 @@ public async Task CreateReleaseAsync(long entryId, IEntrySour
MultipartFormDataContent content = new();
StreamContent streamContent = new(archiveStream);
streamContent.Headers.ContentType = new MediaTypeHeaderValue("application/zip");
+ if (!string.IsNullOrWhiteSpace(changelog))
+ content.Add(new StringContent(changelog), "Changelog");
content.Add(streamContent, "file", "file.zip");
// Submit
diff --git a/src/Artemis.WebClient.Workshop/Handlers/UploadHandlers/Implementations/PluginEntryUploadHandler.cs b/src/Artemis.WebClient.Workshop/Handlers/UploadHandlers/Implementations/PluginEntryUploadHandler.cs
index f8c51034c..926f8485b 100644
--- a/src/Artemis.WebClient.Workshop/Handlers/UploadHandlers/Implementations/PluginEntryUploadHandler.cs
+++ b/src/Artemis.WebClient.Workshop/Handlers/UploadHandlers/Implementations/PluginEntryUploadHandler.cs
@@ -14,7 +14,7 @@ public PluginEntryUploadHandler(IHttpClientFactory httpClientFactory)
}
///
- public async Task CreateReleaseAsync(long entryId, IEntrySource entrySource, CancellationToken cancellationToken)
+ public async Task CreateReleaseAsync(long entryId, IEntrySource entrySource, string? changelog, CancellationToken cancellationToken)
{
if (entrySource is not PluginEntrySource source)
throw new InvalidOperationException("Can only create releases for plugins");
@@ -27,6 +27,8 @@ public async Task CreateReleaseAsync(long entryId, IEntrySour
MultipartFormDataContent content = new();
StreamContent streamContent = new(fileStream);
streamContent.Headers.ContentType = new MediaTypeHeaderValue("application/zip");
+ if (!string.IsNullOrWhiteSpace(changelog))
+ content.Add(new StringContent(changelog), "Changelog");
content.Add(streamContent, "file", "file.zip");
// Submit
diff --git a/src/Artemis.WebClient.Workshop/Handlers/UploadHandlers/Implementations/ProfileEntryUploadHandler.cs b/src/Artemis.WebClient.Workshop/Handlers/UploadHandlers/Implementations/ProfileEntryUploadHandler.cs
index 3dbbd68e9..381bd0199 100644
--- a/src/Artemis.WebClient.Workshop/Handlers/UploadHandlers/Implementations/ProfileEntryUploadHandler.cs
+++ b/src/Artemis.WebClient.Workshop/Handlers/UploadHandlers/Implementations/ProfileEntryUploadHandler.cs
@@ -17,7 +17,7 @@ public ProfileEntryUploadHandler(IHttpClientFactory httpClientFactory, IProfileS
}
///
- public async Task CreateReleaseAsync(long entryId, IEntrySource entrySource, CancellationToken cancellationToken)
+ public async Task CreateReleaseAsync(long entryId, IEntrySource entrySource, string? changelog, CancellationToken cancellationToken)
{
if (entrySource is not ProfileEntrySource source)
throw new InvalidOperationException("Can only create releases for profile configurations");
@@ -32,6 +32,8 @@ public async Task CreateReleaseAsync(long entryId, IEntrySour
StreamContent streamContent = new(archiveStream);
streamContent.Headers.ContentType = new MediaTypeHeaderValue("application/zip");
content.Add(JsonContent.Create(source.Dependencies.Select(d => new {PluginId = d.Plugin.Guid, FeatureId = d.Id}).ToList()), "ReleaseDependencies");
+ if (!string.IsNullOrWhiteSpace(changelog))
+ content.Add(new StringContent(changelog), "Changelog");
content.Add(streamContent, "file", "file.zip");
// Submit
diff --git a/src/Artemis.WebClient.Workshop/WorkshopConstants.cs b/src/Artemis.WebClient.Workshop/WorkshopConstants.cs
index 907ddb843..10807064c 100644
--- a/src/Artemis.WebClient.Workshop/WorkshopConstants.cs
+++ b/src/Artemis.WebClient.Workshop/WorkshopConstants.cs
@@ -2,10 +2,10 @@ 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";
+ // 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";
public const string IDENTITY_CLIENT_NAME = "IdentityApiClient";
public const string WORKSHOP_CLIENT_NAME = "WorkshopApiClient";
}
\ No newline at end of file