diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..be457cc --- /dev/null +++ b/.editorconfig @@ -0,0 +1,532 @@ +# editorconfig.org + +# top-most EditorConfig file +root = true + +# Default settings: +# A newline ending every file +# Use 4 spaces as indentation +[*] +insert_final_newline = true +indent_style = space +indent_size = 4 +dotnet_diagnostic.CA1027.severity=error +dotnet_diagnostic.CA1062.severity=error +dotnet_diagnostic.CA1064.severity=error +dotnet_diagnostic.CA1066.severity=error +dotnet_diagnostic.CA1067.severity=error +dotnet_diagnostic.CA1068.severity=error +dotnet_diagnostic.CA1069.severity=warning +dotnet_diagnostic.CA2013.severity=error +dotnet_diagnostic.CA1802.severity=error +dotnet_diagnostic.CA1813.severity=error +dotnet_diagnostic.CA1814.severity=error +dotnet_diagnostic.CA1815.severity=error +dotnet_diagnostic.CA1822.severity=error +dotnet_diagnostic.CA1827.severity=error +dotnet_diagnostic.CA1828.severity=error +dotnet_diagnostic.CA1826.severity=error +dotnet_diagnostic.CA1829.severity=error +dotnet_diagnostic.CA1830.severity=error +dotnet_diagnostic.CA1831.severity=error +dotnet_diagnostic.CA1832.severity=error +dotnet_diagnostic.CA1833.severity=error +dotnet_diagnostic.CA1834.severity=error +dotnet_diagnostic.CA1835.severity=error +dotnet_diagnostic.CA1836.severity=error +dotnet_diagnostic.CA1837.severity=error +dotnet_diagnostic.CA1838.severity=error +dotnet_diagnostic.CA2015.severity=error +dotnet_diagnostic.CA2012.severity=error +dotnet_diagnostic.CA2011.severity=error +dotnet_diagnostic.CA2009.severity=error +dotnet_diagnostic.CA2008.severity=error +dotnet_diagnostic.CA2007.severity=warning +dotnet_diagnostic.CA2000.severity=suggestion + +[project.json] +indent_size = 2 + +# C# files +[*.cs] +# New line preferences +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 preferences +csharp_indent_block_contents = true +csharp_indent_braces = false +csharp_indent_case_contents = true +csharp_indent_case_contents_when_block = true +csharp_indent_switch_labels = true +csharp_indent_labels = one_less_than_current + +# Modifier preferences +csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion + +# avoid this. unless absolutely necessary +dotnet_style_qualification_for_field = false:suggestion +dotnet_style_qualification_for_property = false:suggestion +dotnet_style_qualification_for_method = false:suggestion +dotnet_style_qualification_for_event = false:suggestion + +# only use var when it's obvious what the variable type is +csharp_style_var_for_built_in_types = true:suggestion +csharp_style_var_when_type_is_apparent = true:suggestion +csharp_style_var_elsewhere = true:suggestion + +# prefer C# premade types. +dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion +dotnet_style_predefined_type_for_member_access = true:suggestion + +# name all constant fields using PascalCase +dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields +dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style +dotnet_naming_symbols.constant_fields.applicable_kinds = field +dotnet_naming_symbols.constant_fields.required_modifiers = const +dotnet_naming_style.pascal_case_style.capitalization = pascal_case + +# static fields should have s_ prefix +dotnet_naming_rule.static_fields_should_have_prefix.severity = suggestion +dotnet_naming_rule.static_fields_should_have_prefix.symbols = static_fields +dotnet_naming_rule.static_fields_should_have_prefix.style = static_prefix_style +dotnet_naming_symbols.static_fields.applicable_kinds = field +dotnet_naming_symbols.static_fields.required_modifiers = static +dotnet_naming_symbols.static_fields.applicable_accessibilities = private, internal, private_protected +dotnet_naming_style.static_prefix_style.required_prefix = s_ +dotnet_naming_style.static_prefix_style.capitalization = camel_case + +# internal and private fields should be _camelCase +dotnet_naming_rule.camel_case_for_private_internal_fields.severity = suggestion +dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields +dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style +dotnet_naming_symbols.private_internal_fields.applicable_kinds = field +dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal +dotnet_naming_style.camel_case_underscore_style.required_prefix = _ +dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case + +# Code style defaults +csharp_using_directive_placement = outside_namespace:suggestion +dotnet_sort_system_directives_first = true +csharp_prefer_braces = true:silent +csharp_preserve_single_line_blocks = true:none +csharp_preserve_single_line_statements = false:none +csharp_prefer_static_local_function = true:suggestion +csharp_prefer_simple_using_statement = false:none +csharp_style_prefer_switch_expression = true:suggestion + +# Code quality +dotnet_style_readonly_field = true:suggestion +dotnet_code_quality_unused_parameters = non_public:suggestion + +# Expression-level preferences +dotnet_style_object_initializer = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_explicit_tuple_names = true:suggestion +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_null_propagation = true:suggestion +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion +dotnet_style_prefer_inferred_tuple_names = true:suggestion +dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion +dotnet_style_prefer_auto_properties = true:suggestion +dotnet_style_prefer_conditional_expression_over_assignment = true:silent +dotnet_style_prefer_conditional_expression_over_return = true:silent +csharp_prefer_simple_default_expression = true:suggestion + +# Expression-bodied members +csharp_style_expression_bodied_methods = true:suggestion +csharp_style_expression_bodied_constructors = true:suggestion +csharp_style_expression_bodied_operators = true:suggestion +csharp_style_expression_bodied_properties = true:suggestion +csharp_style_expression_bodied_indexers = true:suggestion +csharp_style_expression_bodied_accessors = true:suggestion +csharp_style_expression_bodied_lambdas = true:suggestion +csharp_style_expression_bodied_local_functions = true:suggestion + +# Pattern matching +csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion +csharp_style_pattern_matching_over_as_with_null_check = true:suggestion +csharp_style_inlined_variable_declaration = true:suggestion + +# Null checking preferences +csharp_style_throw_expression = true:suggestion +csharp_style_conditional_delegate_call = true:suggestion + +# Other features +csharp_style_prefer_index_operator = false:none +csharp_style_prefer_range_operator = false:none +csharp_style_pattern_local_over_anonymous_function = false:none + +# Space preferences +csharp_space_after_cast = false +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_after_comma = true +csharp_space_after_dot = false +csharp_space_after_keywords_in_control_flow_statements = true +csharp_space_after_semicolon_in_for_statement = true +csharp_space_around_binary_operators = before_and_after +csharp_space_around_declaration_statements = do_not_ignore +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_before_comma = false +csharp_space_before_dot = false +csharp_space_before_open_square_brackets = false +csharp_space_before_semicolon_in_for_statement = false +csharp_space_between_empty_square_brackets = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_call_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_declaration_parameter_list_parentheses = false +csharp_space_between_parentheses = false +csharp_space_between_square_brackets = false + +# analyzers +dotnet_diagnostic.AvoidAsyncVoid.severity = suggestion + +dotnet_diagnostic.CA1000.severity = none +dotnet_diagnostic.CA1001.severity = error +dotnet_diagnostic.CA1009.severity = error +dotnet_diagnostic.CA1016.severity = error +dotnet_diagnostic.CA1030.severity = none +dotnet_diagnostic.CA1031.severity = none +dotnet_diagnostic.CA1033.severity = none +dotnet_diagnostic.CA1036.severity = none +dotnet_diagnostic.CA1049.severity = error +dotnet_diagnostic.CA1056.severity = suggestion +dotnet_diagnostic.CA1060.severity = error +dotnet_diagnostic.CA1061.severity = error +dotnet_diagnostic.CA1063.severity = error +dotnet_diagnostic.CA1065.severity = error +dotnet_diagnostic.CA1301.severity = error +dotnet_diagnostic.CA1303.severity = none +dotnet_diagnostic.CA1308.severity = none +dotnet_diagnostic.CA1400.severity = error +dotnet_diagnostic.CA1401.severity = error +dotnet_diagnostic.CA1403.severity = error +dotnet_diagnostic.CA1404.severity = error +dotnet_diagnostic.CA1405.severity = error +dotnet_diagnostic.CA1410.severity = error +dotnet_diagnostic.CA1415.severity = error +dotnet_diagnostic.CA1507.severity = error +dotnet_diagnostic.CA1710.severity = suggestion +dotnet_diagnostic.CA1724.severity = none +dotnet_diagnostic.CA1810.severity = none +dotnet_diagnostic.CA1821.severity = error +dotnet_diagnostic.CA1900.severity = error +dotnet_diagnostic.CA1901.severity = error +dotnet_diagnostic.CA2000.severity = none +dotnet_diagnostic.CA2002.severity = error +dotnet_diagnostic.CA2007.severity = none +dotnet_diagnostic.CA2100.severity = error +dotnet_diagnostic.CA2101.severity = error +dotnet_diagnostic.CA2108.severity = error +dotnet_diagnostic.CA2111.severity = error +dotnet_diagnostic.CA2112.severity = error +dotnet_diagnostic.CA2114.severity = error +dotnet_diagnostic.CA2116.severity = error +dotnet_diagnostic.CA2117.severity = error +dotnet_diagnostic.CA2122.severity = error +dotnet_diagnostic.CA2123.severity = error +dotnet_diagnostic.CA2124.severity = error +dotnet_diagnostic.CA2126.severity = error +dotnet_diagnostic.CA2131.severity = error +dotnet_diagnostic.CA2132.severity = error +dotnet_diagnostic.CA2133.severity = error +dotnet_diagnostic.CA2134.severity = error +dotnet_diagnostic.CA2137.severity = error +dotnet_diagnostic.CA2138.severity = error +dotnet_diagnostic.CA2140.severity = error +dotnet_diagnostic.CA2141.severity = error +dotnet_diagnostic.CA2146.severity = error +dotnet_diagnostic.CA2147.severity = error +dotnet_diagnostic.CA2149.severity = error +dotnet_diagnostic.CA2200.severity = error +dotnet_diagnostic.CA2202.severity = error +dotnet_diagnostic.CA2207.severity = error +dotnet_diagnostic.CA2212.severity = error +dotnet_diagnostic.CA2213.severity = error +dotnet_diagnostic.CA2214.severity = error +dotnet_diagnostic.CA2216.severity = error +dotnet_diagnostic.CA2220.severity = error +dotnet_diagnostic.CA2229.severity = error +dotnet_diagnostic.CA2231.severity = error +dotnet_diagnostic.CA2232.severity = error +dotnet_diagnostic.CA2235.severity = error +dotnet_diagnostic.CA2236.severity = error +dotnet_diagnostic.CA2237.severity = error +dotnet_diagnostic.CA2238.severity = error +dotnet_diagnostic.CA2240.severity = error +dotnet_diagnostic.CA2241.severity = error +dotnet_diagnostic.CA2242.severity = error + +dotnet_diagnostic.RCS1001.severity = error +dotnet_diagnostic.RCS1018.severity = error +dotnet_diagnostic.RCS1037.severity = error +dotnet_diagnostic.RCS1055.severity = error +dotnet_diagnostic.RCS1062.severity = error +dotnet_diagnostic.RCS1066.severity = error +dotnet_diagnostic.RCS1069.severity = error +dotnet_diagnostic.RCS1071.severity = error +dotnet_diagnostic.RCS1074.severity = error +dotnet_diagnostic.RCS1090.severity = error +dotnet_diagnostic.RCS1138.severity = error +dotnet_diagnostic.RCS1139.severity = error +dotnet_diagnostic.RCS1163.severity = suggestion +dotnet_diagnostic.RCS1168.severity = suggestion +dotnet_diagnostic.RCS1188.severity = error +dotnet_diagnostic.RCS1201.severity = error +dotnet_diagnostic.RCS1207.severity = error +dotnet_diagnostic.RCS1211.severity = error +dotnet_diagnostic.RCS1507.severity = error + +dotnet_diagnostic.SA1000.severity = error +dotnet_diagnostic.SA1001.severity = error +dotnet_diagnostic.SA1002.severity = error +dotnet_diagnostic.SA1003.severity = error +dotnet_diagnostic.SA1004.severity = error +dotnet_diagnostic.SA1005.severity = error +dotnet_diagnostic.SA1006.severity = error +dotnet_diagnostic.SA1007.severity = error +dotnet_diagnostic.SA1008.severity = error +dotnet_diagnostic.SA1009.severity = error +dotnet_diagnostic.SA1010.severity = none +dotnet_diagnostic.SA1011.severity = error +dotnet_diagnostic.SA1012.severity = error +dotnet_diagnostic.SA1013.severity = error +dotnet_diagnostic.SA1014.severity = error +dotnet_diagnostic.SA1015.severity = error +dotnet_diagnostic.SA1016.severity = error +dotnet_diagnostic.SA1017.severity = error +dotnet_diagnostic.SA1018.severity = error +dotnet_diagnostic.SA1019.severity = error +dotnet_diagnostic.SA1020.severity = error +dotnet_diagnostic.SA1021.severity = error +dotnet_diagnostic.SA1022.severity = error +dotnet_diagnostic.SA1023.severity = error +dotnet_diagnostic.SA1024.severity = error +dotnet_diagnostic.SA1025.severity = error +dotnet_diagnostic.SA1026.severity = error +dotnet_diagnostic.SA1027.severity = error +dotnet_diagnostic.SA1028.severity = error +dotnet_diagnostic.SA1100.severity = error +dotnet_diagnostic.SA1101.severity = none +dotnet_diagnostic.SA1102.severity = error +dotnet_diagnostic.SA1103.severity = error +dotnet_diagnostic.SA1104.severity = error +dotnet_diagnostic.SA1105.severity = error +dotnet_diagnostic.SA1106.severity = error +dotnet_diagnostic.SA1107.severity = error +dotnet_diagnostic.SA1108.severity = error +dotnet_diagnostic.SA1110.severity = error +dotnet_diagnostic.SA1111.severity = error +dotnet_diagnostic.SA1112.severity = error +dotnet_diagnostic.SA1113.severity = error +dotnet_diagnostic.SA1114.severity = error +dotnet_diagnostic.SA1115.severity = error +dotnet_diagnostic.SA1116.severity = error +dotnet_diagnostic.SA1117.severity = error +dotnet_diagnostic.SA1118.severity = error +dotnet_diagnostic.SA1119.severity = error +dotnet_diagnostic.SA1120.severity = error +dotnet_diagnostic.SA1121.severity = error +dotnet_diagnostic.SA1122.severity = error +dotnet_diagnostic.SA1123.severity = error +dotnet_diagnostic.SA1124.severity = error +dotnet_diagnostic.SA1125.severity = error +dotnet_diagnostic.SA1127.severity = error +dotnet_diagnostic.SA1128.severity = error +dotnet_diagnostic.SA1129.severity = error +dotnet_diagnostic.SA1130.severity = error +dotnet_diagnostic.SA1131.severity = error +dotnet_diagnostic.SA1132.severity = error +dotnet_diagnostic.SA1133.severity = error +dotnet_diagnostic.SA1134.severity = error +dotnet_diagnostic.SA1135.severity = error +dotnet_diagnostic.SA1136.severity = error +dotnet_diagnostic.SA1137.severity = error +dotnet_diagnostic.SA1139.severity = error +dotnet_diagnostic.SA1200.severity = none +dotnet_diagnostic.SA1201.severity = error +dotnet_diagnostic.SA1202.severity = error +dotnet_diagnostic.SA1203.severity = error +dotnet_diagnostic.SA1204.severity = error +dotnet_diagnostic.SA1205.severity = error +dotnet_diagnostic.SA1206.severity = error +dotnet_diagnostic.SA1207.severity = error +dotnet_diagnostic.SA1208.severity = error +dotnet_diagnostic.SA1209.severity = error +dotnet_diagnostic.SA1210.severity = error +dotnet_diagnostic.SA1211.severity = error +dotnet_diagnostic.SA1212.severity = error +dotnet_diagnostic.SA1213.severity = error +dotnet_diagnostic.SA1214.severity = error +dotnet_diagnostic.SA1216.severity = error +dotnet_diagnostic.SA1217.severity = error +dotnet_diagnostic.SA1300.severity = error +dotnet_diagnostic.SA1302.severity = error +dotnet_diagnostic.SA1303.severity = error +dotnet_diagnostic.SA1304.severity = error +dotnet_diagnostic.SA1306.severity = none +dotnet_diagnostic.SA1307.severity = error +dotnet_diagnostic.SA1308.severity = error +dotnet_diagnostic.SA1309.severity = none +dotnet_diagnostic.SA1310.severity = error +dotnet_diagnostic.SA1311.severity = none +dotnet_diagnostic.SA1312.severity = error +dotnet_diagnostic.SA1313.severity = error +dotnet_diagnostic.SA1314.severity = error +dotnet_diagnostic.SA1316.severity = none +dotnet_diagnostic.SA1400.severity = error +dotnet_diagnostic.SA1401.severity = error +dotnet_diagnostic.SA1402.severity = error +dotnet_diagnostic.SA1403.severity = error +dotnet_diagnostic.SA1404.severity = error +dotnet_diagnostic.SA1405.severity = error +dotnet_diagnostic.SA1406.severity = error +dotnet_diagnostic.SA1407.severity = error +dotnet_diagnostic.SA1408.severity = error +dotnet_diagnostic.SA1410.severity = error +dotnet_diagnostic.SA1411.severity = error +dotnet_diagnostic.SA1413.severity = none +dotnet_diagnostic.SA1500.severity = error +dotnet_diagnostic.SA1501.severity = error +dotnet_diagnostic.SA1502.severity = error +dotnet_diagnostic.SA1503.severity = error +dotnet_diagnostic.SA1504.severity = error +dotnet_diagnostic.SA1505.severity = none +dotnet_diagnostic.SA1506.severity = error +dotnet_diagnostic.SA1507.severity = error +dotnet_diagnostic.SA1508.severity = error +dotnet_diagnostic.SA1509.severity = error +dotnet_diagnostic.SA1510.severity = error +dotnet_diagnostic.SA1511.severity = error +dotnet_diagnostic.SA1512.severity = error +dotnet_diagnostic.SA1513.severity = error +dotnet_diagnostic.SA1514.severity = none +dotnet_diagnostic.SA1515.severity = error +dotnet_diagnostic.SA1516.severity = error +dotnet_diagnostic.SA1517.severity = error +dotnet_diagnostic.SA1518.severity = error +dotnet_diagnostic.SA1519.severity = error +dotnet_diagnostic.SA1520.severity = error +dotnet_diagnostic.SA1600.severity = error +dotnet_diagnostic.SA1601.severity = error +dotnet_diagnostic.SA1602.severity = error +dotnet_diagnostic.SA1604.severity = error +dotnet_diagnostic.SA1605.severity = error +dotnet_diagnostic.SA1606.severity = error +dotnet_diagnostic.SA1607.severity = error +dotnet_diagnostic.SA1608.severity = error +dotnet_diagnostic.SA1610.severity = error +dotnet_diagnostic.SA1611.severity = error +dotnet_diagnostic.SA1612.severity = error +dotnet_diagnostic.SA1613.severity = error +dotnet_diagnostic.SA1614.severity = error +dotnet_diagnostic.SA1615.severity = error +dotnet_diagnostic.SA1616.severity = error +dotnet_diagnostic.SA1617.severity = error +dotnet_diagnostic.SA1618.severity = error +dotnet_diagnostic.SA1619.severity = error +dotnet_diagnostic.SA1620.severity = error +dotnet_diagnostic.SA1621.severity = error +dotnet_diagnostic.SA1622.severity = error +dotnet_diagnostic.SA1623.severity = error +dotnet_diagnostic.SA1624.severity = error +dotnet_diagnostic.SA1625.severity = error +dotnet_diagnostic.SA1626.severity = error +dotnet_diagnostic.SA1627.severity = error +dotnet_diagnostic.SA1629.severity = error +dotnet_diagnostic.SA1633.severity = error +dotnet_diagnostic.SA1634.severity = error +dotnet_diagnostic.SA1635.severity = error +dotnet_diagnostic.SA1636.severity = error +dotnet_diagnostic.SA1637.severity = none +dotnet_diagnostic.SA1638.severity = none +dotnet_diagnostic.SA1640.severity = error +dotnet_diagnostic.SA1641.severity = error +dotnet_diagnostic.SA1642.severity = error +dotnet_diagnostic.SA1643.severity = error +dotnet_diagnostic.SA1649.severity = error +dotnet_diagnostic.SA1651.severity = error + +dotnet_diagnostic.SX1101.severity = error +dotnet_diagnostic.SX1309.severity = error +dotnet_diagnostic.SX1623.severity = none +dotnet_diagnostic.RCS1102.severity=error +dotnet_diagnostic.RCS1166.severity=error +dotnet_diagnostic.RCS1078i.severity=error +dotnet_diagnostic.RCS1248.severity=error +dotnet_diagnostic.RCS1080.severity=error +dotnet_diagnostic.RCS1077.severity=error +dotnet_diagnostic.CA1825.severity=error +dotnet_diagnostic.CA1812.severity=error +dotnet_diagnostic.CA1805.severity=error +dotnet_diagnostic.RCS1197.severity=error +dotnet_diagnostic.RCS1198.severity=none +dotnet_diagnostic.RCS1231.severity=suggestion +dotnet_diagnostic.RCS1235.severity=error +dotnet_diagnostic.RCS1242.severity=error +dotnet_diagnostic.RCS1256.severity=none +dotnet_diagnostic.CA2016.severity=warning +dotnet_diagnostic.CA2014.severity=error +dotnet_diagnostic.RCS1010.severity=error +dotnet_diagnostic.RCS1006.severity=error +dotnet_diagnostic.RCS1005.severity=error +dotnet_diagnostic.RCS1020.severity=error +dotnet_diagnostic.RCS1049.severity=warning +dotnet_diagnostic.RCS1058.severity=warning +dotnet_diagnostic.RCS1068.severity=warning +dotnet_diagnostic.RCS1073.severity=warning +dotnet_diagnostic.RCS1084.severity=error +dotnet_diagnostic.RCS1085.severity=error +dotnet_diagnostic.RCS1105.severity=error +dotnet_diagnostic.RCS1112.severity=error +dotnet_diagnostic.RCS1128.severity=error +dotnet_diagnostic.RCS1143.severity=error +dotnet_diagnostic.RCS1158.severity=none +dotnet_diagnostic.RCS1163.severity=none +dotnet_diagnostic.RCS1171.severity=error +dotnet_diagnostic.RCS1173.severity=error +dotnet_diagnostic.RCS1176.severity=error +dotnet_diagnostic.RCS1177.severity=error +dotnet_diagnostic.RCS1179.severity=error +dotnet_diagnostic.RCS1180.severity=warning +dotnet_diagnostic.RCS1190.severity=error +dotnet_diagnostic.RCS1195.severity=error +dotnet_diagnostic.RCS1214.severity=error + +# C++ Files +[*.{cpp,h,in}] +curly_bracket_next_line = true +indent_brace_style = Allman + +# Xml project files +[*.{csproj,vcxproj,vcxproj.filters,proj,nativeproj,locproj}] +indent_size = 2 + +# Xml build files +[*.builds] +indent_size = 2 + +# Xml files +[*.{xml,stylecop,resx,ruleset}] +indent_size = 2 + +# Xml config files +[*.{props,targets,config,nuspec}] +indent_size = 2 + +# Shell scripts +[*.sh] +end_of_line = lf +[*.{cmd, bat}] +end_of_line = crlf + +vsspell_dictionary_languages = en-US \ No newline at end of file diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..15bebd9 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,45 @@ +# A CODEOWNERS file uses a pattern that follows the same rules used in gitignore files. +# The pattern is followed by one or more GitHub usernames or team names using the +# standard @username or @org/team-name format. You can also refer to a user by an +# email address that has been added to their GitHub account, for example user@example.com + +.github/* @reactiveui/maintainers + +* @reactiveui/core-team +version.json @reactiveui/maintainers + +build.* @reactiveui/devops-team +SignPackages.* @reactiveui/devops-team +NuGet.* @reactiveui/devops-team +.vsts-ci.yml @reactiveui/devops-team +script/* @reactiveui/devops-team + +samples/* @reactiveui/learning-team +snippets/* @reactiveui/learning-team +*.md @reactiveui/learning-team + +src/ReactiveUI.AndroidSupport/* @reactiveui/android-team +src/ReactiveUI/Platforms/android/* @reactiveui/android-team +src/ReactiveUI/Platforms/apple-common/* @reactiveui/ios-team @reactiveui/mac-team +src/ReactiveUI/Platforms/ios/* @reactiveui/ios-team +src/ReactiveUI/Platforms/mac/* @reactiveui/mac-team +src/ReactiveUI/Platforms/net461/* @reactiveui/wpf-team @reactiveui/winforms-team +src/ReactiveUI/Platforms/netcoreapp/* @reactiveui/dotnetcore-team @reactiveui/webassembly-team +src/ReactiveUI/Platforms/uap10/* @reactiveui/uwp-team +src/ReactiveUI/Platforms/tizen/* @reactiveui/tizen-team +src/ReactiveUI/Platforms/tvos/* @reactiveui/tvos-team +src/ReactiveUI/Platforms/windows-common/* @reactiveui/wpf-team @reactiveui/winforms-team @reactiveui/uwp-team +src/ReactiveUI/Platforms/xamarin-common/* @reactiveui/xamarin-forms-team + +src/ReactiveUI.Blend/* @reactiveui/wpf-team @reactiveui/winforms-team @reactiveui/uwp-team + +src/ReactiveUI.Events.WPF/* @reactiveui/wpf-team +src/ReactiveUI.Events.XamForms/* @reactiveui/xamarin-forms-team + +src/ReactiveUI.Fody*/* @reactiveui/fody-team + +src/ReactiveUI.Winforms/* @reactiveui/winforms-team + +src/ReactiveUI.Wpf/* @reactiveui/wpf-team + +src/ReactiveUI.XamForms/* @reactiveui/xamarin-forms-team diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml new file mode 100644 index 0000000..2c19687 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -0,0 +1,102 @@ +name: Bug Report +description: Create a report to help us improve +title: "[Bug]: " +labels: ["bug"] +body: + - type: markdown + attributes: + value: | + ## Please note although we can't commit to any timeline, priority will be given to those who are [Contributors](https://github.com/reactiveui/ReactiveUI#contribute ) to the project. + - type: textarea + id: description + attributes: + label: Describe the bug 🐞 + description: A clear and concise description of what the bug is. + value: "A bug happened!" + validations: + required: true + - type: textarea + id: reproduce-steps + attributes: + label: Step to reproduce + description: "Steps to reproduce the behavior:" + value: | + 1. Go to '...' + 2. Click on '....' + 3. Scroll down to '....' + 4. See error + validations: + required: true + - type: input + id: reproduce-repository + attributes: + label: Reproduction repository + description: "Simple repository representing the bug" + placeholder: https://github.com/reactiveui/ReactiveUI + value: | + https://github.com/reactiveui/ReactiveUI + validations: + required: false + - type: textarea + id: expected-behavior + attributes: + label: Expected behavior + description: A clear and concise description of what you expected to happen. + value: This should happen... + validations: + required: true + - type: textarea + id: screenshots + attributes: + label: Screenshots 🖼️ + description: If applicable, add screenshots to help explain your problem. + validations: + required: false + - type: dropdown + id: ide + attributes: + label: IDE + multiple: true + options: + - Visual Studio 2022 + - Visual Studio 2019 + - Visual Studio 2017 + - Visual Studio for Mac + - Rider Windows + - Rider macOS + - Visual Studio Code + - type: input + id: operating-system + attributes: + label: Operating system + description: Windows, Linux, Mac OS... + validations: + required: false + - type: input + id: system-version + attributes: + label: Version + description: Version and distribution (if applicable) + validations: + required: false + - type: input + id: device + attributes: + label: Device + description: Device e.g. iPhone 6 + validations: + required: false + - type: input + id: reactiveui-version + attributes: + label: ReactiveUI Version + description: e.g. 15.1.1 + validations: + required: false + - type: textarea + id: additional-information + attributes: + label: Additional information ℹ️ + description: Add any other information about the problem here. + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..190b5a1 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: false +contact_links: + - name: Questions + url: https://github.com/reactiveui/ReactiveUI/discussions + about: 'For general questions about ReactiveUI, ask in the GitHub discussions' + - name: Chat + url: https://www.reactiveui.net/slack + about: 'Our slack chat community invite' diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..7290c08 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,37 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: feature request +assignees: '' + +--- + + + +**Is your feature request related to a problem? Please describe.** + + + + +**Describe the solution you'd like** + + + + +**Describe alternatives you've considered** + + + + +**Describe suggestions on how to achieve the feature** + + + + +**Additional context** + diff --git a/.github/renovate.json b/.github/renovate.json new file mode 100644 index 0000000..181188b --- /dev/null +++ b/.github/renovate.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": ["local>reactiveui/.github:renovate"] +} \ No newline at end of file diff --git a/.github/workflows/build-samples.yml b/.github/workflows/build-samples.yml new file mode 100644 index 0000000..65f88b0 --- /dev/null +++ b/.github/workflows/build-samples.yml @@ -0,0 +1,27 @@ +name: Sample Build + +on: + workflow_dispatch: + inputs: + disable: + description: "temporarily disabled" + +env: + productNamespacePrefix: "ReactiveUI" + +permissions: + contents: read + +jobs: + build: + permissions: + contents: none + uses: reactiveui/actions-common/.github/workflows/workflow-common-setup-and-build.yml@main + with: + configuration: Release + productNamespacePrefix: "ReactiveUI" + useVisualStudioPreview: false + useMauiCheckDotNetTool: false + srcFolder: 'integrationtests' + solutionFile: 'IntegrationTests.All.sln' + performTests: false diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml new file mode 100644 index 0000000..90ef074 --- /dev/null +++ b/.github/workflows/ci-build.yml @@ -0,0 +1,26 @@ +name: Build + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +env: + productNamespacePrefix: "ReactiveUI" + +permissions: + contents: read + +jobs: + build: + permissions: + contents: none + uses: reactiveui/actions-common/.github/workflows/workflow-common-setup-and-build.yml@main + with: + configuration: Release + productNamespacePrefix: "ReactiveUI" + dotNetBuild: true + useVisualStudioPreview: false + useMauiCheckDotNetTool: false + solutionFile: "ReactiveUI.Maui.Plugins.Popup.sln" diff --git a/.github/workflows/lock.yml b/.github/workflows/lock.yml new file mode 100644 index 0000000..3f79ecb --- /dev/null +++ b/.github/workflows/lock.yml @@ -0,0 +1,31 @@ +name: 'Lock Threads' + +on: + schedule: + - cron: '0 0 * * *' + workflow_dispatch: + +permissions: + issues: write + pull-requests: write + +concurrency: + group: lock + +jobs: + action: + runs-on: ubuntu-latest + steps: + - uses: dessant/lock-threads@v5 + with: + github-token: ${{ github.token }} + issue-inactive-days: '14' + pr-inactive-days: '14' + issue-comment: > + This issue has been automatically locked since there + has not been any recent activity after it was closed. + Please open a new issue for related bugs. + pr-comment: > + This pull request has been automatically locked since there + has not been any recent activity after it was closed. + Please open a new issue for related bugs. diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..197b313 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,26 @@ +name: Release + +on: + push: + branches: + - main + - patches/* + +env: + productNamespacePrefix: "ReactiveUI" + +jobs: + release: + uses: reactiveui/actions-common/.github/workflows/workflow-common-release.yml@main + with: + configuration: Release + productNamespacePrefix: "ReactiveUI" + dotNetBuild: true + useVisualStudioPreview: false + useMauiCheckDotNetTool: false + solutionFile: "reactiveui.sln" + secrets: + SIGN_CLIENT_USER_ID: ${{ secrets.SIGN_CLIENT_USER_ID }} + SIGN_CLIENT_SECRET: ${{ secrets.SIGN_CLIENT_SECRET }} + SIGN_CLIENT_CONFIG: ${{ secrets.SIGN_CLIENT_CONFIG }} + NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }} diff --git a/README.md b/README.md index 48474fa..83d1b38 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,63 @@ -# Maui.Plugins.Popup +# ReactiveUI.Maui.Plugins.Popup ReactiveUI support for Maui Popups + +## Usage + +Use ConfigureReactiveUIPopup() with MauiAppBuilder to initialise ReactiveUI.Maui.Plugins.Popup + +```csharp +using Microsoft.Maui; +using Microsoft.Maui.Controls.Hosting; +using Microsoft.Maui.Hosting; +using ReactiveUI.Maui.Plugins.Popup; + +namespace MauiApp1 +{ + public class Startup : IStartup + { + public void Configure(IAppHostBuilder appBuilder) + { + appBuilder + .UseMauiApp() + .ConfigureReactiveUIPopup(); + } + } +} +``` + + +The following methods are available + + PopAllPopup + PopPopup + PushPopup + RemovePopupPage + +The Following Observable Events are available + + PoppingObservable + PoppedObservable + PushingObservable + PushedObservable + +The following Controls are available + + ReactivePopupPage + ReactivePopupPage + +## Sponsorship + +The core team members, ReactiveUI contributors and contributors in the ecosystem do this open-source work in their free time. If you use ReactiveUI, a serious task, and you'd like us to invest more time on it, please donate. This project increases your income/productivity too. It makes development and applications faster and it reduces the required bandwidth. + +[Become a sponsor](https://github.com/sponsors/reactivemarbles). + +This is how we use the donations: + +* Allow the core team to work on ReactiveUI +* Thank contributors if they invested a large amount of time in contributing +* Support projects in the ecosystem + + +## .NET Foundation + +ReactiveUI is part of the [.NET Foundation](https://www.dotnetfoundation.org/). Other projects that are associated with the foundation include the Microsoft .NET Compiler Platform ("Roslyn") as well as the Microsoft ASP.NET family of projects, Microsoft .NET Core & Xamarin Forms. diff --git a/images/logo.png b/images/logo.png new file mode 100644 index 0000000..360ee39 Binary files /dev/null and b/images/logo.png differ diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props new file mode 100644 index 0000000..9de0255 --- /dev/null +++ b/src/Directory.Packages.props @@ -0,0 +1,33 @@ + + + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Directory.build.props b/src/Directory.build.props new file mode 100644 index 0000000..c68c7d3 --- /dev/null +++ b/src/Directory.build.props @@ -0,0 +1,68 @@ + + + true + AnyCPU + $(MSBuildProjectName.Contains('Tests')) + embedded + .NET Foundation and Contributors + Copyright (c) .NET Foundation and Contributors + logo.png + README.md + MIT + https://reactiveui.net + A MVVM framework that integrates with the Reactive Extensions for .NET to create elegant, testable User Interfaces that run on any mobile or desktop platform. Supports Maui Popups. + $(DefaultPackageDescription) + mvvm;reactiveui;rx;reactive extensions;observable;LINQ;events;frp;android;ios;mac;maui + https://github.com/reactiveui/Maui.Plugins.Popup/releases + https://github.com/reactiveui/Maui.Plugins.Popup + git + + true + + true + + $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb + enable + preview + True + latest + nullable + true + true + true + + + true + + + + + + + + + + + + + + + + + + $(MSBuildThisFileDirectory) + + + + + + + + + + + + + + + diff --git a/src/ReactiveUI.Maui.Plugins.Popup.sln b/src/ReactiveUI.Maui.Plugins.Popup.sln new file mode 100644 index 0000000..6e63e0f --- /dev/null +++ b/src/ReactiveUI.Maui.Plugins.Popup.sln @@ -0,0 +1,35 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.10.34916.146 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReactiveUI.Maui.Plugins.Popup", "ReactiveUI.Maui.Plugins.Popup\ReactiveUI.Maui.Plugins.Popup.csproj", "{3AB0DD06-D29C-40A3-9BB4-7F98B68A49A1}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionConfig", "SolutionConfig", "{D7DEFA90-ABB2-4B15-B882-FD045EF63844}" + ProjectSection(SolutionItems) = preProject + ..\.editorconfig = ..\.editorconfig + ..\README.md = ..\README.md + ..\version.json = ..\version.json + Directory.build.props = Directory.build.props + Directory.Packages.props = Directory.Packages.props + global.json = global.json + stylecop.json = stylecop.json + EndProjectSection +EndProject +Global + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {60209B6D-CF1E-4D77-B9A9-4A189806F70F} + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3AB0DD06-D29C-40A3-9BB4-7F98B68A49A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3AB0DD06-D29C-40A3-9BB4-7F98B68A49A1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3AB0DD06-D29C-40A3-9BB4-7F98B68A49A1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3AB0DD06-D29C-40A3-9BB4-7F98B68A49A1}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/ReactiveUI.Maui.Plugins.Popup/INavigationMixins.cs b/src/ReactiveUI.Maui.Plugins.Popup/INavigationMixins.cs new file mode 100644 index 0000000..5f0c144 --- /dev/null +++ b/src/ReactiveUI.Maui.Plugins.Popup/INavigationMixins.cs @@ -0,0 +1,118 @@ +// Copyright (c) 2024 .NET Foundation and Contributors. All rights reserved. +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using System.Reactive; +using System.Reactive.Linq; +using Mopups.Events; +using Mopups.Pages; +using Mopups.Services; + +namespace ReactiveUI.Maui.Plugins.Popup; + +/// +/// INavigation Mixins. +/// +public static class INavigationMixins +{ + /// + /// Pops all popup. + /// + /// The navigation. + /// if set to true [animate]. + /// An Observable of Unit. + public static IObservable PopAllPopup(this INavigation navigation, bool animate = true) => + Observable.FromAsync(async _ => await MopupService.Instance.PopAllAsync(animate).ConfigureAwait(false)); + + /// + /// Pops the popup. + /// + /// The navigation. + /// if set to true [animate]. + /// An Observable of Unit. + public static IObservable PopPopup(this INavigation navigation, bool animate = true) => + Observable.FromAsync(async _ => await MopupService.Instance.PopAsync(animate).ConfigureAwait(false)); + + /// + /// Pushes the popup. + /// + /// The Type of Popup Page. + /// The navigation. + /// The popup page. + /// if set to true [animate]. + /// An Observable of Unit. + public static IObservable PushPopup(this INavigation navigation, T page, bool animate = true) + where T : PopupPage => Observable.FromAsync(async _ => await MopupService.Instance.PushAsync(page, animate).ConfigureAwait(false)); + + /// + /// Removes the popup page. + /// + /// The Type of Popup Page. + /// The navigation. + /// The popup page. + /// if set to true [animate]. + /// An Observable of Unit. + public static IObservable RemovePopupPage(this INavigation navigation, T page, bool animate = true) + where T : PopupPage => Observable.FromAsync(async _ => await MopupService.Instance.RemovePageAsync(page, animate).ConfigureAwait(false)); + + /// + /// Poppings the specified service. + /// + /// The service. + /// A PopupNavigationEventArgs. + public static IObservable PoppingObservable(this INavigation navigation) => + Observable.FromEvent, PopupNavigationEventArgs>( + handler => + { + void EventHandler(object? sender, PopupNavigationEventArgs args) => handler(args); + return EventHandler; + }, + x => MopupService.Instance.Popping += x, + x => MopupService.Instance.Popping -= x); + + /// + /// Poppeds the observable. + /// + /// The service. + /// A PopupNavigationEventArgs. + public static IObservable PoppedObservable(this INavigation navigation) => + Observable.FromEvent, PopupNavigationEventArgs>( + handler => + { + void EventHandler(object? sender, PopupNavigationEventArgs args) => handler(args); + return EventHandler; + }, + x => MopupService.Instance.Popped += x, + x => MopupService.Instance.Popped -= x); + + /// + /// Pushings the observable. + /// + /// The service. + /// A PopupNavigationEventArgs. + public static IObservable PushingObservable(this INavigation navigation) => + Observable.FromEvent, PopupNavigationEventArgs>( + handler => + { + void EventHandler(object? sender, PopupNavigationEventArgs args) => handler(args); + return EventHandler; + }, + x => MopupService.Instance.Pushing += x, + x => MopupService.Instance.Pushing -= x); + + /// + /// Pusheds the observable. + /// + /// The service. + /// A PopupNavigationEventArgs. + public static IObservable PushedObservable(this INavigation navigation) => + Observable.FromEvent, PopupNavigationEventArgs>( + handler => + { + void EventHandler(object? sender, PopupNavigationEventArgs args) => handler(args); + return EventHandler; + }, + x => MopupService.Instance.Pushed += x, + x => MopupService.Instance.Pushed -= x); +} diff --git a/src/ReactiveUI.Maui.Plugins.Popup/IPopupNavigationMixins.cs b/src/ReactiveUI.Maui.Plugins.Popup/IPopupNavigationMixins.cs new file mode 100644 index 0000000..d0f8e85 --- /dev/null +++ b/src/ReactiveUI.Maui.Plugins.Popup/IPopupNavigationMixins.cs @@ -0,0 +1,118 @@ +// Copyright (c) 2024 .NET Foundation and Contributors. All rights reserved. +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using System.Reactive; +using System.Reactive.Linq; +using Mopups.Events; +using Mopups.Interfaces; +using Mopups.Pages; + +namespace ReactiveUI.Maui.Plugins.Popup; + +/// +/// IPopupNavigation Mixins. +/// +public static class IPopupNavigationMixins +{ + /// + /// Pops all popup. + /// + /// The navigation. + /// if set to true [animate]. + /// An Observable of Unit. + public static IObservable PopAllPopup(this IPopupNavigation service, bool animate = true) => + Observable.FromAsync(async _ => await service.PopAllAsync(animate).ConfigureAwait(false)); + + /// + /// Pops the popup. + /// + /// The navigation. + /// if set to true [animate]. + /// An Observable of Unit. + public static IObservable PopPopup(this IPopupNavigation service, bool animate = true) => + Observable.FromAsync(async _ => await service.PopAsync(animate).ConfigureAwait(false)); + + /// + /// Pushes the popup. + /// + /// The Type of Popup Page. + /// The navigation. + /// The popup page. + /// if set to true [animate]. + /// An Observable of Unit. + public static IObservable PushPopup(this IPopupNavigation service, T page, bool animate = true) + where T : PopupPage => Observable.FromAsync(async _ => await service.PushAsync(page, animate).ConfigureAwait(false)); + + /// + /// Removes the popup page. + /// + /// The Type of Popup Page. + /// The navigation. + /// The popup page. + /// if set to true [animate]. + /// An Observable of Unit. + public static IObservable RemovePopupPage(this IPopupNavigation service, T page, bool animate = true) + where T : PopupPage => Observable.FromAsync(async _ => await service.RemovePageAsync(page, animate).ConfigureAwait(false)); + + /// + /// Poppings the specified service. + /// + /// The service. + /// A PopupNavigationEventArgs. + public static IObservable PoppingObservable(this IPopupNavigation service) => + Observable.FromEvent, PopupNavigationEventArgs>( + handler => + { + void EventHandler(object? sender, PopupNavigationEventArgs args) => handler(args); + return EventHandler; + }, + x => service.Popping += x, + x => service.Popping -= x); + + /// + /// Poppeds the observable. + /// + /// The service. + /// A PopupNavigationEventArgs. + public static IObservable PoppedObservable(this IPopupNavigation service) => + Observable.FromEvent, PopupNavigationEventArgs>( + handler => + { + void EventHandler(object? sender, PopupNavigationEventArgs args) => handler(args); + return EventHandler; + }, + x => service.Popped += x, + x => service.Popped -= x); + + /// + /// Pushings the observable. + /// + /// The service. + /// A PopupNavigationEventArgs. + public static IObservable PushingObservable(this IPopupNavigation service) => + Observable.FromEvent, PopupNavigationEventArgs>( + handler => + { + void EventHandler(object? sender, PopupNavigationEventArgs args) => handler(args); + return EventHandler; + }, + x => service.Pushing += x, + x => service.Pushing -= x); + + /// + /// Pusheds the observable. + /// + /// The service. + /// A PopupNavigationEventArgs. + public static IObservable PushedObservable(this IPopupNavigation service) => + Observable.FromEvent, PopupNavigationEventArgs>( + handler => + { + void EventHandler(object? sender, PopupNavigationEventArgs args) => handler(args); + return EventHandler; + }, + x => service.Pushed += x, + x => service.Pushed -= x); +} diff --git a/src/ReactiveUI.Maui.Plugins.Popup/MauiAppBuilderMixins.cs b/src/ReactiveUI.Maui.Plugins.Popup/MauiAppBuilderMixins.cs new file mode 100644 index 0000000..32809f6 --- /dev/null +++ b/src/ReactiveUI.Maui.Plugins.Popup/MauiAppBuilderMixins.cs @@ -0,0 +1,48 @@ +// Copyright (c) 2024 .NET Foundation and Contributors. All rights reserved. +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using Mopups.Hosting; +using ReactiveUI; +using ReactiveUI.Maui.Plugins.Popup; +using Splat; + +namespace Microsoft.Maui.Hosting; + +/// +/// INavigation Mixins. +/// +public static class MauiAppBuilderMixins +{ + /// + /// Registers all the default registrations that are needed by the Splat module. + /// Initialize resolvers with the default ReactiveUI types. + /// Configures ReactiveUI Maui Mopups. + /// + /// The builder. + /// MauiAppBuilder. + public static MauiAppBuilder ConfigureReactiveUIPopup(this MauiAppBuilder builder) + { + builder.ConfigureMopups(); + var resolver = Locator.CurrentMutable; + resolver.InitializeSplat(); + resolver.InitializeReactiveUI(RegistrationNamespace.Maui); + return builder; + } + + /// + /// Configures the reactive UI mopups. + /// + /// The builder. + /// The back press handler. + /// MauiAppBuilder. + public static MauiAppBuilder ConfigureReactiveUIPopup(this MauiAppBuilder builder, Action? backPressHandler) + { + builder.ConfigureMopups(backPressHandler); + var resolver = Locator.CurrentMutable; + resolver.InitializeSplat(); + resolver.InitializeReactiveUI(RegistrationNamespace.Maui); + return builder; + } +} diff --git a/src/ReactiveUI.Maui.Plugins.Popup/ReactivePopupPage.cs b/src/ReactiveUI.Maui.Plugins.Popup/ReactivePopupPage.cs new file mode 100644 index 0000000..d433650 --- /dev/null +++ b/src/ReactiveUI.Maui.Plugins.Popup/ReactivePopupPage.cs @@ -0,0 +1,81 @@ +// Copyright (c) 2024 .NET Foundation and Contributors. All rights reserved. +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using System.Reactive; +using System.Reactive.Disposables; +using System.Reactive.Linq; +using Mopups.Pages; + +namespace ReactiveUI.Maui.Plugins.Popup; + +/// +/// Base Popup page for that implements . +/// +public abstract class ReactivePopupPage : PopupPage, IViewFor +{ + /// + /// The view model property. + /// + public static readonly BindableProperty ViewModelProperty = BindableProperty.Create( + nameof(ViewModel), + typeof(object), + typeof(IViewFor), + default, + BindingMode.OneWay, + propertyChanged: OnViewModelChanged); + + /// + /// Initializes a new instance of the class. + /// + protected ReactivePopupPage() => BackgroundClick = + Observable.FromEvent( + handler => + { + void EventHandler(object? sender, EventArgs args) => handler(Unit.Default); + return EventHandler; + }, + x => BackgroundClicked += x, + x => BackgroundClicked -= x) + .Select(_ => Unit.Default); + + /// + /// Gets or sets the background click observable signal. + /// + /// The background click. + public IObservable BackgroundClick { get; protected set; } + + /// + /// Gets or sets the ViewModel to display. + /// + public object? ViewModel + { + get => GetValue(ViewModelProperty); + set => SetValue(ViewModelProperty, value); + } + + /// + /// Gets the control binding disposable. + /// + protected CompositeDisposable ControlBindings { get; } = []; + + /// + /// Called when [view model changed]. + /// + /// The bindable object. + /// The old value. + /// The new value. + protected static void OnViewModelChanged(BindableObject bindableObject, object oldValue, object newValue) + { + ArgumentNullException.ThrowIfNull(bindableObject); + bindableObject.BindingContext = newValue; + } + + /// + protected override void OnBindingContextChanged() + { + base.OnBindingContextChanged(); + ViewModel = BindingContext; + } +} diff --git a/src/ReactiveUI.Maui.Plugins.Popup/ReactivePopupPage{TViewModel}.cs b/src/ReactiveUI.Maui.Plugins.Popup/ReactivePopupPage{TViewModel}.cs new file mode 100644 index 0000000..e1d798a --- /dev/null +++ b/src/ReactiveUI.Maui.Plugins.Popup/ReactivePopupPage{TViewModel}.cs @@ -0,0 +1,41 @@ +// Copyright (c) 2024 .NET Foundation and Contributors. All rights reserved. +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +namespace ReactiveUI.Maui.Plugins.Popup; + +/// +/// Base Popup page for that implements . +/// +/// The view model type. +public abstract class ReactivePopupPage : ReactivePopupPage, IViewFor + where TViewModel : class +{ + /// + /// The view model property. + /// + public static new readonly BindableProperty ViewModelProperty = BindableProperty.Create( + nameof(ViewModel), + typeof(TViewModel), + typeof(ReactivePopupPage), + default(TViewModel), + BindingMode.OneWay, + propertyChanged: OnViewModelChanged); + + /// + /// Gets or sets the ViewModel to display. + /// + public new TViewModel? ViewModel + { + get => (TViewModel?)GetValue(ViewModelProperty); + set => SetValue(ViewModelProperty, value); + } + + /// + protected override void OnBindingContextChanged() + { + base.OnBindingContextChanged(); + ViewModel = BindingContext as TViewModel; + } +} diff --git a/src/ReactiveUI.Maui.Plugins.Popup/ReactiveUI.Maui.Plugins.Popup.csproj b/src/ReactiveUI.Maui.Plugins.Popup/ReactiveUI.Maui.Plugins.Popup.csproj new file mode 100644 index 0000000..63845da --- /dev/null +++ b/src/ReactiveUI.Maui.Plugins.Popup/ReactiveUI.Maui.Plugins.Popup.csproj @@ -0,0 +1,26 @@ + + + net8.0;net8.0-android;net8.0-ios;net8.0-maccatalyst + $(TargetFrameworks);net8.0-windows10.0.19041.0 + Contains the ReactiveUI platform specific extensions for Microsoft Maui Popup + mvvm;reactiveui;rx;reactive extensions;observable;LINQ;events;frp;maui;android;ios;mac;windows;net;popup + true + enable + enable + + 11.0 + 13.1 + 21.0 + 10.0.17763.0 + 10.0.17763.0 + 6.5 + + + + + + + + + + diff --git a/src/global.json b/src/global.json new file mode 100644 index 0000000..4c31281 --- /dev/null +++ b/src/global.json @@ -0,0 +1,6 @@ +{ + "sdk": { + "version": "8.0.10", + "rollForward": "latestMinor" + } +} diff --git a/src/stylecop.json b/src/stylecop.json new file mode 100644 index 0000000..d312166 --- /dev/null +++ b/src/stylecop.json @@ -0,0 +1,41 @@ +{ + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "indentation": { + "useTabs": false, + "indentationSize": 4 + }, + "documentationRules": { + "documentExposedElements": true, + "documentInternalElements": false, + "documentPrivateElements": false, + "documentInterfaces": true, + "documentPrivateFields": false, + "documentationCulture": "en-US", + "companyName": ".NET Foundation and Contributors", + "copyrightText": "Copyright (c) 2024 {companyName}. All rights reserved.\nLicensed to the .NET Foundation under one or more agreements.\nThe .NET Foundation licenses this file to you under the {licenseName} license.\nSee the {licenseFile} file in the project root for full license information.", + "variables": { + "licenseName": "MIT", + "licenseFile": "LICENSE" + }, + "xmlHeader": false + }, + "layoutRules": { + "newlineAtEndOfFile": "allow", + "allowConsecutiveUsings": true + }, + "maintainabilityRules": { + "topLevelTypes": [ + "class", + "interface", + "struct", + "enum", + "delegate" + ] + }, + "orderingRules": { + "usingDirectivesPlacement": "outsideNamespace", + "systemUsingDirectivesFirst": true + } + } +} diff --git a/version.json b/version.json new file mode 100644 index 0000000..2ec07f1 --- /dev/null +++ b/version.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "1.0", + "publicReleaseRefSpec": [ + "^refs/heads/master$", // we release out of master + "^refs/heads/main$", + "^refs/heads/latest$", + "^refs/heads/preview/.*", // we release previews + "^refs/heads/patches/.*", // we release previews + "^refs/heads/rel/\\d+\\.\\d+\\.\\d+" // we also release branches starting with rel/N.N.N + ], + "nugetPackageVersion":{ + "semVer": 2 + }, + "cloudBuild": { + "setVersionVariables": true, + "buildNumber": { + "enabled": false + } + } +}