mirror of
https://github.com/Artemis-RGB/Artemis
synced 2026-02-04 02:43:32 +00:00
Surface editor - Show model instead of device name
Settings - Add link to plugin's workshop page Workshop library - Recently updated tab (WIP)
This commit is contained in:
parent
0823de45a4
commit
74d5480d7b
@ -50,7 +50,8 @@ namespace Artemis.UI.Routing
|
|||||||
new RouteRegistration<SubmissionsTabViewModel>("submissions"),
|
new RouteRegistration<SubmissionsTabViewModel>("submissions"),
|
||||||
new RouteRegistration<SubmissionManagementViewModel>("submissions/{entryId:long}", [
|
new RouteRegistration<SubmissionManagementViewModel>("submissions/{entryId:long}", [
|
||||||
new RouteRegistration<SubmissionReleaseViewModel>("releases/{releaseId:long}")
|
new RouteRegistration<SubmissionReleaseViewModel>("releases/{releaseId:long}")
|
||||||
])
|
]),
|
||||||
|
new RouteRegistration<RecentlyUpdatedViewModel>("recently-updated")
|
||||||
])
|
])
|
||||||
]),
|
]),
|
||||||
new RouteRegistration<SurfaceEditorViewModel>("surface-editor"),
|
new RouteRegistration<SurfaceEditorViewModel>("surface-editor"),
|
||||||
|
|||||||
@ -92,6 +92,12 @@
|
|||||||
ToolTip.Tip="Open settings">
|
ToolTip.Tip="Open settings">
|
||||||
<avalonia:MaterialIcon Kind="Cog" />
|
<avalonia:MaterialIcon Kind="Cog" />
|
||||||
</HyperlinkButton>
|
</HyperlinkButton>
|
||||||
|
<HyperlinkButton Classes="icon-button icon-button-large"
|
||||||
|
IsVisible="{CompiledBinding WorkshopEntry, Converter={x:Static ObjectConverters.IsNotNull}}"
|
||||||
|
Command="{CompiledBinding ViewEntry}"
|
||||||
|
ToolTip.Tip="View on workshop">
|
||||||
|
<avalonia:MaterialIcon Kind="TestTube" />
|
||||||
|
</HyperlinkButton>
|
||||||
<HyperlinkButton Classes="icon-button icon-button-large"
|
<HyperlinkButton Classes="icon-button icon-button-large"
|
||||||
IsVisible="{CompiledBinding PluginInfo.HelpPage, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"
|
IsVisible="{CompiledBinding PluginInfo.HelpPage, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"
|
||||||
NavigateUri="{CompiledBinding PluginInfo.HelpPage}"
|
NavigateUri="{CompiledBinding PluginInfo.HelpPage}"
|
||||||
|
|||||||
@ -11,6 +11,8 @@ using Artemis.UI.Exceptions;
|
|||||||
using Artemis.UI.Services.Interfaces;
|
using Artemis.UI.Services.Interfaces;
|
||||||
using Artemis.UI.Shared;
|
using Artemis.UI.Shared;
|
||||||
using Artemis.UI.Shared.Services;
|
using Artemis.UI.Shared.Services;
|
||||||
|
using Artemis.WebClient.Workshop.Models;
|
||||||
|
using Artemis.WebClient.Workshop.Services;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
using Material.Icons;
|
using Material.Icons;
|
||||||
@ -22,21 +24,25 @@ namespace Artemis.UI.Screens.Plugins;
|
|||||||
public partial class PluginViewModel : ActivatableViewModelBase
|
public partial class PluginViewModel : ActivatableViewModelBase
|
||||||
{
|
{
|
||||||
private readonly IPluginInteractionService _pluginInteractionService;
|
private readonly IPluginInteractionService _pluginInteractionService;
|
||||||
|
private readonly IWorkshopService _workshopService;
|
||||||
private readonly IWindowService _windowService;
|
private readonly IWindowService _windowService;
|
||||||
private Window? _settingsWindow;
|
private Window? _settingsWindow;
|
||||||
[Notify] private bool _canInstallPrerequisites;
|
[Notify] private bool _canInstallPrerequisites;
|
||||||
[Notify] private bool _canRemovePrerequisites;
|
[Notify] private bool _canRemovePrerequisites;
|
||||||
[Notify] private bool _enabling;
|
[Notify] private bool _enabling;
|
||||||
|
[Notify] private InstalledEntry? _workshopEntry;
|
||||||
|
|
||||||
public PluginInfo PluginInfo { get; }
|
public PluginInfo PluginInfo { get; }
|
||||||
public Plugin? Plugin { get; }
|
public Plugin? Plugin { get; }
|
||||||
|
|
||||||
public PluginViewModel(PluginInfo pluginInfo, ReactiveCommand<Unit, Unit>? reload, IWindowService windowService, IPluginInteractionService pluginInteractionService)
|
public PluginViewModel(PluginInfo pluginInfo, ReactiveCommand<Unit, Unit>? reload, IWindowService windowService, IPluginInteractionService pluginInteractionService,
|
||||||
|
IWorkshopService workshopService)
|
||||||
{
|
{
|
||||||
PluginInfo = pluginInfo;
|
PluginInfo = pluginInfo;
|
||||||
Plugin = pluginInfo?.Plugin;
|
Plugin = pluginInfo?.Plugin;
|
||||||
_windowService = windowService;
|
_windowService = windowService;
|
||||||
_pluginInteractionService = pluginInteractionService;
|
_pluginInteractionService = pluginInteractionService;
|
||||||
|
_workshopService = workshopService;
|
||||||
|
|
||||||
Platforms = [];
|
Platforms = [];
|
||||||
if (PluginInfo.Platforms != null)
|
if (PluginInfo.Platforms != null)
|
||||||
@ -51,12 +57,8 @@ public partial class PluginViewModel : ActivatableViewModelBase
|
|||||||
|
|
||||||
Reload = reload;
|
Reload = reload;
|
||||||
OpenSettings = ReactiveCommand.Create(ExecuteOpenSettings, this.WhenAnyValue(vm => vm.IsEnabled, e => e && Plugin?.ConfigurationDialog != null));
|
OpenSettings = ReactiveCommand.Create(ExecuteOpenSettings, this.WhenAnyValue(vm => vm.IsEnabled, e => e && Plugin?.ConfigurationDialog != null));
|
||||||
RemoveSettings = ReactiveCommand.CreateFromTask(ExecuteRemoveSettings);
|
|
||||||
Remove = ReactiveCommand.CreateFromTask(ExecuteRemove);
|
|
||||||
InstallPrerequisites = ReactiveCommand.CreateFromTask(ExecuteInstallPrerequisites, this.WhenAnyValue(x => x.CanInstallPrerequisites));
|
InstallPrerequisites = ReactiveCommand.CreateFromTask(ExecuteInstallPrerequisites, this.WhenAnyValue(x => x.CanInstallPrerequisites));
|
||||||
RemovePrerequisites = ReactiveCommand.CreateFromTask<bool>(ExecuteRemovePrerequisites, this.WhenAnyValue(x => x.CanRemovePrerequisites));
|
RemovePrerequisites = ReactiveCommand.CreateFromTask<bool>(ExecuteRemovePrerequisites, this.WhenAnyValue(x => x.CanRemovePrerequisites));
|
||||||
ShowLogsFolder = ReactiveCommand.Create(ExecuteShowLogsFolder);
|
|
||||||
OpenPluginDirectory = ReactiveCommand.Create(ExecuteOpenPluginDirectory);
|
|
||||||
|
|
||||||
this.WhenActivated(d =>
|
this.WhenActivated(d =>
|
||||||
{
|
{
|
||||||
@ -65,6 +67,7 @@ public partial class PluginViewModel : ActivatableViewModelBase
|
|||||||
|
|
||||||
Plugin.Enabled += OnPluginToggled;
|
Plugin.Enabled += OnPluginToggled;
|
||||||
Plugin.Disabled += OnPluginToggled;
|
Plugin.Disabled += OnPluginToggled;
|
||||||
|
WorkshopEntry = _workshopService.GetInstalledEntryByPlugin(Plugin);
|
||||||
|
|
||||||
Disposable.Create(() =>
|
Disposable.Create(() =>
|
||||||
{
|
{
|
||||||
@ -77,12 +80,8 @@ public partial class PluginViewModel : ActivatableViewModelBase
|
|||||||
|
|
||||||
public ReactiveCommand<Unit, Unit>? Reload { get; }
|
public ReactiveCommand<Unit, Unit>? Reload { get; }
|
||||||
public ReactiveCommand<Unit, Unit> OpenSettings { get; }
|
public ReactiveCommand<Unit, Unit> OpenSettings { get; }
|
||||||
public ReactiveCommand<Unit, Unit> RemoveSettings { get; }
|
|
||||||
public ReactiveCommand<Unit, Unit> Remove { get; }
|
|
||||||
public ReactiveCommand<Unit, Unit> InstallPrerequisites { get; }
|
public ReactiveCommand<Unit, Unit> InstallPrerequisites { get; }
|
||||||
public ReactiveCommand<bool, Unit> RemovePrerequisites { get; }
|
public ReactiveCommand<bool, Unit> RemovePrerequisites { get; }
|
||||||
public ReactiveCommand<Unit, Unit> ShowLogsFolder { get; }
|
|
||||||
public ReactiveCommand<Unit, Unit> OpenPluginDirectory { get; }
|
|
||||||
|
|
||||||
public ObservableCollection<PluginPlatformViewModel> Platforms { get; }
|
public ObservableCollection<PluginPlatformViewModel> Platforms { get; }
|
||||||
public bool IsEnabled => Plugin != null && Plugin.IsEnabled;
|
public bool IsEnabled => Plugin != null && Plugin.IsEnabled;
|
||||||
@ -121,6 +120,68 @@ public partial class PluginViewModel : ActivatableViewModelBase
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void OpenPluginDirectory()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (Plugin != null)
|
||||||
|
Utilities.OpenFolder(Plugin.Directory.FullName);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_windowService.ShowExceptionDialog("Welp, we couldn't open the device's plugin folder for you", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task RemoveSettings()
|
||||||
|
{
|
||||||
|
if (Plugin == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
await _pluginInteractionService.RemovePluginSettings(Plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Remove()
|
||||||
|
{
|
||||||
|
if (Plugin == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
await _pluginInteractionService.RemovePlugin(Plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task AutoEnable()
|
||||||
|
{
|
||||||
|
if (IsEnabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
await UpdateEnabled(true);
|
||||||
|
|
||||||
|
// If enabling failed, don't offer to show the settings
|
||||||
|
if (!IsEnabled || Plugin?.ConfigurationDialog == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (await _windowService.ShowConfirmContentDialog("Open plugin settings", "This plugin has settings, would you like to view them?", "Yes", "No"))
|
||||||
|
ExecuteOpenSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task ViewEntry()
|
||||||
|
{
|
||||||
|
if (WorkshopEntry != null)
|
||||||
|
await _workshopService.NavigateToEntry(WorkshopEntry.Id, WorkshopEntry.EntryType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task ExecuteRemovePrerequisites(bool forPluginRemoval = false)
|
||||||
|
{
|
||||||
|
if (Plugin == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
List<IPrerequisitesSubject> subjects = [PluginInfo];
|
||||||
|
subjects.AddRange(!forPluginRemoval ? Plugin.Features.Where(f => f.AlwaysEnabled) : Plugin.Features);
|
||||||
|
|
||||||
|
if (subjects.Any(s => s.PlatformPrerequisites.Any(p => p.UninstallActions.Any())))
|
||||||
|
await PluginPrerequisitesUninstallDialogViewModel.Show(_windowService, subjects, forPluginRemoval ? "Skip, remove plugin" : "Cancel");
|
||||||
|
}
|
||||||
|
|
||||||
private void ExecuteOpenSettings()
|
private void ExecuteOpenSettings()
|
||||||
{
|
{
|
||||||
if (Plugin?.ConfigurationDialog == null)
|
if (Plugin?.ConfigurationDialog == null)
|
||||||
@ -148,19 +209,6 @@ public partial class PluginViewModel : ActivatableViewModelBase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ExecuteOpenPluginDirectory()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (Plugin != null)
|
|
||||||
Utilities.OpenFolder(Plugin.Directory.FullName);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
_windowService.ShowExceptionDialog("Welp, we couldn't open the device's plugin folder for you", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task ExecuteInstallPrerequisites()
|
private async Task ExecuteInstallPrerequisites()
|
||||||
{
|
{
|
||||||
if (Plugin == null)
|
if (Plugin == null)
|
||||||
@ -173,46 +221,6 @@ public partial class PluginViewModel : ActivatableViewModelBase
|
|||||||
await PluginPrerequisitesInstallDialogViewModel.Show(_windowService, subjects);
|
await PluginPrerequisitesInstallDialogViewModel.Show(_windowService, subjects);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task ExecuteRemovePrerequisites(bool forPluginRemoval = false)
|
|
||||||
{
|
|
||||||
if (Plugin == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
List<IPrerequisitesSubject> subjects = [PluginInfo];
|
|
||||||
subjects.AddRange(!forPluginRemoval ? Plugin.Features.Where(f => f.AlwaysEnabled) : Plugin.Features);
|
|
||||||
|
|
||||||
if (subjects.Any(s => s.PlatformPrerequisites.Any(p => p.UninstallActions.Any())))
|
|
||||||
await PluginPrerequisitesUninstallDialogViewModel.Show(_windowService, subjects, forPluginRemoval ? "Skip, remove plugin" : "Cancel");
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task ExecuteRemoveSettings()
|
|
||||||
{
|
|
||||||
if (Plugin == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
await _pluginInteractionService.RemovePluginSettings(Plugin);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task ExecuteRemove()
|
|
||||||
{
|
|
||||||
if (Plugin == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
await _pluginInteractionService.RemovePlugin(Plugin);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ExecuteShowLogsFolder()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Utilities.OpenFolder(Constants.LogsFolder);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
_windowService.ShowExceptionDialog("Welp, we couldn\'t open the logs folder for you", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnPluginToggled(object? sender, EventArgs e)
|
private void OnPluginToggled(object? sender, EventArgs e)
|
||||||
{
|
{
|
||||||
Dispatcher.UIThread.Post(() =>
|
Dispatcher.UIThread.Post(() =>
|
||||||
@ -222,19 +230,4 @@ public partial class PluginViewModel : ActivatableViewModelBase
|
|||||||
_settingsWindow?.Close();
|
_settingsWindow?.Close();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task AutoEnable()
|
|
||||||
{
|
|
||||||
if (IsEnabled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
await UpdateEnabled(true);
|
|
||||||
|
|
||||||
// If enabling failed, don't offer to show the settings
|
|
||||||
if (!IsEnabled || Plugin?.ConfigurationDialog == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (await _windowService.ShowConfirmContentDialog("Open plugin settings", "This plugin has settings, would you like to view them?", "Yes", "No"))
|
|
||||||
ExecuteOpenSettings();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@ -11,7 +11,7 @@
|
|||||||
<Border Grid.Column="0" Grid.RowSpan="2" Width="64" Height="50" Margin="0 0 10 0">
|
<Border Grid.Column="0" Grid.RowSpan="2" Width="64" Height="50" Margin="0 0 10 0">
|
||||||
<shared:DeviceVisualizer Device="{CompiledBinding Device}" ShowColors="True" VerticalAlignment="Center" HorizontalAlignment="Center" RenderOptions.BitmapInterpolationMode="MediumQuality"/>
|
<shared:DeviceVisualizer Device="{CompiledBinding Device}" ShowColors="True" VerticalAlignment="Center" HorizontalAlignment="Center" RenderOptions.BitmapInterpolationMode="MediumQuality"/>
|
||||||
</Border>
|
</Border>
|
||||||
<TextBlock Grid.Column="1" Grid.Row="0" Text="{CompiledBinding Device.RgbDevice.DeviceInfo.DeviceName}" VerticalAlignment="Bottom" />
|
<TextBlock Grid.Column="1" Grid.Row="0" Text="{CompiledBinding Device.RgbDevice.DeviceInfo.Model}" VerticalAlignment="Bottom" />
|
||||||
<TextBlock Grid.Column="1" Grid.Row="1" Classes="subtitle" Text="{CompiledBinding Device.RgbDevice.DeviceInfo.Manufacturer}" VerticalAlignment="Top" />
|
<TextBlock Grid.Column="1" Grid.Row="1" Classes="subtitle" Text="{CompiledBinding Device.RgbDevice.DeviceInfo.Manufacturer}" VerticalAlignment="Top" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
<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:tabs="clr-namespace:Artemis.UI.Screens.Workshop.Library.Tabs"
|
||||||
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
|
x:Class="Artemis.UI.Screens.Workshop.Library.Tabs.RecentlyUpdatedItemView"
|
||||||
|
x:DataType="tabs:RecentlyUpdatedItemViewModel">
|
||||||
|
Welcome to Avalonia!
|
||||||
|
</UserControl>
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
using ReactiveUI.Avalonia;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Screens.Workshop.Library.Tabs;
|
||||||
|
|
||||||
|
public partial class RecentlyUpdatedItemView : ReactiveUserControl<RecentlyUpdatedItemViewModel>
|
||||||
|
{
|
||||||
|
public RecentlyUpdatedItemView()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
using Artemis.UI.Shared;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Screens.Workshop.Library.Tabs;
|
||||||
|
|
||||||
|
public partial class RecentlyUpdatedItemViewModel : ActivatableViewModelBase
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
<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:tabs="clr-namespace:Artemis.UI.Screens.Workshop.Library.Tabs"
|
||||||
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
|
x:Class="Artemis.UI.Screens.Workshop.Library.Tabs.RecentlyUpdatedView"
|
||||||
|
x:DataType="tabs:RecentlyUpdatedViewModel">
|
||||||
|
Welcome to Avalonia!
|
||||||
|
</UserControl>
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
using ReactiveUI.Avalonia;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Screens.Workshop.Library.Tabs;
|
||||||
|
|
||||||
|
public partial class RecentlyUpdatedView : ReactiveUserControl<InstalledTabViewModel>
|
||||||
|
{
|
||||||
|
public RecentlyUpdatedView()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
using Artemis.UI.Shared.Routing;
|
||||||
|
|
||||||
|
namespace Artemis.UI.Screens.Workshop.Library.Tabs;
|
||||||
|
|
||||||
|
public partial class RecentlyUpdatedViewModel : RoutableScreen
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@ -26,7 +26,8 @@ public partial class WorkshopLibraryViewModel : RoutableHostScreen<RoutableScree
|
|||||||
Tabs =
|
Tabs =
|
||||||
[
|
[
|
||||||
new RouteViewModel("Installed", "workshop/library/installed"),
|
new RouteViewModel("Installed", "workshop/library/installed"),
|
||||||
new RouteViewModel("Submissions", "workshop/library/submissions")
|
new RouteViewModel("Submissions", "workshop/library/submissions"),
|
||||||
|
new RouteViewModel("Recently Updated", "workshop/library/recently-updated")
|
||||||
];
|
];
|
||||||
|
|
||||||
this.WhenActivated(d =>
|
this.WhenActivated(d =>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user