From 9fb1c69a5ceba7c3920052152f5bd3121cca0fa2 Mon Sep 17 00:00:00 2001 From: Toastie Date: Tue, 7 Jan 2025 14:26:32 +1300 Subject: [PATCH] Cleaned up warnings --- .editorconfig | 60 +++--- EllieHub/App.axaml.cs | 2 +- .../Controls/DesignBotConfigViewModel.cs | 2 +- .../Controls/DesignConfigViewModel.cs | 2 +- .../DesignDependencyButtonViewModel.cs | 2 +- .../Controls/DesignFakeConsoleViewModel.cs | 2 +- .../Controls/DesignUriInputBarViewModel.cs | 2 +- EllieHub/Avalonia/Resources/Fonts.axaml | 7 +- EllieHub/Avalonia/Resources/Images.axaml | 4 +- EllieHub/Common/Utilities.cs | 202 ++---------------- EllieHub/EllieHub.csproj | 26 +-- EllieHub/Extensions/IServiceCollectionExt.cs | 11 +- EllieHub/Extensions/IServiceProviderExt.cs | 31 --- EllieHub/Extensions/WindowExt.cs | 2 +- .../Services/Abstractions/IFfmpegResolver.cs | 2 +- .../Services/Abstractions/IYtdlpResolver.cs | 2 +- .../AppConfig/Services/FfmpegLinuxResolver.cs | 24 +-- .../AppConfig/Services/FfmpegMacResolver.cs | 14 +- .../Services/FfmpegWindowsResolver.cs | 14 +- .../AppConfig/Services/YtdlpResolver.cs | 10 +- .../AppConfig/ViewModels/ConfigViewModel.cs | 4 +- .../AppConfig/Views/Controls/ConfigView.axaml | 7 +- .../AppConfig/Views/Windows/AboutMeView.axaml | 1 - .../Views/Controls/LateralBarView.axaml | 1 - .../Views/Controls/LateralBarView.axaml.cs | 2 - .../AppWindow/Views/Windows/AppView.axaml.cs | 12 +- .../Services/Abstractions/IBotOrchestrator.cs | 6 +- .../Services/Abstractions/IBotResolver.cs | 2 +- .../BotConfig/Services/EllieOrchestrator.cs | 6 +- .../BotConfig/Services/EllieResolver.cs | 43 ++-- .../ViewModels/BotConfigViewModel.cs | 28 ++- .../ViewModels/FakeConsoleViewModel.cs | 2 +- .../Views/Controls/BotConfigView.axaml | 2 +- .../Views/Controls/FakeConsole.axaml | 2 +- .../Views/Controls/FakeConsole.axaml.cs | 2 +- .../Models/UriInputBarEventArgs.cs | 4 +- .../Abstractions/IDependencyResolver.cs | 2 +- .../ViewModels/DependencyButtonViewModel.cs | 4 +- .../ViewModels/UriInputBarViewModel.cs | 6 +- .../Views/Controls/DependencyButton.axaml | 4 +- .../Views/Controls/DependencyButton.axaml.cs | 4 +- .../Views/Controls/UriInputBar.axaml | 4 +- .../Views/Controls/UriInputBar.axaml.cs | 4 +- .../Services/Abstractions/IAppResolver.cs | 2 +- .../Features/Home/Services/AppResolver.cs | 23 +- .../Home/Views/Controls/HomeView.axaml | 16 +- EllieHub/ViewLocator.cs | 2 +- 47 files changed, 203 insertions(+), 413 deletions(-) delete mode 100644 EllieHub/Extensions/IServiceProviderExt.cs rename EllieHub/Features/{Shared => Common}/Models/UriInputBarEventArgs.cs (89%) rename EllieHub/Features/{Shared => Common}/Services/Abstractions/IDependencyResolver.cs (97%) rename EllieHub/Features/{Shared => Common}/ViewModels/DependencyButtonViewModel.cs (97%) rename EllieHub/Features/{Shared => Common}/ViewModels/UriInputBarViewModel.cs (96%) rename EllieHub/Features/{Shared => Common}/Views/Controls/DependencyButton.axaml (92%) rename EllieHub/Features/{Shared => Common}/Views/Controls/DependencyButton.axaml.cs (79%) rename EllieHub/Features/{Shared => Common}/Views/Controls/UriInputBar.axaml (91%) rename EllieHub/Features/{Shared => Common}/Views/Controls/UriInputBar.axaml.cs (80%) diff --git a/.editorconfig b/.editorconfig index a513f1f..644396b 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,3 +1,5 @@ +root = true + [*] charset = utf-8 end_of_line = lf @@ -7,24 +9,16 @@ indent_style = space indent_size = 4 # A property with the same name was updated with a value 2 in a section [{*.yaml,*.yml}] [{*.yaml,*.yml}] -indent_style = space indent_size = 2 # A property with the same name was updated with a value 4 in a section [*]; with a value 4 in a section [*.{appxmanifest,asax,ascx,aspx,axaml,build,cg,cginc,compute,cs,cshtml,dtd,hlsl,hlsli,hlslinc,master,nuspec,paml,razor,resw,resx,skin,usf,ush,vb,xaml,xamlx,xoml,xsd}] -dotnet_diagnostic.CA1047.severity = error [*.{appxmanifest,asax,ascx,aspx,axaml,build,cg,cginc,compute,cs,cshtml,dtd,hlsl,hlsli,hlslinc,master,nuspec,paml,razor,resw,resx,skin,usf,ush,vb,xaml,xamlx,xoml,xsd}] -indent_style = space -indent_size = 4 # A property with the same name was updated with a value 2 in a section [{*.yaml,*.yml}] tab_width = 4 -dotnet_style_operator_placement_when_wrapping = beginning_of_line + dotnet_style_coalesce_expression = true:suggestion dotnet_style_null_propagation = true:suggestion -dotnet_style_prefer_is_null_check_over_reference_equality_method = true:error -dotnet_style_prefer_auto_properties = true:warning dotnet_style_object_initializer = true:suggestion dotnet_style_collection_initializer = true:suggestion dotnet_style_prefer_simplified_boolean_expressions = true:suggestion -dotnet_style_prefer_conditional_expression_over_assignment = true:suggestion -dotnet_style_prefer_conditional_expression_over_return = true:suggestion dotnet_style_explicit_tuple_names = true:suggestion dotnet_style_prefer_inferred_tuple_names = true:suggestion dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion @@ -35,13 +29,8 @@ dotnet_style_namespace_match_folder = true:suggestion dotnet_style_readonly_field = true:warning dotnet_style_predefined_type_for_locals_parameters_members = true:warning dotnet_style_predefined_type_for_member_access = true:warning -dotnet_style_require_accessibility_modifiers = always:error dotnet_style_allow_multiple_blank_lines_experimental = false:silent dotnet_style_allow_statement_immediately_after_block_experimental = false:silent -dotnet_code_quality_unused_parameters = all:warning -dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:warning -dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:warning -dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:warning dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent dotnet_style_qualification_for_field = false:silent dotnet_style_qualification_for_property = false:silent @@ -68,7 +57,7 @@ dotnet_diagnostic.CA1832.severity = warning dotnet_diagnostic.CA1833.severity = warning dotnet_diagnostic.CA1842.severity = warning dotnet_diagnostic.CA1843.severity = warning -dotnet_diagnostic.CA1836.severity = none +dotnet_diagnostic.CA1836.severity = warning dotnet_diagnostic.CA1839.severity = warning dotnet_diagnostic.CA1840.severity = warning dotnet_diagnostic.CA1846.severity = warning @@ -77,6 +66,8 @@ dotnet_diagnostic.CA1852.severity = suggestion dotnet_diagnostic.CA2012.severity = warning dotnet_diagnostic.CA2019.severity = warning dotnet_diagnostic.CA2211.severity = warning +dotnet_diagnostic.CA1822.severity = suggestion +dotnet_diagnostic.CA1725.severity = suggestion [*.cs] @@ -712,14 +703,16 @@ resharper_blank_lines_inside_region = 1 resharper_blank_lines_inside_type = 0 resharper_blank_line_after_pi = true resharper_braces_for_dowhile = required -resharper_braces_for_fixed = required +resharper_braces_for_fixed = required_for_multiline resharper_braces_for_for = required_for_multiline resharper_braces_for_foreach = required_for_multiline resharper_braces_for_ifelse = required_for_multiline -resharper_braces_for_lock = required -resharper_braces_for_using = required +resharper_braces_for_lock = required_for_multiline +resharper_braces_for_using = required_for_multiline resharper_braces_for_while = required_for_multiline resharper_braces_redundant = true +resharper_builtin_type_apply_to_native_integer = true +resharper_csharp_empty_block_style = together_same_line resharper_break_template_declaration = line_break resharper_can_use_global_alias = false resharper_configure_await_analysis_mode = disabled @@ -817,7 +810,7 @@ resharper_indent_typearg_angles = inside resharper_indent_typeparam_angles = inside resharper_indent_type_constraints = true resharper_indent_wrapped_function_names = false -resharper_instance_members_qualify_declared_in = base_class +resharper_instance_members_qualify_declared_in = resharper_int_align_assignments = false resharper_int_align_binary_expressions = false resharper_int_align_declaration_names = false @@ -918,7 +911,7 @@ resharper_place_simple_switch_expression_on_single_line = false resharper_place_type_attribute_on_same_line = false resharper_place_type_constraints_on_same_line = true resharper_prefer_explicit_discard_declaration = false -resharper_prefer_separate_deconstructed_variables_declaration = true +resharper_prefer_separate_deconstructed_variables_declaration = false resharper_preserve_spaces_inside_tags = pre,textarea resharper_qualified_using_at_nested_scope = false resharper_quote_style = doublequoted @@ -1069,6 +1062,7 @@ resharper_space_within_typeof_parentheses = false resharper_space_within_type_argument_angles = false resharper_space_within_type_parameter_angles = false resharper_space_within_type_parameter_parentheses = false +resharper_csharp_allow_alias = false resharper_special_else_if_treatment = true resharper_static_members_qualify_members = none resharper_static_members_qualify_with = declared_type @@ -1289,7 +1283,7 @@ resharper_convert_to_using_declaration_highlighting = suggestion resharper_convert_to_vb_auto_property_highlighting = suggestion resharper_convert_to_vb_auto_property_when_possible_highlighting = hint resharper_convert_to_vb_auto_property_with_private_setter_highlighting = hint -resharper_convert_type_check_pattern_to_null_check_highlighting = warning +resharper_convert_type_check_pattern_to_null_check_highlighting = none resharper_convert_type_check_to_null_check_highlighting = warning resharper_co_variant_array_conversion_highlighting = warning resharper_c_declaration_with_implicit_int_type_highlighting = warning @@ -1408,8 +1402,8 @@ resharper_meaningless_default_parameter_value_highlighting = warning resharper_member_can_be_internal_highlighting = none resharper_member_can_be_made_static_global_highlighting = hint resharper_member_can_be_made_static_local_highlighting = hint -resharper_member_can_be_private_global_highlighting = suggestion -resharper_member_can_be_private_local_highlighting = suggestion +resharper_member_can_be_private_global_highlighting = hint +resharper_member_can_be_private_local_highlighting = hint resharper_member_can_be_protected_global_highlighting = suggestion resharper_member_can_be_protected_local_highlighting = suggestion resharper_member_hides_interface_member_with_default_implementation_highlighting = warning @@ -1537,7 +1531,7 @@ resharper_redundant_assignment_highlighting = warning resharper_redundant_attribute_parentheses_highlighting = hint resharper_redundant_attribute_usage_property_highlighting = suggestion resharper_redundant_base_constructor_call_highlighting = warning -resharper_redundant_base_qualifier_highlighting = warning +resharper_redundant_base_qualifier_highlighting = none resharper_redundant_blank_lines_highlighting = none resharper_redundant_bool_compare_highlighting = warning resharper_redundant_case_label_highlighting = warning @@ -1547,7 +1541,7 @@ resharper_redundant_check_before_assignment_highlighting = warning resharper_redundant_collection_initializer_element_braces_highlighting = hint resharper_redundant_configure_await_highlighting = suggestion resharper_redundant_declaration_semicolon_highlighting = hint -resharper_redundant_default_member_initializer_highlighting = warning +resharper_redundant_default_member_initializer_highlighting = hint resharper_redundant_delegate_creation_highlighting = warning resharper_redundant_disable_warning_comment_highlighting = warning resharper_redundant_discard_designation_highlighting = suggestion @@ -1872,4 +1866,18 @@ resharper_virtual_member_never_overridden_local_highlighting = suggestion resharper_void_method_with_must_use_return_value_attribute_highlighting = warning resharper_with_expression_instead_of_initializer_highlighting = suggestion resharper_wrong_indent_size_highlighting = none -resharper_xunit_xunit_test_with_console_output_highlighting = warning \ No newline at end of file +resharper_xunit_xunit_test_with_console_output_highlighting = warning +resharper_arrange_constructor_or_destructor_body_highlighting = hint +resharper_arrange_local_function_body_highlighting = hint +resharper_arrange_method_or_operator_body_highlighting = hint +resharper_arrange_null_checking_pattern_highlighting = suggestion +resharper_enforce_do_while_statement_braces_highlighting = warning +resharper_enforce_fixed_statement_braces_highlighting = warning +resharper_enforce_foreach_statement_braces_highlighting = suggestion +resharper_enforce_for_statement_braces_highlighting = suggestion +resharper_enforce_if_statement_braces_highlighting = suggestion +resharper_enforce_lock_statement_braces_highlighting = warning +resharper_enforce_while_statement_braces_highlighting = suggestion +resharper_remove_redundant_braces_highlighting = hint +resharper_suggest_discard_declaration_var_style_highlighting = warning +resharper_prefer_concrete_value_over_default_highlighting = hint \ No newline at end of file diff --git a/EllieHub/App.axaml.cs b/EllieHub/App.axaml.cs index d535943..9a6e0b1 100644 --- a/EllieHub/App.axaml.cs +++ b/EllieHub/App.axaml.cs @@ -20,7 +20,7 @@ public partial class App : Application /// public IServiceProvider Services { get; } = new ServiceCollection() .RegisterViewsAndViewModels(Assembly.GetExecutingAssembly()) - .RegisterServices() + .RegisterAppServices() .BuildServiceProvider(true); /// diff --git a/EllieHub/Avalonia/DesignData/Controls/DesignBotConfigViewModel.cs b/EllieHub/Avalonia/DesignData/Controls/DesignBotConfigViewModel.cs index 6d7a88b..73b43d6 100644 --- a/EllieHub/Avalonia/DesignData/Controls/DesignBotConfigViewModel.cs +++ b/EllieHub/Avalonia/DesignData/Controls/DesignBotConfigViewModel.cs @@ -6,7 +6,7 @@ using EllieHub.Features.AppWindow.Views.Windows; using EllieHub.Features.BotConfig.Services.Abstractions; using EllieHub.Features.BotConfig.Services.Mocks; using EllieHub.Features.BotConfig.ViewModels; -using EllieHub.Features.Shared.ViewModels; +using EllieHub.Features.Common.ViewModels; namespace EllieHub.Avalonia.DesignData.Controls; diff --git a/EllieHub/Avalonia/DesignData/Controls/DesignConfigViewModel.cs b/EllieHub/Avalonia/DesignData/Controls/DesignConfigViewModel.cs index 670e539..d4c0507 100644 --- a/EllieHub/Avalonia/DesignData/Controls/DesignConfigViewModel.cs +++ b/EllieHub/Avalonia/DesignData/Controls/DesignConfigViewModel.cs @@ -4,7 +4,7 @@ using EllieHub.Features.AppConfig.Services.Abstractions; using EllieHub.Features.AppConfig.Services.Mocks; using EllieHub.Features.AppConfig.ViewModels; using EllieHub.Features.AppWindow.Views.Windows; -using EllieHub.Features.Shared.ViewModels; +using EllieHub.Features.Common.ViewModels; namespace EllieHub.Avalonia.DesignData.Controls; diff --git a/EllieHub/Avalonia/DesignData/Controls/DesignDependencyButtonViewModel.cs b/EllieHub/Avalonia/DesignData/Controls/DesignDependencyButtonViewModel.cs index ff1399f..245f8d7 100644 --- a/EllieHub/Avalonia/DesignData/Controls/DesignDependencyButtonViewModel.cs +++ b/EllieHub/Avalonia/DesignData/Controls/DesignDependencyButtonViewModel.cs @@ -1,7 +1,7 @@ using Microsoft.Extensions.DependencyInjection; using EllieHub.Avalonia.DesignData.Common; using EllieHub.Features.AppWindow.Views.Windows; -using EllieHub.Features.Shared.ViewModels; +using EllieHub.Features.Common.ViewModels; namespace EllieHub.Avalonia.DesignData.Controls; diff --git a/EllieHub/Avalonia/DesignData/Controls/DesignFakeConsoleViewModel.cs b/EllieHub/Avalonia/DesignData/Controls/DesignFakeConsoleViewModel.cs index 9836508..3d87c0d 100644 --- a/EllieHub/Avalonia/DesignData/Controls/DesignFakeConsoleViewModel.cs +++ b/EllieHub/Avalonia/DesignData/Controls/DesignFakeConsoleViewModel.cs @@ -10,6 +10,6 @@ public sealed class DesignFakeConsoleViewModel : FakeConsoleViewModel /// /// Creates a mock to be used at design-time. /// - public DesignFakeConsoleViewModel() : base() + public DesignFakeConsoleViewModel() => Watermark = "Sample watermark."; } \ No newline at end of file diff --git a/EllieHub/Avalonia/DesignData/Controls/DesignUriInputBarViewModel.cs b/EllieHub/Avalonia/DesignData/Controls/DesignUriInputBarViewModel.cs index a70d2de..4dd32b4 100644 --- a/EllieHub/Avalonia/DesignData/Controls/DesignUriInputBarViewModel.cs +++ b/EllieHub/Avalonia/DesignData/Controls/DesignUriInputBarViewModel.cs @@ -1,7 +1,7 @@ using Avalonia.Platform.Storage; using Microsoft.Extensions.DependencyInjection; using EllieHub.Avalonia.DesignData.Common; -using EllieHub.Features.Shared.ViewModels; +using EllieHub.Features.Common.ViewModels; namespace EllieHub.Avalonia.DesignData.Controls; diff --git a/EllieHub/Avalonia/Resources/Fonts.axaml b/EllieHub/Avalonia/Resources/Fonts.axaml index 7b6d0a9..902d474 100644 --- a/EllieHub/Avalonia/Resources/Fonts.axaml +++ b/EllieHub/Avalonia/Resources/Fonts.axaml @@ -1,5 +1,9 @@ + + avares://EllieHub/Assets/Fonts/NotoSans-Regular.ttf + avares://EllieHub/Assets/Fonts/NotoSans-Bold.ttf + @@ -13,7 +17,4 @@ - - avares://EllieHub/Assets/Fonts/NotoSans-Regular.ttf - avares://EllieHub/Assets/Fonts/NotoSans-Bold.ttf \ No newline at end of file diff --git a/EllieHub/Avalonia/Resources/Images.axaml b/EllieHub/Avalonia/Resources/Images.axaml index 403d07a..0acf6b0 100644 --- a/EllieHub/Avalonia/Resources/Images.axaml +++ b/EllieHub/Avalonia/Resources/Images.axaml @@ -50,7 +50,7 @@ avares://EllieHub/Assets/Light/icon-link.png avares://EllieHub/Assets/Light/icon-suggest.png avares://EllieHub/Assets/Light/icon-support.png - avares://EllieHub/Assets/Light/ellieupdatericon.ico + avares://EllieHub/Assets/Light/ellieupdatericon.ico avares://EllieHub/Assets/Light/terminal.png @@ -65,7 +65,7 @@ avares://EllieHub/Assets/Dark/icon-link.png avares://EllieHub/Assets/Dark/icon-suggest.png avares://EllieHub/Assets/Dark/icon-support.png - avares://EllieHub/Assets/Dark/ellieupdatericon.ico + avares://EllieHub/Assets/Dark/ellieupdatericon.ico avares://EllieHub/Assets/Dark/terminal.png diff --git a/EllieHub/Common/Utilities.cs b/EllieHub/Common/Utilities.cs index 7533d5c..eb2bc3c 100644 --- a/EllieHub/Common/Utilities.cs +++ b/EllieHub/Common/Utilities.cs @@ -1,8 +1,5 @@ using Avalonia.Platform; using SkiaSharp; -using System.ComponentModel; -using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; namespace EllieHub.Common; @@ -11,205 +8,30 @@ namespace EllieHub.Common; /// internal static class Utilities { - private static readonly string _programVerifier = (Environment.OSVersion.Platform is PlatformID.Win32NT) ? "where" : "which"; - private static readonly string _envPathSeparator = (Environment.OSVersion.Platform is PlatformID.Win32NT) ? ";" : ":"; - private static readonly EnvironmentVariableTarget _envTarget = (Environment.OSVersion.Platform is PlatformID.Win32NT) - ? EnvironmentVariableTarget.User - : EnvironmentVariableTarget.Process; - /// - /// Loads an image embeded with this application. + /// Loads an image embedded with this application. /// /// An uri that starts with "avares://" /// Valid uris must start with "avares://". - /// The embeded image or the default bot avatar placeholder. - /// Occurs when the embeded resource does not exist. - public static SKBitmap LoadEmbededImage(string? uri = default) + /// The embedded image or the default bot avatar placeholder. + /// Occurs when the embedded resource does not exist. + public static SKBitmap LoadEmbeddedImage(string? uri = default) { return (string.IsNullOrWhiteSpace(uri) || !uri.StartsWith("avares://", StringComparison.Ordinal)) - ? SKBitmap.Decode(AssetLoader.Open(new Uri(AppConstants.BotAvatarUri))) - : SKBitmap.Decode(AssetLoader.Open(new Uri(uri))); + ? SKBitmap.Decode(AssetLoader.Open(new(AppConstants.BotAvatarUri))) + : SKBitmap.Decode(AssetLoader.Open(new(uri))); } /// /// Loads the image at the specified location or the bot avatar placeholder if it was not found. /// - /// The absolute path to the image file or to get the avatar placeholder. - /// This fallsback to if doesn't point to a valid image file. + /// The absolute path to the image file or to get the avatar placeholder. + /// This fallsback to if doesn't point to a valid image file. /// The requested image or the default bot avatar placeholder. - public static SKBitmap LoadLocalImage(string? uri = default) + public static SKBitmap LoadLocalImage(string? imagePath) { - return (File.Exists(uri)) - ? SKBitmap.Decode(uri) - : LoadEmbededImage(uri); - } - - /// - /// Safely casts an to a . - /// - /// The type to cast to. - /// The object to be cast. - /// The cast object, or is casting failed. - /// if the object was successfully cast, otherwise. - public static bool TryCastTo(object? obj, [MaybeNullWhen(false)] out T castObject) - { - if (obj is T result) - { - castObject = result; - return true; - } - - castObject = default; - return false; - } - - /// - /// Starts the specified program in the background. - /// - /// - /// The name of the program in the PATH environment variable, - /// or the absolute path to its executable. - /// - /// The arguments to the program. - /// The process of the specified program. - /// - /// - /// Occurs when does not exist. - /// Occurs when the process fails to execute. - public static Process StartProcess(string program, string arguments = "") - { - ArgumentException.ThrowIfNullOrEmpty(program, nameof(program)); - ArgumentNullException.ThrowIfNull(arguments, nameof(arguments)); - - return Process.Start(new ProcessStartInfo() - { - FileName = program, - Arguments = arguments, - UseShellExecute = false, - CreateNoWindow = true, - RedirectStandardOutput = true, - }) ?? throw new InvalidOperationException($"Failed spawing process for: {program} {arguments}"); - } - - /// - /// Checks if a program exists. - /// - /// The name of the program. - /// The cancellation token. - /// if the program exists, otherwise. - /// - /// - public static async ValueTask ProgramExistsAsync(string programName, CancellationToken cToken = default) - { - ArgumentException.ThrowIfNullOrEmpty(programName, nameof(programName)); - - using var process = StartProcess(_programVerifier, programName); - return !string.IsNullOrWhiteSpace(await process.StandardOutput.ReadToEndAsync(cToken)); - } - - /// - /// Safely deletes a file. - /// - /// The absolute path to the file. - /// if the file was deleted, otherwise. - /// - /// - /// - /// - /// - /// - public static bool TryDeleteFile(string fileUri) - { - ArgumentException.ThrowIfNullOrEmpty(fileUri, nameof(fileUri)); - - if (!File.Exists(fileUri)) - return false; - - File.Delete(fileUri); - return true; - } - - /// - /// Safely deletes a directory. - /// - /// The absolute path to the directory. - /// if the directory was deleted, otherwise. - /// - /// - /// - /// - /// - /// - public static bool TryDeleteDirectory(string directoryUri) - { - ArgumentException.ThrowIfNullOrEmpty(directoryUri, nameof(directoryUri)); - - if (!Directory.Exists(directoryUri)) - return false; - - Directory.Delete(directoryUri, true); - return true; - } - - /// - /// Checks if this application can write to . - /// - /// The absolute path to a directory. - /// if writing is allowed, otherwise. - /// - /// - public static bool CanWriteTo(string directoryUri) - { - var tempFileUri = Path.Combine(directoryUri, $"{Guid.NewGuid()}.tmp"); - - try - { - using var fileStream = File.Create(tempFileUri); - return true; - } - catch (UnauthorizedAccessException) - { - return false; - } - finally - { - TryDeleteFile(tempFileUri); - } - } - - /// - /// Adds a directory path to the PATH environment variable. - /// - /// The absolute path to a directory. - /// - /// On Windows, this needs to be called once and the dependencies will be available for the user forever.
- /// On Unix systems, we can only add to the PATH on a process basis, so this needs to be called at least once everytime the application is opened. - ///
- /// if got successfully added to the PATH envar, otherwise. - /// - /// - public static bool AddPathToPATHEnvar(string directoryUri) - { - ArgumentException.ThrowIfNullOrEmpty(directoryUri, nameof(directoryUri)); - - if (File.Exists(directoryUri)) - throw new ArgumentException("Parameter must point to a directory, not a file.", nameof(directoryUri)); - - var envPathValue = Environment.GetEnvironmentVariable("PATH", _envTarget) ?? string.Empty; - - // If directoryPath is already in the PATH envar, don't add it again. - if (envPathValue.Contains(directoryUri, StringComparison.Ordinal)) - return false; - - var newPathEnvValue = envPathValue + _envPathSeparator + directoryUri; - - // Add path to Windows' user envar, so it persists across reboots. - if (Environment.OSVersion.Platform is PlatformID.Win32NT) - Environment.SetEnvironmentVariable("PATH", newPathEnvValue, EnvironmentVariableTarget.User); - - // Add path to the current process' envar, so the updater can see the dependencies. - Environment.SetEnvironmentVariable("PATH", newPathEnvValue, EnvironmentVariableTarget.Process); - - return true; + return (File.Exists(imagePath)) + ? SKBitmap.Decode(imagePath) + : LoadEmbeddedImage(imagePath); } } \ No newline at end of file diff --git a/EllieHub/EllieHub.csproj b/EllieHub/EllieHub.csproj index fd51eff..1104402 100644 --- a/EllieHub/EllieHub.csproj +++ b/EllieHub/EllieHub.csproj @@ -2,7 +2,7 @@ WinExe - net8.0 + net9.0 latest latest enable @@ -20,7 +20,7 @@ embedded - 1.0.3.4 + 1.0.4.0 app.manifest @@ -46,21 +46,23 @@ - - - - - - - + + + + + + + + - - + + - + + diff --git a/EllieHub/Extensions/IServiceCollectionExt.cs b/EllieHub/Extensions/IServiceCollectionExt.cs index e224b91..2af9b0f 100644 --- a/EllieHub/Extensions/IServiceCollectionExt.cs +++ b/EllieHub/Extensions/IServiceCollectionExt.cs @@ -10,7 +10,6 @@ using EllieHub.Features.BotConfig.Services.Abstractions; using EllieHub.Features.BotConfig.Services.Mocks; using EllieHub.Features.Home.Services; using EllieHub.Features.Home.Services.Abstractions; -using EllieHub.Services; using ReactiveUI; using System.Reflection; using System.Text.Json; @@ -48,7 +47,7 @@ public static class IServiceCollectionExt /// /// This service collection. /// This service collection with the services added. - public static IServiceCollection RegisterServices(this IServiceCollection serviceCollection) + public static IServiceCollection RegisterAppServices(this IServiceCollection serviceCollection) { // Design-time if (Design.IsDesignMode) @@ -66,18 +65,18 @@ public static class IServiceCollectionExt // Web requests serviceCollection.AddHttpClient(); - serviceCollection.AddHttpClient(AppConstants.NoRedirectClient) // Client that doesn't allow automatic reditections + serviceCollection.AddHttpClient(AppConstants.NoRedirectClient) // Client that doesn't allow automatic redirections .ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler() { AllowAutoRedirect = false }); serviceCollection.AddHttpClient(AppConstants.ToastielabClient) .ConfigureHttpClient(x => { x.DefaultRequestHeaders.Add("Accept", "application/vnd.toastielab+json"); x.DefaultRequestHeaders.Add("X-Toastielab-Api-Version", "2022-11-28"); - #if DEBUG +#if DEBUG x.DefaultRequestHeaders.UserAgent.TryParseAdd($"EllieHub v{AppStatics.AppVersion}-Debug"); - #else +#else x.DefaultRequestHeaders.UserAgent.TryParseAdd($"EllieHub v{AppStatics.AppVersion}"); - #endif +#endif }); // App settings diff --git a/EllieHub/Extensions/IServiceProviderExt.cs b/EllieHub/Extensions/IServiceProviderExt.cs deleted file mode 100644 index f488bd5..0000000 --- a/EllieHub/Extensions/IServiceProviderExt.cs +++ /dev/null @@ -1,31 +0,0 @@ -using Microsoft.Extensions.DependencyInjection; - -namespace EllieHub.Extensions; - -/// -/// Defines extension methods for . -/// -public static class IServiceProviderExt -{ - /// - /// Gets service of type from the . - /// - /// The type of service object to get. - /// The to retrieve the service object from. - /// - /// Do not use abstract types in the type argument! - /// A service object of type . - /// Occurs when or are . - /// Occurs when there is no concrete service of type or when the arguments are wrong. - public static T GetParameterizedService(this IServiceProvider serviceProvider, params object[] arguments) - { - ArgumentNullException.ThrowIfNull(serviceProvider, nameof(serviceProvider)); - ArgumentNullException.ThrowIfNull(arguments, nameof(arguments)); - - var result = ActivatorUtilities.CreateInstance(serviceProvider, arguments); - - return (result is null) - ? throw new InvalidOperationException($"There is no service of type {nameof(T)} or the arguments were incorrect.") - : result; - } -} \ No newline at end of file diff --git a/EllieHub/Extensions/WindowExt.cs b/EllieHub/Extensions/WindowExt.cs index 71bbe95..f54dd3e 100644 --- a/EllieHub/Extensions/WindowExt.cs +++ b/EllieHub/Extensions/WindowExt.cs @@ -85,6 +85,6 @@ public static class WindowExt ? throw new InvalidOperationException($"Resource '{resourceName}' was not found.") : (resource is T castResource) ? castResource - : throw new InvalidCastException($"Could not convert resource of type '{resource?.GetType()?.FullName}' to '{nameof(T)}'."); + : throw new InvalidCastException($"Could not convert resource of type '{resource?.GetType().FullName}' to '{nameof(T)}'."); } } \ No newline at end of file diff --git a/EllieHub/Features/AppConfig/Services/Abstractions/IFfmpegResolver.cs b/EllieHub/Features/AppConfig/Services/Abstractions/IFfmpegResolver.cs index 26f39c2..5cabfa8 100644 --- a/EllieHub/Features/AppConfig/Services/Abstractions/IFfmpegResolver.cs +++ b/EllieHub/Features/AppConfig/Services/Abstractions/IFfmpegResolver.cs @@ -1,4 +1,4 @@ -using EllieHub.Features.Shared.Services.Abstractions; +using EllieHub.Features.Common.Services.Abstractions; namespace EllieHub.Features.AppConfig.Services.Abstractions; diff --git a/EllieHub/Features/AppConfig/Services/Abstractions/IYtdlpResolver.cs b/EllieHub/Features/AppConfig/Services/Abstractions/IYtdlpResolver.cs index 5a85453..d83d5f6 100644 --- a/EllieHub/Features/AppConfig/Services/Abstractions/IYtdlpResolver.cs +++ b/EllieHub/Features/AppConfig/Services/Abstractions/IYtdlpResolver.cs @@ -1,4 +1,4 @@ -using EllieHub.Features.Shared.Services.Abstractions; +using EllieHub.Features.Common.Services.Abstractions; namespace EllieHub.Features.AppConfig.Services.Abstractions; diff --git a/EllieHub/Features/AppConfig/Services/FfmpegLinuxResolver.cs b/EllieHub/Features/AppConfig/Services/FfmpegLinuxResolver.cs index 852f1a2..4c6774e 100644 --- a/EllieHub/Features/AppConfig/Services/FfmpegLinuxResolver.cs +++ b/EllieHub/Features/AppConfig/Services/FfmpegLinuxResolver.cs @@ -3,7 +3,7 @@ using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Text.RegularExpressions; -namespace EllieHub.Services; +namespace EllieHub.Features.AppConfig.Services; /// /// Service that checks, downloads, installs, and updates ffmpeg on Linux. @@ -14,7 +14,7 @@ public sealed partial class FfmpegLinuxResolver : FfmpegResolver { private readonly Regex _ffmpegLatestVersionRegex = FfmpegLatestVersionRegexGenerator(); private readonly string _tempDirectory = Path.GetTempPath(); - private bool _isUpdating = false; + private bool _isUpdating; private readonly IHttpClientFactory _httpClientFactory; /// @@ -48,7 +48,7 @@ public sealed partial class FfmpegLinuxResolver : FfmpegResolver } /// - public override async ValueTask<(string? OldVersion, string? NewVersion)> InstallOrUpdateAsync(string dependenciesUri, CancellationToken cToken = default) + public override async ValueTask<(string? OldVersion, string? NewVersion)> InstallOrUpdateAsync(string installationUri, CancellationToken cToken = default) { if (_isUpdating) return (null, null); @@ -64,22 +64,22 @@ public sealed partial class FfmpegLinuxResolver : FfmpegResolver if (currentVersion == newVersion) return (currentVersion, null); - Utilities.TryDeleteFile(Path.Combine(dependenciesUri, FileName)); - Utilities.TryDeleteFile(Path.Combine(dependenciesUri, "ffprobe")); + Utilities.TryDeleteFile(Path.Combine(installationUri, FileName)); + Utilities.TryDeleteFile(Path.Combine(installationUri, "ffprobe")); } // Install - Directory.CreateDirectory(dependenciesUri); + Directory.CreateDirectory(installationUri); var architecture = (RuntimeInformation.OSArchitecture is Architecture.X64) ? "amd" : "arm"; var tarFileName = $"ffmpeg-release-{architecture}64-static.tar.xz"; var http = _httpClientFactory.CreateClient(); - using var downloadStream = await http.GetStreamAsync($"https://johnvansickle.com/ffmpeg/releases/{tarFileName}", cToken); + await using var downloadStream = await http.GetStreamAsync($"https://johnvansickle.com/ffmpeg/releases/{tarFileName}", cToken); // Save tar file to the temporary directory. var tarFilePath = Path.Combine(_tempDirectory, tarFileName); var tarExtractDir = Path.Combine(_tempDirectory, $"ffmpeg-{newVersion}-{architecture}64-static"); - using (var fileStream = new FileStream(tarFilePath, FileMode.Create)) + await using (var fileStream = new FileStream(tarFilePath, FileMode.Create)) await downloadStream.CopyToAsync(fileStream, cToken); // Extract the tar file. @@ -87,11 +87,11 @@ public sealed partial class FfmpegLinuxResolver : FfmpegResolver await extractProcess.WaitForExitAsync(cToken); // Move ffmpeg to the dependencies directory. - File.Move(Path.Combine(tarExtractDir, FileName), Path.Combine(dependenciesUri, FileName), true); - File.Move(Path.Combine(tarExtractDir, "ffprobe"), Path.Combine(dependenciesUri, "ffprobe"), true); + File.Move(Path.Combine(tarExtractDir, FileName), Path.Combine(installationUri, FileName), true); + File.Move(Path.Combine(tarExtractDir, "ffprobe"), Path.Combine(installationUri, "ffprobe"), true); // Mark the files as executable. - using var chmod = Utilities.StartProcess("chmod", $"+x \"{Path.Combine(dependenciesUri, FileName)}\" \"{Path.Combine(dependenciesUri, "ffprobe")}\""); + using var chmod = Utilities.StartProcess("chmod", $"+x \"{Path.Combine(installationUri, FileName)}\" \"{Path.Combine(installationUri, "ffprobe")}\""); await chmod.WaitForExitAsync(cToken); // Cleanup @@ -99,7 +99,7 @@ public sealed partial class FfmpegLinuxResolver : FfmpegResolver Directory.Delete(tarExtractDir, true); // Update environment variable - Utilities.AddPathToPATHEnvar(dependenciesUri); + Utilities.AddPathToPathEnvar(installationUri); _isUpdating = false; return (currentVersion, newVersion); diff --git a/EllieHub/Features/AppConfig/Services/FfmpegMacResolver.cs b/EllieHub/Features/AppConfig/Services/FfmpegMacResolver.cs index 8557ec0..7d04e2f 100644 --- a/EllieHub/Features/AppConfig/Services/FfmpegMacResolver.cs +++ b/EllieHub/Features/AppConfig/Services/FfmpegMacResolver.cs @@ -38,7 +38,7 @@ public sealed class FfmpegMacResolver : FfmpegResolver } /// - public override async ValueTask<(string? OldVersion, string? NewVersion)> InstallOrUpdateAsync(string dependenciesUri, CancellationToken cToken = default) + public override async ValueTask<(string? OldVersion, string? NewVersion)> InstallOrUpdateAsync(string installationUri, CancellationToken cToken = default) { if (_isUpdating) return (null, null); @@ -57,24 +57,24 @@ public sealed class FfmpegMacResolver : FfmpegResolver return (currentVersion, null); } - Utilities.TryDeleteFile(Path.Combine(dependenciesUri, FileName)); - Utilities.TryDeleteFile(Path.Combine(dependenciesUri, "ffprobe")); + Utilities.TryDeleteFile(Path.Combine(installationUri, FileName)); + Utilities.TryDeleteFile(Path.Combine(installationUri, "ffprobe")); } // Install - Directory.CreateDirectory(dependenciesUri); + Directory.CreateDirectory(installationUri); var http = _httpClientFactory.CreateClient(); var ffmpegResponse = await http.CallApiAsync(_apiFfmpegInfoEndpoint, cToken); var ffprobeResponse = await http.CallApiAsync(_apiFfprobeInfoEndpoint, cToken); await Task.WhenAll( - InstallDependencyAsync(ffmpegResponse, dependenciesUri, cToken), - InstallDependencyAsync(ffprobeResponse, dependenciesUri, cToken) + InstallDependencyAsync(ffmpegResponse, installationUri, cToken), + InstallDependencyAsync(ffprobeResponse, installationUri, cToken) ); // Update environment variable - Utilities.AddPathToPATHEnvar(dependenciesUri); + Utilities.AddPathToPathEnvar(installationUri); _isUpdating = false; return (currentVersion, newVersion); diff --git a/EllieHub/Features/AppConfig/Services/FfmpegWindowsResolver.cs b/EllieHub/Features/AppConfig/Services/FfmpegWindowsResolver.cs index c99f49b..40a5f1c 100644 --- a/EllieHub/Features/AppConfig/Services/FfmpegWindowsResolver.cs +++ b/EllieHub/Features/AppConfig/Services/FfmpegWindowsResolver.cs @@ -49,7 +49,7 @@ public sealed class FfmpegWindowsResolver : FfmpegResolver } /// - public override async ValueTask<(string? OldVersion, string? NewVersion)> InstallOrUpdateAsync(string dependenciesUri, CancellationToken cToken = default) + public override async ValueTask<(string? OldVersion, string? NewVersion)> InstallOrUpdateAsync(string installationUri, CancellationToken cToken = default) { if (_isUpdating) return (null, null); @@ -68,13 +68,13 @@ public sealed class FfmpegWindowsResolver : FfmpegResolver return (currentVersion, null); } - Utilities.TryDeleteFile(Path.Combine(dependenciesUri, FileName)); - Utilities.TryDeleteFile(Path.Combine(dependenciesUri, "ffprobe.exe")); + Utilities.TryDeleteFile(Path.Combine(installationUri, FileName)); + Utilities.TryDeleteFile(Path.Combine(installationUri, "ffprobe.exe")); //Utilities.TryDeleteFile(Path.Combine(dependenciesUri, "ffplay.exe")); } // Install - Directory.CreateDirectory(dependenciesUri); + Directory.CreateDirectory(installationUri); var zipFileName = $"ffmpeg-{newVersion}-full_build.zip"; var http = _httpClientFactory.CreateClient(); @@ -94,8 +94,8 @@ public sealed class FfmpegWindowsResolver : FfmpegResolver ZipFile.ExtractToDirectory(zipFilePath, _tempDirectory); // Move ffmpeg to the dependencies directory. - File.Move(Path.Combine(zipExtractDir, "bin", FileName), Path.Combine(dependenciesUri, FileName), true); - File.Move(Path.Combine(zipExtractDir, "bin", "ffprobe.exe"), Path.Combine(dependenciesUri, "ffprobe.exe"), true); + File.Move(Path.Combine(zipExtractDir, "bin", FileName), Path.Combine(installationUri, FileName), true); + File.Move(Path.Combine(zipExtractDir, "bin", "ffprobe.exe"), Path.Combine(installationUri, "ffprobe.exe"), true); //File.Move(Path.Combine(zipExtractDir, "bin", "ffplay.exe"), Path.Combine(dependenciesUri, "ffplay.exe")); // Cleanup @@ -104,7 +104,7 @@ public sealed class FfmpegWindowsResolver : FfmpegResolver }, cToken); // Update environment variable - Utilities.AddPathToPATHEnvar(dependenciesUri); + Utilities.AddPathToPathEnvar(installationUri); _isUpdating = false; return (currentVersion, newVersion); diff --git a/EllieHub/Features/AppConfig/Services/YtdlpResolver.cs b/EllieHub/Features/AppConfig/Services/YtdlpResolver.cs index 259dcc5..dc30dae 100644 --- a/EllieHub/Features/AppConfig/Services/YtdlpResolver.cs +++ b/EllieHub/Features/AppConfig/Services/YtdlpResolver.cs @@ -65,7 +65,7 @@ public sealed class YtdlpResolver : IYtdlpResolver // Else, add the dependencies directory to the PATH envar, // then try again. - Utilities.AddPathToPATHEnvar(AppStatics.AppDepsUri); + Utilities.AddPathToPathEnvar(AppStatics.AppDepsUri); return await GetCurrentVersionAsync(cToken); } @@ -95,7 +95,7 @@ public sealed class YtdlpResolver : IYtdlpResolver } /// - public async ValueTask<(string? OldVersion, string? NewVersion)> InstallOrUpdateAsync(string dependenciesUri, CancellationToken cToken = default) + public async ValueTask<(string? OldVersion, string? NewVersion)> InstallOrUpdateAsync(string installationUri, CancellationToken cToken = default) { if (_isUpdating) return (null, null); @@ -124,16 +124,16 @@ public sealed class YtdlpResolver : IYtdlpResolver } // Install - Directory.CreateDirectory(dependenciesUri); + Directory.CreateDirectory(installationUri); - var finalFilePath = Path.Combine(dependenciesUri, FileName); + var finalFilePath = Path.Combine(installationUri, FileName); var http = _httpClientFactory.CreateClient(); using var downloadStream = await http.GetStreamAsync($"https://github.com/yt-dlp/yt-dlp/releases/download/{newVersion}/{_downloadedFileName}", cToken); using (var fileStream = new FileStream(finalFilePath, FileMode.Create)) await downloadStream.CopyToAsync(fileStream, cToken); // Update environment variable - Utilities.AddPathToPATHEnvar(dependenciesUri); + Utilities.AddPathToPathEnvar(installationUri); // On Linux and MacOS, we need to mark the file as executable. if (Environment.OSVersion.Platform is PlatformID.Unix) diff --git a/EllieHub/Features/AppConfig/ViewModels/ConfigViewModel.cs b/EllieHub/Features/AppConfig/ViewModels/ConfigViewModel.cs index 54861b0..0f59d52 100644 --- a/EllieHub/Features/AppConfig/ViewModels/ConfigViewModel.cs +++ b/EllieHub/Features/AppConfig/ViewModels/ConfigViewModel.cs @@ -8,8 +8,8 @@ using EllieHub.Features.AppConfig.Views.Controls; using EllieHub.Features.AppConfig.Views.Windows; using EllieHub.Features.AppWindow.ViewModels; using EllieHub.Features.AppWindow.Views.Windows; -using EllieHub.Features.Shared.Services.Abstractions; -using EllieHub.Features.Shared.ViewModels; +using EllieHub.Features.Common.Services.Abstractions; +using EllieHub.Features.Common.ViewModels; using ReactiveUI; using System.Diagnostics; diff --git a/EllieHub/Features/AppConfig/Views/Controls/ConfigView.axaml b/EllieHub/Features/AppConfig/Views/Controls/ConfigView.axaml index 3249969..f794e2d 100644 --- a/EllieHub/Features/AppConfig/Views/Controls/ConfigView.axaml +++ b/EllieHub/Features/AppConfig/Views/Controls/ConfigView.axaml @@ -3,7 +3,7 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:vm="using:EllieHub.Features.AppConfig.ViewModels" - xmlns:views="using:EllieHub.Features.Shared.Views.Controls" + xmlns:views="using:EllieHub.Features.Common.Views.Controls" xmlns:const="using:EllieHub.Common" xmlns:dd="using:EllieHub.Avalonia.DesignData.Controls" mc:Ignorable="d" @@ -23,7 +23,6 @@ Fill="{DynamicResource HeavyBackground}" /> @@ -87,9 +86,10 @@ + ToolTip.Tip="Defines the directory the updater is going to store the backups of the bot instances."/> diff --git a/EllieHub/Features/AppConfig/Views/Windows/AboutMeView.axaml b/EllieHub/Features/AppConfig/Views/Windows/AboutMeView.axaml index 9c964b7..5345aad 100644 --- a/EllieHub/Features/AppConfig/Views/Windows/AboutMeView.axaml +++ b/EllieHub/Features/AppConfig/Views/Windows/AboutMeView.axaml @@ -3,7 +3,6 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:vm="using:EllieHub.Features.AppConfig.ViewModels" - xmlns:const="using:EllieHub.Common" xmlns:dd="using:EllieHub.Avalonia.DesignData.Windows" mc:Ignorable="d" d:DesignWidth="400" d:DesignHeight="305" Width="400" Height="305" diff --git a/EllieHub/Features/AppWindow/Views/Controls/LateralBarView.axaml b/EllieHub/Features/AppWindow/Views/Controls/LateralBarView.axaml index 19e6fb9..63bcbe6 100644 --- a/EllieHub/Features/AppWindow/Views/Controls/LateralBarView.axaml +++ b/EllieHub/Features/AppWindow/Views/Controls/LateralBarView.axaml @@ -5,7 +5,6 @@ xmlns:siv="https://github.com/kekyo/SkiaImageView" xmlns:vm="using:EllieHub.Features.AppWindow.ViewModels" xmlns:dd="using:EllieHub.Avalonia.DesignData.Controls" - xmlns:const="using:EllieHub.Common" mc:Ignorable="d" d:DesignWidth="70" d:DesignHeight="450" x:Class="EllieHub.Features.AppWindow.Views.Controls.LateralBarView" x:DataType="vm:LateralBarViewModel"> diff --git a/EllieHub/Features/AppWindow/Views/Controls/LateralBarView.axaml.cs b/EllieHub/Features/AppWindow/Views/Controls/LateralBarView.axaml.cs index 1885fc6..232c194 100644 --- a/EllieHub/Features/AppWindow/Views/Controls/LateralBarView.axaml.cs +++ b/EllieHub/Features/AppWindow/Views/Controls/LateralBarView.axaml.cs @@ -20,8 +20,6 @@ namespace EllieHub.Features.AppWindow.Views.Controls; /// public partial class LateralBarView : ReactiveUserControl { - private static readonly Cursor _pointingHandCursor = new(StandardCursorType.Hand); - private static readonly Cursor _arrow = new(StandardCursorType.Arrow); private readonly ReadOnlyAppSettings _appConfig; /// diff --git a/EllieHub/Features/AppWindow/Views/Windows/AppView.axaml.cs b/EllieHub/Features/AppWindow/Views/Windows/AppView.axaml.cs index 70205f8..f021f89 100644 --- a/EllieHub/Features/AppWindow/Views/Windows/AppView.axaml.cs +++ b/EllieHub/Features/AppWindow/Views/Windows/AppView.axaml.cs @@ -1,6 +1,8 @@ using Avalonia.Controls; using Avalonia.ReactiveUI; using Avalonia.Styling; +using Toastie.DependencyInjection.Extensions; +using Toastie.Utilities; using Microsoft.Extensions.DependencyInjection; using EllieHub.Avalonia.DesignData.Common; using EllieHub.Enums; @@ -15,7 +17,7 @@ using EllieHub.Features.BotConfig.ViewModels; using EllieHub.Features.Home.Services.Abstractions; using EllieHub.Features.Home.ViewModels; using EllieHub.Features.Home.Views.Windows; -using EllieHub.Services; +using EllieHub.Features.BotConfig.Services; using ReactiveUI; using System.Diagnostics; using System.Runtime.Versioning; @@ -117,7 +119,7 @@ public partial class AppView : ReactiveWindow { // Ensure that bots on Unix system have access to the dependencies. if (Environment.OSVersion.Platform is PlatformID.Unix) - Utilities.AddPathToPATHEnvar(AppStatics.AppDepsUri); + ToastieUtilities.AddPathToPATHEnvar(AppStatics.AppDepsUri); // Set the window size from the last session base.Height = _appConfigManager.AppConfig.WindowSize.Height; @@ -156,11 +158,11 @@ public partial class AppView : ReactiveWindow } /// - protected override async void OnClosed(EventArgs eventArgs) + protected override void OnClosed(EventArgs eventArgs) { // When the updater is closed, kill all bots and write their logs. - _botOrchestrator.StopAll(); - await _logWriter.FlushAllAsync(true); + _botOrchestrator.StopAllBots(); + _logWriter.FlushAllAsync(true).Wait(); base.OnClosed(eventArgs); } diff --git a/EllieHub/Features/BotConfig/Services/Abstractions/IBotOrchestrator.cs b/EllieHub/Features/BotConfig/Services/Abstractions/IBotOrchestrator.cs index cb9a21c..91b9fbb 100644 --- a/EllieHub/Features/BotConfig/Services/Abstractions/IBotOrchestrator.cs +++ b/EllieHub/Features/BotConfig/Services/Abstractions/IBotOrchestrator.cs @@ -34,18 +34,18 @@ public interface IBotOrchestrator /// /// The bot's Id. /// if the bot successfully started, otherwise. - bool Start(Guid botId); + bool StartBot(Guid botId); /// /// Stops the bot with the specified . /// /// The bot's Id. /// if the bot successfully stopped, otherwise. - bool Stop(Guid botId); + bool StopBot(Guid botId); /// /// Stops all bot instances. /// /// if at least one bot instance was stopped, otherwise. - bool StopAll(); + bool StopAllBots(); } \ No newline at end of file diff --git a/EllieHub/Features/BotConfig/Services/Abstractions/IBotResolver.cs b/EllieHub/Features/BotConfig/Services/Abstractions/IBotResolver.cs index 7d33ad0..e555a19 100644 --- a/EllieHub/Features/BotConfig/Services/Abstractions/IBotResolver.cs +++ b/EllieHub/Features/BotConfig/Services/Abstractions/IBotResolver.cs @@ -1,4 +1,4 @@ -using EllieHub.Features.Shared.Services.Abstractions; +using EllieHub.Features.Common.Services.Abstractions; namespace EllieHub.Features.BotConfig.Services.Abstractions; diff --git a/EllieHub/Features/BotConfig/Services/EllieOrchestrator.cs b/EllieHub/Features/BotConfig/Services/EllieOrchestrator.cs index fefc4f2..a03ce9f 100644 --- a/EllieHub/Features/BotConfig/Services/EllieOrchestrator.cs +++ b/EllieHub/Features/BotConfig/Services/EllieOrchestrator.cs @@ -35,7 +35,7 @@ public sealed class EllieOrchestrator : IBotOrchestrator => _runningBots.ContainsKey(botId); /// - public bool Start(Guid botId) + public bool StartBot(Guid botId) { if (_runningBots.ContainsKey(botId) || !_appConfig.BotEntries.TryGetValue(botId, out var botEntry) @@ -66,7 +66,7 @@ public sealed class EllieOrchestrator : IBotOrchestrator } /// - public bool Stop(Guid botId) + public bool StopBot(Guid botId) { if (!_runningBots.TryGetValue(botId, out var botProcess)) return false; @@ -76,7 +76,7 @@ public sealed class EllieOrchestrator : IBotOrchestrator } /// - public bool StopAll() + public bool StopAllBots() { var amount = _runningBots.Count; diff --git a/EllieHub/Features/BotConfig/Services/EllieResolver.cs b/EllieHub/Features/BotConfig/Services/EllieResolver.cs index bb8ce25..7c92fbd 100644 --- a/EllieHub/Features/BotConfig/Services/EllieResolver.cs +++ b/EllieHub/Features/BotConfig/Services/EllieResolver.cs @@ -1,3 +1,4 @@ +using Toastie.Utilities; using Microsoft.Extensions.Caching.Memory; using EllieHub.Features.AppConfig.Services.Abstractions; using EllieHub.Features.BotConfig.Models.Api.Toastielab; @@ -10,7 +11,7 @@ using System.Runtime.InteropServices; using System.Text.Json; using System.Text.RegularExpressions; -namespace EllieHub.Services; +namespace EllieHub.Features.BotConfig.Services; /// /// Service that checks, downloads, installs, and updates a EllieBot instance. @@ -23,7 +24,7 @@ public sealed partial class EllieResolver : IBotResolver private const string _toastielabReleasesRepoUrl = "https://toastielab.dev/EllieBotDevs/elliebot/releases/latest"; private static readonly HashSet _updateIdOngoing = []; private static readonly string _tempDirectory = Path.GetTempPath(); - private static readonly Regex _unzipedDirRegex = GenerateUnzipedDirRegex(); + private static readonly Regex _unzippedDirRegex = GenerateUnzipedDirRegex(); private readonly IHttpClientFactory _httpClientFactory; private readonly IMemoryCache _memoryCache; private readonly IAppConfigManager _appConfigManager; @@ -94,7 +95,7 @@ public sealed partial class EllieResolver : IBotResolver var now = DateTimeOffset.Now; var date = new DateOnly(now.Year, now.Month, now.Day).ToShortDateString().Replace('/', '-'); var backupZipName = $"{botInstance.Name}_v{botInstance.Version}_{date}-{now.ToUnixTimeMilliseconds()}.zip"; - var destinationUri = Path.Combine(_appConfigManager.AppConfig.BotsBackupDirectoryUri, backupZipName); + var destinationUri = Path.Join(_appConfigManager.AppConfig.BotsBackupDirectoryUri, backupZipName); // ZipFile does not provide asynchronous implementations, so we have to schedule its // execution to be run in the thread-pool due to how long it takes to finish execution. @@ -107,7 +108,7 @@ public sealed partial class EllieResolver : IBotResolver public async ValueTask GetCurrentVersionAsync(CancellationToken cToken = default) { var botEntry = _appConfigManager.AppConfig.BotEntries[Id]; - var executableUri = Path.Combine(botEntry.InstanceDirectoryUri, FileName); + var executableUri = Path.Join(botEntry.InstanceDirectoryUri, FileName); if (!File.Exists(executableUri)) { @@ -161,8 +162,8 @@ public sealed partial class EllieResolver : IBotResolver var http = _httpClientFactory.CreateClient(); var downloadFileName = GetDownloadFileName(latestVersion); - var botTempLocation = Path.Combine(_tempDirectory, "elliebot-" + _unzipedDirRegex.Match(downloadFileName).Groups[1].Value); - var zipTempLocation = Path.Combine(_tempDirectory, downloadFileName); + var botTempLocation = Path.Join(_tempDirectory, "elliebot-" + _unzippedDirRegex.Match(downloadFileName).Groups[1].Value); + var zipTempLocation = Path.Join(_tempDirectory, downloadFileName); try { @@ -185,10 +186,10 @@ public sealed partial class EllieResolver : IBotResolver await _appConfigManager.UpdateBotEntryAsync(Id, x => x with { Version = latestVersion }, cToken); // Create creds.yml - var credsUri = Path.Combine(installationUri, "creds.yml"); + var credsUri = Path.Join(installationUri, "creds.yml"); if (!File.Exists(credsUri)) - File.Copy(Path.Combine(installationUri, "creds_example.yml"), credsUri); + File.Copy(Path.Join(installationUri, "creds_example.yml"), credsUri); return (currentVersion, latestVersion); } @@ -197,8 +198,8 @@ public sealed partial class EllieResolver : IBotResolver _updateIdOngoing.Remove(Id); // Cleanup - Utilities.TryDeleteFile(zipTempLocation); - Utilities.TryDeleteDirectory(botTempLocation); + ToastieUtilities.TryDeleteFile(zipTempLocation); + ToastieUtilities.TryDeleteDirectory(botTempLocation); } } @@ -214,12 +215,10 @@ public sealed partial class EllieResolver : IBotResolver // Extract the tar ball await TarFile.ExtractToDirectoryAsync(downloadStream, _tempDirectory, true, cToken); - // Move the bot root directory with "mv" to circumvent this issue on Unix systems: https://github.com/dotnet/runtime/issues/31149 - using var moveProcess = Utilities.StartProcess("mv", $"\"{botTempLocation}\" \"{installationUri}\""); - await moveProcess.WaitForExitAsync(cToken); + ToastieUtilities.TryMoveDirectory(botTempLocation, installationUri); // Set executable permission - using var chmod = Utilities.StartProcess("chmod", $"+x \"{Path.Combine(installationUri, FileName)}\""); + using var chmod = ToastieUtilities.StartProcess("chmod", ["+x", Path.Join(installationUri, FileName)]); await chmod.WaitForExitAsync(cToken); } @@ -231,10 +230,10 @@ public sealed partial class EllieResolver : IBotResolver /// The absolute path to the zip file the bot is initially on. /// The absolute path to the temporary directory the bot is extracted to. /// The cancellation token. - private async static ValueTask InstallToWindowsAsync(Stream downloadStream, string installationUri, string zipTempLocation, string botTempLocation, CancellationToken cToken = default) + private static async ValueTask InstallToWindowsAsync(Stream downloadStream, string installationUri, string zipTempLocation, string botTempLocation, CancellationToken cToken = default) { // Save the zip file - using (var fileStream = new FileStream(zipTempLocation, FileMode.Create)) + await using (var fileStream = new FileStream(zipTempLocation, FileMode.Create)) await downloadStream.CopyToAsync(fileStream, cToken); // Extract the zip file @@ -250,7 +249,7 @@ public sealed partial class EllieResolver : IBotResolver /// The absolute path to the directory the bot got installed to. /// The absolute path to the backup zip file. /// The cancellation token. - private async static ValueTask ReaplyBotSettingsAsync(string installationUri, string backupFileUri, CancellationToken cToken = default) + private static async ValueTask ReaplyBotSettingsAsync(string installationUri, string backupFileUri, CancellationToken cToken = default) { using var zipFile = ZipFile.OpenRead(backupFileUri); var zippedFiles = zipFile.Entries @@ -265,7 +264,7 @@ public sealed partial class EllieResolver : IBotResolver .Prepend(Directory.GetParent(installationUri)?.FullName ?? string.Empty) .ToArray(); - await RestoreFileAsync(zippedFile, Path.Combine(fileDestinationPath), cToken); + await RestoreFileAsync(zippedFile, Path.Join(fileDestinationPath), cToken); } } @@ -275,10 +274,10 @@ public sealed partial class EllieResolver : IBotResolver /// The file to be extracted. /// The final location of the extracted file. /// The cancellation token. - private async static ValueTask RestoreFileAsync(ZipArchiveEntry zippedFile, string destinationPath, CancellationToken cToken = default) + private static async ValueTask RestoreFileAsync(ZipArchiveEntry zippedFile, string destinationPath, CancellationToken cToken = default) { - using var zipStream = zippedFile.Open(); - using var fileStream = new FileStream(destinationPath, FileMode.Create); + await using var zipStream = zippedFile.Open(); + await using var fileStream = new FileStream(destinationPath, FileMode.Create); await zipStream.CopyToAsync(fileStream, cToken); } @@ -414,7 +413,7 @@ public sealed partial class EllieResolver : IBotResolver finally { if (isSingleFile) - Utilities.TryDeleteDirectory(directoryUri); + ToastieUtilities.TryDeleteDirectory(directoryUri); } } diff --git a/EllieHub/Features/BotConfig/ViewModels/BotConfigViewModel.cs b/EllieHub/Features/BotConfig/ViewModels/BotConfigViewModel.cs index 26566ca..0ffbbe0 100644 --- a/EllieHub/Features/BotConfig/ViewModels/BotConfigViewModel.cs +++ b/EllieHub/Features/BotConfig/ViewModels/BotConfigViewModel.cs @@ -1,15 +1,15 @@ using Avalonia.Controls; +using Toastie.Utilities; using MsBox.Avalonia.Enums; using EllieHub.Enums; using EllieHub.Features.Abstractions; using EllieHub.Features.AppConfig.Services.Abstractions; using EllieHub.Features.AppWindow.ViewModels; -using EllieHub.Features.AppWindow.Views.Controls; using EllieHub.Features.AppWindow.Views.Windows; using EllieHub.Features.BotConfig.Models; using EllieHub.Features.BotConfig.Services.Abstractions; using EllieHub.Features.BotConfig.Views.Controls; -using EllieHub.Features.Shared.ViewModels; +using EllieHub.Features.Common.ViewModels; using ReactiveUI; using SkiaSharp; using System.Diagnostics; @@ -216,14 +216,12 @@ public class BotConfigViewModel : ViewModelBase, IDisposable Directory.Delete(BotDirectoryUriBar.CurrentUri); } - if (Environment.OSVersion.Platform is not PlatformID.Unix) - Directory.Move(oldUri, BotDirectoryUriBar.CurrentUri); - else - { - // Move the bot root directory with "mv" to circumvent this issue on Unix systems: https://github.com/dotnet/runtime/issues/31149 - using var moveProcess = Utilities.StartProcess("mv", $"\"{oldUri}\" \"{BotDirectoryUriBar.CurrentUri}\""); - await moveProcess.WaitForExitAsync(); - } + if (!ToastieUtilities.TryMoveDirectory(oldUri, BotDirectoryUriBar.CurrentUri)) + throw new InvalidOperationException( + $"Could not move \"{oldUri}\" to \"{BotDirectoryUriBar.CurrentUri}\"." + + Environment.NewLine + Environment.NewLine + + "Make sure you have permission to write to the target directory." + ); BotDirectoryUriBar.RecheckCurrentUri(); } @@ -330,7 +328,7 @@ public class BotConfigViewModel : ViewModelBase, IDisposable ButtonDefinitions = ButtonEnum.OkCancel, ContentTitle = "Are you sure?", ContentMessage = $"Are you sure you want to delete {ActualBotName}?{Environment.NewLine}This action cannot be reversed.", - MaxWidth = int.Parse(WindowConstants.DefaultWindowWidth) / 2.0, + MaxWidth = WindowConstants.DefaultWindowWidth / 2.0, SizeToContent = SizeToContent.WidthAndHeight, ShowInCenter = true, WindowIcon = _mainWindow.GetResource(AppResources.EllieHubIcon), @@ -343,7 +341,7 @@ public class BotConfigViewModel : ViewModelBase, IDisposable EnableButtons(true, false); // Stop the bot instance - _botOrchestrator.Stop(Resolver.Id); + _botOrchestrator.StopBot(Resolver.Id); // Cleanup FakeConsole.Content = string.Empty; @@ -410,7 +408,7 @@ public class BotConfigViewModel : ViewModelBase, IDisposable /// public void StartBot() { - IsBotRunning = _botOrchestrator.Start(Id); + IsBotRunning = _botOrchestrator.StartBot(Id); if (IsBotRunning) EnableButtons(true, false); @@ -420,7 +418,7 @@ public class BotConfigViewModel : ViewModelBase, IDisposable /// Stops the bot instance associated with this view-model. /// public void StopBot() - => _botOrchestrator.Stop(Id); + => _botOrchestrator.StopBot(Id); /// /// Loads the bot update bar. @@ -508,7 +506,7 @@ public class BotConfigViewModel : ViewModelBase, IDisposable /// public void Dispose() { - BotAvatar?.Dispose(); + BotAvatar.Dispose(); GC.SuppressFinalize(this); } } \ No newline at end of file diff --git a/EllieHub/Features/BotConfig/ViewModels/FakeConsoleViewModel.cs b/EllieHub/Features/BotConfig/ViewModels/FakeConsoleViewModel.cs index a008aaa..981ce07 100644 --- a/EllieHub/Features/BotConfig/ViewModels/FakeConsoleViewModel.cs +++ b/EllieHub/Features/BotConfig/ViewModels/FakeConsoleViewModel.cs @@ -1,5 +1,5 @@ using EllieHub.Features.Abstractions; -using EllieHub.Features.AppConfig.Views.Controls; +using EllieHub.Features.BotConfig.Views.Controls; using ReactiveUI; namespace EllieHub.Features.BotConfig.ViewModels; diff --git a/EllieHub/Features/BotConfig/Views/Controls/BotConfigView.axaml b/EllieHub/Features/BotConfig/Views/Controls/BotConfigView.axaml index d5d59f1..a4f4a3b 100644 --- a/EllieHub/Features/BotConfig/Views/Controls/BotConfigView.axaml +++ b/EllieHub/Features/BotConfig/Views/Controls/BotConfigView.axaml @@ -22,7 +22,7 @@ Fill="{DynamicResource HeavyBackground}"/> diff --git a/EllieHub/Features/BotConfig/Views/Controls/FakeConsole.axaml b/EllieHub/Features/BotConfig/Views/Controls/FakeConsole.axaml index e78ff89..c6174b3 100644 --- a/EllieHub/Features/BotConfig/Views/Controls/FakeConsole.axaml +++ b/EllieHub/Features/BotConfig/Views/Controls/FakeConsole.axaml @@ -5,7 +5,7 @@ xmlns:vm="using:EllieHub.Features.BotConfig.ViewModels" xmlns:dd="using:EllieHub.Avalonia.DesignData.Controls" mc:Ignorable="d" d:DesignWidth="500" d:DesignHeight="250" - x:Class="EllieHub.Features.AppConfig.Views.Controls.FakeConsole" + x:Class="EllieHub.Features.BotConfig.Views.Controls.FakeConsole" x:DataType="vm:FakeConsoleViewModel"> diff --git a/EllieHub/Features/BotConfig/Views/Controls/FakeConsole.axaml.cs b/EllieHub/Features/BotConfig/Views/Controls/FakeConsole.axaml.cs index edc6873..2039ee4 100644 --- a/EllieHub/Features/BotConfig/Views/Controls/FakeConsole.axaml.cs +++ b/EllieHub/Features/BotConfig/Views/Controls/FakeConsole.axaml.cs @@ -1,7 +1,7 @@ using Avalonia.ReactiveUI; using EllieHub.Features.BotConfig.ViewModels; -namespace EllieHub.Features.AppConfig.Views.Controls; +namespace EllieHub.Features.BotConfig.Views.Controls; /// /// Represents a control that mimics the appearance of a terminal emulator. diff --git a/EllieHub/Features/Shared/Models/UriInputBarEventArgs.cs b/EllieHub/Features/Common/Models/UriInputBarEventArgs.cs similarity index 89% rename from EllieHub/Features/Shared/Models/UriInputBarEventArgs.cs rename to EllieHub/Features/Common/Models/UriInputBarEventArgs.cs index 768c1c9..5b66614 100644 --- a/EllieHub/Features/Shared/Models/UriInputBarEventArgs.cs +++ b/EllieHub/Features/Common/Models/UriInputBarEventArgs.cs @@ -1,6 +1,6 @@ -using EllieHub.Features.Shared.ViewModels; +using EllieHub.Features.Common.ViewModels; -namespace EllieHub.Features.Shared.Models; +namespace EllieHub.Features.Common.Models; /// /// Defines the event arguments for when a valid uri is set to a . diff --git a/EllieHub/Features/Shared/Services/Abstractions/IDependencyResolver.cs b/EllieHub/Features/Common/Services/Abstractions/IDependencyResolver.cs similarity index 97% rename from EllieHub/Features/Shared/Services/Abstractions/IDependencyResolver.cs rename to EllieHub/Features/Common/Services/Abstractions/IDependencyResolver.cs index 6a80f42..d2e1861 100644 --- a/EllieHub/Features/Shared/Services/Abstractions/IDependencyResolver.cs +++ b/EllieHub/Features/Common/Services/Abstractions/IDependencyResolver.cs @@ -1,4 +1,4 @@ -namespace EllieHub.Features.Shared.Services.Abstractions; +namespace EllieHub.Features.Common.Services.Abstractions; /// /// Represents a service that checks, downloads, installs, and updates a dependency. diff --git a/EllieHub/Features/Shared/ViewModels/DependencyButtonViewModel.cs b/EllieHub/Features/Common/ViewModels/DependencyButtonViewModel.cs similarity index 97% rename from EllieHub/Features/Shared/ViewModels/DependencyButtonViewModel.cs rename to EllieHub/Features/Common/ViewModels/DependencyButtonViewModel.cs index ede11ec..34df368 100644 --- a/EllieHub/Features/Shared/ViewModels/DependencyButtonViewModel.cs +++ b/EllieHub/Features/Common/ViewModels/DependencyButtonViewModel.cs @@ -2,11 +2,11 @@ using Avalonia.Media.Immutable; using EllieHub.Enums; using EllieHub.Features.Abstractions; using EllieHub.Features.AppWindow.Views.Windows; -using EllieHub.Features.Shared.Views.Controls; +using EllieHub.Features.Common.Views.Controls; using ReactiveUI; using System.Diagnostics; -namespace EllieHub.Features.Shared.ViewModels; +namespace EllieHub.Features.Common.ViewModels; /// /// Defines the view-model for a button that installs a dependency for Ellie. diff --git a/EllieHub/Features/Shared/ViewModels/UriInputBarViewModel.cs b/EllieHub/Features/Common/ViewModels/UriInputBarViewModel.cs similarity index 96% rename from EllieHub/Features/Shared/ViewModels/UriInputBarViewModel.cs rename to EllieHub/Features/Common/ViewModels/UriInputBarViewModel.cs index d3c7b5a..a08cc5f 100644 --- a/EllieHub/Features/Shared/ViewModels/UriInputBarViewModel.cs +++ b/EllieHub/Features/Common/ViewModels/UriInputBarViewModel.cs @@ -1,11 +1,11 @@ using Avalonia.Platform.Storage; using EllieHub.Features.Abstractions; -using EllieHub.Features.Shared.Models; -using EllieHub.Features.Shared.Views.Controls; +using EllieHub.Features.Common.Models; +using EllieHub.Features.Common.Views.Controls; using ReactiveUI; using System.Diagnostics; -namespace EllieHub.Features.Shared.ViewModels; +namespace EllieHub.Features.Common.ViewModels; /// /// Represents a text box for inputting the absolute path of a directory. diff --git a/EllieHub/Features/Shared/Views/Controls/DependencyButton.axaml b/EllieHub/Features/Common/Views/Controls/DependencyButton.axaml similarity index 92% rename from EllieHub/Features/Shared/Views/Controls/DependencyButton.axaml rename to EllieHub/Features/Common/Views/Controls/DependencyButton.axaml index 683943c..1c7fefa 100644 --- a/EllieHub/Features/Shared/Views/Controls/DependencyButton.axaml +++ b/EllieHub/Features/Common/Views/Controls/DependencyButton.axaml @@ -2,10 +2,10 @@ 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:vm="using:EllieHub.Features.Shared.ViewModels" + xmlns:vm="using:EllieHub.Features.Common.ViewModels" xmlns:dd="using:EllieHub.Avalonia.DesignData.Controls" mc:Ignorable="d" d:DesignWidth="600" d:DesignHeight="50" - x:Class="EllieHub.Features.Shared.Views.Controls.DependencyButton" + x:Class="EllieHub.Features.Common.Views.Controls.DependencyButton" x:DataType="vm:DependencyButtonViewModel"> diff --git a/EllieHub/Features/Shared/Views/Controls/DependencyButton.axaml.cs b/EllieHub/Features/Common/Views/Controls/DependencyButton.axaml.cs similarity index 79% rename from EllieHub/Features/Shared/Views/Controls/DependencyButton.axaml.cs rename to EllieHub/Features/Common/Views/Controls/DependencyButton.axaml.cs index 1b72be6..2bec229 100644 --- a/EllieHub/Features/Shared/Views/Controls/DependencyButton.axaml.cs +++ b/EllieHub/Features/Common/Views/Controls/DependencyButton.axaml.cs @@ -1,7 +1,7 @@ using Avalonia.ReactiveUI; -using EllieHub.Features.Shared.ViewModels; +using EllieHub.Features.Common.ViewModels; -namespace EllieHub.Features.Shared.Views.Controls; +namespace EllieHub.Features.Common.Views.Controls; /// /// Represents a button that installs a dependency for Ellie. diff --git a/EllieHub/Features/Shared/Views/Controls/UriInputBar.axaml b/EllieHub/Features/Common/Views/Controls/UriInputBar.axaml similarity index 91% rename from EllieHub/Features/Shared/Views/Controls/UriInputBar.axaml rename to EllieHub/Features/Common/Views/Controls/UriInputBar.axaml index 38ea3fc..4ed0890 100644 --- a/EllieHub/Features/Shared/Views/Controls/UriInputBar.axaml +++ b/EllieHub/Features/Common/Views/Controls/UriInputBar.axaml @@ -2,10 +2,10 @@ 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:vm="using:EllieHub.Features.Shared.ViewModels" + xmlns:vm="using:EllieHub.Features.Common.ViewModels" xmlns:dd="using:EllieHub.Avalonia.DesignData.Controls" mc:Ignorable="d" d:DesignWidth="700" d:DesignHeight="33" - x:Class="EllieHub.Features.Shared.Views.Controls.UriInputBar" + x:Class="EllieHub.Features.Common.Views.Controls.UriInputBar" x:DataType="vm:UriInputBarViewModel"> diff --git a/EllieHub/Features/Shared/Views/Controls/UriInputBar.axaml.cs b/EllieHub/Features/Common/Views/Controls/UriInputBar.axaml.cs similarity index 80% rename from EllieHub/Features/Shared/Views/Controls/UriInputBar.axaml.cs rename to EllieHub/Features/Common/Views/Controls/UriInputBar.axaml.cs index beae307..42dc5a2 100644 --- a/EllieHub/Features/Shared/Views/Controls/UriInputBar.axaml.cs +++ b/EllieHub/Features/Common/Views/Controls/UriInputBar.axaml.cs @@ -1,7 +1,7 @@ using Avalonia.ReactiveUI; -using EllieHub.Features.Shared.ViewModels; +using EllieHub.Features.Common.ViewModels; -namespace EllieHub.Features.Shared.Views.Controls; +namespace EllieHub.Features.Common.Views.Controls; /// /// Represents a text box that receives the absolute path to a directory. diff --git a/EllieHub/Features/Home/Services/Abstractions/IAppResolver.cs b/EllieHub/Features/Home/Services/Abstractions/IAppResolver.cs index fb17d89..4f32b76 100644 --- a/EllieHub/Features/Home/Services/Abstractions/IAppResolver.cs +++ b/EllieHub/Features/Home/Services/Abstractions/IAppResolver.cs @@ -1,4 +1,4 @@ -using EllieHub.Features.Shared.Services.Abstractions; +using EllieHub.Features.Common.Services.Abstractions; namespace EllieHub.Features.Home.Services.Abstractions; diff --git a/EllieHub/Features/Home/Services/AppResolver.cs b/EllieHub/Features/Home/Services/AppResolver.cs index de05f50..20a46bb 100644 --- a/EllieHub/Features/Home/Services/AppResolver.cs +++ b/EllieHub/Features/Home/Services/AppResolver.cs @@ -1,3 +1,4 @@ +using Toastie.Utilities; using Microsoft.Extensions.Caching.Memory; using EllieHub.Features.Home.Models.Api.Toastielab; using EllieHub.Features.Home.Services.Abstractions; @@ -51,7 +52,7 @@ public sealed class AppResolver : IAppResolver /// public void LaunchNewVersion() - => Utilities.StartProcess(BinaryUri); + => ToastieUtilities.StartProcess(BinaryUri); /// /// if the updater can be updated, @@ -61,7 +62,7 @@ public sealed class AppResolver : IAppResolver /// public async ValueTask CanUpdateAsync(CancellationToken cToken = default) { - if (!Utilities.CanWriteTo(AppContext.BaseDirectory)) + if (!ToastieUtilities.HasWritePermissionAt(AppContext.BaseDirectory)) return null; var currentVersion = await GetCurrentVersionAsync(cToken); @@ -88,7 +89,7 @@ public sealed class AppResolver : IAppResolver var result = false; foreach (var file in Directory.GetFiles(AppContext.BaseDirectory).Where(x => x.EndsWith(OldFileSuffix, StringComparison.Ordinal))) - result |= Utilities.TryDeleteFile(file); + result |= ToastieUtilities.TryDeleteFile(file); return result; } @@ -144,21 +145,13 @@ public sealed class AppResolver : IAppResolver if (File.Exists(destinationUri)) File.Move(destinationUri, destinationUri + OldFileSuffix, true); - // Move the new file to the application's directory. - if (Environment.OSVersion.Platform is not PlatformID.Unix) - File.Move(newFileUri, destinationUri, true); - else - { - // Circumvent this issue on Unix systems: https://github.com/dotnet/runtime/issues/31149 - using var moveProcess = Utilities.StartProcess("mv", $"\"{newFileUri}\" \"{destinationUri}\""); - await moveProcess.WaitForExitAsync(cToken); - } + ToastieUtilities.TryMoveFile(newFileUri, destinationUri, true); } // Mark the new binary file as executable. if (Environment.OSVersion.Platform is PlatformID.Unix) { - using var chmod = Utilities.StartProcess("chmod", $"+x \"{BinaryUri}\""); + using var chmod = ToastieUtilities.StartProcess("chmod", $"+x \"{BinaryUri}\""); await chmod.WaitForExitAsync(cToken); } @@ -167,8 +160,8 @@ public sealed class AppResolver : IAppResolver finally { // Cleanup - Utilities.TryDeleteFile(zipTempLocation); - Utilities.TryDeleteDirectory(appTempLocation); + ToastieUtilities.TryDeleteFile(zipTempLocation); + ToastieUtilities.TryDeleteDirectory(appTempLocation); } } diff --git a/EllieHub/Features/Home/Views/Controls/HomeView.axaml b/EllieHub/Features/Home/Views/Controls/HomeView.axaml index 91aaf0f..6d30451 100644 --- a/EllieHub/Features/Home/Views/Controls/HomeView.axaml +++ b/EllieHub/Features/Home/Views/Controls/HomeView.axaml @@ -28,15 +28,15 @@ Grid.ColumnSpan="5" Fill="{DynamicResource HeavyBackground}"/> - - - @@ -147,7 +147,7 @@ VerticalAlignment="Top"/> -