Change password generator to use ColoredPassword (#686)

* Change password generator to use ColoredPassword

* Change ColoredPassword from FormattedString to HTML string for improved performance

* PasswordFormatter fixes

* Correct || to && condition

* Apply password colouring to history pages
This commit is contained in:
ShirokaiLon 2020-01-03 19:56:55 +00:00 committed by Kyle Spearrin
parent 051e15215d
commit a9dacd561c
7 changed files with 64 additions and 16 deletions

View file

@ -19,6 +19,7 @@
<ResourceDictionary>
<u:InverseBoolConverter x:Key="inverseBool" />
<u:DateTimeConverter x:Key="dateTime" />
<u:ColoredPasswordConverter x:Key="coloredPassword" />
<ToolbarItem Text="{u:I18n Close}" Clicked="Close_Clicked" Order="Primary" Priority="-1"
x:Name="_closeItem" x:Key="closeItem" />
<ToolbarItem Text="{u:I18n Clear}"
@ -71,7 +72,8 @@
Grid.Column="0"
Grid.Row="0"
StyleClass="list-title, list-title-platform"
Text="{Binding Password, Mode=OneWay}" />
TextType="Html"
Text="{Binding Password, Mode=OneWay, Converter={StaticResource coloredPassword}}" />
<Label LineBreakMode="TailTruncation"
Grid.Column="0"
Grid.Row="1"

View file

@ -40,7 +40,8 @@
<StackLayout Spacing="0" Padding="0">
<StackLayout StyleClass="box">
<controls:MonoLabel
Text="{Binding Password}"
Text="{Binding ColoredPassword, Mode=OneWay}"
TextType="Html"
Margin="0, 20"
StyleClass="text-lg"
HorizontalTextAlignment="Center"

View file

@ -53,7 +53,7 @@ namespace Bit.App.Pages
});
}
public FormattedString ColoredPassword => PasswordFormatter.FormatPassword(Password);
public string ColoredPassword => PasswordFormatter.FormatPassword(Password);
public bool IsPassword
{

View file

@ -23,6 +23,7 @@
<ResourceDictionary>
<u:InverseBoolConverter x:Key="inverseBool" />
<u:DateTimeConverter x:Key="dateTime" />
<u:ColoredPasswordConverter x:Key="coloredPassword" />
</ResourceDictionary>
</ContentPage.Resources>
@ -62,7 +63,8 @@
Grid.Column="0"
Grid.Row="0"
StyleClass="list-title, list-title-platform"
Text="{Binding Password, Mode=OneWay}" />
TextType="Html"
Text="{Binding Password, Mode=OneWay, Converter={StaticResource coloredPassword}}" />
<Label LineBreakMode="TailTruncation"
Grid.Column="0"
Grid.Row="1"

View file

@ -118,7 +118,8 @@
Grid.Column="0"
IsVisible="{Binding ShowPassword, Converter={StaticResource inverseBool}}" />
<controls:MonoLabel
FormattedText="{Binding ColoredPassword, Mode=OneWay}"
Text="{Binding ColoredPassword, Mode=OneWay}"
TextType="Html"
StyleClass="box-value"
Grid.Row="1"
Grid.Column="0"

View file

@ -0,0 +1,28 @@
using System;
using Xamarin.Forms;
namespace Bit.App.Utilities
{
public class ColoredPasswordConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
if(targetType != typeof(string))
{
throw new InvalidOperationException("The target must be a string.");
}
if(value == null)
{
return string.Empty;
}
return PasswordFormatter.FormatPassword((string)value);
}
public object ConvertBack(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
throw new NotSupportedException();
}
}
}

View file

@ -21,17 +21,19 @@ namespace Bit.App.Utilities
Special
}
public static FormattedString FormatPassword(string password)
public static string FormatPassword(string password)
{
if(password == null)
{
return new FormattedString();
return string.Empty;
}
var result = new FormattedString();
// Start off with an empty span to prevent possible NPEs. Due to the way the state machine
// works, this will actually always be replaced by a new span anyway.
var currentSpan = new Span();
// First two digits of returned hex code contains the alpha,
// which is not supported in HTML color, so we need to cut those out.
var numberColor = $"<span style=\"color:#{((Color)Application.Current.Resources["PasswordNumberColor"]).ToHex().Substring(2)}\">";
var specialColor = $"<span style=\"color:#{((Color)Application.Current.Resources["PasswordSpecialColor"]).ToHex().Substring(2)}\">";
var result = string.Empty;
// Start with an otherwise uncovered case so we will definitely enter the "something changed"
// state.
var currentType = CharType.None;
@ -56,24 +58,36 @@ namespace Bit.App.Utilities
// If the char type changed, build a new span to append the text to.
if(charType != currentType)
{
currentSpan = new Span();
result.Spans.Add(currentSpan);
// Close off previous span.
if (currentType != CharType.None && currentType != CharType.Normal)
{
result += "</span>";
}
currentType = charType;
// Switch the color if it is not a normal text. Otherwise leave the
// default value.
switch(currentType)
{
// Apply color style to span.
case CharType.Number:
currentSpan.TextColor = (Color)Application.Current.Resources["PasswordNumberColor"];
result += numberColor;
break;
case CharType.Special:
currentSpan.TextColor = (Color)Application.Current.Resources["PasswordSpecialColor"];
result += specialColor;
break;
}
}
currentSpan.Text += c;
result += c;
}
// Close off last span.
if (currentType != CharType.None && currentType != CharType.Normal)
{
result += "</span>";
}
return result;
}
}