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

Meta - Fixed a bunch of build warnings

This commit is contained in:
Robert 2023-10-18 23:13:57 +02:00
parent 6921561317
commit 1bd4efbbc5
27 changed files with 199 additions and 149 deletions

View File

@ -151,8 +151,7 @@ public static class Constants
public static ReadOnlyCollection<string> StartupArguments { get; set; } = null!; public static ReadOnlyCollection<string> StartupArguments { get; set; } = null!;
/// <summary> /// <summary>
/// Gets the graphics context to be used for rendering by SkiaSharp. Can be set via /// Gets the graphics context to be used for rendering by SkiaSharp.
/// <see cref="IRgbService.UpdateGraphicsContext" />.
/// </summary> /// </summary>
public static IManagedGraphicsContext? ManagedGraphicsContext { get; internal set; } public static IManagedGraphicsContext? ManagedGraphicsContext { get; internal set; }
} }

View File

@ -23,7 +23,6 @@ public class ProfileConfiguration : BreakableModel, IStorageModel, IDisposable
private bool _disposed; private bool _disposed;
private Hotkey? _enableHotkey; private Hotkey? _enableHotkey;
private ProfileConfigurationHotkeyMode _hotkeyMode; private ProfileConfigurationHotkeyMode _hotkeyMode;
private bool _isBeingEdited;
private bool _isMissingModule; private bool _isMissingModule;
private bool _isSuspended; private bool _isSuspended;
private bool _fadeInAndOut; private bool _fadeInAndOut;

View File

@ -5,6 +5,7 @@ using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using Artemis.Core.DeviceProviders; using Artemis.Core.DeviceProviders;
using Artemis.Core.Services;
using Artemis.Storage.Entities.Surface; using Artemis.Storage.Entities.Surface;
using RGB.NET.Core; using RGB.NET.Core;
using SkiaSharp; using SkiaSharp;
@ -266,7 +267,7 @@ public class ArtemisDevice : CorePropertyChanged
/// <summary> /// <summary>
/// Gets a boolean indicating whether this devices is enabled or not /// Gets a boolean indicating whether this devices is enabled or not
/// <para>Note: To enable/disable a device use the methods provided by <see cref="IRgbService" /></para> /// <para>Note: To enable/disable a device use the methods provided by <see cref="IDeviceService" /></para>
/// </summary> /// </summary>
public bool IsEnabled public bool IsEnabled
{ {
@ -320,7 +321,7 @@ public class ArtemisDevice : CorePropertyChanged
} }
/// <summary> /// <summary>
/// Gets or sets the path of the custom layout to load when calling <see cref="IRgbService.ApplyBestDeviceLayout" /> /// Gets or sets the path of the custom layout to load when calling <see cref="GetBestDeviceLayout" />
/// for this device /// for this device
/// </summary> /// </summary>
public string? CustomLayoutPath public string? CustomLayoutPath

View File

@ -31,7 +31,7 @@ internal class PluginManagementService : IPluginManagementService
private readonly IPluginRepository _pluginRepository; private readonly IPluginRepository _pluginRepository;
private readonly List<Plugin> _plugins; private readonly List<Plugin> _plugins;
private readonly IQueuedActionRepository _queuedActionRepository; private readonly IQueuedActionRepository _queuedActionRepository;
private FileSystemWatcher _hotReloadWatcher; private FileSystemWatcher? _hotReloadWatcher;
private bool _disposed; private bool _disposed;
private bool _isElevated; private bool _isElevated;

View File

@ -1,24 +1,49 @@
namespace Artemis.Core.Services; namespace Artemis.Core.Services;
/// <summary>
/// This readonly struct provides information about a process.
/// </summary>
public readonly struct ProcessInfo public readonly struct ProcessInfo
{ {
#region Properties & Fields #region Properties & Fields
/// <summary>
/// Gets the Identifier for the process.
/// </summary>
public readonly int ProcessId; public readonly int ProcessId;
/// <summary>
/// Gets the name of the process.
/// </summary>
public readonly string ProcessName; public readonly string ProcessName;
public readonly string ImageName; //TODO DarthAffe 01.09.2023: Do we need this if we can't get it through Process.GetProcesses()?
/// <summary>
/// Gets the Image Name of the Process.
/// </summary>
public readonly string ImageName; // TODO DarthAffe 01.09.2023: Do we need this if we can't get it through Process.GetProcesses()?
/// <summary>
/// Gets the Executable associated with the Process.
/// </summary>
public readonly string Executable; public readonly string Executable;
#endregion #endregion
#region Constructors #region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="ProcessInfo"/> struct.
/// </summary>
/// <param name="processId">The identifier for the process.</param>
/// <param name="processName">The name of the process.</param>
/// <param name="imageName">The Image Name of the process.</param>
/// <param name="executable">The executable associated with the process.</param>
public ProcessInfo(int processId, string processName, string imageName, string executable) public ProcessInfo(int processId, string processName, string imageName, string executable)
{ {
this.ProcessId = processId; ProcessId = processId;
this.ProcessName = processName; ProcessName = processName;
this.ImageName = imageName; ImageName = imageName;
this.Executable = executable; Executable = executable;
} }
#endregion #endregion

View File

@ -15,7 +15,7 @@ public class LostFocusTextBoxBindingBehavior : Behavior<TextBox>
/// <summary> /// <summary>
/// Gets or sets the value of the binding. /// Gets or sets the value of the binding.
/// </summary> /// </summary>
public static readonly StyledProperty<string> TextProperty = AvaloniaProperty.Register<LostFocusTextBoxBindingBehavior, string>( public static readonly StyledProperty<string?> TextProperty = AvaloniaProperty.Register<LostFocusTextBoxBindingBehavior, string?>(
"Text", defaultBindingMode: BindingMode.TwoWay); "Text", defaultBindingMode: BindingMode.TwoWay);
static LostFocusTextBoxBindingBehavior() static LostFocusTextBoxBindingBehavior()
@ -26,7 +26,7 @@ public class LostFocusTextBoxBindingBehavior : Behavior<TextBox>
/// <summary> /// <summary>
/// Gets or sets the value of the binding. /// Gets or sets the value of the binding.
/// </summary> /// </summary>
public string Text public string? Text
{ {
get => GetValue(TextProperty); get => GetValue(TextProperty);
set => SetValue(TextProperty, value); set => SetValue(TextProperty, value);

View File

@ -305,7 +305,7 @@ public class DeviceVisualizer : Control
{ {
_deviceImage = await Task.Run(() => GetDeviceImage(device)); _deviceImage = await Task.Run(() => GetDeviceImage(device));
} }
catch (Exception e) catch (Exception)
{ {
// ignored // ignored
} }

View File

@ -19,32 +19,32 @@ namespace Artemis.UI.Shared.Pagination;
[TemplatePart("PART_PagesView", typeof(StackPanel))] [TemplatePart("PART_PagesView", typeof(StackPanel))]
public partial class Pagination : TemplatedControl public partial class Pagination : TemplatedControl
{ {
private Button? _previousButton;
private Button? _nextButton;
private StackPanel? _pagesView;
/// <inheritdoc /> /// <inheritdoc />
public Pagination() public Pagination()
{ {
PropertyChanged += OnPropertyChanged; PropertyChanged += OnPropertyChanged;
} }
public Button? PreviousButton { get; set; }
public Button? NextButton { get; set; }
public StackPanel? PagesView { get; set; }
/// <inheritdoc /> /// <inheritdoc />
protected override void OnApplyTemplate(TemplateAppliedEventArgs e) protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{ {
if (PreviousButton != null) if (_previousButton != null)
PreviousButton.Click -= PreviousButtonOnClick; _previousButton.Click -= PreviousButtonOnClick;
if (NextButton != null) if (_nextButton != null)
NextButton.Click -= NextButtonOnClick; _nextButton.Click -= NextButtonOnClick;
PreviousButton = e.NameScope.Find<Button>("PART_PreviousButton"); _previousButton = e.NameScope.Find<Button>("PART_PreviousButton");
NextButton = e.NameScope.Find<Button>("PART_NextButton"); _nextButton = e.NameScope.Find<Button>("PART_NextButton");
PagesView = e.NameScope.Find<StackPanel>("PART_PagesView"); _pagesView = e.NameScope.Find<StackPanel>("PART_PagesView");
if (PreviousButton != null) if (_previousButton != null)
PreviousButton.Click += PreviousButtonOnClick; _previousButton.Click += PreviousButtonOnClick;
if (NextButton != null) if (_nextButton != null)
NextButton.Click += NextButtonOnClick; _nextButton.Click += NextButtonOnClick;
Update(); Update();
} }
@ -69,40 +69,40 @@ public partial class Pagination : TemplatedControl
private void Update() private void Update()
{ {
if (PagesView == null) if (_pagesView == null)
return; return;
List<int> pages = GetPages(Value, Maximum); List<int> pages = GetPages(Value, Maximum);
// Remove extra children // Remove extra children
while (PagesView.Children.Count > pages.Count) while (_pagesView.Children.Count > pages.Count)
{ {
PagesView.Children.RemoveAt(PagesView.Children.Count - 1); _pagesView.Children.RemoveAt(_pagesView.Children.Count - 1);
} }
if (PagesView.Children.Count > pages.Count) if (_pagesView.Children.Count > pages.Count)
PagesView.Children.RemoveRange(0, PagesView.Children.Count - pages.Count); _pagesView.Children.RemoveRange(0, _pagesView.Children.Count - pages.Count);
// Add/modify children // Add/modify children
for (int i = 0; i < pages.Count; i++) for (int i = 0; i < pages.Count; i++)
{ {
int page = pages[i]; int page = pages[i];
// -1 indicates an ellipsis (...) // -1 indicates an ellipsis (...)
if (page == -1) if (page == -1)
{ {
if (PagesView.Children.ElementAtOrDefault(i) is not PaginationEllipsis) if (_pagesView.Children.ElementAtOrDefault(i) is not PaginationEllipsis)
{ {
if (PagesView.Children.Count - 1 >= i) if (_pagesView.Children.Count - 1 >= i)
PagesView.Children[i] = new PaginationEllipsis(); _pagesView.Children[i] = new PaginationEllipsis();
else else
PagesView.Children.Add(new PaginationEllipsis()); _pagesView.Children.Add(new PaginationEllipsis());
} }
} }
// Anything else indicates a regular page // Anything else indicates a regular page
else else
{ {
if (PagesView.Children.ElementAtOrDefault(i) is PaginationPage paginationPage) if (_pagesView.Children.ElementAtOrDefault(i) is PaginationPage paginationPage)
{ {
paginationPage.Page = page; paginationPage.Page = page;
paginationPage.Command = ReactiveCommand.Create(() => Value = page); paginationPage.Command = ReactiveCommand.Create(() => Value = page);
@ -110,14 +110,14 @@ public partial class Pagination : TemplatedControl
} }
paginationPage = new PaginationPage {Page = page, Command = ReactiveCommand.Create(() => Value = page)}; paginationPage = new PaginationPage {Page = page, Command = ReactiveCommand.Create(() => Value = page)};
if (PagesView.Children.Count - 1 >= i) if (_pagesView.Children.Count - 1 >= i)
PagesView.Children[i] = paginationPage; _pagesView.Children[i] = paginationPage;
else else
PagesView.Children.Add(paginationPage); _pagesView.Children.Add(paginationPage);
} }
} }
foreach (Control child in PagesView.Children) foreach (Control child in _pagesView.Children)
{ {
if (child is PaginationPage paginationPage) if (child is PaginationPage paginationPage)
((IPseudoClasses) paginationPage.Classes).Set(":selected", paginationPage.Page == Value); ((IPseudoClasses) paginationPage.Classes).Set(":selected", paginationPage.Page == Value);

View File

@ -8,10 +8,17 @@ using ReactiveUI;
namespace Artemis.UI.Shared.TagsInput; namespace Artemis.UI.Shared.TagsInput;
/// <summary>
/// Represents an input for tags.
/// </summary>
[TemplatePart("PART_TagInputBox", typeof(TextBox))] [TemplatePart("PART_TagInputBox", typeof(TextBox))]
public partial class TagsInput : TemplatedControl public partial class TagsInput : TemplatedControl
{ {
public TextBox? TagInputBox { get; set; } private TextBox? _tagInputBox;
/// <summary>
/// Gets the command that is to be called when removing a tag
/// </summary>
public ICommand RemoveTag { get; } public ICommand RemoveTag { get; }
/// <inheritdoc /> /// <inheritdoc />
@ -23,18 +30,18 @@ public partial class TagsInput : TemplatedControl
/// <inheritdoc /> /// <inheritdoc />
protected override void OnApplyTemplate(TemplateAppliedEventArgs e) protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{ {
if (TagInputBox != null) if (_tagInputBox != null)
{ {
TagInputBox.KeyDown -= TagInputBoxOnKeyDown; _tagInputBox.KeyDown -= TagInputBoxOnKeyDown;
TagInputBox.TextChanging -= TagInputBoxOnTextChanging; _tagInputBox.TextChanging -= TagInputBoxOnTextChanging;
} }
TagInputBox = e.NameScope.Find<TextBox>("PART_TagInputBox"); _tagInputBox = e.NameScope.Find<TextBox>("PART_TagInputBox");
if (TagInputBox != null) if (_tagInputBox != null)
{ {
TagInputBox.KeyDown += TagInputBoxOnKeyDown; _tagInputBox.KeyDown += TagInputBoxOnKeyDown;
TagInputBox.TextChanging += TagInputBoxOnTextChanging; _tagInputBox.TextChanging += TagInputBoxOnTextChanging;
} }
} }
@ -42,21 +49,21 @@ public partial class TagsInput : TemplatedControl
{ {
Tags.Remove(t); Tags.Remove(t);
if (TagInputBox != null) if (_tagInputBox != null)
TagInputBox.IsEnabled = Tags.Count < MaxLength; _tagInputBox.IsEnabled = Tags.Count < MaxLength;
} }
private void TagInputBoxOnTextChanging(object? sender, TextChangingEventArgs e) private void TagInputBoxOnTextChanging(object? sender, TextChangingEventArgs e)
{ {
if (TagInputBox?.Text == null) if (_tagInputBox?.Text == null)
return; return;
TagInputBox.Text = CleanTagRegex().Replace(TagInputBox.Text.ToLower(), ""); _tagInputBox.Text = CleanTagRegex().Replace(_tagInputBox.Text.ToLower(), "");
} }
private void TagInputBoxOnKeyDown(object? sender, KeyEventArgs e) private void TagInputBoxOnKeyDown(object? sender, KeyEventArgs e)
{ {
if (TagInputBox == null) if (_tagInputBox == null)
return; return;
if (e.Key == Key.Space) if (e.Key == Key.Space)
@ -64,13 +71,13 @@ public partial class TagsInput : TemplatedControl
if (e.Key != Key.Enter) if (e.Key != Key.Enter)
return; return;
if (string.IsNullOrWhiteSpace(TagInputBox.Text) || Tags.Contains(TagInputBox.Text) || Tags.Count >= MaxLength) if (string.IsNullOrWhiteSpace(_tagInputBox.Text) || Tags.Contains(_tagInputBox.Text) || Tags.Count >= MaxLength)
return; return;
Tags.Add(CleanTagRegex().Replace(TagInputBox.Text.ToLower(), "")); Tags.Add(CleanTagRegex().Replace(_tagInputBox.Text.ToLower(), ""));
TagInputBox.Text = ""; _tagInputBox.Text = "";
TagInputBox.IsEnabled = Tags.Count < MaxLength; _tagInputBox.IsEnabled = Tags.Count < MaxLength;
} }
[GeneratedRegex("[\\s\\-]+")] [GeneratedRegex("[\\s\\-]+")]

View File

@ -2,6 +2,9 @@ using System;
namespace Artemis.UI.Shared; namespace Artemis.UI.Shared;
/// <summary>
/// Represents errors that occur within the Artemis router.
/// </summary>
public class ArtemisRoutingException : Exception public class ArtemisRoutingException : Exception
{ {
/// <inheritdoc /> /// <inheritdoc />

View File

@ -5,50 +5,60 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Artemis.UI.Shared.Utilities; using Artemis.UI.Shared.Utilities;
namespace Artemis.UI.Shared.Extensions namespace Artemis.UI.Shared.Extensions;
/// <summary>
/// Provides extension methods for the <see cref="HttpClient" /> type.
/// </summary>
public static class HttpClientProgressExtensions
{ {
public static class HttpClientProgressExtensions /// <summary>
/// Send a GET request to the specified Uri with an HTTP completion option and a cancellation token as an asynchronous operation.
/// </summary>
/// <param name="client">The HTTP client to use.</param>
/// <param name="requestUrl">The Uri the request is sent to.</param>
/// <param name="destination">The destination stream.</param>
/// <param name="progress">The progress instance to use for progress indication.</param>
/// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
public static async Task DownloadDataAsync(this HttpClient client, string requestUrl, Stream destination, IProgress<StreamProgress>? progress, CancellationToken cancellationToken)
{ {
public static async Task DownloadDataAsync(this HttpClient client, string requestUrl, Stream destination, IProgress<StreamProgress>? progress, CancellationToken cancellationToken) using HttpResponseMessage response = await client.GetAsync(requestUrl, HttpCompletionOption.ResponseHeadersRead, cancellationToken);
response.EnsureSuccessStatusCode();
long? contentLength = response.Content.Headers.ContentLength;
await using Stream download = await response.Content.ReadAsStreamAsync(cancellationToken);
// no progress... no contentLength... very sad
if (progress is null || !contentLength.HasValue)
{ {
using HttpResponseMessage response = await client.GetAsync(requestUrl, HttpCompletionOption.ResponseHeadersRead, cancellationToken); await download.CopyToAsync(destination, cancellationToken);
response.EnsureSuccessStatusCode(); return;
long? contentLength = response.Content.Headers.ContentLength;
await using Stream download = await response.Content.ReadAsStreamAsync(cancellationToken);
// no progress... no contentLength... very sad
if (progress is null || !contentLength.HasValue)
{
await download.CopyToAsync(destination, cancellationToken);
return;
}
// Such progress and contentLength much reporting Wow!
await download.CopyToAsync(destination, 81920, progress, contentLength, cancellationToken);
} }
static async Task CopyToAsync(this Stream source, Stream destination, int bufferSize, IProgress<StreamProgress> progress, long? contentLength, CancellationToken cancellationToken) // Such progress and contentLength much reporting Wow!
{ await download.CopyToAsync(destination, 81920, progress, contentLength, cancellationToken);
if (bufferSize < 0) }
throw new ArgumentOutOfRangeException(nameof(bufferSize));
if (source is null)
throw new ArgumentNullException(nameof(source));
if (!source.CanRead)
throw new InvalidOperationException($"'{nameof(source)}' is not readable.");
if (destination == null)
throw new ArgumentNullException(nameof(destination));
if (!destination.CanWrite)
throw new InvalidOperationException($"'{nameof(destination)}' is not writable.");
byte[] buffer = new byte[bufferSize]; private static async Task CopyToAsync(this Stream source, Stream destination, int bufferSize, IProgress<StreamProgress> progress, long? contentLength, CancellationToken cancellationToken)
long totalBytesRead = 0; {
int bytesRead; if (bufferSize < 0)
while ((bytesRead = await source.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false)) != 0) throw new ArgumentOutOfRangeException(nameof(bufferSize));
{ if (source is null)
await destination.WriteAsync(buffer, 0, bytesRead, cancellationToken).ConfigureAwait(false); throw new ArgumentNullException(nameof(source));
totalBytesRead += bytesRead; if (!source.CanRead)
progress?.Report(new StreamProgress(totalBytesRead, contentLength ?? totalBytesRead)); throw new InvalidOperationException($"'{nameof(source)}' is not readable.");
} if (destination == null)
throw new ArgumentNullException(nameof(destination));
if (!destination.CanWrite)
throw new InvalidOperationException($"'{nameof(destination)}' is not writable.");
byte[] buffer = new byte[bufferSize];
long totalBytesRead = 0;
int bytesRead;
while ((bytesRead = await source.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false)) != 0)
{
await destination.WriteAsync(buffer, 0, bytesRead, cancellationToken).ConfigureAwait(false);
totalBytesRead += bytesRead;
progress?.Report(new StreamProgress(totalBytesRead, contentLength ?? totalBytesRead));
} }
} }
} }

View File

@ -61,7 +61,10 @@ internal class WindowService : IWindowService
public async Task ShowDialogAsync(object viewModel) public async Task ShowDialogAsync(object viewModel)
{ {
Window? parent = GetCurrentWindow(); Window? parent = GetCurrentWindow();
if (parent == null)
throw new ArtemisSharedUIException("Failed to get the current window.");
string name = viewModel.GetType().FullName!.Split('`')[0].Replace("ViewModel", "View"); string name = viewModel.GetType().FullName!.Split('`')[0].Replace("ViewModel", "View");
Type? type = viewModel.GetType().Assembly.GetType(name); Type? type = viewModel.GetType().Assembly.GetType(name);
@ -100,6 +103,9 @@ internal class WindowService : IWindowService
public async Task<TResult> ShowDialogAsync<TResult>(DialogViewModelBase<TResult> viewModel) public async Task<TResult> ShowDialogAsync<TResult>(DialogViewModelBase<TResult> viewModel)
{ {
Window? parent = GetCurrentWindow(); Window? parent = GetCurrentWindow();
if (parent == null)
throw new ArtemisSharedUIException("Failed to get the current window.");
string name = viewModel.GetType().FullName!.Split('`')[0].Replace("ViewModel", "View"); string name = viewModel.GetType().FullName!.Split('`')[0].Replace("ViewModel", "View");
Type? type = viewModel.GetType().Assembly.GetType(name); Type? type = viewModel.GetType().Assembly.GetType(name);

View File

@ -18,6 +18,9 @@ public static class UI
{ {
private static readonly BehaviorSubject<bool> MicaEnabledSubject = new(false); private static readonly BehaviorSubject<bool> MicaEnabledSubject = new(false);
/// <summary>
/// Gets the background event loop scheduler.
/// </summary>
public static EventLoopScheduler BackgroundScheduler = new(ts => new Thread(ts)); public static EventLoopScheduler BackgroundScheduler = new(ts => new Thread(ts));
static UI() static UI()

View File

@ -33,9 +33,9 @@ public static class ArtemisBootstrapper
{ {
if (_application != null || _container != null) if (_application != null || _container != null)
throw new ArtemisUIException("UI already bootstrapped"); throw new ArtemisUIException("UI already bootstrapped");
Utilities.PrepareFirstLaunch(); Utilities.PrepareFirstLaunch();
application.RequestedThemeVariant = ThemeVariant.Dark; application.RequestedThemeVariant = ThemeVariant.Dark;
_application = application; _application = application;
_container = new Container(rules => rules _container = new Container(rules => rules
@ -52,7 +52,7 @@ public static class ArtemisBootstrapper
configureServices?.Invoke(_container); configureServices?.Invoke(_container);
_container.UseDryIocDependencyResolver(); _container.UseDryIocDependencyResolver();
Logger.Sink = _container.Resolve<SerilogAvaloniaSink>(); Logger.Sink = _container.Resolve<SerilogAvaloniaSink>();
return _container; return _container;
} }
@ -64,7 +64,7 @@ public static class ArtemisBootstrapper
if (_application.ApplicationLifetime is not IClassicDesktopStyleApplicationLifetime desktop) if (_application.ApplicationLifetime is not IClassicDesktopStyleApplicationLifetime desktop)
return; return;
Constants.StartupArguments = new ReadOnlyCollection<string>(new List<string>(desktop.Args)); Constants.StartupArguments = new ReadOnlyCollection<string>(desktop.Args != null ? new List<string>(desktop.Args) : new List<string>());
// Don't shut down when the last window closes, we might still be active in the tray // Don't shut down when the last window closes, we might still be active in the tray
desktop.ShutdownMode = ShutdownMode.OnExplicitShutdown; desktop.ShutdownMode = ShutdownMode.OnExplicitShutdown;

View File

@ -1,15 +1,10 @@
using Artemis.UI.Shared; using System;
using Artemis.UI.Shared;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reactive.Disposables; using System.Reactive.Disposables;
using System.Text;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Artemis.Core; using Artemis.Core;
using Artemis.Core.Services; using Artemis.Core.Services;
using Artemis.UI.Shared;
using Artemis.UI.Shared.Services; using Artemis.UI.Shared.Services;
using ReactiveUI; using ReactiveUI;
using RGB.NET.Core; using RGB.NET.Core;
@ -50,10 +45,10 @@ public class DeviceGeneralTabViewModel : ActivatableViewModelBase
Device = device; Device = device;
DisplayName = "General"; DisplayName = "General";
X = (int)Device.X; X = (int) Device.X;
Y = (int)Device.Y; Y = (int) Device.Y;
Scale = Device.Scale; Scale = Device.Scale;
Rotation = (int)Device.Rotation; Rotation = (int) Device.Rotation;
RedScale = Device.RedScale * 100f; RedScale = Device.RedScale * 100f;
GreenScale = Device.GreenScale * 100f; GreenScale = Device.GreenScale * 100f;
BlueScale = Device.BlueScale * 100f; BlueScale = Device.BlueScale * 100f;
@ -234,7 +229,7 @@ public class DeviceGeneralTabViewModel : ActivatableViewModelBase
if (!DisplayOnDevices) if (!DisplayOnDevices)
return; return;
using SKPaint overlayPaint = new() { Color = CurrentColor }; using SKPaint overlayPaint = new() {Color = CurrentColor};
e.Canvas.DrawRect(0, 0, e.Canvas.LocalClipBounds.Width, e.Canvas.LocalClipBounds.Height, overlayPaint); e.Canvas.DrawRect(0, 0, e.Canvas.LocalClipBounds.Width, e.Canvas.LocalClipBounds.Height, overlayPaint);
} }
} }

View File

@ -1,8 +1,5 @@
using Avalonia; using Avalonia.Controls;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using Avalonia.ReactiveUI; using Avalonia.ReactiveUI;
namespace Artemis.UI.Screens.Device; namespace Artemis.UI.Screens.Device;
@ -18,17 +15,17 @@ public partial class DeviceLayoutTabView : ReactiveUserControl<DeviceLayoutTabVi
{ {
if (ViewModel?.DefaultLayoutPath is null) if (ViewModel?.DefaultLayoutPath is null)
return; return;
TopLevel.GetTopLevel(this).Clipboard.SetTextAsync(ViewModel.DefaultLayoutPath); TopLevel.GetTopLevel(this)?.Clipboard?.SetTextAsync(ViewModel.DefaultLayoutPath);
ViewModel.ShowCopiedNotification(); ViewModel.ShowCopiedNotification();
} }
private void ImagePathButton_OnClick(object? sender, RoutedEventArgs e) private void ImagePathButton_OnClick(object? sender, RoutedEventArgs e)
{ {
if (ViewModel?.Device?.Layout?.Image?.LocalPath is null) if (ViewModel?.Device.Layout?.Image?.LocalPath is null)
return; return;
TopLevel.GetTopLevel(this).Clipboard.SetTextAsync(ViewModel.Device.Layout.Image.LocalPath); TopLevel.GetTopLevel(this)?.Clipboard?.SetTextAsync(ViewModel.Device.Layout.Image.LocalPath);
ViewModel.ShowCopiedNotification(); ViewModel.ShowCopiedNotification();
} }
} }

View File

@ -25,8 +25,10 @@ public partial class DeviceLogicalLayoutDialogView : ReactiveUserControl<DeviceL
RegionsAutoCompleteBox.PopulateComplete(); RegionsAutoCompleteBox.PopulateComplete();
} }
private bool SearchRegions(string search, object item) private bool SearchRegions(string? search, object? item)
{ {
if (search == null)
return true;
if (item is not RegionInfo regionInfo) if (item is not RegionInfo regionInfo)
return false; return false;

View File

@ -11,7 +11,7 @@ namespace Artemis.UI.Screens.ProfileEditor.ProfileTree.Dialogs.AdaptionHints;
public partial class SingleLedAdaptionHintViewModel : AdaptionHintViewModelBase public partial class SingleLedAdaptionHintViewModel : AdaptionHintViewModelBase
{ {
[Notify] private List<AdaptionLed> _adaptionLeds; [Notify] private List<AdaptionLed> _adaptionLeds = new();
[Notify] private AdaptionLed? _selectedLed; [Notify] private AdaptionLed? _selectedLed;
public SingleLedAdaptionHintViewModel(Layer layer, SingleLedAdaptionHint adaptionHint) : base(layer, adaptionHint) public SingleLedAdaptionHintViewModel(Layer layer, SingleLedAdaptionHint adaptionHint) : base(layer, adaptionHint)

View File

@ -5,7 +5,6 @@ using Avalonia.Input;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Layout; using Avalonia.Layout;
using Avalonia.LogicalTree; using Avalonia.LogicalTree;
using Avalonia.Markup.Xaml;
using Avalonia.Media; using Avalonia.Media;
using Avalonia.Media.Imaging; using Avalonia.Media.Imaging;
using Avalonia.ReactiveUI; using Avalonia.ReactiveUI;
@ -40,7 +39,8 @@ public partial class ProfileTreeView : ReactiveUserControl<ProfileTreeViewModel>
private void CreateDragAdorner(DragEventArgs e) private void CreateDragAdorner(DragEventArgs e)
{ {
if (_dragAdorner != null) Window? window = this.FindAncestorOfType<Window>();
if (window == null || _dragAdorner != null)
return; return;
if (e.Source is not Control c) if (e.Source is not Control c)
@ -55,7 +55,7 @@ public partial class ProfileTreeView : ReactiveUserControl<ProfileTreeViewModel>
ITransform? originalTransform = container.RenderTransform; ITransform? originalTransform = container.RenderTransform;
try try
{ {
_dragStartPosition = e.GetPosition(this.FindAncestorOfType<Window>()); _dragStartPosition = e.GetPosition(window);
_elementDragOffset = e.GetPosition(container); _elementDragOffset = e.GetPosition(container);
RenderTargetBitmap renderTarget = new(new PixelSize((int) container.Bounds.Width, (int) container.Bounds.Height)); RenderTargetBitmap renderTarget = new(new PixelSize((int) container.Bounds.Width, (int) container.Bounds.Height));
@ -106,10 +106,11 @@ public partial class ProfileTreeView : ReactiveUserControl<ProfileTreeViewModel>
private void UpdateDragAdorner(DragEventArgs e) private void UpdateDragAdorner(DragEventArgs e)
{ {
if (_dragAdorner == null) Window? window = this.FindAncestorOfType<Window>();
if (window == null || _dragAdorner == null)
return; return;
Point position = e.GetPosition(this.FindAncestorOfType<Window>()); Point position = e.GetPosition(window);
_dragAdorner.RenderTransform = new TranslateTransform(_dragStartPosition.X - _elementDragOffset.X, position.Y - _elementDragOffset.Y); _dragAdorner.RenderTransform = new TranslateTransform(_dragStartPosition.X - _elementDragOffset.X, position.Y - _elementDragOffset.Y);
} }

View File

@ -15,7 +15,7 @@ public partial class RootView : ReactiveUserControl<RootViewModel>
this.WhenActivated(d => ViewModel.WhenAnyValue(vm => vm.Screen).Subscribe(Navigate).DisposeWith(d)); this.WhenActivated(d => ViewModel.WhenAnyValue(vm => vm.Screen).Subscribe(Navigate).DisposeWith(d));
} }
private void Navigate(RoutableScreen viewModel) private void Navigate(RoutableScreen? viewModel)
{ {
try try
{ {

View File

@ -23,7 +23,7 @@ public partial class ReleasesTabView : ReactiveUserControl<ReleasesTabViewModel>
{ {
ReleaseFrame.NavigateFromObject(viewModel); ReleaseFrame.NavigateFromObject(viewModel);
} }
catch (Exception e) catch (Exception)
{ {
// ignored // ignored
} }

View File

@ -202,14 +202,17 @@ public class ProfileConfigurationEditViewModel : DialogViewModelBase<ProfileConf
{ {
// Preselect the icon based on streams if needed // Preselect the icon based on streams if needed
if (_profileConfiguration.Icon.IconType == ProfileConfigurationIconType.BitmapImage) if (_profileConfiguration.Icon.IconType == ProfileConfigurationIconType.BitmapImage)
{
try try
{ {
SelectedBitmapSource = new Bitmap(_profileConfiguration.Icon.GetIconStream()); Stream? iconStream = _profileConfiguration.Icon.GetIconStream();
SelectedBitmapSource = iconStream != null ? new Bitmap(iconStream) : null;
} }
catch (Exception e) catch (Exception e)
{ {
_windowService.ShowConfirmContentDialog("Failed to load profile icon", e.Message, "Meh", null); _windowService.ShowConfirmContentDialog("Failed to load profile icon", e.Message, "Meh", null);
} }
}
// Prepare the contents of the dropdown box, it should be virtualized so no need to wait with this // Prepare the contents of the dropdown box, it should be virtualized so no need to wait with this
ObservableCollection<ProfileIconViewModel> icons = new(Enum.GetValues<MaterialIconKind>() ObservableCollection<ProfileIconViewModel> icons = new(Enum.GetValues<MaterialIconKind>()

View File

@ -49,7 +49,8 @@ public partial class SidebarCategoryView : ReactiveUserControl<SidebarCategoryVi
private void CreateDragAdorner(DragEventArgs e) private void CreateDragAdorner(DragEventArgs e)
{ {
if (_dragAdorner != null) Window? window = this.FindAncestorOfType<Window>();
if (window == null || _dragAdorner != null)
return; return;
if (e.Source is not Control c) if (e.Source is not Control c)
@ -64,7 +65,7 @@ public partial class SidebarCategoryView : ReactiveUserControl<SidebarCategoryVi
ITransform? originalTransform = container.RenderTransform; ITransform? originalTransform = container.RenderTransform;
try try
{ {
_dragStartPosition = e.GetPosition(this.FindAncestorOfType<Window>()); _dragStartPosition = e.GetPosition(window);
_elementDragOffset = e.GetPosition(container); _elementDragOffset = e.GetPosition(container);
RenderTargetBitmap renderTarget = new(new PixelSize((int) container.Bounds.Width, (int) container.Bounds.Height)); RenderTargetBitmap renderTarget = new(new PixelSize((int) container.Bounds.Width, (int) container.Bounds.Height));
@ -88,7 +89,9 @@ public partial class SidebarCategoryView : ReactiveUserControl<SidebarCategoryVi
private void HandleDragOver(object? sender, DragEventArgs e) private void HandleDragOver(object? sender, DragEventArgs e)
{ {
UpdateDragAdorner(e.GetPosition(this.FindAncestorOfType<Window>())); Window? window = this.FindAncestorOfType<Window>();
if (window != null)
UpdateDragAdorner(e.GetPosition(window));
} }
private void HandleLeaveEvent(object? sender, RoutedEventArgs e) private void HandleLeaveEvent(object? sender, RoutedEventArgs e)

View File

@ -1,10 +1,8 @@
using System;
using System.Reactive; using System.Reactive;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Artemis.UI.Shared;
using Artemis.UI.Shared.Routing; using Artemis.UI.Shared.Routing;
using Artemis.WebClient.Workshop;
using Artemis.WebClient.Workshop.Services; using Artemis.WebClient.Workshop.Services;
using ReactiveUI; using ReactiveUI;
@ -14,7 +12,7 @@ public class WorkshopOfflineViewModel : RoutableScreen<WorkshopOfflineParameters
{ {
private readonly IRouter _router; private readonly IRouter _router;
private readonly IWorkshopService _workshopService; private readonly IWorkshopService _workshopService;
private string _message; private string _message = string.Empty;
/// <inheritdoc /> /// <inheritdoc />
public WorkshopOfflineViewModel(IWorkshopService workshopService, IRouter router) public WorkshopOfflineViewModel(IWorkshopService workshopService, IRouter router)
@ -51,5 +49,5 @@ public class WorkshopOfflineViewModel : RoutableScreen<WorkshopOfflineParameters
public class WorkshopOfflineParameters public class WorkshopOfflineParameters
{ {
public string Message { get; set; } public string Message { get; set; } = string.Empty;
} }

View File

@ -11,7 +11,7 @@ namespace Artemis.VisualScripting.Converters;
public class JsonConverter : IValueConverter public class JsonConverter : IValueConverter
{ {
/// <inheritdoc /> /// <inheritdoc />
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{ {
return JsonConvert.SerializeObject(value, Formatting.Indented); return JsonConvert.SerializeObject(value, Formatting.Indented);
} }
@ -19,8 +19,7 @@ public class JsonConverter : IValueConverter
/// <inheritdoc /> /// <inheritdoc />
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{ {
if (value == null) string? json = value?.ToString();
return null; return json == null ? null : JsonConvert.DeserializeObject(json, targetType);
return JsonConvert.DeserializeObject(value.ToString(), targetType);
} }
} }

View File

@ -44,7 +44,7 @@ public class EnumEqualsNodeCustomViewModel : CustomNodeViewModel
public ObservableCollection<EnumValueItem> EnumValues { get; } = new(); public ObservableCollection<EnumValueItem> EnumValues { get; } = new();
public EnumValueItem CurrentValue public EnumValueItem? CurrentValue
{ {
get => EnumValues.FirstOrDefault(v => v.Value == _node.Storage); get => EnumValues.FirstOrDefault(v => v.Value == _node.Storage);
set set

View File

@ -2,6 +2,5 @@ namespace Artemis.WebClient.Workshop.Entities;
public class RefreshTokenEntity public class RefreshTokenEntity
{ {
public string RefreshToken { get; set; } public string RefreshToken { get; set; } = string.Empty;
} }