mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-12 13:28:33 +00:00
Workshop - Fix library virtualization
Workshop - Tweak screenshots scaling
This commit is contained in:
parent
28edabae89
commit
8b4b5d8810
@ -14,7 +14,7 @@
|
||||
<TextBlock Text="Current layout" />
|
||||
<TextBlock Classes="subtitle" FontSize="12" Text="Loading the layout from a workshop entry" TextWrapping="Wrap" />
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Row="1" Grid.Column="1" VerticalAlignment="Center">
|
||||
<StackPanel Grid.Row="1" Grid.Column="1" VerticalAlignment="Center" Spacing="5">
|
||||
<StackPanel.Styles>
|
||||
<Style Selector="ComboBox.layoutProvider /template/ ContentControl#ContentPresenter">
|
||||
<Setter Property="ContentTemplate">
|
||||
@ -40,6 +40,7 @@
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
<Button HorizontalAlignment="Right" Click="Button_OnClick">Browse workshop layouts</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
using System.Threading.Tasks;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.ReactiveUI;
|
||||
|
||||
namespace Artemis.UI.Screens.Device.Layout.LayoutProviders;
|
||||
@ -9,4 +11,10 @@ public partial class WorkshopLayoutView : ReactiveUserControl<WorkshopLayoutView
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private async void Button_OnClick(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (ViewModel != null && await ViewModel.BrowseLayouts())
|
||||
(VisualRoot as Window)?.Close();
|
||||
}
|
||||
}
|
||||
@ -2,10 +2,13 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Reactive.Disposables;
|
||||
using System.Threading.Tasks;
|
||||
using Artemis.Core;
|
||||
using Artemis.Core.Providers;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.UI.Shared;
|
||||
using Artemis.UI.Shared.Routing;
|
||||
using Artemis.UI.Shared.Services;
|
||||
using Artemis.WebClient.Workshop;
|
||||
using Artemis.WebClient.Workshop.Providers;
|
||||
using Artemis.WebClient.Workshop.Services;
|
||||
@ -19,11 +22,16 @@ public partial class WorkshopLayoutViewModel : ActivatableViewModelBase, ILayout
|
||||
[Notify] private InstalledEntry? _selectedEntry;
|
||||
private readonly WorkshopLayoutProvider _layoutProvider;
|
||||
private readonly IDeviceService _deviceService;
|
||||
private readonly IWindowService _windowService;
|
||||
private readonly IRouter _router;
|
||||
|
||||
public WorkshopLayoutViewModel(WorkshopLayoutProvider layoutProvider, IWorkshopService workshopService, IDeviceService deviceService)
|
||||
public WorkshopLayoutViewModel(WorkshopLayoutProvider layoutProvider, IWorkshopService workshopService, IDeviceService deviceService, IWindowService windowService, IRouter router)
|
||||
{
|
||||
_layoutProvider = layoutProvider;
|
||||
_deviceService = deviceService;
|
||||
_windowService = windowService;
|
||||
_router = router;
|
||||
|
||||
Entries = new ObservableCollection<InstalledEntry>(workshopService.GetInstalledEntries().Where(e => e.EntryType == EntryType.Layout));
|
||||
|
||||
this.WhenAnyValue(vm => vm.SelectedEntry).Subscribe(ApplyEntry);
|
||||
@ -50,6 +58,15 @@ public partial class WorkshopLayoutViewModel : ActivatableViewModelBase, ILayout
|
||||
Save();
|
||||
}
|
||||
|
||||
public async Task<bool> BrowseLayouts()
|
||||
{
|
||||
if (!await _windowService.ShowConfirmContentDialog("Open workshop", "Do you want to close this window and view the workshop?"))
|
||||
return false;
|
||||
|
||||
await _router.Navigate("workshop/entries/layouts/1");
|
||||
return true;
|
||||
}
|
||||
|
||||
private void ApplyEntry(InstalledEntry? entry)
|
||||
{
|
||||
if (entry == null || Device.LayoutSelection.Parameter == entry.EntryId.ToString())
|
||||
|
||||
@ -8,13 +8,9 @@
|
||||
x:Class="Artemis.UI.Screens.Workshop.Entries.Details.EntryImageView"
|
||||
x:DataType="details:EntryImageViewModel">
|
||||
<Border Classes="card" Padding="0">
|
||||
<Grid RowDefinitions="230,*">
|
||||
<Grid RowDefinitions="Auto,*">
|
||||
<Border Grid.Row="0" ClipToBounds="True" CornerRadius="4 4 0 0" Padding="0">
|
||||
<Rectangle RenderOptions.BitmapInterpolationMode="HighQuality">
|
||||
<Rectangle.Fill>
|
||||
<ImageBrush asyncImageLoader:ImageBrushLoader.Source="{CompiledBinding ThumbnailUrl}" Stretch="UniformToFill" />
|
||||
</Rectangle.Fill>
|
||||
</Rectangle>
|
||||
<Image asyncImageLoader:ImageLoader.Source="{CompiledBinding ThumbnailUrl}" Stretch="Uniform" HorizontalAlignment="Stretch" MaxHeight="250" />
|
||||
</Border>
|
||||
<Border Grid.Row="1" ClipToBounds="True" CornerRadius="0 0 4 4" Background="{DynamicResource ControlFillColorDefaultBrush}">
|
||||
<StackPanel Margin="16">
|
||||
|
||||
@ -8,5 +8,5 @@
|
||||
x:Class="Artemis.UI.Screens.Workshop.Entries.Details.EntryImagesDialogView"
|
||||
x:DataType="details:EntryImagesDialogViewModel"
|
||||
Margin="-25 -63 -25 -25">
|
||||
<Image asyncImageLoader:ImageLoader.Source="{CompiledBinding CurrentImage.Url}" Stretch="None"/>
|
||||
<Image asyncImageLoader:ImageLoader.Source="{CompiledBinding CurrentImage.Url}" Stretch="Uniform"/>
|
||||
</UserControl>
|
||||
|
||||
@ -8,6 +8,7 @@ using Artemis.UI.Shared.Services.Builders;
|
||||
using Artemis.UI.Shared.Utilities;
|
||||
using Artemis.WebClient.Workshop;
|
||||
using Artemis.WebClient.Workshop.Handlers.InstallationHandlers;
|
||||
using Artemis.WebClient.Workshop.Services;
|
||||
using Humanizer;
|
||||
using ReactiveUI;
|
||||
|
||||
@ -32,6 +33,8 @@ public class EntryReleasesViewModel : ViewModelBase
|
||||
public IGetEntryById_Entry Entry { get; }
|
||||
public ReactiveCommand<Unit, Unit> DownloadLatestRelease { get; }
|
||||
|
||||
public Func<InstalledEntry, Task>? OnInstallationFinished { get; set; }
|
||||
|
||||
private async Task ExecuteDownloadLatestRelease(CancellationToken cancellationToken)
|
||||
{
|
||||
if (Entry.LatestRelease == null)
|
||||
@ -46,8 +49,12 @@ public class EntryReleasesViewModel : ViewModelBase
|
||||
|
||||
IEntryInstallationHandler installationHandler = _factory.CreateHandler(Entry.EntryType);
|
||||
EntryInstallResult result = await installationHandler.InstallAsync(Entry, Entry.LatestRelease, new Progress<StreamProgress>(), cancellationToken);
|
||||
if (result.IsSuccess)
|
||||
if (result.IsSuccess && result.Entry != null)
|
||||
{
|
||||
if (OnInstallationFinished != null)
|
||||
await OnInstallationFinished(result.Entry);
|
||||
_notificationService.CreateNotification().WithTitle($"{Entry.EntryType.Humanize(LetterCasing.Sentence)} installed").WithSeverity(NotificationSeverity.Success).Show();
|
||||
}
|
||||
else
|
||||
{
|
||||
_notificationService.CreateNotification()
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
x:Class="Artemis.UI.Screens.Workshop.Layout.LayoutDetailsView"
|
||||
x:DataType="layout:LayoutDetailsViewModel">
|
||||
<Grid ColumnDefinitions="300,*, 300" RowDefinitions="Auto,*">
|
||||
<StackPanel Grid.Row="1" Grid.Column="0" Margin="0 0 10 0" Spacing="10">
|
||||
<StackPanel Grid.Row="1" Grid.Column="0" Spacing="10">
|
||||
<Border Classes="card" VerticalAlignment="Top">
|
||||
<ContentControl Content="{CompiledBinding EntryInfoViewModel}" />
|
||||
</Border>
|
||||
@ -17,7 +17,7 @@
|
||||
</Border>
|
||||
</StackPanel>
|
||||
|
||||
<Border Classes="card" Grid.Row="1" Grid.Column="1">
|
||||
<Border Classes="card" Grid.Row="1" Grid.Column="1" Margin="10 0">
|
||||
<mdxaml:MarkdownScrollViewer Markdown="{CompiledBinding Entry.Description}" MarkdownStyleName="FluentAvalonia">
|
||||
<mdxaml:MarkdownScrollViewer.Styles>
|
||||
<StyleInclude Source="/Styles/Markdown.axaml" />
|
||||
@ -25,8 +25,6 @@
|
||||
</mdxaml:MarkdownScrollViewer>
|
||||
</Border>
|
||||
|
||||
<StackPanel Grid.Row="1" Grid.Column="2" IsVisible="{CompiledBinding Entry.Images.Count}">
|
||||
<ContentControl Content="{CompiledBinding EntryImagesViewModel}" />
|
||||
</StackPanel>
|
||||
<ContentControl Grid.Row="1" Grid.Column="2" IsVisible="{CompiledBinding Entry.Images.Count}" Content="{CompiledBinding EntryImagesViewModel}" />
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@ -1,10 +1,12 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.UI.Screens.Workshop.Entries.Details;
|
||||
using Artemis.UI.Screens.Workshop.Parameters;
|
||||
using Artemis.UI.Shared.Routing;
|
||||
using Artemis.WebClient.Workshop;
|
||||
using Artemis.WebClient.Workshop.Services;
|
||||
using PropertyChanged.SourceGenerator;
|
||||
using StrawberryShake;
|
||||
|
||||
@ -13,6 +15,7 @@ namespace Artemis.UI.Screens.Workshop.Layout;
|
||||
public partial class LayoutDetailsViewModel : RoutableScreen<WorkshopDetailParameters>
|
||||
{
|
||||
private readonly IWorkshopClient _client;
|
||||
private readonly IDeviceService _deviceService;
|
||||
private readonly Func<IGetEntryById_Entry, EntryInfoViewModel> _getEntryInfoViewModel;
|
||||
private readonly Func<IGetEntryById_Entry, EntryReleasesViewModel> _getEntryReleasesViewModel;
|
||||
private readonly Func<IGetEntryById_Entry, EntryImagesViewModel> _getEntryImagesViewModel;
|
||||
@ -22,11 +25,13 @@ public partial class LayoutDetailsViewModel : RoutableScreen<WorkshopDetailParam
|
||||
[Notify] private EntryImagesViewModel? _entryImagesViewModel;
|
||||
|
||||
public LayoutDetailsViewModel(IWorkshopClient client,
|
||||
IDeviceService deviceService,
|
||||
Func<IGetEntryById_Entry, EntryInfoViewModel> getEntryInfoViewModel,
|
||||
Func<IGetEntryById_Entry, EntryReleasesViewModel> getEntryReleasesViewModel,
|
||||
Func<IGetEntryById_Entry, EntryImagesViewModel> getEntryImagesViewModel)
|
||||
{
|
||||
_client = client;
|
||||
_deviceService = deviceService;
|
||||
_getEntryInfoViewModel = getEntryInfoViewModel;
|
||||
_getEntryReleasesViewModel = getEntryReleasesViewModel;
|
||||
_getEntryImagesViewModel = getEntryImagesViewModel;
|
||||
@ -54,6 +59,17 @@ public partial class LayoutDetailsViewModel : RoutableScreen<WorkshopDetailParam
|
||||
EntryInfoViewModel = _getEntryInfoViewModel(Entry);
|
||||
EntryReleasesViewModel = _getEntryReleasesViewModel(Entry);
|
||||
EntryImagesViewModel = _getEntryImagesViewModel(Entry);
|
||||
|
||||
EntryReleasesViewModel.OnInstallationFinished = OnInstallationFinished;
|
||||
}
|
||||
}
|
||||
|
||||
private Task OnInstallationFinished(InstalledEntry installedEntry)
|
||||
{
|
||||
// Find compatible devices
|
||||
// If any are found, offer to apply
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
}
|
||||
@ -26,13 +26,18 @@
|
||||
</StackPanel>
|
||||
|
||||
<ScrollViewer IsVisible="{CompiledBinding !Empty}">
|
||||
<ItemsRepeater ItemsSource="{CompiledBinding InstalledEntries}">
|
||||
<ItemsRepeater.ItemTemplate>
|
||||
<ItemsControl ItemsSource="{CompiledBinding InstalledEntries}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<ContentControl Content="{CompiledBinding}"/>
|
||||
</DataTemplate>
|
||||
</ItemsRepeater.ItemTemplate>
|
||||
</ItemsRepeater>
|
||||
</ItemsControl.ItemTemplate>
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<VirtualizingStackPanel />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
</ItemsControl>
|
||||
</ScrollViewer>
|
||||
</Panel>
|
||||
|
||||
|
||||
@ -37,13 +37,18 @@
|
||||
</StackPanel>
|
||||
|
||||
<ScrollViewer IsVisible="{CompiledBinding Entries.Count}">
|
||||
<ItemsRepeater ItemsSource="{CompiledBinding Entries}">
|
||||
<ItemsRepeater.ItemTemplate>
|
||||
<ItemsControl ItemsSource="{CompiledBinding Entries}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<ContentControl Content="{CompiledBinding}"/>
|
||||
</DataTemplate>
|
||||
</ItemsRepeater.ItemTemplate>
|
||||
</ItemsRepeater>
|
||||
</ItemsControl.ItemTemplate>
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<VirtualizingStackPanel />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
</ItemsControl>
|
||||
</ScrollViewer>
|
||||
</Panel>
|
||||
</Panel>
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
namespace Artemis.WebClient.Workshop.Handlers.InstallationHandlers;
|
||||
using Artemis.WebClient.Workshop.Services;
|
||||
|
||||
namespace Artemis.WebClient.Workshop.Handlers.InstallationHandlers;
|
||||
|
||||
public class EntryInstallResult
|
||||
{
|
||||
public bool IsSuccess { get; set; }
|
||||
public string? Message { get; set; }
|
||||
public object? Result { get; set; }
|
||||
public InstalledEntry? Entry { get; set; }
|
||||
|
||||
public static EntryInstallResult FromFailure(string? message)
|
||||
{
|
||||
@ -15,12 +17,12 @@ public class EntryInstallResult
|
||||
};
|
||||
}
|
||||
|
||||
public static EntryInstallResult FromSuccess(object installationResult)
|
||||
public static EntryInstallResult FromSuccess(InstalledEntry installedEntry)
|
||||
{
|
||||
return new EntryInstallResult
|
||||
{
|
||||
IsSuccess = true,
|
||||
Result = installationResult
|
||||
Entry = installedEntry
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -41,28 +41,28 @@ public class LayoutEntryInstallationHandler : IEntryInstallationHandler
|
||||
|
||||
// Ensure there is an installed entry
|
||||
InstalledEntry installedEntry = _workshopService.GetInstalledEntry(entry) ?? new InstalledEntry(entry, release);
|
||||
DirectoryInfo entryDirectory = installedEntry.GetReleaseDirectory(release);
|
||||
DirectoryInfo releaseDirectory = installedEntry.GetReleaseDirectory(release);
|
||||
|
||||
// If the folder already exists, remove it so that if the layout now contains less files, old things dont stick around
|
||||
if (entryDirectory.Exists)
|
||||
entryDirectory.Delete(true);
|
||||
entryDirectory.Create();
|
||||
if (releaseDirectory.Exists)
|
||||
releaseDirectory.Delete(true);
|
||||
releaseDirectory.Create();
|
||||
|
||||
// Extract the archive, we could go through the hoops of keeping track of progress but this should be so quick it doesn't matter
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
using ZipArchive archive = new(stream);
|
||||
archive.ExtractToDirectory(entryDirectory.FullName);
|
||||
archive.ExtractToDirectory(releaseDirectory.FullName);
|
||||
|
||||
ArtemisLayout layout = new(Path.Combine(entryDirectory.FullName, "layout.xml"));
|
||||
ArtemisLayout layout = new(Path.Combine(releaseDirectory.FullName, "layout.xml"));
|
||||
if (layout.IsValid)
|
||||
{
|
||||
installedEntry.ApplyRelease(release);
|
||||
_workshopService.SaveInstalledEntry(installedEntry);
|
||||
return EntryInstallResult.FromSuccess(layout);
|
||||
return EntryInstallResult.FromSuccess(installedEntry);
|
||||
}
|
||||
|
||||
// If the layout ended up being invalid yoink it out again, shoooo
|
||||
entryDirectory.Delete(true);
|
||||
releaseDirectory.Delete(true);
|
||||
_workshopService.RemoveInstalledEntry(installedEntry);
|
||||
return EntryInstallResult.FromFailure("Layout failed to load because it is invalid");
|
||||
}
|
||||
|
||||
@ -46,7 +46,7 @@ public class ProfileEntryInstallationHandler : IEntryInstallationHandler
|
||||
|
||||
// Update the release and return the profile configuration
|
||||
UpdateRelease(installedEntry, release);
|
||||
return EntryInstallResult.FromSuccess(overwritten);
|
||||
return EntryInstallResult.FromSuccess(installedEntry);
|
||||
}
|
||||
}
|
||||
|
||||
@ -60,7 +60,7 @@ public class ProfileEntryInstallationHandler : IEntryInstallationHandler
|
||||
|
||||
// Update the release and return the profile configuration
|
||||
UpdateRelease(installedEntry, release);
|
||||
return EntryInstallResult.FromSuccess(imported);
|
||||
return EntryInstallResult.FromSuccess(installedEntry);
|
||||
}
|
||||
|
||||
public async Task<EntryUninstallResult> UninstallAsync(InstalledEntry installedEntry, CancellationToken cancellationToken)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user