mirror of
https://github.com/Artemis-RGB/Artemis
synced 2026-11-12 11:56:30 +00:00
Workshop - Added dedicated release page
This commit is contained in:
1 parent
9c04932afa
commit
9e994840f6
36 files changed
+535
-190
No files matched your search
@@ -0,0 +1,35 @@
|
||||
<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:plugins="clr-namespace:Artemis.UI.Screens.Workshop.Plugins"
|
||||
xmlns:mdxaml="https://github.com/whistyun/Markdown.Avalonia.Tight"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.UI.Screens.Workshop.Plugins.PluginDescriptionView"
|
||||
x:DataType="plugins:PluginDescriptionViewModel">
|
||||
<StackPanel Spacing="10">
|
||||
<Border Classes="card">
|
||||
<mdxaml:MarkdownScrollViewer Markdown="{CompiledBinding Entry.Description}" MarkdownStyleName="FluentAvalonia">
|
||||
<mdxaml:MarkdownScrollViewer.Styles>
|
||||
<StyleInclude Source="/Styles/Markdown.axaml" />
|
||||
</mdxaml:MarkdownScrollViewer.Styles>
|
||||
</mdxaml:MarkdownScrollViewer>
|
||||
</Border>
|
||||
|
||||
<Border Classes="card" VerticalAlignment="Top" IsVisible="{CompiledBinding Dependants, Converter={x:Static ObjectConverters.IsNotNull}}">
|
||||
<StackPanel>
|
||||
<TextBlock Theme="{StaticResource SubtitleTextBlockStyle}">Used by these profiles</TextBlock>
|
||||
<Border Classes="card-separator" />
|
||||
<ScrollViewer>
|
||||
<ItemsControl ItemsSource="{CompiledBinding Dependants}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Spacing="5"></StackPanel>
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
</ItemsControl>
|
||||
</ScrollViewer>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,14 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Screens.Workshop.Plugins;
|
||||
|
||||
public partial class PluginDescriptionView : ReactiveUserControl<PluginDescriptionViewModel>
|
||||
{
|
||||
public PluginDescriptionView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Artemis.UI.Screens.Workshop.Entries.List;
|
||||
using Artemis.UI.Shared.Routing;
|
||||
using Artemis.WebClient.Workshop;
|
||||
using PropertyChanged.SourceGenerator;
|
||||
|
||||
namespace Artemis.UI.Screens.Workshop.Plugins;
|
||||
|
||||
public partial class PluginDescriptionViewModel : RoutableScreen
|
||||
{
|
||||
[Notify] private IEntryDetails? _entry;
|
||||
[Notify] private List<EntryListItemViewModel>? _dependants;
|
||||
private readonly IWorkshopClient _client;
|
||||
private readonly Func<IEntrySummary, EntryListItemViewModel> _getEntryListViewModel;
|
||||
|
||||
public PluginDescriptionViewModel(IWorkshopClient client, Func<IEntrySummary, EntryListItemViewModel> getEntryListViewModel)
|
||||
{
|
||||
_client = client;
|
||||
_getEntryListViewModel = getEntryListViewModel;
|
||||
}
|
||||
|
||||
public async Task SetEntry(IEntryDetails? entry, CancellationToken cancellationToken)
|
||||
{
|
||||
Entry = entry;
|
||||
|
||||
if (entry != null)
|
||||
{
|
||||
IReadOnlyList<IEntrySummary>? dependants = (await _client.GetDependantEntries.ExecuteAsync(entry.Id, 0, 25, cancellationToken)).Data?.Entries?.Items;
|
||||
Dependants = dependants != null && dependants.Any() ? dependants.Select(_getEntryListViewModel).OrderByDescending(d => d.Entry.Downloads).Take(10).ToList() : null;
|
||||
}
|
||||
else
|
||||
{
|
||||
Dependants = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,8 @@
|
||||
xmlns:mdxaml="https://github.com/whistyun/Markdown.Avalonia.Tight"
|
||||
xmlns:plugins="clr-namespace:Artemis.UI.Screens.Workshop.Plugins"
|
||||
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||
xmlns:controls="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||
xmlns:ui="clr-namespace:Artemis.UI"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:Class="Artemis.UI.Screens.Workshop.Plugins.PluginDetailsView"
|
||||
x:DataType="plugins:PluginDetailsViewModel">
|
||||
@@ -35,31 +37,11 @@
|
||||
</StackPanel>
|
||||
|
||||
<ScrollViewer Grid.Row="1" Grid.Column="1">
|
||||
<StackPanel Margin="10 0" Spacing="10">
|
||||
<Border Classes="card">
|
||||
<mdxaml:MarkdownScrollViewer Markdown="{CompiledBinding Entry.Description}" MarkdownStyleName="FluentAvalonia">
|
||||
<mdxaml:MarkdownScrollViewer.Styles>
|
||||
<StyleInclude Source="/Styles/Markdown.axaml" />
|
||||
</mdxaml:MarkdownScrollViewer.Styles>
|
||||
</mdxaml:MarkdownScrollViewer>
|
||||
</Border>
|
||||
|
||||
<Border Classes="card" VerticalAlignment="Top" IsVisible="{CompiledBinding Dependants, Converter={x:Static ObjectConverters.IsNotNull}}">
|
||||
<StackPanel>
|
||||
<TextBlock Theme="{StaticResource SubtitleTextBlockStyle}">Used by these profiles</TextBlock>
|
||||
<Border Classes="card-separator" />
|
||||
<ScrollViewer>
|
||||
<ItemsControl ItemsSource="{CompiledBinding Dependants}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Spacing="5"></StackPanel>
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
</ItemsControl>
|
||||
</ScrollViewer>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
<controls:Frame Name="RouterFrame" IsNavigationStackEnabled="False" CacheSize="0" Margin="10 0">
|
||||
<controls:Frame.NavigationPageFactory>
|
||||
<ui:PageFactory />
|
||||
</controls:Frame.NavigationPageFactory>
|
||||
</controls:Frame>
|
||||
</ScrollViewer>
|
||||
|
||||
<ContentControl Grid.Row="1" Grid.Column="2" IsVisible="{CompiledBinding Entry.Images.Count}" Content="{CompiledBinding EntryImagesViewModel}" />
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using System;
|
||||
using System.Reactive.Disposables;
|
||||
using Avalonia.ReactiveUI;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Screens.Workshop.Plugins;
|
||||
|
||||
@@ -7,5 +10,8 @@ public partial class PluginDetailsView : ReactiveUserControl<PluginDetailsViewMo
|
||||
public PluginDetailsView()
|
||||
{
|
||||
InitializeComponent();
|
||||
this.WhenActivated(d => ViewModel.WhenAnyValue(vm => vm.Screen)
|
||||
.Subscribe(screen => RouterFrame.NavigateFromObject(screen ?? ViewModel?.PluginDescriptionViewModel))
|
||||
.DisposeWith(d));
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,7 @@ using StrawberryShake;
|
||||
|
||||
namespace Artemis.UI.Screens.Workshop.Plugins;
|
||||
|
||||
public partial class PluginDetailsViewModel : RoutableScreen<WorkshopDetailParameters>
|
||||
public partial class PluginDetailsViewModel : RoutableHostScreen<RoutableScreen, WorkshopDetailParameters>
|
||||
{
|
||||
private readonly IWorkshopClient _client;
|
||||
private readonly IWindowService _windowService;
|
||||
@@ -27,7 +27,6 @@ public partial class PluginDetailsViewModel : RoutableScreen<WorkshopDetailParam
|
||||
private readonly Func<IEntryDetails, EntryInfoViewModel> _getEntryInfoViewModel;
|
||||
private readonly Func<IEntryDetails, EntryReleasesViewModel> _getEntryReleasesViewModel;
|
||||
private readonly Func<IEntryDetails, EntryImagesViewModel> _getEntryImagesViewModel;
|
||||
private readonly Func<IEntrySummary, EntryListItemViewModel> _getEntryListViewModel;
|
||||
[Notify] private IGetPluginEntryById_Entry? _entry;
|
||||
[Notify] private EntryInfoViewModel? _entryInfoViewModel;
|
||||
[Notify] private EntryReleasesViewModel? _entryReleasesViewModel;
|
||||
@@ -37,23 +36,26 @@ public partial class PluginDetailsViewModel : RoutableScreen<WorkshopDetailParam
|
||||
public PluginDetailsViewModel(IWorkshopClient client,
|
||||
IWindowService windowService,
|
||||
IPluginManagementService pluginManagementService,
|
||||
PluginDescriptionViewModel pluginDescriptionViewModel,
|
||||
Func<IEntryDetails, EntryInfoViewModel> getEntryInfoViewModel,
|
||||
Func<IEntryDetails, EntryReleasesViewModel> getEntryReleasesViewModel,
|
||||
Func<IEntryDetails, EntryImagesViewModel> getEntryImagesViewModel,
|
||||
Func<IEntrySummary, EntryListItemViewModel> getEntryListViewModel)
|
||||
Func<IEntryDetails, EntryImagesViewModel> getEntryImagesViewModel)
|
||||
{
|
||||
PluginDescriptionViewModel = pluginDescriptionViewModel;
|
||||
_client = client;
|
||||
_windowService = windowService;
|
||||
_pluginManagementService = pluginManagementService;
|
||||
_getEntryInfoViewModel = getEntryInfoViewModel;
|
||||
_getEntryReleasesViewModel = getEntryReleasesViewModel;
|
||||
_getEntryImagesViewModel = getEntryImagesViewModel;
|
||||
_getEntryListViewModel = getEntryListViewModel;
|
||||
}
|
||||
|
||||
public PluginDescriptionViewModel PluginDescriptionViewModel { get; }
|
||||
|
||||
public override async Task OnNavigating(WorkshopDetailParameters parameters, NavigationArguments args, CancellationToken cancellationToken)
|
||||
{
|
||||
await GetEntry(parameters.EntryId, cancellationToken);
|
||||
if (Entry?.Id != parameters.EntryId)
|
||||
await GetEntry(parameters.EntryId, cancellationToken);
|
||||
}
|
||||
|
||||
private async Task GetEntry(long entryId, CancellationToken cancellationToken)
|
||||
@@ -73,13 +75,7 @@ public partial class PluginDetailsViewModel : RoutableScreen<WorkshopDetailParam
|
||||
EntryReleasesViewModel.OnInstallationFinished = OnInstallationFinished;
|
||||
}
|
||||
|
||||
IReadOnlyList<IEntrySummary>? dependants = (await _client.GetDependantEntries.ExecuteAsync(entryId, 0, 25, cancellationToken)).Data?.Entries?.Items;
|
||||
Dependants = dependants != null && dependants.Any()
|
||||
? new ReadOnlyObservableCollection<EntryListItemViewModel>(new ObservableCollection<EntryListItemViewModel>(dependants
|
||||
.Select(_getEntryListViewModel)
|
||||
.OrderByDescending(d => d.Entry.Downloads)
|
||||
.Take(10)))
|
||||
: null;
|
||||
await PluginDescriptionViewModel.SetEntry(Entry, cancellationToken);
|
||||
}
|
||||
|
||||
private async Task<bool> OnInstallationStarted(IEntryDetails entryDetails, IRelease release)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Reactive.Disposables;
|
||||
using Artemis.UI.Shared.Routing;
|
||||
using Avalonia.ReactiveUI;
|
||||
using ReactiveUI;
|
||||
|
||||
@@ -11,14 +10,8 @@ public partial class PluginListView : ReactiveUserControl<PluginListViewModel>
|
||||
public PluginListView()
|
||||
{
|
||||
InitializeComponent();
|
||||
this.WhenActivated(d =>
|
||||
{
|
||||
ViewModel.WhenAnyValue(vm => vm.Screen).Subscribe(Navigate).DisposeWith(d);
|
||||
});
|
||||
}
|
||||
|
||||
private void Navigate(RoutableScreen? viewModel)
|
||||
{
|
||||
RouterFrame.NavigateFromObject(viewModel ?? ViewModel?.EntryListViewModel);
|
||||
this.WhenActivated(d => ViewModel.WhenAnyValue(vm => vm.Screen)
|
||||
.Subscribe(screen => RouterFrame.NavigateFromObject(screen ?? ViewModel?.EntryListViewModel))
|
||||
.DisposeWith(d));
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user