TableView to add site page

This commit is contained in:
Kyle Spearrin 2016-05-11 17:30:09 -04:00
parent 15be1cbf43
commit 6fd81fc40e
11 changed files with 133 additions and 156 deletions

View file

@ -45,7 +45,6 @@
<Compile Include="Behaviors\ConnectivityBehavior.cs" /> <Compile Include="Behaviors\ConnectivityBehavior.cs" />
<Compile Include="Behaviors\RequiredValidationBehavior.cs" /> <Compile Include="Behaviors\RequiredValidationBehavior.cs" />
<Compile Include="Controls\EntryLabel.cs" /> <Compile Include="Controls\EntryLabel.cs" />
<Compile Include="Controls\BottomBorderEntry.cs" />
<Compile Include="Controls\ExtendedPicker.cs" /> <Compile Include="Controls\ExtendedPicker.cs" />
<Compile Include="Controls\ExtendedEntry.cs" /> <Compile Include="Controls\ExtendedEntry.cs" />
<Compile Include="Controls\ExtendedTabbedPage.cs" /> <Compile Include="Controls\ExtendedTabbedPage.cs" />

View file

@ -1,13 +0,0 @@
using Xamarin.Forms;
namespace Bit.App.Controls
{
public class BottomBorderEntry : ExtendedEntry
{
public BottomBorderEntry()
{
HasBorder = HasOnlyBottomBorder = true;
BottomBorderColor = Color.FromHex("d2d6de");
}
}
}

View file

@ -8,28 +8,10 @@ namespace Bit.App.Controls
public static readonly BindableProperty HasBorderProperty = public static readonly BindableProperty HasBorderProperty =
BindableProperty.Create(nameof(HasBorder), typeof(bool), typeof(ExtendedEntry), true); BindableProperty.Create(nameof(HasBorder), typeof(bool), typeof(ExtendedEntry), true);
public static readonly BindableProperty HasOnlyBottomBorderProperty =
BindableProperty.Create(nameof(HasOnlyBottomBorder), typeof(bool), typeof(ExtendedEntry), false);
public static readonly BindableProperty BottomBorderColorProperty =
BindableProperty.Create(nameof(BottomBorderColor), typeof(Color), typeof(ExtendedEntry), Color.Default);
public bool HasBorder public bool HasBorder
{ {
get { return (bool)GetValue(HasBorderProperty); } get { return (bool)GetValue(HasBorderProperty); }
set { SetValue(HasBorderProperty, value); } set { SetValue(HasBorderProperty, value); }
} }
public bool HasOnlyBottomBorder
{
get { return (bool)GetValue(HasOnlyBottomBorderProperty); }
set { SetValue(HasOnlyBottomBorderProperty, value); }
}
public Color BottomBorderColor
{
get { return (Color)GetValue(BottomBorderColorProperty); }
set { SetValue(BottomBorderColorProperty, value); }
}
} }
} }

View file

@ -19,27 +19,12 @@ namespace Bit.App.Pages
private void Init() private void Init()
{ {
var foldersLayout = new StackLayout { Orientation = StackOrientation.Horizontal }; var foldersCell = new TextCell { Text = "Folders" };
foldersLayout.Children.Add(new Label
{
Text = "Folders",
HorizontalOptions = LayoutOptions.StartAndExpand,
VerticalOptions = LayoutOptions.Center,
Margin = new Thickness(10, 0, 0, 0)
});
foldersLayout.Children.Add(new Image
{
Source = ImageSource.FromFile("ion-chevron-right.png"),
Opacity = 0.3,
HorizontalOptions = LayoutOptions.End,
VerticalOptions = LayoutOptions.Center,
Margin = new Thickness(0, 0, 10, 0)
});
var foldersCell = new ViewCell { View = foldersLayout };
foldersCell.Tapped += FoldersCell_Tapped; foldersCell.Tapped += FoldersCell_Tapped;
var table = new TableView var table = new TableView
{ {
Intent = TableIntent.Menu,
Root = new TableRoot Root = new TableRoot
{ {
new TableSection("Manage Folders") new TableSection("Manage Folders")

View file

@ -30,25 +30,25 @@ namespace Bit.App.Pages
var syncButton = new Button var syncButton = new Button
{ {
Text = "Sync Vault", Text = "Sync Vault",
Command = new Command( async () => await SyncAsync() ) Command = new Command(async () => await SyncAsync())
}; };
var stackLayout = new StackLayout { }; var stackLayout = new StackLayout { };
stackLayout.Children.Add( syncButton ); stackLayout.Children.Add(syncButton);
stackLayout.Children.Add( new ExtendedEntry stackLayout.Children.Add(new ExtendedEntry
{ {
BottomBorderColor = Color.Black, BottomBorderColor = Color.Black,
HasBorder = true, HasBorder = true,
HasOnlyBottomBorder = true, HasOnlyBottomBorder = true,
Placeholder = "Some placeholder", Placeholder = "Some placeholder",
PlaceholderColor = Color.Red PlaceholderColor = Color.Red
} ); });
Title = "Sync"; Title = "Sync";
Content = stackLayout; Content = stackLayout;
Icon = "fa-refresh"; Icon = "fa-refresh";
if( !_connectivity.IsConnected ) if(!_connectivity.IsConnected)
{ {
AlertNoConnection(); AlertNoConnection();
} }
@ -56,28 +56,28 @@ namespace Bit.App.Pages
public async Task SyncAsync() public async Task SyncAsync()
{ {
if( !_connectivity.IsConnected ) if(!_connectivity.IsConnected)
{ {
AlertNoConnection(); AlertNoConnection();
return; return;
} }
_userDialogs.ShowLoading( "Syncing...", MaskType.Black ); _userDialogs.ShowLoading("Syncing...", MaskType.Black);
var succeeded = await _syncService.SyncAsync(); var succeeded = await _syncService.SyncAsync();
_userDialogs.HideLoading(); _userDialogs.HideLoading();
if( succeeded ) if(succeeded)
{ {
_userDialogs.SuccessToast( "Syncing complete." ); _userDialogs.SuccessToast("Syncing complete.");
} }
else else
{ {
_userDialogs.ErrorToast( "Syncing failed." ); _userDialogs.ErrorToast("Syncing failed.");
} }
} }
public void AlertNoConnection() public void AlertNoConnection()
{ {
DisplayAlert( AppResources.InternetConnectionRequiredTitle, AppResources.InternetConnectionRequiredMessage, AppResources.Ok ); DisplayAlert(AppResources.InternetConnectionRequiredTitle, AppResources.InternetConnectionRequiredMessage, AppResources.Ok);
} }
} }
} }

View file

@ -30,94 +30,130 @@ namespace Bit.App.Pages
private void Init() private void Init()
{ {
var folders = _folderService.GetAllAsync().GetAwaiter().GetResult().OrderBy( f => f.Name?.Decrypt() ); var folders = _folderService.GetAllAsync().GetAwaiter().GetResult().OrderBy(f => f.Name?.Decrypt());
var uriEntry = new BottomBorderEntry { Keyboard = Keyboard.Url }; var uriEntry = new ExtendedEntry { Keyboard = Keyboard.Url, HasBorder = false };
var nameEntry = new BottomBorderEntry(); var nameEntry = new ExtendedEntry { HasBorder = false };
var folderPicker = new ExtendedPicker var folderPicker = new ExtendedPicker { Title = AppResources.Folder, HasBorder = false };
{ folderPicker.Items.Add(AppResources.FolderNone);
Title = AppResources.Folder,
BottomBorderColor = Color.FromHex( "d2d6de" ),
HasOnlyBottomBorder = true
};
folderPicker.Items.Add( AppResources.FolderNone );
folderPicker.SelectedIndex = 0; folderPicker.SelectedIndex = 0;
foreach( var folder in folders ) foreach(var folder in folders)
{ {
folderPicker.Items.Add( folder.Name.Decrypt() ); folderPicker.Items.Add(folder.Name.Decrypt());
} }
var usernameEntry = new BottomBorderEntry(); var usernameEntry = new ExtendedEntry { HasBorder = false };
var passwordEntry = new BottomBorderEntry { IsPassword = true }; var passwordEntry = new ExtendedEntry { IsPassword = true, HasBorder = false };
var notesEditor = new Editor { HeightRequest = 75 }; var notesEditor = new Editor { HeightRequest = 75 };
var stackLayout = new StackLayout { Padding = new Thickness( 15 ) }; var uriStackLayout = new FormEntryStackLayout();
stackLayout.Children.Add( new EntryLabel { Text = AppResources.URI } ); uriStackLayout.Children.Add(new EntryLabel { Text = AppResources.URI });
stackLayout.Children.Add( uriEntry ); uriStackLayout.Children.Add(uriEntry);
stackLayout.Children.Add( new EntryLabel { Text = AppResources.Name, Margin = new Thickness( 0, 15, 0, 0 ) } ); var uriCell = new ViewCell();
stackLayout.Children.Add( nameEntry ); uriCell.View = uriStackLayout;
stackLayout.Children.Add( new EntryLabel { Text = AppResources.Folder, Margin = new Thickness( 0, 15, 0, 0 ) } );
stackLayout.Children.Add( folderPicker ); var nameStackLayout = new FormEntryStackLayout();
stackLayout.Children.Add( new EntryLabel { Text = AppResources.Username, Margin = new Thickness( 0, 15, 0, 0 ) } ); nameStackLayout.Children.Add(new EntryLabel { Text = AppResources.Name });
stackLayout.Children.Add( usernameEntry ); nameStackLayout.Children.Add(nameEntry);
stackLayout.Children.Add( new EntryLabel { Text = AppResources.Password, Margin = new Thickness( 0, 15, 0, 0 ) } ); var nameCell = new ViewCell();
stackLayout.Children.Add( passwordEntry ); nameCell.View = nameStackLayout;
stackLayout.Children.Add( new EntryLabel { Text = AppResources.Notes, Margin = new Thickness( 0, 15, 0, 0 ) } );
stackLayout.Children.Add( notesEditor ); var folderStackLayout = new FormEntryStackLayout();
folderStackLayout.Children.Add(new EntryLabel { Text = AppResources.Folder });
folderStackLayout.Children.Add(folderPicker);
var folderCell = new ViewCell();
folderCell.View = folderStackLayout;
var usernameStackLayout = new FormEntryStackLayout();
usernameStackLayout.Children.Add(new EntryLabel { Text = AppResources.Username });
usernameStackLayout.Children.Add(usernameEntry);
var usernameCell = new ViewCell();
usernameCell.View = usernameStackLayout;
var passwordStackLayout = new FormEntryStackLayout();
passwordStackLayout.Children.Add(new EntryLabel { Text = AppResources.Password });
passwordStackLayout.Children.Add(passwordEntry);
var passwordCell = new ViewCell();
passwordCell.View = passwordStackLayout;
var notesStackLayout = new FormEntryStackLayout();
notesStackLayout.Children.Add(new EntryLabel { Text = AppResources.Notes });
notesStackLayout.Children.Add(notesEditor);
var notesCell = new ViewCell();
notesCell.View = notesStackLayout;
var table = new TableView
{
Intent = TableIntent.Form,
RowHeight = 65,
HasUnevenRows = true,
Root = new TableRoot
{
new TableSection
{
uriCell,
nameCell,
folderCell,
usernameCell,
passwordCell,
notesCell
}
}
};
var scrollView = new ScrollView var scrollView = new ScrollView
{ {
Content = stackLayout, Content = table,
Orientation = ScrollOrientation.Vertical Orientation = ScrollOrientation.Vertical
}; };
var saveToolBarItem = new ToolbarItem( AppResources.Save, null, async () => var saveToolBarItem = new ToolbarItem(AppResources.Save, null, async () =>
{ {
if( !_connectivity.IsConnected ) if(!_connectivity.IsConnected)
{ {
AlertNoConnection(); AlertNoConnection();
return; return;
} }
if( string.IsNullOrWhiteSpace( uriEntry.Text ) ) if(string.IsNullOrWhiteSpace(uriEntry.Text))
{ {
await DisplayAlert( AppResources.AnErrorHasOccurred, string.Format( AppResources.ValidationFieldRequired, AppResources.URI ), AppResources.Ok ); await DisplayAlert(AppResources.AnErrorHasOccurred, string.Format(AppResources.ValidationFieldRequired, AppResources.URI), AppResources.Ok);
return; return;
} }
if( string.IsNullOrWhiteSpace( nameEntry.Text ) ) if(string.IsNullOrWhiteSpace(nameEntry.Text))
{ {
await DisplayAlert( AppResources.AnErrorHasOccurred, string.Format( AppResources.ValidationFieldRequired, AppResources.Name ), AppResources.Ok ); await DisplayAlert(AppResources.AnErrorHasOccurred, string.Format(AppResources.ValidationFieldRequired, AppResources.Name), AppResources.Ok);
return; return;
} }
var site = new Site var site = new Site
{ {
Uri = uriEntry.Text.Encrypt(), Uri = uriEntry.Text.Encrypt(),
Name = nameEntry.Text.Encrypt(), Name = nameEntry.Text.Encrypt(),
Username = usernameEntry.Text?.Encrypt(), Username = usernameEntry.Text?.Encrypt(),
Password = passwordEntry.Text?.Encrypt(), Password = passwordEntry.Text?.Encrypt(),
Notes = notesEditor.Text?.Encrypt(), Notes = notesEditor.Text?.Encrypt(),
}; };
if( folderPicker.SelectedIndex > 0 ) if(folderPicker.SelectedIndex > 0)
{ {
site.FolderId = folders.ElementAt( folderPicker.SelectedIndex - 1 ).Id; site.FolderId = folders.ElementAt(folderPicker.SelectedIndex - 1).Id;
} }
var saveTask = _siteService.SaveAsync( site ); var saveTask = _siteService.SaveAsync(site);
_userDialogs.ShowLoading( "Saving...", MaskType.Black ); _userDialogs.ShowLoading("Saving...", MaskType.Black);
await saveTask; await saveTask;
_userDialogs.HideLoading(); _userDialogs.HideLoading();
await Navigation.PopAsync(); await Navigation.PopAsync();
_userDialogs.SuccessToast( nameEntry.Text, "New site created." ); _userDialogs.SuccessToast(nameEntry.Text, "New site created.");
}, ToolbarItemOrder.Default, 0 ); }, ToolbarItemOrder.Default, 0);
Title = AppResources.AddSite; Title = AppResources.AddSite;
Content = scrollView; Content = scrollView;
ToolbarItems.Add( saveToolBarItem ); ToolbarItems.Add(saveToolBarItem);
if( !_connectivity.IsConnected ) if(!_connectivity.IsConnected)
{ {
AlertNoConnection(); AlertNoConnection();
} }
@ -125,7 +161,15 @@ namespace Bit.App.Pages
private void AlertNoConnection() private void AlertNoConnection()
{ {
DisplayAlert( AppResources.InternetConnectionRequiredTitle, AppResources.InternetConnectionRequiredMessage, AppResources.Ok ); DisplayAlert(AppResources.InternetConnectionRequiredTitle, AppResources.InternetConnectionRequiredMessage, AppResources.Ok);
}
private class FormEntryStackLayout : StackLayout
{
public FormEntryStackLayout()
{
Padding = new Thickness(15, 15, 15, 0);
}
} }
} }
} }

View file

@ -132,6 +132,8 @@ namespace Bit.App.Pages
} }
Model.Update(site); Model.Update(site);
base.OnAppearing();
} }
private void Copy(string copyText, string alertLabel) private void Copy(string copyText, string alertLabel)

View file

@ -8,7 +8,7 @@ using Foundation;
namespace Bit.iOS.Extension namespace Bit.iOS.Extension
{ {
[Register("ActionViewController")] [Register("ActionViewController")]
partial class ActionViewController partial class ActionViewController
{ {
[Outlet] [Outlet]

View file

@ -2,13 +2,11 @@
using System.ComponentModel; using System.ComponentModel;
using Bit.App.Controls; using Bit.App.Controls;
using Bit.iOS.Controls; using Bit.iOS.Controls;
using CoreAnimation;
using CoreGraphics;
using UIKit; using UIKit;
using Xamarin.Forms; using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS; using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(ExtendedPicker), typeof( ExtendedPickerRenderer ) )] [assembly: ExportRenderer(typeof(ExtendedPicker), typeof(ExtendedPickerRenderer))]
namespace Bit.iOS.Controls namespace Bit.iOS.Controls
{ {
public class ExtendedPickerRenderer : PickerRenderer public class ExtendedPickerRenderer : PickerRenderer
@ -30,35 +28,15 @@ namespace Bit.iOS.Controls
var view = (ExtendedPicker)Element; var view = (ExtendedPicker)Element;
if(e.PropertyName == ExtendedPicker.HasBorderProperty.PropertyName if(e.PropertyName == ExtendedPicker.HasBorderProperty.PropertyName)
|| e.PropertyName == ExtendedPicker.HasOnlyBottomBorderProperty.PropertyName
|| e.PropertyName == ExtendedPicker.BottomBorderColorProperty.PropertyName)
{ {
SetBorder(view); SetBorder(view);
} }
} }
private void SetBorder( ExtendedPicker view ) private void SetBorder(ExtendedPicker view)
{ {
if(view.HasOnlyBottomBorder) Control.BorderStyle = view.HasBorder ? UITextBorderStyle.RoundedRect : UITextBorderStyle.None;
{
var borderLayer = new CALayer();
borderLayer.MasksToBounds = true;
borderLayer.Frame = new CGRect( 0f, Frame.Height / 2, Frame.Width * 2, 1f );
borderLayer.BorderColor = view.BottomBorderColor.ToCGColor();
borderLayer.BorderWidth = 1f;
Control.Layer.AddSublayer( borderLayer );
Control.BorderStyle = UITextBorderStyle.None;
}
else if(view.HasBorder)
{
Control.BorderStyle = UITextBorderStyle.RoundedRect;
}
else
{
Control.BorderStyle = UITextBorderStyle.None;
}
} }
} }
} }

View file

@ -7,7 +7,7 @@ using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(ExtendedTabbedPage), typeof(ExtendedTabbedPageRenderer))] [assembly: ExportRenderer(typeof(ExtendedTabbedPage), typeof(ExtendedTabbedPageRenderer))]
namespace Bit.iOS.Controls namespace Bit.iOS.Controls
{ {
public class ExtendedTabbedPageRenderer: TabbedRenderer public class ExtendedTabbedPageRenderer : TabbedRenderer
{ {
protected override void OnElementChanged(VisualElementChangedEventArgs e) protected override void OnElementChanged(VisualElementChangedEventArgs e)
{ {