Optimized startup tasks to only happen when necessary. Added some GA telemetry to autofill.

This commit is contained in:
Kyle Spearrin 2017-02-05 23:55:46 -05:00
parent 6629eaf485
commit 52a866147e
6 changed files with 85 additions and 27 deletions

View file

@ -77,7 +77,8 @@ namespace Bit.Android
Resolver.Resolve<ISettings>(),
Resolver.Resolve<ILockService>(),
Resolver.Resolve<IGoogleAnalyticsService>(),
Resolver.Resolve<ILocalizeService>()));
Resolver.Resolve<ILocalizeService>(),
Resolver.Resolve<IAppInfoService>()));
MessagingCenter.Subscribe<Xamarin.Forms.Application>(Xamarin.Forms.Application.Current, "RateApp", (sender) =>
{

View file

@ -20,6 +20,8 @@ namespace Bit.App
{
public class App : Application
{
private const string LastBuildKey = "LastBuild";
private string _uri;
private readonly IDatabaseService _databaseService;
private readonly IConnectivity _connectivity;
@ -31,6 +33,7 @@ namespace Bit.App
private readonly ILockService _lockService;
private readonly IGoogleAnalyticsService _googleAnalyticsService;
private readonly ILocalizeService _localizeService;
private readonly IAppInfoService _appInfoService;
private CancellationTokenSource _setMainPageCancellationTokenSource = null;
public static bool FromAutofillService { get; set; } = false;
@ -46,7 +49,8 @@ namespace Bit.App
ISettings settings,
ILockService lockService,
IGoogleAnalyticsService googleAnalyticsService,
ILocalizeService localizeService)
ILocalizeService localizeService,
IAppInfoService appInfoService)
{
_uri = uri;
_databaseService = databaseService;
@ -59,6 +63,7 @@ namespace Bit.App
_lockService = lockService;
_googleAnalyticsService = googleAnalyticsService;
_localizeService = localizeService;
_appInfoService = appInfoService;
SetCulture();
SetStyles();
@ -93,14 +98,9 @@ namespace Bit.App
Device.BeginInvokeOnMainThread(() => Logout(args));
});
MessagingCenter.Subscribe<Application>(Current, "SetMainPage", (sender) =>
MessagingCenter.Subscribe<Application, int>(Current, "SetMainPage", (sender, ms) =>
{
_setMainPageCancellationTokenSource = SetMainPageFromAutofill(_setMainPageCancellationTokenSource, 500);
});
MessagingCenter.Subscribe<Application>(Current, "SetMainPageNow", (sender) =>
{
_setMainPageCancellationTokenSource = SetMainPageFromAutofill(_setMainPageCancellationTokenSource, 0);
_setMainPageCancellationTokenSource = SetMainPageFromAutofill(_setMainPageCancellationTokenSource, ms);
});
}
@ -108,8 +108,18 @@ namespace Bit.App
{
// Handle when your app starts
await CheckLockAsync(false);
if(!FromAutofillService)
{
var lastBuild = _settings.GetValueOrDefault<string>(LastBuildKey);
if(lastBuild == null || lastBuild != _appInfoService.Build)
{
_settings.AddOrUpdateValue(LastBuildKey, _appInfoService.Build);
_databaseService.CreateTables();
}
await Task.Run(() => FullSyncAsync()).ConfigureAwait(false);
}
Debug.WriteLine("OnStart");
}

View file

@ -18,8 +18,9 @@ namespace Bit.App.Pages
private readonly IClipboardService _clipboardService;
private readonly IGoogleAnalyticsService _googleAnalyticsService;
private readonly Action<string> _passwordValueAction;
private readonly bool _fromAutofill;
public ToolsPasswordGeneratorPage(Action<string> passwordValueAction = null)
public ToolsPasswordGeneratorPage(Action<string> passwordValueAction = null, bool fromAutofill = false)
{
_userDialogs = Resolver.Resolve<IUserDialogs>();
_passwordGenerationService = Resolver.Resolve<IPasswordGenerationService>();
@ -27,6 +28,7 @@ namespace Bit.App.Pages
_clipboardService = Resolver.Resolve<IClipboardService>();
_googleAnalyticsService = Resolver.Resolve<IGoogleAnalyticsService>();
_passwordValueAction = passwordValueAction;
_fromAutofill = fromAutofill;
Init();
}
@ -110,8 +112,16 @@ namespace Bit.App.Pages
if(_passwordValueAction != null)
{
var selectToolBarItem = new ToolbarItem(AppResources.Select, null, async () =>
{
if(_fromAutofill)
{
_googleAnalyticsService.TrackExtensionEvent("SelectedGeneratedPassword");
}
else
{
_googleAnalyticsService.TrackAppEvent("SelectedGeneratedPassword");
}
_passwordValueAction(Password.Text);
await Navigation.PopForDeviceAsync();
}, ToolbarItemOrder.Default, 0);
@ -132,7 +142,14 @@ namespace Bit.App.Pages
protected override void OnAppearing()
{
base.OnAppearing();
if(_fromAutofill)
{
_googleAnalyticsService.TrackExtensionEvent("GeneratedPassword");
}
else
{
_googleAnalyticsService.TrackAppEvent("GeneratedPassword");
}
Model.Password = _passwordGenerationService.GeneratePassword();
Model.Length = _settings.GetValueOrDefault(Constants.PasswordGeneratorLength, 10).ToString();
}
@ -140,8 +157,15 @@ namespace Bit.App.Pages
private void RegenerateCell_Tapped(object sender, EventArgs e)
{
Model.Password = _passwordGenerationService.GeneratePassword();
if(_fromAutofill)
{
_googleAnalyticsService.TrackExtensionEvent("RegeneratedPassword");
}
else
{
_googleAnalyticsService.TrackAppEvent("RegeneratedPassword");
}
}
private void CopyCell_Tapped(object sender, EventArgs e)
{
@ -154,8 +178,15 @@ namespace Bit.App.Pages
}
private void CopyPassword()
{
if(_fromAutofill)
{
_googleAnalyticsService.TrackExtensionEvent("CopiedGeneratedPassword");
}
else
{
_googleAnalyticsService.TrackAppEvent("CopiedGeneratedPassword");
}
_clipboardService.CopyToClipboard(Password.Text);
_userDialogs.Toast(string.Format(AppResources.ValueHasBeenCopied, AppResources.Password));
}

View file

@ -25,11 +25,13 @@ namespace Bit.App.Pages
private readonly ISettings _settings;
private readonly string _defaultUri;
private readonly string _defaultName;
private readonly bool _fromAutofill;
public VaultAddLoginPage(string defaultUri = null, string defaultName = null)
public VaultAddLoginPage(string defaultUri = null, string defaultName = null, bool fromAutofill = false)
{
_defaultUri = defaultUri;
_defaultName = defaultName;
_fromAutofill = fromAutofill;
_loginService = Resolver.Resolve<ILoginService>();
_folderService = Resolver.Resolve<IFolderService>();
@ -163,8 +165,15 @@ namespace Bit.App.Pages
{
await Navigation.PopForDeviceAsync();
_userDialogs.Toast(AppResources.NewLoginCreated);
if(_fromAutofill)
{
_googleAnalyticsService.TrackExtensionEvent("CreatedLogin");
}
else
{
_googleAnalyticsService.TrackAppEvent("CreatedLogin");
}
}
else if(saveTask.Errors.Count() > 0)
{
await _userDialogs.AlertAsync(saveTask.Errors.First().Message, AppResources.AnErrorHasOccurred);
@ -211,7 +220,7 @@ namespace Bit.App.Pages
{
PasswordCell.Entry.Text = password;
_userDialogs.Toast(AppResources.PasswordGenerated);
});
}, _fromAutofill);
await Navigation.PushForDeviceAsync(page);
}

View file

@ -23,16 +23,15 @@ namespace Bit.App.Pages
private readonly IClipboardService _clipboardService;
private CancellationTokenSource _filterResultsCancellationTokenSource;
private readonly DomainName _domainName;
private readonly string _uri;
private readonly string _name;
private readonly bool _androidApp = false;
public VaultAutofillListLoginsPage(string uriString)
: base(true)
{
_uri = uriString;
Uri = uriString;
Uri uri;
if(!Uri.TryCreate(uriString, UriKind.Absolute, out uri) ||
if(!System.Uri.TryCreate(uriString, UriKind.Absolute, out uri) ||
!DomainName.TryParse(uri.Host, out _domainName))
{
if(uriString != null && uriString.StartsWith(Constants.AndroidAppProtocol))
@ -50,14 +49,18 @@ namespace Bit.App.Pages
_deviceInfoService = Resolver.Resolve<IDeviceInfoService>();
_userDialogs = Resolver.Resolve<IUserDialogs>();
_clipboardService = Resolver.Resolve<IClipboardService>();
GoogleAnalyticsService = Resolver.Resolve<IGoogleAnalyticsService>();
Init();
}
public ExtendedObservableCollection<VaultListPageModel.Login> PresentationLogins { get; private set; }
= new ExtendedObservableCollection<VaultListPageModel.Login>();
public StackLayout NoDataStackLayout { get; set; }
public ListView ListView { get; set; }
public ActivityIndicator LoadingIndicator { get; set; }
private IGoogleAnalyticsService GoogleAnalyticsService { get; set; }
private string Uri { get; set; }
private void Init()
{
@ -122,6 +125,7 @@ namespace Bit.App.Pages
protected override bool OnBackButtonPressed()
{
GoogleAnalyticsService.TrackExtensionEvent("BackClosed", Uri.StartsWith("http") ? "Website" : "App");
MessagingCenter.Send(Application.Current, "Autofill", (VaultListPageModel.Login)null);
return true;
}
@ -148,7 +152,7 @@ namespace Bit.App.Pages
var logins = await _loginService.GetAllAsync();
var filteredLogins = logins
.Select(s => new VaultListPageModel.Login(s))
.Where(s => (_androidApp && _domainName == null && s.Uri.Value == _uri) ||
.Where(s => (_androidApp && _domainName == null && s.Uri.Value == Uri) ||
(_domainName != null && s.BaseDomain != null && s.BaseDomain == _domainName.BaseDomain))
.OrderBy(s => s.Name)
.ThenBy(s => s.Username);
@ -167,18 +171,19 @@ namespace Bit.App.Pages
{
var login = e.SelectedItem as VaultListPageModel.Login;
if(_uri.StartsWith("http") && _deviceInfoService.Version < 21)
if(Uri.StartsWith("http") && _deviceInfoService.Version < 21)
{
MoreClickedAsync(login);
return;
}
GoogleAnalyticsService.TrackExtensionEvent("AutoFilled", Uri.StartsWith("http") ? "Website" : "App");
MessagingCenter.Send(Application.Current, "Autofill", login);
}
private async void AddLoginAsync()
{
var page = new VaultAddLoginPage(_uri, _name);
var page = new VaultAddLoginPage(Uri, _name, true);
await Navigation.PushForDeviceAsync(page);
}
@ -256,7 +261,8 @@ namespace Bit.App.Pages
private void ClickedItem(object sender, EventArgs e)
{
MessagingCenter.Send(Application.Current, "SetMainPageNow");
_page.GoogleAnalyticsService.TrackExtensionEvent("Closed", _page.Uri.StartsWith("http") ? "Website" : "App");
MessagingCenter.Send(Application.Current, "SetMainPage", 0);
}
}
}

View file

@ -66,7 +66,8 @@ namespace Bit.iOS
Resolver.Resolve<ISettings>(),
Resolver.Resolve<ILockService>(),
Resolver.Resolve<IGoogleAnalyticsService>(),
Resolver.Resolve<ILocalizeService>()));
Resolver.Resolve<ILocalizeService>(),
Resolver.Resolve<IAppInfoService>()));
// Appearance stuff