add uri and add buttons of search page

This commit is contained in:
Kyle Spearrin 2017-11-27 13:22:42 -05:00
parent 186f839569
commit f5896be699
6 changed files with 144 additions and 47 deletions

View file

@ -67,6 +67,7 @@
<Compile Include="Abstractions\Services\ISecureStorageService.cs" /> <Compile Include="Abstractions\Services\ISecureStorageService.cs" />
<Compile Include="Abstractions\Services\ISqlService.cs" /> <Compile Include="Abstractions\Services\ISqlService.cs" />
<Compile Include="Constants.cs" /> <Compile Include="Constants.cs" />
<Compile Include="Controls\AddCipherToolbarItem.cs" />
<Compile Include="Controls\HybridWebView.cs" /> <Compile Include="Controls\HybridWebView.cs" />
<Compile Include="Controls\ExtendedToolbarItem.cs" /> <Compile Include="Controls\ExtendedToolbarItem.cs" />
<Compile Include="Controls\DismissModalToolBarItem.cs" /> <Compile Include="Controls\DismissModalToolBarItem.cs" />

View file

@ -0,0 +1,16 @@
using Bit.App.Resources;
using Bit.App.Utilities;
using Xamarin.Forms;
namespace Bit.App.Controls
{
public class AddCipherToolbarItem : ExtendedToolbarItem
{
public AddCipherToolbarItem(Page page, string folderId)
: base(() => Helpers.AddCipher(page, folderId))
{
Text = AppResources.Add;
Icon = "plus.png";
}
}
}

View file

@ -30,6 +30,7 @@ namespace Bit.App.Pages
private readonly IAppInfoService _appInfoService; private readonly IAppInfoService _appInfoService;
private readonly IDeviceInfoService _deviceInfo; private readonly IDeviceInfoService _deviceInfo;
private readonly IDeviceActionService _deviceActionService; private readonly IDeviceActionService _deviceActionService;
private readonly string _defaultFolderId;
private readonly string _defaultUri; private readonly string _defaultUri;
private readonly string _defaultName; private readonly string _defaultName;
private readonly string _defaultUsername; private readonly string _defaultUsername;
@ -60,9 +61,10 @@ namespace Bit.App.Pages
Init(); Init();
} }
public VaultAddCipherPage(CipherType type, string defaultUri = null, public VaultAddCipherPage(CipherType type, string defaultUri = null, string defaultName = null,
string defaultName = null, bool fromAutofill = false, bool doInit = true) bool fromAutofill = false, bool doInit = true, string defaultFolderId = null)
{ {
_defaultFolderId = defaultFolderId;
_type = type; _type = type;
_defaultUri = defaultUri; _defaultUri = defaultUri;
_defaultName = defaultName; _defaultName = defaultName;
@ -146,11 +148,19 @@ namespace Bit.App.Pages
var folderOptions = new List<string> { AppResources.FolderNone }; var folderOptions = new List<string> { AppResources.FolderNone };
Folders = _folderService.GetAllAsync().GetAwaiter().GetResult() Folders = _folderService.GetAllAsync().GetAwaiter().GetResult()
.OrderBy(f => f.Name?.Decrypt()).ToList(); .OrderBy(f => f.Name?.Decrypt()).ToList();
var selectedIndex = 0;
var i = 1;
foreach(var folder in Folders) foreach(var folder in Folders)
{ {
if(folder.Id == _defaultFolderId)
{
selectedIndex = i;
}
folderOptions.Add(folder.Name.Decrypt()); folderOptions.Add(folder.Name.Decrypt());
i++;
} }
FolderCell = new FormPickerCell(AppResources.Folder, folderOptions.ToArray()); FolderCell = new FormPickerCell(AppResources.Folder, folderOptions.ToArray());
FolderCell.Picker.SelectedIndex = selectedIndex;
// Favorite // Favorite
FavoriteCell = new ExtendedSwitchCell { Text = AppResources.Favorite }; FavoriteCell = new ExtendedSwitchCell { Text = AppResources.Favorite };

View file

@ -12,7 +12,6 @@ using Plugin.Settings.Abstractions;
using Plugin.Connectivity.Abstractions; using Plugin.Connectivity.Abstractions;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading; using System.Threading;
using Bit.App.Enums;
using static Bit.App.Models.Page.VaultListPageModel; using static Bit.App.Models.Page.VaultListPageModel;
namespace Bit.App.Pages namespace Bit.App.Pages
@ -57,13 +56,13 @@ namespace Bit.App.Pages
public ListView ListView { get; set; } public ListView ListView { get; set; }
public StackLayout NoDataStackLayout { get; set; } public StackLayout NoDataStackLayout { get; set; }
public ActivityIndicator LoadingIndicator { get; set; } public ActivityIndicator LoadingIndicator { get; set; }
private AddCipherToolBarItem AddCipherItem { get; set; } private AddCipherToolbarItem AddCipherItem { get; set; }
private SearchToolBarItem SearchItem { get; set; } private SearchToolBarItem SearchItem { get; set; }
private void Init() private void Init()
{ {
SearchItem = new SearchToolBarItem(this); SearchItem = new SearchToolBarItem(this);
AddCipherItem = new AddCipherToolBarItem(this); AddCipherItem = new AddCipherToolbarItem(this, null);
ToolbarItems.Add(SearchItem); ToolbarItems.Add(SearchItem);
ToolbarItems.Add(AddCipherItem); ToolbarItems.Add(AddCipherItem);
@ -102,7 +101,7 @@ namespace Bit.App.Pages
var addCipherButton = new ExtendedButton var addCipherButton = new ExtendedButton
{ {
Text = AppResources.AddAnItem, Text = AppResources.AddAnItem,
Command = new Command(() => AddCipher()), Command = new Command(() => Helpers.AddCipher(this, null)),
Style = (Style)Application.Current.Resources["btn-primaryAccent"] Style = (Style)Application.Current.Resources["btn-primaryAccent"]
}; };
@ -135,6 +134,37 @@ namespace Bit.App.Pages
SearchItem?.InitEvents(); SearchItem?.InitEvents();
_filterResultsCancellationTokenSource = FetchAndLoadVault(); _filterResultsCancellationTokenSource = FetchAndLoadVault();
if(_connectivity.IsConnected && Device.RuntimePlatform == Device.iOS)
{
var pushPromptShow = _settings.GetValueOrDefault(Constants.PushInitialPromptShown, false);
Action registerAction = () =>
{
var lastPushRegistration =
_settings.GetValueOrDefault(Constants.PushLastRegistrationDate, DateTime.MinValue);
if(!pushPromptShow || DateTime.UtcNow - lastPushRegistration > TimeSpan.FromDays(1))
{
_pushNotification.Register();
}
};
if(!pushPromptShow)
{
_settings.AddOrUpdateValue(Constants.PushInitialPromptShown, true);
_userDialogs.Alert(new AlertConfig
{
Message = AppResources.PushNotificationAlert,
Title = AppResources.EnableAutomaticSyncing,
OnAction = registerAction,
OkText = AppResources.OkGotIt
});
}
else
{
// Check push registration once per day
registerAction();
}
}
} }
protected override void OnDisappearing() protected override void OnDisappearing()
@ -236,49 +266,12 @@ namespace Bit.App.Pages
((ListView)sender).SelectedItem = null; ((ListView)sender).SelectedItem = null;
} }
private async void AddCipher()
{
var type = await _userDialogs.ActionSheetAsync(AppResources.SelectTypeAdd, AppResources.Cancel, null, null,
AppResources.TypeLogin, AppResources.TypeCard, AppResources.TypeIdentity, AppResources.TypeSecureNote);
var selectedType = CipherType.SecureNote;
if(type == AppResources.Cancel)
{
return;
}
else if(type == AppResources.TypeLogin)
{
selectedType = CipherType.Login;
}
else if(type == AppResources.TypeCard)
{
selectedType = CipherType.Card;
}
else if(type == AppResources.TypeIdentity)
{
selectedType = CipherType.Identity;
}
var page = new VaultAddCipherPage(selectedType);
await Navigation.PushForDeviceAsync(page);
}
private async void Search() private async void Search()
{ {
var page = new ExtendedNavigationPage(new VaultSearchCiphersPage()); var page = new ExtendedNavigationPage(new VaultSearchCiphersPage());
await Navigation.PushModalAsync(page); await Navigation.PushModalAsync(page);
} }
private class AddCipherToolBarItem : ExtendedToolbarItem
{
public AddCipherToolBarItem(VaultListGroupingsPage page)
: base(() => page.AddCipher())
{
Text = AppResources.Add;
Icon = "plus.png";
}
}
private class SearchToolBarItem : ExtendedToolbarItem private class SearchToolBarItem : ExtendedToolbarItem
{ {
public SearchToolBarItem(VaultListGroupingsPage page) public SearchToolBarItem(VaultListGroupingsPage page)

View file

@ -24,15 +24,17 @@ namespace Bit.App.Pages
private readonly ISettings _settings; private readonly ISettings _settings;
private readonly IAppSettingsService _appSettingsService; private readonly IAppSettingsService _appSettingsService;
private readonly IGoogleAnalyticsService _googleAnalyticsService; private readonly IGoogleAnalyticsService _googleAnalyticsService;
private readonly IDeviceActionService _deviceActionService;
private CancellationTokenSource _filterResultsCancellationTokenSource; private CancellationTokenSource _filterResultsCancellationTokenSource;
private readonly bool _favorites = false; private readonly bool _favorites = false;
private readonly bool _folder = false; private readonly bool _folder = false;
private readonly string _folderId = null; private readonly string _folderId = null;
private readonly string _collectionId = null; private readonly string _collectionId = null;
private readonly string _groupingName = null; private readonly string _groupingName = null;
private readonly string _uri = null;
public VaultSearchCiphersPage(bool folder = false, string folderId = null, public VaultSearchCiphersPage(bool folder = false, string folderId = null,
string collectionId = null, string groupingName = null, bool favorites = false) string collectionId = null, string groupingName = null, bool favorites = false, string uri = null)
: base(true) : base(true)
{ {
_folder = folder; _folder = folder;
@ -40,6 +42,7 @@ namespace Bit.App.Pages
_collectionId = collectionId; _collectionId = collectionId;
_favorites = favorites; _favorites = favorites;
_groupingName = groupingName; _groupingName = groupingName;
_uri = uri;
_cipherService = Resolver.Resolve<ICipherService>(); _cipherService = Resolver.Resolve<ICipherService>();
_connectivity = Resolver.Resolve<IConnectivity>(); _connectivity = Resolver.Resolve<IConnectivity>();
@ -48,6 +51,7 @@ namespace Bit.App.Pages
_settings = Resolver.Resolve<ISettings>(); _settings = Resolver.Resolve<ISettings>();
_appSettingsService = Resolver.Resolve<IAppSettingsService>(); _appSettingsService = Resolver.Resolve<IAppSettingsService>();
_googleAnalyticsService = Resolver.Resolve<IGoogleAnalyticsService>(); _googleAnalyticsService = Resolver.Resolve<IGoogleAnalyticsService>();
_deviceActionService = Resolver.Resolve<IDeviceActionService>();
Init(); Init();
} }
@ -58,9 +62,16 @@ namespace Bit.App.Pages
public ListView ListView { get; set; } public ListView ListView { get; set; }
public SearchBar Search { get; set; } public SearchBar Search { get; set; }
public StackLayout ResultsStackLayout { get; set; } public StackLayout ResultsStackLayout { get; set; }
private AddCipherToolbarItem AddCipherItem { get; set; }
private void Init() private void Init()
{ {
if(!string.IsNullOrWhiteSpace(_uri) || _folder || !string.IsNullOrWhiteSpace(_folderId))
{
AddCipherItem = new AddCipherToolbarItem(this, _folderId);
ToolbarItems.Add(AddCipherItem);
}
ListView = new ListView(ListViewCachingStrategy.RecycleElement) ListView = new ListView(ListViewCachingStrategy.RecycleElement)
{ {
IsGroupingEnabled = true, IsGroupingEnabled = true,
@ -70,7 +81,7 @@ namespace Bit.App.Pages
nameof(Section<Cipher>.Count))), nameof(Section<Cipher>.Count))),
GroupShortNameBinding = new Binding(nameof(Section<Cipher>.Name)), GroupShortNameBinding = new Binding(nameof(Section<Cipher>.Name)),
ItemTemplate = new DataTemplate(() => new VaultListViewCell( ItemTemplate = new DataTemplate(() => new VaultListViewCell(
(Cipher c) => Helpers.CipherMoreClickedAsync(this, c, false))) (Cipher c) => Helpers.CipherMoreClickedAsync(this, c, !string.IsNullOrWhiteSpace(_uri))))
}; };
if(Device.RuntimePlatform == Device.iOS) if(Device.RuntimePlatform == Device.iOS)
@ -187,6 +198,18 @@ namespace Bit.App.Pages
} }
} }
protected override bool OnBackButtonPressed()
{
if(string.IsNullOrWhiteSpace(_uri))
{
return false;
}
_googleAnalyticsService.TrackExtensionEvent("BackClosed", _uri.StartsWith("http") ? "Website" : "App");
_deviceActionService.CloseAutofill();
return true;
}
protected override void OnAppearing() protected override void OnAppearing()
{ {
base.OnAppearing(); base.OnAppearing();
@ -198,6 +221,7 @@ namespace Bit.App.Pages
} }
}); });
AddCipherItem?.InitEvents();
ListView.ItemSelected += CipherSelected; ListView.ItemSelected += CipherSelected;
Search.TextChanged += SearchBar_TextChanged; Search.TextChanged += SearchBar_TextChanged;
Search.SearchButtonPressed += SearchBar_SearchButtonPressed; Search.SearchButtonPressed += SearchBar_SearchButtonPressed;
@ -214,6 +238,7 @@ namespace Bit.App.Pages
base.OnDisappearing(); base.OnDisappearing();
MessagingCenter.Unsubscribe<ISyncService, bool>(_syncService, "SyncCompleted"); MessagingCenter.Unsubscribe<ISyncService, bool>(_syncService, "SyncCompleted");
AddCipherItem?.Dispose();
ListView.ItemSelected -= CipherSelected; ListView.ItemSelected -= CipherSelected;
Search.TextChanged -= SearchBar_TextChanged; Search.TextChanged -= SearchBar_TextChanged;
Search.SearchButtonPressed -= SearchBar_SearchButtonPressed; Search.SearchButtonPressed -= SearchBar_SearchButtonPressed;
@ -291,8 +316,32 @@ namespace Bit.App.Pages
return; return;
} }
var page = new VaultViewCipherPage(cipher.Type, cipher.Id); string selection = null;
await Navigation.PushForDeviceAsync(page); if(!string.IsNullOrWhiteSpace(_uri))
{
selection = await DisplayActionSheet(AppResources.AutofillOrView, AppResources.Cancel, null,
AppResources.Autofill, AppResources.View);
}
if(selection == AppResources.View || string.IsNullOrWhiteSpace(_uri))
{
var page = new VaultViewCipherPage(cipher.Type, cipher.Id);
await Navigation.PushForDeviceAsync(page);
}
else if(selection == AppResources.Autofill)
{
if(_deviceInfoService.Version < 21)
{
Helpers.CipherMoreClickedAsync(this, cipher, !string.IsNullOrWhiteSpace(_uri));
}
else
{
_googleAnalyticsService.TrackExtensionEvent("AutoFilled",
_uri.StartsWith("http") ? "Website" : "App");
_deviceActionService.Autofill(cipher);
}
}
((ListView)sender).SelectedItem = null; ((ListView)sender).SelectedItem = null;
} }
} }

View file

@ -144,5 +144,33 @@ namespace Bit.App.Utilities
Resolver.Resolve<IDeviceActionService>().CopyToClipboard(copyText); Resolver.Resolve<IDeviceActionService>().CopyToClipboard(copyText);
Resolver.Resolve<IUserDialogs>().Toast(string.Format(AppResources.ValueHasBeenCopied, alertLabel)); Resolver.Resolve<IUserDialogs>().Toast(string.Format(AppResources.ValueHasBeenCopied, alertLabel));
} }
public static async void AddCipher(Page page, string folderId)
{
var type = await Resolver.Resolve<IUserDialogs>().ActionSheetAsync(
AppResources.SelectTypeAdd, AppResources.Cancel, null, null, AppResources.TypeLogin,
AppResources.TypeCard, AppResources.TypeIdentity, AppResources.TypeSecureNote);
var selectedType = CipherType.SecureNote;
if(type == AppResources.Cancel)
{
return;
}
else if(type == AppResources.TypeLogin)
{
selectedType = CipherType.Login;
}
else if(type == AppResources.TypeCard)
{
selectedType = CipherType.Card;
}
else if(type == AppResources.TypeIdentity)
{
selectedType = CipherType.Identity;
}
var addPage = new VaultAddCipherPage(selectedType, defaultFolderId: folderId);
await page.Navigation.PushForDeviceAsync(addPage);
}
} }
} }