Removed disclosure from view cell in favor of button. Updated sync logic for incrementals. Store revision date from server record. Apply more accessability font size support for editor and picker controls

This commit is contained in:
Kyle Spearrin 2016-06-30 18:53:43 -04:00
parent 7a48128e43
commit 17af08b7d4
17 changed files with 166 additions and 6236 deletions

View file

@ -6,7 +6,6 @@ using Bit.App.Controls;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using AView = Android.Views.View;
using Android.Widget;
[assembly: ExportRenderer(typeof(ExtendedViewCell), typeof(ExtendedViewCellRenderer))]
namespace Bit.Android.Controls
@ -23,22 +22,6 @@ namespace Bit.Android.Controls
if(View != null)
{
View.SetBackgroundColor(extendedCell.BackgroundColor.ToAndroid());
if(extendedCell.ShowDisclousure)
{
var resourceId = Resource.Drawable.ion_chevron_right;
if(!string.IsNullOrWhiteSpace(extendedCell.DisclousureImage))
{
var fileName = System.IO.Path.GetFileNameWithoutExtension(extendedCell.DisclousureImage);
resourceId = context.Resources.GetIdentifier(fileName, "drawable", context.PackageName);
}
var image = new DisclosureImage(context, extendedCell);
image.SetImageResource(resourceId);
image.SetPadding(10, 10, 30, 10);
//View.SetAccessoryView(image);
}
}
return View;
@ -55,29 +38,5 @@ namespace Bit.Android.Controls
View.SetBackgroundColor(cell.BackgroundColor.ToAndroid());
}
}
private class DisclosureImage : ImageView
{
private ExtendedViewCell _cell;
public DisclosureImage(Context context, ExtendedViewCell cell) : base(context)
{
_cell = cell;
}
public override bool OnTouchEvent(MotionEvent e)
{
switch(e.Action)
{
case MotionEventActions.Up:
_cell.OnDisclousureTapped();
break;
default:
break;
}
return true;
}
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -125,10 +125,12 @@ namespace Bit.App
}
else if(pinUnlock && !string.IsNullOrWhiteSpace(_authService.PIN))
{
if((currentPage?.CurrentPage as LockPinPage) == null)
var lockPinPage = (currentPage?.CurrentPage as LockPinPage);
if(lockPinPage == null)
{
await Current.MainPage.Navigation.PushModalAsync(new ExtendedNavigationPage(new LockPinPage()), false);
lockPinPage = new LockPinPage();
await Current.MainPage.Navigation.PushModalAsync(new ExtendedNavigationPage(lockPinPage), false);
lockPinPage.PinControl.Entry.Focus();
}
}
else

View file

@ -8,35 +8,10 @@ namespace Bit.App.Controls
public static readonly BindableProperty BackgroundColorProperty =
BindableProperty.Create(nameof(BackgroundColor), typeof(Color), typeof(ExtendedTextCell), Color.White);
public static readonly BindableProperty ShowDisclousureProperty =
BindableProperty.Create(nameof(DisclousureImage), typeof(bool), typeof(ExtendedTextCell), false);
public static readonly BindableProperty DisclousureImageProperty =
BindableProperty.Create(nameof(DisclousureImage), typeof(string), typeof(ExtendedTextCell), string.Empty);
public Color BackgroundColor
{
get { return (Color)GetValue(BackgroundColorProperty); }
set { SetValue(BackgroundColorProperty, value); }
}
public bool ShowDisclousure
{
get { return (bool)GetValue(ShowDisclousureProperty); }
set { SetValue(ShowDisclousureProperty, value); }
}
public string DisclousureImage
{
get { return (string)GetValue(DisclousureImageProperty); }
set { SetValue(DisclousureImageProperty, value); }
}
public event EventHandler DisclousureTapped;
public void OnDisclousureTapped()
{
DisclousureTapped?.Invoke(this, EventArgs.Empty);
}
}
}

View file

@ -2,7 +2,7 @@
namespace Bit.App.Controls
{
public class LabeledDetailCell : ExtendedViewCell
public class LabeledDetailCell : ViewCell
{
public LabeledDetailCell()
{
@ -20,19 +20,33 @@ namespace Bit.App.Controls
Style = (Style)Application.Current.Resources["text-muted"],
};
var stackLayout = new StackLayout
var labelDetailStackLayout = new StackLayout
{
Padding = new Thickness(20, 5),
HorizontalOptions = LayoutOptions.FillAndExpand,
HorizontalOptions = LayoutOptions.StartAndExpand,
VerticalOptions = LayoutOptions.FillAndExpand,
Children = { Label, Detail },
Padding = new Thickness(15, 5, 5, 5),
Spacing = 0
};
View = stackLayout;
Button = new Button
{
HorizontalOptions = LayoutOptions.End,
VerticalOptions = LayoutOptions.FillAndExpand,
WidthRequest = 50
};
var containerStackLayout = new StackLayout
{
Orientation = StackOrientation.Horizontal,
Children = { labelDetailStackLayout, Button }
};
View = containerStackLayout;
}
public Label Label { get; private set; }
public Label Detail { get; private set; }
public Button Button { get; private set; }
}
}

View file

@ -38,6 +38,7 @@ namespace Bit.App.Controls
Value = new Label
{
Text = valueText,
FontSize = Device.GetNamedSize(NamedSize.Default, typeof(Label)),
LineBreakMode = LineBreakMode.TailTruncation,
VerticalOptions = LayoutOptions.CenterAndExpand
};

View file

@ -12,7 +12,7 @@ namespace Bit.App.Controls
Label = new Label
{
HorizontalTextAlignment = TextAlignment.Center,
FontSize = 30,
FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label)),
FontFamily = "Courier"
};

View file

@ -23,6 +23,7 @@ namespace Bit.App.Models.Data
Id = folder.Id;
UserId = userId;
Name = folder.Name;
RevisionDateTime = folder.RevisionDate;
}
public FolderData(CipherResponse cipher, string userId)
@ -37,6 +38,7 @@ namespace Bit.App.Models.Data
Id = cipher.Id;
UserId = userId;
Name = data.Name;
RevisionDateTime = cipher.RevisionDate;
}
[PrimaryKey]

View file

@ -2,7 +2,6 @@
using SQLite;
using Bit.App.Abstractions;
using Bit.App.Models.Api;
using Newtonsoft.Json.Linq;
namespace Bit.App.Models.Data
{
@ -36,6 +35,7 @@ namespace Bit.App.Models.Data
Password = site.Password;
Notes = site.Notes;
Favorite = site.Favorite;
RevisionDateTime = site.RevisionDate;
}
public SiteData(CipherResponse cipher, string userId)
@ -55,6 +55,7 @@ namespace Bit.App.Models.Data
Password = data.Password;
Notes = data.Notes;
Favorite = cipher.Favorite;
RevisionDateTime = cipher.RevisionDate;
}
[PrimaryKey]

View file

@ -53,6 +53,7 @@ namespace Bit.App.Pages
var tgr = new TapGestureRecognizer();
tgr.Tapped += Tgr_Tapped;
PinControl.Label.GestureRecognizers.Add(tgr);
Title = "Verify PIN";
Content = stackLayout;

View file

@ -44,6 +44,7 @@ namespace Bit.App.Pages
var tgr = new TapGestureRecognizer();
tgr.Tapped += Tgr_Tapped;
PinControl.Label.GestureRecognizers.Add(tgr);
Title = "Set PIN";
Content = stackLayout;

View file

@ -12,7 +12,6 @@ using XLabs.Ioc;
using Bit.App.Utilities;
using PushNotification.Plugin.Abstractions;
using Plugin.Settings.Abstractions;
using System.Windows.Input;
namespace Bit.App.Pages
{
@ -59,7 +58,6 @@ namespace Bit.App.Pages
if(Device.OS == TargetPlatform.iOS)
{
listView.Margin = new Thickness(0, 0, -15, 0);
listView.RowHeight = -1;
}
@ -195,7 +193,7 @@ namespace Bit.App.Pages
_page = page;
// Adding whitespace to Delete action to account for the negative margin offset on the listview
var deleteAction = new MenuItem { Text = AppResources.Delete + " ", IsDestructive = true };
var deleteAction = new MenuItem { Text = AppResources.Delete, IsDestructive = true };
deleteAction.SetBinding(MenuItem.CommandParameterProperty, new Binding("."));
deleteAction.Clicked += page.DeleteClickedAsync;
@ -210,9 +208,8 @@ namespace Bit.App.Pages
ContextActions.Add(deleteAction);
ContextActions.Add(moreAction);
DisclousureTapped += VaultListViewCell_DisclousureTapped;
ShowDisclousure = true;
DisclousureImage = "more";
Button.Image = "more";
Button.Command = new Command(() => ShowMore());
}
public VaultListPageModel.Site SiteParameter
@ -228,10 +225,9 @@ namespace Bit.App.Pages
_page.MoreClickedAsync(site);
}
private void VaultListViewCell_DisclousureTapped(object sender, EventArgs e)
private void ShowMore()
{
var cell = sender as VaultListViewCell;
_page.MoreClickedAsync(cell.SiteParameter);
_page.MoreClickedAsync(SiteParameter);
}
}
@ -264,6 +260,7 @@ namespace Bit.App.Pages
};
View = stackLayout;
Height = 40;
}
}
}

View file

@ -156,15 +156,10 @@ namespace Bit.App.Services
var siteTask = SyncSitesAsync(ciphers.Result.Revised.Where(c => c.Type == Enums.CipherType.Site), false);
var folderTask = SyncFoldersAsync(ciphers.Result.Revised.Where(c => c.Type == Enums.CipherType.Folder), false);
var deleteTask = DeleteCiphersAsync(ciphers.Result.Deleted);
foreach(var cipherId in ciphers.Result.Deleted)
{
await _siteRepository.DeleteAsync(cipherId);
}
await Task.WhenAll(siteTask, folderTask);
if(folderTask.Exception != null || siteTask.Exception != null)
await Task.WhenAll(siteTask, folderTask, deleteTask);
if(folderTask.Exception != null || siteTask.Exception != null || deleteTask.Exception != null)
{
return false;
}
@ -179,14 +174,15 @@ namespace Bit.App.Services
foreach(var serverFolder in serverFolders)
{
var data = new FolderData(serverFolder, _authService.UserId);
var existingLocalFolder = localFolders.SingleOrDefault(f => f.Id == serverFolder.Id);
if(existingLocalFolder == null)
{
var data = new FolderData(serverFolder, _authService.UserId);
await _folderRepository.InsertAsync(data);
}
else
else if(existingLocalFolder.RevisionDateTime != serverFolder.RevisionDate)
{
var data = new FolderData(serverFolder, _authService.UserId);
await _folderRepository.UpdateAsync(data);
}
}
@ -208,14 +204,15 @@ namespace Bit.App.Services
foreach(var serverSite in serverSites)
{
var data = new SiteData(serverSite, _authService.UserId);
var existingLocalSite = localSites.SingleOrDefault(s => s.Id == serverSite.Id);
if(existingLocalSite == null)
{
var data = new SiteData(serverSite, _authService.UserId);
await _siteRepository.InsertAsync(data);
}
else
else if(existingLocalSite.RevisionDateTime != serverSite.RevisionDate)
{
var data = new SiteData(serverSite, _authService.UserId);
await _siteRepository.UpdateAsync(data);
}
}
@ -230,5 +227,16 @@ namespace Bit.App.Services
await _siteRepository.DeleteAsync(site.Id);
}
}
private async Task DeleteCiphersAsync(IEnumerable<string> cipherIds)
{
var tasks = new List<Task>();
foreach(var cipherId in cipherIds)
{
tasks.Add(_siteRepository.DeleteAsync(cipherId));
tasks.Add(_folderRepository.DeleteAsync(cipherId));
}
await Task.WhenAll(tasks);
}
}
}

View file

@ -0,0 +1,26 @@
using System;
using System.ComponentModel;
using Bit.App.Controls;
using Bit.iOS.Controls;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(ExtendedEditor), typeof(ExtendedEditorRenderer))]
namespace Bit.iOS.Controls
{
public class ExtendedEditorRenderer : EditorRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Editor> e)
{
base.OnElementChanged(e);
var view = e.NewElement as ExtendedEditor;
if(view != null)
{
var descriptor = UIFontDescriptor.PreferredBody;
Control.Font = UIFont.FromDescriptor(descriptor, descriptor.PointSize);
}
}
}
}

View file

@ -18,6 +18,9 @@ namespace Bit.iOS.Controls
var view = e.NewElement as ExtendedPicker;
if(view != null)
{
var descriptor = UIFontDescriptor.PreferredBody;
Control.Font = UIFont.FromDescriptor(descriptor, descriptor.PointSize);
SetBorder(view);
}
}

View file

@ -1,6 +1,5 @@
using Bit.App.Controls;
using Bit.iOS.Controls;
using CoreGraphics;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
@ -18,31 +17,6 @@ namespace Bit.iOS.Controls
if(cell != null)
{
cell.BackgroundColor = extendedCell.BackgroundColor.ToUIColor();
if(extendedCell.ShowDisclousure)
{
cell.Accessory = UITableViewCellAccessory.DisclosureIndicator;
if(!string.IsNullOrEmpty(extendedCell.DisclousureImage))
{
var detailDisclosureButton = UIButton.FromType(UIButtonType.Custom);
detailDisclosureButton.SetImage(UIImage.FromBundle(extendedCell.DisclousureImage), UIControlState.Normal);
try
{
detailDisclosureButton.SetImage(UIImage.FromBundle(extendedCell.DisclousureImage + "_selected"), UIControlState.Selected);
}
catch
{
detailDisclosureButton.SetImage(UIImage.FromBundle(extendedCell.DisclousureImage), UIControlState.Selected);
}
detailDisclosureButton.Frame = new CGRect(0f, 0f, 50f, 100f);
detailDisclosureButton.TouchUpInside += (sender, e) =>
{
extendedCell.OnDisclousureTapped();
};
cell.AccessoryView = detailDisclosureButton;
}
}
}
return cell;

View file

@ -103,6 +103,7 @@
<Compile Include="Controls\ContentPageRenderer.cs" />
<Compile Include="Controls\CustomButtonRenderer.cs" />
<Compile Include="Controls\CustomLabelRenderer.cs" />
<Compile Include="Controls\ExtendedEditorRenderer.cs" />
<Compile Include="Controls\ExtendedSwitchCellRenderer.cs" />
<Compile Include="Controls\ListViewRenderer.cs" />
<Compile Include="Controls\ExtendedViewCellRenderer.cs" />