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<ISettings>(),
Resolver.Resolve<ILockService>(), Resolver.Resolve<ILockService>(),
Resolver.Resolve<IGoogleAnalyticsService>(), Resolver.Resolve<IGoogleAnalyticsService>(),
Resolver.Resolve<ILocalizeService>())); Resolver.Resolve<ILocalizeService>(),
Resolver.Resolve<IAppInfoService>()));
MessagingCenter.Subscribe<Xamarin.Forms.Application>(Xamarin.Forms.Application.Current, "RateApp", (sender) => MessagingCenter.Subscribe<Xamarin.Forms.Application>(Xamarin.Forms.Application.Current, "RateApp", (sender) =>
{ {

View File

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

View File

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

View File

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

View File

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