Added secure field (and examples) on iOS.

This commit is contained in:
Jon Lipsky 2019-07-11 17:03:27 -05:00
Родитель 829cf20dfd
Коммит 041e8c29f1
10 изменённых файлов: 261 добавлений и 1 удалений

Просмотреть файл

@ -25,6 +25,9 @@ namespace HotUI.Samples {
new MenuItem("ListPage1", ()=> new ListPage()),
new MenuItem("ListPage2", ()=> new ListPage2()),
new MenuItem("Insane Diff", ()=> new InsaneDiffPage()),
new MenuItem("SecureFieldSample1", ()=> new SecureFieldSample1()),
new MenuItem("SecureFieldSample2", ()=> new SecureFieldSample2()),
new MenuItem("SecureFieldSample3", ()=> new SecureFieldSample3()),
new MenuItem("SwiftUI Tutorial Section 1", ()=> new Section1()),
new MenuItem("SwiftUI Tutorial Section 2", ()=> new Section2()),
new MenuItem("SwiftUI Tutorial Section 3", ()=> new Section3()),

Просмотреть файл

@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
/*
struct ContentView : View {
@State private var password: String = ""
var body: some View {
VStack {
SecureField("Enter a password", text: $password)
Text("You entered: \(password)")
}
}
}
*/
namespace HotUI.Samples
{
public class SecureFieldSample1 : View
{
/*[State]
readonly MyBindingObject state;*/
readonly State<string> password = new State<string>("");
public SecureFieldSample1()
{
Body = () => new VStack
{
new SecureField("Enter a password", newValue => password.Value = newValue),
new Text(() => $"{password.Value}")
};
}
}
}

Просмотреть файл

@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
/*
struct ContentView : View {
@State private var password: String = ""
var body: some View {
VStack {
SecureField("Enter a password", text: $password)
Text("You entered: \(password)")
}
}
}
*/
namespace HotUI.Samples
{
public class SecureFieldSample2 : View
{
readonly State<string> password = new State<string>("");
public SecureFieldSample2()
{
Body = () => new VStack
{
new SecureField("Enter a password", value => password.Value = value),
new Text(password.Value)
};
}
}
}

Просмотреть файл

@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
/*
struct ContentView : View {
@State private var password: String = ""
var body: some View {
VStack {
SecureField("Enter a password", text: $password)
Text("You entered: \(password)")
}
}
}
*/
namespace HotUI.Samples
{
public class SecureFieldSample3 : View
{
readonly State<string> password = new State<string>("");
public SecureFieldSample3()
{
Body = () => new VStack
{
new SecureField("Enter a password", password),
new Text(password)
};
}
}
}

Просмотреть файл

@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
/*
struct ContentView : View {
@State private var password: String = ""
var body: some View {
VStack {
SecureField("Enter a password", text: $password)
Text("You entered: \(password)")
}
}
}
*/
namespace HotUI.Samples
{
public class SecureFieldSample4 : View
{
readonly State<string> password = "";
public SecureFieldSample4()
{
Body = () => new VStack
{
new SecureField("Enter a password", password),
new Text(password)
};
}
}
}

Просмотреть файл

@ -0,0 +1,55 @@
using System;
using UIKit;
// ReSharper disable MemberCanBePrivate.Global
// ReSharper disable ClassNeverInstantiated.Global
namespace HotUI.iOS
{
public class SecureFieldHandler : AbstractHandler<SecureField, UITextField>
{
public static readonly PropertyMapper<SecureField> Mapper = new PropertyMapper<SecureField>(ViewHandler.Mapper)
{
[nameof(SecureField.Text)] = MapTextProperty,
[nameof(SecureField.Placeholder)] = MapPlaceholderProperty
};
public SecureFieldHandler() : base(Mapper)
{
}
protected override UITextField CreateView()
{
var textField = new UITextField();
textField.SecureTextEntry = true;
textField.EditingDidEnd += EntryHandler_EditingDidEnd;
textField.ShouldReturn = s =>
{
textField.ResignFirstResponder();
return true;
};
return textField;
}
private void EntryHandler_EditingDidEnd(object sender, EventArgs e)
{
VirtualView?.OnCommit(TypedNativeView.Text);
}
public static void MapTextProperty(IViewHandler viewHandler, SecureField virtualView)
{
var nativeView = (UITextField) viewHandler.NativeView;
nativeView.Text = virtualView.Text;
nativeView.SizeToFit();
}
public static void MapPlaceholderProperty(IViewHandler viewHandler, SecureField virtualView)
{
var nativeView = (UITextField) viewHandler.NativeView;
nativeView.Placeholder = virtualView.Placeholder;
nativeView.SizeToFit();
}
}
}

Просмотреть файл

@ -50,6 +50,7 @@
<Compile Include="Extensions\CoreGraphicsExtensions.cs" />
<Compile Include="Handlers\AbstractLayoutHandler.cs" />
<Compile Include="Handlers\HStackHandler.cs" />
<Compile Include="Handlers\SecureFieldHandler.cs" />
<Compile Include="Handlers\SpacerHandler.cs" />
<Compile Include="Handlers\VStackHandler.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />

Просмотреть файл

@ -16,6 +16,7 @@ namespace HotUI.iOS {
hasInit = true;
Registrar.Handlers.Register<Button, ButtonHandler> ();
Registrar.Handlers.Register<TextField, TextFieldHandler> ();
Registrar.Handlers.Register<SecureField, SecureFieldHandler>();
Registrar.Handlers.Register<Text, TextHandler> ();
Registrar.Handlers.Register<Toggle, ToggleHandler>();
Registrar.Handlers.Register<VStack, VStackHandler> ();

Просмотреть файл

@ -0,0 +1,60 @@
using System;
namespace HotUI {
public class SecureField : View
{
public SecureField ()
{
}
public SecureField (string placeholder, Action<string> onCommit = null) : base (true)
{
Placeholder = placeholder;
OnCommit = onCommit;
}
public SecureField (string text = null, string placeholder = null, Action<string> onCommit = null) : base (true)
{
Text = text;
Placeholder = placeholder;
OnCommit = onCommit;
}
public SecureField (Func<string> builder, string placeholder = null, Action<string> onCommit = null )
{
TextBinding = builder;
Placeholder = placeholder;
OnCommit = onCommit;
}
string text;
public string Text {
get => text;
private set => this.SetValue (State, ref text, value, ViewPropertyChanged);
}
public Func<string> TextBinding { get; private set; }
protected override void WillUpdateView ()
{
base.WillUpdateView ();
if (TextBinding != null) {
State.StartProperty ();
var text = TextBinding.Invoke ();
var props = State.EndProperty ();
var propCount = props.Length;
if (propCount > 0) {
State.BindingState.AddViewProperty (props, (s,o)=> Text = TextBinding.Invoke());
}
Text = text;
}
}
string placeholder;
public string Placeholder {
get => placeholder;
set => this.SetValue (State, ref placeholder, value, ViewPropertyChanged);
}
public Action<string> OnCommit { get; set; }
}
}

Просмотреть файл

@ -24,7 +24,12 @@ namespace HotUI {
get => GetProperty<T> ();
set => SetProperty (value);
}
public static implicit operator T(State<T> state) => state.Value;
public static implicit operator Action<T>(State<T> state) => value => state.Value = value;
public static implicit operator State<T>(T value) => new State<T>(value);
}
public class StateBuilder : IDisposable {
static List<State> currentStates = new List<State> ();
public static State CurrentState => currentStates.LastOrDefault ();