mirror of
https://github.com/bitwarden/android.git
synced 2024-10-31 15:15:34 +03:00
more updates to autofill flow
This commit is contained in:
parent
ddec7ab643
commit
36d4ce8718
6 changed files with 166 additions and 42 deletions
|
@ -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;
|
||||
|
|
|
@ -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(() =>
|
||||
{
|
||||
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);
|
||||
MessagingCenter.Send(Application.Current, "Autofill", login as VaultListPageModel.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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,19 +397,22 @@ 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");
|
||||
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)
|
||||
{
|
||||
var buttons = new List<string> { AppResources.View, AppResources.Edit };
|
||||
|
|
45
src/App/Resources/AppResources.Designer.cs
generated
45
src/App/Resources/AppResources.Designer.cs
generated
|
@ -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 "{0}"..
|
||||
/// </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 "Ok" on the following prompt when asked to enable push notifications..
|
||||
/// </summary>
|
||||
|
|
|
@ -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>
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue