1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-13 05:48:35 +00:00

Update service - Removed option to install updates without asking

Modules - Decrease CPU usage for activation requirements check by using a centralized service
Devices - Reload provider when unloading a layout
This commit is contained in:
Robert 2021-06-10 17:41:54 +02:00
parent 38c04913e2
commit fe933f60e8
17 changed files with 195 additions and 135 deletions

View File

@ -549,11 +549,6 @@ namespace Artemis.Core
else else
LogicalLayout = DeviceEntity.LogicalLayout; LogicalLayout = DeviceEntity.LogicalLayout;
} }
public void ClearLayout()
{
// TODO
}
} }
/// <summary> /// <summary>

View File

@ -3,6 +3,8 @@ using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using Artemis.Core.Services;
using Ninject;
namespace Artemis.Core.Modules namespace Artemis.Core.Modules
{ {
@ -11,6 +13,8 @@ namespace Artemis.Core.Modules
/// </summary> /// </summary>
public class ProcessActivationRequirement : IModuleActivationRequirement public class ProcessActivationRequirement : IModuleActivationRequirement
{ {
private readonly IProcessMonitorService _processMonitorService;
/// <summary> /// <summary>
/// Creates a new instance of the <see cref="ProcessActivationRequirement" /> class /// Creates a new instance of the <see cref="ProcessActivationRequirement" /> class
/// </summary> /// </summary>
@ -18,6 +22,14 @@ namespace Artemis.Core.Modules
/// <param name="location">The location of where the process must be running from (optional)</param> /// <param name="location">The location of where the process must be running from (optional)</param>
public ProcessActivationRequirement(string? processName, string? location = null) public ProcessActivationRequirement(string? processName, string? location = null)
{ {
if (string.IsNullOrWhiteSpace(ProcessName) && string.IsNullOrWhiteSpace(Location))
throw new ArgumentNullException($"Atleast one {nameof(processName)} and {nameof(location)} must not be null");
// Let's not make a habit out of this :P
if (CoreService.Kernel == null)
throw new ArtemisCoreException("Cannot create a ProcessActivationRequirement before initializing the Core");
_processMonitorService = CoreService.Kernel.Get<IProcessMonitorService>();
ProcessName = processName; ProcessName = processName;
Location = location; Location = location;
} }
@ -38,10 +50,13 @@ namespace Artemis.Core.Modules
if (ProcessName == null && Location == null) if (ProcessName == null && Location == null)
return false; return false;
IEnumerable<Process> processes = ProcessName != null ? Process.GetProcessesByName(ProcessName).Where(p => !p.HasExited) : Process.GetProcesses().Where(p => !p.HasExited); IEnumerable<Process> processes = _processMonitorService.GetRunningProcesses().Where(p => !p.HasExited);
return Location != null if (ProcessName != null)
? processes.Any(p => string.Equals(Path.GetDirectoryName(p.GetProcessFilename()), Location, StringComparison.CurrentCultureIgnoreCase)) processes = processes.Where(p => string.Equals(p.ProcessName, ProcessName, StringComparison.InvariantCultureIgnoreCase));
: processes.Any(); if (Location != null)
processes = processes.Where(p => string.Equals(Path.GetDirectoryName(p.GetProcessFilename()), Location, StringComparison.InvariantCultureIgnoreCase));
return processes.Any();
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@ -22,6 +22,8 @@ namespace Artemis.Core
internal TimedUpdateRegistration(PluginFeature feature, TimeSpan interval, Action<double> action, string? name) internal TimedUpdateRegistration(PluginFeature feature, TimeSpan interval, Action<double> action, string? name)
{ {
if (CoreService.Kernel == null)
throw new ArtemisCoreException("Cannot create a TimedUpdateRegistration before initializing the Core");
_logger = CoreService.Kernel.Get<ILogger>(); _logger = CoreService.Kernel.Get<ILogger>();
Feature = feature; Feature = feature;
@ -37,6 +39,8 @@ namespace Artemis.Core
internal TimedUpdateRegistration(PluginFeature feature, TimeSpan interval, Func<double, Task> asyncAction, string? name) internal TimedUpdateRegistration(PluginFeature feature, TimeSpan interval, Func<double, Task> asyncAction, string? name)
{ {
if (CoreService.Kernel == null)
throw new ArtemisCoreException("Cannot create a TimedUpdateRegistration before initializing the Core");
_logger = CoreService.Kernel.Get<ILogger>(); _logger = CoreService.Kernel.Get<ILogger>();
Feature = feature; Feature = feature;

View File

@ -22,7 +22,7 @@ namespace Artemis.Core.Services
/// </summary> /// </summary>
internal class CoreService : ICoreService internal class CoreService : ICoreService
{ {
internal static IKernel Kernel = null!; internal static IKernel? Kernel;
private readonly Stopwatch _frameStopWatch; private readonly Stopwatch _frameStopWatch;
private readonly ILogger _logger; private readonly ILogger _logger;
@ -201,7 +201,7 @@ namespace Artemis.Core.Services
Version? hidSharpVersion = Assembly.GetAssembly(typeof(HidDevice))!.GetName().Version; Version? hidSharpVersion = Assembly.GetAssembly(typeof(HidDevice))!.GetName().Version;
_logger.Debug("Forcing plugins to use HidSharp {hidSharpVersion}", hidSharpVersion); _logger.Debug("Forcing plugins to use HidSharp {hidSharpVersion}", hidSharpVersion);
DeserializationLogger.Initialize(Kernel); DeserializationLogger.Initialize(Kernel!);
// Initialize the services // Initialize the services
_pluginManagementService.CopyBuiltInPlugins(); _pluginManagementService.CopyBuiltInPlugins();

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading;
using Artemis.Core.DeviceProviders; using Artemis.Core.DeviceProviders;
using Artemis.Core.Services.Models; using Artemis.Core.Services.Models;
using Artemis.Core.SkiaSharp; using Artemis.Core.SkiaSharp;
@ -345,6 +346,13 @@ namespace Artemis.Core.Services
return layout; return layout;
} }
if (device.DisableDefaultLayout)
{
layout = null;
ApplyDeviceLayout(device, layout);
return null;
}
// Look for a layout provided by the plugin // Look for a layout provided by the plugin
layout = device.DeviceProvider.LoadLayout(device); layout = device.DeviceProvider.LoadLayout(device);
if (layout.IsValid) if (layout.IsValid)
@ -354,7 +362,6 @@ namespace Artemis.Core.Services
} }
// Finally fall back to a default layout // Finally fall back to a default layout
if (!device.DisableDefaultLayout)
layout = ArtemisLayout.GetDefaultLayout(device); layout = ArtemisLayout.GetDefaultLayout(device);
ApplyDeviceLayout(device, layout); ApplyDeviceLayout(device, layout);
return layout; return layout;
@ -365,7 +372,7 @@ namespace Artemis.Core.Services
if (layout == null) if (layout == null)
{ {
if (device.Layout != null) if (device.Layout != null)
device.ClearLayout(); ReloadDevice(device);
return; return;
} }
@ -377,6 +384,16 @@ namespace Artemis.Core.Services
UpdateLedGroup(); UpdateLedGroup();
} }
private void ReloadDevice(ArtemisDevice device)
{
DeviceProvider deviceProvider = device.DeviceProvider;
// Feels bad but need to in order to get the initial LEDs back
_pluginManagementService.DisablePluginFeature(deviceProvider, false);
Thread.Sleep(500);
_pluginManagementService.EnablePluginFeature(deviceProvider, false);
}
public ArtemisDevice? GetDevice(IRGBDevice rgbDevice) public ArtemisDevice? GetDevice(IRGBDevice rgbDevice)
{ {
return _devices.FirstOrDefault(d => d.RgbDevice == rgbDevice); return _devices.FirstOrDefault(d => d.RgbDevice == rgbDevice);

View File

@ -9,6 +9,7 @@ using System.Windows.Media;
using Artemis.Core; using Artemis.Core;
using Artemis.Core.LayerEffects; using Artemis.Core.LayerEffects;
using Artemis.Core.Services; using Artemis.Core.Services;
using Artemis.UI.Extensions;
using Artemis.UI.Ninject.Factories; using Artemis.UI.Ninject.Factories;
using Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings; using Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings;
using Artemis.UI.Screens.ProfileEditor.LayerProperties.LayerEffects; using Artemis.UI.Screens.ProfileEditor.LayerProperties.LayerEffects;
@ -220,7 +221,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
private void SelectedProfileEditorServiceOnSelectedProfileElementChanged(object sender, RenderProfileElementEventArgs e) private void SelectedProfileEditorServiceOnSelectedProfileElementChanged(object sender, RenderProfileElementEventArgs e)
{ {
PopulateProperties(e.RenderProfileElement); Execute.PostToUIThread(() => PopulateProperties(e.RenderProfileElement));
} }
private void ProfileEditorServiceOnCurrentTimeChanged(object sender, EventArgs e) private void ProfileEditorServiceOnCurrentTimeChanged(object sender, EventArgs e)
@ -347,7 +348,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
.ToList(); .ToList();
// Order the effects // Order the effects
List<LayerPropertyGroupViewModel> effectProperties = Items List<LayerPropertyGroupViewModel> effectProperties = Items
.Where(l => l.TreeGroupViewModel.GroupType == LayerEffectRoot) .Where(l => l.TreeGroupViewModel.GroupType == LayerEffectRoot && l.LayerPropertyGroup.LayerEffect != null)
.OrderBy(l => l.LayerPropertyGroup.LayerEffect.Order) .OrderBy(l => l.LayerPropertyGroup.LayerEffect.Order)
.ToList(); .ToList();
@ -355,6 +356,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
for (int index = 0; index < nonEffectProperties.Count; index++) for (int index = 0; index < nonEffectProperties.Count; index++)
{ {
LayerPropertyGroupViewModel layerPropertyGroupViewModel = nonEffectProperties[index]; LayerPropertyGroupViewModel layerPropertyGroupViewModel = nonEffectProperties[index];
if (Items.IndexOf(layerPropertyGroupViewModel) != index)
((BindableCollection<LayerPropertyGroupViewModel>) Items).Move(Items.IndexOf(layerPropertyGroupViewModel), index); ((BindableCollection<LayerPropertyGroupViewModel>) Items).Move(Items.IndexOf(layerPropertyGroupViewModel), index);
} }
@ -362,6 +364,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties
for (int index = 0; index < effectProperties.Count; index++) for (int index = 0; index < effectProperties.Count; index++)
{ {
LayerPropertyGroupViewModel layerPropertyGroupViewModel = effectProperties[index]; LayerPropertyGroupViewModel layerPropertyGroupViewModel = effectProperties[index];
if (Items.IndexOf(layerPropertyGroupViewModel) != index + nonEffectProperties.Count)
((BindableCollection<LayerPropertyGroupViewModel>) Items).Move(Items.IndexOf(layerPropertyGroupViewModel), index + nonEffectProperties.Count); ((BindableCollection<LayerPropertyGroupViewModel>) Items).Move(Items.IndexOf(layerPropertyGroupViewModel), index + nonEffectProperties.Count);
} }
} }

View File

@ -15,6 +15,15 @@
d:DataContext="{d:DesignInstance {x:Type profileTree1:ProfileTreeViewModel}}"> d:DataContext="{d:DesignInstance {x:Type profileTree1:ProfileTreeViewModel}}">
<materialDesign:DialogHost IsTabStop="False" Focusable="False" Identifier="ProfileTreeDialog" DialogTheme="Inherit"> <materialDesign:DialogHost IsTabStop="False" Focusable="False" Identifier="ProfileTreeDialog" DialogTheme="Inherit">
<Grid> <Grid>
<Grid.Resources>
<DataTemplate x:Key="ElementDragTemplate" DataType="{x:Type treeItem:TreeItemViewModel}">
<Border Background="{DynamicResource MaterialDesignTextFieldBoxHoverBackground}"
Padding="10"
CornerRadius="4">
<TextBlock Text="{Binding ProfileElement.Name}" VerticalAlignment="Center" Foreground="{DynamicResource MaterialDesignBody}" />
</Border>
</DataTemplate>
</Grid.Resources>
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="*" /> <RowDefinition Height="*" />
@ -33,7 +42,10 @@
dd:DragDrop.IsDragSource="True" dd:DragDrop.IsDragSource="True"
dd:DragDrop.IsDropTarget="True" dd:DragDrop.IsDropTarget="True"
dd:DragDrop.DropHandler="{Binding}" dd:DragDrop.DropHandler="{Binding}"
ContextMenuOpening="{s:Action ContextMenuOpening}"> dd:DragDrop.DragAdornerTemplate="{StaticResource ElementDragTemplate}"
ContextMenuOpening="{s:Action ContextMenuOpening}"
PreviewMouseDown="{s:Action TreeViewPreviewMouseDown}"
PreviewMouseUp="{s:Action TreeViewPreviewMouseUp}">
<TreeView.InputBindings> <TreeView.InputBindings>
<KeyBinding Key="F2" Command="{s:Action RenameElement}" s:View.ActionTarget="{Binding SelectedTreeItem}" /> <KeyBinding Key="F2" Command="{s:Action RenameElement}" s:View.ActionTarget="{Binding SelectedTreeItem}" />
<KeyBinding Key="Delete" Command="{s:Action DeleteElement}" s:View.ActionTarget="{Binding SelectedTreeItem}" /> <KeyBinding Key="Delete" Command="{s:Action DeleteElement}" s:View.ActionTarget="{Binding SelectedTreeItem}" />
@ -83,7 +95,7 @@
</ContextMenu> </ContextMenu>
</TreeView.ContextMenu> </TreeView.ContextMenu>
<b:Interaction.Behaviors> <b:Interaction.Behaviors>
<behaviors:TreeViewSelectionBehavior SelectedItem="{Binding SelectedTreeItem}" /> <behaviors:TreeViewSelectionBehavior SelectedItem="{Binding SelectedTreeItem, IsAsync=True}" />
</b:Interaction.Behaviors> </b:Interaction.Behaviors>
<TreeView.Resources> <TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type treeItem:FolderViewModel}" ItemsSource="{Binding Items}"> <HierarchicalDataTemplate DataType="{x:Type treeItem:FolderViewModel}" ItemsSource="{Binding Items}">

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Linq; using System.Linq;
using System.Windows; using System.Windows;
using System.Windows.Input;
using Artemis.Core; using Artemis.Core;
using Artemis.UI.Ninject.Factories; using Artemis.UI.Ninject.Factories;
using Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem; using Artemis.UI.Screens.ProfileEditor.ProfileTree.TreeItem;
@ -15,6 +16,7 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree
{ {
private readonly IProfileEditorService _profileEditorService; private readonly IProfileEditorService _profileEditorService;
private readonly IProfileTreeVmFactory _profileTreeVmFactory; private readonly IProfileTreeVmFactory _profileTreeVmFactory;
private bool _draggingTreeView;
private TreeItemViewModel _selectedTreeItem; private TreeItemViewModel _selectedTreeItem;
private bool _updatingTree; private bool _updatingTree;
@ -33,16 +35,25 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree
{ {
if (_updatingTree) return; if (_updatingTree) return;
if (!SetAndNotify(ref _selectedTreeItem, value)) return; if (!SetAndNotify(ref _selectedTreeItem, value)) return;
if (_draggingTreeView) return;
if (value != null && value.ProfileElement is RenderProfileElement renderElement) ApplySelectedTreeItem();
_profileEditorService.ChangeSelectedProfileElement(renderElement);
else
_profileEditorService.ChangeSelectedProfileElement(null);
} }
} }
public bool CanPasteElement => _profileEditorService.GetCanPasteProfileElement(); public bool CanPasteElement => _profileEditorService.GetCanPasteProfileElement();
public void TreeViewPreviewMouseDown(object sender, MouseButtonEventArgs e)
{
_draggingTreeView = true;
}
public void TreeViewPreviewMouseUp(object sender, MouseButtonEventArgs e)
{
_draggingTreeView = false;
ApplySelectedTreeItem();
}
protected override void OnInitialActivate() protected override void OnInitialActivate()
{ {
Subscribe(); Subscribe();
@ -55,6 +66,14 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree
base.OnClose(); base.OnClose();
} }
private void ApplySelectedTreeItem()
{
if (_selectedTreeItem != null && _selectedTreeItem.ProfileElement is RenderProfileElement renderElement)
_profileEditorService.ChangeSelectedProfileElement(renderElement);
else
_profileEditorService.ChangeSelectedProfileElement(null);
}
private void CreateRootFolderViewModel() private void CreateRootFolderViewModel()
{ {
_updatingTree = true; _updatingTree = true;

View File

@ -25,9 +25,11 @@ namespace Artemis.UI.Screens.Settings.Device
private readonly ICoreService _coreService; private readonly ICoreService _coreService;
private readonly IDeviceService _deviceService; private readonly IDeviceService _deviceService;
private readonly IDialogService _dialogService; private readonly IDialogService _dialogService;
private readonly IDeviceDebugVmFactory _factory;
private readonly IRgbService _rgbService; private readonly IRgbService _rgbService;
private SnackbarMessageQueue _deviceMessageQueue; private SnackbarMessageQueue _deviceMessageQueue;
private BindableCollection<ArtemisLed> _selectedLeds; private BindableCollection<ArtemisLed> _selectedLeds;
private ArtemisDevice _device;
public DeviceDialogViewModel(ArtemisDevice device, public DeviceDialogViewModel(ArtemisDevice device,
ICoreService coreService, ICoreService coreService,
@ -40,22 +42,46 @@ namespace Artemis.UI.Screens.Settings.Device
_deviceService = deviceService; _deviceService = deviceService;
_rgbService = rgbService; _rgbService = rgbService;
_dialogService = dialogService; _dialogService = dialogService;
_factory = factory;
Device = device;
PanZoomViewModel = new PanZoomViewModel(); PanZoomViewModel = new PanZoomViewModel();
SelectedLeds = new BindableCollection<ArtemisLed>(); SelectedLeds = new BindableCollection<ArtemisLed>();
Items.Add(factory.DevicePropertiesTabViewModel(device)); Initialize(device);
if (device.DeviceType == RGBDeviceType.Keyboard) }
Items.Add(factory.InputMappingsTabViewModel(device));
Items.Add(factory.DeviceInfoTabViewModel(device)); private void Initialize(ArtemisDevice device)
Items.Add(factory.DeviceLedsTabViewModel(device)); {
if (SelectedLeds.Any())
ActiveItem = Items.First(); SelectedLeds.Clear();
DisplayName = $"{device.RgbDevice.DeviceInfo.Model} | Artemis";
if (Device != null)
Device.DeviceUpdated -= DeviceOnDeviceUpdated;
Device = device;
Device.DeviceUpdated += DeviceOnDeviceUpdated;
int activeTabIndex = 0;
if (Items.Any())
{
activeTabIndex = Items.IndexOf(ActiveItem);
Items.Clear();
}
Items.Add(_factory.DevicePropertiesTabViewModel(Device));
if (Device.DeviceType == RGBDeviceType.Keyboard)
Items.Add(_factory.InputMappingsTabViewModel(Device));
Items.Add(_factory.DeviceInfoTabViewModel(Device));
Items.Add(_factory.DeviceLedsTabViewModel(Device));
ActiveItem = Items[activeTabIndex];
DisplayName = $"{Device.RgbDevice.DeviceInfo.Model} | Artemis";
}
public ArtemisDevice Device
{
get => _device;
set => SetAndNotify(ref _device, value);
} }
public ArtemisDevice Device { get; }
public PanZoomViewModel PanZoomViewModel { get; } public PanZoomViewModel PanZoomViewModel { get; }
public SnackbarMessageQueue DeviceMessageQueue public SnackbarMessageQueue DeviceMessageQueue
@ -84,14 +110,21 @@ namespace Artemis.UI.Screens.Settings.Device
protected override void OnInitialActivate() protected override void OnInitialActivate()
{ {
_coreService.FrameRendering += CoreServiceOnFrameRendering; _coreService.FrameRendering += CoreServiceOnFrameRendering;
_rgbService.DeviceAdded += RgbServiceOnDeviceAdded;
DeviceMessageQueue = new SnackbarMessageQueue(TimeSpan.FromSeconds(5)); DeviceMessageQueue = new SnackbarMessageQueue(TimeSpan.FromSeconds(5));
Device.DeviceUpdated += DeviceOnDeviceUpdated;
base.OnInitialActivate(); base.OnInitialActivate();
} }
private void RgbServiceOnDeviceAdded(object sender, DeviceEventArgs e)
{
if (e.Device != Device && e.Device.Identifier == Device.Identifier)
Execute.OnUIThread(() => Initialize(e.Device));
}
protected override void OnClose() protected override void OnClose()
{ {
_coreService.FrameRendering -= CoreServiceOnFrameRendering; _coreService.FrameRendering -= CoreServiceOnFrameRendering;
_rgbService.DeviceAdded -= RgbServiceOnDeviceAdded;
Device.DeviceUpdated -= DeviceOnDeviceUpdated; Device.DeviceUpdated -= DeviceOnDeviceUpdated;
base.OnClose(); base.OnClose();
} }

View File

@ -202,12 +202,12 @@
The device layout is used to determine the position of LEDs and to create the visual representation of the device you see on the left side of this window. The device layout is used to determine the position of LEDs and to create the visual representation of the device you see on the left side of this window.
</TextBlock> </TextBlock>
<CheckBox Margin="0 0 0 5" Style="{StaticResource MaterialDesignCheckBox}" IsChecked="{Binding UseDefaultLayout}"> <CheckBox Margin="0 0 0 5" Style="{StaticResource MaterialDesignCheckBox}" IsChecked="{Binding Device.DisableDefaultLayout, Delay=300}">
<CheckBox.Content> <CheckBox.Content>
<TextBlock Margin="0 -5 0 0"> <TextBlock Margin="0 -5 0 0">
Use default layout if needed Don't load default layout
<materialDesign:PackIcon Kind="HelpCircle" <materialDesign:PackIcon Kind="HelpCircle"
ToolTip="If there is no built-in layout and no custom layout, with this enabled Artemis will fall back to the default layout of this device type." /> ToolTip="With this enabled Artemis will not load a layout for this device unless you specifically provide one." />
</TextBlock> </TextBlock>
</CheckBox.Content> </CheckBox.Content>
</CheckBox> </CheckBox>

View File

@ -134,16 +134,6 @@ namespace Artemis.UI.Screens.Settings.Device.Tabs
set => SetCategory(DeviceCategory.Peripherals, value); set => SetCategory(DeviceCategory.Peripherals, value);
} }
public bool UseDefaultLayout
{
get => !Device.DisableDefaultLayout;
set
{
Device.DisableDefaultLayout = !value;
NotifyOfPropertyChange(nameof(UseDefaultLayout));
}
}
public void ApplyScaling() public void ApplyScaling()
{ {
Device.RedScale = RedScale / 100f; Device.RedScale = RedScale / 100f;
@ -266,7 +256,9 @@ namespace Artemis.UI.Screens.Settings.Device.Tabs
private void DeviceOnPropertyChanged(object sender, PropertyChangedEventArgs e) private void DeviceOnPropertyChanged(object sender, PropertyChangedEventArgs e)
{ {
if (e.PropertyName == nameof(Device.CustomLayoutPath) || e.PropertyName == nameof(Device.DisableDefaultLayout)) if (e.PropertyName == nameof(Device.CustomLayoutPath) || e.PropertyName == nameof(Device.DisableDefaultLayout))
_rgbService.ApplyBestDeviceLayout(Device); {
Task.Run(() => _rgbService.ApplyBestDeviceLayout(Device));
}
} }
private void OnFrameRendering(object sender, FrameRenderingEventArgs e) private void OnFrameRendering(object sender, FrameRenderingEventArgs e)

View File

@ -1,6 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Artemis.Core;
using Artemis.Core.Services; using Artemis.Core.Services;
using Artemis.UI.Ninject.Factories; using Artemis.UI.Ninject.Factories;
using Artemis.UI.Shared.Services; using Artemis.UI.Shared.Services;
@ -10,9 +11,9 @@ namespace Artemis.UI.Screens.Settings.Tabs.Devices
{ {
public class DeviceSettingsTabViewModel : Conductor<DeviceSettingsViewModel>.Collection.AllActive public class DeviceSettingsTabViewModel : Conductor<DeviceSettingsViewModel>.Collection.AllActive
{ {
private readonly ISettingsVmFactory _settingsVmFactory;
private readonly IRgbService _rgbService;
private readonly IDialogService _dialogService; private readonly IDialogService _dialogService;
private readonly IRgbService _rgbService;
private readonly ISettingsVmFactory _settingsVmFactory;
private bool _confirmedDisable; private bool _confirmedDisable;
public DeviceSettingsTabViewModel(IRgbService rgbService, IDialogService dialogService, ISettingsVmFactory settingsVmFactory) public DeviceSettingsTabViewModel(IRgbService rgbService, IDialogService dialogService, ISettingsVmFactory settingsVmFactory)
@ -24,28 +25,6 @@ namespace Artemis.UI.Screens.Settings.Tabs.Devices
_settingsVmFactory = settingsVmFactory; _settingsVmFactory = settingsVmFactory;
} }
#region Overrides of AllActive
/// <inheritdoc />
protected override void OnActivate()
{
// Take it off the UI thread to avoid freezing on tab change
Task.Run(async () =>
{
if (Items.Any())
Items.Clear();
await Task.Delay(200);
List<DeviceSettingsViewModel> instances = _rgbService.Devices.Select(d => _settingsVmFactory.CreateDeviceSettingsViewModel(d)).ToList();
foreach (DeviceSettingsViewModel deviceSettingsViewModel in instances)
Items.Add(deviceSettingsViewModel);
});
base.OnActivate();
}
#endregion
public async Task<bool> ShowDeviceDisableDialog() public async Task<bool> ShowDeviceDisableDialog()
{ {
if (_confirmedDisable) if (_confirmedDisable)
@ -61,5 +40,49 @@ namespace Artemis.UI.Screens.Settings.Tabs.Devices
return confirmed; return confirmed;
} }
private void RgbServiceOnDeviceRemoved(object sender, DeviceEventArgs e)
{
DeviceSettingsViewModel viewModel = Items.FirstOrDefault(i => i.Device == e.Device);
if (viewModel != null)
Items.Remove(viewModel);
}
private void RgbServiceOnDeviceAdded(object sender, DeviceEventArgs e)
{
Items.Add(_settingsVmFactory.CreateDeviceSettingsViewModel(e.Device));
}
#region Overrides of AllActive
/// <inheritdoc />
protected override void OnActivate()
{
_rgbService.DeviceAdded += RgbServiceOnDeviceAdded;
_rgbService.DeviceRemoved += RgbServiceOnDeviceRemoved;
// Take it off the UI thread to avoid freezing on tab change
Task.Run(async () =>
{
if (Items.Any())
Items.Clear();
await Task.Delay(200);
List<DeviceSettingsViewModel> instances = _rgbService.Devices.Select(d => _settingsVmFactory.CreateDeviceSettingsViewModel(d)).ToList();
foreach (DeviceSettingsViewModel deviceSettingsViewModel in instances)
Items.Add(deviceSettingsViewModel);
});
base.OnActivate();
}
/// <inheritdoc />
protected override void OnClose()
{
_rgbService.DeviceAdded -= RgbServiceOnDeviceAdded;
_rgbService.DeviceRemoved -= RgbServiceOnDeviceRemoved;
base.OnClose();
}
#endregion
} }
} }

View File

@ -218,27 +218,6 @@
</Grid> </Grid>
<Separator Style="{StaticResource MaterialDesignSeparator}" Margin="-15 5" /> <Separator Style="{StaticResource MaterialDesignSeparator}" Margin="-15 5" />
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0">
<TextBlock Style="{StaticResource MaterialDesignTextBlock}">Automatically install updates</TextBlock>
<TextBlock Style="{StaticResource MaterialDesignTextBlock}" Foreground="{DynamicResource MaterialDesignNavigationItemSubheader}" TextWrapping="Wrap">
If enabled updates are installed automatically without asking first.
</TextBlock>
</StackPanel>
<StackPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
<ToggleButton Style="{StaticResource MaterialDesignSwitchToggleButton}" IsChecked="{Binding AutoInstallUpdates}" IsEnabled="{Binding CheckForUpdates}" />
</StackPanel>
</Grid>
<Separator Style="{StaticResource MaterialDesignSeparator}" Margin="-15 5" />
<Grid> <Grid>
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition /> <RowDefinition />

View File

@ -158,20 +158,6 @@ namespace Artemis.UI.Screens.Settings.Tabs.General
_settingsService.GetSetting("UI.CheckForUpdates", true).Value = value; _settingsService.GetSetting("UI.CheckForUpdates", true).Value = value;
_settingsService.GetSetting("UI.CheckForUpdates", true).Save(); _settingsService.GetSetting("UI.CheckForUpdates", true).Save();
NotifyOfPropertyChange(nameof(CheckForUpdates)); NotifyOfPropertyChange(nameof(CheckForUpdates));
if (!value)
AutoInstallUpdates = false;
}
}
public bool AutoInstallUpdates
{
get => _settingsService.GetSetting("UI.AutoInstallUpdates", false).Value;
set
{
_settingsService.GetSetting("UI.AutoInstallUpdates", false).Value = value;
_settingsService.GetSetting("UI.AutoInstallUpdates", false).Save();
NotifyOfPropertyChange(nameof(AutoInstallUpdates));
} }
} }

View File

@ -91,14 +91,10 @@
<StackPanel> <StackPanel>
<StackPanel.Resources> <StackPanel.Resources>
<DataTemplate x:Key="CategoryDragTemplate" DataType="{x:Type sidebar:SidebarCategoryViewModel}"> <DataTemplate x:Key="CategoryDragTemplate" DataType="{x:Type sidebar:SidebarCategoryViewModel}">
<DataTemplate.Resources>
<shared:NullToVisibilityConverter x:Key="NullToVisibilityConverter" />
</DataTemplate.Resources>
<Border Background="{DynamicResource MaterialDesignTextFieldBoxHoverBackground}" <Border Background="{DynamicResource MaterialDesignTextFieldBoxHoverBackground}"
Padding="10" Padding="10"
CornerRadius="4" CornerRadius="4">
Visibility="{Binding Path=ProfileCategory, FallbackValue=null, Converter={StaticResource NullToVisibilityConverter}}"> <TextBlock Text="{Binding ProfileCategory.Name}" VerticalAlignment="Center" Foreground="{DynamicResource MaterialDesignBody}" />
<TextBlock Text="{Binding ProfileCategory.Name,TargetNullValue='Oops, I am missing'}" VerticalAlignment="Center" Foreground="{DynamicResource MaterialDesignBody}" />
</Border> </Border>
</DataTemplate> </DataTemplate>
</StackPanel.Resources> </StackPanel.Resources>

View File

@ -69,7 +69,7 @@ namespace Artemis.UI.Screens.Sidebar
private void UpdateHeaderDevice() private void UpdateHeaderDevice()
{ {
HeaderDevice = _rgbService.Devices.FirstOrDefault(d => d.DeviceType == RGBDeviceType.Keyboard && d.Layout.IsValid); HeaderDevice = _rgbService.Devices.FirstOrDefault(d => d.DeviceType == RGBDeviceType.Keyboard && d.Layout is {IsValid: true});
} }
public ArtemisDevice HeaderDevice public ArtemisDevice HeaderDevice

View File

@ -28,7 +28,6 @@ namespace Artemis.UI.Services
private const double UpdateCheckInterval = 3600000; // once per hour private const double UpdateCheckInterval = 3600000; // once per hour
private const string ApiUrl = "https://dev.azure.com/artemis-rgb/Artemis/_apis/"; private const string ApiUrl = "https://dev.azure.com/artemis-rgb/Artemis/_apis/";
private readonly PluginSetting<bool> _autoInstallUpdates;
private readonly PluginSetting<bool> _checkForUpdates; private readonly PluginSetting<bool> _checkForUpdates;
private readonly IDialogService _dialogService; private readonly IDialogService _dialogService;
private readonly ILogger _logger; private readonly ILogger _logger;
@ -42,7 +41,6 @@ namespace Artemis.UI.Services
_windowService.MainWindowOpened += WindowServiceOnMainWindowOpened; _windowService.MainWindowOpened += WindowServiceOnMainWindowOpened;
_checkForUpdates = settingsService.GetSetting("UI.CheckForUpdates", true); _checkForUpdates = settingsService.GetSetting("UI.CheckForUpdates", true);
_autoInstallUpdates = settingsService.GetSetting("UI.AutoInstallUpdates", false);
_checkForUpdates.SettingChanged += CheckForUpdatesOnSettingChanged; _checkForUpdates.SettingChanged += CheckForUpdatesOnSettingChanged;
Timer timer = new(UpdateCheckInterval); Timer timer = new(UpdateCheckInterval);
@ -136,18 +134,7 @@ namespace Artemis.UI.Services
if (_windowService.IsMainWindowOpen) if (_windowService.IsMainWindowOpen)
await OfferUpdate(buildInfo); await OfferUpdate(buildInfo);
else if (_autoInstallUpdates.Value)
{
new ToastContentBuilder()
.AddText("Installing new version", AdaptiveTextStyle.Header)
.AddText($"Build {buildNumberDisplay} is available, currently on {Constants.BuildInfo.BuildNumberDisplay}.")
.AddProgressBar(null, null, true)
.Show();
await ApplyUpdate();
}
else else
{
// If auto-install is disabled and the window is closed, best we can do is notify the user and stop. // If auto-install is disabled and the window is closed, best we can do is notify the user and stop.
new ToastContentBuilder() new ToastContentBuilder()
.AddText("New version available", AdaptiveTextStyle.Header) .AddText("New version available", AdaptiveTextStyle.Header)
@ -155,7 +142,6 @@ namespace Artemis.UI.Services
.AddButton("Update", ToastActivationType.Background, "update") .AddButton("Update", ToastActivationType.Background, "update")
.AddButton("Later", ToastActivationType.Background, "later") .AddButton("Later", ToastActivationType.Background, "later")
.Show(t => t.Activated += TOnActivated); .Show(t => t.Activated += TOnActivated);
}
return true; return true;
} }