more updates to autofill flow

This commit is contained in:
Kyle Spearrin 2017-02-13 22:10:34 -05:00
parent ddec7ab643
commit 36d4ce8718
6 changed files with 166 additions and 42 deletions

View file

@ -8,8 +8,6 @@ namespace Bit.App.Models.Page
{
public class Login
{
private string _baseDomain;
public Login(Models.Login login)
{
Id = login.Id;
@ -28,6 +26,17 @@ namespace Bit.App.Models.Page
public Lazy<string> Uri { get; set; }
}
public class AutofillLogin : Login
{
public AutofillLogin(Models.Login login, bool fuzzy = false)
: base(login)
{
Fuzzy = fuzzy;
}
public bool Fuzzy { get; set; }
}
public class Folder : List<Login>
{
public Folder(Models.Folder folder)
@ -45,9 +54,9 @@ namespace Bit.App.Models.Page
public string Name { get; set; } = AppResources.FolderNone;
}
public class AutofillGrouping : List<Login>
public class AutofillGrouping : List<AutofillLogin>
{
public AutofillGrouping(List<Login> logins, string name)
public AutofillGrouping(List<AutofillLogin> logins, string name)
{
AddRange(logins);
Name = name;

View file

@ -152,25 +152,35 @@ namespace Bit.App.Pages
Task.Run(async () =>
{
var autofillGroupings = new List<VaultListPageModel.AutofillGrouping>();
var logins = await _loginService.GetAllAsync(Uri);
var normalLogins = logins.Item1.Select(l => new VaultListPageModel.Login(l))
.OrderBy(s => s.Name)
.ThenBy(s => s.Username)
.ToList();
var fuzzyLogins = logins.Item2.Select(l => new VaultListPageModel.Login(l))
.OrderBy(s => s.Name)
.ThenBy(s => s.Username)
.ToList();
var autofillGroupings = new List<VaultListPageModel.AutofillGrouping>
var normalLogins = logins?.Item1.Select(l => new VaultListPageModel.AutofillLogin(l, false))
.OrderBy(s => s.Name)
.ThenBy(s => s.Username)
.ToList();
if(normalLogins?.Any() ?? false)
{
new VaultListPageModel.AutofillGrouping(normalLogins, "Matching"),
new VaultListPageModel.AutofillGrouping(fuzzyLogins, "Possible Matches")
};
autofillGroupings.Add(new VaultListPageModel.AutofillGrouping(normalLogins, AppResources.MatchingLogins));
}
var fuzzyLogins = logins?.Item2.Select(l => new VaultListPageModel.AutofillLogin(l, true))
.OrderBy(s => s.Name)
.ThenBy(s => s.Username)
.ToList();
if(fuzzyLogins?.Any() ?? false)
{
autofillGroupings.Add(new VaultListPageModel.AutofillGrouping(fuzzyLogins,
AppResources.PossibleMatchingLogins));
}
Device.BeginInvokeOnMainThread(() =>
{
PresentationLogins.ResetWithRange(autofillGroupings);
if(autofillGroupings.Any())
{
PresentationLogins.ResetWithRange(autofillGroupings);
}
AdjustContent();
});
}, cts.Token);
@ -178,18 +188,36 @@ namespace Bit.App.Pages
return cts;
}
private void LoginSelected(object sender, SelectedItemChangedEventArgs e)
private async void LoginSelected(object sender, SelectedItemChangedEventArgs e)
{
var login = e.SelectedItem as VaultListPageModel.Login;
var login = e.SelectedItem as VaultListPageModel.AutofillLogin;
if(login == null)
{
return;
}
if(Uri.StartsWith("http") && _deviceInfoService.Version < 21)
{
MoreClickedAsync(login);
return;
}
else
{
bool doAutofill = true;
if(login.Fuzzy)
{
doAutofill = await _userDialogs.ConfirmAsync(
string.Format(AppResources.BitwardenAutofillServiceMatchConfirm, _name),
okText: AppResources.Yes, cancelText: AppResources.No);
}
if(doAutofill)
{
GoogleAnalyticsService.TrackExtensionEvent("AutoFilled", Uri.StartsWith("http") ? "Website" : "App");
MessagingCenter.Send(Application.Current, "Autofill", login as VaultListPageModel.Login);
}
}
GoogleAnalyticsService.TrackExtensionEvent("AutoFilled", Uri.StartsWith("http") ? "Website" : "App");
MessagingCenter.Send(Application.Current, "Autofill", login);
((ListView)sender).SelectedItem = null;
}
private async void AddLoginAsync()
@ -272,7 +300,8 @@ namespace Bit.App.Pages
private void ClickedItem(object sender, EventArgs e)
{
_page.GoogleAnalyticsService.TrackExtensionEvent("CloseToSearch", _page.Uri.StartsWith("http") ? "Website" : "App");
_page.GoogleAnalyticsService.TrackExtensionEvent("CloseToSearch",
_page.Uri.StartsWith("http") ? "Website" : "App");
Application.Current.MainPage = new MainPage(_page.Uri);
}
}

View file

@ -28,6 +28,7 @@ namespace Bit.App.Pages
private readonly IPushNotification _pushNotification;
private readonly IDeviceInfoService _deviceInfoService;
private readonly ISettings _settings;
private readonly IGoogleAnalyticsService _googleAnalyticsService;
private readonly bool _favorites;
private bool _loadExistingData;
private CancellationTokenSource _filterResultsCancellationTokenSource;
@ -45,6 +46,7 @@ namespace Bit.App.Pages
_pushNotification = Resolver.Resolve<IPushNotification>();
_deviceInfoService = Resolver.Resolve<IDeviceInfoService>();
_settings = Resolver.Resolve<ISettings>();
_googleAnalyticsService = Resolver.Resolve<IGoogleAnalyticsService>();
var cryptoService = Resolver.Resolve<ICryptoService>();
_loadExistingData = !_settings.GetValueOrDefault(Constants.FirstVaultLoad, true) || !cryptoService.KeyChanged;
@ -272,7 +274,7 @@ namespace Bit.App.Pages
return false;
}
//GoogleAnalyticsService.TrackExtensionEvent("BackClosed", Uri.StartsWith("http") ? "Website" : "App");
_googleAnalyticsService.TrackExtensionEvent("BackClosed", Uri.StartsWith("http") ? "Website" : "App");
MessagingCenter.Send(Application.Current, "Autofill", (VaultListPageModel.Login)null);
return true;
}
@ -378,12 +380,16 @@ namespace Bit.App.Pages
private async void LoginSelected(object sender, SelectedItemChangedEventArgs e)
{
var login = e.SelectedItem as VaultListPageModel.Login;
if(login == null)
{
return;
}
string selection = null;
if(!string.IsNullOrWhiteSpace(Uri))
{
selection = await DisplayActionSheet("Auto-fill or view?", AppResources.Cancel, null,
"Autofill", AppResources.View);
selection = await DisplayActionSheet(AppResources.AutofillOrView, AppResources.Cancel, null,
AppResources.Autofill, AppResources.View);
}
if(selection == AppResources.View || string.IsNullOrWhiteSpace(Uri))
@ -391,17 +397,20 @@ namespace Bit.App.Pages
var page = new VaultViewLoginPage(login.Id);
await Navigation.PushForDeviceAsync(page);
}
else if(selection == "Autofill")
else if(selection == AppResources.Autofill)
{
if(Uri.StartsWith("http") && _deviceInfoService.Version < 21)
{
MoreClickedAsync(login);
return;
}
//GoogleAnalyticsService.TrackExtensionEvent("AutoFilled", Uri.StartsWith("http") ? "Website" : "App");
MessagingCenter.Send(Application.Current, "Autofill", login);
else
{
_googleAnalyticsService.TrackExtensionEvent("AutoFilled", Uri.StartsWith("http") ? "Website" : "App");
MessagingCenter.Send(Application.Current, "Autofill", login);
}
}
((ListView)sender).SelectedItem = null;
}
private async void MoreClickedAsync(VaultListPageModel.Login login)

View file

@ -142,6 +142,15 @@ namespace Bit.App.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to Auto-fill.
/// </summary>
public static string Autofill {
get {
return ResourceManager.GetString("Autofill", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Use the bitwarden accessibility service to auto-fill your logins across apps and the web..
/// </summary>
@ -151,6 +160,15 @@ namespace Bit.App.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to Do you want to auto-fill or view this login?.
/// </summary>
public static string AutofillOrView {
get {
return ResourceManager.GetString("AutofillOrView", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Auto-fill Service.
/// </summary>
@ -250,6 +268,15 @@ namespace Bit.App.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to Are you sure you want to auto-fill this login? It is not a complete match for &quot;{0}&quot;..
/// </summary>
public static string BitwardenAutofillServiceMatchConfirm {
get {
return ResourceManager.GetString("BitwardenAutofillServiceMatchConfirm", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to When you see a bitwarden auto-fill notification, you can tap it to launch the auto-fill service..
/// </summary>
@ -1204,6 +1231,15 @@ namespace Bit.App.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to Matching Logins.
/// </summary>
public static string MatchingLogins {
get {
return ResourceManager.GetString("MatchingLogins", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Minimum Numbers.
/// </summary>
@ -1456,6 +1492,15 @@ namespace Bit.App.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to Possible Matching Logins.
/// </summary>
public static string PossibleMatchingLogins {
get {
return ResourceManager.GetString("PossibleMatchingLogins", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to bitwarden keeps your vault automatically synced by using push notifications. For the best possible experience, please select &quot;Ok&quot; on the following prompt when asked to enable push notifications..
/// </summary>

View file

@ -795,4 +795,19 @@
<data name="BitwardenAutofillServiceAlert" xml:space="preserve">
<value>The easiest way to add new logins to your vault is from the bitwarden Auto-fill Service. Learn more about using the bitwarden Auto-fill Service by navigating to the "Tools" screen.</value>
</data>
<data name="Autofill" xml:space="preserve">
<value>Auto-fill</value>
</data>
<data name="AutofillOrView" xml:space="preserve">
<value>Do you want to auto-fill or view this login?</value>
</data>
<data name="BitwardenAutofillServiceMatchConfirm" xml:space="preserve">
<value>Are you sure you want to auto-fill this login? It is not a complete match for "{0}".</value>
</data>
<data name="MatchingLogins" xml:space="preserve">
<value>Matching Logins</value>
</data>
<data name="PossibleMatchingLogins" xml:space="preserve">
<value>Possible Matching Logins</value>
</data>
</root>

View file

@ -70,7 +70,7 @@ namespace Bit.App.Services
{
if(domainName == null)
{
androidApp = uriString.StartsWith(Constants.AndroidAppProtocol);
androidApp = UriIsAndroidApp(uriString);
}
}
@ -79,16 +79,7 @@ namespace Bit.App.Services
return null;
}
string androidAppWebUriString = null;
if(androidApp)
{
var androidUriParts = uriString.Replace(Constants.AndroidAppProtocol, string.Empty).Split('.');
if(androidUriParts.Length >= 2)
{
androidAppWebUriString = string.Join(".", androidUriParts[1], androidUriParts[0]);
}
}
var androidAppWebUriString = WebUriFromAndroidAppUri(uriString);
var eqDomains = (await _settingsService.GetEquivalentDomainsAsync()).Select(d => d.ToArray());
var matchingDomains = new List<string>();
var matchingFuzzyDomains = new List<string>();
@ -150,6 +141,11 @@ namespace Bit.App.Services
matchingFuzzyLogins.Add(new Login(login));
continue;
}
else if(!androidApp && Array.IndexOf(matchingDomainsArray, WebUriFromAndroidAppUri(loginUriString)) >= 0)
{
matchingFuzzyLogins.Add(new Login(login));
continue;
}
Uri loginUri;
DomainName loginDomainName;
@ -223,5 +219,26 @@ namespace Bit.App.Services
return response;
}
private string WebUriFromAndroidAppUri(string androidAppUriString)
{
if(!UriIsAndroidApp(androidAppUriString))
{
return null;
}
var androidUriParts = androidAppUriString.Replace(Constants.AndroidAppProtocol, string.Empty).Split('.');
if(androidUriParts.Length >= 2)
{
return string.Join(".", androidUriParts[1], androidUriParts[0]);
}
return null;
}
private bool UriIsAndroidApp(string uriString)
{
return uriString.StartsWith(Constants.AndroidAppProtocol);
}
}
}