reuse code

This commit is contained in:
Kyle Spearrin 2018-09-24 16:11:54 -04:00
parent 44fe5af4fb
commit f416f95b77
8 changed files with 162 additions and 201 deletions

View file

@ -1,12 +1,11 @@
using System; using System;
using System.Linq;
using Bit.iOS.Autofill.Models; using Bit.iOS.Autofill.Models;
using Foundation; using Foundation;
using UIKit; using UIKit;
using Bit.iOS.Core.Utilities;
using Bit.iOS.Core.Controllers; using Bit.iOS.Core.Controllers;
using Bit.App.Resources; using Bit.App.Resources;
using Bit.iOS.Core.Views; using Bit.iOS.Core.Views;
using Bit.iOS.Autofill.Utilities;
namespace Bit.iOS.Autofill namespace Bit.iOS.Autofill
{ {
@ -87,7 +86,7 @@ namespace Bit.iOS.Autofill
private LoginListViewController _controller; private LoginListViewController _controller;
public TableSource(LoginListViewController controller) public TableSource(LoginListViewController controller)
:base(controller.Context, controller) : base(controller.Context, controller)
{ {
_context = controller.Context; _context = controller.Context;
_controller = controller; _controller = controller;
@ -95,77 +94,8 @@ namespace Bit.iOS.Autofill
public override void RowSelected(UITableView tableView, NSIndexPath indexPath) public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
{ {
tableView.DeselectRow(indexPath, true); AutofillHelpers.TableRowSelected(tableView, indexPath, this,
tableView.EndEditing(true); _controller.CPViewController, _controller, _settings, "loginAddSegue");
if(_tableItems == null || _tableItems.Count() == 0)
{
_controller.PerformSegue("loginAddSegue", this);
return;
}
var item = _tableItems.ElementAt(indexPath.Row);
if(item == null)
{
_controller.CPViewController.CompleteRequest(null, null, null);
return;
}
if(!string.IsNullOrWhiteSpace(item.Password))
{
string totp = null;
if(!_settings.GetValueOrDefault(App.Constants.SettingDisableTotpCopy, false))
{
totp = GetTotp(item);
}
_controller.CPViewController.CompleteRequest(item.Username, item.Password, totp);
}
else if(!string.IsNullOrWhiteSpace(item.Username) || !string.IsNullOrWhiteSpace(item.Totp.Value))
{
var sheet = Dialogs.CreateActionSheet(item.Name, _controller);
if(!string.IsNullOrWhiteSpace(item.Username))
{
sheet.AddAction(UIAlertAction.Create(AppResources.CopyUsername, UIAlertActionStyle.Default, a =>
{
UIPasteboard clipboard = UIPasteboard.General;
clipboard.String = item.Username;
var alert = Dialogs.CreateMessageAlert(AppResources.CopyUsername);
_controller.PresentViewController(alert, true, () =>
{
_controller.DismissViewController(true, null);
});
}));
}
if(!string.IsNullOrWhiteSpace(item.Totp.Value))
{
sheet.AddAction(UIAlertAction.Create(AppResources.CopyTotp, UIAlertActionStyle.Default, a =>
{
var totp = GetTotp(item);
if(string.IsNullOrWhiteSpace(totp))
{
return;
}
UIPasteboard clipboard = UIPasteboard.General;
clipboard.String = totp;
var alert = Dialogs.CreateMessageAlert(AppResources.CopiedTotp);
_controller.PresentViewController(alert, true, () =>
{
_controller.DismissViewController(true, null);
});
}));
}
sheet.AddAction(UIAlertAction.Create(AppResources.Cancel, UIAlertActionStyle.Cancel, null));
_controller.PresentViewController(sheet, true, null);
}
else
{
var alert = Dialogs.CreateAlert(null, AppResources.NoUsernamePasswordConfigured, AppResources.Ok);
_controller.PresentViewController(alert, true, null);
}
} }
} }
} }

View file

@ -1,14 +1,11 @@
using System; using System;
using System.Linq;
using Bit.iOS.Autofill.Models; using Bit.iOS.Autofill.Models;
using Foundation; using Foundation;
using UIKit; using UIKit;
using Bit.iOS.Core.Utilities;
using Bit.iOS.Core.Controllers; using Bit.iOS.Core.Controllers;
using Bit.App.Resources; using Bit.App.Resources;
using Bit.iOS.Core.Views; using Bit.iOS.Core.Views;
using System.Threading; using Bit.iOS.Autofill.Utilities;
using System.Threading.Tasks;
namespace Bit.iOS.Autofill namespace Bit.iOS.Autofill
{ {
@ -36,7 +33,7 @@ namespace Bit.iOS.Autofill
TableView.RowHeight = UITableView.AutomaticDimension; TableView.RowHeight = UITableView.AutomaticDimension;
TableView.EstimatedRowHeight = 44; TableView.EstimatedRowHeight = 44;
TableView.Source = new TableSource(this); TableView.Source = new TableSource(this);
SearchBar.Delegate = new SearchDelegate(this); SearchBar.Delegate = new ExtensionSearchDelegate(TableView);
await ((TableSource)TableView.Source).LoadItemsAsync(false, SearchBar.Text); await ((TableSource)TableView.Source).LoadItemsAsync(false, SearchBar.Text);
} }
@ -87,118 +84,8 @@ namespace Bit.iOS.Autofill
public override void RowSelected(UITableView tableView, NSIndexPath indexPath) public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
{ {
tableView.DeselectRow(indexPath, true); AutofillHelpers.TableRowSelected(tableView, indexPath, this,
tableView.EndEditing(true); _controller.CPViewController, _controller, _settings, "loginAddFromSearchSegue");
if(_tableItems == null || _tableItems.Count() == 0)
{
_controller.PerformSegue("loginAddFromSearchSegue", this);
return;
}
var item = _tableItems.ElementAt(indexPath.Row);
if(item == null)
{
_controller.CPViewController.CompleteRequest(null, null, null);
return;
}
if(!string.IsNullOrWhiteSpace(item.Password))
{
string totp = null;
if(!_settings.GetValueOrDefault(App.Constants.SettingDisableTotpCopy, false))
{
totp = GetTotp(item);
}
_controller.CPViewController.CompleteRequest(item.Username, item.Password, totp);
}
else if(!string.IsNullOrWhiteSpace(item.Username) || !string.IsNullOrWhiteSpace(item.Totp.Value))
{
var sheet = Dialogs.CreateActionSheet(item.Name, _controller);
if(!string.IsNullOrWhiteSpace(item.Username))
{
sheet.AddAction(UIAlertAction.Create(AppResources.CopyUsername, UIAlertActionStyle.Default, a =>
{
UIPasteboard clipboard = UIPasteboard.General;
clipboard.String = item.Username;
var alert = Dialogs.CreateMessageAlert(AppResources.CopyUsername);
_controller.PresentViewController(alert, true, () =>
{
_controller.DismissViewController(true, null);
});
}));
}
if(!string.IsNullOrWhiteSpace(item.Totp.Value))
{
sheet.AddAction(UIAlertAction.Create(AppResources.CopyTotp, UIAlertActionStyle.Default, a =>
{
var totp = GetTotp(item);
if(string.IsNullOrWhiteSpace(totp))
{
return;
}
UIPasteboard clipboard = UIPasteboard.General;
clipboard.String = totp;
var alert = Dialogs.CreateMessageAlert(AppResources.CopiedTotp);
_controller.PresentViewController(alert, true, () =>
{
_controller.DismissViewController(true, null);
});
}));
}
sheet.AddAction(UIAlertAction.Create(AppResources.Cancel, UIAlertActionStyle.Cancel, null));
_controller.PresentViewController(sheet, true, null);
}
else
{
var alert = Dialogs.CreateAlert(null, AppResources.NoUsernamePasswordConfigured, AppResources.Ok);
_controller.PresentViewController(alert, true, null);
}
}
}
public class SearchDelegate : UISearchBarDelegate
{
private readonly LoginSearchViewController _controller;
private CancellationTokenSource _filterResultsCancellationTokenSource;
public SearchDelegate(LoginSearchViewController controller)
{
_controller = controller;
}
public override void TextChanged(UISearchBar searchBar, string searchText)
{
var cts = new CancellationTokenSource();
Task.Run(() =>
{
NSRunLoop.Main.BeginInvokeOnMainThread(async () =>
{
if (!string.IsNullOrWhiteSpace(searchText))
{
await Task.Delay(300);
if (searchText != searchBar.Text)
{
return;
}
else
{
_filterResultsCancellationTokenSource?.Cancel();
}
}
try
{
((TableSource)_controller.TableView.Source).FilterResults(searchText, cts.Token);
_controller.TableView.ReloadData();
}
catch (OperationCanceledException) { }
_filterResultsCancellationTokenSource = cts;
});
}, cts.Token);
} }
} }
} }

View file

@ -0,0 +1,91 @@
using System;
using System.Linq;
using Bit.App.Resources;
using Bit.iOS.Core.Utilities;
using Bit.iOS.Core.Views;
using Foundation;
using Plugin.Settings.Abstractions;
using UIKit;
namespace Bit.iOS.Autofill.Utilities
{
public static class AutofillHelpers
{
public static void TableRowSelected(UITableView tableView, NSIndexPath indexPath,
ExtensionTableSource tableSource, CredentialProviderViewController cpViewController,
UITableViewController controller, ISettings settings, string loginAddSegue)
{
tableView.DeselectRow(indexPath, true);
tableView.EndEditing(true);
if(tableSource.Items == null || tableSource.Items.Count() == 0)
{
controller.PerformSegue(loginAddSegue, tableSource);
return;
}
var item = tableSource.Items.ElementAt(indexPath.Row);
if(item == null)
{
cpViewController.CompleteRequest(null);
return;
}
if(!string.IsNullOrWhiteSpace(item.Password))
{
string totp = null;
if(!settings.GetValueOrDefault(App.Constants.SettingDisableTotpCopy, false))
{
totp = tableSource.GetTotp(item);
}
cpViewController.CompleteRequest(item.Username, item.Password, totp);
}
else if(!string.IsNullOrWhiteSpace(item.Username) || !string.IsNullOrWhiteSpace(item.Totp.Value))
{
var sheet = Dialogs.CreateActionSheet(item.Name, controller);
if(!string.IsNullOrWhiteSpace(item.Username))
{
sheet.AddAction(UIAlertAction.Create(AppResources.CopyUsername, UIAlertActionStyle.Default, a =>
{
UIPasteboard clipboard = UIPasteboard.General;
clipboard.String = item.Username;
var alert = Dialogs.CreateMessageAlert(AppResources.CopyUsername);
controller.PresentViewController(alert, true, () =>
{
controller.DismissViewController(true, null);
});
}));
}
if(!string.IsNullOrWhiteSpace(item.Totp.Value))
{
sheet.AddAction(UIAlertAction.Create(AppResources.CopyTotp, UIAlertActionStyle.Default, a =>
{
var totp = tableSource.GetTotp(item);
if(string.IsNullOrWhiteSpace(totp))
{
return;
}
UIPasteboard clipboard = UIPasteboard.General;
clipboard.String = totp;
var alert = Dialogs.CreateMessageAlert(AppResources.CopiedTotp);
controller.PresentViewController(alert, true, () =>
{
controller.DismissViewController(true, null);
});
}));
}
sheet.AddAction(UIAlertAction.Create(AppResources.Cancel, UIAlertActionStyle.Cancel, null));
controller.PresentViewController(sheet, true, null);
}
else
{
var alert = Dialogs.CreateAlert(null, AppResources.NoUsernamePasswordConfigured, AppResources.Ok);
controller.PresentViewController(alert, true, null);
}
}
}
}

View file

@ -213,6 +213,7 @@
<Compile Include="SetupViewController.designer.cs"> <Compile Include="SetupViewController.designer.cs">
<DependentUpon>SetupViewController.cs</DependentUpon> <DependentUpon>SetupViewController.cs</DependentUpon>
</Compile> </Compile>
<Compile Include="Utilities\AutofillHelpers.cs" />
<None Include="Info.plist" /> <None Include="Info.plist" />
<None Include="Entitlements.plist" /> <None Include="Entitlements.plist" />
<Compile Include="PasswordGeneratorViewController.cs" /> <Compile Include="PasswordGeneratorViewController.cs" />
@ -299,5 +300,6 @@
<ItemGroup> <ItemGroup>
<BundleResource Include="Resources\check%403x.png" /> <BundleResource Include="Resources\check%403x.png" />
</ItemGroup> </ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.AppExtension.CSharp.targets" /> <Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.AppExtension.CSharp.targets" />
</Project> </Project>

View file

@ -0,0 +1,49 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Foundation;
using UIKit;
namespace Bit.iOS.Core.Views
{
public class ExtensionSearchDelegate : UISearchBarDelegate
{
private readonly UITableView _tableView;
private CancellationTokenSource _filterResultsCancellationTokenSource;
public ExtensionSearchDelegate(UITableView tableView)
{
_tableView = tableView;
}
public override void TextChanged(UISearchBar searchBar, string searchText)
{
var cts = new CancellationTokenSource();
Task.Run(() =>
{
NSRunLoop.Main.BeginInvokeOnMainThread(async () =>
{
if(!string.IsNullOrWhiteSpace(searchText))
{
await Task.Delay(300);
if(searchText != searchBar.Text)
{
return;
}
else
{
_filterResultsCancellationTokenSource?.Cancel();
}
}
try
{
((ExtensionTableSource)_tableView.Source).FilterResults(searchText, cts.Token);
_tableView.ReloadData();
}
catch(OperationCanceledException) { }
_filterResultsCancellationTokenSource = cts;
});
}, cts.Token);
}
}
}

View file

@ -21,7 +21,6 @@ namespace Bit.iOS.Core.Views
private const string CellIdentifier = "TableCell"; private const string CellIdentifier = "TableCell";
private IEnumerable<CipherViewModel> _allItems = new List<CipherViewModel>(); private IEnumerable<CipherViewModel> _allItems = new List<CipherViewModel>();
protected IEnumerable<CipherViewModel> _tableItems = new List<CipherViewModel>();
protected ICipherService _cipherService; protected ICipherService _cipherService;
protected ISettings _settings; protected ISettings _settings;
private bool _accessPremium; private bool _accessPremium;
@ -37,6 +36,8 @@ namespace Bit.iOS.Core.Views
_controller = controller; _controller = controller;
} }
public IEnumerable<CipherViewModel> Items { get; private set; }
public async Task LoadItemsAsync(bool urlFilter = true, string searchFilter = null) public async Task LoadItemsAsync(bool urlFilter = true, string searchFilter = null)
{ {
var combinedLogins = new List<Cipher>(); var combinedLogins = new List<Cipher>();
@ -74,12 +75,12 @@ namespace Bit.iOS.Core.Views
if(string.IsNullOrWhiteSpace(searchFilter)) if(string.IsNullOrWhiteSpace(searchFilter))
{ {
_tableItems = _allItems.ToList(); Items = _allItems.ToList();
} }
else else
{ {
searchFilter = searchFilter.ToLower(); searchFilter = searchFilter.ToLower();
_tableItems = _allItems Items = _allItems
.Where(s => s.Name.ToLower().Contains(searchFilter) || .Where(s => s.Name.ToLower().Contains(searchFilter) ||
(s.Username?.ToLower().Contains(searchFilter) ?? false) || (s.Username?.ToLower().Contains(searchFilter) ?? false) ||
(s.Uris?.FirstOrDefault()?.Uri.ToLower().Contains(searchFilter) ?? false)) (s.Uris?.FirstOrDefault()?.Uri.ToLower().Contains(searchFilter) ?? false))
@ -92,12 +93,12 @@ namespace Bit.iOS.Core.Views
public override nint RowsInSection(UITableView tableview, nint section) public override nint RowsInSection(UITableView tableview, nint section)
{ {
return _tableItems == null || _tableItems.Count() == 0 ? 1 : _tableItems.Count(); return Items == null || Items.Count() == 0 ? 1 : Items.Count();
} }
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath) public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{ {
if(_tableItems == null || _tableItems.Count() == 0) if(Items == null || Items.Count() == 0)
{ {
var noDataCell = new UITableViewCell(UITableViewCellStyle.Default, "NoDataCell"); var noDataCell = new UITableViewCell(UITableViewCellStyle.Default, "NoDataCell");
noDataCell.TextLabel.Text = AppResources.NoItemsTap; noDataCell.TextLabel.Text = AppResources.NoItemsTap;
@ -121,17 +122,17 @@ namespace Bit.iOS.Core.Views
public override void WillDisplay(UITableView tableView, UITableViewCell cell, NSIndexPath indexPath) public override void WillDisplay(UITableView tableView, UITableViewCell cell, NSIndexPath indexPath)
{ {
if(_tableItems == null || _tableItems.Count() == 0 || cell == null) if(Items == null || Items.Count() == 0 || cell == null)
{ {
return; return;
} }
var item = _tableItems.ElementAt(indexPath.Row); var item = Items.ElementAt(indexPath.Row);
cell.TextLabel.Text = item.Name; cell.TextLabel.Text = item.Name;
cell.DetailTextLabel.Text = item.Username; cell.DetailTextLabel.Text = item.Username;
} }
protected string GetTotp(CipherViewModel item) public string GetTotp(CipherViewModel item)
{ {
string totp = null; string totp = null;
if(_accessPremium) if(_accessPremium)

View file

@ -71,6 +71,7 @@
<Compile Include="Views\SliderTableViewCell.cs" /> <Compile Include="Views\SliderTableViewCell.cs" />
<Compile Include="Views\SwitchTableViewCell.cs" /> <Compile Include="Views\SwitchTableViewCell.cs" />
<Compile Include="Views\FormEntryTableViewCell.cs" /> <Compile Include="Views\FormEntryTableViewCell.cs" />
<Compile Include="Views\ExtensionSearchDelegate.cs" />
<Compile Include="Views\Toast.cs" /> <Compile Include="Views\Toast.cs" />
<Compile Include="Models\CipherViewModel.cs" /> <Compile Include="Models\CipherViewModel.cs" />
<Compile Include="Utilities\ASHelpers.cs" /> <Compile Include="Utilities\ASHelpers.cs" />

View file

@ -107,13 +107,13 @@ namespace Bit.iOS.Extension
tableView.DeselectRow(indexPath, true); tableView.DeselectRow(indexPath, true);
tableView.EndEditing(true); tableView.EndEditing(true);
if(_tableItems == null || _tableItems.Count() == 0) if(Items == null || Items.Count() == 0)
{ {
_controller.PerformSegue("loginAddSegue", this); _controller.PerformSegue("loginAddSegue", this);
return; return;
} }
var item = _tableItems.ElementAt(indexPath.Row); var item = Items.ElementAt(indexPath.Row);
if(item == null) if(item == null)
{ {
_controller.LoadingController.CompleteRequest(null); _controller.LoadingController.CompleteRequest(null);