diff --git a/src/App/App.csproj b/src/App/App.csproj
index b242631d4..a57043e39 100644
--- a/src/App/App.csproj
+++ b/src/App/App.csproj
@@ -60,6 +60,7 @@
+
diff --git a/src/App/Controls/ExtendedEntry.cs b/src/App/Controls/ExtendedEntry.cs
index a6e1c0bb9..62b8270cd 100644
--- a/src/App/Controls/ExtendedEntry.cs
+++ b/src/App/Controls/ExtendedEntry.cs
@@ -47,7 +47,6 @@ namespace Bit.App.Controls
set { SetValue(MaxLengthProperty, value); }
}
-
public ReturnType? ReturnType { get; set; }
public bool? Autocorrect { get; set; }
public bool DisableAutocapitalize { get; set; }
diff --git a/src/App/Controls/PinControl.cs b/src/App/Controls/PinControl.cs
new file mode 100644
index 000000000..8b9a11907
--- /dev/null
+++ b/src/App/Controls/PinControl.cs
@@ -0,0 +1,45 @@
+using System;
+using Bit.App.Models.Page;
+using Xamarin.Forms;
+
+namespace Bit.App.Controls
+{
+ public class PinControl
+ {
+ private Action _pinEnteredAction;
+
+ public PinControl(Action pinEnteredAction)
+ {
+ _pinEnteredAction = pinEnteredAction;
+
+ Label = new Label
+ {
+ HorizontalTextAlignment = TextAlignment.Center,
+ FontSize = 30,
+ TextColor = Color.FromHex("333333"),
+ FontFamily = "Courier"
+ };
+ Label.SetBinding(Label.TextProperty, s => s.LabelText);
+
+ Entry = new ExtendedEntry
+ {
+ Keyboard = Keyboard.Numeric,
+ IsVisible = false,
+ MaxLength = 4
+ };
+ Entry.SetBinding(Xamarin.Forms.Entry.TextProperty, s => s.PIN);
+ Entry.TextChanged += PinEntry_TextChanged;
+ }
+
+ private void PinEntry_TextChanged(object sender, TextChangedEventArgs e)
+ {
+ if(e.NewTextValue.Length >= 4)
+ {
+ _pinEnteredAction();
+ }
+ }
+
+ public Label Label { get; set; }
+ public ExtendedEntry Entry { get; set; }
+ }
+}
diff --git a/src/App/Models/Page/PinPageModel.cs b/src/App/Models/Page/PinPageModel.cs
index d3819a877..e04e59755 100644
--- a/src/App/Models/Page/PinPageModel.cs
+++ b/src/App/Models/Page/PinPageModel.cs
@@ -6,33 +6,32 @@ namespace Bit.App.Models.Page
{
public class PinPageModel : INotifyPropertyChanged
{
- private string _labelText;
- private List _pin;
-
- public PinPageModel()
- {
- LabelText = "_ _ _ _";
- PIN = new List();
- }
+ private string _pin = string.Empty;
public event PropertyChangedEventHandler PropertyChanged;
public string LabelText
{
- get { return _labelText; }
- set
+ get
{
- _labelText = value;
- PropertyChanged(this, new PropertyChangedEventArgs(nameof(LabelText)));
+ var newText = string.Empty;
+ for(int i = 0; i < 4; i++)
+ {
+ newText += _pin.Length <= i ? "- " : "● ";
+ }
+
+ return newText.TrimEnd();
}
}
- public List PIN
+
+ public string PIN
{
get { return _pin; }
set
{
_pin = value;
PropertyChanged(this, new PropertyChangedEventArgs(nameof(PIN)));
+ PropertyChanged(this, new PropertyChangedEventArgs(nameof(LabelText)));
}
}
}
diff --git a/src/App/Pages/LockPinPage.cs b/src/App/Pages/LockPinPage.cs
index 2e22b672f..b8960d0fa 100644
--- a/src/App/Pages/LockPinPage.cs
+++ b/src/App/Pages/LockPinPage.cs
@@ -8,6 +8,8 @@ using XLabs.Ioc;
using Plugin.Settings.Abstractions;
using System.Collections.Generic;
using Bit.App.Models.Page;
+using Bit.App.Controls;
+using System.Diagnostics;
namespace Bit.App.Pages
{
@@ -27,43 +29,11 @@ namespace Bit.App.Pages
}
public PinPageModel Model { get; set; } = new PinPageModel();
+ public PinControl PinControl { get; set; }
public void Init()
{
- var label = new Label
- {
- HorizontalTextAlignment = TextAlignment.Center,
- FontSize = 40,
- TextColor = Color.FromHex("333333")
- };
- label.SetBinding(Label.TextProperty, s => s.LabelText);
-
- var grid = new Grid();
- grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
- grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
- grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
- grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
-
- grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
- grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
- grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
-
- Action updateLabelAction = new Action(UpdateLabel);
- grid.Children.Add(new PinButton("1", this, updateLabelAction), 0, 0);
- grid.Children.Add(new PinButton("2", this, updateLabelAction), 1, 0);
- grid.Children.Add(new PinButton("3", this, updateLabelAction), 2, 0);
-
- grid.Children.Add(new PinButton("4", this, updateLabelAction), 0, 1);
- grid.Children.Add(new PinButton("5", this, updateLabelAction), 1, 1);
- grid.Children.Add(new PinButton("6", this, updateLabelAction), 2, 1);
-
- grid.Children.Add(new PinButton("7", this, updateLabelAction), 0, 2);
- grid.Children.Add(new PinButton("8", this, updateLabelAction), 1, 2);
- grid.Children.Add(new PinButton("9", this, updateLabelAction), 2, 2);
-
- grid.Children.Add(new Label(), 0, 3);
- grid.Children.Add(new PinButton("0", this, updateLabelAction), 1, 3);
- grid.Children.Add(new DeleteButton(this, updateLabelAction), 2, 3);
+ PinControl = new PinControl(PinEntered);
var logoutButton = new Button
{
@@ -76,7 +46,7 @@ namespace Bit.App.Pages
{
Padding = new Thickness(30, 40),
Spacing = 10,
- Children = { label, grid, logoutButton }
+ Children = { PinControl.Label, PinControl.Entry, logoutButton }
};
Title = "Verify PIN";
@@ -87,6 +57,22 @@ namespace Bit.App.Pages
protected override void OnAppearing()
{
base.OnAppearing();
+ PinControl.Entry.Focus();
+ }
+
+ protected void PinEntered()
+ {
+ if(Model.PIN == "1234")
+ {
+ PinControl.Entry.Unfocus();
+ Navigation.PopModalAsync();
+ }
+ else
+ {
+ _userDialogs.Alert("Invalid PIN. Try again.");
+ Model.PIN = string.Empty;
+ PinControl.Entry.Focus();
+ }
}
private async Task LogoutAsync()
@@ -100,60 +86,5 @@ namespace Bit.App.Pages
await Navigation.PopModalAsync();
Application.Current.MainPage = new LoginNavigationPage();
}
-
- private void UpdateLabel()
- {
- var newText = string.Empty;
- for(int i = 0; i < 4; i++)
- {
- if(Model.PIN.Count <= i)
- {
- newText += "_ ";
- }
- else
- {
- newText += "* ";
- }
- }
-
- Model.LabelText = newText.TrimEnd();
- }
-
- public class PinButton : Button
- {
- public PinButton(string text, LockPinPage page, Action updateLabelAction)
- {
- Text = text;
- Command = new Command(() =>
- {
- if(page.Model.PIN.Count >= 4)
- {
- return;
- }
-
- page.Model.PIN.Add(text);
- updateLabelAction();
- });
- CommandParameter = text;
- }
- }
-
- public class DeleteButton : Button
- {
- public DeleteButton(LockPinPage page, Action updateLabelAction)
- {
- Text = "Delete";
- Command = new Command(() =>
- {
- if(page.Model.PIN.Count == 0)
- {
- return;
- }
-
- page.Model.PIN.RemoveAt(page.Model.PIN.Count - 1);
- updateLabelAction();
- });
- }
- }
}
}
diff --git a/src/iOS/Controls/ExtendedEntryRenderer.cs b/src/iOS/Controls/ExtendedEntryRenderer.cs
index 241479dd5..fbc2403e0 100644
--- a/src/iOS/Controls/ExtendedEntryRenderer.cs
+++ b/src/iOS/Controls/ExtendedEntryRenderer.cs
@@ -23,6 +23,7 @@ namespace Bit.iOS.Controls
{
SetBorder(view);
SetMaxLength(view);
+ UpdateKeyboard();
if(view.DisableAutocapitalize)
{
@@ -79,6 +80,10 @@ namespace Bit.iOS.Controls
{
SetBorder(view);
}
+ else if(e.PropertyName == Xamarin.Forms.InputView.KeyboardProperty.PropertyName)
+ {
+ UpdateKeyboard();
+ }
}
private void SetBorder(ExtendedEntry view)
@@ -112,5 +117,17 @@ namespace Bit.iOS.Controls
return newLength <= view.MaxLength;
};
}
+
+ private void UpdateKeyboard()
+ {
+ if(Element.Keyboard == Keyboard.Numeric)
+ {
+ Control.KeyboardType = UIKeyboardType.NumberPad;
+ }
+ else
+ {
+ Control.ApplyKeyboard(Element.Keyboard);
+ }
+ }
}
}