diff --git a/src/App/App.csproj b/src/App/App.csproj index 45c41f270..ab30c1057 100644 --- a/src/App/App.csproj +++ b/src/App/App.csproj @@ -53,6 +53,7 @@ + diff --git a/src/App/Controls/LabeledValueCell.cs b/src/App/Controls/LabeledValueCell.cs new file mode 100644 index 000000000..5d1fb11a8 --- /dev/null +++ b/src/App/Controls/LabeledValueCell.cs @@ -0,0 +1,97 @@ +using Acr.UserDialogs; +using Bit.App.Abstractions; +using Bit.App.Resources; +using System; +using Xamarin.Forms; +using XLabs.Ioc; + +namespace Bit.App.Controls +{ + public class LabeledValueCell : ViewCell + { + private readonly IUserDialogs _userDialogs; + private readonly IClipboardService _clipboardService; + + public LabeledValueCell( + string labelText, + string valueText = null, + bool copyValue = false, + bool password = false, + bool launch = false) + { + _userDialogs = Resolver.Resolve(); + _clipboardService = Resolver.Resolve(); + + var stackLayout = new StackLayout + { + Padding = new Thickness(15, 15, 15, 0), + BackgroundColor = Color.White + }; + + if(labelText != null) + { + Label = new Label + { + Text = labelText, + FontSize = 14, + TextColor = Color.FromHex("777777") + }; + + stackLayout.Children.Add(Label); + } + + Value = new Label + { + Text = valueText, + LineBreakMode = LineBreakMode.TailTruncation, + HorizontalOptions = LayoutOptions.StartAndExpand, + VerticalOptions = LayoutOptions.Center + }; + + var valueStackLayout = new StackLayout + { + Orientation = StackOrientation.Horizontal + }; + valueStackLayout.Children.Add(Value); + + if(copyValue) + { + var copyButton = new Button + { + Text = AppResources.Copy, + HorizontalOptions = LayoutOptions.End, + VerticalOptions = LayoutOptions.Center, + Command = new Command(() => Copy()) + }; + + valueStackLayout.Children.Add(copyButton); + } + + if(launch) + { + var launchButton = new Button + { + Text = AppResources.Launch, + HorizontalOptions = LayoutOptions.End, + VerticalOptions = LayoutOptions.Center, + Command = new Command(() => Device.OpenUri(new Uri(Value.Text))) + }; + + valueStackLayout.Children.Add(launchButton); + } + + stackLayout.Children.Add(valueStackLayout); + + View = stackLayout; + } + + public Label Label { get; private set; } + public Label Value { get; private set; } + + private void Copy() + { + _clipboardService.CopyToClipboard(Value.Text); + _userDialogs.SuccessToast(string.Format(AppResources.ValueHasBeenCopied, Label.Text)); + } + } +} diff --git a/src/App/Pages/VaultListPage.cs b/src/App/Pages/VaultListPage.cs index 6e2fbd7fd..c976a69b2 100644 --- a/src/App/Pages/VaultListPage.cs +++ b/src/App/Pages/VaultListPage.cs @@ -42,7 +42,6 @@ namespace Bit.App.Pages Title = AppResources.MyVault; Content = listView; - NavigationPage.SetBackButtonTitle(this, AppResources.Back); } protected override void OnAppearing() diff --git a/src/App/Pages/VaultViewSitePage.cs b/src/App/Pages/VaultViewSitePage.cs index 06cec8bb1..f5a5e5f06 100644 --- a/src/App/Pages/VaultViewSitePage.cs +++ b/src/App/Pages/VaultViewSitePage.cs @@ -27,101 +27,70 @@ namespace Bit.App.Pages } private VaultViewSitePageModel Model { get; set; } = new VaultViewSitePageModel(); + private ExtendedTableView Table { get; set; } private void Init() { ToolbarItems.Add(new EditSiteToolBarItem(this, _siteId)); ToolbarItems.Add(new DismissModalToolBarItem(this)); - var stackLayout = new StackLayout(); // Username - var usernameRow = new StackLayout { Orientation = StackOrientation.Horizontal }; - var usernameLabel = new Label - { - HorizontalOptions = LayoutOptions.StartAndExpand, - VerticalOptions = LayoutOptions.Center, - LineBreakMode = LineBreakMode.TailTruncation - }; - usernameLabel.SetBinding(Label.TextProperty, s => s.Username); - usernameRow.Children.Add(usernameLabel); - usernameRow.Children.Add(new Button - { - Text = AppResources.Copy, - HorizontalOptions = LayoutOptions.End, - VerticalOptions = LayoutOptions.Center, - Command = new Command(() => Copy(usernameLabel.Text, AppResources.Username)) - }); - stackLayout.Children.Add(new Label { Text = AppResources.Username }); - stackLayout.Children.Add(usernameRow); + var nameCell = new LabeledValueCell(AppResources.Name); + nameCell.Value.SetBinding(Label.TextProperty, s => s.Name); + + // Username + var usernameCell = new LabeledValueCell(AppResources.Username, copyValue: true); + usernameCell.Value.SetBinding(Label.TextProperty, s => s.Username); // Password - var passwordRow = new StackLayout { Orientation = StackOrientation.Horizontal }; - var passwordLabel = new Label - { - HorizontalOptions = LayoutOptions.StartAndExpand, - VerticalOptions = LayoutOptions.Center, - LineBreakMode = LineBreakMode.TailTruncation - }; - passwordLabel.SetBinding(Label.TextProperty, s => s.MaskedPassword); - passwordRow.Children.Add(passwordLabel); - var togglePasswordButton = new Button - { - HorizontalOptions = LayoutOptions.End, - VerticalOptions = LayoutOptions.Center, - Command = new Command(() => Model.ShowPassword = !Model.ShowPassword) - }; - togglePasswordButton.CommandParameter = togglePasswordButton; - togglePasswordButton.SetBinding(Button.TextProperty, s => s.ShowHideText); - passwordRow.Children.Add(togglePasswordButton); - passwordRow.Children.Add(new Button - { - Text = AppResources.Copy, - HorizontalOptions = LayoutOptions.End, - VerticalOptions = LayoutOptions.Center, - Command = new Command(() => Copy(Model.Password, AppResources.Password)) - }); - stackLayout.Children.Add(new Label { Text = AppResources.Password }); - stackLayout.Children.Add(passwordRow); + var passwordCell = new LabeledValueCell(AppResources.Password, copyValue: true); + passwordCell.Value.SetBinding(Label.TextProperty, s => s.Password); // URI - var uriRow = new StackLayout { Orientation = StackOrientation.Horizontal }; - var uriLabel = new Label - { - HorizontalOptions = LayoutOptions.StartAndExpand, - VerticalOptions = LayoutOptions.Center, - LineBreakMode = LineBreakMode.TailTruncation - }; - uriLabel.SetBinding(Label.TextProperty, s => s.Uri); - uriRow.Children.Add(uriLabel); - uriRow.Children.Add(new Button - { - Text = AppResources.Launch, - HorizontalOptions = LayoutOptions.End, - VerticalOptions = LayoutOptions.Center, - Command = new Command(() => Device.OpenUri(new Uri(uriLabel.Text))) - }); - stackLayout.Children.Add(new Label { Text = AppResources.Website }); - stackLayout.Children.Add(uriRow); + var uriCell = new LabeledValueCell(AppResources.URI, launch: true); + uriCell.Value.SetBinding(Label.TextProperty, s => s.Uri); // Notes - var notes = new Label { Text = AppResources.Notes }; - notes.SetBinding(Label.IsVisibleProperty, s => s.ShowNotes); - stackLayout.Children.Add(notes); - var notesLabel = new Label(); - notesLabel.SetBinding(Label.TextProperty, s => s.Notes); - notesLabel.SetBinding(Label.IsVisibleProperty, s => s.ShowNotes); - stackLayout.Children.Add(notesLabel); + var notesCell = new LabeledValueCell(AppResources.Notes); + notesCell.Value.SetBinding(Label.TextProperty, s => s.Notes); + + Table = new ExtendedTableView + { + Intent = TableIntent.Settings, + EnableScrolling = false, + HasUnevenRows = true, + EnableSelection = true, + Root = new TableRoot + { + new TableSection("Site Information") + { + uriCell, + nameCell, + usernameCell, + passwordCell + }, + new TableSection(AppResources.Notes) + { + notesCell + } + } + }; + + if(Device.OS == TargetPlatform.iOS) + { + Table.RowHeight = -1; + Table.EstimatedRowHeight = 70; + } var scrollView = new ScrollView { - Content = stackLayout, + Content = Table, Orientation = ScrollOrientation.Vertical }; SetBinding(Page.TitleProperty, new Binding("PageTitle")); Content = scrollView; BindingContext = Model; - NavigationPage.SetBackButtonTitle(this, AppResources.Back); } protected override void OnAppearing() @@ -136,6 +105,10 @@ namespace Bit.App.Pages Model.Update(site); base.OnAppearing(); + + // Hack to get table row height binding to update. Better way to do this probably? + Table.Root.Add(new TableSection { new TextCell() }); + Table.Root.RemoveAt(Table.Root.Count - 1); } private void Copy(string copyText, string alertLabel)