diff --git a/.editorconfig b/.editorconfig index a33a9742..fe3764bd 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,205 +1,210 @@ -# To learn more about .editorconfig see https://aka.ms/editorconfigdocs - -############################### -# Core EditorConfig Options # https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-code-style-settings-reference -############################### -# Remove the line below if you want to inherit .editorconfig settings from higher directories -root = true - -# All files -[*] -# Don't use tabs for indentation. -indent_style = space -max_line_length = 120 -end_of_line = lf -charset = utf-8 -trim_trailing_whitespace = true -insert_final_newline = true -# (Please don't specify an indent_size here; that has too many unintended consequences.) -spelling_languages = en-us, uk-ua - -# Code files -[*.cs] -indent_size = 2 - -# XML project files -[*.{csproj,projitems,shproj,wixproj,runsettings}] -indent_size = 2 - -# XML config files -[*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct,wxs}] -indent_size = 2 - -# XAML files -[*.xaml] -indent_size = 2 - -# JSON files -[*.json] -indent_size = 2 - -# XML files -[*.xml, *.svg] -indent_size = 2 - -# Powershell files -[*.ps1] -indent_size = 2 - -# Shell script files -[*.sh] -indent_size = 2 - - -############################### -# Code style rules # https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ -############################### -[*.cs] - -# | Language rules -# |-- Parentheses preferences -dotnet_diagnostic.IDE0047.severity = none -dotnet_diagnostic.IDE0048.severity = none -# |-- Namespace options -csharp_style_namespace_declarations = file_scoped:silent -# |-- var preferences -csharp_style_var_for_built_in_types = true:silent -csharp_style_var_when_type_is_apparent = true:silent -csharp_style_var_elsewhere = true:silent -# |-- Expression-bodied members -dotnet_diagnostic.IDE0021.severity = none -dotnet_diagnostic.IDE0022.severity = none -dotnet_diagnostic.IDE0023.severity = none -dotnet_diagnostic.IDE0024.severity = none - -# | Formatting rules -# |-- Using directive options -dotnet_sort_system_directives_first = true -dotnet_separate_import_directive_groups = false -# |-- Dotnet namespace options -dotnet_style_namespace_match_folder = true -# |-- New-line options -csharp_new_line_before_open_brace = all -csharp_new_line_before_else = true -csharp_new_line_before_catch = true -csharp_new_line_before_finally = true -csharp_new_line_before_members_in_object_initializers = true -csharp_new_line_before_members_in_anonymous_types = true -csharp_new_line_between_query_expression_clauses = true -# |-- Indentation options -csharp_indent_case_contents = true -csharp_indent_switch_labels = true -csharp_indent_labels = flush_left -csharp_indent_block_contents = true -csharp_indent_braces = false -csharp_indent_case_contents_when_block = false -# |-- Spacing options -csharp_space_after_cast = true -csharp_space_after_keywords_in_control_flow_statements = true -#csharp_space_between_parentheses = control_flow_statements, expressions, type_casts -csharp_space_before_colon_in_inheritance_clause = true -csharp_space_after_colon_in_inheritance_clause = true -csharp_space_around_binary_operators = before_and_after -csharp_space_between_method_declaration_parameter_list_parentheses = false -csharp_space_between_method_declaration_empty_parameter_list_parentheses = false -csharp_space_between_method_declaration_name_and_open_parenthesis = false -csharp_space_between_method_call_parameter_list_parentheses = false -csharp_space_between_method_call_empty_parameter_list_parentheses = false -csharp_space_between_method_call_name_and_opening_parenthesis = false -csharp_space_after_comma = true -csharp_space_before_comma = false -csharp_space_after_dot = false -csharp_space_before_dot = false -csharp_space_after_semicolon_in_for_statement = true -csharp_space_before_semicolon_in_for_statement = false -csharp_space_around_declaration_statements = false -csharp_space_before_open_square_brackets = false -csharp_space_between_empty_square_brackets = false -csharp_space_between_square_brackets = false -# |--Wrap options -csharp_preserve_single_line_statements = false -csharp_preserve_single_line_blocks = true - -# | Naming rules -# |-- Non-private static fields are PascalCase -dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.severity = warning -dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.symbols = non_private_static_fields -dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.style = non_private_static_field_style -dotnet_naming_symbols.non_private_static_fields.applicable_kinds = field -dotnet_naming_symbols.non_private_static_fields.applicable_accessibilities = public, protected, internal, protected_internal, private_protected -dotnet_naming_symbols.non_private_static_fields.required_modifiers = static -dotnet_naming_style.non_private_static_field_style.capitalization = pascal_case -# |-- Non-private readonly fields are PascalCase -dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.severity = warning -dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.symbols = non_private_readonly_fields -dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.style = non_private_static_field_style -dotnet_naming_symbols.non_private_readonly_fields.applicable_kinds = field -dotnet_naming_symbols.non_private_readonly_fields.applicable_accessibilities = public, protected, internal, protected_internal, private_protected -dotnet_naming_symbols.non_private_readonly_fields.required_modifiers = readonly -dotnet_naming_style.non_private_readonly_field_style.capitalization = pascal_case -# |-- Constants are PascalCase -dotnet_naming_rule.constants_should_be_pascal_case.severity = warning -dotnet_naming_rule.constants_should_be_pascal_case.symbols = constants -dotnet_naming_rule.constants_should_be_pascal_case.style = non_private_static_field_style -dotnet_naming_symbols.constants.applicable_kinds = field, local -dotnet_naming_symbols.constants.required_modifiers = const -dotnet_naming_style.constant_style.capitalization = pascal_case -# |-- Static fields are camelCase and start with s_ -dotnet_naming_rule.static_fields_should_be_camel_case.severity = suggestion -dotnet_naming_rule.static_fields_should_be_camel_case.symbols = static_fields -dotnet_naming_rule.static_fields_should_be_camel_case.style = static_field_style -dotnet_naming_symbols.static_fields.applicable_kinds = field -dotnet_naming_symbols.static_fields.required_modifiers = static -dotnet_naming_style.static_field_style.capitalization = camel_case -dotnet_naming_style.static_field_style.required_prefix = s_ -# |-- Instance fields are camelCase and start with _ -dotnet_naming_rule.instance_fields_should_be_camel_case.severity = warning -dotnet_naming_rule.instance_fields_should_be_camel_case.symbols = instance_fields -dotnet_naming_rule.instance_fields_should_be_camel_case.style = instance_field_style -dotnet_naming_symbols.instance_fields.applicable_kinds = field -dotnet_naming_style.instance_field_style.capitalization = camel_case -dotnet_naming_style.instance_field_style.required_prefix = _ -# |-- Locals and parameters are camelCase -dotnet_naming_rule.locals_should_be_camel_case.severity = warning -dotnet_naming_rule.locals_should_be_camel_case.symbols = locals_and_parameters -dotnet_naming_rule.locals_should_be_camel_case.style = camel_case_style -dotnet_naming_symbols.locals_and_parameters.applicable_kinds = parameter, local -dotnet_naming_style.camel_case_style.capitalization = camel_case -# |-- Local functions are PascalCase -dotnet_naming_rule.local_functions_should_be_pascal_case.severity = warning -dotnet_naming_rule.local_functions_should_be_pascal_case.symbols = local_functions -dotnet_naming_rule.local_functions_should_be_pascal_case.style = non_private_static_field_style -dotnet_naming_symbols.local_functions.applicable_kinds = local_function -dotnet_naming_style.local_function_style.capitalization = pascal_case -# |-- Interfaces are PascalCase and start with I -dotnet_naming_rule.interface_should_be_begins_with_i.severity = warning -dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface -dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i -dotnet_naming_symbols.interface.applicable_kinds = interface -dotnet_naming_style.begins_with_i.required_prefix = I -dotnet_naming_style.begins_with_i.capitalization = pascal_case -# |-- By default, name items with PascalCase -dotnet_naming_rule.members_should_be_pascal_case.severity = warning -dotnet_naming_rule.members_should_be_pascal_case.symbols = all_members -dotnet_naming_rule.members_should_be_pascal_case.style = non_private_static_field_style -dotnet_naming_symbols.all_members.applicable_kinds = * -dotnet_naming_style.pascal_case_style.capitalization = pascal_case - - -############################### -# Warnings Suppressing # -############################### -[*.cs] - -# CA1010: Collections should implement generic interface +# To learn more about .editorconfig see https://aka.ms/editorconfigdocs + +############################### +# Core EditorConfig Options # https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-code-style-settings-reference +############################### +# Remove the line below if you want to inherit .editorconfig settings from higher directories +root = true + +# All files +[*] +# Don't use tabs for indentation. +indent_style = space +max_line_length = 120 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true +# (Please don't specify an indent_size here; that has too many unintended consequences.) +spelling_languages = en-us, uk-ua + +# Code files +[*.cs] +indent_size = 2 + +# XML project files +[*.{csproj,projitems,shproj,wixproj,runsettings}] +indent_size = 2 + +# XML config files +[*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct,wxs}] +indent_size = 2 + +# XAML files +[*.xaml] +indent_size = 2 + +# JSON files +[*.json] +indent_size = 2 + +# XML files +[*.xml, *.svg] +indent_size = 2 + +# Powershell files +[*.ps1] +indent_size = 2 + +# Shell script files +[*.sh] +indent_size = 2 + + +############################### +# Code style rules # https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/ +############################### +[*.cs] + +# | Language rules +# |-- Parentheses preferences +dotnet_diagnostic.IDE0047.severity = none +dotnet_diagnostic.IDE0048.severity = none +# |-- Namespace options +csharp_style_namespace_declarations = file_scoped:silent +# |-- var preferences +csharp_style_var_for_built_in_types = true:silent +csharp_style_var_when_type_is_apparent = true:silent +csharp_style_var_elsewhere = true:silent +# |-- Expression-bodied members +dotnet_diagnostic.IDE0021.severity = none +dotnet_diagnostic.IDE0022.severity = none +dotnet_diagnostic.IDE0023.severity = none +dotnet_diagnostic.IDE0024.severity = none + +# | Formatting rules +# |-- Using directive options +dotnet_sort_system_directives_first = true +dotnet_separate_import_directive_groups = false +# |-- Dotnet namespace options +dotnet_style_namespace_match_folder = true +# |-- New-line options +csharp_new_line_before_open_brace = all +csharp_new_line_before_else = true +csharp_new_line_before_catch = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_between_query_expression_clauses = true +# |-- Indentation options +csharp_indent_case_contents = true +csharp_indent_switch_labels = true +csharp_indent_labels = flush_left +csharp_indent_block_contents = true +csharp_indent_braces = false +csharp_indent_case_contents_when_block = false +# |-- Spacing options +csharp_space_after_cast = true +csharp_space_after_keywords_in_control_flow_statements = true +#csharp_space_between_parentheses = control_flow_statements, expressions, type_casts +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_around_binary_operators = before_and_after +csharp_space_between_method_declaration_parameter_list_parentheses = false +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +csharp_space_between_method_declaration_name_and_open_parenthesis = false +csharp_space_between_method_call_parameter_list_parentheses = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_after_comma = true +csharp_space_before_comma = false +csharp_space_after_dot = false +csharp_space_before_dot = false +csharp_space_after_semicolon_in_for_statement = true +csharp_space_before_semicolon_in_for_statement = false +csharp_space_around_declaration_statements = false +csharp_space_before_open_square_brackets = false +csharp_space_between_empty_square_brackets = false +csharp_space_between_square_brackets = false +# |--Wrap options +csharp_preserve_single_line_statements = false +csharp_preserve_single_line_blocks = true + +# | Naming rules +# |-- Non-private static fields are PascalCase +dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.severity = warning +dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.symbols = non_private_static_fields +dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.style = non_private_static_field_style +dotnet_naming_symbols.non_private_static_fields.applicable_kinds = field +dotnet_naming_symbols.non_private_static_fields.applicable_accessibilities = public, protected, internal, protected_internal, private_protected +dotnet_naming_symbols.non_private_static_fields.required_modifiers = static +dotnet_naming_style.non_private_static_field_style.capitalization = pascal_case +# |-- Non-private readonly fields are PascalCase +dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.severity = warning +dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.symbols = non_private_readonly_fields +dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.style = non_private_static_field_style +dotnet_naming_symbols.non_private_readonly_fields.applicable_kinds = field +dotnet_naming_symbols.non_private_readonly_fields.applicable_accessibilities = public, protected, internal, protected_internal, private_protected +dotnet_naming_symbols.non_private_readonly_fields.required_modifiers = readonly +dotnet_naming_style.non_private_readonly_field_style.capitalization = pascal_case +# |-- Constants are PascalCase +dotnet_naming_rule.constants_should_be_pascal_case.severity = warning +dotnet_naming_rule.constants_should_be_pascal_case.symbols = constants +dotnet_naming_rule.constants_should_be_pascal_case.style = non_private_static_field_style +dotnet_naming_symbols.constants.applicable_kinds = field, local +dotnet_naming_symbols.constants.required_modifiers = const +dotnet_naming_style.constant_style.capitalization = pascal_case +# |-- Static fields are camelCase and start with s_ +dotnet_naming_rule.static_fields_should_be_camel_case.severity = suggestion +dotnet_naming_rule.static_fields_should_be_camel_case.symbols = static_fields +dotnet_naming_rule.static_fields_should_be_camel_case.style = static_field_style +dotnet_naming_symbols.static_fields.applicable_kinds = field +dotnet_naming_symbols.static_fields.required_modifiers = static +dotnet_naming_style.static_field_style.capitalization = camel_case +dotnet_naming_style.static_field_style.required_prefix = s_ +# |-- Instance fields are camelCase and start with _ +dotnet_naming_rule.instance_fields_should_be_camel_case.severity = warning +dotnet_naming_rule.instance_fields_should_be_camel_case.symbols = instance_fields +dotnet_naming_rule.instance_fields_should_be_camel_case.style = instance_field_style +dotnet_naming_symbols.instance_fields.applicable_kinds = field +dotnet_naming_style.instance_field_style.capitalization = camel_case +dotnet_naming_style.instance_field_style.required_prefix = _ +# |-- Locals and parameters are camelCase +dotnet_naming_rule.locals_should_be_camel_case.severity = warning +dotnet_naming_rule.locals_should_be_camel_case.symbols = locals_and_parameters +dotnet_naming_rule.locals_should_be_camel_case.style = camel_case_style +dotnet_naming_symbols.locals_and_parameters.applicable_kinds = parameter, local +dotnet_naming_style.camel_case_style.capitalization = camel_case +# |-- Local functions are PascalCase +dotnet_naming_rule.local_functions_should_be_pascal_case.severity = warning +dotnet_naming_rule.local_functions_should_be_pascal_case.symbols = local_functions +dotnet_naming_rule.local_functions_should_be_pascal_case.style = non_private_static_field_style +dotnet_naming_symbols.local_functions.applicable_kinds = local_function +dotnet_naming_style.local_function_style.capitalization = pascal_case +# |-- Interfaces are PascalCase and start with I +dotnet_naming_rule.interface_should_be_begins_with_i.severity = warning +dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface +dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i +dotnet_naming_symbols.interface.applicable_kinds = interface +dotnet_naming_style.begins_with_i.required_prefix = I +dotnet_naming_style.begins_with_i.capitalization = pascal_case +# |-- By default, name items with PascalCase +dotnet_naming_rule.members_should_be_pascal_case.severity = warning +dotnet_naming_rule.members_should_be_pascal_case.symbols = all_members +dotnet_naming_rule.members_should_be_pascal_case.style = non_private_static_field_style +dotnet_naming_symbols.all_members.applicable_kinds = * +dotnet_naming_style.pascal_case_style.capitalization = pascal_case + + +############################### +# Warnings Suppressing # +############################### +[*.cs] + +# CA1010: Collections should implement generic interface dotnet_diagnostic.CA1010.severity = none -# CS1591: Missing XML comment for publicly visible type or member -dotnet_diagnostic.CS1591.severity = none - +# CA1062: Validate arguments of public methods +dotnet_diagnostic.CA1062.severity = none + +# CS1591: Missing XML comment for publicly visible type or member +dotnet_diagnostic.CS1591.severity = none + dotnet_diagnostic.S1186.severity = none +dotnet_diagnostic.S3885.severity = none dotnet_diagnostic.S4200.severity = none - -dotnet_diagnostic.VSTHRD100.severity = none - -dotnet_diagnostic.SYSLIB1054.severity = none +dotnet_diagnostic.S6602.severity = none + +dotnet_diagnostic.VSTHRD100.severity = none + +dotnet_diagnostic.SYSLIB1054.severity = none diff --git a/Plugins/Tum4ik.JustClipboardManager.PluginsDevKit/Tum4ik.JustClipboardManager.PluginDevKit.csproj b/Plugins/Tum4ik.JustClipboardManager.PluginsDevKit/Tum4ik.JustClipboardManager.PluginDevKit.csproj index 842d651a..c881acd3 100644 --- a/Plugins/Tum4ik.JustClipboardManager.PluginsDevKit/Tum4ik.JustClipboardManager.PluginDevKit.csproj +++ b/Plugins/Tum4ik.JustClipboardManager.PluginsDevKit/Tum4ik.JustClipboardManager.PluginDevKit.csproj @@ -29,14 +29,14 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/Tests/Tum4ik.Deployment.UnitTests/Tum4ik.Deployment.UnitTests.csproj b/Tests/Tum4ik.Deployment.UnitTests/Tum4ik.Deployment.UnitTests.csproj index be906843..6148c17e 100644 --- a/Tests/Tum4ik.Deployment.UnitTests/Tum4ik.Deployment.UnitTests.csproj +++ b/Tests/Tum4ik.Deployment.UnitTests/Tum4ik.Deployment.UnitTests.csproj @@ -10,9 +10,9 @@ - - - + + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/Tests/Tum4ik.JustClipboardManager.UnitTests/Services/ClipboardHookServiceTests.cs b/Tests/Tum4ik.JustClipboardManager.UnitTests/Services/ClipboardHookServiceTests.cs index 0c4a1a0c..8a553c64 100644 --- a/Tests/Tum4ik.JustClipboardManager.UnitTests/Services/ClipboardHookServiceTests.cs +++ b/Tests/Tum4ik.JustClipboardManager.UnitTests/Services/ClipboardHookServiceTests.cs @@ -38,7 +38,7 @@ internal async Task HwndHook_ClipboardUpdateMsg_PublishesClipboardChangedEvent() var handled = false; testeeService.HwndHook(WinHandle, 0x031D, default, default, ref handled); - await Task.Delay(505); + await Task.Delay(600); clipboardChangedEvent.Received(1).Publish(); } diff --git a/Tests/Tum4ik.JustClipboardManager.UnitTests/Tum4ik.JustClipboardManager.UnitTests.csproj b/Tests/Tum4ik.JustClipboardManager.UnitTests/Tum4ik.JustClipboardManager.UnitTests.csproj index 0e677a64..ae7df5fd 100644 --- a/Tests/Tum4ik.JustClipboardManager.UnitTests/Tum4ik.JustClipboardManager.UnitTests.csproj +++ b/Tests/Tum4ik.JustClipboardManager.UnitTests/Tum4ik.JustClipboardManager.UnitTests.csproj @@ -23,14 +23,14 @@ - + - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/Tum4ik.JustClipboardManager/Ioc/Wrappers/IClipboard.cs b/Tum4ik.JustClipboardManager/Ioc/Wrappers/IClipboard.cs index 22249289..8f54474d 100644 --- a/Tum4ik.JustClipboardManager/Ioc/Wrappers/IClipboard.cs +++ b/Tum4ik.JustClipboardManager/Ioc/Wrappers/IClipboard.cs @@ -1,9 +1,9 @@ using System.Windows; -using YT.IIGen.Attributes; +using Tum4ik.StinimGen.Attributes; namespace Tum4ik.JustClipboardManager.Ioc.Wrappers; -[IIFor(typeof(Clipboard), "ClipboardWrapper")] +[IIFor(typeof(Clipboard), WrapperClassName = "ClipboardWrapper")] internal partial interface IClipboard { } diff --git a/Tum4ik.JustClipboardManager/Ioc/Wrappers/IEnvironment.cs b/Tum4ik.JustClipboardManager/Ioc/Wrappers/IEnvironment.cs index 7debd9eb..1ef79d23 100644 --- a/Tum4ik.JustClipboardManager/Ioc/Wrappers/IEnvironment.cs +++ b/Tum4ik.JustClipboardManager/Ioc/Wrappers/IEnvironment.cs @@ -1,8 +1,8 @@ -using YT.IIGen.Attributes; +using Tum4ik.StinimGen.Attributes; namespace Tum4ik.JustClipboardManager.Ioc.Wrappers; -[IIFor(typeof(Environment), "EnvironmentWrapper")] +[IIFor(typeof(Environment), WrapperClassName = "EnvironmentWrapper")] internal partial interface IEnvironment { } diff --git a/Tum4ik.JustClipboardManager/Ioc/Wrappers/IFile.cs b/Tum4ik.JustClipboardManager/Ioc/Wrappers/IFile.cs index 002caaee..9cd0dcd1 100644 --- a/Tum4ik.JustClipboardManager/Ioc/Wrappers/IFile.cs +++ b/Tum4ik.JustClipboardManager/Ioc/Wrappers/IFile.cs @@ -1,9 +1,9 @@ -using System.IO; -using YT.IIGen.Attributes; +using System.IO; +using Tum4ik.StinimGen.Attributes; namespace Tum4ik.JustClipboardManager.Ioc.Wrappers; -[IIFor(typeof(File), "FileWrapper")] +[IIFor(typeof(File), WrapperClassName = "FileWrapper")] internal partial interface IFile { } diff --git a/Tum4ik.JustClipboardManager/Ioc/Wrappers/IPath.cs b/Tum4ik.JustClipboardManager/Ioc/Wrappers/IPath.cs index 7f15b705..2b6c9579 100644 --- a/Tum4ik.JustClipboardManager/Ioc/Wrappers/IPath.cs +++ b/Tum4ik.JustClipboardManager/Ioc/Wrappers/IPath.cs @@ -1,9 +1,9 @@ using System.IO; -using YT.IIGen.Attributes; +using Tum4ik.StinimGen.Attributes; namespace Tum4ik.JustClipboardManager.Ioc.Wrappers; -[IIFor(typeof(Path), "PathWrapper")] +[IIFor(typeof(Path), WrapperClassName = "PathWrapper")] internal partial interface IPath { } diff --git a/Tum4ik.JustClipboardManager/Ioc/Wrappers/IProcess.cs b/Tum4ik.JustClipboardManager/Ioc/Wrappers/IProcess.cs index 96c372ad..a77b85b0 100644 --- a/Tum4ik.JustClipboardManager/Ioc/Wrappers/IProcess.cs +++ b/Tum4ik.JustClipboardManager/Ioc/Wrappers/IProcess.cs @@ -1,9 +1,9 @@ using System.Diagnostics; -using YT.IIGen.Attributes; +using Tum4ik.StinimGen.Attributes; namespace Tum4ik.JustClipboardManager.Ioc.Wrappers; -[IIFor(typeof(Process), "ProcessWrapper")] +[IIFor(typeof(Process), WrapperClassName = "ProcessWrapper")] internal partial interface IProcess { } diff --git a/Tum4ik.JustClipboardManager/Services/PInvokeWrappers/IKernel32DllService.cs b/Tum4ik.JustClipboardManager/Services/PInvokeWrappers/IKernel32DllService.cs index 154c058e..048ecfee 100644 --- a/Tum4ik.JustClipboardManager/Services/PInvokeWrappers/IKernel32DllService.cs +++ b/Tum4ik.JustClipboardManager/Services/PInvokeWrappers/IKernel32DllService.cs @@ -3,26 +3,10 @@ namespace Tum4ik.JustClipboardManager.Services.PInvokeWrappers; internal interface IKernel32DllService { - /// - /// Adds a character string to the global atom table and returns a unique value (an atom) identifying the string. - /// - /// - /// The null-terminated string to be added. The string can have a maximum size of 255 bytes. - /// Strings that differ only in case are considered identical. The case of the first string of this name - /// added to the table is preserved and returned by the GlobalGetAtomName function. - /// - /// - /// If the function succeeds, the return value is the newly created atom. - /// If the function fails, the return value is zero. - /// + /// ushort GlobalAddAtom(string lpString) => PInvoke.GlobalAddAtom(lpString); - /// - /// Decrements the reference count of a global string atom. If the atom's reference count reaches zero, - /// removes the string associated with the atom from the global atom table. - /// - /// The atom and character string to be deleted. - /// The function always returns (ATOM) 0. + /// ushort GlobalDeleteAtom(ushort nAtom) => PInvoke.GlobalDeleteAtom(nAtom); } diff --git a/Tum4ik.JustClipboardManager/Services/PInvokeWrappers/IOleaccDllService.cs b/Tum4ik.JustClipboardManager/Services/PInvokeWrappers/IOleaccDllService.cs index 79673ce7..b9cca1f8 100644 --- a/Tum4ik.JustClipboardManager/Services/PInvokeWrappers/IOleaccDllService.cs +++ b/Tum4ik.JustClipboardManager/Services/PInvokeWrappers/IOleaccDllService.cs @@ -6,6 +6,7 @@ namespace Tum4ik.JustClipboardManager.Services.PInvokeWrappers; internal interface IOleaccDllService { + /// unsafe int AccessibleObjectFromWindow(nint hwnd, OBJECT_IDENTIFIER dwId, Guid riid, out object ppvObject) { var result = PInvoke.AccessibleObjectFromWindow((HWND) hwnd, (uint) dwId, riid, out var ppv); diff --git a/Tum4ik.JustClipboardManager/Services/PInvokeWrappers/ISHCoreDllService.cs b/Tum4ik.JustClipboardManager/Services/PInvokeWrappers/ISHCoreDllService.cs index 7619be4c..370ca9cf 100644 --- a/Tum4ik.JustClipboardManager/Services/PInvokeWrappers/ISHCoreDllService.cs +++ b/Tum4ik.JustClipboardManager/Services/PInvokeWrappers/ISHCoreDllService.cs @@ -6,20 +6,7 @@ namespace Tum4ik.JustClipboardManager.Services.PInvokeWrappers; internal interface ISHCoreDllService { - /// - /// Queries the dots per inch (dpi) of a display. - /// - /// Handle of the monitor being queried. - /// The type of DPI being queried. - /// - /// The value of the DPI along the X axis. This value always refers to the horizontal edge, - /// even when the screen is rotated. - /// - /// - /// The value of the DPI along the Y axis. This value always refers to the vertical edge, - /// even when the screen is rotated. - /// - /// True if operation succeeds, otherwise - false. + /// bool GetDpiForMonitor(nint hmonitor, MONITOR_DPI_TYPE dpiType, out uint dpiX, out uint dpiY) { var result = PInvoke.GetDpiForMonitor((HMONITOR)hmonitor, dpiType, out dpiX, out dpiY); diff --git a/Tum4ik.JustClipboardManager/Services/PInvokeWrappers/IUser32DllService.cs b/Tum4ik.JustClipboardManager/Services/PInvokeWrappers/IUser32DllService.cs index 3ca81439..868ffe9e 100644 --- a/Tum4ik.JustClipboardManager/Services/PInvokeWrappers/IUser32DllService.cs +++ b/Tum4ik.JustClipboardManager/Services/PInvokeWrappers/IUser32DllService.cs @@ -10,100 +10,26 @@ namespace Tum4ik.JustClipboardManager.Services.PInvokeWrappers; internal interface IUser32DllService { - /// - /// Retrieves the position of the mouse cursor, in screen coordinates. - /// - /// - /// A pointer to a structure that receives the screen coordinates of the cursor. - /// - /// Returns true if successful or false otherwise. + /// bool GetCursorPos(out Point lpPoint) => PInvoke.GetCursorPos(out lpPoint); - /// - /// Changes the size, position, and Z order of a child, pop-up, or top-level window. These windows are ordered - /// according to their appearance on the screen. The topmost window receives the highest rank and is the first - /// window in the Z order. - /// - /// A handle to the window. - /// - /// A handle to the window to precede the positioned window in the Z order. This parameter must be a window handle - /// or one of the following values. - /// - /// The new position of the left side of the window, in client coordinates. - /// The new position of the top of the window, in client coordinates. - /// The new width of the window, in pixels. - /// The new height of the window, in pixels. - /// The window sizing and positioning flags. - /// - /// If the function succeeds, the return value is true. - /// If the function fails, the return value is false. - /// + /// bool SetWindowPos(nint hWnd, nint hWndInsertAfter, int X, int Y, int cx, int cy, SET_WINDOW_POS_FLAGS uFlags) => PInvoke.SetWindowPos((HWND) hWnd, (HWND) hWndInsertAfter, X, Y, cx, cy, uFlags); - /// - /// Sets the specified window's show state. - /// - /// A handle to the window. - /// Controls how the window is to be shown. - /// - /// If the window was previously visible, the return value is nonzero. - /// If the window was previously hidden, the return value is zero. - /// + /// bool ShowWindow(nint hWnd, SHOW_WINDOW_CMD nCmdShow) => PInvoke.ShowWindow((HWND) hWnd, nCmdShow); - /// - /// Retrieves a handle to the foreground window (the window with which the user is currently working). The system - /// assigns a slightly higher priority to the thread that creates the foreground window than it does to other threads. - /// - /// - /// C++ ( Type: Type: HWND )
The return value is a handle to the foreground window. The foreground window - /// can be NULL in certain circumstances, such as when a window is losing activation. - ///
+ /// nint GetForegroundWindow() => PInvoke.GetForegroundWindow(); - /// - /// Retrieves a handle to the display monitor that contains a specified point. - /// - /// Specifies the point of interest in virtual-screen coordinates. - /// - /// Determines the function's return value if the point is not contained within any display monitor. - /// This parameter can be one of the values. - /// - /// - /// If the point is contained by a display monitor, the return value is a handle to that display monitor. - /// If the point is not contained by a display monitor, - /// the return value depends on the value of . - /// + /// nint MonitorFromPoint(Point pt, MONITOR_FROM_FLAGS dwFlags) => PInvoke.MonitorFromPoint(pt, dwFlags); - /// - /// Retrieves a handle to the display monitor that has the largest area of intersection with the bounding rectangle - /// of a specified window. - /// - /// A handle to the window of interest. - /// - /// Determines the function's return value if the window does not intersect any display monitor. - /// - /// - /// If the window intersects one or more display monitor rectangles, the return value is an HMONITOR handle to - /// the display monitor that has the largest area of intersection with the window. - /// If the window does not intersect a display monitor, the return value depends on the value of dwFlags. - /// - /// - /// If the window is currently minimized, MonitorFromWindow uses the rectangle of the window before it was minimized. - /// + /// nint MonitorFromWindow(nint hwnd, MONITOR_FROM_FLAGS dwFlags) => PInvoke.MonitorFromWindow((HWND) hwnd, dwFlags); - /// - /// Retrieves information about a display monitor. - /// - /// A handle to the display monitor of interest. - /// Information about the specified display monitor. - /// - /// If the function succeeds, the return value is true. - /// If the function fails, the return value is false. - /// + /// bool GetMonitorInfo(nint hMonitor, out MONITORINFO monitorInfo) { monitorInfo = new MONITORINFO(); @@ -111,100 +37,29 @@ bool GetMonitorInfo(nint hMonitor, out MONITORINFO monitorInfo) return PInvoke.GetMonitorInfo((HMONITOR) hMonitor, ref monitorInfo); } - /// - /// Defines a system-wide hot key. - /// - /// - /// A handle to the window that will receive WM_HOTKEY messages generated by the hot key. - /// If this parameter is NULL, WM_HOTKEY messages are posted to the message queue of the calling thread - /// and must be processed in the message loop. - /// - /// - /// The identifier of the hot key. If the hWnd parameter is NULL, - /// then the hot key is associated with the current thread rather than with a particular window. - /// - /// The keys that must be pressed in combination with the . - /// The key code of the hot key. - /// - /// If the function succeeds, the return value is true. - /// If the function fails, the return value is false. - /// + /// bool RegisterHotKey(nint hWnd, int id, ModifierKeys modifiers, Key key) { var vk = (uint) KeyInterop.VirtualKeyFromKey(key); return PInvoke.RegisterHotKey((HWND) hWnd, id, (HOT_KEY_MODIFIERS) modifiers, vk); } - /// - /// Frees a hot key previously registered by the calling thread. - /// - /// - /// A handle to the window associated with the hot key to be freed. - /// This parameter should be NULL if the hot key is not associated with a window. - /// - /// The identifier of the hot key to be freed. - /// - /// If the function succeeds, the return value is true. - /// If the function fails, the return value is false. - /// + /// bool UnregisterHotKey(nint hWnd, int id) => PInvoke.UnregisterHotKey((HWND) hWnd, id); - /// - /// Places the given window in the system-maintained clipboard format listener list. - /// - /// A handle to the window to be placed in the clipboard format listener list. - /// Returns TRUE if successful, FALSE otherwise + /// bool AddClipboardFormatListener(nint hwnd) => PInvoke.AddClipboardFormatListener((HWND) hwnd); - /// - /// Removes the given window from the system-maintained clipboard format listener list. - /// - /// A handle to the window to remove from the clipboard format listener list. - /// Returns TRUE if successful, FALSE otherwise. + /// bool RemoveClipboardFormatListener(nint hwnd) => PInvoke.RemoveClipboardFormatListener((HWND) hwnd); - /// - /// Synthesizes keystrokes, mouse motions, and button clicks. - /// - /// - /// An array of structures. - /// Each structure represents an event to be inserted into the keyboard or mouse input stream. - /// - /// - /// The size, in bytes, of an structure. - /// If cbSize is not the size of an structure, the function fails. - /// - /// - /// The function returns the number of events that it successfully inserted into the keyboard or mouse input stream. - /// If the function returns zero, the input was already blocked by another thread. - /// - uint SendInput(INPUT[] pInputs, int cbSize) => PInvoke.SendInput(/*cInputs,*/ pInputs, cbSize); - - /// - /// Brings the thread that created the specified window into the foreground and activates the window. - /// Keyboard input is directed to the window, and various visual cues are changed for the user. - /// The system assigns a slightly higher priority to the thread that created the foreground window - /// than it does to other threads. - /// - /// A handle to the window that should be activated and brought to the foreground. - /// - /// If the window was brought to the foreground, the return value is true. - /// If the window was not brought to the foreground, the return value is false. - /// + /// + uint SendInput(INPUT[] pInputs, int cbSize) => PInvoke.SendInput(pInputs, cbSize); + + /// bool SetForegroundWindow(nint hWnd) => PInvoke.SetForegroundWindow((HWND) hWnd); - /// - /// Sets the keyboard focus to the specified window. - /// The window must be attached to the calling thread's message queue. - /// - /// - /// A handle to the window that will receive the keyboard input. If this parameter is NULL, keystrokes are ignored. - /// - /// - /// If the function succeeds, the return value is the handle to the window that previously had the keyboard focus. - /// If the hWnd parameter is invalid or the window is not attached to the calling thread's message queue, - /// the return value is NULL. - /// + /// nint SetFocus(nint hWnd) => PInvoke.SetFocus((HWND) hWnd); } diff --git a/Tum4ik.JustClipboardManager/Services/PasteService.cs b/Tum4ik.JustClipboardManager/Services/PasteService.cs index ce95a85d..d68f7bc5 100644 --- a/Tum4ik.JustClipboardManager/Services/PasteService.cs +++ b/Tum4ik.JustClipboardManager/Services/PasteService.cs @@ -19,7 +19,7 @@ public PasteService(IClipboardService clipboardService, private static readonly unsafe int InputStructSize = sizeof(INPUT); - public void PasteData(nint targetWindowPtr, ICollection data, string? additionalInfo) + public unsafe void PasteData(nint targetWindowPtr, ICollection data, string? additionalInfo) { if (data.Count == 0) { diff --git a/Tum4ik.JustClipboardManager/Services/UpdateService.cs b/Tum4ik.JustClipboardManager/Services/UpdateService.cs index c9886be2..d0d0e784 100644 --- a/Tum4ik.JustClipboardManager/Services/UpdateService.cs +++ b/Tum4ik.JustClipboardManager/Services/UpdateService.cs @@ -1,178 +1,182 @@ -using System.Diagnostics.CodeAnalysis; -using System.IO; -using System.Net.Http; -using Microsoft.AppCenter.Crashes; -using Octokit; -using Tum4ik.JustClipboardManager.Ioc.Wrappers; -using FileMode = System.IO.FileMode; - -namespace Tum4ik.JustClipboardManager.Services; -internal class UpdateService : IUpdateService -{ - private readonly IInfoService _infoService; - private readonly IGitHubClient _gitHubClient; - private readonly IEnvironment _environment; - - public UpdateService(IInfoService infoService, - IGitHubClient gitHubClient, - IEnvironment environment) - { - _infoService = infoService; - _gitHubClient = gitHubClient; - _environment = environment; - } - - - public async Task CheckForUpdatesAsync() - { - try - { - var latestRelease = await _gitHubClient.Repository - .Release - .GetLatest("Tum4ik", "just-clipboard-manager") - .ConfigureAwait(false); - if (Version.TryParse(latestRelease.TagName, out var latestReleaseVersion)) - { - if (latestReleaseVersion > _infoService.Version) - { - var osArchitecture = _environment.Is64BitOperatingSystem ? "x64" : "x86"; - var downloadLink = latestRelease.Assets - .Single(a => a.Name.Contains(osArchitecture, StringComparison.OrdinalIgnoreCase) - && a.Name.Contains(".exe", StringComparison.OrdinalIgnoreCase)) - .BrowserDownloadUrl; - return new(true) - { - LatestVersion = latestReleaseVersion, - DownloadLink = new(downloadLink), - ReleaseNotes = latestRelease.Body - }; - } - } - else - { - Crashes.TrackError( - new ArgumentException("Parse version problem when check for updates."), new Dictionary() - { - { "Lates release tag", latestRelease.TagName } - } - ); - } - } - catch (TaskCanceledException) - { - // TODO - } - catch (HttpRequestException) - { - // TODO: log request problem - } - catch (ApiException) - { - // TODO: log github api exception +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Net.Http; +using Microsoft.AppCenter.Crashes; +using Octokit; +using Tum4ik.JustClipboardManager.Ioc.Wrappers; +using FileMode = System.IO.FileMode; + +namespace Tum4ik.JustClipboardManager.Services; +internal class UpdateService : IUpdateService +{ + private readonly IInfoService _infoService; + private readonly IGitHubClient _gitHubClient; + private readonly IEnvironment _environment; + + public UpdateService(IInfoService infoService, + IGitHubClient gitHubClient, + IEnvironment environment) + { + _infoService = infoService; + _gitHubClient = gitHubClient; + _environment = environment; + } + + + public async Task CheckForUpdatesAsync() + { + try + { + var latestRelease = await _gitHubClient.Repository + .Release + .GetLatest("Tum4ik", "just-clipboard-manager") + .ConfigureAwait(false); + if (Version.TryParse(latestRelease.TagName, out var latestReleaseVersion)) + { + if (latestReleaseVersion > _infoService.Version) + { + var osArchitecture = _environment.Is64BitOperatingSystem ? "x64" : "x86"; + var downloadLink = latestRelease.Assets + .Single(a => a.Name.Contains(osArchitecture, StringComparison.OrdinalIgnoreCase) + && a.Name.Contains(".exe", StringComparison.OrdinalIgnoreCase)) + .BrowserDownloadUrl; + return new(true) + { + LatestVersion = latestReleaseVersion, + DownloadLink = new(downloadLink), + ReleaseNotes = latestRelease.Body + }; + } + } + else + { + Crashes.TrackError( + new ArgumentException("Parse version problem when check for updates."), new Dictionary() + { + { "Lates release tag", latestRelease.TagName } + } + ); + } + } + catch (TaskCanceledException) + { + // TODO + } + catch (HttpRequestException) + { + // TODO: log request problem + } + catch (ApiException) + { + // TODO: log github api exception + } + + return new(false); + } + + + public async Task DownloadUpdatesAsync(Uri downloadLink, + IProgress? progress, + CancellationToken cancellationToken) + { + using var httpClient = new HttpClient(); + try + { + using var response = await httpClient + .GetAsync(downloadLink, HttpCompletionOption.ResponseHeadersRead, cancellationToken) + .ConfigureAwait(false); + response.EnsureSuccessStatusCode(); + + var exeFilePath = Path.Combine(Path.GetTempPath(), downloadLink.Segments.Last()); + var buffer = new byte[8192]; + var totalBytes = response.Content.Headers.ContentLength; + var totalBytesDownloaded = 0L; + + using var contentStream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); + using var fileStream = + new FileStream(exeFilePath, FileMode.Create, FileAccess.Write, FileShare.None, buffer.Length, true); + + var prevPercentage = 0; + while (true) + { + var bytesDownloaded = await contentStream + .ReadAsync(buffer.AsMemory(0, buffer.Length), cancellationToken) + .ConfigureAwait(false); + if (bytesDownloaded == 0) + { + progress?.Report(100); + break; + } + + await fileStream.WriteAsync(buffer.AsMemory(0, bytesDownloaded), cancellationToken).ConfigureAwait(false); + totalBytesDownloaded += bytesDownloaded; + + int currentPercentage; + if (totalBytes.HasValue) + { + currentPercentage = GetDownloadPercentage(totalBytes.Value, totalBytesDownloaded); + } + else + { + currentPercentage = 0; + } + + if (currentPercentage > prevPercentage) + { + prevPercentage = currentPercentage; + progress?.Report(currentPercentage); + } + } + + return new(exeFilePath); + } + catch (HttpRequestException) + { + // TODO: log request problem + } + catch (TaskCanceledException) + { + // download canceled } - - return new(false); - } - - - public async Task DownloadUpdatesAsync(Uri downloadLink, - IProgress? progress, - CancellationToken cancellationToken) - { - using var httpClient = new HttpClient(); - try + catch (IOException) { - using var response = await httpClient - .GetAsync(downloadLink, HttpCompletionOption.ResponseHeadersRead, cancellationToken) - .ConfigureAwait(false); - response.EnsureSuccessStatusCode(); - - var exeFilePath = Path.Combine(Path.GetTempPath(), downloadLink.Segments.Last()); - var buffer = new byte[8192]; - var totalBytes = response.Content.Headers.ContentLength; - var totalBytesDownloaded = 0L; - - using var contentStream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); - using var fileStream = - new FileStream(exeFilePath, FileMode.Create, FileAccess.Write, FileShare.None, buffer.Length, true); - - var prevPercentage = 0; - while (true) - { - var bytesDownloaded = await contentStream - .ReadAsync(buffer.AsMemory(0, buffer.Length), cancellationToken) - .ConfigureAwait(false); - if (bytesDownloaded == 0) - { - progress?.Report(100); - break; - } - - await fileStream.WriteAsync(buffer.AsMemory(0, bytesDownloaded), cancellationToken).ConfigureAwait(false); - totalBytesDownloaded += bytesDownloaded; - - int currentPercentage; - if (totalBytes.HasValue) - { - currentPercentage = GetDownloadPercentage(totalBytes.Value, totalBytesDownloaded); - } - else - { - currentPercentage = 0; - } - - if (currentPercentage > prevPercentage) - { - prevPercentage = currentPercentage; - progress?.Report(currentPercentage); - } - } - - return new(exeFilePath); - } - catch (HttpRequestException) - { - // TODO: log request problem - } - catch (TaskCanceledException) - { - // download canceled - } - - return null; - } - - - [ExcludeFromCodeCoverage] - public void InstallUpdates(FileInfo exeFile) - { -#if !DEBUG - System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo(exeFile.FullName, "/SILENT") - { - UseShellExecute = true - }); -#endif - } - - - public async void SilentUpdate() - { - var checkUpdatesResult = await CheckForUpdatesAsync().ConfigureAwait(false); - if (checkUpdatesResult.NewVersionIsAvailable - && checkUpdatesResult.DownloadLink is not null) - { - var exe = await DownloadUpdatesAsync(checkUpdatesResult.DownloadLink, null, CancellationToken.None) - .ConfigureAwait(false); - if (exe is not null) - { - InstallUpdates(exe); - } - } - } - - - private static int GetDownloadPercentage(long totalSize, long downloadedSize) - { - return (int) ((double) downloadedSize / totalSize * 100); - } -} + // aborted connection + } + + return null; + } + + + [ExcludeFromCodeCoverage] + public void InstallUpdates(FileInfo exeFile) + { +#if !DEBUG + System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo(exeFile.FullName, "/SILENT") + { + UseShellExecute = true + }); +#endif + } + + + public async void SilentUpdate() + { + var checkUpdatesResult = await CheckForUpdatesAsync().ConfigureAwait(false); + if (checkUpdatesResult.NewVersionIsAvailable + && checkUpdatesResult.DownloadLink is not null) + { + var exe = await DownloadUpdatesAsync(checkUpdatesResult.DownloadLink, null, CancellationToken.None) + .ConfigureAwait(false); + if (exe is not null) + { + InstallUpdates(exe); + } + } + } + + + private static int GetDownloadPercentage(long totalSize, long downloadedSize) + { + return (int) ((double) downloadedSize / totalSize * 100); + } +} diff --git a/Tum4ik.JustClipboardManager/Tum4ik.JustClipboardManager.csproj b/Tum4ik.JustClipboardManager/Tum4ik.JustClipboardManager.csproj index 49562074..7fbfe9d1 100644 --- a/Tum4ik.JustClipboardManager/Tum4ik.JustClipboardManager.csproj +++ b/Tum4ik.JustClipboardManager/Tum4ik.JustClipboardManager.csproj @@ -175,10 +175,10 @@
- + - + @@ -191,14 +191,14 @@ all - + - - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + +