From aa077c2ed14b8f81a67bd7ff32797e422bac0c6d Mon Sep 17 00:00:00 2001 From: Chris Pulman Date: Sat, 15 Apr 2023 15:32:29 +0100 Subject: [PATCH 01/18] Base Code Need to create a base navigation class --- .editorconfig | 527 ++++++++++++++++ .gitattributes | 289 +++++++++ .github/dependabot.yml | 13 + .github/workflows/ci-build.yml | 83 +++ .github/workflows/lock.yml | 31 + .github/workflows/release.yml | 98 +++ images/logo.png | 3 + src/Directory.Build.props | 56 ++ src/ReactiveMarbles.Navigation.sln | 51 ++ src/ViewModel.Core/IActivatableView.cs | 13 + src/ViewModel.Core/IAmViewFor.cs | 17 + src/ViewModel.Core/IAmViewFor{T}.cs | 20 + src/ViewModel.Core/IHostScreen.cs | 10 + .../INotifiyRoutableViewModel.cs | 47 ++ src/ViewModel.Core/IRxObject.cs | 15 + .../IViewModelRoutedViewHost.cs | 124 ++++ .../MagicInterfaces/IAmBuilt.cs | 12 + .../MagicInterfaces/INotifiyNavigation.cs | 47 ++ .../MagicInterfaces/ISetNavigation.cs | 19 + .../MagicInterfaces/IUseHostedNavigation.cs | 12 + .../MagicInterfaces/IUseNavigation.cs | 19 + .../IViewModelNavigatingEventArgs.cs | 19 + .../IViewModelNavigationBaseEventArgs.cs | 35 ++ .../IViewModelNavigationEventArgs.cs | 35 ++ .../ViewModelNavigatingEventArgs.cs | 36 ++ .../ViewModelNavigationBaseEventArgs.cs | 37 ++ .../ViewModelNavigationEventArgs.cs | 54 ++ src/ViewModel.Core/NavigationType.cs | 26 + .../ReactiveMarbles.ViewModel.Core.csproj | 14 + src/ViewModel.Core/RxObject.cs | 98 +++ src/ViewModel.Core/RxObjectMixins.cs | 32 + .../ViewModelRoutedViewHostMixins.cs | 568 ++++++++++++++++++ .../ReactiveMarbles.ViewModel.WinForms.csproj | 14 + .../ReactiveMarbles.ViewModel.Wpf.csproj | 14 + src/stylecop.json | 41 ++ version.json | 16 + 36 files changed, 2545 insertions(+) create mode 100644 .editorconfig create mode 100644 .gitattributes create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/ci-build.yml create mode 100644 .github/workflows/lock.yml create mode 100644 .github/workflows/release.yml create mode 100644 images/logo.png create mode 100644 src/Directory.Build.props create mode 100644 src/ReactiveMarbles.Navigation.sln create mode 100644 src/ViewModel.Core/IActivatableView.cs create mode 100644 src/ViewModel.Core/IAmViewFor.cs create mode 100644 src/ViewModel.Core/IAmViewFor{T}.cs create mode 100644 src/ViewModel.Core/IHostScreen.cs create mode 100644 src/ViewModel.Core/INotifiyRoutableViewModel.cs create mode 100644 src/ViewModel.Core/IRxObject.cs create mode 100644 src/ViewModel.Core/IViewModelRoutedViewHost.cs create mode 100644 src/ViewModel.Core/MagicInterfaces/IAmBuilt.cs create mode 100644 src/ViewModel.Core/MagicInterfaces/INotifiyNavigation.cs create mode 100644 src/ViewModel.Core/MagicInterfaces/ISetNavigation.cs create mode 100644 src/ViewModel.Core/MagicInterfaces/IUseHostedNavigation.cs create mode 100644 src/ViewModel.Core/MagicInterfaces/IUseNavigation.cs create mode 100644 src/ViewModel.Core/NavigationEvents/IViewModelNavigatingEventArgs.cs create mode 100644 src/ViewModel.Core/NavigationEvents/IViewModelNavigationBaseEventArgs.cs create mode 100644 src/ViewModel.Core/NavigationEvents/IViewModelNavigationEventArgs.cs create mode 100644 src/ViewModel.Core/NavigationEvents/ViewModelNavigatingEventArgs.cs create mode 100644 src/ViewModel.Core/NavigationEvents/ViewModelNavigationBaseEventArgs.cs create mode 100644 src/ViewModel.Core/NavigationEvents/ViewModelNavigationEventArgs.cs create mode 100644 src/ViewModel.Core/NavigationType.cs create mode 100644 src/ViewModel.Core/ReactiveMarbles.ViewModel.Core.csproj create mode 100644 src/ViewModel.Core/RxObject.cs create mode 100644 src/ViewModel.Core/RxObjectMixins.cs create mode 100644 src/ViewModel.Core/ViewModelRoutedViewHostMixins.cs create mode 100644 src/ViewModel.WinForms/ReactiveMarbles.ViewModel.WinForms.csproj create mode 100644 src/ViewModel.Wpf/ReactiveMarbles.ViewModel.Wpf.csproj create mode 100644 src/stylecop.json create mode 100644 version.json diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..c516004 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,527 @@ +# 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 = error +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=suggestion +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=error +dotnet_diagnostic.RCS1231.severity=none +dotnet_diagnostic.RCS1235.severity=error +dotnet_diagnostic.RCS1242.severity=error +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.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 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..5044446 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,289 @@ +# Catch all for anything we forgot. Add rules if you get CRLF to LF warnings. +* text=auto + +# Text files that should be normalized to LF in odb. +*.cs text eol=lf diff=csharp +*.xaml text +*.config text +*.c text +*.h text +*.cpp text +*.hpp text +*.sln text +*.csproj text +*.vcxproj text +*.md text +*.tt text +*.sh text +*.ps1 text +*.cmd text +*.bat text +*.markdown text +*.msbuild text +# Binary files that should not be normalized or diffed +*.png binary +*.jpg binary +*.gif binary +*.ico binary +*.rc binary +*.pfx binary +*.snk binary +*.dll binary +*.exe binary +*.lib binary +*.exp binary +*.pdb binary +*.sdf binary +*.7z binary +# Generated file should just use CRLF, it's fiiine +SolutionInfo.cs text eol=crlf diff=csharp +*.mht filter=lfs diff=lfs merge=lfs -text +*.ppam filter=lfs diff=lfs merge=lfs -text +*.wmv filter=lfs diff=lfs merge=lfs -text +*.btif filter=lfs diff=lfs merge=lfs -text +*.fla filter=lfs diff=lfs merge=lfs -text +*.qt filter=lfs diff=lfs merge=lfs -text +*.xlam filter=lfs diff=lfs merge=lfs -text +*.xm filter=lfs diff=lfs merge=lfs -text +*.djvu filter=lfs diff=lfs merge=lfs -text +*.woff filter=lfs diff=lfs merge=lfs -text +*.a filter=lfs diff=lfs merge=lfs -text +*.bak filter=lfs diff=lfs merge=lfs -text +*.lha filter=lfs diff=lfs merge=lfs -text +*.mpg filter=lfs diff=lfs merge=lfs -text +*.xltm filter=lfs diff=lfs merge=lfs -text +*.eol filter=lfs diff=lfs merge=lfs -text +*.ipa filter=lfs diff=lfs merge=lfs -text +*.ttf filter=lfs diff=lfs merge=lfs -text +*.uvm filter=lfs diff=lfs merge=lfs -text +*.cmx filter=lfs diff=lfs merge=lfs -text +*.dng filter=lfs diff=lfs merge=lfs -text +*.xltx filter=lfs diff=lfs merge=lfs -text +*.fli filter=lfs diff=lfs merge=lfs -text +*.wmx filter=lfs diff=lfs merge=lfs -text +*.jxr filter=lfs diff=lfs merge=lfs -text +*.pyv filter=lfs diff=lfs merge=lfs -text +*.s7z filter=lfs diff=lfs merge=lfs -text +*.csv filter=lfs diff=lfs merge=lfs -text +*.pptm filter=lfs diff=lfs merge=lfs -text +*.rz filter=lfs diff=lfs merge=lfs -text +*.wm filter=lfs diff=lfs merge=lfs -text +*.xlsx filter=lfs diff=lfs merge=lfs -text +*.bh filter=lfs diff=lfs merge=lfs -text +*.dat filter=lfs diff=lfs merge=lfs -text +*.mid filter=lfs diff=lfs merge=lfs -text +*.mpga filter=lfs diff=lfs merge=lfs -text +*.ogg filter=lfs diff=lfs merge=lfs -text +*.s3m filter=lfs diff=lfs merge=lfs -text +*.mar filter=lfs diff=lfs merge=lfs -text +*.movie filter=lfs diff=lfs merge=lfs -text +*.pptx filter=lfs diff=lfs merge=lfs -text +*.dll filter=lfs diff=lfs merge=lfs -text +*.docm filter=lfs diff=lfs merge=lfs -text +*.m3u filter=lfs diff=lfs merge=lfs -text +*.mov filter=lfs diff=lfs merge=lfs -text +*.aac filter=lfs diff=lfs merge=lfs -text +*.jar filter=lfs diff=lfs merge=lfs -text +*.midi filter=lfs diff=lfs merge=lfs -text +*.mobi filter=lfs diff=lfs merge=lfs -text +*.potm filter=lfs diff=lfs merge=lfs -text +*.woff2 filter=lfs diff=lfs merge=lfs -text +*.cab filter=lfs diff=lfs merge=lfs -text +*.dmg filter=lfs diff=lfs merge=lfs -text +*.pdf filter=lfs diff=lfs merge=lfs -text +*.war filter=lfs diff=lfs merge=lfs -text +*.bz2 filter=lfs diff=lfs merge=lfs -text +*.icns filter=lfs diff=lfs merge=lfs -text +*.slk filter=lfs diff=lfs merge=lfs -text +*.wbmp filter=lfs diff=lfs merge=lfs -text +*.xpm filter=lfs diff=lfs merge=lfs -text +*.xmind filter=lfs diff=lfs merge=lfs -text +*.3g2 filter=lfs diff=lfs merge=lfs -text +*.m4v filter=lfs diff=lfs merge=lfs -text +*.pic filter=lfs diff=lfs merge=lfs -text +*.uvi filter=lfs diff=lfs merge=lfs -text +*.uvp filter=lfs diff=lfs merge=lfs -text +*.xls filter=lfs diff=lfs merge=lfs -text +*.jpgv filter=lfs diff=lfs merge=lfs -text +*.mka filter=lfs diff=lfs merge=lfs -text +*.swf filter=lfs diff=lfs merge=lfs -text +*.uvs filter=lfs diff=lfs merge=lfs -text +*.wav filter=lfs diff=lfs merge=lfs -text +*.ecelp4800 filter=lfs diff=lfs merge=lfs -text +*.mng filter=lfs diff=lfs merge=lfs -text +*.pps filter=lfs diff=lfs merge=lfs -text +*.whl filter=lfs diff=lfs merge=lfs -text +*.arj filter=lfs diff=lfs merge=lfs -text +*.lzh filter=lfs diff=lfs merge=lfs -text +*.raw filter=lfs diff=lfs merge=lfs -text +*.rlc filter=lfs diff=lfs merge=lfs -text +*.sgi filter=lfs diff=lfs merge=lfs -text +*.tar filter=lfs diff=lfs merge=lfs -text +*.au filter=lfs diff=lfs merge=lfs -text +*.dcm filter=lfs diff=lfs merge=lfs -text +*.GIF filter=lfs diff=lfs merge=lfs -text +*.resources filter=lfs diff=lfs merge=lfs -text +*.txz filter=lfs diff=lfs merge=lfs -text +*.rar filter=lfs diff=lfs merge=lfs -text +*.sil filter=lfs diff=lfs merge=lfs -text +*.bk filter=lfs diff=lfs merge=lfs -text +*.DS_Store filter=lfs diff=lfs merge=lfs -text +*.ief filter=lfs diff=lfs merge=lfs -text +*.JPEG filter=lfs diff=lfs merge=lfs -text +*.pbm filter=lfs diff=lfs merge=lfs -text +*.png filter=lfs diff=lfs merge=lfs -text +*.sketch filter=lfs diff=lfs merge=lfs -text +*.tbz2 filter=lfs diff=lfs merge=lfs -text +*.nef filter=lfs diff=lfs merge=lfs -text +*.oga filter=lfs diff=lfs merge=lfs -text +*.zip filter=lfs diff=lfs merge=lfs -text +*.ecelp7470 filter=lfs diff=lfs merge=lfs -text +*.xlt filter=lfs diff=lfs merge=lfs -text +*.exe filter=lfs diff=lfs merge=lfs -text +*.mp4 filter=lfs diff=lfs merge=lfs -text +*.pnm filter=lfs diff=lfs merge=lfs -text +*.ttc filter=lfs diff=lfs merge=lfs -text +*.wdp filter=lfs diff=lfs merge=lfs -text +*.xbm filter=lfs diff=lfs merge=lfs -text +*.ecelp9600 filter=lfs diff=lfs merge=lfs -text +*.pot filter=lfs diff=lfs merge=lfs -text +*.wvx filter=lfs diff=lfs merge=lfs -text +*.uvu filter=lfs diff=lfs merge=lfs -text +*.asf filter=lfs diff=lfs merge=lfs -text +*.dxf filter=lfs diff=lfs merge=lfs -text +*.flv filter=lfs diff=lfs merge=lfs -text +*.mdi filter=lfs diff=lfs merge=lfs -text +*.pcx filter=lfs diff=lfs merge=lfs -text +*.tiff filter=lfs diff=lfs merge=lfs -text +*.bzip2 filter=lfs diff=lfs merge=lfs -text +*.deb filter=lfs diff=lfs merge=lfs -text +*.graffle filter=lfs diff=lfs merge=lfs -text +*.h261 filter=lfs diff=lfs merge=lfs -text +*.jpeg filter=lfs diff=lfs merge=lfs -text +*.ppm filter=lfs diff=lfs merge=lfs -text +*.tif filter=lfs diff=lfs merge=lfs -text +*.ppt filter=lfs diff=lfs merge=lfs -text +*.fbs filter=lfs diff=lfs merge=lfs -text +*.gzip filter=lfs diff=lfs merge=lfs -text +*.o filter=lfs diff=lfs merge=lfs -text +*.sub filter=lfs diff=lfs merge=lfs -text +*.z filter=lfs diff=lfs merge=lfs -text +*.alz filter=lfs diff=lfs merge=lfs -text +*.BMP filter=lfs diff=lfs merge=lfs -text +*.dotm filter=lfs diff=lfs merge=lfs -text +*.key filter=lfs diff=lfs merge=lfs -text +*.rgb filter=lfs diff=lfs merge=lfs -text +*.f4v filter=lfs diff=lfs merge=lfs -text +*.iso filter=lfs diff=lfs merge=lfs -text +*.ai filter=lfs diff=lfs merge=lfs -text +*.dtshd filter=lfs diff=lfs merge=lfs -text +*.fpx filter=lfs diff=lfs merge=lfs -text +*.shar filter=lfs diff=lfs merge=lfs -text +*.img filter=lfs diff=lfs merge=lfs -text +*.rmf filter=lfs diff=lfs merge=lfs -text +*.xz filter=lfs diff=lfs merge=lfs -text +*.eot filter=lfs diff=lfs merge=lfs -text +*.wma filter=lfs diff=lfs merge=lfs -text +*.cpio filter=lfs diff=lfs merge=lfs -text +*.cr2 filter=lfs diff=lfs merge=lfs -text +*.adp filter=lfs diff=lfs merge=lfs -text +*.mpeg filter=lfs diff=lfs merge=lfs -text +*.npx filter=lfs diff=lfs merge=lfs -text +*.pdb filter=lfs diff=lfs merge=lfs -text +*.PNG filter=lfs diff=lfs merge=lfs -text +*.xwd filter=lfs diff=lfs merge=lfs -text +*.egg filter=lfs diff=lfs merge=lfs -text +*.ppsx filter=lfs diff=lfs merge=lfs -text +*.mp4a filter=lfs diff=lfs merge=lfs -text +*.pages filter=lfs diff=lfs merge=lfs -text +*.baml filter=lfs diff=lfs merge=lfs -text +*.bin filter=lfs diff=lfs merge=lfs -text +*.class filter=lfs diff=lfs merge=lfs -text +*.h264 filter=lfs diff=lfs merge=lfs -text +*.lib filter=lfs diff=lfs merge=lfs -text +*.mmr filter=lfs diff=lfs merge=lfs -text +*.dot filter=lfs diff=lfs merge=lfs -text +*.gif filter=lfs diff=lfs merge=lfs -text +*.JPG filter=lfs diff=lfs merge=lfs -text +*.m4a filter=lfs diff=lfs merge=lfs -text +*.so filter=lfs diff=lfs merge=lfs -text +*.tgz filter=lfs diff=lfs merge=lfs -text +*.thmx filter=lfs diff=lfs merge=lfs -text +*.3ds filter=lfs diff=lfs merge=lfs -text +*.bmp filter=lfs diff=lfs merge=lfs -text +*.ogv filter=lfs diff=lfs merge=lfs -text +*.xif filter=lfs diff=lfs merge=lfs -text +*.aiff filter=lfs diff=lfs merge=lfs -text +*.dts filter=lfs diff=lfs merge=lfs -text +*.rip filter=lfs diff=lfs merge=lfs -text +*.vob filter=lfs diff=lfs merge=lfs -text +*.7z filter=lfs diff=lfs merge=lfs -text +*.fh filter=lfs diff=lfs merge=lfs -text +*.flac filter=lfs diff=lfs merge=lfs -text +*.g3 filter=lfs diff=lfs merge=lfs -text +*.jpm filter=lfs diff=lfs merge=lfs -text +*.ppsm filter=lfs diff=lfs merge=lfs -text +*.potx filter=lfs diff=lfs merge=lfs -text +*.zipx filter=lfs diff=lfs merge=lfs -text +*.dsk filter=lfs diff=lfs merge=lfs -text +*.ico filter=lfs diff=lfs merge=lfs -text +*.ktx filter=lfs diff=lfs merge=lfs -text +*.lz filter=lfs diff=lfs merge=lfs -text +*.numbers filter=lfs diff=lfs merge=lfs -text +*.3gp filter=lfs diff=lfs merge=lfs -text +*.fst filter=lfs diff=lfs merge=lfs -text +*.scpt filter=lfs diff=lfs merge=lfs -text +*.epub filter=lfs diff=lfs merge=lfs -text +*.rmvb filter=lfs diff=lfs merge=lfs -text +*.webm filter=lfs diff=lfs merge=lfs -text +*.docx filter=lfs diff=lfs merge=lfs -text +*.pgm filter=lfs diff=lfs merge=lfs -text +*.pya filter=lfs diff=lfs merge=lfs -text +*.rtf filter=lfs diff=lfs merge=lfs -text +*.smv filter=lfs diff=lfs merge=lfs -text +*.tga filter=lfs diff=lfs merge=lfs -text +*.cur filter=lfs diff=lfs merge=lfs -text +*.dwg filter=lfs diff=lfs merge=lfs -text +*.lvp filter=lfs diff=lfs merge=lfs -text +*.pyo filter=lfs diff=lfs merge=lfs -text +*.apk filter=lfs diff=lfs merge=lfs -text +*.ar filter=lfs diff=lfs merge=lfs -text +*.caf filter=lfs diff=lfs merge=lfs -text +*.doc filter=lfs diff=lfs merge=lfs -text +*.h263 filter=lfs diff=lfs merge=lfs -text +*.xlsm filter=lfs diff=lfs merge=lfs -text +*.mp3 filter=lfs diff=lfs merge=lfs -text +*.mxu filter=lfs diff=lfs merge=lfs -text +*.wax filter=lfs diff=lfs merge=lfs -text +*.gz filter=lfs diff=lfs merge=lfs -text +*.mj2 filter=lfs diff=lfs merge=lfs -text +*.otf filter=lfs diff=lfs merge=lfs -text +*.udf filter=lfs diff=lfs merge=lfs -text +*.aif filter=lfs diff=lfs merge=lfs -text +*.lzma filter=lfs diff=lfs merge=lfs -text +*.pyc filter=lfs diff=lfs merge=lfs -text +*.weba filter=lfs diff=lfs merge=lfs -text +*.webp filter=lfs diff=lfs merge=lfs -text +*.cgm filter=lfs diff=lfs merge=lfs -text +*.mkv filter=lfs diff=lfs merge=lfs -text +*.ppa filter=lfs diff=lfs merge=lfs -text +*.uvh filter=lfs diff=lfs merge=lfs -text +*.xpi filter=lfs diff=lfs merge=lfs -text +*.psd filter=lfs diff=lfs merge=lfs -text +*.xlsb filter=lfs diff=lfs merge=lfs -text +*.tbz filter=lfs diff=lfs merge=lfs -text +*.wim filter=lfs diff=lfs merge=lfs -text +*.ape filter=lfs diff=lfs merge=lfs -text +*.avi filter=lfs diff=lfs merge=lfs -text +*.dex filter=lfs diff=lfs merge=lfs -text +*.dra filter=lfs diff=lfs merge=lfs -text +*.dvb filter=lfs diff=lfs merge=lfs -text +*.jpg filter=lfs diff=lfs merge=lfs -text +*.xla filter=lfs diff=lfs merge=lfs -text +*.fvt filter=lfs diff=lfs merge=lfs -text +*.lzo filter=lfs diff=lfs merge=lfs -text +*.pea filter=lfs diff=lfs merge=lfs -text +*.ras filter=lfs diff=lfs merge=lfs -text +*.tlz filter=lfs diff=lfs merge=lfs -text +*.viv filter=lfs diff=lfs merge=lfs -text +*.winmd filter=lfs diff=lfs merge=lfs -text diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..9d06ed1 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,13 @@ +version: 2 +updates: +- package-ecosystem: nuget + directory: "/" + schedule: + interval: monthly + time: "00:00" + open-pull-requests-limit: 20 +- package-ecosystem: "github-actions" + directory: "/" + schedule: + # Check for updates to GitHub Actions every weekday + interval: "monthly" diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml new file mode 100644 index 0000000..df1b256 --- /dev/null +++ b/.github/workflows/ci-build.yml @@ -0,0 +1,83 @@ +name: Build + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +env: + configuration: Release + productNamespacePrefix: "ReactiveMarbles" + +jobs: + build: + runs-on: windows-2022 + outputs: + nbgv: ${{ steps.nbgv.outputs.SemVer2 }} + steps: + - name: Get Current Visual Studio Information + shell: bash + run: | + dotnet tool update -g dotnet-vs + echo "-- About RELEASE --" + vs where release + + - name: Update Visual Studio Latest Release + shell: bash + run: | + echo "-- Update RELEASE --" + vs update release Enterprise + vs modify release Enterprise +mobile +desktop +uwp +web + echo "-- About RELEASE Updated --" + vs where release + + - name: Checkout + uses: actions/checkout@v3.5.0 + with: + fetch-depth: 0 + lfs: true + + - name: Install .NET 6 & 7 + uses: actions/setup-dotnet@v3 + with: + dotnet-version: | + 6.0.x + 7.0.x + + - name: NBGV + id: nbgv + uses: dotnet/nbgv@master + with: + setAllVars: true + + - name: NuGet Restore + run: dotnet restore + working-directory: src + + - name: Build + run: dotnet build --configuration=${{ env.configuration }} --verbosity=minimal --no-restore + working-directory: src + + - name: Run Unit Tests and Generate Coverage + uses: glennawatson/coverlet-msbuild@v2.1 + with: + project-files: '**/*Tests*.csproj' + no-build: true + exclude-filter: '[${{env.productNamespacePrefix}}.*.Tests.*]*' + include-filter: '[${{env.productNamespacePrefix}}*]*' + output-format: cobertura + configuration: ${{ env.configuration }} + + - name: Pack + run: dotnet pack --configuration=${{ env.configuration }} --verbosity=minimal --no-restore + working-directory: src + + - name: Upload Code Coverage + uses: codecov/codecov-action@v3 + + - name: Create NuGet Artifacts + uses: actions/upload-artifact@master + with: + name: nuget + path: '**/*.nupkg' diff --git a/.github/workflows/lock.yml b/.github/workflows/lock.yml new file mode 100644 index 0000000..307b83a --- /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@v4 + 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. \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..be9814a --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,98 @@ +name: Build and Release + +on: + push: + branches: [ main ] + +env: + configuration: Release + productNamespacePrefix: "ReactiveMarbles" + +jobs: + release: + runs-on: windows-2022 + environment: + name: release + outputs: + nbgv: ${{ steps.nbgv.outputs.SemVer2 }} + steps: + - name: Get Current Visual Studio Information + shell: bash + run: | + dotnet tool update -g dotnet-vs + echo "-- About RELEASE --" + vs where release + + - name: Update Visual Studio Latest Release + shell: bash + run: | + echo "-- Update RELEASE --" + vs update release Enterprise + vs modify release Enterprise +mobile +desktop +uwp +web + echo "-- About RELEASE Updated --" + vs where release + + - name: Checkout + uses: actions/checkout@v3.5.0 + with: + fetch-depth: 0 + lfs: true + + - name: Install .NET 6 & 7 + uses: actions/setup-dotnet@v3 + with: + dotnet-version: | + 6.0.x + 7.0.x + + - name: NBGV + id: nbgv + uses: dotnet/nbgv@master + with: + setAllVars: true + + - name: NuGet Restore + run: dotnet restore + working-directory: src + + - name: Build + run: dotnet build --configuration=${{ env.configuration }} --verbosity=minimal --no-restore + working-directory: src + + - uses: nuget/setup-nuget@v1 + name: Setup NuGet + + - name: Pack + run: dotnet pack --configuration=${{ env.configuration }} --verbosity=minimal --no-restore + working-directory: src + + # Decode the base 64 encoded pfx and save the Signing_Certificate + - name: Sign NuGet packages + shell: pwsh + run: | + $pfx_cert_byte = [System.Convert]::FromBase64String("${{ secrets.SIGNING_CERTIFICATE }}") + [IO.File]::WriteAllBytes("GitHubActionsWorkflow.pfx", $pfx_cert_byte) + $secure_password = ConvertTo-SecureString ${{ secrets.SIGN_CERTIFICATE_PASSWORD }} –asplaintext –force + Import-PfxCertificate -FilePath GitHubActionsWorkflow.pfx -Password $secure_password -CertStoreLocation Cert:\CurrentUser\My + nuget sign -Timestamper http://timestamp.digicert.com -CertificateFingerprint ${{ secrets.SIGN_CERTIFICATE_HASH }} **/*.nupkg + + - name: Changelog + uses: glennawatson/ChangeLog@v1 + id: changelog + + - name: Create Release + uses: actions/create-release@v1.1.4 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token + with: + tag_name: ${{ steps.nbgv.outputs.SemVer2 }} + release_name: ${{ steps.nbgv.outputs.SemVer2 }} + body: | + ${{ steps.changelog.outputs.commitLog }} + + - name: NuGet Push + env: + NUGET_AUTH_TOKEN: ${{ secrets.NUGET_API_KEY }} + SOURCE_URL: https://api.nuget.org/v3/index.json + run: | + dotnet nuget push -s ${{ env.SOURCE_URL }} -k ${{ env.NUGET_AUTH_TOKEN }} **/*.nupkg diff --git a/images/logo.png b/images/logo.png new file mode 100644 index 0000000..70c7e75 --- /dev/null +++ b/images/logo.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:722b25de1d0f7577e122a4d96c9d96f4019f7a34283a3612ae244a68eea7fc17 +size 47204 diff --git a/src/Directory.Build.props b/src/Directory.Build.props new file mode 100644 index 0000000..4e7be29 --- /dev/null +++ b/src/Directory.Build.props @@ -0,0 +1,56 @@ + + + true + $(NoWarn);1591;1701;1702;1705;VSX1000;IDE0190 + AnyCPU + $(MSBuildProjectName.Contains('Tests')) + embedded + Chris Pulman, Glenn Watson + Copyright (c) 2021 ReactiveUI Association Inc + MIT + https://github.com/reactivemarbles/Navigation + Provides a Navigation Framework for ReactiveMarbles based projects. + logo.png + README.md + chrispulman;glennawatson + Navigation;inpc;reactive;functional + https://github.com/reactivemarbles/Navigation/releases + https://github.com/reactivemarbles/Navigation + git + true + + + true + + true + + $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb + true + true + true + $(MSBuildThisFileDirectory) + + + + true + + + + + + + + + + + + + + + + + + + + + diff --git a/src/ReactiveMarbles.Navigation.sln b/src/ReactiveMarbles.Navigation.sln new file mode 100644 index 0000000..c3408fe --- /dev/null +++ b/src/ReactiveMarbles.Navigation.sln @@ -0,0 +1,51 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.33530.505 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReactiveMarbles.ViewModel.Wpf", "ViewModel.Wpf\ReactiveMarbles.ViewModel.Wpf.csproj", "{6B5A20B7-CAA7-4CBF-B48F-6EFFE9414610}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReactiveMarbles.ViewModel.Core", "ViewModel.Core\ReactiveMarbles.ViewModel.Core.csproj", "{990C0E6D-0C09-482D-8AFA-F135EC206C43}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReactiveMarbles.ViewModel.WinForms", "ViewModel.WinForms\ReactiveMarbles.ViewModel.WinForms.csproj", "{CD830D09-4558-403B-9504-C0CFD90FDC3B}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionConfig", "SolutionConfig", "{B9D5E36A-C2F2-4D70-B5D0-797574468968}" + ProjectSection(SolutionItems) = preProject + ..\.editorconfig = ..\.editorconfig + ..\.gitattributes = ..\.gitattributes + ..\.gitignore = ..\.gitignore + ..\.github\workflows\ci-build.yml = ..\.github\workflows\ci-build.yml + Directory.Build.props = Directory.Build.props + ..\LICENSE = ..\LICENSE + ..\README.md = ..\README.md + ..\.github\workflows\release.yml = ..\.github\workflows\release.yml + stylecop.json = stylecop.json + ..\version.json = ..\version.json + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6B5A20B7-CAA7-4CBF-B48F-6EFFE9414610}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6B5A20B7-CAA7-4CBF-B48F-6EFFE9414610}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6B5A20B7-CAA7-4CBF-B48F-6EFFE9414610}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6B5A20B7-CAA7-4CBF-B48F-6EFFE9414610}.Release|Any CPU.Build.0 = Release|Any CPU + {990C0E6D-0C09-482D-8AFA-F135EC206C43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {990C0E6D-0C09-482D-8AFA-F135EC206C43}.Debug|Any CPU.Build.0 = Debug|Any CPU + {990C0E6D-0C09-482D-8AFA-F135EC206C43}.Release|Any CPU.ActiveCfg = Release|Any CPU + {990C0E6D-0C09-482D-8AFA-F135EC206C43}.Release|Any CPU.Build.0 = Release|Any CPU + {CD830D09-4558-403B-9504-C0CFD90FDC3B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CD830D09-4558-403B-9504-C0CFD90FDC3B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CD830D09-4558-403B-9504-C0CFD90FDC3B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CD830D09-4558-403B-9504-C0CFD90FDC3B}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {489B52FF-BC1B-435B-8412-301C8A46D473} + EndGlobalSection +EndGlobal diff --git a/src/ViewModel.Core/IActivatableView.cs b/src/ViewModel.Core/IActivatableView.cs new file mode 100644 index 0000000..7de7544 --- /dev/null +++ b/src/ViewModel.Core/IActivatableView.cs @@ -0,0 +1,13 @@ +// Copyright (c) 2019-2023 ReactiveUI Association Incorporated. All rights reserved. +// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +namespace ReactiveMarbles.ViewModel.Core +{ + /// + /// IActivatableView. + /// + public interface IActivatableView + { + } +} diff --git a/src/ViewModel.Core/IAmViewFor.cs b/src/ViewModel.Core/IAmViewFor.cs new file mode 100644 index 0000000..ae02b32 --- /dev/null +++ b/src/ViewModel.Core/IAmViewFor.cs @@ -0,0 +1,17 @@ +// Copyright (c) 2019-2023 ReactiveUI Association Incorporated. All rights reserved. +// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +namespace ReactiveMarbles.ViewModel.Core; + +/// +/// IAmViewFor. +/// +/// +public interface IAmViewFor : IActivatableView +{ + /// + /// Gets or sets the View Model associated with the View. + /// + object? ViewModel { get; set; } +} diff --git a/src/ViewModel.Core/IAmViewFor{T}.cs b/src/ViewModel.Core/IAmViewFor{T}.cs new file mode 100644 index 0000000..79e8e40 --- /dev/null +++ b/src/ViewModel.Core/IAmViewFor{T}.cs @@ -0,0 +1,20 @@ +// Copyright (c) 2019-2023 ReactiveUI Association Incorporated. All rights reserved. +// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +namespace ReactiveMarbles.ViewModel.Core; + +/// +/// IAmViewFor. +/// +/// The type of ViewModel. +/// +public interface IAmViewFor : IAmViewFor +where T : class +{ + /// + /// Gets or sets the ViewModel corresponding to this specific View. This should be + /// a DependencyProperty if you're using XAML. + /// + new T? ViewModel { get; set; } +} diff --git a/src/ViewModel.Core/IHostScreen.cs b/src/ViewModel.Core/IHostScreen.cs new file mode 100644 index 0000000..6e0e2e8 --- /dev/null +++ b/src/ViewModel.Core/IHostScreen.cs @@ -0,0 +1,10 @@ +// Copyright (c) 2019-2023 ReactiveUI Association Incorporated. All rights reserved. +// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +namespace ReactiveMarbles.ViewModel.Core +{ + public interface IHostScreen + { + } +} \ No newline at end of file diff --git a/src/ViewModel.Core/INotifiyRoutableViewModel.cs b/src/ViewModel.Core/INotifiyRoutableViewModel.cs new file mode 100644 index 0000000..0a40572 --- /dev/null +++ b/src/ViewModel.Core/INotifiyRoutableViewModel.cs @@ -0,0 +1,47 @@ +// Copyright (c) 2019-2023 ReactiveUI Association Incorporated. All rights reserved. +// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using System.Reactive.Disposables; + +namespace ReactiveMarbles.ViewModel.Core; + +/// +/// INotifiy Routable ViewModel. +/// +/// +public interface INotifiyRoutableViewModel : Mvvm.IRxObject, IUseHostedNavigation +{ + /// + /// Gets the name. + /// + /// + /// The name. + /// + string? Name { get; } + + /// + /// Raises the event. + /// + /// + /// The instance containing the event data. + /// + void WhenNavigatedFrom(IViewModelNavigationEventArgs e); + + /// + /// Raises the event. + /// + /// + /// The instance containing the event data. + /// + /// The disposables. + void WhenNavigatedTo(IViewModelNavigationEventArgs e, CompositeDisposable disposables); + + /// + /// Raises the event. + /// + /// + /// The instance containing the event data. + /// + void WhenNavigating(IViewModelNavigatingEventArgs e); +} diff --git a/src/ViewModel.Core/IRxObject.cs b/src/ViewModel.Core/IRxObject.cs new file mode 100644 index 0000000..79fc5c4 --- /dev/null +++ b/src/ViewModel.Core/IRxObject.cs @@ -0,0 +1,15 @@ +// Copyright (c) 2019-2023 ReactiveUI Association Incorporated. All rights reserved. +// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using System.Reactive.Disposables; + +namespace ReactiveMarbles.ViewModel.Core; + +/// +/// interface for RxBase. +/// +/// +public interface IRxObject : INotifiyRoutableViewModel, ICancelable, IAmBuilt +{ +} diff --git a/src/ViewModel.Core/IViewModelRoutedViewHost.cs b/src/ViewModel.Core/IViewModelRoutedViewHost.cs new file mode 100644 index 0000000..a733242 --- /dev/null +++ b/src/ViewModel.Core/IViewModelRoutedViewHost.cs @@ -0,0 +1,124 @@ +// Copyright (c) 2019-2023 ReactiveUI Association Incorporated. All rights reserved. +// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using System.Collections.ObjectModel; + +namespace ReactiveMarbles.ViewModel.Core; + +/// +/// IViewModel Routed ViewHost. +/// +public interface IViewModelRoutedViewHost : IActivatableView +{ + /// + /// Gets the navigation stack. + /// + /// + /// The navigation stack. + /// + ObservableCollection NavigationStack { get; } + + /// + /// Gets the current view model. + /// + /// + /// The current view model. + /// + IObservable CurrentViewModel { get; } + + /// + /// Gets or sets a value indicating whether [navigate back is enabled]. + /// + /// + /// true if [navigate back is enabled]; otherwise, false. + /// + bool CanNavigateBack { get; set; } + + /// + /// Gets the can navigate back observable. + /// + /// + /// The can navigate back observable. + /// + IObservable CanNavigateBackObservable { get; } + + /// + /// Gets or sets a value indicating whether [navigate back is enabled]. + /// + /// + /// true if [navigate back is enabled]; otherwise, false. + /// + bool NavigateBackIsEnabled { get; set; } + + /// + /// Gets or sets the name of the host. + /// + /// + /// The name of the host. + /// + string Name { get; set; } + + /// + /// Gets a value indicating whether [requires setup]. + /// + /// + /// true if [requires setup]; otherwise, false. + /// + bool RequiresSetup { get; } + + /// + /// Clears the history. + /// + void ClearHistory(); + + /// + /// Setups this instance. + /// + void Setup(); + + /// + /// Navigates the specified contract. + /// + /// The Type. + /// The contract. + /// The parameter. + void Navigate(string? contract = null, object? parameter = null) + where T : class, IRxObject; + + /// + /// Navigates the specified contract. + /// + /// The view model. + /// The contract. + /// The parameter. + void Navigate(IRxObject viewModel, string? contract = null, object? parameter = null); + + /// + /// Navigates the and reset. + /// + /// The Type. + /// The contract. + /// The parameter. + void NavigateAndReset(string? contract = null, object? parameter = null) + where T : class, IRxObject; + + /// + /// Navigates the and reset. + /// + /// The view model. + /// The contract. + /// The parameter. + void NavigateAndReset(IRxObject viewModel, string? contract = null, object? parameter = null); + + /// + /// Navigates the back. + /// + /// The parameter. + void NavigateBack(object? parameter = null); + + /// + /// Refreshes this instance. + /// + void Refresh(); +} diff --git a/src/ViewModel.Core/MagicInterfaces/IAmBuilt.cs b/src/ViewModel.Core/MagicInterfaces/IAmBuilt.cs new file mode 100644 index 0000000..f579c82 --- /dev/null +++ b/src/ViewModel.Core/MagicInterfaces/IAmBuilt.cs @@ -0,0 +1,12 @@ +// Copyright (c) 2019-2023 ReactiveUI Association Incorporated. All rights reserved. +// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +namespace ReactiveMarbles.ViewModel.Core; + +/// +/// IAmBuilt. +/// +public interface IAmBuilt +{ +} diff --git a/src/ViewModel.Core/MagicInterfaces/INotifiyNavigation.cs b/src/ViewModel.Core/MagicInterfaces/INotifiyNavigation.cs new file mode 100644 index 0000000..a8cc5b0 --- /dev/null +++ b/src/ViewModel.Core/MagicInterfaces/INotifiyNavigation.cs @@ -0,0 +1,47 @@ +// Copyright (c) 2019-2023 ReactiveUI Association Incorporated. All rights reserved. +// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using System.Reactive.Disposables; + +namespace ReactiveMarbles.ViewModel.Core; + +/// +/// INotifiy Navigation. +/// +/// +/// +public interface INotifiyNavigation : IActivatableView, ICancelable +{ + /// + /// Gets or sets a value indicating whether [i setup navigated to]. + /// + /// + /// true if [i setup navigated to]; otherwise, false. + /// + bool ISetupNavigatedTo { get; set; } + + /// + /// Gets or sets a value indicating whether [i setup navigated from]. + /// + /// + /// true if [i setup navigated from]; otherwise, false. + /// + bool ISetupNavigatedFrom { get; set; } + + /// + /// Gets or sets a value indicating whether [i setup navigating]. + /// + /// + /// true if [i setup navigating]; otherwise, false. + /// + bool ISetupNavigating { get; set; } + + /// + /// Gets the clean up. + /// + /// + /// The clean up. + /// + CompositeDisposable CleanUp { get; } +} diff --git a/src/ViewModel.Core/MagicInterfaces/ISetNavigation.cs b/src/ViewModel.Core/MagicInterfaces/ISetNavigation.cs new file mode 100644 index 0000000..8505e8a --- /dev/null +++ b/src/ViewModel.Core/MagicInterfaces/ISetNavigation.cs @@ -0,0 +1,19 @@ +// Copyright (c) 2019-2023 ReactiveUI Association Incorporated. All rights reserved. +// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +namespace ReactiveMarbles.ViewModel.Core; + +/// +/// Enables setting of ViewModelRoutedViewHost. +/// +public interface ISetNavigation +{ + /// + /// Gets the name. + /// + /// + /// The name. + /// + string Name { get; } +} diff --git a/src/ViewModel.Core/MagicInterfaces/IUseHostedNavigation.cs b/src/ViewModel.Core/MagicInterfaces/IUseHostedNavigation.cs new file mode 100644 index 0000000..b84c762 --- /dev/null +++ b/src/ViewModel.Core/MagicInterfaces/IUseHostedNavigation.cs @@ -0,0 +1,12 @@ +// Copyright (c) 2019-2023 ReactiveUI Association Incorporated. All rights reserved. +// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +namespace ReactiveMarbles.ViewModel.Core; + +/// +/// Enables Navigation commands specified by host name. +/// +public interface IUseHostedNavigation +{ +} diff --git a/src/ViewModel.Core/MagicInterfaces/IUseNavigation.cs b/src/ViewModel.Core/MagicInterfaces/IUseNavigation.cs new file mode 100644 index 0000000..52adf2e --- /dev/null +++ b/src/ViewModel.Core/MagicInterfaces/IUseNavigation.cs @@ -0,0 +1,19 @@ +// Copyright (c) 2019-2023 ReactiveUI Association Incorporated. All rights reserved. +// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +namespace ReactiveMarbles.ViewModel.Core; + +/// +/// I Use Navigation. +/// +public interface IUseNavigation +{ + /// + /// Gets the name. + /// + /// + /// The name. + /// + string Name { get; } +} diff --git a/src/ViewModel.Core/NavigationEvents/IViewModelNavigatingEventArgs.cs b/src/ViewModel.Core/NavigationEvents/IViewModelNavigatingEventArgs.cs new file mode 100644 index 0000000..06972b4 --- /dev/null +++ b/src/ViewModel.Core/NavigationEvents/IViewModelNavigatingEventArgs.cs @@ -0,0 +1,19 @@ +// Copyright (c) 2019-2023 ReactiveUI Association Incorporated. All rights reserved. +// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +namespace ReactiveMarbles.ViewModel.Core; + +/// +/// IView Model Navigating EventArgs. +/// +public interface IViewModelNavigatingEventArgs : IViewModelNavigationEventArgs +{ + /// + /// Gets or sets a value indicating whether this is cancel. + /// + /// + /// true if cancel; otherwise, false. + /// + bool Cancel { get; set; } +} diff --git a/src/ViewModel.Core/NavigationEvents/IViewModelNavigationBaseEventArgs.cs b/src/ViewModel.Core/NavigationEvents/IViewModelNavigationBaseEventArgs.cs new file mode 100644 index 0000000..9e7e166 --- /dev/null +++ b/src/ViewModel.Core/NavigationEvents/IViewModelNavigationBaseEventArgs.cs @@ -0,0 +1,35 @@ +// Copyright (c) 2019-2023 ReactiveUI Association Incorporated. All rights reserved. +// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +namespace ReactiveMarbles.ViewModel.Core; + +/// +/// IView Model Navigation Base Event Args. +/// +public interface IViewModelNavigationBaseEventArgs +{ + /// + /// Gets from. + /// + /// + /// From. + /// + IRxObject? From { get; } + + /// + /// Gets the navigation parameter. + /// + /// + /// The navigation parameter. + /// + object? NavigationParameter { get; } + + /// + /// Gets to. + /// + /// + /// To. + /// + IRxObject? To { get; } +} diff --git a/src/ViewModel.Core/NavigationEvents/IViewModelNavigationEventArgs.cs b/src/ViewModel.Core/NavigationEvents/IViewModelNavigationEventArgs.cs new file mode 100644 index 0000000..a3a87fe --- /dev/null +++ b/src/ViewModel.Core/NavigationEvents/IViewModelNavigationEventArgs.cs @@ -0,0 +1,35 @@ +// Copyright (c) 2019-2023 ReactiveUI Association Incorporated. All rights reserved. +// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +namespace ReactiveMarbles.ViewModel.Core; + +/// +/// I View Model Navigation EventArgs. +/// +public interface IViewModelNavigationEventArgs : IViewModelNavigationBaseEventArgs +{ + /// + /// Gets or sets the name of the host. + /// + /// + /// The name of the host. + /// + string HostName { get; set; } + + /// + /// Gets the type of the navigation. + /// + /// + /// The type of the navigation. + /// + NavigationType NavigationType { get; } + + /// + /// Gets or sets the view. + /// + /// + /// The view. + /// + IAmViewFor? View { get; set; } +} diff --git a/src/ViewModel.Core/NavigationEvents/ViewModelNavigatingEventArgs.cs b/src/ViewModel.Core/NavigationEvents/ViewModelNavigatingEventArgs.cs new file mode 100644 index 0000000..d1aa653 --- /dev/null +++ b/src/ViewModel.Core/NavigationEvents/ViewModelNavigatingEventArgs.cs @@ -0,0 +1,36 @@ +// Copyright (c) 2019-2023 ReactiveUI Association Incorporated. All rights reserved. +// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using System.Runtime.Serialization; + +namespace ReactiveMarbles.ViewModel.Core; + +/// +/// View Model Navigating Event Args. +/// +[DataContract] +public class ViewModelNavigatingEventArgs : ViewModelNavigationEventArgs, IViewModelNavigatingEventArgs +{ + /// + /// Initializes a new instance of the class. + /// + /// From. + /// To. + /// Type of the nav. + /// The view. + /// The hostName. + /// The parmeter. + public ViewModelNavigatingEventArgs(IRxObject? from, IRxObject? to, NavigationType navType, IViewFor? view, string hostName, object? parmeter = null) + : base(from, to, navType, view, hostName, parmeter) + { + } + + /// + /// Gets or sets a value indicating whether this + /// is canceled. + /// + /// true if cancel; otherwise, false. + [DataMember] + public bool Cancel { get; set; } +} diff --git a/src/ViewModel.Core/NavigationEvents/ViewModelNavigationBaseEventArgs.cs b/src/ViewModel.Core/NavigationEvents/ViewModelNavigationBaseEventArgs.cs new file mode 100644 index 0000000..3946074 --- /dev/null +++ b/src/ViewModel.Core/NavigationEvents/ViewModelNavigationBaseEventArgs.cs @@ -0,0 +1,37 @@ +// Copyright (c) 2019-2023 ReactiveUI Association Incorporated. All rights reserved. +// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using System.Runtime.Serialization; + +namespace ReactiveMarbles.ViewModel.Core; + +/// +/// View Model Navigation Base Event Args. +/// +/// +[DataContract] +public abstract class ViewModelNavigationBaseEventArgs + : EventArgs, IViewModelNavigationBaseEventArgs +{ + /// + /// Gets or sets where is Navigating from. + /// + /// From. + [DataMember] + public IRxObject? From { get; protected set; } + + /// + /// Gets or sets the navigation parameter. + /// + /// The navigation parameter. + [DataMember] + public object? NavigationParameter { get; protected set; } + + /// + /// Gets or sets where is Navigating to. + /// + /// To. + [DataMember] + public IRxObject? To { get; protected set; } +} diff --git a/src/ViewModel.Core/NavigationEvents/ViewModelNavigationEventArgs.cs b/src/ViewModel.Core/NavigationEvents/ViewModelNavigationEventArgs.cs new file mode 100644 index 0000000..0e20276 --- /dev/null +++ b/src/ViewModel.Core/NavigationEvents/ViewModelNavigationEventArgs.cs @@ -0,0 +1,54 @@ +// Copyright (c) 2019-2023 ReactiveUI Association Incorporated. All rights reserved. +// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using System.Runtime.Serialization; + +namespace ReactiveMarbles.ViewModel.Core; + +/// +/// View Model Navigation EventArgs. +/// +[DataContract] +public class ViewModelNavigationEventArgs : ViewModelNavigationBaseEventArgs, IViewModelNavigationEventArgs +{ + /// Initializes a new instance of the class. + /// From. + /// To. + /// Type of the nav. + /// The view. + /// The Hostname. + /// The parmeter. + public ViewModelNavigationEventArgs(IRxObject? from, IRxObject? to, NavigationType navType, IViewFor? view, string hostName, object? parmeter = null) + { + From = from; + To = to; + View = view; + NavigationType = navType; + NavigationParameter = parmeter; + HostName = hostName; + } + + /// + /// Gets or sets the name of the host. + /// + /// + /// The name of the host. + /// + [DataMember] + public string HostName { get; set; } + + /// + /// Gets or sets the type of the navigation. + /// + /// The type of the navigation. + [DataMember] + public NavigationType NavigationType { get; protected set; } + + /// + /// Gets or sets the view. + /// + /// The view. + [DataMember] + public IViewFor? View { get; set; } +} diff --git a/src/ViewModel.Core/NavigationType.cs b/src/ViewModel.Core/NavigationType.cs new file mode 100644 index 0000000..5841ac3 --- /dev/null +++ b/src/ViewModel.Core/NavigationType.cs @@ -0,0 +1,26 @@ +// Copyright (c) 2019-2023 ReactiveUI Association Incorporated. All rights reserved. +// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +namespace ReactiveMarbles.ViewModel.Core; + +/// +/// Identifies the types of navigation that are supported. +/// +public enum NavigationType +{ + /// + /// Navigating to new content. + /// + New = 0, + + /// + /// Navigating back in the back navigation history. + /// + Back = 1, + + /// + /// Reloading the current content. + /// + Refresh = 2 +} diff --git a/src/ViewModel.Core/ReactiveMarbles.ViewModel.Core.csproj b/src/ViewModel.Core/ReactiveMarbles.ViewModel.Core.csproj new file mode 100644 index 0000000..6a540a1 --- /dev/null +++ b/src/ViewModel.Core/ReactiveMarbles.ViewModel.Core.csproj @@ -0,0 +1,14 @@ + + + + net7.0 + enable + enable + false + + + + + + + diff --git a/src/ViewModel.Core/RxObject.cs b/src/ViewModel.Core/RxObject.cs new file mode 100644 index 0000000..7f335b9 --- /dev/null +++ b/src/ViewModel.Core/RxObject.cs @@ -0,0 +1,98 @@ +// Copyright (c) 2019-2023 ReactiveUI Association Incorporated. All rights reserved. +// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using System.Reactive.Disposables; + +namespace ReactiveMarbles.ViewModel.Core; + +/// +/// Rx Object. +/// +/// +/// +public abstract class RxObject : Mvvm.RxObject, IRxObject +{ + /// + /// Initializes a new instance of the class. + /// + protected RxObject() + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The host screen. + protected RxObject(IHostScreen? hostScreen = null) => HostScreen = hostScreen!; + + /// + /// Gets the URL path segment. + /// + /// + /// The URL path segment. + /// + public string? Name => GetType().FullName; + + /// + /// Gets or sets the host screen. + /// + /// + /// The host screen. + /// + public IHostScreen? HostScreen { get; protected set; } + + /// + /// Gets a value indicating whether this instance is disposed. + /// + /// true if this instance is disposed; otherwise, false. + public bool IsDisposed => Disposables.IsDisposed; + + /// + /// Gets the disposables. + /// + /// + /// The disposables. + /// + protected CompositeDisposable Disposables { get; } = new CompositeDisposable(); + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting + /// unmanaged resources. + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// + public virtual void WhenNavigatedFrom(IViewModelNavigationEventArgs e) + { + } + + /// + public virtual void WhenNavigatedTo(IViewModelNavigationEventArgs e, CompositeDisposable disposables) + { + } + + /// + public virtual void WhenNavigating(IViewModelNavigatingEventArgs e) + { + } + + /// + /// Releases unmanaged and - optionally - managed resources. + /// + /// + /// true to release both managed and unmanaged resources; false to release only + /// unmanaged resources. + /// + protected virtual void Dispose(bool disposing) + { + if (Disposables?.IsDisposed == false && disposing) + { + Disposables?.Dispose(); + } + } +} diff --git a/src/ViewModel.Core/RxObjectMixins.cs b/src/ViewModel.Core/RxObjectMixins.cs new file mode 100644 index 0000000..8d4f864 --- /dev/null +++ b/src/ViewModel.Core/RxObjectMixins.cs @@ -0,0 +1,32 @@ +// Copyright (c) 2019-2023 ReactiveUI Association Incorporated. All rights reserved. +// ReactiveUI Association Incorporated 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 System.Reactive.Subjects; +using ReactiveMarbles.Locator; + +namespace ReactiveMarbles.ViewModel.Core; + +/// +/// RxObjectMixins. +/// +public static class RxObjectMixins +{ + private static readonly ReplaySubject _buildCompleteSubject = new(1); + + /// + /// Sets the IOC container build complete, Execute this once after completion of IOC registrations. + /// + /// The dummy. + public static void SetupComplete(this IEditServices dummy) => _buildCompleteSubject.OnNext(Unit.Default); + + /// + /// Gets the build complete. + /// + /// The dummy. + /// The action. + /// The build complete. + public static void BuildComplete(this IAmBuilt dummy, Action action) => _buildCompleteSubject.Subscribe(_ => action()); +} diff --git a/src/ViewModel.Core/ViewModelRoutedViewHostMixins.cs b/src/ViewModel.Core/ViewModelRoutedViewHostMixins.cs new file mode 100644 index 0000000..c93bc31 --- /dev/null +++ b/src/ViewModel.Core/ViewModelRoutedViewHostMixins.cs @@ -0,0 +1,568 @@ +// Copyright (c) 2019-2023 ReactiveUI Association Incorporated. All rights reserved. +// ReactiveUI Association Incorporated 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 System.Reactive.Subjects; +using System.Runtime.CompilerServices; +using ReactiveMarbles.Extensions; + +[assembly: InternalsVisibleTo("ReactiveMarbles.ViewModel.Wpf")] +[assembly: InternalsVisibleTo("ReactiveMarbles.ViewModel.WinForms")] +[assembly: InternalsVisibleTo("ReactiveMarbles.ViewModel.XamForms")] +[assembly: InternalsVisibleTo("ReactiveMarbles.ViewModel.MAUI")] +[assembly: InternalsVisibleTo("ReactiveMarbles.ViewModel.WinUI")] +[assembly: InternalsVisibleTo("ReactiveMarbles.ViewModel.Avalonia")] + +namespace ReactiveMarbles.ViewModel.Core; + +/// +/// View Model Routed View Host Mixins. +/// +public static class ViewModelRoutedViewHostMixins +{ + internal static Subject ASetupCompleted { get; } = new(); + + internal static Dictionary CurrentViewDisposable { get; } = new(); + + internal static Dictionary NavigationHost { get; } = new(); + + internal static Dictionary> ResultNavigating { get; } = new(); + + internal static Subject SetWhenNavigated { get; } = new(); + + internal static Subject SetWhenNavigating { get; } = new(); + + internal static Dictionary> WhenSetupSubjects { get; } = new(); + + /// + /// Determines whether this instance [can navigate back] the specified this. + /// + /// The this. + /// A bool. + public static IObservable CanNavigateBack(this IUseNavigation @this) + { + if (@this == null) + { + throw new ArgumentNullException(nameof(@this)); + } + + return Observable.Create(obs => + { + var dis = new CompositeDisposable(); + @this.WhenSetup().Subscribe(_ => + { + if (NavigationHost.Count > 0 && @this.Name != null) + { + if (@this.Name.Length == 0) + { + NavigationHost.First().Value.CanNavigateBackObservable + .Subscribe(x => obs.OnNext(x)) + .DisposeWith(dis); + } + + if (NavigationHost.TryGetValue(@this.Name, out var value)) + { + value.CanNavigateBackObservable + .Subscribe(x => obs.OnNext(x)) + .DisposeWith(dis); + } + } + }); + + obs.OnNext(false); + + return dis; + }); + } + + /// + /// Determines whether this instance [can navigate back] the specified host name. + /// + /// The navigation host. + /// Name of the host. + /// + /// A bool. + /// + public static IObservable CanNavigateBack(this IUseHostedNavigation @this, string hostName = "") + { + if (@this == null) + { + throw new ArgumentNullException(nameof(@this)); + } + + return Observable.Create(obs => + { + var dis = new CompositeDisposable(); + @this.WhenSetup(hostName).Subscribe(_ => + { + if (NavigationHost.Count > 0 && hostName != null) + { + if (hostName.Length == 0) + { + NavigationHost.First().Value.CanNavigateBackObservable + .Subscribe(x => obs.OnNext(x)) + .DisposeWith(dis); + } + + if (NavigationHost.TryGetValue(hostName, out var value)) + { + value.CanNavigateBackObservable + .Subscribe(x => obs.OnNext(x)) + .DisposeWith(dis); + } + } + }).DisposeWith(dis); + + obs.OnNext(false); + + return dis; + }); + } + + /// + /// Clears the history. + /// + /// The dummy. + public static void ClearHistory(this IUseNavigation @this) + { + if (@this == null) + { + throw new ArgumentNullException(nameof(@this)); + } + + if (NavigationHost.Count == 0) + { + throw new InvalidOperationException("No navigation host registered, please ensure that the NavigationShell has a Name."); + } + + if (NavigationHost.Count > 0 && @this.Name != null) + { + switch (@this.Name.Length) + { + case 0: + NavigationHost.First().Value.ClearHistory(); + break; + default: + NavigationHost[@this.Name].ClearHistory(); + break; + } + } + } + + /// + /// Clears the history. + /// + /// The dummy. + /// Name of the host. + public static void ClearHistory(this IUseHostedNavigation dummy, string hostName = "") + { + if (NavigationHost.Count == 0) + { + throw new InvalidOperationException("No navigation host registered, please ensure that the NavigationShell has a Name."); + } + + if (NavigationHost.Count > 0 && hostName != null) + { + switch (hostName.Length) + { + case 0: + NavigationHost.First().Value.ClearHistory(); + break; + default: + NavigationHost[hostName].ClearHistory(); + break; + } + } + } + + /// + /// Navigates the back. + /// + /// The this. + /// The parameter. + public static void NavigateBack(this IUseNavigation @this, object? parameter = null) + { + if (@this == null) + { + throw new ArgumentNullException(nameof(@this)); + } + + if (NavigationHost.Count == 0) + { + throw new InvalidOperationException("No navigation host registered, please ensure that the NavigationShell has a Name."); + } + + if (NavigationHost.Count > 0 && @this.Name != null) + { + switch (@this.Name.Length) + { + case 0: + NavigationHost.First().Value.NavigateBack(parameter); + break; + default: + if (NavigationHost.TryGetValue(@this.Name, out var value)) + { + value.NavigateBack(parameter); + } + + break; + } + } + } + + /// + /// Navigates backwards. + /// + /// The dummy. + /// Name of the host. + /// The parameter. + public static void NavigateBack(this IUseHostedNavigation dummy, string hostName = "", object? parameter = null) + { + if (NavigationHost.Count == 0) + { + throw new InvalidOperationException("No navigation host registered, please ensure that the NavigationShell has a Name."); + } + + if (NavigationHost.Count > 0 && hostName != null) + { + switch (hostName.Length) + { + case 0: + NavigationHost.First().Value.NavigateBack(parameter); + break; + default: + if (NavigationHost.TryGetValue(hostName, out var value)) + { + value.NavigateBack(parameter); + } + + break; + } + } + } + + /// + /// Navigates the specified contract. + /// + /// The Type. + /// The this. + /// The contract. + /// The parameter. + public static void NavigateToView(this IUseNavigation @this, string? contract = null, object? parameter = null) + where T : class, IRxObject + { + if (@this == null) + { + throw new ArgumentNullException(nameof(@this)); + } + + if (NavigationHost.Count == 0) + { + throw new InvalidOperationException("No navigation host registered, please ensure that the NavigationShell has a Name."); + } + + if (NavigationHost.Count > 0 && @this.Name != null) + { + switch (@this.Name.Length) + { + case 0: + NavigationHost.First().Value.Navigate(contract, parameter); + break; + default: + NavigationHost[@this.Name].Navigate(contract, parameter); + break; + } + } + } + + /// + /// Navigates to view. + /// + /// The Type. + /// The dummy. + /// Name of the host. + /// The contract. + /// The parameter. + public static void NavigateToView(this IUseHostedNavigation dummy, string? hostName = "", string? contract = null, object? parameter = null) + where T : class, IRxObject + { + if (NavigationHost.Count == 0) + { + throw new InvalidOperationException("No navigation host registered, please ensure that the NavigationShell has a Name."); + } + + if (NavigationHost.Count > 0 && hostName != null) + { + switch (hostName.Length) + { + case 0: + NavigationHost.First().Value.Navigate(contract, parameter); + break; + default: + if (NavigationHost.TryGetValue(hostName, out var value)) + { + value.Navigate(contract, parameter); + } + + break; + } + } + } + + /// + /// Navigates the and reset. + /// + /// The Type. + /// The this. + /// The contract. + /// The parameter. + public static void NavigateToViewAndClearHistory(this IUseNavigation @this, string? contract = null, object? parameter = null) + where T : class, IRxObject + { + if (@this == null) + { + throw new ArgumentNullException(nameof(@this)); + } + + if (NavigationHost.Count == 0) + { + throw new InvalidOperationException("No navigation host registered, please ensure that the NavigationShell has a Name."); + } + + if (NavigationHost.Count > 0 && @this.Name != null) + { + switch (@this.Name.Length) + { + case 0: + NavigationHost.First().Value.NavigateAndReset(contract, parameter); + break; + default: + if (NavigationHost.TryGetValue(@this.Name, out var value)) + { + value.NavigateAndReset(contract, parameter); + } + + break; + } + } + } + + /// + /// Navigates to view and clear history. + /// + /// The Type. + /// The dummy. + /// Name of the host. + /// The contract. + /// The parameter. + public static void NavigateToViewAndClearHistory(this IUseHostedNavigation dummy, string hostName = "", string? contract = null, object? parameter = null) + where T : class, IRxObject + { + if (NavigationHost.Count == 0) + { + throw new InvalidOperationException("No navigation host registered, please ensure that the NavigationShell has a Name."); + } + + if (NavigationHost.Count > 0 && hostName != null) + { + switch (hostName.Length) + { + case 0: + NavigationHost.First().Value.NavigateAndReset(contract, parameter); + break; + default: + if (NavigationHost.TryGetValue(hostName, out var value)) + { + value.NavigateAndReset(contract, parameter); + } + + break; + } + } + } + + /// + /// Sets the main navigation host. + /// + /// The dummy. + /// The view host. + public static void SetMainNavigationHost(this ISetNavigation @this, IViewModelRoutedViewHost viewHost) + { + if (@this == null) + { + throw new ArgumentNullException(nameof(@this)); + } + + if (viewHost == null) + { + throw new ArgumentNullException(nameof(viewHost)); + } + + if (NavigationHost.ContainsKey(@this.Name)) + { + return; + } + + WhenSetupSubjects.Add(@this.Name, new(1)); + NavigationHost.Add(@this.Name, viewHost); + CurrentViewDisposable.Add(@this.Name, new CompositeDisposable()); + ResultNavigating.Add(@this.Name, new Subject()); + + if (viewHost.RequiresSetup) + { + viewHost.Setup(); + } + + ASetupCompleted.OnNext(Unit.Default); + WhenSetupSubjects[@this.Name].OnNext(true); + } + + /// + /// Whens the navigated from. + /// + /// The this. + /// The e. + public static void WhenNavigatedFrom(this INotifiyNavigation @this, Action e) + { + if (@this == null) + { + throw new ArgumentNullException(nameof(@this)); + } + + @this.ISetupNavigatedFrom = true; + var vm = (@this as IAmViewFor)?.ViewModel as INotifiyRoutableViewModel; + SetWhenNavigated.Where(x => x.From != null && x.From.Name == vm?.Name).Subscribe(ea => + { + e(ea); + ea.From?.WhenNavigatedFrom(ea); + }).DisposeWith(@this.CleanUp); + } + + /// + /// Whens the navigated to. + /// + /// The this. + /// The e. + public static void WhenNavigatedTo(this INotifiyNavigation @this, Action e) + { + if (@this == null) + { + throw new ArgumentNullException(nameof(@this)); + } + + @this.ISetupNavigatedTo = true; + var vm = (@this as IAmViewFor)?.ViewModel as INotifiyRoutableViewModel; + SetWhenNavigated.Where(x => x?.To?.Name == vm?.Name).Subscribe(ea => + { + if (ea.NavigationType == NavigationType.New) + { + CurrentViewDisposable[ea.HostName]?.Dispose(); + CurrentViewDisposable[ea.HostName] = new CompositeDisposable(); + } + + e(ea, CurrentViewDisposable[ea.HostName]); + ea?.To?.WhenNavigatedTo(ea, CurrentViewDisposable[ea.HostName]); + }).DisposeWith(@this.CleanUp); + } + + /// + /// Called when [navigating]. + /// + /// The this. + /// + /// The instance containing the event data. + /// + public static void WhenNavigating(this INotifiyNavigation @this, Func e) + { + if (@this == null) + { + throw new ArgumentNullException(nameof(@this)); + } + + @this.ISetupNavigating = true; + var vm = (@this as IAmViewFor)?.ViewModel as INotifiyRoutableViewModel; + SetWhenNavigating.Where(x => x?.From == null || x.From.Name == vm?.Name).Subscribe(ea => + { + if (ea != null) + { + if (ea.From != null) + { + e(ea); + } + + ea.From?.WhenNavigating(ea); + + ResultNavigating[ea.HostName].OnNext(ea); + } + }).DisposeWith(@this.CleanUp); + } + + /// + /// Whens the activated. + /// + /// The this. + /// A Bool. + public static IObservable WhenSetup(this IUseNavigation @this) => + Observable.Create(obs => + { + var dis = new CompositeDisposable(); + ASetupCompleted.Subscribe(_ => + { + if (WhenSetupSubjects.Count > 0 && @this.Name != null) + { + switch (@this.Name.Length) + { + case 0: + { + WhenSetupSubjects.First().Value.Where(x => x).Subscribe(obs).DisposeWith(dis); + break; + } + + default: + if (NavigationHost.ContainsKey(@this.Name)) + { + WhenSetupSubjects[@this.Name].Where(x => x).Subscribe(obs).DisposeWith(dis); + } + + break; + } + } + }).DisposeWith(dis); + return dis; + }); + + /// + /// Whens the activated. + /// + /// The dummy. + /// Name of the host. + /// + /// A Bool. + /// + public static IObservable WhenSetup(this IUseHostedNavigation dummy, string? hostName = "") => + Observable.Create(obs => + { + var dis = new CompositeDisposable(); + ASetupCompleted.Subscribe(_ => + { + if (WhenSetupSubjects.Count > 0) + { + if (hostName?.Length > 0) + { + if (NavigationHost.ContainsKey(hostName)) + { + WhenSetupSubjects[hostName].Where(x => x).Subscribe(obs).DisposeWith(dis); + } + } + else + { + WhenSetupSubjects.First().Value.Where(x => x).Subscribe(obs).DisposeWith(dis); + } + } + }).DisposeWith(dis); + return dis; + }); +} diff --git a/src/ViewModel.WinForms/ReactiveMarbles.ViewModel.WinForms.csproj b/src/ViewModel.WinForms/ReactiveMarbles.ViewModel.WinForms.csproj new file mode 100644 index 0000000..5ff9e2b --- /dev/null +++ b/src/ViewModel.WinForms/ReactiveMarbles.ViewModel.WinForms.csproj @@ -0,0 +1,14 @@ + + + + net7.0 + enable + enable + false + + + + + + + diff --git a/src/ViewModel.Wpf/ReactiveMarbles.ViewModel.Wpf.csproj b/src/ViewModel.Wpf/ReactiveMarbles.ViewModel.Wpf.csproj new file mode 100644 index 0000000..4c6aaf9 --- /dev/null +++ b/src/ViewModel.Wpf/ReactiveMarbles.ViewModel.Wpf.csproj @@ -0,0 +1,14 @@ + + + + net7.0 + enable + enable + false + + + + + + + diff --git a/src/stylecop.json b/src/stylecop.json new file mode 100644 index 0000000..695f2aa --- /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": "ReactiveUI Association Incorporated", + "copyrightText": "Copyright (c) 2019-2023 {companyName}. All rights reserved.\n{companyName} 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..ffd1721 --- /dev/null +++ b/version.json @@ -0,0 +1,16 @@ +{ + "version": "1.0", + "publicReleaseRefSpec": [ + "^refs/heads/master$", + "^refs/heads/main$" + ], + "nugetPackageVersion":{ + "semVer": 2 + }, + "cloudBuild": { + "setVersionVariables": true, + "buildNumber": { + "enabled": false + } + } +} From 98d786ef076a84c60723266fe2ba156198a71a4c Mon Sep 17 00:00:00 2001 From: Chris Pulman Date: Sat, 15 Apr 2023 16:18:22 +0100 Subject: [PATCH 02/18] Update ViewModelRoutedViewHostMixins.cs --- src/ViewModel.Core/ViewModelRoutedViewHostMixins.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/ViewModel.Core/ViewModelRoutedViewHostMixins.cs b/src/ViewModel.Core/ViewModelRoutedViewHostMixins.cs index c93bc31..c9e2156 100644 --- a/src/ViewModel.Core/ViewModelRoutedViewHostMixins.cs +++ b/src/ViewModel.Core/ViewModelRoutedViewHostMixins.cs @@ -11,7 +11,6 @@ [assembly: InternalsVisibleTo("ReactiveMarbles.ViewModel.Wpf")] [assembly: InternalsVisibleTo("ReactiveMarbles.ViewModel.WinForms")] -[assembly: InternalsVisibleTo("ReactiveMarbles.ViewModel.XamForms")] [assembly: InternalsVisibleTo("ReactiveMarbles.ViewModel.MAUI")] [assembly: InternalsVisibleTo("ReactiveMarbles.ViewModel.WinUI")] [assembly: InternalsVisibleTo("ReactiveMarbles.ViewModel.Avalonia")] From 22e5bba314fd98fe971bb08e2515f4048c5131b0 Mon Sep 17 00:00:00 2001 From: Chris Pulman Date: Sat, 15 Apr 2023 23:18:18 +0100 Subject: [PATCH 03/18] Add Example Found issue with RxCommand => Could not load type 'ReactiveMarbles.Mvvm.ScheduledSubject', ServiceLocator needs to be able to resolve from types --- src/Directory.Build.props | 2 +- src/ReactiveMarbles.Navigation.sln | 13 +- src/ViewModel.Core/IHostScreen.cs | 5 +- .../ViewModelNavigatingEventArgs.cs | 2 +- .../ViewModelNavigationEventArgs.cs | 4 +- .../ReactiveMarbles.ViewModel.Core.csproj | 6 +- .../ReactiveMarbles.ViewModel.WinForms.csproj | 3 +- src/ViewModel.Wpf.Example/App.xaml | 32 ++ src/ViewModel.Wpf.Example/App.xaml.cs | 32 ++ src/ViewModel.Wpf.Example/AssemblyInfo.cs | 7 + src/ViewModel.Wpf.Example/MainWindow.xaml | 22 ++ src/ViewModel.Wpf.Example/MainWindow.xaml.cs | 31 ++ .../MainWindowViewModel.cs | 31 ++ src/ViewModel.Wpf.Example/SecondWindow.xaml | 21 ++ .../SecondWindow.xaml.cs | 31 ++ .../ViewModel.Wpf.Example.csproj | 23 ++ .../ViewModels/FirstViewModel.cs | 106 ++++++ .../ViewModels/MainViewModel.cs | 103 +++++ .../Views/FirstView.xaml | 27 ++ .../Views/FirstView.xaml.cs | 32 ++ src/ViewModel.Wpf.Example/Views/MainView.xaml | 27 ++ .../Views/MainView.xaml.cs | 33 ++ src/ViewModel.Wpf/AssemblyInfo.cs | 11 + src/ViewModel.Wpf/NavigationWindow.cs | 90 +++++ .../NavigationWindow{TViewModel}.cs | 54 +++ .../ReactiveMarbles.ViewModel.Wpf.csproj | 9 +- .../RxUserControl{TViewModel}.cs | 46 +++ src/ViewModel.Wpf/RxWindow{TViewModel}.cs | 48 +++ src/ViewModel.Wpf/ServiceLocatorMixins.cs | 121 ++++++ src/ViewModel.Wpf/Themes/Generic.xaml | 19 + src/ViewModel.Wpf/ViewModelRoutedViewHost.cs | 357 ++++++++++++++++++ 31 files changed, 1338 insertions(+), 10 deletions(-) create mode 100644 src/ViewModel.Wpf.Example/App.xaml create mode 100644 src/ViewModel.Wpf.Example/App.xaml.cs create mode 100644 src/ViewModel.Wpf.Example/AssemblyInfo.cs create mode 100644 src/ViewModel.Wpf.Example/MainWindow.xaml create mode 100644 src/ViewModel.Wpf.Example/MainWindow.xaml.cs create mode 100644 src/ViewModel.Wpf.Example/MainWindowViewModel.cs create mode 100644 src/ViewModel.Wpf.Example/SecondWindow.xaml create mode 100644 src/ViewModel.Wpf.Example/SecondWindow.xaml.cs create mode 100644 src/ViewModel.Wpf.Example/ViewModel.Wpf.Example.csproj create mode 100644 src/ViewModel.Wpf.Example/ViewModels/FirstViewModel.cs create mode 100644 src/ViewModel.Wpf.Example/ViewModels/MainViewModel.cs create mode 100644 src/ViewModel.Wpf.Example/Views/FirstView.xaml create mode 100644 src/ViewModel.Wpf.Example/Views/FirstView.xaml.cs create mode 100644 src/ViewModel.Wpf.Example/Views/MainView.xaml create mode 100644 src/ViewModel.Wpf.Example/Views/MainView.xaml.cs create mode 100644 src/ViewModel.Wpf/AssemblyInfo.cs create mode 100644 src/ViewModel.Wpf/NavigationWindow.cs create mode 100644 src/ViewModel.Wpf/NavigationWindow{TViewModel}.cs create mode 100644 src/ViewModel.Wpf/RxUserControl{TViewModel}.cs create mode 100644 src/ViewModel.Wpf/RxWindow{TViewModel}.cs create mode 100644 src/ViewModel.Wpf/ServiceLocatorMixins.cs create mode 100644 src/ViewModel.Wpf/Themes/Generic.xaml create mode 100644 src/ViewModel.Wpf/ViewModelRoutedViewHost.cs diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 4e7be29..830ad36 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -6,7 +6,7 @@ $(MSBuildProjectName.Contains('Tests')) embedded Chris Pulman, Glenn Watson - Copyright (c) 2021 ReactiveUI Association Inc + Copyright (c) $([System.DateTime]::Now.ToString(yyyy)) ReactiveUI Association Inc MIT https://github.com/reactivemarbles/Navigation Provides a Navigation Framework for ReactiveMarbles based projects. diff --git a/src/ReactiveMarbles.Navigation.sln b/src/ReactiveMarbles.Navigation.sln index c3408fe..eb523dc 100644 --- a/src/ReactiveMarbles.Navigation.sln +++ b/src/ReactiveMarbles.Navigation.sln @@ -7,7 +7,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReactiveMarbles.ViewModel.W EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReactiveMarbles.ViewModel.Core", "ViewModel.Core\ReactiveMarbles.ViewModel.Core.csproj", "{990C0E6D-0C09-482D-8AFA-F135EC206C43}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReactiveMarbles.ViewModel.WinForms", "ViewModel.WinForms\ReactiveMarbles.ViewModel.WinForms.csproj", "{CD830D09-4558-403B-9504-C0CFD90FDC3B}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReactiveMarbles.ViewModel.WinForms", "ViewModel.WinForms\ReactiveMarbles.ViewModel.WinForms.csproj", "{CD830D09-4558-403B-9504-C0CFD90FDC3B}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionConfig", "SolutionConfig", "{B9D5E36A-C2F2-4D70-B5D0-797574468968}" ProjectSection(SolutionItems) = preProject @@ -23,6 +23,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionConfig", "SolutionC ..\version.json = ..\version.json EndProjectSection EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{6E654C37-7F3A-4E17-83C1-CA8BC9B54476}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ViewModel.Wpf.Example", "ViewModel.Wpf.Example\ViewModel.Wpf.Example.csproj", "{5E67BC1D-9AD7-4DDA-B095-6EFE99AD2C2E}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -41,10 +45,17 @@ Global {CD830D09-4558-403B-9504-C0CFD90FDC3B}.Debug|Any CPU.Build.0 = Debug|Any CPU {CD830D09-4558-403B-9504-C0CFD90FDC3B}.Release|Any CPU.ActiveCfg = Release|Any CPU {CD830D09-4558-403B-9504-C0CFD90FDC3B}.Release|Any CPU.Build.0 = Release|Any CPU + {5E67BC1D-9AD7-4DDA-B095-6EFE99AD2C2E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5E67BC1D-9AD7-4DDA-B095-6EFE99AD2C2E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5E67BC1D-9AD7-4DDA-B095-6EFE99AD2C2E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5E67BC1D-9AD7-4DDA-B095-6EFE99AD2C2E}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {5E67BC1D-9AD7-4DDA-B095-6EFE99AD2C2E} = {6E654C37-7F3A-4E17-83C1-CA8BC9B54476} + EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {489B52FF-BC1B-435B-8412-301C8A46D473} EndGlobalSection diff --git a/src/ViewModel.Core/IHostScreen.cs b/src/ViewModel.Core/IHostScreen.cs index 6e0e2e8..ec55bf0 100644 --- a/src/ViewModel.Core/IHostScreen.cs +++ b/src/ViewModel.Core/IHostScreen.cs @@ -4,7 +4,10 @@ namespace ReactiveMarbles.ViewModel.Core { + /// + /// IHostScreen. + /// public interface IHostScreen { } -} \ No newline at end of file +} diff --git a/src/ViewModel.Core/NavigationEvents/ViewModelNavigatingEventArgs.cs b/src/ViewModel.Core/NavigationEvents/ViewModelNavigatingEventArgs.cs index d1aa653..6fd7c4c 100644 --- a/src/ViewModel.Core/NavigationEvents/ViewModelNavigatingEventArgs.cs +++ b/src/ViewModel.Core/NavigationEvents/ViewModelNavigatingEventArgs.cs @@ -21,7 +21,7 @@ public class ViewModelNavigatingEventArgs : ViewModelNavigationEventArgs, IViewM /// The view. /// The hostName. /// The parmeter. - public ViewModelNavigatingEventArgs(IRxObject? from, IRxObject? to, NavigationType navType, IViewFor? view, string hostName, object? parmeter = null) + public ViewModelNavigatingEventArgs(IRxObject? from, IRxObject? to, NavigationType navType, IAmViewFor? view, string hostName, object? parmeter = null) : base(from, to, navType, view, hostName, parmeter) { } diff --git a/src/ViewModel.Core/NavigationEvents/ViewModelNavigationEventArgs.cs b/src/ViewModel.Core/NavigationEvents/ViewModelNavigationEventArgs.cs index 0e20276..9b1844a 100644 --- a/src/ViewModel.Core/NavigationEvents/ViewModelNavigationEventArgs.cs +++ b/src/ViewModel.Core/NavigationEvents/ViewModelNavigationEventArgs.cs @@ -19,7 +19,7 @@ public class ViewModelNavigationEventArgs : ViewModelNavigationBaseEventArgs, IV /// The view. /// The Hostname. /// The parmeter. - public ViewModelNavigationEventArgs(IRxObject? from, IRxObject? to, NavigationType navType, IViewFor? view, string hostName, object? parmeter = null) + public ViewModelNavigationEventArgs(IRxObject? from, IRxObject? to, NavigationType navType, IAmViewFor? view, string hostName, object? parmeter = null) { From = from; To = to; @@ -50,5 +50,5 @@ public ViewModelNavigationEventArgs(IRxObject? from, IRxObject? to, NavigationTy /// /// The view. [DataMember] - public IViewFor? View { get; set; } + public IAmViewFor? View { get; set; } } diff --git a/src/ViewModel.Core/ReactiveMarbles.ViewModel.Core.csproj b/src/ViewModel.Core/ReactiveMarbles.ViewModel.Core.csproj index 6a540a1..d2ea1ac 100644 --- a/src/ViewModel.Core/ReactiveMarbles.ViewModel.Core.csproj +++ b/src/ViewModel.Core/ReactiveMarbles.ViewModel.Core.csproj @@ -1,10 +1,12 @@  - net7.0 + netstandard2.0;net6.0;net6.0-android;net6.0-ios;net6.0-tvos;net6.0-macos;net7.0;net7.0-android;net7.0-ios;net7.0-tvos;net7.0-macos + $(TargetFrameworks);net462;net472;net6.0-windows10.0.19041.0;net7.0-windows10.0.19041.0 enable - enable false + latest + enable diff --git a/src/ViewModel.WinForms/ReactiveMarbles.ViewModel.WinForms.csproj b/src/ViewModel.WinForms/ReactiveMarbles.ViewModel.WinForms.csproj index 5ff9e2b..28da272 100644 --- a/src/ViewModel.WinForms/ReactiveMarbles.ViewModel.WinForms.csproj +++ b/src/ViewModel.WinForms/ReactiveMarbles.ViewModel.WinForms.csproj @@ -1,8 +1,9 @@ - + net7.0 enable + latest enable false diff --git a/src/ViewModel.Wpf.Example/App.xaml b/src/ViewModel.Wpf.Example/App.xaml new file mode 100644 index 0000000..8ae459d --- /dev/null +++ b/src/ViewModel.Wpf.Example/App.xaml @@ -0,0 +1,32 @@ + + + + + diff --git a/src/ViewModel.Wpf.Example/App.xaml.cs b/src/ViewModel.Wpf.Example/App.xaml.cs new file mode 100644 index 0000000..fcb6d32 --- /dev/null +++ b/src/ViewModel.Wpf.Example/App.xaml.cs @@ -0,0 +1,32 @@ +// Copyright (c) 2019-2023 ReactiveUI Association Incorporated. All rights reserved. +// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using System.Reactive.Concurrency; +using System.Windows; +using ReactiveMarbles.Locator; +using ReactiveMarbles.Mvvm; + +namespace ViewModel.Wpf.Example +{ + /// + /// Interaction logic for App.xaml. + /// + public partial class App : Application + { + /// + /// Initializes a new instance of the class. + /// + public App() + { + ServiceLocator.Current().AddCoreRegistrations(() => + CoreRegistrationBuilder + .Create() + .WithMainThreadScheduler(DefaultScheduler.Instance) + .WithTaskPoolScheduler(TaskPoolScheduler.Default) + .WithExceptionHandler(new DebugExceptionHandler()) + .Build()); + ServiceLocator.Current().AddSingleton(() => new()); + } + } +} diff --git a/src/ViewModel.Wpf.Example/AssemblyInfo.cs b/src/ViewModel.Wpf.Example/AssemblyInfo.cs new file mode 100644 index 0000000..c100ffa --- /dev/null +++ b/src/ViewModel.Wpf.Example/AssemblyInfo.cs @@ -0,0 +1,7 @@ +// Copyright (c) 2019-2023 ReactiveUI Association Incorporated. All rights reserved. +// ReactiveUI Association Incorporated licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using System.Windows; + +[assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)] diff --git a/src/ViewModel.Wpf.Example/MainWindow.xaml b/src/ViewModel.Wpf.Example/MainWindow.xaml new file mode 100644 index 0000000..1b3c027 --- /dev/null +++ b/src/ViewModel.Wpf.Example/MainWindow.xaml @@ -0,0 +1,22 @@ + + +