mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-12 21:38:38 +00:00
Workshop - Refactor markdown editor
Workshop - Add changelog during upload
This commit is contained in:
parent
62057d657a
commit
7b71ee05da
51
src/Artemis.UI/Controls/SplitMarkdownEditor.axaml
Normal file
51
src/Artemis.UI/Controls/SplitMarkdownEditor.axaml
Normal file
@ -0,0 +1,51 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:avaloniaEdit="https://github.com/avaloniaui/avaloniaedit"
|
||||
xmlns:mdxaml="https://github.com/whistyun/Markdown.Avalonia.Tight"
|
||||
xmlns:fa="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.UI.Controls.SplitMarkdownEditor">
|
||||
<Grid RowDefinitions="Auto,*">
|
||||
<Grid Row="0" ColumnDefinitions="Auto,*">
|
||||
<Label Grid.Column="0" Name="DescriptionEditorLabel" Target="DescriptionEditor" Margin="0 28 0 0" />
|
||||
<StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Right">
|
||||
<CheckBox Name="SynchronizedScrolling" IsChecked="True" VerticalAlignment="Bottom">Synchronized scrolling</CheckBox>
|
||||
<fa: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="1" Grid.Column="0" ColumnDefinitions="*,Auto,*">
|
||||
<Border Grid.Column="0" BorderThickness="1"
|
||||
BorderBrush="{DynamicResource TextControlBorderBrush}"
|
||||
CornerRadius="{DynamicResource ControlCornerRadius}"
|
||||
Background="{DynamicResource TextControlBackground}"
|
||||
Padding="{DynamicResource TextControlThemePadding}">
|
||||
<avaloniaEdit:TextEditor
|
||||
FontFamily="{StaticResource RobotoMono}"
|
||||
FontSize="13"
|
||||
Name="DescriptionEditor"
|
||||
TextChanged="DescriptionEditor_OnTextChanged"
|
||||
WordWrap="True" />
|
||||
</Border>
|
||||
|
||||
<GridSplitter Grid.Column="1" Margin="5 0"></GridSplitter>
|
||||
<Border Grid.Column="2" Classes="card-condensed">
|
||||
<mdxaml:MarkdownScrollViewer Margin="5 0"
|
||||
Name="DescriptionPreview"
|
||||
Markdown="{CompiledBinding Document.Text, Mode=OneWay, ElementName=DescriptionEditor}"
|
||||
MarkdownStyleName="FluentAvalonia"
|
||||
SaveScrollValueWhenContentUpdated="True">
|
||||
<mdxaml:MarkdownScrollViewer.Styles>
|
||||
<StyleInclude Source="/Styles/Markdown.axaml" />
|
||||
</mdxaml:MarkdownScrollViewer.Styles>
|
||||
</mdxaml:MarkdownScrollViewer>
|
||||
</Border>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
150
src/Artemis.UI/Controls/SplitMarkdownEditor.axaml.cs
Normal file
150
src/Artemis.UI/Controls/SplitMarkdownEditor.axaml.cs
Normal file
@ -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<string> TitleProperty = AvaloniaProperty.Register<SplitMarkdownEditor, string>(nameof(Title), string.Empty);
|
||||
public static readonly StyledProperty<string> MarkdownProperty = AvaloniaProperty.Register<SplitMarkdownEditor, string>(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<ScrollViewer>(DescriptionEditor).FirstOrDefault();
|
||||
_previewScrollViewer = VisualExtensions.GetVisualChildrenOfType<ScrollViewer>(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;
|
||||
}
|
||||
}
|
||||
@ -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">
|
||||
<Grid RowDefinitions="Auto,Auto,*,Auto">
|
||||
<Grid RowDefinitions="Auto,*,Auto">
|
||||
<StackPanel>
|
||||
<StackPanel.Styles>
|
||||
<Styles>
|
||||
@ -95,48 +92,9 @@
|
||||
<tagsInput:TagsInput Tags="{CompiledBinding Tags}" />
|
||||
</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,*">
|
||||
<Border Grid.Column="0" BorderThickness="1"
|
||||
BorderBrush="{DynamicResource TextControlBorderBrush}"
|
||||
CornerRadius="{DynamicResource ControlCornerRadius}"
|
||||
Background="{DynamicResource TextControlBackground}"
|
||||
Padding="{DynamicResource TextControlThemePadding}">
|
||||
<avaloniaEdit:TextEditor
|
||||
FontFamily="{StaticResource RobotoMono}"
|
||||
FontSize="13"
|
||||
Name="DescriptionEditor"
|
||||
Document="{CompiledBinding MarkdownDocument}"
|
||||
WordWrap="True" />
|
||||
</Border>
|
||||
|
||||
<GridSplitter Grid.Column="1" Margin="5 0"></GridSplitter>
|
||||
<Border Grid.Column="2" Classes="card-condensed">
|
||||
<mdxaml:MarkdownScrollViewer Margin="5 0"
|
||||
Name="DescriptionPreview"
|
||||
Markdown="{CompiledBinding Description}"
|
||||
MarkdownStyleName="FluentAvalonia"
|
||||
SaveScrollValueWhenContentUpdated="True">
|
||||
<mdxaml:MarkdownScrollViewer.Styles>
|
||||
<StyleInclude Source="/Styles/Markdown.axaml" />
|
||||
</mdxaml:MarkdownScrollViewer.Styles>
|
||||
</mdxaml:MarkdownScrollViewer>
|
||||
</Border>
|
||||
</Grid>
|
||||
<controls:SplitMarkdownEditor Grid.Row="1" Title="Description" Markdown="{CompiledBinding Description}"/>
|
||||
|
||||
<TextBlock Grid.Row="3"
|
||||
<TextBlock Grid.Row="2"
|
||||
Foreground="{DynamicResource SystemFillColorCriticalBrush}"
|
||||
Margin="2 8 0 0"
|
||||
IsVisible="{CompiledBinding !DescriptionValid}">
|
||||
|
||||
@ -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<EntrySpecificationsViewModel>
|
||||
{
|
||||
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<ScrollViewer>(DescriptionEditor).FirstOrDefault();
|
||||
_previewScrollViewer = VisualExtensions.GetVisualChildrenOfType<ScrollViewer>(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));
|
||||
}
|
||||
}
|
||||
@ -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 partial class EntrySpecificationsViewModel : ValidatableViewModelBase
|
||||
{
|
||||
// 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 partial class EntrySpecificationsViewModel : ValidatableViewModelBase
|
||||
public bool DescriptionValid => _descriptionValid.Value;
|
||||
|
||||
public List<long> 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()
|
||||
|
||||
@ -36,6 +36,8 @@ public partial class SubmissionManagementViewModel : RoutableHostScreen<Routable
|
||||
_windowService = windowService;
|
||||
_workshopService = workshopService;
|
||||
|
||||
RecycleScreen = false;
|
||||
|
||||
this.WhenActivated(d =>
|
||||
{
|
||||
this.WhenAnyValue(vm => vm.SelectedRelease)
|
||||
|
||||
@ -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">
|
||||
<Grid RowDefinitions="Auto,Auto,*,Auto">
|
||||
<Grid RowDefinitions="Auto,*,Auto">
|
||||
<StackPanel Grid.Row="0" Orientation="Horizontal" Spacing="5">
|
||||
<Button VerticalAlignment="Center" Classes="icon-button" Command="{CompiledBinding Close}">
|
||||
<avalonia:MaterialIcon Kind="ArrowBack" />
|
||||
@ -18,47 +16,9 @@
|
||||
<TextBlock Classes="h3 no-margin" Text="{CompiledBinding Release.Version}" />
|
||||
</StackPanel>
|
||||
|
||||
<Grid Row="1" ColumnDefinitions="Auto,*">
|
||||
<Label Grid.Column="0" Target="DescriptionEditor" Margin="0 28 0 0">Changelog</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" Grid.Column="0" ColumnDefinitions="*,Auto,*">
|
||||
<Border Grid.Column="0" BorderThickness="1"
|
||||
BorderBrush="{DynamicResource TextControlBorderBrush}"
|
||||
CornerRadius="{DynamicResource ControlCornerRadius}"
|
||||
Background="{DynamicResource TextControlBackground}"
|
||||
Padding="{DynamicResource TextControlThemePadding}">
|
||||
<avaloniaEdit:TextEditor
|
||||
FontFamily="{StaticResource RobotoMono}"
|
||||
FontSize="13"
|
||||
Name="DescriptionEditor"
|
||||
Document="{CompiledBinding MarkdownDocument}"
|
||||
WordWrap="True" />
|
||||
</Border>
|
||||
|
||||
<GridSplitter Grid.Column="1" Margin="5 0"></GridSplitter>
|
||||
<Border Grid.Column="2" Classes="card-condensed">
|
||||
<mdxaml:MarkdownScrollViewer Margin="5 0"
|
||||
Name="DescriptionPreview"
|
||||
Markdown="{CompiledBinding Changelog}"
|
||||
MarkdownStyleName="FluentAvalonia"
|
||||
SaveScrollValueWhenContentUpdated="True">
|
||||
<mdxaml:MarkdownScrollViewer.Styles>
|
||||
<StyleInclude Source="/Styles/Markdown.axaml" />
|
||||
</mdxaml:MarkdownScrollViewer.Styles>
|
||||
</mdxaml:MarkdownScrollViewer>
|
||||
</Border>
|
||||
</Grid>
|
||||
|
||||
<StackPanel Grid.Row="3" Margin="0 10 0 0" Orientation="Horizontal" Spacing="5" HorizontalAlignment="Right">
|
||||
<controls1:SplitMarkdownEditor Grid.Row="1" Title="Changelog" Markdown="{CompiledBinding Changelog}"/>
|
||||
|
||||
<StackPanel Grid.Row="2" Margin="0 10 0 0" Orientation="Horizontal" Spacing="5" HorizontalAlignment="Right">
|
||||
<Button Classes="danger" Command="{CompiledBinding DeleteRelease}">Delete release</Button>
|
||||
<Button Command="{CompiledBinding Discard}">Discard changes</Button>
|
||||
<Button Command="{CompiledBinding Save}">Save</Button>
|
||||
|
||||
@ -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<SubmissionReleaseViewModel>
|
||||
{
|
||||
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<ScrollViewer>(DescriptionEditor).FirstOrDefault();
|
||||
_previewScrollViewer = VisualExtensions.GetVisualChildrenOfType<ScrollViewer>(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));
|
||||
}
|
||||
}
|
||||
@ -22,11 +22,10 @@ public partial class SubmissionReleaseViewModel : RoutableScreen<ReleaseDetailPa
|
||||
private readonly IRouter _router;
|
||||
private readonly IWindowService _windowService;
|
||||
private readonly INotificationService _notificationService;
|
||||
private readonly ObservableAsPropertyHelper<bool> _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 partial class SubmissionReleaseViewModel : RoutableScreen<ReleaseDetailPa
|
||||
_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<Unit, Unit> Discard { get; set; }
|
||||
public ReactiveCommand<Unit, Unit> Save { get; set; }
|
||||
|
||||
@ -57,9 +46,17 @@ public partial class SubmissionReleaseViewModel : RoutableScreen<ReleaseDetailPa
|
||||
{
|
||||
IOperationResult<IGetReleaseByIdResult> 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 partial class SubmissionReleaseViewModel : RoutableScreen<ReleaseDetailPa
|
||||
.WithHorizontalPosition(HorizontalAlignment.Left)
|
||||
.Show();
|
||||
|
||||
HasChanges = false;
|
||||
await Close();
|
||||
}
|
||||
|
||||
@ -100,25 +98,13 @@ public partial class SubmissionReleaseViewModel : RoutableScreen<ReleaseDetailPa
|
||||
.WithSeverity(NotificationSeverity.Success)
|
||||
.WithHorizontalPosition(HorizontalAlignment.Left)
|
||||
.Show();
|
||||
|
||||
HasChanges = false;
|
||||
}
|
||||
|
||||
private void ExecuteDiscard()
|
||||
{
|
||||
Changelog = Release?.Changelog ?? string.Empty;
|
||||
SetupMarkdownDocument();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
Changelog = MarkdownDocument?.Text ?? string.Empty;
|
||||
Changelog = Release?.Changelog;
|
||||
HasChanges = false;
|
||||
}
|
||||
}
|
||||
@ -53,7 +53,7 @@ public partial class WorkshopLibraryViewModel : RoutableHostScreen<RoutableScree
|
||||
public void GoBack()
|
||||
{
|
||||
if (ViewingDetails)
|
||||
_router.GoBack();
|
||||
_router.Navigate("workshop/library/submissions");
|
||||
else
|
||||
_router.Navigate("workshop");
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
x:DataType="profile:ProfileDescriptionViewModel">
|
||||
<StackPanel Spacing="10">
|
||||
<Border Classes="card">
|
||||
<mdxaml:MarkdownScrollViewer Markdown="{CompiledBinding Entry.Description}" MarkdownStyleName="FluentAvalonia">
|
||||
<mdxaml:MarkdownScrollViewer Markdown="{CompiledBinding Entry.Description}" MarkdownStyleName="FluentAvalonia" Name="MarkdownScrollViewer" >
|
||||
<mdxaml:MarkdownScrollViewer.Styles>
|
||||
<StyleInclude Source="/Styles/Markdown.axaml" />
|
||||
</mdxaml:MarkdownScrollViewer.Styles>
|
||||
|
||||
@ -38,6 +38,7 @@ public class SubmissionWizardState : IDisposable
|
||||
public List<ImageUploadRequest> Images { get; set; } = new();
|
||||
|
||||
public IEntrySource? EntrySource { get; set; }
|
||||
public string? Changelog { get; set; }
|
||||
|
||||
public void ChangeScreen<TSubmissionViewModel>() where TSubmissionViewModel : SubmissionViewModel
|
||||
{
|
||||
|
||||
@ -0,0 +1,27 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:controls="clr-namespace:Artemis.UI.Controls"
|
||||
xmlns:steps="clr-namespace:Artemis.UI.Screens.Workshop.SubmissionWizard.Steps"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.UI.Screens.Workshop.SubmissionWizard.Steps.ChangelogStepView"
|
||||
x:DataType="steps:ChangelogStepViewModel">
|
||||
<Grid RowDefinitions="Auto,*">
|
||||
<StackPanel Grid.Row="0">
|
||||
<StackPanel.Styles>
|
||||
<Styles>
|
||||
<Style Selector="TextBlock">
|
||||
<Setter Property="TextWrapping" Value="Wrap"></Setter>
|
||||
</Style>
|
||||
</Styles>
|
||||
</StackPanel.Styles>
|
||||
<TextBlock Theme="{StaticResource TitleTextBlockStyle}" TextWrapping="Wrap">Changelog</TextBlock>
|
||||
<TextBlock TextWrapping="Wrap">
|
||||
If you want to inform your users what has changed in this release, you can provide a changelog. This is optional but recommended.
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
|
||||
<controls:SplitMarkdownEditor Grid.Row="1" Markdown="{CompiledBinding Changelog}"/>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@ -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<ChangelogStepViewModel>
|
||||
{
|
||||
public ChangelogStepView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
@ -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<UploadStepViewModel>();
|
||||
}
|
||||
|
||||
private void ExecuteGoBack()
|
||||
{
|
||||
State.Changelog = Changelog;
|
||||
if (State.EntryType == EntryType.Layout)
|
||||
State.ChangeScreen<LayoutInfoStepViewModel>();
|
||||
else if (State.EntryType == EntryType.Plugin)
|
||||
State.ChangeScreen<SpecificationsStepViewModel>();
|
||||
else if (State.EntryType == EntryType.Profile)
|
||||
State.ChangeScreen<ProfileAdaptionHintsStepViewModel>();
|
||||
}
|
||||
}
|
||||
@ -98,6 +98,6 @@ public partial class LayoutInfoStepViewModel : SubmissionViewModel
|
||||
if (State.EntryId == null)
|
||||
State.ChangeScreen<SpecificationsStepViewModel>();
|
||||
else
|
||||
State.ChangeScreen<UploadStepViewModel>();
|
||||
State.ChangeScreen<ChangelogStepViewModel>();
|
||||
}
|
||||
}
|
||||
@ -78,6 +78,6 @@ public partial class PluginSelectionStepViewModel : SubmissionViewModel
|
||||
if (State.EntryId == null)
|
||||
State.ChangeScreen<SpecificationsStepViewModel>();
|
||||
else
|
||||
State.ChangeScreen<UploadStepViewModel>();
|
||||
State.ChangeScreen<ChangelogStepViewModel>();
|
||||
}
|
||||
}
|
||||
@ -64,6 +64,6 @@ public class ProfileAdaptionHintsStepViewModel : SubmissionViewModel
|
||||
if (State.EntryId == null)
|
||||
State.ChangeScreen<SpecificationsStepViewModel>();
|
||||
else
|
||||
State.ChangeScreen<UploadStepViewModel>();
|
||||
State.ChangeScreen<ChangelogStepViewModel>();
|
||||
}
|
||||
}
|
||||
@ -70,7 +70,7 @@ public partial class UploadStepViewModel : SubmissionViewModel
|
||||
|
||||
// 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);
|
||||
|
||||
|
||||
@ -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<EntryUploadResult> CreateReleaseAsync(long entryId, IEntrySource entrySource, CancellationToken cancellationToken);
|
||||
Task<EntryUploadResult> CreateReleaseAsync(long entryId, IEntrySource entrySource, string? changelog, CancellationToken cancellationToken);
|
||||
}
|
||||
@ -18,7 +18,7 @@ public class LayoutEntryUploadHandler : IEntryUploadHandler
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<EntryUploadResult> CreateReleaseAsync(long entryId, IEntrySource entrySource, CancellationToken cancellationToken)
|
||||
public async Task<EntryUploadResult> 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 class LayoutEntryUploadHandler : IEntryUploadHandler
|
||||
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
|
||||
|
||||
@ -14,7 +14,7 @@ public class PluginEntryUploadHandler : IEntryUploadHandler
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<EntryUploadResult> CreateReleaseAsync(long entryId, IEntrySource entrySource, CancellationToken cancellationToken)
|
||||
public async Task<EntryUploadResult> 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 class PluginEntryUploadHandler : IEntryUploadHandler
|
||||
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
|
||||
|
||||
@ -17,7 +17,7 @@ public class ProfileEntryUploadHandler : IEntryUploadHandler
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<EntryUploadResult> CreateReleaseAsync(long entryId, IEntrySource entrySource, CancellationToken cancellationToken)
|
||||
public async Task<EntryUploadResult> 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 class ProfileEntryUploadHandler : IEntryUploadHandler
|
||||
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
|
||||
|
||||
@ -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";
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user