Skip to content

Commit

Permalink
Fixed all the warnings and added all the missing XML docs
Browse files Browse the repository at this point in the history
  • Loading branch information
xperiandri committed Apr 7, 2022
1 parent 89e9771 commit 6f29ea6
Show file tree
Hide file tree
Showing 19 changed files with 256 additions and 98 deletions.
32 changes: 28 additions & 4 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# To learn more about .editorconfig see https://aka.ms/editorconfigdocs
root = true
###############################
# Core EditorConfig Options #
###############################
root = true
# All files
[*]
end_of_line = crlf
Expand All @@ -14,7 +14,7 @@ trim_trailing_whitespace = true
indent_size = 4
charset = utf-8-bom
# Project files
[*.{csproj,fsproj,vbproj,shproj,projitems,plist,nuspec}]
[*.{csproj,fsproj,vbproj,shproj,projitems,props,nuspec,config,xaml,xml,plist}]
indent_size = 2
charset = utf-8-bom
###############################
Expand All @@ -37,8 +37,11 @@ dotnet_style_parentheses_in_relational_binary_operators = always_for_cl
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity : suggestion
dotnet_style_parentheses_in_other_operators = never_if_unnecessary : suggestion
# Modifier preferences
dotnet_style_require_accessibility_modifiers = always : warning
dotnet_style_readonly_field = true : warning
dotnet_style_require_accessibility_modifiers = always : warning
roslynator_accessibility_modifiers = explicit
roslynator_enum_has_flag_style = method
roslynator_object_creation_type_style = implicit
# Expression-level preferences
dotnet_style_object_initializer = true : warning
dotnet_style_collection_initializer = true : warning
Expand Down Expand Up @@ -815,7 +818,7 @@ dotnet_diagnostic.CA5383.severity = warning
# CA5384: Do Not Use Digital Signature Algorithm (DSA)
dotnet_diagnostic.CA5384.severity = warning

# CA5385: Use Rivest–Shamir–Adleman (RSA) Algorithm With Sufficient Key Size
# CA5385: Use Rivest-Shamir-Adleman (RSA) Algorithm With Sufficient Key Size
dotnet_diagnostic.CA5385.severity = warning

# CA5386: Avoid hardcoding SecurityProtocolType value
Expand Down Expand Up @@ -874,3 +877,24 @@ dotnet_diagnostic.CA5403.severity = warning

# CA9999: Analyzer version mismatch
dotnet_diagnostic.CA9999.severity = warning

###############################
# Code Analysis Exceptions #
###############################
[**/{Main.cs,Program.cs,*Activity.cs,*Page.cs,*.xaml.cs,Controls/**.cs}]
# CA1010: Collections should implement generic interface
dotnet_diagnostic.CA1010.severity = none
# CA1012: Abstract type 'ShellBase' should not have public constructors
dotnet_diagnostic.CA1012.severity = none
# CA1501: Avoid excessive inheritance
dotnet_diagnostic.CA1501.severity = none
# IDE0001: Simplify Names
dotnet_diagnostic.IDE0001.severity = suggestion
# IDE0021: Use expression body for constructors
dotnet_diagnostic.IDE0021.severity = suggestion

[{App.xaml.cs,Shell.xaml.cs,Program.cs}]
# CA1724: The type name App conflicts in whole or in part with the namespace name. Change either name to eliminate the conflict.
dotnet_diagnostic.CA1724.severity = none
# CA1801: Parameter args of method Main is never used. Remove the parameter or use it in the method body.
dotnet_diagnostic.CA1801.severity = none
2 changes: 1 addition & 1 deletion src/Elmish.Uno.Uwp/Elmish.Uno.Uwp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@
</PropertyGroup>
<PropertyGroup>
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
<DocumentationFile>$(OutputPath)\Elmish.Uno.Mobile.XML</DocumentationFile>
<DocumentationFile>$(OutputPath)Elmish.Uno.Mobile.xml</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<Compile Include="NavigationService.cs" />
Expand Down
61 changes: 61 additions & 0 deletions src/Elmish.Uno.Uwp/NavigationService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,38 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;

using Windows.UI.Xaml.Controls;

namespace Elmish.Uno.Navigation
{
/// <summary>
/// Class that allows to navigate to pages within an attached <see cref="Frame"/>
/// using a dictionary map of page names and their types.
/// </summary>
public class NavigationService : INavigationService
{
private readonly Frame frame;
private readonly IReadOnlyDictionary<string, Type> pageMap;

/// <summary>
/// Creates a NavigationService instance attaching a <see cref="Frame"/>
/// and specifying a map of pages names and their types.
/// </summary>
/// <param name="frame">Frame to use for navigation.</param>
/// <param name="pageMap">Map of page names to page types.</param>
public NavigationService(Frame frame, IReadOnlyDictionary<string, Type> pageMap)
{
this.frame = frame;
this.pageMap = pageMap;
}

/// <summary>
/// Creates a NavigationService instance attaching a <see cref="Frame"/>
/// and specifying a list of pages names and their types pairs.
/// </summary>
/// <param name="frame">Frame to use for navigation.</param>
/// <param name="pageMap">Map of page names to page types.</param>
public NavigationService(Frame frame, IEnumerable<KeyValuePair<string, Type>> pageMap)
{
this.frame = frame;
Expand All @@ -26,19 +43,63 @@ public NavigationService(Frame frame, IEnumerable<KeyValuePair<string, Type>> pa
.ToImmutable();
}

/// <summary>
/// Gets the number of pages in the navigation history that can be cached for the <see cref="Frame"/>.
/// </summary>
public int CacheSize => frame.CacheSize;

/// <summary>
/// Gets the number of entries in the navigation back stack.
/// </summary>
public int BackStackDepth => frame.BackStackDepth;

/// <summary>
/// Gets a value that indicates whether there is at least one entry in
/// back navigation history.
/// </summary>
public bool CanGoBack => frame.CanGoBack;

/// <summary>
/// Gets a value that indicates whether there is at least one entry in
/// forward navigation history.
/// </summary>
public bool CanGoForward => frame.CanGoForward;

/// <summary>
/// Serializes the <see cref="Frame"/> navigation history into a string.
/// </summary>
/// <returns>The string-form serialized navigation history.</returns>
public string GetNavigationState() => frame.GetNavigationState();
/// <summary>
/// Reads and restores the navigation history of a <see cref="Frame"/> from
/// a provided serialization string.
/// </summary>
/// <param name="navigationState">
/// The serialization string that supplies the restore point for navigation history.
/// </param>
public void SetNavigationState(string navigationState) => frame.SetNavigationState(navigationState);
/// <summary>
/// Navigates to the most recent item in back navigation history,
/// if a Frame manages its own navigation history.
/// </summary>
public void GoBack() => frame.GoBack();
/// <summary>
/// Navigates to the most recent item in forward navigation history,
/// if a Frame manages its own navigation history.
/// </summary>
public void GoForward() => frame.GoForward();
/// <summary>
/// Navigates an attached <see cref="Frame"/> to a page specified my its name.
/// </summary>
/// <param name="name">Page name</param>
/// <returns>True if navigation succeeded.</returns>
public bool Navigate(string name) => frame.Navigate(pageMap[name], null);
/// <summary>
/// Navigates an attached <see cref="Frame"/> to a page specified my its name.
/// </summary>
/// <param name="name">Page name</param>
/// <param name="navigationParams">Parameter to be passed to a page</param>
/// <returns>True if navigation succeeded.</returns>
public bool Navigate(string name, IReadOnlyDictionary<string, object> navigationParams) => frame.Navigate(pageMap[name], navigationParams);
}
}
103 changes: 96 additions & 7 deletions src/Elmish.Uno.Uwp/ViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,70 @@

namespace Elmish.Windows
{
/// <summary>
/// Implementation of dynamic property required by WinRT to do bindings.
/// </summary>
/// <typeparam name="TTarget">Target object type from which to get and to which to set a property value.</typeparam>
/// <typeparam name="TValue">Value type.</typeparam>
public class DynamicCustomProperty<TTarget, TValue> : ICustomProperty
{
/// <summary>
/// Property getter delegate.
/// </summary>
public Func<TTarget, TValue> Getter { get; }
/// <summary>
/// Property setter delegate
/// </summary>
public Action<TTarget, TValue> Setter { get; }
/// <summary>
/// Indexer getter delegate
/// </summary>
public Func<TTarget, object, TValue> IndexGetter { get; }
/// <summary>
/// Indexer setter delegate
/// </summary>
public Action<TTarget, object, TValue> IndexSetter { get; }

public object GetValue(object target) => Getter.Invoke((TTarget) target);
/// <summary>Gets the value of the custom property from a particular instance.</summary>
/// <param name="target">The owning instance.</param>
/// <returns>The retrieved value.</returns>
public object GetValue(object target) => Getter.Invoke((TTarget)target);
/// <summary>Sets the custom property value on a specified instance.</summary>
/// <param name="target">The owner instance.</param>
/// <param name="value">The value to set.</param>
public void SetValue(object target, object value) => Setter.Invoke((TTarget)target, (TValue)value);
/// <summary>Gets the value at an index location, for cases where the custom property has indexer support.</summary>
/// <param name="target">The owning instance.</param>
/// <param name="index">The index to get.</param>
/// <returns>The retrieved value at the index.</returns>
public object GetIndexedValue(object target, object index) => IndexGetter.Invoke((TTarget)target, index);
/// <summary>Sets the value at an index location, for cases where the custom property has indexer support.</summary>
/// <param name="target">The owner instance.</param>
/// <param name="value">The value to set.</param>
/// <param name="index">The index location to set to.</param>
public void SetIndexedValue(object target, object value, object index) => IndexSetter.Invoke((TTarget)target, index, (TValue)value);

/// <summary>Gets a value that determines whether the custom property supports read access.</summary>
/// <returns>**true** if the property value can be read as a data source. **false** if the property cannot be a data source value.</returns>
public bool CanRead => Getter != null || IndexGetter != null;
/// <summary>Gets a value that determines whether the custom property supports write access.</summary>
/// <returns>**true** if the value can be written to through a data source relationship in a two-way binding. **false** if the property cannot be written to.</returns>
public bool CanWrite => Setter != null || IndexSetter != null;
/// <summary>Gets the path-relevant name of the property.</summary>
/// <returns>The name of the property as it would be specified in a binding expression.</returns>
public string Name { get; }
/// <summary>Gets the underlying type of the custom property.</summary>
/// <returns>The underlying type, with relevant information as the values of the TypeName structure. TypeName provides the infrastructure such that property backing does not have to resemble common language runtime (CLR) and **System.Type** definitions.</returns>
public Type Type => typeof(TValue);

/// <summary>
/// Creates an instance of <see href="DynamicCustomProperty">DynamicCustomProperty</see>.
/// </summary>
/// <param name="name">Property name.</param>
/// <param name="getter">Property getter delegate.</param>
/// <param name="setter">Property setter delegate.</param>
/// <param name="indexGetter">Indexer getter delegate.</param>
/// <param name="indexSetter">Indexer setter delegate.</param>
public DynamicCustomProperty(string name, Func<TTarget, TValue> getter, Action<TTarget, TValue> setter = null, Func<TTarget, object, TValue> indexGetter = null, Action<TTarget, object, TValue> indexSetter = null)
{
Name = name;
Expand Down Expand Up @@ -112,41 +159,83 @@ private ICustomProperty GetProperty(string name)

namespace Elmish.Uno
{
/// <summary>
/// View model methods to correspond to F# module
/// </summary>
[RequireQualifiedAccess, CompilationMapping(SourceConstructFlags.Module)]
public static class ViewModel
{
/// <summary>
/// Creates an instance of Elmish view model without dispatcher subscription.
/// </summary>
/// <typeparam name="TModel">Model type.</typeparam>
/// <typeparam name="TMsg">Elmish message type.</typeparam>
/// <param name="model">Design time model.</param>
/// <param name="bindings">Elmish program to run.</param>
/// <returns>An instance of internal Elmish view model class.</returns>
public static object DesignInstance<TModel, TMsg>(TModel model, FSharpList<Binding<TModel, TMsg>> bindings)
{
var emptyDispatch = FuncConvert.FromAction((TMsg msg) => { });
return new Elmish.Windows.ViewModel<TModel, TMsg>(model, emptyDispatch, bindings, ElmConfig.Default, "main");
}

public static object DesignInstance<T, TModel, TMsg>(TModel model, Program<T, TModel, TMsg, FSharpList<Binding<TModel, TMsg>>> program)
/// <summary>
/// Creates an instance of Elmish view model without dispatcher subscription.
/// and with an initial program argument.
/// </summary>
/// <typeparam name="T">Initial program argument type.</typeparam>
/// <typeparam name="TModel">Model type.</typeparam>
/// <typeparam name="TMsg">Elmish message type.</typeparam>
/// <param name="model">Design time model.</param>
/// <param name="bindings">Elmish program to run.</param>
/// <returns>An instance of internal Elmish view model class.</returns>
public static object DesignInstance<T, TModel, TMsg>(TModel model, Program<T, TModel, TMsg, FSharpList<Binding<TModel, TMsg>>> bindings)
{
var emptyDispatch = FuncConvert.FromAction((TMsg msg) => { });
var mapping = FSharpFunc<TModel, FSharpFunc<TMsg, Unit>>.InvokeFast(ProgramModule.view(program), model, emptyDispatch);
var mapping = FSharpFunc<TModel, FSharpFunc<TMsg, Unit>>.InvokeFast(ProgramModule.view(bindings), model, emptyDispatch);
return DesignInstance(model, mapping);
}

public static void StartLoop<TModel, TMsg>(ElmConfig config, FrameworkElement element, Action<Program<Microsoft.FSharp.Core.Unit, TModel, TMsg, FSharpList<Binding<TModel, TMsg>>>> programRun, Program<Unit, TModel, TMsg, FSharpList<Binding<TModel, TMsg>>> program)
/// <summary>
/// Creates an instance of Elmish view model with dispatcher subscription.
/// </summary>
/// <typeparam name="TModel">Model type.</typeparam>
/// <typeparam name="TMsg">Elmish message type.</typeparam>
/// <param name="config">Elmish config.</param>
/// <param name="element">UI control to set DataContext property on.</param>
/// <param name="bindings">Elmish bindings definitions list.</param>
/// <param name="program">Elmish program to run.</param>
public static void StartLoop<TModel, TMsg>(ElmConfig config, FrameworkElement element, Action<Program<Microsoft.FSharp.Core.Unit, TModel, TMsg, FSharpList<Binding<TModel, TMsg>>>> bindings, Program<Unit, TModel, TMsg, FSharpList<Binding<TModel, TMsg>>> program)
{
FSharpRef<FSharpOption<ViewModel<TModel, TMsg>>> lastModel = new FSharpRef<FSharpOption<ViewModel<TModel, TMsg>>>(null);
FSharpFunc<FSharpFunc<TMsg, Unit>, FSharpFunc<TMsg, Unit>> syncDispatch =
FuncConvert.FromAction(MakeSyncDispatch<TMsg>(element));
var setState = FuncConvert.FromAction(MakeSetState(config, element, program, lastModel));
programRun.Invoke(
bindings.Invoke(
ProgramModule.withSyncDispatch(syncDispatch,
ProgramModule.withSetState(setState, program)));
}

public static void StartLoop<T, TModel, TMsg>(ElmConfig config, FrameworkElement element, Action<T, Program<T, TModel, TMsg, FSharpList<Binding<TModel, TMsg>>>> programRun, Program<T, TModel, TMsg, FSharpList<Binding<TModel, TMsg>>> program, T arg)
/// <summary>
/// Creates an instance of Elmish view model with dispatcher subscription
/// and with an initial program argument.
/// </summary>
/// <typeparam name="T">Initial program argument type.</typeparam>
/// <typeparam name="TModel">Model type.</typeparam>
/// <typeparam name="TMsg">Elmish message type.</typeparam>
/// <param name="config">Elmish config.</param>
/// <param name="element">UI control to set DataContext property on.</param>
/// <param name="bindings">Elmish bindings definitions list.</param>
/// <param name="program">Elmish program to run.</param>
/// <param name="arg">Initial program argument.</param>
public static void StartLoop<T, TModel, TMsg>(ElmConfig config, FrameworkElement element, Action<T, Program<T, TModel, TMsg, FSharpList<Binding<TModel, TMsg>>>> bindings, Program<T, TModel, TMsg, FSharpList<Binding<TModel, TMsg>>> program, T arg)
{
FSharpRef<FSharpOption<ViewModel<TModel, TMsg>>> lastModel = new FSharpRef<FSharpOption<ViewModel<TModel, TMsg>>>(null);
FSharpFunc<FSharpFunc<TMsg, Unit>, FSharpFunc<TMsg, Unit>> syncDispatch =
FuncConvert.FromAction(MakeSyncDispatch<TMsg>(element));
var setState = FuncConvert.FromAction(MakeSetState(config, element, program, lastModel));

programRun.Invoke(arg,
bindings.Invoke(arg,
ProgramModule.withSyncDispatch(syncDispatch,
ProgramModule.withSetState(setState, program)));
}
Expand Down
1 change: 1 addition & 0 deletions src/Elmish.Uno.sln
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "NuGet", "NuGet", "{49DD7592-B03D-4EEE-B1BF-522488992C80}"
ProjectSection(SolutionItems) = preProject
..\Elmish.Uno.nuspec = ..\Elmish.Uno.nuspec
Templates\Templates.nuspec = Templates\Templates.nuspec
EndProjectSection
EndProject
Global
Expand Down
6 changes: 4 additions & 2 deletions src/Samples/Samples.Droid/Samples.Droid.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,11 @@
<PackageReference Include="Uno.UI" Version="$(UnoUIVersion)" />
<PackageReference Include="Uno.UI.RemoteControl" Version="$(UnoUIVersion)" Condition="'$(Configuration)'=='Debug'" />
<PackageReference Include="Uno.UniversalImageLoader" Version="1.9.*" />
<PackageReference Include="Xamarin.AndroidX.Activity" Version="1.3.*" />
<PackageReference Include="Xamarin.AndroidX.Activity" Version="1.4.*" />
<PackageReference Include="Xamarin.AndroidX.AppCompat" Version="1.3.*" />
<PackageReference Include="Xamarin.AndroidX.Legacy.Support.V4" Version="1.0.0.*" />
<PackageReference Include="Xamarin.AndroidX.Core" Version="1.7.*" />
<PackageReference Include="Xamarin.AndroidX.Fragment" Version="1.3.*" />
<PackageReference Include="Xamarin.AndroidX.Legacy.Support.V4" Version="1.0.*" />
<PackageReference Include="Xamarin.AndroidX.RecyclerView" Version="1.2.*" />
</ItemGroup>
<ItemGroup>
Expand Down
Loading

0 comments on commit 6f29ea6

Please sign in to comment.