mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Add AXAML hot reload (debug only)
Major progress on default entries too I guess lmao
This commit is contained in:
parent
20fb6b7662
commit
b351f685f7
@ -141,6 +141,11 @@ public static class Constants
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static ReadOnlyCollection<string> StartupArguments { get; set; } = null!;
|
public static ReadOnlyCollection<string> StartupArguments { get; set; } = null!;
|
||||||
|
|
||||||
|
public static string? GetStartupRoute()
|
||||||
|
{
|
||||||
|
return StartupArguments.FirstOrDefault(a => a.StartsWith("--route=artemis://"))?.Split("--route=artemis://")[1];
|
||||||
|
}
|
||||||
|
|
||||||
internal static readonly CorePluginFeature CorePluginFeature = new() {Plugin = CorePlugin, Profiler = CorePlugin.GetProfiler("Feature - Core")};
|
internal static readonly CorePluginFeature CorePluginFeature = new() {Plugin = CorePlugin, Profiler = CorePlugin.GetProfiler("Feature - Core")};
|
||||||
internal static readonly EffectPlaceholderPlugin EffectPlaceholderPlugin = new() {Plugin = CorePlugin, Profiler = CorePlugin.GetProfiler("Feature - Effect Placeholder")};
|
internal static readonly EffectPlaceholderPlugin EffectPlaceholderPlugin = new() {Plugin = CorePlugin, Profiler = CorePlugin.GetProfiler("Feature - Effect Placeholder")};
|
||||||
internal static readonly JsonSerializerOptions JsonConvertSettings = new() {Converters = {new SKColorConverter(), new NumericJsonConverter()}};
|
internal static readonly JsonSerializerOptions JsonConvertSettings = new() {Converters = {new SKColorConverter(), new NumericJsonConverter()}};
|
||||||
|
|||||||
@ -251,7 +251,13 @@ internal class Router : CorePropertyChanged, IRouter, IDisposable
|
|||||||
if (_previousWindowRoute != null && _currentRouteSubject.Value == "blank")
|
if (_previousWindowRoute != null && _currentRouteSubject.Value == "blank")
|
||||||
Dispatcher.UIThread.InvokeAsync(async () => await Navigate(_previousWindowRoute, new RouterNavigationOptions {AddToHistory = false, EnableLogging = false}));
|
Dispatcher.UIThread.InvokeAsync(async () => await Navigate(_previousWindowRoute, new RouterNavigationOptions {AddToHistory = false, EnableLogging = false}));
|
||||||
else if (_currentRouteSubject.Value == null || _currentRouteSubject.Value == "blank")
|
else if (_currentRouteSubject.Value == null || _currentRouteSubject.Value == "blank")
|
||||||
Dispatcher.UIThread.InvokeAsync(async () => await Navigate("home", new RouterNavigationOptions {AddToHistory = false, EnableLogging = true}));
|
{
|
||||||
|
string? startupRoute = Constants.GetStartupRoute();
|
||||||
|
if (startupRoute != null)
|
||||||
|
Dispatcher.UIThread.InvokeAsync(async () => await Navigate(startupRoute, new RouterNavigationOptions {AddToHistory = false, EnableLogging = true}));
|
||||||
|
else
|
||||||
|
Dispatcher.UIThread.InvokeAsync(async () => await Navigate("home", new RouterNavigationOptions {AddToHistory = false, EnableLogging = true}));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MainWindowServiceOnMainWindowClosed(object? sender, EventArgs e)
|
private void MainWindowServiceOnMainWindowClosed(object? sender, EventArgs e)
|
||||||
|
|||||||
@ -16,6 +16,7 @@ using Avalonia.Controls.ApplicationLifetimes;
|
|||||||
using Avalonia.Markup.Xaml;
|
using Avalonia.Markup.Xaml;
|
||||||
using Avalonia.ReactiveUI;
|
using Avalonia.ReactiveUI;
|
||||||
using DryIoc;
|
using DryIoc;
|
||||||
|
using HotAvalonia;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
|
|
||||||
namespace Artemis.UI.Windows;
|
namespace Artemis.UI.Windows;
|
||||||
@ -27,6 +28,8 @@ public class App : Application
|
|||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
|
this.EnableHotReload();
|
||||||
|
|
||||||
// If Artemis is already running, bring it to foreground and stop this process
|
// If Artemis is already running, bring it to foreground and stop this process
|
||||||
if (FocusExistingInstance())
|
if (FocusExistingInstance())
|
||||||
{
|
{
|
||||||
@ -89,7 +92,7 @@ public class App : Application
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
CancellationTokenSource cts = new();
|
CancellationTokenSource cts = new();
|
||||||
cts.CancelAfter(2000);
|
cts.CancelAfter(5000);
|
||||||
|
|
||||||
HttpResponseMessage httpResponseMessage = client.Send(new HttpRequestMessage(HttpMethod.Post, url + "remote/bring-to-foreground") {Content = new StringContent(route ?? "")}, cts.Token);
|
HttpResponseMessage httpResponseMessage = client.Send(new HttpRequestMessage(HttpMethod.Post, url + "remote/bring-to-foreground") {Content = new StringContent(route ?? "")}, cts.Token);
|
||||||
httpResponseMessage.EnsureSuccessStatusCode();
|
httpResponseMessage.EnsureSuccessStatusCode();
|
||||||
|
|||||||
@ -35,40 +35,4 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<AvaloniaResource Include="Assets\**" />
|
<AvaloniaResource Include="Assets\**" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Update="Screens\Workshop\Plugin\Dialogs\DeviceProviderPickerDialogView.axaml.cs">
|
|
||||||
<DependentUpon>DeviceProviderPickerDialogView.axaml</DependentUpon>
|
|
||||||
<SubType>Code</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Update="Screens\Workshop\Plugin\Dialogs\DeviceSelectionDialogView.axaml.cs">
|
|
||||||
<DependentUpon>DeviceSelectionDialogView.axaml</DependentUpon>
|
|
||||||
<SubType>Code</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Update="Screens\Workshop\Layout\LayoutListView.axaml.cs">
|
|
||||||
<DependentUpon>LayoutListView.axaml</DependentUpon>
|
|
||||||
<SubType>Code</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Update="Screens\Workshop\Plugins\PluginListView.axaml.cs">
|
|
||||||
<DependentUpon>LayoutListView.axaml</DependentUpon>
|
|
||||||
<SubType>Code</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Update="Screens\Workshop\Profile\ProfileListView.axaml.cs">
|
|
||||||
<DependentUpon>LayoutListView.axaml</DependentUpon>
|
|
||||||
<SubType>Code</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Update="Screens\Workshop\EntryReleases\EntryReleasesView.axaml.cs">
|
|
||||||
<DependentUpon>EntryReleasesView.axaml</DependentUpon>
|
|
||||||
<SubType>Code</SubType>
|
|
||||||
</Compile>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<UpToDateCheckInput Remove="Screens\Workshop\Entries\Tabs\PluginListView.axaml" />
|
|
||||||
<UpToDateCheckInput Remove="Screens\Workshop\Entries\Tabs\ProfileListView.axaml" />
|
|
||||||
<UpToDateCheckInput Remove="Screens\Workshop\Plugins\Dialogs\PluginDialogView.axaml" />
|
|
||||||
<UpToDateCheckInput Remove="Screens\Scripting\Dialogs\ScriptConfigurationCreateView.axaml" />
|
|
||||||
<UpToDateCheckInput Remove="Screens\Scripting\Dialogs\ScriptConfigurationEditView.axaml" />
|
|
||||||
<UpToDateCheckInput Remove="Screens\Scripting\ScriptsDialogView.axaml" />
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
</Project>
|
||||||
@ -22,7 +22,7 @@
|
|||||||
Foreground="White"
|
Foreground="White"
|
||||||
FontSize="32"
|
FontSize="32"
|
||||||
Margin="30"
|
Margin="30"
|
||||||
Text=" Welcome to Artemis, the unified RGB platform.">
|
Text="Welcome to Artemis, the unified RGB platform.">
|
||||||
<TextBlock.Effect>
|
<TextBlock.Effect>
|
||||||
<DropShadowEffect Color="Black" OffsetX="2" OffsetY="2" BlurRadius="5"></DropShadowEffect>
|
<DropShadowEffect Color="Black" OffsetX="2" OffsetY="2" BlurRadius="5"></DropShadowEffect>
|
||||||
</TextBlock.Effect>
|
</TextBlock.Effect>
|
||||||
|
|||||||
@ -7,26 +7,52 @@
|
|||||||
x:Class="Artemis.UI.Screens.StartupWizard.Steps.DefaultEntriesStepView"
|
x:Class="Artemis.UI.Screens.StartupWizard.Steps.DefaultEntriesStepView"
|
||||||
x:DataType="steps:DefaultEntriesStepViewModel">
|
x:DataType="steps:DefaultEntriesStepViewModel">
|
||||||
<Border Classes="card">
|
<Border Classes="card">
|
||||||
<Grid RowDefinitions="Auto,Auto,Auto,Auto,*">
|
<Grid RowDefinitions="*,Auto">
|
||||||
<StackPanel Grid.Row="0">
|
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
|
||||||
|
<StackPanel>
|
||||||
<TextBlock TextWrapping="Wrap">
|
<TextBlock TextWrapping="Wrap">
|
||||||
Installing default plugins and profiles, these will provide you with a basic setup to get started with Artemis.
|
Below is a list of default features that can be installed to get you started with Artemis. You can always install or uninstall features later via the Workshop.
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
</StackPanel>
|
|
||||||
|
|
||||||
<TextBlock Grid.Row="2">
|
<TextBlock Classes="card-title" IsVisible="{CompiledBinding DeviceProviderEntryViewModels.Count}">
|
||||||
<Run Text="Installed"/>
|
Device providers
|
||||||
<Run Text="{CompiledBinding InstalledEntries}"/>
|
</TextBlock>
|
||||||
<Run Text=" of "/>
|
<ItemsControl ItemsSource="{CompiledBinding DeviceProviderEntryViewModels}" Margin="0,0,5,0">
|
||||||
<Run Text="{CompiledBinding TotalEntries}"/>
|
<ItemsControl.ItemsPanel>
|
||||||
<Run Text=" entries."/>
|
<ItemsPanelTemplate>
|
||||||
</TextBlock>
|
<UniformGrid Columns="2" ColumnSpacing="5" />
|
||||||
|
</ItemsPanelTemplate>
|
||||||
|
</ItemsControl.ItemsPanel>
|
||||||
|
</ItemsControl>
|
||||||
|
|
||||||
<ProgressBar Grid.Row="3" Minimum="0" Maximum="{CompiledBinding TotalEntries}" IsIndeterminate="{CompiledBinding FetchingDefaultEntries}" Value="{CompiledBinding InstalledEntries}" />
|
<TextBlock Classes="card-title" IsVisible="{CompiledBinding EssentialEntryViewModels.Count}">
|
||||||
<StackPanel Grid.Row="4" Orientation="Vertical" IsVisible="{CompiledBinding CurrentEntry, Converter={x:Static ObjectConverters.IsNotNull}}" Margin="0 10">
|
Essentials
|
||||||
<TextBlock Text="{CompiledBinding CurrentEntry.Name, StringFormat='Currently installing: {0}'}" />
|
</TextBlock>
|
||||||
<ProgressBar Minimum="0" Maximum="100" Value="{CompiledBinding InstallProgress}" />
|
<ItemsControl ItemsSource="{CompiledBinding EssentialEntryViewModels}" Margin="0,0,5,0">
|
||||||
|
<ItemsControl.ItemsPanel>
|
||||||
|
<ItemsPanelTemplate>
|
||||||
|
<UniformGrid Columns="2" ColumnSpacing="5"/>
|
||||||
|
</ItemsPanelTemplate>
|
||||||
|
</ItemsControl.ItemsPanel>
|
||||||
|
</ItemsControl>
|
||||||
|
|
||||||
|
<TextBlock Classes="card-title" IsVisible="{CompiledBinding OtherEntryViewModels.Count}">
|
||||||
|
Other features
|
||||||
|
</TextBlock>
|
||||||
|
<ItemsControl ItemsSource="{CompiledBinding OtherEntryViewModels}" Margin="0,0,5,0">
|
||||||
|
<ItemsControl.ItemsPanel>
|
||||||
|
<ItemsPanelTemplate>
|
||||||
|
<UniformGrid Columns="2" ColumnSpacing="5"/>
|
||||||
|
</ItemsPanelTemplate>
|
||||||
|
</ItemsControl.ItemsPanel>
|
||||||
|
</ItemsControl>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</ScrollViewer>
|
||||||
</Border>
|
<ProgressBar Grid.Row="1"
|
||||||
|
Minimum="0"
|
||||||
|
Maximum="{CompiledBinding TotalEntries}"
|
||||||
|
IsIndeterminate="{CompiledBinding FetchingDefaultEntries}"
|
||||||
|
Value="{CompiledBinding CurrentEntries}" />
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -8,7 +9,6 @@ using Artemis.UI.Extensions;
|
|||||||
using Artemis.UI.Shared.Services;
|
using Artemis.UI.Shared.Services;
|
||||||
using Artemis.UI.Shared.Utilities;
|
using Artemis.UI.Shared.Utilities;
|
||||||
using Artemis.WebClient.Workshop;
|
using Artemis.WebClient.Workshop;
|
||||||
using Artemis.WebClient.Workshop.Handlers.InstallationHandlers;
|
|
||||||
using Artemis.WebClient.Workshop.Services;
|
using Artemis.WebClient.Workshop.Services;
|
||||||
using PropertyChanged.SourceGenerator;
|
using PropertyChanged.SourceGenerator;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
@ -20,25 +20,31 @@ public partial class DefaultEntriesStepViewModel : WizardStepViewModel
|
|||||||
{
|
{
|
||||||
[Notify] private bool _workshopReachable;
|
[Notify] private bool _workshopReachable;
|
||||||
[Notify] private bool _fetchingDefaultEntries;
|
[Notify] private bool _fetchingDefaultEntries;
|
||||||
[Notify] private int _totalEntries;
|
[Notify] private bool _installed;
|
||||||
[Notify] private int _installedEntries;
|
[Notify] private int _currentEntries;
|
||||||
[Notify] private int _installProgress;
|
[Notify] private int _totalEntries = 1;
|
||||||
[Notify] private IEntrySummary? _currentEntry;
|
|
||||||
|
|
||||||
private readonly IWorkshopService _workshopService;
|
|
||||||
private readonly IWorkshopClient _client;
|
private readonly IWorkshopClient _client;
|
||||||
private readonly IWindowService _windowService;
|
private readonly Func<IEntrySummary, DefaultEntryItemViewModel> _getDefaultEntryItemViewModel;
|
||||||
private readonly Progress<StreamProgress> _currentEntryProgress = new();
|
|
||||||
|
|
||||||
|
public ObservableCollection<DefaultEntryItemViewModel> DeviceProviderEntryViewModels { get; } = [];
|
||||||
|
public ObservableCollection<DefaultEntryItemViewModel> EssentialEntryViewModels { get; } = [];
|
||||||
|
public ObservableCollection<DefaultEntryItemViewModel> OtherEntryViewModels { get; } = [];
|
||||||
|
|
||||||
public DefaultEntriesStepViewModel(IWorkshopService workshopService, IDeviceService deviceService, IWorkshopClient client, IWindowService windowService)
|
public DefaultEntriesStepViewModel(IWorkshopService workshopService, IDeviceService deviceService, IWorkshopClient client,
|
||||||
|
Func<IEntrySummary, DefaultEntryItemViewModel> getDefaultEntryItemViewModel)
|
||||||
{
|
{
|
||||||
_workshopService = workshopService;
|
|
||||||
_client = client;
|
_client = client;
|
||||||
_windowService = windowService;
|
_getDefaultEntryItemViewModel = getDefaultEntryItemViewModel;
|
||||||
_currentEntryProgress.ProgressChanged += (_, f) => InstallProgress = f.ProgressPercentage;
|
|
||||||
|
|
||||||
Continue = ReactiveCommand.Create(() => Wizard.ChangeScreen<SettingsStepViewModel>());
|
ContinueText = "Install selected entries";
|
||||||
|
Continue = ReactiveCommand.CreateFromTask(async ct =>
|
||||||
|
{
|
||||||
|
if (Installed)
|
||||||
|
Wizard.ChangeScreen<SettingsStepViewModel>();
|
||||||
|
else
|
||||||
|
await Install(ct);
|
||||||
|
});
|
||||||
GoBack = ReactiveCommand.Create(() =>
|
GoBack = ReactiveCommand.Create(() =>
|
||||||
{
|
{
|
||||||
if (deviceService.EnabledDevices.Count == 0)
|
if (deviceService.EnabledDevices.Count == 0)
|
||||||
@ -49,22 +55,57 @@ public partial class DefaultEntriesStepViewModel : WizardStepViewModel
|
|||||||
|
|
||||||
this.WhenActivatedAsync(async d =>
|
this.WhenActivatedAsync(async d =>
|
||||||
{
|
{
|
||||||
WorkshopReachable = await _workshopService.ValidateWorkshopStatus(d.AsCancellationToken());
|
WorkshopReachable = await workshopService.ValidateWorkshopStatus(d.AsCancellationToken());
|
||||||
if (WorkshopReachable)
|
if (WorkshopReachable)
|
||||||
{
|
{
|
||||||
await InstallDefaultEntries(d.AsCancellationToken());
|
await GetDefaultEntries(d.AsCancellationToken());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> InstallDefaultEntries(CancellationToken cancellationToken)
|
private async Task Install(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
FetchingDefaultEntries = true;
|
// Remove entries that aren't to be installed
|
||||||
TotalEntries = 0;
|
RemoveUnselectedEntries(DeviceProviderEntryViewModels);
|
||||||
InstalledEntries = 0;
|
RemoveUnselectedEntries(EssentialEntryViewModels);
|
||||||
|
RemoveUnselectedEntries(OtherEntryViewModels);
|
||||||
|
|
||||||
|
TotalEntries = DeviceProviderEntryViewModels.Count + EssentialEntryViewModels.Count + OtherEntryViewModels.Count;
|
||||||
|
CurrentEntries = 0;
|
||||||
|
|
||||||
|
// Install entries one by one, removing them from the list as we go
|
||||||
|
List<DefaultEntryItemViewModel> entries = [..DeviceProviderEntryViewModels, ..EssentialEntryViewModels, ..OtherEntryViewModels];
|
||||||
|
foreach (DefaultEntryItemViewModel defaultEntryItemViewModel in entries)
|
||||||
|
{
|
||||||
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
bool removeFromList = await defaultEntryItemViewModel.InstallEntry(cancellationToken);
|
||||||
|
if (!removeFromList)
|
||||||
|
break;
|
||||||
|
|
||||||
|
DeviceProviderEntryViewModels.Remove(defaultEntryItemViewModel);
|
||||||
|
EssentialEntryViewModels.Remove(defaultEntryItemViewModel);
|
||||||
|
OtherEntryViewModels.Remove(defaultEntryItemViewModel);
|
||||||
|
CurrentEntries++;
|
||||||
|
}
|
||||||
|
|
||||||
|
Installed = true;
|
||||||
|
ContinueText = "Continue";
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RemoveUnselectedEntries(ObservableCollection<DefaultEntryItemViewModel> entryViewModels)
|
||||||
|
{
|
||||||
|
List<DefaultEntryItemViewModel> toRemove = entryViewModels.Where(e => !e.ShouldInstall).ToList();
|
||||||
|
foreach (DefaultEntryItemViewModel defaultEntryItemViewModel in toRemove)
|
||||||
|
entryViewModels.Remove(defaultEntryItemViewModel);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task GetDefaultEntries(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
if (!WorkshopReachable)
|
if (!WorkshopReachable)
|
||||||
return false;
|
return;
|
||||||
|
|
||||||
|
FetchingDefaultEntries = true;
|
||||||
|
|
||||||
IOperationResult<IGetDefaultEntriesResult> result = await _client.GetDefaultEntries.ExecuteAsync(100, null, cancellationToken);
|
IOperationResult<IGetDefaultEntriesResult> result = await _client.GetDefaultEntries.ExecuteAsync(100, null, cancellationToken);
|
||||||
List<IEntrySummary> entries = result.Data?.EntriesV2?.Edges?.Select(e => e.Node).Cast<IEntrySummary>().ToList() ?? [];
|
List<IEntrySummary> entries = result.Data?.EntriesV2?.Edges?.Select(e => e.Node).Cast<IEntrySummary>().ToList() ?? [];
|
||||||
@ -75,41 +116,25 @@ public partial class DefaultEntriesStepViewModel : WizardStepViewModel
|
|||||||
entries.AddRange(result.Data.EntriesV2.Edges.Select(e => e.Node));
|
entries.AddRange(result.Data.EntriesV2.Edges.Select(e => e.Node));
|
||||||
}
|
}
|
||||||
|
|
||||||
await Task.Delay(1000);
|
DeviceProviderEntryViewModels.Clear();
|
||||||
FetchingDefaultEntries = false;
|
EssentialEntryViewModels.Clear();
|
||||||
TotalEntries = entries.Count;
|
OtherEntryViewModels.Clear();
|
||||||
|
|
||||||
if (entries.Count == 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
foreach (IEntrySummary entry in entries)
|
foreach (IEntrySummary entry in entries)
|
||||||
{
|
{
|
||||||
if (cancellationToken.IsCancellationRequested)
|
if (entry.DefaultEntryInfo == null)
|
||||||
return false;
|
|
||||||
|
|
||||||
CurrentEntry = entry;
|
|
||||||
|
|
||||||
// Skip entries without a release and entries that are already installed
|
|
||||||
if (entry.LatestRelease == null || _workshopService.GetInstalledEntry(entry.Id) != null)
|
|
||||||
{
|
|
||||||
InstalledEntries++;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
EntryInstallResult installResult = await _workshopService.InstallEntry(entry, entry.LatestRelease, _currentEntryProgress, cancellationToken);
|
DefaultEntryItemViewModel viewModel = _getDefaultEntryItemViewModel(entry);
|
||||||
|
viewModel.ShouldInstall = entry.DefaultEntryInfo.IsEssential;
|
||||||
|
|
||||||
// Unlikely as default entries do nothing fancy
|
if (entry.DefaultEntryInfo.IsDeviceProvider)
|
||||||
if (!installResult.IsSuccess)
|
DeviceProviderEntryViewModels.Add(viewModel);
|
||||||
{
|
else if (entry.DefaultEntryInfo.IsEssential)
|
||||||
await _windowService.CreateContentDialog().WithTitle("Failed to install entry")
|
EssentialEntryViewModels.Add(viewModel);
|
||||||
.WithContent($"Failed to install entry '{entry.Name}' ({entry.Id}): {installResult.Message}")
|
else
|
||||||
.WithCloseButtonText("Skip and continue")
|
OtherEntryViewModels.Add(viewModel);
|
||||||
.ShowAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
InstalledEntries++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
FetchingDefaultEntries = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -0,0 +1,72 @@
|
|||||||
|
<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:il="clr-namespace:AsyncImageLoader;assembly=AsyncImageLoader.Avalonia"
|
||||||
|
xmlns:converters="clr-namespace:Artemis.UI.Converters"
|
||||||
|
xmlns:avalonia="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
|
||||||
|
xmlns:steps="clr-namespace:Artemis.UI.Screens.StartupWizard.Steps"
|
||||||
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
|
x:Class="Artemis.UI.Screens.StartupWizard.Steps.DefaultEntryItemView"
|
||||||
|
x:DataType="steps:DefaultEntryItemViewModel">
|
||||||
|
<UserControl.Resources>
|
||||||
|
<converters:EntryIconUriConverter x:Key="EntryIconUriConverter" />
|
||||||
|
<converters:DateTimeConverter x:Key="DateTimeConverter" />
|
||||||
|
</UserControl.Resources>
|
||||||
|
<Border Classes="card" Padding="15" Margin="0 5">
|
||||||
|
<Grid ColumnDefinitions="Auto,*,Auto,Auto" RowDefinitions="*, Auto">
|
||||||
|
<!-- Icon -->
|
||||||
|
<Border Grid.Column="0"
|
||||||
|
Grid.Row="0"
|
||||||
|
Grid.RowSpan="2"
|
||||||
|
CornerRadius="6"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Margin="0 0 10 0"
|
||||||
|
Width="80"
|
||||||
|
Height="80"
|
||||||
|
ClipToBounds="True">
|
||||||
|
<Image Stretch="UniformToFill" il:ImageLoader.Source="{CompiledBinding Entry.Id, Converter={StaticResource EntryIconUriConverter}, Mode=OneWay}" />
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
<!-- Body -->
|
||||||
|
<Grid Grid.Column="1" Grid.Row="0" Grid.RowSpan="2" VerticalAlignment="Stretch" RowDefinitions="Auto,*,Auto">
|
||||||
|
<StackPanel Grid.Row="0" Orientation="Horizontal">
|
||||||
|
<TextBlock Classes="h5" Margin="0 0 0 5" TextTrimming="CharacterEllipsis" Text="{CompiledBinding Entry.Name, FallbackValue=Title}" />
|
||||||
|
</StackPanel>
|
||||||
|
<TextBlock Grid.Row="1"
|
||||||
|
Classes="subtitle"
|
||||||
|
TextWrapping="Wrap"
|
||||||
|
TextTrimming="CharacterEllipsis"
|
||||||
|
Text="{CompiledBinding Entry.Summary, FallbackValue=Summary}" />
|
||||||
|
|
||||||
|
<ItemsControl Grid.Row="2" ItemsSource="{CompiledBinding Entry.Categories}" Margin="0 8 0 0">
|
||||||
|
<ItemsControl.ItemsPanel>
|
||||||
|
<ItemsPanelTemplate>
|
||||||
|
<StackPanel Orientation="Horizontal" Spacing="8" />
|
||||||
|
</ItemsPanelTemplate>
|
||||||
|
</ItemsControl.ItemsPanel>
|
||||||
|
<ItemsControl.ItemTemplate>
|
||||||
|
<DataTemplate>
|
||||||
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<avalonia:MaterialIcon Kind="{CompiledBinding Icon}" Margin="0 0 3 0" />
|
||||||
|
<TextBlock Text="{CompiledBinding Name}" TextTrimming="CharacterEllipsis" />
|
||||||
|
</StackPanel>
|
||||||
|
</DataTemplate>
|
||||||
|
</ItemsControl.ItemTemplate>
|
||||||
|
</ItemsControl>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<!-- Management -->
|
||||||
|
<Border Grid.Column="3" Grid.Row="0" Grid.RowSpan="2" BorderBrush="{DynamicResource ButtonBorderBrush}" BorderThickness="1 0 0 0" Margin="10 0 0 0" Padding="10 0 0 0" IsVisible="{CompiledBinding !IsInstalled}">
|
||||||
|
<StackPanel VerticalAlignment="Center">
|
||||||
|
<CheckBox MinHeight="26" Margin="0 4 0 0" IsChecked="{CompiledBinding ShouldInstall}">Install</CheckBox>
|
||||||
|
</StackPanel>
|
||||||
|
</Border>
|
||||||
|
<Border Grid.Column="3" Grid.Row="0" Grid.RowSpan="2" BorderBrush="{DynamicResource ButtonBorderBrush}" BorderThickness="1 0 0 0" Margin="10 0 0 0" Padding="10 0 0 0" IsVisible="{CompiledBinding IsInstalled}">
|
||||||
|
<StackPanel VerticalAlignment="Center">
|
||||||
|
<TextBlock>Already installed</TextBlock>
|
||||||
|
</StackPanel>
|
||||||
|
</Border>
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
|
</UserControl>
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
using Avalonia.ReactiveUI;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Screens.StartupWizard.Steps;
|
||||||
|
|
||||||
|
public partial class DefaultEntryItemView : ReactiveUserControl<StartupWizard.Steps.DefaultEntryItemViewModel>
|
||||||
|
{
|
||||||
|
public DefaultEntryItemView()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,86 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reactive.Disposables;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Artemis.Core;
|
||||||
|
using Artemis.Core.Services;
|
||||||
|
using Artemis.UI.DryIoc.Factories;
|
||||||
|
using Artemis.UI.Screens.Plugins;
|
||||||
|
using Artemis.UI.Shared;
|
||||||
|
using Artemis.UI.Shared.Services;
|
||||||
|
using Artemis.UI.Shared.Utilities;
|
||||||
|
using Artemis.WebClient.Workshop;
|
||||||
|
using Artemis.WebClient.Workshop.Handlers.InstallationHandlers;
|
||||||
|
using Artemis.WebClient.Workshop.Models;
|
||||||
|
using Artemis.WebClient.Workshop.Services;
|
||||||
|
using PropertyChanged.SourceGenerator;
|
||||||
|
using ReactiveUI;
|
||||||
|
using StrawberryShake;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Screens.StartupWizard.Steps;
|
||||||
|
|
||||||
|
public partial class DefaultEntryItemViewModel : ActivatableViewModelBase
|
||||||
|
{
|
||||||
|
private readonly IWorkshopService _workshopService;
|
||||||
|
private readonly IWindowService _windowService;
|
||||||
|
private readonly IPluginManagementService _pluginManagementService;
|
||||||
|
private readonly ISettingsVmFactory _settingsVmFactory;
|
||||||
|
private readonly Progress<StreamProgress> _progress = new();
|
||||||
|
|
||||||
|
[Notify] private bool _isInstalled;
|
||||||
|
[Notify] private bool _shouldInstall;
|
||||||
|
|
||||||
|
public DefaultEntryItemViewModel(IEntrySummary entry, IWorkshopService workshopService, IWindowService windowService, IPluginManagementService pluginManagementService, ISettingsVmFactory settingsVmFactory)
|
||||||
|
{
|
||||||
|
_workshopService = workshopService;
|
||||||
|
_windowService = windowService;
|
||||||
|
_pluginManagementService = pluginManagementService;
|
||||||
|
_settingsVmFactory = settingsVmFactory;
|
||||||
|
Entry = entry;
|
||||||
|
|
||||||
|
this.WhenActivated((CompositeDisposable _) => { IsInstalled = workshopService.GetInstalledEntry(entry.Id) != null; });
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEntrySummary Entry { get; }
|
||||||
|
|
||||||
|
public async Task<bool> InstallEntry(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
if (IsInstalled || !ShouldInstall || Entry.LatestRelease == null)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Most entries install so quick it looks broken without a small delay
|
||||||
|
Task minimumDelay = Task.Delay(100, cancellationToken);
|
||||||
|
EntryInstallResult result = await _workshopService.InstallEntry(Entry, Entry.LatestRelease, _progress, cancellationToken);
|
||||||
|
await minimumDelay;
|
||||||
|
|
||||||
|
if (!result.IsSuccess)
|
||||||
|
{
|
||||||
|
await _windowService.CreateContentDialog().WithTitle("Failed to install entry")
|
||||||
|
.WithContent($"Failed to install entry '{Entry.Name}' ({Entry.Id}): {result.Message}")
|
||||||
|
.WithCloseButtonText("Skip and continue")
|
||||||
|
.ShowAsync();
|
||||||
|
}
|
||||||
|
// If the entry is a plugin, enable the plugin
|
||||||
|
else if (result.Entry?.EntryType == EntryType.Plugin)
|
||||||
|
{
|
||||||
|
await EnablePlugin(result.Entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.IsSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task EnablePlugin(InstalledEntry entry)
|
||||||
|
{
|
||||||
|
if (!entry.TryGetMetadata("PluginId", out Guid pluginId))
|
||||||
|
throw new InvalidOperationException("Plugin entry does not contain a PluginId metadata value.");
|
||||||
|
|
||||||
|
Plugin? plugin = _pluginManagementService.GetAllPlugins().FirstOrDefault(p => p.Guid == pluginId);
|
||||||
|
if (plugin == null)
|
||||||
|
throw new InvalidOperationException($"Plugin with id '{pluginId}' does not exist.");
|
||||||
|
|
||||||
|
// There's quite a bit of UI involved in enabling a plugin, borrowing the PluginSettingsViewModel for this
|
||||||
|
PluginViewModel pluginViewModel = _settingsVmFactory.PluginViewModel(plugin, ReactiveCommand.Create(() => { }));
|
||||||
|
await pluginViewModel.UpdateEnabled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -64,7 +64,11 @@
|
|||||||
<Label Target="Summary" Margin="0 5 0 0">Summary</Label>
|
<Label Target="Summary" Margin="0 5 0 0">Summary</Label>
|
||||||
<TextBox Name="Summary" Text="{CompiledBinding Summary}"></TextBox>
|
<TextBox Name="Summary" Text="{CompiledBinding Summary}"></TextBox>
|
||||||
|
|
||||||
<CheckBox IsVisible="{CompiledBinding IsAdministrator}" IsChecked="{CompiledBinding IsDefault}">Download by default (admin only)</CheckBox>
|
<StackPanel IsVisible="{CompiledBinding IsAdministrator}" Orientation="Horizontal">
|
||||||
|
<CheckBox IsChecked="{CompiledBinding IsDefault}">Download by default (admin only)</CheckBox>
|
||||||
|
<CheckBox IsEnabled="{CompiledBinding IsDefault}" IsChecked="{CompiledBinding IsEssential}">Essential</CheckBox>
|
||||||
|
<CheckBox IsEnabled="{CompiledBinding IsDefault}" IsChecked="{CompiledBinding IsDeviceProvider}">Device provider</CheckBox>
|
||||||
|
</StackPanel>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
@ -94,7 +98,7 @@
|
|||||||
<tagsInput:TagsInput Tags="{CompiledBinding Tags}" />
|
<tagsInput:TagsInput Tags="{CompiledBinding Tags}" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
<controls:SplitMarkdownEditor Grid.Row="1" Title="Description" Markdown="{CompiledBinding Description}"/>
|
<controls:SplitMarkdownEditor Grid.Row="1" Title="Description" Markdown="{CompiledBinding Description}" />
|
||||||
|
|
||||||
<TextBlock Grid.Row="2"
|
<TextBlock Grid.Row="2"
|
||||||
Foreground="{DynamicResource SystemFillColorCriticalBrush}"
|
Foreground="{DynamicResource SystemFillColorCriticalBrush}"
|
||||||
|
|||||||
@ -36,6 +36,8 @@ public partial class EntrySpecificationsViewModel : ValidatableViewModelBase
|
|||||||
[Notify] private string _summary = string.Empty;
|
[Notify] private string _summary = string.Empty;
|
||||||
[Notify] private string _description = string.Empty;
|
[Notify] private string _description = string.Empty;
|
||||||
[Notify] private bool _isDefault;
|
[Notify] private bool _isDefault;
|
||||||
|
[Notify] private bool _isEssential;
|
||||||
|
[Notify] private bool _isDeviceProvider;
|
||||||
[Notify] private Bitmap? _iconBitmap;
|
[Notify] private Bitmap? _iconBitmap;
|
||||||
[Notify(Setter.Private)] private bool _iconChanged;
|
[Notify(Setter.Private)] private bool _iconChanged;
|
||||||
|
|
||||||
|
|||||||
@ -105,7 +105,9 @@ public partial class SubmissionDetailsViewModel : RoutableScreen
|
|||||||
specificationsViewModel.Name = Entry.Name;
|
specificationsViewModel.Name = Entry.Name;
|
||||||
specificationsViewModel.Summary = Entry.Summary;
|
specificationsViewModel.Summary = Entry.Summary;
|
||||||
specificationsViewModel.Description = Entry.Description;
|
specificationsViewModel.Description = Entry.Description;
|
||||||
specificationsViewModel.IsDefault = Entry.IsDefault;
|
specificationsViewModel.IsDefault = Entry.DefaultEntryInfo != null;
|
||||||
|
specificationsViewModel.IsEssential = Entry.DefaultEntryInfo?.IsEssential ?? false;
|
||||||
|
specificationsViewModel.IsDeviceProvider = Entry.DefaultEntryInfo?.IsDeviceProvider ?? false;
|
||||||
specificationsViewModel.PreselectedCategories = Entry.Categories.Select(c => c.Id).ToList();
|
specificationsViewModel.PreselectedCategories = Entry.Categories.Select(c => c.Id).ToList();
|
||||||
|
|
||||||
specificationsViewModel.Tags.Clear();
|
specificationsViewModel.Tags.Clear();
|
||||||
@ -170,14 +172,29 @@ public partial class SubmissionDetailsViewModel : RoutableScreen
|
|||||||
HasChanges = EntrySpecificationsViewModel.Name != Entry.Name ||
|
HasChanges = EntrySpecificationsViewModel.Name != Entry.Name ||
|
||||||
EntrySpecificationsViewModel.Description != Entry.Description ||
|
EntrySpecificationsViewModel.Description != Entry.Description ||
|
||||||
EntrySpecificationsViewModel.Summary != Entry.Summary ||
|
EntrySpecificationsViewModel.Summary != Entry.Summary ||
|
||||||
EntrySpecificationsViewModel.IsDefault != Entry.IsDefault ||
|
|
||||||
EntrySpecificationsViewModel.IconChanged ||
|
EntrySpecificationsViewModel.IconChanged ||
|
||||||
|
HasAdminChanges() ||
|
||||||
!tags.SequenceEqual(Entry.Tags.Select(t => t.Name).OrderBy(t => t)) ||
|
!tags.SequenceEqual(Entry.Tags.Select(t => t.Name).OrderBy(t => t)) ||
|
||||||
!categories.SequenceEqual(Entry.Categories.Select(c => c.Id).OrderBy(c => c)) ||
|
!categories.SequenceEqual(Entry.Categories.Select(c => c.Id).OrderBy(c => c)) ||
|
||||||
Images.Any(i => i.HasChanges) ||
|
Images.Any(i => i.HasChanges) ||
|
||||||
_removedImages.Any();
|
_removedImages.Any();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool HasAdminChanges()
|
||||||
|
{
|
||||||
|
if (EntrySpecificationsViewModel == null || Entry == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool isDefault = Entry.DefaultEntryInfo != null;
|
||||||
|
bool isEssential = Entry.DefaultEntryInfo?.IsEssential ?? false;
|
||||||
|
bool isDeviceProvider = Entry.DefaultEntryInfo?.IsDeviceProvider ?? false;
|
||||||
|
|
||||||
|
return EntrySpecificationsViewModel.IsDefault != isDefault ||
|
||||||
|
(EntrySpecificationsViewModel.IsDefault && (
|
||||||
|
EntrySpecificationsViewModel.IsEssential != isEssential ||
|
||||||
|
EntrySpecificationsViewModel.IsDeviceProvider != isDeviceProvider));
|
||||||
|
}
|
||||||
|
|
||||||
private async Task ExecuteDiscardChanges()
|
private async Task ExecuteDiscardChanges()
|
||||||
{
|
{
|
||||||
await ApplyDetailsFromEntry(CancellationToken.None);
|
await ApplyDetailsFromEntry(CancellationToken.None);
|
||||||
@ -194,9 +211,15 @@ public partial class SubmissionDetailsViewModel : RoutableScreen
|
|||||||
Name = EntrySpecificationsViewModel.Name,
|
Name = EntrySpecificationsViewModel.Name,
|
||||||
Summary = EntrySpecificationsViewModel.Summary,
|
Summary = EntrySpecificationsViewModel.Summary,
|
||||||
Description = EntrySpecificationsViewModel.Description,
|
Description = EntrySpecificationsViewModel.Description,
|
||||||
IsDefault = EntrySpecificationsViewModel.IsDefault,
|
|
||||||
Categories = EntrySpecificationsViewModel.SelectedCategories,
|
Categories = EntrySpecificationsViewModel.SelectedCategories,
|
||||||
Tags = EntrySpecificationsViewModel.Tags
|
Tags = EntrySpecificationsViewModel.Tags,
|
||||||
|
DefaultEntryInfo = EntrySpecificationsViewModel.IsDefault
|
||||||
|
? new DefaultEntryInfoInput
|
||||||
|
{
|
||||||
|
IsEssential = EntrySpecificationsViewModel.IsEssential,
|
||||||
|
IsDeviceProvider = EntrySpecificationsViewModel.IsDeviceProvider
|
||||||
|
}
|
||||||
|
: null
|
||||||
};
|
};
|
||||||
|
|
||||||
IOperationResult<IUpdateEntryResult> result = await _client.UpdateEntry.ExecuteAsync(input, cancellationToken);
|
IOperationResult<IUpdateEntryResult> result = await _client.UpdateEntry.ExecuteAsync(input, cancellationToken);
|
||||||
|
|||||||
@ -33,6 +33,8 @@ public class SubmissionWizardState : IDisposable
|
|||||||
public string Summary { get; set; } = string.Empty;
|
public string Summary { get; set; } = string.Empty;
|
||||||
public string Description { get; set; } = string.Empty;
|
public string Description { get; set; } = string.Empty;
|
||||||
public bool IsDefault { get; set; }
|
public bool IsDefault { get; set; }
|
||||||
|
public bool IsEssential { get; set; }
|
||||||
|
public bool IsDeviceProvider { get; set; }
|
||||||
|
|
||||||
public List<long> Categories { get; set; } = new();
|
public List<long> Categories { get; set; } = new();
|
||||||
public List<string> Tags { get; set; } = new();
|
public List<string> Tags { get; set; } = new();
|
||||||
|
|||||||
@ -66,6 +66,8 @@ public partial class SpecificationsStepViewModel : SubmissionViewModel
|
|||||||
viewModel.Summary = State.Summary;
|
viewModel.Summary = State.Summary;
|
||||||
viewModel.Description = State.Description;
|
viewModel.Description = State.Description;
|
||||||
viewModel.IsDefault = State.IsDefault;
|
viewModel.IsDefault = State.IsDefault;
|
||||||
|
viewModel.IsEssential = State.IsEssential;
|
||||||
|
viewModel.IsDeviceProvider = State.IsDeviceProvider;
|
||||||
|
|
||||||
// Tags
|
// Tags
|
||||||
viewModel.Tags.Clear();
|
viewModel.Tags.Clear();
|
||||||
@ -95,6 +97,8 @@ public partial class SpecificationsStepViewModel : SubmissionViewModel
|
|||||||
State.Summary = EntrySpecificationsViewModel.Summary;
|
State.Summary = EntrySpecificationsViewModel.Summary;
|
||||||
State.Description = EntrySpecificationsViewModel.Description;
|
State.Description = EntrySpecificationsViewModel.Description;
|
||||||
State.IsDefault = EntrySpecificationsViewModel.IsDefault;
|
State.IsDefault = EntrySpecificationsViewModel.IsDefault;
|
||||||
|
State.IsEssential = EntrySpecificationsViewModel.IsEssential;
|
||||||
|
State.IsDeviceProvider = EntrySpecificationsViewModel.IsDeviceProvider;
|
||||||
|
|
||||||
// Categories and tasks
|
// Categories and tasks
|
||||||
State.Categories = EntrySpecificationsViewModel.Categories.Where(c => c.IsSelected).Select(c => c.Id).ToList();
|
State.Categories = EntrySpecificationsViewModel.Categories.Where(c => c.IsSelected).Select(c => c.Id).ToList();
|
||||||
|
|||||||
@ -105,7 +105,14 @@ public partial class UploadStepViewModel : SubmissionViewModel
|
|||||||
Summary = State.Summary,
|
Summary = State.Summary,
|
||||||
Description = State.Description,
|
Description = State.Description,
|
||||||
Categories = State.Categories,
|
Categories = State.Categories,
|
||||||
Tags = State.Tags
|
Tags = State.Tags,
|
||||||
|
DefaultEntryInfo = State.IsDefault
|
||||||
|
? new DefaultEntryInfoInput
|
||||||
|
{
|
||||||
|
IsEssential = State.IsEssential,
|
||||||
|
IsDeviceProvider = State.IsDeviceProvider
|
||||||
|
}
|
||||||
|
: null
|
||||||
}, cancellationToken);
|
}, cancellationToken);
|
||||||
|
|
||||||
result.EnsureNoErrors();
|
result.EnsureNoErrors();
|
||||||
|
|||||||
@ -26,7 +26,9 @@ fragment submittedEntry on Entry {
|
|||||||
entryType
|
entryType
|
||||||
downloads
|
downloads
|
||||||
createdAt
|
createdAt
|
||||||
isDefault
|
defaultEntryInfo {
|
||||||
|
...defaultEntryInfo
|
||||||
|
}
|
||||||
latestRelease {
|
latestRelease {
|
||||||
...release
|
...release
|
||||||
}
|
}
|
||||||
@ -48,6 +50,9 @@ fragment entrySummary on Entry {
|
|||||||
categories {
|
categories {
|
||||||
...category
|
...category
|
||||||
}
|
}
|
||||||
|
defaultEntryInfo {
|
||||||
|
...defaultEntryInfo
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fragment entryDetails on Entry {
|
fragment entryDetails on Entry {
|
||||||
@ -96,3 +101,8 @@ fragment pluginInfo on PluginInfo {
|
|||||||
supportsLinux
|
supportsLinux
|
||||||
supportsOSX
|
supportsOSX
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fragment defaultEntryInfo on DefaultEntryInfo {
|
||||||
|
isEssential
|
||||||
|
isDeviceProvider
|
||||||
|
}
|
||||||
@ -20,8 +20,12 @@ query GetPopularEntries {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
query GetDefaultEntries($first: Int $after: String) {
|
query GetDefaultEntries($first: Int, $after: String) {
|
||||||
entriesV2(where: {isDefault: {eq: true}} first: $first after: $after) {
|
entriesV2(
|
||||||
|
where: { defaultEntryInfo: { entryId: { gt: 0 } } }
|
||||||
|
first: $first
|
||||||
|
after: $after
|
||||||
|
) {
|
||||||
totalCount
|
totalCount
|
||||||
pageInfo {
|
pageInfo {
|
||||||
hasNextPage
|
hasNextPage
|
||||||
|
|||||||
@ -2,10 +2,10 @@ namespace Artemis.WebClient.Workshop;
|
|||||||
|
|
||||||
public static class WorkshopConstants
|
public static class WorkshopConstants
|
||||||
{
|
{
|
||||||
// public const string AUTHORITY_URL = "https://localhost:5001";
|
public const string AUTHORITY_URL = "https://localhost:5001";
|
||||||
// public const string WORKSHOP_URL = "https://localhost:7281";
|
public const string WORKSHOP_URL = "https://localhost:7281";
|
||||||
public const string AUTHORITY_URL = "https://identity.artemis-rgb.com";
|
// public const string AUTHORITY_URL = "https://identity.artemis-rgb.com";
|
||||||
public const string WORKSHOP_URL = "https://workshop.artemis-rgb.com";
|
// public const string WORKSHOP_URL = "https://workshop.artemis-rgb.com";
|
||||||
public const string IDENTITY_CLIENT_NAME = "IdentityApiClient";
|
public const string IDENTITY_CLIENT_NAME = "IdentityApiClient";
|
||||||
public const string WORKSHOP_CLIENT_NAME = "WorkshopApiClient";
|
public const string WORKSHOP_CLIENT_NAME = "WorkshopApiClient";
|
||||||
}
|
}
|
||||||
@ -2,7 +2,7 @@ schema: schema.graphql
|
|||||||
extensions:
|
extensions:
|
||||||
endpoints:
|
endpoints:
|
||||||
Default GraphQL Endpoint:
|
Default GraphQL Endpoint:
|
||||||
url: https://workshop.artemis-rgb.com/graphql
|
url: https://localhost:7281/graphql/
|
||||||
headers:
|
headers:
|
||||||
user-agent: JS GraphQL
|
user-agent: JS GraphQL
|
||||||
introspect: true
|
introspect: true
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -27,6 +27,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
|||||||
Artemis.sln.DotSettings.user = Artemis.sln.DotSettings.user
|
Artemis.sln.DotSettings.user = Artemis.sln.DotSettings.user
|
||||||
Directory.Packages.props = Directory.Packages.props
|
Directory.Packages.props = Directory.Packages.props
|
||||||
Directory.Build.props = Directory.Build.props
|
Directory.Build.props = Directory.Build.props
|
||||||
|
Directory.Build.targets = Directory.Build.targets
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Artemis.Storage.Legacy", "Artemis.Storage.Legacy\Artemis.Storage.Legacy.csproj", "{D7B0966D-774A-40E4-9455-00C1261ACB6A}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Artemis.Storage.Legacy", "Artemis.Storage.Legacy\Artemis.Storage.Legacy.csproj", "{D7B0966D-774A-40E4-9455-00C1261ACB6A}"
|
||||||
|
|||||||
12
src/Directory.Build.targets
Normal file
12
src/Directory.Build.targets
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<Project>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
|
||||||
|
<!-- If you're a .vbproj user, replace ';' with ',' -->
|
||||||
|
<DefineConstants>$(DefineConstants);ENABLE_XAML_HOT_RELOAD</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Condition="$(DefineConstants.Contains(ENABLE_XAML_HOT_RELOAD))" Include="Avalonia.Markup.Xaml.Loader" />
|
||||||
|
<PackageReference Condition="$(DefineConstants.Contains(ENABLE_XAML_HOT_RELOAD))" Include="HotAvalonia" />
|
||||||
|
<PackageReference Include="HotAvalonia.Extensions" PrivateAssets="All" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
@ -66,5 +66,9 @@
|
|||||||
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="8.11.0" />
|
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="8.11.0" />
|
||||||
<PackageVersion Include="System.Text.Json" Version="9.0.5" />
|
<PackageVersion Include="System.Text.Json" Version="9.0.5" />
|
||||||
<PackageVersion Include="TextMateSharp.Grammars" Version="1.0.68" />
|
<PackageVersion Include="TextMateSharp.Grammars" Version="1.0.68" />
|
||||||
|
|
||||||
|
<PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="11.3.0" />
|
||||||
|
<PackageVersion Include="HotAvalonia" Version="2.1.0" />
|
||||||
|
<PackageVersion Include="HotAvalonia.Extensions" Version="2.1.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
Loading…
x
Reference in New Issue
Block a user