mirror of
https://github.com/bitwarden/mobile
synced 2026-01-21 03:43:17 +00:00
multibutton alert, autofill and save new uri
This commit is contained in:
@@ -23,5 +23,6 @@ namespace Bit.App.Abstractions
|
||||
void OpenAutofillSettings();
|
||||
Task LaunchAppAsync(string appName, Page page);
|
||||
Task<string> DisplayPromptAync(string title = null, string description = null, string text = null);
|
||||
Task<string> DisplayAlertAsync(string title, string message, string cancel, params string[] buttons);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ using Bit.App.Models;
|
||||
using System.Collections.Generic;
|
||||
using Bit.App.Enums;
|
||||
using static Bit.App.Models.Page.VaultListPageModel;
|
||||
using Plugin.Connectivity.Abstractions;
|
||||
|
||||
namespace Bit.App.Pages
|
||||
{
|
||||
@@ -22,6 +23,7 @@ namespace Bit.App.Pages
|
||||
private readonly IDeviceInfoService _deviceInfoService;
|
||||
private readonly ISettingsService _settingsService;
|
||||
private readonly IAppSettingsService _appSettingsService;
|
||||
public readonly IConnectivity _connectivity;
|
||||
private CancellationTokenSource _filterResultsCancellationTokenSource;
|
||||
private readonly string _name;
|
||||
private readonly AppOptions _appOptions;
|
||||
@@ -47,6 +49,7 @@ namespace Bit.App.Pages
|
||||
_settingsService = Resolver.Resolve<ISettingsService>();
|
||||
_appSettingsService = Resolver.Resolve<IAppSettingsService>();
|
||||
GoogleAnalyticsService = Resolver.Resolve<IGoogleAnalyticsService>();
|
||||
_connectivity = Resolver.Resolve<IConnectivity>();
|
||||
|
||||
Init();
|
||||
}
|
||||
@@ -237,17 +240,57 @@ namespace Bit.App.Pages
|
||||
}
|
||||
else
|
||||
{
|
||||
bool doAutofill = true;
|
||||
var autofillResponse = AppResources.Yes;
|
||||
if(cipher.Fuzzy)
|
||||
{
|
||||
doAutofill = await DisplayAlert(null,
|
||||
string.Format(AppResources.BitwardenAutofillServiceMatchConfirm, _name),
|
||||
AppResources.Yes, AppResources.No);
|
||||
var options = new List<string> { AppResources.Yes };
|
||||
if(cipher.Type == CipherType.Login && _connectivity.IsConnected)
|
||||
{
|
||||
options.Add(AppResources.YesAndSave);
|
||||
}
|
||||
|
||||
autofillResponse = await DeviceActionService.DisplayAlertAsync(null,
|
||||
string.Format(AppResources.BitwardenAutofillServiceMatchConfirm, _name), AppResources.No,
|
||||
options.ToArray());
|
||||
}
|
||||
|
||||
if(doAutofill)
|
||||
if(autofillResponse == AppResources.YesAndSave && cipher.Type == CipherType.Login)
|
||||
{
|
||||
GoogleAnalyticsService.TrackExtensionEvent("AutoFilled", Uri.StartsWith("http") ? "Website" : "App");
|
||||
if(!_connectivity.IsConnected)
|
||||
{
|
||||
Helpers.AlertNoConnection(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
var uris = cipher.CipherModel.Login?.Uris?.ToList();
|
||||
if(uris == null)
|
||||
{
|
||||
uris = new List<LoginUri>();
|
||||
}
|
||||
|
||||
uris.Add(new LoginUri
|
||||
{
|
||||
Uri = Uri.Encrypt(cipher.CipherModel.OrganizationId),
|
||||
Match = null
|
||||
});
|
||||
|
||||
cipher.CipherModel.Login.Uris = uris;
|
||||
|
||||
await DeviceActionService.ShowLoadingAsync(AppResources.Saving);
|
||||
var saveTask = await _cipherService.SaveAsync(cipher.CipherModel);
|
||||
await DeviceActionService.HideLoadingAsync();
|
||||
|
||||
if(saveTask.Succeeded)
|
||||
{
|
||||
GoogleAnalyticsService.TrackAppEvent("AddedLoginUriDuringAutofill");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(autofillResponse == AppResources.Yes || autofillResponse == AppResources.YesAndSave)
|
||||
{
|
||||
GoogleAnalyticsService.TrackExtensionEvent("AutoFilled",
|
||||
Uri.StartsWith("http") ? "Website" : "App");
|
||||
DeviceActionService.Autofill(cipher);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -403,8 +403,14 @@ namespace Bit.App.Pages
|
||||
string selection = null;
|
||||
if(!string.IsNullOrWhiteSpace(_uri))
|
||||
{
|
||||
var options = new List<string> { AppResources.Autofill };
|
||||
if(cipher.Type == Enums.CipherType.Login && _connectivity.IsConnected)
|
||||
{
|
||||
options.Add(AppResources.AutofillAndSave);
|
||||
}
|
||||
options.Add(AppResources.View);
|
||||
selection = await DisplayActionSheet(AppResources.AutofillOrView, AppResources.Cancel, null,
|
||||
AppResources.Autofill, AppResources.View);
|
||||
options.ToArray());
|
||||
}
|
||||
|
||||
if(selection == AppResources.View || string.IsNullOrWhiteSpace(_uri))
|
||||
@@ -412,8 +418,40 @@ namespace Bit.App.Pages
|
||||
var page = new VaultViewCipherPage(cipher.Type, cipher.Id);
|
||||
await Navigation.PushForDeviceAsync(page);
|
||||
}
|
||||
else if(selection == AppResources.Autofill)
|
||||
else if(selection == AppResources.Autofill || selection == AppResources.AutofillAndSave)
|
||||
{
|
||||
if(selection == AppResources.AutofillAndSave)
|
||||
{
|
||||
if(!_connectivity.IsConnected)
|
||||
{
|
||||
Helpers.AlertNoConnection(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
var uris = cipher.CipherModel.Login?.Uris?.ToList();
|
||||
if(uris == null)
|
||||
{
|
||||
uris = new List<Models.LoginUri>();
|
||||
}
|
||||
|
||||
uris.Add(new Models.LoginUri
|
||||
{
|
||||
Uri = _uri.Encrypt(cipher.CipherModel.OrganizationId),
|
||||
Match = null
|
||||
});
|
||||
|
||||
cipher.CipherModel.Login.Uris = uris;
|
||||
|
||||
await _deviceActionService.ShowLoadingAsync(AppResources.Saving);
|
||||
var saveTask = await _cipherService.SaveAsync(cipher.CipherModel);
|
||||
await _deviceActionService.HideLoadingAsync();
|
||||
if(saveTask.Succeeded)
|
||||
{
|
||||
_googleAnalyticsService.TrackAppEvent("AddedLoginUriDuringAutofill");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(_deviceInfoService.Version < 21)
|
||||
{
|
||||
Helpers.CipherMoreClickedAsync(this, cipher, !string.IsNullOrWhiteSpace(_uri));
|
||||
|
||||
18
src/App/Resources/AppResources.Designer.cs
generated
18
src/App/Resources/AppResources.Designer.cs
generated
@@ -330,6 +330,15 @@ namespace Bit.App.Resources {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Auto-fill and save.
|
||||
/// </summary>
|
||||
public static string AutofillAndSave {
|
||||
get {
|
||||
return ResourceManager.GetString("AutofillAndSave", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Do you want to auto-fill or view this item?.
|
||||
/// </summary>
|
||||
@@ -3291,6 +3300,15 @@ namespace Bit.App.Resources {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Yes, and Save.
|
||||
/// </summary>
|
||||
public static string YesAndSave {
|
||||
get {
|
||||
return ResourceManager.GetString("YesAndSave", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to To continue, hold your YubiKey NEO against the back of the device or insert your YubiKey into your device's USB port, then touch its button..
|
||||
/// </summary>
|
||||
|
||||
@@ -1283,4 +1283,10 @@
|
||||
<value>Match Detection</value>
|
||||
<comment>URI match detection for auto-fill.</comment>
|
||||
</data>
|
||||
<data name="YesAndSave" xml:space="preserve">
|
||||
<value>Yes, and Save</value>
|
||||
</data>
|
||||
<data name="AutofillAndSave" xml:space="preserve">
|
||||
<value>Auto-fill and save</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -93,7 +93,8 @@ namespace Bit.App.Services
|
||||
return ciphers.Where(c => cipherIds.Contains(c.Id));
|
||||
}
|
||||
|
||||
public async Task<Tuple<IEnumerable<Cipher>, IEnumerable<Cipher>, IEnumerable<Cipher>>> GetAllAsync(string uriString)
|
||||
public async Task<Tuple<IEnumerable<Cipher>, IEnumerable<Cipher>, IEnumerable<Cipher>>> GetAllAsync(
|
||||
string uriString)
|
||||
{
|
||||
if(string.IsNullOrWhiteSpace(uriString))
|
||||
{
|
||||
@@ -173,42 +174,42 @@ namespace Bit.App.Services
|
||||
break;
|
||||
}
|
||||
|
||||
var added = false;
|
||||
var match = false;
|
||||
switch(u.Match)
|
||||
{
|
||||
case null:
|
||||
case Enums.UriMatchType.Domain:
|
||||
added = CheckDefaultUriMatch(cipher, loginUriString, matchingLogins, matchingFuzzyLogins,
|
||||
match = CheckDefaultUriMatch(cipher, loginUriString, matchingLogins, matchingFuzzyLogins,
|
||||
matchingDomainsArray, matchingFuzzyDomainsArray, mobileApp, mobileAppSearchTerms);
|
||||
break;
|
||||
case Enums.UriMatchType.Host:
|
||||
var urlHost = Helpers.GetUrlHost(uriString);
|
||||
added = urlHost != null && urlHost == Helpers.GetUrlHost(loginUriString);
|
||||
if(added)
|
||||
match = urlHost != null && urlHost == Helpers.GetUrlHost(loginUriString);
|
||||
if(match)
|
||||
{
|
||||
matchingLogins.Add(cipher);
|
||||
AddMatchingLogin(cipher, matchingLogins, matchingFuzzyLogins);
|
||||
}
|
||||
break;
|
||||
case Enums.UriMatchType.Exact:
|
||||
added = uriString == loginUriString;
|
||||
if(added)
|
||||
match = uriString == loginUriString;
|
||||
if(match)
|
||||
{
|
||||
matchingLogins.Add(cipher);
|
||||
AddMatchingLogin(cipher, matchingLogins, matchingFuzzyLogins);
|
||||
}
|
||||
break;
|
||||
case Enums.UriMatchType.StartsWith:
|
||||
added = uriString.StartsWith(loginUriString);
|
||||
if(added)
|
||||
match = uriString.StartsWith(loginUriString);
|
||||
if(match)
|
||||
{
|
||||
matchingLogins.Add(cipher);
|
||||
AddMatchingLogin(cipher, matchingLogins, matchingFuzzyLogins);
|
||||
}
|
||||
break;
|
||||
case Enums.UriMatchType.RegularExpression:
|
||||
var regex = new Regex(loginUriString, RegexOptions.IgnoreCase, TimeSpan.FromSeconds(1));
|
||||
added = regex.IsMatch(uriString);
|
||||
if(added)
|
||||
match = regex.IsMatch(uriString);
|
||||
if(match)
|
||||
{
|
||||
matchingLogins.Add(cipher);
|
||||
AddMatchingLogin(cipher, matchingLogins, matchingFuzzyLogins);
|
||||
}
|
||||
break;
|
||||
case Enums.UriMatchType.Never:
|
||||
@@ -216,7 +217,7 @@ namespace Bit.App.Services
|
||||
break;
|
||||
}
|
||||
|
||||
if(added)
|
||||
if(match)
|
||||
{
|
||||
break;
|
||||
}
|
||||
@@ -436,21 +437,21 @@ namespace Bit.App.Services
|
||||
{
|
||||
if(Array.IndexOf(matchingDomainsArray, loginUriString) >= 0)
|
||||
{
|
||||
matchingLogins.Add(cipher);
|
||||
AddMatchingLogin(cipher, matchingLogins, matchingFuzzyLogins);
|
||||
return true;
|
||||
}
|
||||
else if(mobileApp && Array.IndexOf(matchingFuzzyDomainsArray, loginUriString) >= 0)
|
||||
{
|
||||
matchingFuzzyLogins.Add(cipher);
|
||||
return true;
|
||||
AddMatchingFuzzyLogin(cipher, matchingLogins, matchingFuzzyLogins);
|
||||
return false;
|
||||
}
|
||||
else if(!mobileApp)
|
||||
{
|
||||
var info = InfoFromMobileAppUri(loginUriString);
|
||||
if(info?.Item1 != null && Array.IndexOf(matchingDomainsArray, info.Item1) >= 0)
|
||||
{
|
||||
matchingFuzzyLogins.Add(cipher);
|
||||
return true;
|
||||
AddMatchingFuzzyLogin(cipher, matchingLogins, matchingFuzzyLogins);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -462,13 +463,13 @@ namespace Bit.App.Services
|
||||
|
||||
if(Array.IndexOf(matchingDomainsArray, loginDomainName) >= 0)
|
||||
{
|
||||
matchingLogins.Add(cipher);
|
||||
AddMatchingLogin(cipher, matchingLogins, matchingFuzzyLogins);
|
||||
return true;
|
||||
}
|
||||
else if(mobileApp && Array.IndexOf(matchingFuzzyDomainsArray, loginDomainName) >= 0)
|
||||
{
|
||||
matchingFuzzyLogins.Add(cipher);
|
||||
return true;
|
||||
AddMatchingFuzzyLogin(cipher, matchingLogins, matchingFuzzyLogins);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -491,13 +492,31 @@ namespace Bit.App.Services
|
||||
|
||||
if(addedFromSearchTerm)
|
||||
{
|
||||
matchingFuzzyLogins.Add(cipher);
|
||||
return true;
|
||||
AddMatchingFuzzyLogin(cipher, matchingLogins, matchingFuzzyLogins);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void AddMatchingLogin(Cipher cipher, List<Cipher> matchingLogins, List<Cipher> matchingFuzzyLogins)
|
||||
{
|
||||
if(matchingFuzzyLogins.Contains(cipher))
|
||||
{
|
||||
matchingFuzzyLogins.Remove(cipher);
|
||||
}
|
||||
|
||||
matchingLogins.Add(cipher);
|
||||
}
|
||||
|
||||
private void AddMatchingFuzzyLogin(Cipher cipher, List<Cipher> matchingLogins, List<Cipher> matchingFuzzyLogins)
|
||||
{
|
||||
if(!matchingFuzzyLogins.Contains(cipher) && !matchingLogins.Contains(cipher))
|
||||
{
|
||||
matchingFuzzyLogins.Add(cipher);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -521,5 +521,11 @@ namespace Bit.App.Utilities
|
||||
|
||||
return host;
|
||||
}
|
||||
|
||||
public static void AlertNoConnection(Page page)
|
||||
{
|
||||
page.DisplayAlert(AppResources.InternetConnectionRequiredTitle,
|
||||
AppResources.InternetConnectionRequiredMessage, AppResources.Ok);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user