mirror of
https://github.com/bitwarden/android.git
synced 2024-12-20 08:12:26 +03:00
tearing down event handlers on page disappears
This commit is contained in:
parent
fb564fa817
commit
22f3bd1073
9 changed files with 154 additions and 90 deletions
|
@ -58,6 +58,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\ExtendedToolbarItem.cs" />
|
||||||
<Compile Include="Controls\DismissModalToolBarItem.cs" />
|
<Compile Include="Controls\DismissModalToolBarItem.cs" />
|
||||||
<Compile Include="Controls\ExtendedEditor.cs" />
|
<Compile Include="Controls\ExtendedEditor.cs" />
|
||||||
<Compile Include="Controls\ExtendedButton.cs" />
|
<Compile Include="Controls\ExtendedButton.cs" />
|
||||||
|
|
|
@ -4,14 +4,13 @@ using Xamarin.Forms;
|
||||||
|
|
||||||
namespace Bit.App.Controls
|
namespace Bit.App.Controls
|
||||||
{
|
{
|
||||||
public class DismissModalToolBarItem : ToolbarItem, IDisposable
|
public class DismissModalToolBarItem : ExtendedToolbarItem, IDisposable
|
||||||
{
|
{
|
||||||
private readonly ContentPage _page;
|
private readonly ContentPage _page;
|
||||||
private readonly Action _cancelClickedAction;
|
|
||||||
|
|
||||||
public DismissModalToolBarItem(ContentPage page, string text = null, Action cancelClickedAction = null)
|
public DismissModalToolBarItem(ContentPage page, string text = null, Action cancelClickedAction = null)
|
||||||
|
: base(cancelClickedAction)
|
||||||
{
|
{
|
||||||
_cancelClickedAction = cancelClickedAction;
|
|
||||||
_page = page;
|
_page = page;
|
||||||
// TODO: init and dispose events from pages
|
// TODO: init and dispose events from pages
|
||||||
InitEvents();
|
InitEvents();
|
||||||
|
@ -19,20 +18,10 @@ namespace Bit.App.Controls
|
||||||
Priority = -1;
|
Priority = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void ClickedItem(object sender, EventArgs e)
|
protected async override void ClickedItem(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
_cancelClickedAction?.Invoke();
|
base.ClickedItem(sender, e);
|
||||||
await _page.Navigation.PopModalAsync();
|
await _page.Navigation.PopModalAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void InitEvents()
|
|
||||||
{
|
|
||||||
Clicked += ClickedItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
Clicked -= ClickedItem;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
30
src/App/Controls/ExtendedToolbarItem.cs
Normal file
30
src/App/Controls/ExtendedToolbarItem.cs
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
using System;
|
||||||
|
using Xamarin.Forms;
|
||||||
|
|
||||||
|
namespace Bit.App.Controls
|
||||||
|
{
|
||||||
|
public class ExtendedToolbarItem : ToolbarItem, IDisposable
|
||||||
|
{
|
||||||
|
public ExtendedToolbarItem(Action clickAction = null)
|
||||||
|
{
|
||||||
|
ClickAction = clickAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action ClickAction { get; set; }
|
||||||
|
|
||||||
|
protected virtual void ClickedItem(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
ClickAction?.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void InitEvents()
|
||||||
|
{
|
||||||
|
Clicked += ClickedItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Clicked -= ClickedItem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,21 +6,17 @@ namespace Bit.App.Controls
|
||||||
{
|
{
|
||||||
public class VaultListViewCell : LabeledDetailCell
|
public class VaultListViewCell : LabeledDetailCell
|
||||||
{
|
{
|
||||||
private Action<VaultListPageModel.Login> _moreClickedAction;
|
|
||||||
|
|
||||||
public static readonly BindableProperty LoginParameterProperty = BindableProperty.Create(nameof(LoginParameter),
|
public static readonly BindableProperty LoginParameterProperty = BindableProperty.Create(nameof(LoginParameter),
|
||||||
typeof(VaultListPageModel.Login), typeof(VaultListViewCell), null);
|
typeof(VaultListPageModel.Login), typeof(VaultListViewCell), null);
|
||||||
|
|
||||||
public VaultListViewCell(Action<VaultListPageModel.Login> moreClickedAction)
|
public VaultListViewCell(Action<VaultListPageModel.Login> moreClickedAction)
|
||||||
{
|
{
|
||||||
_moreClickedAction = moreClickedAction;
|
|
||||||
|
|
||||||
SetBinding(LoginParameterProperty, new Binding("."));
|
SetBinding(LoginParameterProperty, new Binding("."));
|
||||||
Label.SetBinding<VaultListPageModel.Login>(Label.TextProperty, s => s.Name);
|
Label.SetBinding<VaultListPageModel.Login>(Label.TextProperty, s => s.Name);
|
||||||
Detail.SetBinding<VaultListPageModel.Login>(Label.TextProperty, s => s.Username);
|
Detail.SetBinding<VaultListPageModel.Login>(Label.TextProperty, s => s.Username);
|
||||||
|
|
||||||
Button.Image = "more";
|
Button.Image = "more";
|
||||||
Button.Command = new Command(() => ShowMore());
|
Button.Command = new Command(() => moreClickedAction?.Invoke(LoginParameter));
|
||||||
Button.BackgroundColor = Color.Transparent;
|
Button.BackgroundColor = Color.Transparent;
|
||||||
|
|
||||||
BackgroundColor = Color.White;
|
BackgroundColor = Color.White;
|
||||||
|
@ -31,10 +27,5 @@ namespace Bit.App.Controls
|
||||||
get { return GetValue(LoginParameterProperty) as VaultListPageModel.Login; }
|
get { return GetValue(LoginParameterProperty) as VaultListPageModel.Login; }
|
||||||
set { SetValue(LoginParameterProperty, value); }
|
set { SetValue(LoginParameterProperty, value); }
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ShowMore()
|
|
||||||
{
|
|
||||||
_moreClickedAction?.Invoke(LoginParameter);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,9 @@ namespace Bit.App.Pages
|
||||||
public FormEntryCell PasswordCell { get; set; }
|
public FormEntryCell PasswordCell { get; set; }
|
||||||
public FormEntryCell ConfirmPasswordCell { get; set; }
|
public FormEntryCell ConfirmPasswordCell { get; set; }
|
||||||
public FormEntryCell PasswordHintCell { get; set; }
|
public FormEntryCell PasswordHintCell { get; set; }
|
||||||
|
public StackLayout StackLayout { get; set; }
|
||||||
|
public Label PasswordLabel { get; set; }
|
||||||
|
public Label HintLabel { get; set; }
|
||||||
|
|
||||||
private void Init()
|
private void Init()
|
||||||
{
|
{
|
||||||
|
@ -71,7 +74,7 @@ namespace Bit.App.Pages
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var passwordLabel = new Label
|
PasswordLabel = new Label
|
||||||
{
|
{
|
||||||
Text = AppResources.MasterPasswordDescription,
|
Text = AppResources.MasterPasswordDescription,
|
||||||
LineBreakMode = LineBreakMode.WordWrap,
|
LineBreakMode = LineBreakMode.WordWrap,
|
||||||
|
@ -93,7 +96,7 @@ namespace Bit.App.Pages
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var hintLabel = new Label
|
HintLabel = new Label
|
||||||
{
|
{
|
||||||
Text = AppResources.MasterPasswordHintDescription,
|
Text = AppResources.MasterPasswordHintDescription,
|
||||||
LineBreakMode = LineBreakMode.WordWrap,
|
LineBreakMode = LineBreakMode.WordWrap,
|
||||||
|
@ -102,21 +105,15 @@ namespace Bit.App.Pages
|
||||||
Margin = new Thickness(15, (this.IsLandscape() ? 5 : 0), 15, 25)
|
Margin = new Thickness(15, (this.IsLandscape() ? 5 : 0), 15, 25)
|
||||||
};
|
};
|
||||||
|
|
||||||
var layout = new StackLayout
|
StackLayout = new StackLayout
|
||||||
{
|
{
|
||||||
Children = { table, passwordLabel, table2, hintLabel },
|
Children = { table, PasswordLabel, table2, HintLabel },
|
||||||
Spacing = 0
|
Spacing = 0
|
||||||
};
|
};
|
||||||
|
|
||||||
layout.LayoutChanged += (sender, args) =>
|
|
||||||
{
|
|
||||||
passwordLabel.WidthRequest = layout.Bounds.Width - passwordLabel.Bounds.Left * 2;
|
|
||||||
hintLabel.WidthRequest = layout.Bounds.Width - hintLabel.Bounds.Left * 2;
|
|
||||||
};
|
|
||||||
|
|
||||||
var scrollView = new ScrollView
|
var scrollView = new ScrollView
|
||||||
{
|
{
|
||||||
Content = layout
|
Content = StackLayout
|
||||||
};
|
};
|
||||||
|
|
||||||
var loginToolbarItem = new ToolbarItem(AppResources.Submit, null, async () =>
|
var loginToolbarItem = new ToolbarItem(AppResources.Submit, null, async () =>
|
||||||
|
@ -148,6 +145,7 @@ namespace Bit.App.Pages
|
||||||
PasswordHintCell.InitEvents();
|
PasswordHintCell.InitEvents();
|
||||||
ConfirmPasswordCell.InitEvents();
|
ConfirmPasswordCell.InitEvents();
|
||||||
PasswordHintCell.Entry.Completed += Entry_Completed;
|
PasswordHintCell.Entry.Completed += Entry_Completed;
|
||||||
|
StackLayout.LayoutChanged += Layout_LayoutChanged;
|
||||||
EmailCell.Entry.FocusWithDelay();
|
EmailCell.Entry.FocusWithDelay();
|
||||||
}
|
}
|
||||||
protected override void OnDisappearing()
|
protected override void OnDisappearing()
|
||||||
|
@ -158,6 +156,13 @@ namespace Bit.App.Pages
|
||||||
PasswordHintCell.Dispose();
|
PasswordHintCell.Dispose();
|
||||||
ConfirmPasswordCell.Dispose();
|
ConfirmPasswordCell.Dispose();
|
||||||
PasswordHintCell.Entry.Completed -= Entry_Completed;
|
PasswordHintCell.Entry.Completed -= Entry_Completed;
|
||||||
|
StackLayout.LayoutChanged -= Layout_LayoutChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Layout_LayoutChanged(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
PasswordLabel.WidthRequest = StackLayout.Bounds.Width - PasswordLabel.Bounds.Left * 2;
|
||||||
|
HintLabel.WidthRequest = StackLayout.Bounds.Width - HintLabel.Bounds.Left * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void Entry_Completed(object sender, EventArgs e)
|
private async void Entry_Completed(object sender, EventArgs e)
|
||||||
|
|
|
@ -23,42 +23,37 @@ namespace Bit.App.Pages
|
||||||
Init();
|
Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ToolsViewCell GeneratorCell { get; set; }
|
||||||
|
public ToolsViewCell WebCell { get; set; }
|
||||||
|
public ToolsViewCell ImportCell { get; set; }
|
||||||
|
public ToolsViewCell ExtensionCell { get; set; }
|
||||||
|
public ToolsViewCell AutofillCell { get; set; }
|
||||||
|
|
||||||
public void Init()
|
public void Init()
|
||||||
{
|
{
|
||||||
var generatorCell = new ToolsViewCell(AppResources.PasswordGenerator, AppResources.PasswordGeneratorDescription,
|
GeneratorCell = new ToolsViewCell(AppResources.PasswordGenerator, AppResources.PasswordGeneratorDescription,
|
||||||
"refresh");
|
"refresh");
|
||||||
generatorCell.Tapped += GeneratorCell_Tapped;
|
WebCell = new ToolsViewCell(AppResources.WebVault, AppResources.WebVaultDescription, "globe");
|
||||||
var webCell = new ToolsViewCell(AppResources.WebVault, AppResources.WebVaultDescription, "globe");
|
ImportCell = new ToolsViewCell(AppResources.ImportLogins, AppResources.ImportLoginsDescription, "cloudup");
|
||||||
webCell.Tapped += WebCell_Tapped;
|
|
||||||
var importCell = new ToolsViewCell(AppResources.ImportLogins, AppResources.ImportLoginsDescription, "cloudup");
|
|
||||||
importCell.Tapped += ImportCell_Tapped;
|
|
||||||
|
|
||||||
var section = new TableSection { generatorCell };
|
var section = new TableSection { GeneratorCell };
|
||||||
|
|
||||||
if(Device.OS == TargetPlatform.iOS)
|
if(Device.OS == TargetPlatform.iOS)
|
||||||
{
|
{
|
||||||
var extensionCell = new ToolsViewCell(AppResources.BitwardenAppExtension,
|
ExtensionCell = new ToolsViewCell(AppResources.BitwardenAppExtension,
|
||||||
AppResources.BitwardenAppExtensionDescription, "upload");
|
AppResources.BitwardenAppExtensionDescription, "upload");
|
||||||
extensionCell.Tapped += (object sender, EventArgs e) =>
|
section.Add(ExtensionCell);
|
||||||
{
|
|
||||||
Navigation.PushModalAsync(new ExtendedNavigationPage(new ToolsExtensionPage()));
|
|
||||||
};
|
|
||||||
section.Add(extensionCell);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var autofillServiceCell = new ToolsViewCell(
|
AutofillCell = new ToolsViewCell(
|
||||||
string.Format("{0} ({1})", AppResources.BitwardenAutofillService, AppResources.Beta),
|
string.Format("{0} ({1})", AppResources.BitwardenAutofillService, AppResources.Beta),
|
||||||
AppResources.BitwardenAutofillServiceDescription, "upload");
|
AppResources.BitwardenAutofillServiceDescription, "upload");
|
||||||
autofillServiceCell.Tapped += (object sender, EventArgs e) =>
|
section.Add(AutofillCell);
|
||||||
{
|
|
||||||
Navigation.PushModalAsync(new ExtendedNavigationPage(new ToolsAutofillServicePage()));
|
|
||||||
};
|
|
||||||
section.Add(autofillServiceCell);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
section.Add(webCell);
|
section.Add(WebCell);
|
||||||
section.Add(importCell);
|
section.Add(ImportCell);
|
||||||
|
|
||||||
var table = new ExtendedTableView
|
var table = new ExtendedTableView
|
||||||
{
|
{
|
||||||
|
@ -81,6 +76,37 @@ namespace Bit.App.Pages
|
||||||
Content = table;
|
Content = table;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void OnAppearing()
|
||||||
|
{
|
||||||
|
base.OnAppearing();
|
||||||
|
GeneratorCell.Tapped += GeneratorCell_Tapped;
|
||||||
|
WebCell.Tapped += WebCell_Tapped;
|
||||||
|
ImportCell.Tapped += ImportCell_Tapped;
|
||||||
|
ExtensionCell.Tapped += ExtensionCell_Tapped;
|
||||||
|
AutofillCell.Tapped += AutofillCell_Tapped;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnDisappearing()
|
||||||
|
{
|
||||||
|
base.OnDisappearing();
|
||||||
|
GeneratorCell.Tapped -= GeneratorCell_Tapped;
|
||||||
|
WebCell.Tapped -= WebCell_Tapped;
|
||||||
|
ImportCell.Tapped -= ImportCell_Tapped;
|
||||||
|
ExtensionCell.Tapped -= ExtensionCell_Tapped;
|
||||||
|
AutofillCell.Tapped -= AutofillCell_Tapped;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AutofillCell_Tapped(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
Navigation.PushModalAsync(new ExtendedNavigationPage(new ToolsAutofillServicePage()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ExtensionCell_Tapped(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
Navigation.PushModalAsync(new ExtendedNavigationPage(new ToolsExtensionPage()));
|
||||||
|
}
|
||||||
|
|
||||||
private async void GeneratorCell_Tapped(object sender, EventArgs e)
|
private async void GeneratorCell_Tapped(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
await Navigation.PushForDeviceAsync(new ToolsPasswordGeneratorPage());
|
await Navigation.PushForDeviceAsync(new ToolsPasswordGeneratorPage());
|
||||||
|
|
|
@ -59,6 +59,8 @@ namespace Bit.App.Pages
|
||||||
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 SearchToolBarItem SearchItem { get; set; }
|
||||||
|
private AddLoginToolBarItem AddLoginItem { get; set; }
|
||||||
private IGoogleAnalyticsService GoogleAnalyticsService { get; set; }
|
private IGoogleAnalyticsService GoogleAnalyticsService { get; set; }
|
||||||
private IUserDialogs UserDialogs { get; set; }
|
private IUserDialogs UserDialogs { get; set; }
|
||||||
private string Uri { get; set; }
|
private string Uri { get; set; }
|
||||||
|
@ -88,8 +90,10 @@ namespace Bit.App.Pages
|
||||||
Spacing = 20
|
Spacing = 20
|
||||||
};
|
};
|
||||||
|
|
||||||
ToolbarItems.Add(new AddLoginToolBarItem(this));
|
AddLoginItem = new AddLoginToolBarItem(this);
|
||||||
ToolbarItems.Add(new SearchToolBarItem(this));
|
ToolbarItems.Add(AddLoginItem);
|
||||||
|
SearchItem = new SearchToolBarItem(this);
|
||||||
|
ToolbarItems.Add(SearchItem);
|
||||||
|
|
||||||
ListView = new ListView(ListViewCachingStrategy.RecycleElement)
|
ListView = new ListView(ListViewCachingStrategy.RecycleElement)
|
||||||
{
|
{
|
||||||
|
@ -106,8 +110,6 @@ namespace Bit.App.Pages
|
||||||
ListView.RowHeight = -1;
|
ListView.RowHeight = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ListView.ItemSelected += LoginSelected;
|
|
||||||
|
|
||||||
Title = string.Format(AppResources.LoginsForUri, _name ?? "--");
|
Title = string.Format(AppResources.LoginsForUri, _name ?? "--");
|
||||||
|
|
||||||
LoadingIndicator = new ActivityIndicator
|
LoadingIndicator = new ActivityIndicator
|
||||||
|
@ -123,9 +125,20 @@ namespace Bit.App.Pages
|
||||||
protected override void OnAppearing()
|
protected override void OnAppearing()
|
||||||
{
|
{
|
||||||
base.OnAppearing();
|
base.OnAppearing();
|
||||||
|
ListView.ItemSelected += LoginSelected;
|
||||||
|
AddLoginItem.InitEvents();
|
||||||
|
SearchItem.InitEvents();
|
||||||
_filterResultsCancellationTokenSource = FetchAndLoadVault();
|
_filterResultsCancellationTokenSource = FetchAndLoadVault();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void OnDisappearing()
|
||||||
|
{
|
||||||
|
base.OnDisappearing();
|
||||||
|
ListView.ItemSelected -= LoginSelected;
|
||||||
|
AddLoginItem.Dispose();
|
||||||
|
SearchItem.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
protected override bool OnBackButtonPressed()
|
protected override bool OnBackButtonPressed()
|
||||||
{
|
{
|
||||||
GoogleAnalyticsService.TrackExtensionEvent("BackClosed", Uri.StartsWith("http") ? "Website" : "App");
|
GoogleAnalyticsService.TrackExtensionEvent("BackClosed", Uri.StartsWith("http") ? "Website" : "App");
|
||||||
|
@ -266,26 +279,18 @@ namespace Bit.App.Pages
|
||||||
UserDialogs.Toast(string.Format(AppResources.ValueHasBeenCopied, alertLabel));
|
UserDialogs.Toast(string.Format(AppResources.ValueHasBeenCopied, alertLabel));
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AddLoginToolBarItem : ToolbarItem
|
private class AddLoginToolBarItem : ExtendedToolbarItem
|
||||||
{
|
{
|
||||||
private readonly VaultAutofillListLoginsPage _page;
|
|
||||||
|
|
||||||
public AddLoginToolBarItem(VaultAutofillListLoginsPage page)
|
public AddLoginToolBarItem(VaultAutofillListLoginsPage page)
|
||||||
|
: base(() => page.AddLoginAsync())
|
||||||
{
|
{
|
||||||
_page = page;
|
|
||||||
Text = AppResources.Add;
|
Text = AppResources.Add;
|
||||||
Icon = "plus";
|
Icon = "plus";
|
||||||
Clicked += ClickedItem;
|
|
||||||
Priority = 2;
|
Priority = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ClickedItem(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
_page.AddLoginAsync();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class SearchToolBarItem : ToolbarItem
|
private class SearchToolBarItem : ExtendedToolbarItem
|
||||||
{
|
{
|
||||||
private readonly VaultAutofillListLoginsPage _page;
|
private readonly VaultAutofillListLoginsPage _page;
|
||||||
|
|
||||||
|
@ -294,11 +299,11 @@ namespace Bit.App.Pages
|
||||||
_page = page;
|
_page = page;
|
||||||
Text = AppResources.Search;
|
Text = AppResources.Search;
|
||||||
Icon = "search";
|
Icon = "search";
|
||||||
Clicked += ClickedItem;
|
|
||||||
Priority = 1;
|
Priority = 1;
|
||||||
|
ClickAction = () => DoClick();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ClickedItem(object sender, EventArgs e)
|
private void DoClick()
|
||||||
{
|
{
|
||||||
_page.GoogleAnalyticsService.TrackExtensionEvent("CloseToSearch",
|
_page.GoogleAnalyticsService.TrackExtensionEvent("CloseToSearch",
|
||||||
_page.Uri.StartsWith("http") ? "Website" : "App");
|
_page.Uri.StartsWith("http") ? "Website" : "App");
|
||||||
|
|
|
@ -66,6 +66,7 @@ namespace Bit.App.Pages
|
||||||
public StackLayout NoDataStackLayout { get; set; }
|
public StackLayout NoDataStackLayout { get; set; }
|
||||||
public StackLayout ResultsStackLayout { get; set; }
|
public StackLayout ResultsStackLayout { get; set; }
|
||||||
public ActivityIndicator LoadingIndicator { get; set; }
|
public ActivityIndicator LoadingIndicator { get; set; }
|
||||||
|
private AddLoginToolBarItem AddLoginItem { get; set; }
|
||||||
public string Uri { get; set; }
|
public string Uri { get; set; }
|
||||||
|
|
||||||
private void Init()
|
private void Init()
|
||||||
|
@ -80,7 +81,8 @@ namespace Bit.App.Pages
|
||||||
|
|
||||||
if(!_favorites)
|
if(!_favorites)
|
||||||
{
|
{
|
||||||
ToolbarItems.Add(new AddLoginToolBarItem(this));
|
AddLoginItem = new AddLoginToolBarItem(this);
|
||||||
|
ToolbarItems.Add(AddLoginItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
ListView = new ListView(ListViewCachingStrategy.RecycleElement)
|
ListView = new ListView(ListViewCachingStrategy.RecycleElement)
|
||||||
|
@ -98,16 +100,12 @@ namespace Bit.App.Pages
|
||||||
ListView.RowHeight = -1;
|
ListView.RowHeight = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ListView.ItemSelected += LoginSelected;
|
|
||||||
|
|
||||||
Search = new SearchBar
|
Search = new SearchBar
|
||||||
{
|
{
|
||||||
Placeholder = AppResources.SearchVault,
|
Placeholder = AppResources.SearchVault,
|
||||||
FontSize = Device.GetNamedSize(NamedSize.Small, typeof(Button)),
|
FontSize = Device.GetNamedSize(NamedSize.Small, typeof(Button)),
|
||||||
CancelButtonColor = Color.FromHex("3c8dbc")
|
CancelButtonColor = Color.FromHex("3c8dbc")
|
||||||
};
|
};
|
||||||
Search.TextChanged += SearchBar_TextChanged;
|
|
||||||
Search.SearchButtonPressed += SearchBar_SearchButtonPressed;
|
|
||||||
// Bug with searchbar on android 7, ref https://bugzilla.xamarin.com/show_bug.cgi?id=43975
|
// Bug with searchbar on android 7, ref https://bugzilla.xamarin.com/show_bug.cgi?id=43975
|
||||||
if(Device.OS == TargetPlatform.Android && _deviceInfoService.Version >= 24)
|
if(Device.OS == TargetPlatform.Android && _deviceInfoService.Version >= 24)
|
||||||
{
|
{
|
||||||
|
@ -231,6 +229,11 @@ namespace Bit.App.Pages
|
||||||
protected override void OnAppearing()
|
protected override void OnAppearing()
|
||||||
{
|
{
|
||||||
base.OnAppearing();
|
base.OnAppearing();
|
||||||
|
ListView.ItemSelected += LoginSelected;
|
||||||
|
Search.TextChanged += SearchBar_TextChanged;
|
||||||
|
Search.SearchButtonPressed += SearchBar_SearchButtonPressed;
|
||||||
|
AddLoginItem?.InitEvents();
|
||||||
|
|
||||||
if(_loadExistingData)
|
if(_loadExistingData)
|
||||||
{
|
{
|
||||||
_filterResultsCancellationTokenSource = FetchAndLoadVault();
|
_filterResultsCancellationTokenSource = FetchAndLoadVault();
|
||||||
|
@ -268,6 +271,15 @@ namespace Bit.App.Pages
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void OnDisappearing()
|
||||||
|
{
|
||||||
|
base.OnDisappearing();
|
||||||
|
ListView.ItemSelected -= LoginSelected;
|
||||||
|
Search.TextChanged -= SearchBar_TextChanged;
|
||||||
|
Search.SearchButtonPressed -= SearchBar_SearchButtonPressed;
|
||||||
|
AddLoginItem.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
protected override bool OnBackButtonPressed()
|
protected override bool OnBackButtonPressed()
|
||||||
{
|
{
|
||||||
if(string.IsNullOrWhiteSpace(Uri))
|
if(string.IsNullOrWhiteSpace(Uri))
|
||||||
|
@ -469,21 +481,16 @@ namespace Bit.App.Pages
|
||||||
await Navigation.PushForDeviceAsync(page);
|
await Navigation.PushForDeviceAsync(page);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AddLoginToolBarItem : ToolbarItem
|
private class AddLoginToolBarItem : ExtendedToolbarItem
|
||||||
{
|
{
|
||||||
private readonly VaultListLoginsPage _page;
|
private readonly VaultListLoginsPage _page;
|
||||||
|
|
||||||
public AddLoginToolBarItem(VaultListLoginsPage page)
|
public AddLoginToolBarItem(VaultListLoginsPage page)
|
||||||
|
: base(() => page.AddLogin())
|
||||||
{
|
{
|
||||||
_page = page;
|
_page = page;
|
||||||
Text = AppResources.Add;
|
Text = AppResources.Add;
|
||||||
Icon = "plus";
|
Icon = "plus";
|
||||||
Clicked += ClickedItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ClickedItem(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
_page.AddLogin();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ using Bit.App.Models.Page;
|
||||||
using Bit.App.Resources;
|
using Bit.App.Resources;
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
using XLabs.Ioc;
|
using XLabs.Ioc;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Bit.App.Pages
|
namespace Bit.App.Pages
|
||||||
{
|
{
|
||||||
|
@ -33,10 +34,12 @@ namespace Bit.App.Pages
|
||||||
public LabeledValueCell UsernameCell { get; set; }
|
public LabeledValueCell UsernameCell { get; set; }
|
||||||
public LabeledValueCell PasswordCell { get; set; }
|
public LabeledValueCell PasswordCell { get; set; }
|
||||||
public LabeledValueCell UriCell { get; set; }
|
public LabeledValueCell UriCell { get; set; }
|
||||||
|
private EditLoginToolBarItem EditItem { get; set; }
|
||||||
|
|
||||||
private void Init()
|
private void Init()
|
||||||
{
|
{
|
||||||
ToolbarItems.Add(new EditLoginToolBarItem(this, _loginId));
|
EditItem = new EditLoginToolBarItem(this, _loginId);
|
||||||
|
ToolbarItems.Add(EditItem);
|
||||||
if(Device.OS == TargetPlatform.iOS)
|
if(Device.OS == TargetPlatform.iOS)
|
||||||
{
|
{
|
||||||
ToolbarItems.Add(new DismissModalToolBarItem(this));
|
ToolbarItems.Add(new DismissModalToolBarItem(this));
|
||||||
|
@ -121,6 +124,8 @@ namespace Bit.App.Pages
|
||||||
|
|
||||||
protected async override void OnAppearing()
|
protected async override void OnAppearing()
|
||||||
{
|
{
|
||||||
|
EditItem.InitEvents();
|
||||||
|
|
||||||
var login = await _loginService.GetByIdAsync(_loginId);
|
var login = await _loginService.GetByIdAsync(_loginId);
|
||||||
if(login == null)
|
if(login == null)
|
||||||
{
|
{
|
||||||
|
@ -169,13 +174,18 @@ namespace Bit.App.Pages
|
||||||
base.OnAppearing();
|
base.OnAppearing();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void OnDisappearing()
|
||||||
|
{
|
||||||
|
EditItem.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
private void Copy(string copyText, string alertLabel)
|
private void Copy(string copyText, string alertLabel)
|
||||||
{
|
{
|
||||||
_clipboardService.CopyToClipboard(copyText);
|
_clipboardService.CopyToClipboard(copyText);
|
||||||
_userDialogs.Toast(string.Format(AppResources.ValueHasBeenCopied, alertLabel));
|
_userDialogs.Toast(string.Format(AppResources.ValueHasBeenCopied, alertLabel));
|
||||||
}
|
}
|
||||||
|
|
||||||
private class EditLoginToolBarItem : ToolbarItem
|
private class EditLoginToolBarItem : ExtendedToolbarItem
|
||||||
{
|
{
|
||||||
private readonly VaultViewLoginPage _page;
|
private readonly VaultViewLoginPage _page;
|
||||||
private readonly string _loginId;
|
private readonly string _loginId;
|
||||||
|
@ -185,10 +195,10 @@ namespace Bit.App.Pages
|
||||||
_page = page;
|
_page = page;
|
||||||
_loginId = loginId;
|
_loginId = loginId;
|
||||||
Text = AppResources.Edit;
|
Text = AppResources.Edit;
|
||||||
Clicked += ClickedItem;
|
ClickAction = async () => await ClickedItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void ClickedItem(object sender, EventArgs e)
|
private async Task ClickedItem()
|
||||||
{
|
{
|
||||||
var page = new VaultEditLoginPage(_loginId);
|
var page = new VaultEditLoginPage(_loginId);
|
||||||
await _page.Navigation.PushForDeviceAsync(page);
|
await _page.Navigation.PushForDeviceAsync(page);
|
||||||
|
|
Loading…
Reference in a new issue