mirror of
https://github.com/bitwarden/android.git
synced 2024-12-21 00:31:58 +03:00
autofill WIP into main activity. created login selection page
This commit is contained in:
parent
61e0379eb3
commit
26667c0a59
10 changed files with 266 additions and 51 deletions
|
@ -298,7 +298,6 @@
|
||||||
</Reference>
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="AutofillSelectLoginActivity.cs" />
|
|
||||||
<Compile Include="AutofillActivity.cs" />
|
<Compile Include="AutofillActivity.cs" />
|
||||||
<Compile Include="Controls\CustomSearchBarRenderer.cs" />
|
<Compile Include="Controls\CustomSearchBarRenderer.cs" />
|
||||||
<Compile Include="Controls\CustomButtonRenderer.cs" />
|
<Compile Include="Controls\CustomButtonRenderer.cs" />
|
||||||
|
|
|
@ -7,17 +7,17 @@ using Android.App;
|
||||||
using Android.Content;
|
using Android.Content;
|
||||||
using Android.OS;
|
using Android.OS;
|
||||||
using Android.Runtime;
|
using Android.Runtime;
|
||||||
using Bit.App.Models;
|
using Android.Views;
|
||||||
|
|
||||||
namespace Bit.Android
|
namespace Bit.Android
|
||||||
{
|
{
|
||||||
[Activity(Label = "bitwarden Autofill",
|
[Activity(Label = "bitwarden",
|
||||||
|
Icon = "@drawable/icon",
|
||||||
LaunchMode = global::Android.Content.PM.LaunchMode.SingleInstance,
|
LaunchMode = global::Android.Content.PM.LaunchMode.SingleInstance,
|
||||||
Theme = "@style/android:Theme.Material.Light")]
|
WindowSoftInputMode = SoftInput.StateHidden)]
|
||||||
public class AutofillActivity : Activity
|
public class AutofillActivity : Activity
|
||||||
{
|
{
|
||||||
private string _lastQueriedUri;
|
private string _lastQueriedUri;
|
||||||
|
|
||||||
public static Credentials LastCredentials;
|
public static Credentials LastCredentials;
|
||||||
|
|
||||||
protected override void OnCreate(Bundle bundle)
|
protected override void OnCreate(Bundle bundle)
|
||||||
|
@ -25,12 +25,11 @@ namespace Bit.Android
|
||||||
base.OnCreate(bundle);
|
base.OnCreate(bundle);
|
||||||
_lastQueriedUri = Intent.GetStringExtra("uri");
|
_lastQueriedUri = Intent.GetStringExtra("uri");
|
||||||
|
|
||||||
var intent = new Intent(this, typeof(AutofillSelectLoginActivity));
|
var intent = new Intent(this, typeof(MainActivity));
|
||||||
intent.PutExtra("uri", _lastQueriedUri);
|
intent.PutExtra("uri", _lastQueriedUri);
|
||||||
StartActivityForResult(intent, 123);
|
StartActivityForResult(intent, 123);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent data)
|
protected override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent data)
|
||||||
{
|
{
|
||||||
base.OnActivityResult(requestCode, resultCode, data);
|
base.OnActivityResult(requestCode, resultCode, data);
|
||||||
|
|
|
@ -1,37 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
using Android.App;
|
|
||||||
using Android.Content;
|
|
||||||
using Android.OS;
|
|
||||||
|
|
||||||
namespace Bit.Android
|
|
||||||
{
|
|
||||||
[Activity(LaunchMode = global::Android.Content.PM.LaunchMode.SingleInstance)]
|
|
||||||
public class AutofillSelectLoginActivity : Activity
|
|
||||||
{
|
|
||||||
protected override void OnCreate(Bundle bundle)
|
|
||||||
{
|
|
||||||
base.OnCreate(bundle);
|
|
||||||
var uri = Intent.GetStringExtra("uri");
|
|
||||||
|
|
||||||
Intent data = new Intent();
|
|
||||||
data.PutExtra("uri", uri);
|
|
||||||
data.PutExtra("username", "user123");
|
|
||||||
data.PutExtra("password", "pass123");
|
|
||||||
|
|
||||||
if(Parent == null)
|
|
||||||
{
|
|
||||||
SetResult(Result.Ok, data);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Parent.SetResult(Result.Ok, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
Finish();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -14,6 +14,7 @@ using System.Reflection;
|
||||||
using Xamarin.Forms.Platform.Android;
|
using Xamarin.Forms.Platform.Android;
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Bit.App.Models.Page;
|
||||||
|
|
||||||
namespace Bit.Android
|
namespace Bit.Android
|
||||||
{
|
{
|
||||||
|
@ -27,6 +28,12 @@ namespace Bit.Android
|
||||||
|
|
||||||
protected override void OnCreate(Bundle bundle)
|
protected override void OnCreate(Bundle bundle)
|
||||||
{
|
{
|
||||||
|
var uri = Intent.GetStringExtra("uri");
|
||||||
|
if(uri != null && !Resolver.IsSet)
|
||||||
|
{
|
||||||
|
MainApplication.SetIoc(Application);
|
||||||
|
}
|
||||||
|
|
||||||
var policy = new StrictMode.ThreadPolicy.Builder().PermitAll().Build();
|
var policy = new StrictMode.ThreadPolicy.Builder().PermitAll().Build();
|
||||||
StrictMode.SetThreadPolicy(policy);
|
StrictMode.SetThreadPolicy(policy);
|
||||||
|
|
||||||
|
@ -55,6 +62,7 @@ namespace Bit.Android
|
||||||
.SetValue(null, Color.FromHex("d2d6de"));
|
.SetValue(null, Color.FromHex("d2d6de"));
|
||||||
|
|
||||||
LoadApplication(new App.App(
|
LoadApplication(new App.App(
|
||||||
|
uri,
|
||||||
Resolver.Resolve<IAuthService>(),
|
Resolver.Resolve<IAuthService>(),
|
||||||
Resolver.Resolve<IConnectivity>(),
|
Resolver.Resolve<IConnectivity>(),
|
||||||
Resolver.Resolve<IUserDialogs>(),
|
Resolver.Resolve<IUserDialogs>(),
|
||||||
|
@ -70,6 +78,31 @@ namespace Bit.Android
|
||||||
{
|
{
|
||||||
RateApp();
|
RateApp();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
MessagingCenter.Subscribe<Xamarin.Forms.Application, VaultListPageModel.Login>(
|
||||||
|
Xamarin.Forms.Application.Current, "Autofill", (sender, args) =>
|
||||||
|
{
|
||||||
|
ReturnCredentials(args);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ReturnCredentials(VaultListPageModel.Login login)
|
||||||
|
{
|
||||||
|
Intent data = new Intent();
|
||||||
|
data.PutExtra("uri", login.Uri.Value);
|
||||||
|
data.PutExtra("username", login.Username);
|
||||||
|
data.PutExtra("password", login.Password.Value);
|
||||||
|
|
||||||
|
if(Parent == null)
|
||||||
|
{
|
||||||
|
SetResult(Result.Ok, data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Parent.SetResult(Result.Ok, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
Finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnPause()
|
protected override void OnPause()
|
||||||
|
|
|
@ -43,7 +43,7 @@ namespace Bit.Android
|
||||||
|
|
||||||
if(!Resolver.IsSet)
|
if(!Resolver.IsSet)
|
||||||
{
|
{
|
||||||
SetIoc();
|
SetIoc(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,16 +178,16 @@ namespace Bit.Android
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetIoc()
|
public static void SetIoc(Application application)
|
||||||
{
|
{
|
||||||
UserDialogs.Init(this);
|
UserDialogs.Init(application);
|
||||||
|
|
||||||
var container = new UnityContainer();
|
var container = new UnityContainer();
|
||||||
|
|
||||||
container
|
container
|
||||||
// Android Stuff
|
// Android Stuff
|
||||||
.RegisterInstance(ApplicationContext)
|
.RegisterInstance(application.ApplicationContext)
|
||||||
.RegisterInstance<Application>(this)
|
.RegisterInstance<Application>(application)
|
||||||
// Services
|
// Services
|
||||||
.RegisterType<IDatabaseService, DatabaseService>(new ContainerControlledLifetimeManager())
|
.RegisterType<IDatabaseService, DatabaseService>(new ContainerControlledLifetimeManager())
|
||||||
.RegisterType<ISqlService, SqlService>(new ContainerControlledLifetimeManager())
|
.RegisterType<ISqlService, SqlService>(new ContainerControlledLifetimeManager())
|
||||||
|
|
|
@ -19,6 +19,7 @@ namespace Bit.App
|
||||||
{
|
{
|
||||||
public class App : Application
|
public class App : Application
|
||||||
{
|
{
|
||||||
|
private readonly string _uri;
|
||||||
private readonly IDatabaseService _databaseService;
|
private readonly IDatabaseService _databaseService;
|
||||||
private readonly IConnectivity _connectivity;
|
private readonly IConnectivity _connectivity;
|
||||||
private readonly IUserDialogs _userDialogs;
|
private readonly IUserDialogs _userDialogs;
|
||||||
|
@ -31,6 +32,7 @@ namespace Bit.App
|
||||||
private readonly ILocalizeService _localizeService;
|
private readonly ILocalizeService _localizeService;
|
||||||
|
|
||||||
public App(
|
public App(
|
||||||
|
string uri,
|
||||||
IAuthService authService,
|
IAuthService authService,
|
||||||
IConnectivity connectivity,
|
IConnectivity connectivity,
|
||||||
IUserDialogs userDialogs,
|
IUserDialogs userDialogs,
|
||||||
|
@ -42,6 +44,7 @@ namespace Bit.App
|
||||||
IGoogleAnalyticsService googleAnalyticsService,
|
IGoogleAnalyticsService googleAnalyticsService,
|
||||||
ILocalizeService localizeService)
|
ILocalizeService localizeService)
|
||||||
{
|
{
|
||||||
|
_uri = uri;
|
||||||
_databaseService = databaseService;
|
_databaseService = databaseService;
|
||||||
_connectivity = connectivity;
|
_connectivity = connectivity;
|
||||||
_userDialogs = userDialogs;
|
_userDialogs = userDialogs;
|
||||||
|
@ -56,7 +59,11 @@ namespace Bit.App
|
||||||
SetCulture();
|
SetCulture();
|
||||||
SetStyles();
|
SetStyles();
|
||||||
|
|
||||||
if(authService.IsAuthenticated)
|
if(authService.IsAuthenticated && _uri != null)
|
||||||
|
{
|
||||||
|
MainPage = new ExtendedNavigationPage(new VaultAutofillListLoginsPage(_uri));
|
||||||
|
}
|
||||||
|
else if(authService.IsAuthenticated)
|
||||||
{
|
{
|
||||||
MainPage = new MainPage();
|
MainPage = new MainPage();
|
||||||
}
|
}
|
||||||
|
|
|
@ -134,6 +134,7 @@
|
||||||
<Compile Include="Pages\Settings\SettingsSyncPage.cs" />
|
<Compile Include="Pages\Settings\SettingsSyncPage.cs" />
|
||||||
<Compile Include="Pages\Settings\SettingsPage.cs" />
|
<Compile Include="Pages\Settings\SettingsPage.cs" />
|
||||||
<Compile Include="Pages\Settings\SettingsListFoldersPage.cs" />
|
<Compile Include="Pages\Settings\SettingsListFoldersPage.cs" />
|
||||||
|
<Compile Include="Pages\Vault\VaultAutofillListLoginsPage.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="Abstractions\Repositories\ILoginRepository.cs" />
|
<Compile Include="Abstractions\Repositories\ILoginRepository.cs" />
|
||||||
<Compile Include="Repositories\ApiRepository.cs" />
|
<Compile Include="Repositories\ApiRepository.cs" />
|
||||||
|
|
|
@ -8,6 +8,8 @@ namespace Bit.App.Models.Page
|
||||||
{
|
{
|
||||||
public class Login
|
public class Login
|
||||||
{
|
{
|
||||||
|
private string _baseDomain;
|
||||||
|
|
||||||
public Login(Models.Login login)
|
public Login(Models.Login login)
|
||||||
{
|
{
|
||||||
Id = login.Id;
|
Id = login.Id;
|
||||||
|
@ -24,6 +26,37 @@ namespace Bit.App.Models.Page
|
||||||
public string Username { get; set; }
|
public string Username { get; set; }
|
||||||
public Lazy<string> Password { get; set; }
|
public Lazy<string> Password { get; set; }
|
||||||
public Lazy<string> Uri { get; set; }
|
public Lazy<string> Uri { get; set; }
|
||||||
|
|
||||||
|
public string BaseDomain
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if(_baseDomain != null)
|
||||||
|
{
|
||||||
|
return _baseDomain;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(string.IsNullOrWhiteSpace(Uri.Value))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Uri uri;
|
||||||
|
if(!System.Uri.TryCreate(Uri.Value, UriKind.Absolute, out uri))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
DomainName domain;
|
||||||
|
if(!DomainName.TryParse(uri.Host, out domain))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
_baseDomain = domain.BaseDomain;
|
||||||
|
return _baseDomain;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Folder : List<Login>
|
public class Folder : List<Login>
|
||||||
|
|
179
src/App/Pages/Vault/VaultAutofillListLoginsPage.cs
Normal file
179
src/App/Pages/Vault/VaultAutofillListLoginsPage.cs
Normal file
|
@ -0,0 +1,179 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Acr.UserDialogs;
|
||||||
|
using Bit.App.Abstractions;
|
||||||
|
using Bit.App.Controls;
|
||||||
|
using Bit.App.Models.Page;
|
||||||
|
using Bit.App.Resources;
|
||||||
|
using Xamarin.Forms;
|
||||||
|
using XLabs.Ioc;
|
||||||
|
using Bit.App.Utilities;
|
||||||
|
using PushNotification.Plugin.Abstractions;
|
||||||
|
using Plugin.Settings.Abstractions;
|
||||||
|
using Plugin.Connectivity.Abstractions;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using Bit.App.Models;
|
||||||
|
|
||||||
|
namespace Bit.App.Pages
|
||||||
|
{
|
||||||
|
public class VaultAutofillListLoginsPage : ExtendedContentPage
|
||||||
|
{
|
||||||
|
private readonly IFolderService _folderService;
|
||||||
|
private readonly ILoginService _loginService;
|
||||||
|
private readonly IUserDialogs _userDialogs;
|
||||||
|
private readonly IConnectivity _connectivity;
|
||||||
|
private readonly IClipboardService _clipboardService;
|
||||||
|
private readonly ISyncService _syncService;
|
||||||
|
private readonly IPushNotification _pushNotification;
|
||||||
|
private readonly IDeviceInfoService _deviceInfoService;
|
||||||
|
private readonly ISettings _settings;
|
||||||
|
private CancellationTokenSource _filterResultsCancellationTokenSource;
|
||||||
|
private readonly DomainName _domainName;
|
||||||
|
|
||||||
|
public VaultAutofillListLoginsPage(string uriString)
|
||||||
|
: base(true)
|
||||||
|
{
|
||||||
|
Uri uri;
|
||||||
|
if(Uri.TryCreate(uriString, UriKind.RelativeOrAbsolute, out uri) &&
|
||||||
|
DomainName.TryParse(uri.Host, out _domainName)) { }
|
||||||
|
|
||||||
|
_folderService = Resolver.Resolve<IFolderService>();
|
||||||
|
_loginService = Resolver.Resolve<ILoginService>();
|
||||||
|
_connectivity = Resolver.Resolve<IConnectivity>();
|
||||||
|
_userDialogs = Resolver.Resolve<IUserDialogs>();
|
||||||
|
_clipboardService = Resolver.Resolve<IClipboardService>();
|
||||||
|
_syncService = Resolver.Resolve<ISyncService>();
|
||||||
|
_pushNotification = Resolver.Resolve<IPushNotification>();
|
||||||
|
_deviceInfoService = Resolver.Resolve<IDeviceInfoService>();
|
||||||
|
_settings = Resolver.Resolve<ISettings>();
|
||||||
|
|
||||||
|
Init();
|
||||||
|
}
|
||||||
|
public ExtendedObservableCollection<VaultListPageModel.Login> PresentationLogins { get; private set; }
|
||||||
|
= new ExtendedObservableCollection<VaultListPageModel.Login>();
|
||||||
|
|
||||||
|
public ListView ListView { get; set; }
|
||||||
|
|
||||||
|
private void Init()
|
||||||
|
{
|
||||||
|
MessagingCenter.Subscribe<Application, bool>(Application.Current, "SyncCompleted", (sender, success) =>
|
||||||
|
{
|
||||||
|
if(success)
|
||||||
|
{
|
||||||
|
_filterResultsCancellationTokenSource = FetchAndLoadVault();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ToolbarItems.Add(new AddLoginToolBarItem(this));
|
||||||
|
|
||||||
|
ListView = new ListView(ListViewCachingStrategy.RecycleElement)
|
||||||
|
{
|
||||||
|
ItemsSource = PresentationLogins,
|
||||||
|
HasUnevenRows = true,
|
||||||
|
ItemTemplate = new DataTemplate(() => new VaultListViewCell(this))
|
||||||
|
};
|
||||||
|
|
||||||
|
if(Device.OS == TargetPlatform.iOS)
|
||||||
|
{
|
||||||
|
ListView.RowHeight = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ListView.ItemSelected += LoginSelected;
|
||||||
|
|
||||||
|
Title = AppResources.Logins;
|
||||||
|
|
||||||
|
Content = ListView;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnAppearing()
|
||||||
|
{
|
||||||
|
base.OnAppearing();
|
||||||
|
_filterResultsCancellationTokenSource = FetchAndLoadVault();
|
||||||
|
}
|
||||||
|
|
||||||
|
private CancellationTokenSource FetchAndLoadVault()
|
||||||
|
{
|
||||||
|
var cts = new CancellationTokenSource();
|
||||||
|
_settings.AddOrUpdateValue(Constants.FirstVaultLoad, false);
|
||||||
|
|
||||||
|
if(PresentationLogins.Count > 0 && _syncService.SyncInProgress)
|
||||||
|
{
|
||||||
|
return cts;
|
||||||
|
}
|
||||||
|
|
||||||
|
_filterResultsCancellationTokenSource?.Cancel();
|
||||||
|
|
||||||
|
Task.Run(async () =>
|
||||||
|
{
|
||||||
|
var logins = await _loginService.GetAllAsync();
|
||||||
|
var filteredLogins = logins
|
||||||
|
.Select(s => new VaultListPageModel.Login(s))
|
||||||
|
.Where(s => s.BaseDomain != null && s.BaseDomain == _domainName.BaseDomain)
|
||||||
|
.OrderBy(s => s.Name)
|
||||||
|
.ThenBy(s => s.Username)
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
PresentationLogins.ResetWithRange(filteredLogins);
|
||||||
|
}, cts.Token);
|
||||||
|
|
||||||
|
return cts;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoginSelected(object sender, SelectedItemChangedEventArgs e)
|
||||||
|
{
|
||||||
|
var login = e.SelectedItem as VaultListPageModel.Login;
|
||||||
|
MessagingCenter.Send(Application.Current, "Autofill", login);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void AddLogin()
|
||||||
|
{
|
||||||
|
var page = new VaultAddLoginPage();
|
||||||
|
await Navigation.PushForDeviceAsync(page);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class AddLoginToolBarItem : ToolbarItem
|
||||||
|
{
|
||||||
|
private readonly VaultAutofillListLoginsPage _page;
|
||||||
|
|
||||||
|
public AddLoginToolBarItem(VaultAutofillListLoginsPage page)
|
||||||
|
{
|
||||||
|
_page = page;
|
||||||
|
Text = AppResources.Add;
|
||||||
|
Icon = "plus";
|
||||||
|
Clicked += ClickedItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ClickedItem(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
_page.AddLogin();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class VaultListViewCell : LabeledDetailCell
|
||||||
|
{
|
||||||
|
private VaultAutofillListLoginsPage _page;
|
||||||
|
|
||||||
|
public static readonly BindableProperty LoginParameterProperty = BindableProperty.Create(nameof(LoginParameter),
|
||||||
|
typeof(VaultListPageModel.Login), typeof(VaultListViewCell), null);
|
||||||
|
|
||||||
|
public VaultListViewCell(VaultAutofillListLoginsPage page)
|
||||||
|
{
|
||||||
|
_page = page;
|
||||||
|
|
||||||
|
SetBinding(LoginParameterProperty, new Binding("."));
|
||||||
|
Label.SetBinding<VaultListPageModel.Login>(Label.TextProperty, s => s.Name);
|
||||||
|
Detail.SetBinding<VaultListPageModel.Login>(Label.TextProperty, s => s.Username);
|
||||||
|
|
||||||
|
BackgroundColor = Color.White;
|
||||||
|
}
|
||||||
|
|
||||||
|
public VaultListPageModel.Login LoginParameter
|
||||||
|
{
|
||||||
|
get { return GetValue(LoginParameterProperty) as VaultListPageModel.Login; }
|
||||||
|
set { SetValue(LoginParameterProperty, value); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -56,6 +56,7 @@ namespace Bit.iOS
|
||||||
manager.DisableMetricsManager = manager.DisableFeedbackManager = manager.DisableUpdateManager = true;
|
manager.DisableMetricsManager = manager.DisableFeedbackManager = manager.DisableUpdateManager = true;
|
||||||
|
|
||||||
LoadApplication(new App.App(
|
LoadApplication(new App.App(
|
||||||
|
null,
|
||||||
Resolver.Resolve<IAuthService>(),
|
Resolver.Resolve<IAuthService>(),
|
||||||
Resolver.Resolve<IConnectivity>(),
|
Resolver.Resolve<IConnectivity>(),
|
||||||
Resolver.Resolve<IUserDialogs>(),
|
Resolver.Resolve<IUserDialogs>(),
|
||||||
|
|
Loading…
Reference in a new issue