From d4b56e0e166eb4ae67827e301d56516e95052a43 Mon Sep 17 00:00:00 2001 From: Kyle Spearrin Date: Fri, 6 May 2016 22:29:03 -0400 Subject: [PATCH] Clipboard service and view site page --- src/Android/Android.csproj | 1 + src/Android/MainActivity.cs | 1 + src/Android/Services/ClipboardService.cs | 15 ++ .../Services/IClipboardService.cs | 7 + src/App/App.csproj | 2 +- src/App/Pages/VaultEditFolderPage.cs | 19 --- src/App/Pages/VaultEditSitePage.cs | 4 +- src/App/Pages/VaultListPage.cs | 15 +- src/App/Pages/VaultViewSitePage.cs | 151 +++++++++++++++++- src/iOS/AppDelegate.cs | 1 + src/iOS/Services/ClipboardService.cs | 14 ++ src/iOS/iOS.csproj | 1 + 12 files changed, 192 insertions(+), 39 deletions(-) create mode 100644 src/Android/Services/ClipboardService.cs create mode 100644 src/App/Abstractions/Services/IClipboardService.cs delete mode 100644 src/App/Pages/VaultEditFolderPage.cs create mode 100644 src/iOS/Services/ClipboardService.cs diff --git a/src/Android/Android.csproj b/src/Android/Android.csproj index a589de58c..573d0a0ef 100644 --- a/src/Android/Android.csproj +++ b/src/Android/Android.csproj @@ -197,6 +197,7 @@ + diff --git a/src/Android/MainActivity.cs b/src/Android/MainActivity.cs index 696bf2c88..413e85360 100644 --- a/src/Android/MainActivity.cs +++ b/src/Android/MainActivity.cs @@ -50,6 +50,7 @@ namespace Bit.Android .RegisterType(new ContainerControlledLifetimeManager()) .RegisterType(new ContainerControlledLifetimeManager()) .RegisterType(new ContainerControlledLifetimeManager()) + .RegisterType(new ContainerControlledLifetimeManager()) // Repositories .RegisterType(new ContainerControlledLifetimeManager()) .RegisterType(new ContainerControlledLifetimeManager()) diff --git a/src/Android/Services/ClipboardService.cs b/src/Android/Services/ClipboardService.cs new file mode 100644 index 000000000..c2308d289 --- /dev/null +++ b/src/Android/Services/ClipboardService.cs @@ -0,0 +1,15 @@ +using Android.Content; +using Bit.App.Abstractions; +using Xamarin.Forms; + +namespace Bit.Android.Services +{ + public class ClipboardService : IClipboardService + { + public void CopyToClipboard(string text) + { + var clipboardManager = (ClipboardManager)Forms.Context.GetSystemService(Context.ClipboardService); + clipboardManager.Text = text; + } + } +} diff --git a/src/App/Abstractions/Services/IClipboardService.cs b/src/App/Abstractions/Services/IClipboardService.cs new file mode 100644 index 000000000..ba4d54c58 --- /dev/null +++ b/src/App/Abstractions/Services/IClipboardService.cs @@ -0,0 +1,7 @@ +namespace Bit.App.Abstractions +{ + public interface IClipboardService + { + void CopyToClipboard(string text); + } +} diff --git a/src/App/App.csproj b/src/App/App.csproj index bb21c8877..497fc35e0 100644 --- a/src/App/App.csproj +++ b/src/App/App.csproj @@ -35,6 +35,7 @@ 4 + @@ -94,7 +95,6 @@ - diff --git a/src/App/Pages/VaultEditFolderPage.cs b/src/App/Pages/VaultEditFolderPage.cs deleted file mode 100644 index ff16f2e17..000000000 --- a/src/App/Pages/VaultEditFolderPage.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection.Emit; -using System.Text; - -using Xamarin.Forms; - -namespace Bit.App.Pages -{ - public class VaultEditFolderPage : ContentPage - { - public VaultEditFolderPage() - { - Title = "Edit Folder"; - Content = null; - } - } -} diff --git a/src/App/Pages/VaultEditSitePage.cs b/src/App/Pages/VaultEditSitePage.cs index d0921a08a..b9758567e 100644 --- a/src/App/Pages/VaultEditSitePage.cs +++ b/src/App/Pages/VaultEditSitePage.cs @@ -10,9 +10,9 @@ namespace Bit.App.Pages { public class VaultEditSitePage : ContentPage { - public VaultEditSitePage() + public VaultEditSitePage(string siteId) { - Title = "Edit Site"; + Title = "Edit Site " + siteId; Content = null; } } diff --git a/src/App/Pages/VaultListPage.cs b/src/App/Pages/VaultListPage.cs index 8a20fb68c..a682ebc58 100644 --- a/src/App/Pages/VaultListPage.cs +++ b/src/App/Pages/VaultListPage.cs @@ -67,7 +67,8 @@ namespace Bit.App.Pages private void SiteSelected(object sender, SelectedItemChangedEventArgs e) { - + var site = e.SelectedItem as VaultView.Site; + Navigation.PushAsync(new VaultViewSitePage(site.Id)); } private async void MoreClickedAsync(object sender, EventArgs e) @@ -121,17 +122,7 @@ namespace Bit.App.Pages private async void ClickedItem(object sender, EventArgs e) { - var selection = await _page.DisplayActionSheet("Add", "Cancel", null, "Add New Folder", "Add New Site"); - if(selection == "Add New Folder") - { - var addFolderPage = new VaultAddFolderPage(); - await _page.Navigation.PushAsync(addFolderPage); - } - else if(selection == "Add New Site") - { - var addSitePage = new VaultAddSitePage(); - await _page.Navigation.PushAsync(addSitePage); - } + await _page.Navigation.PushAsync(new VaultAddSitePage()); } } diff --git a/src/App/Pages/VaultViewSitePage.cs b/src/App/Pages/VaultViewSitePage.cs index 2e7cb0a2f..64491c1c4 100644 --- a/src/App/Pages/VaultViewSitePage.cs +++ b/src/App/Pages/VaultViewSitePage.cs @@ -3,21 +3,162 @@ using System.Collections.Generic; using System.Linq; using System.Reflection.Emit; using System.Text; - +using Acr.UserDialogs; +using Bit.App.Abstractions; using Xamarin.Forms; +using XLabs.Ioc; namespace Bit.App.Pages { public class VaultViewSitePage : ContentPage { - private int _siteId; + private readonly string _siteId; + private readonly ISiteService _siteService; + private readonly IUserDialogs _userDialogs; + private readonly IClipboardService _clipboardService; - public VaultViewSitePage(int siteId) + public VaultViewSitePage(string siteId) { _siteId = siteId; + _siteService = Resolver.Resolve(); + _userDialogs = Resolver.Resolve(); + _clipboardService = Resolver.Resolve(); - Title = "View Site"; - Content = null; + Init(); + } + + public void Init() + { + ToolbarItems.Add(new EditSiteToolBarItem(this, _siteId)); + + var site = _siteService.GetByIdAsync(_siteId).GetAwaiter().GetResult(); + if(site == null) + { + // TODO: handle error. navigate back? should never happen... + return; + } + + var usernameRow = new StackLayout { Orientation = StackOrientation.Horizontal }; + var usernameLabel = new Label + { + Text = site.Username?.Decrypt(), + HorizontalOptions = LayoutOptions.StartAndExpand, + VerticalOptions = LayoutOptions.Center, + LineBreakMode = LineBreakMode.TailTruncation + }; + usernameRow.Children.Add(usernameLabel); + usernameRow.Children.Add(new Button + { + Text = "Copy", + HorizontalOptions = LayoutOptions.End, + VerticalOptions = LayoutOptions.Center, + Command = new Command(() => Copy(usernameLabel.Text, "Username")) + }); + + var passwordRow = new StackLayout { Orientation = StackOrientation.Horizontal }; + var password = site.Password?.Decrypt(); + var passwordLabel = new Label + { + Text = new string('●', password.Length), + HorizontalOptions = LayoutOptions.StartAndExpand, + VerticalOptions = LayoutOptions.Center, + LineBreakMode = LineBreakMode.TailTruncation + }; + passwordRow.Children.Add(passwordLabel); + var togglePasswordButton = new Button + { + Text = "Show", + HorizontalOptions = LayoutOptions.End, + VerticalOptions = LayoutOptions.Center, + Command = new Command((self) => TogglePassword(self as Button, passwordLabel, password)) + }; + togglePasswordButton.CommandParameter = togglePasswordButton; + passwordRow.Children.Add(togglePasswordButton); + passwordRow.Children.Add(new Button + { + Text = "Copy", + HorizontalOptions = LayoutOptions.End, + VerticalOptions = LayoutOptions.Center, + Command = new Command(() => Copy(password, "Password")) + }); + + var uriRow = new StackLayout { Orientation = StackOrientation.Horizontal }; + var uri = site.Uri?.Decrypt(); + uriRow.Children.Add(new Label + { + Text = uri, + HorizontalOptions = LayoutOptions.StartAndExpand, + VerticalOptions = LayoutOptions.Center, + LineBreakMode = LineBreakMode.TailTruncation + }); + uriRow.Children.Add(new Button + { + Text = "Launch", + HorizontalOptions = LayoutOptions.End, + VerticalOptions = LayoutOptions.Center, + Command = new Command(() => Device.OpenUri(new Uri(uri))) + }); + + var stackLayout = new StackLayout(); + stackLayout.Children.Add(new Label { Text = "Username" }); + stackLayout.Children.Add(usernameRow); + stackLayout.Children.Add(new Label { Text = "Password" }); + stackLayout.Children.Add(passwordRow); + stackLayout.Children.Add(new Label { Text = "Website" }); + stackLayout.Children.Add(uriRow); + if(site.Notes != null) + { + stackLayout.Children.Add(new Label { Text = "Notes" }); + stackLayout.Children.Add(new Label { Text = site.Notes.Decrypt() }); + } + + var scrollView = new ScrollView + { + Content = stackLayout, + Orientation = ScrollOrientation.Vertical + }; + + Title = site.Name?.Decrypt() ?? "No Name"; + Content = scrollView; + } + + public void TogglePassword(Button toggleButton, Label passwordLabel, string password) + { + if(toggleButton.Text == "Show") + { + toggleButton.Text = "Hide"; + passwordLabel.Text = password; + } + else + { + toggleButton.Text = "Show"; + passwordLabel.Text = new string('●', password.Length); + } + } + + public void Copy(string copyText, string alertLabel) + { + _clipboardService.CopyToClipboard(copyText); + _userDialogs.SuccessToast($"{alertLabel} has been copied."); + } + + private class EditSiteToolBarItem : ToolbarItem + { + private readonly VaultViewSitePage _page; + private readonly string _siteId; + + public EditSiteToolBarItem(VaultViewSitePage page, string siteId) + { + _page = page; + _siteId = siteId; + Text = "Edit"; + Clicked += ClickedItem; + } + + private async void ClickedItem(object sender, EventArgs e) + { + await _page.Navigation.PushAsync(new VaultEditSitePage(_siteId)); + } } } } diff --git a/src/iOS/AppDelegate.cs b/src/iOS/AppDelegate.cs index 56bd49a93..135db2db1 100644 --- a/src/iOS/AppDelegate.cs +++ b/src/iOS/AppDelegate.cs @@ -58,6 +58,7 @@ namespace Bit.iOS .RegisterType(new ContainerControlledLifetimeManager()) .RegisterType(new ContainerControlledLifetimeManager()) .RegisterType(new ContainerControlledLifetimeManager()) + .RegisterType(new ContainerControlledLifetimeManager()) // Repositories .RegisterType(new ContainerControlledLifetimeManager()) .RegisterType(new ContainerControlledLifetimeManager()) diff --git a/src/iOS/Services/ClipboardService.cs b/src/iOS/Services/ClipboardService.cs new file mode 100644 index 000000000..8ac1f4d3a --- /dev/null +++ b/src/iOS/Services/ClipboardService.cs @@ -0,0 +1,14 @@ +using Bit.App.Abstractions; +using UIKit; + +namespace Bit.iOS.Services +{ + public class ClipboardService : IClipboardService + { + public void CopyToClipboard(string text) + { + UIPasteboard clipboard = UIPasteboard.General; + clipboard.String = text; + } + } +} diff --git a/src/iOS/iOS.csproj b/src/iOS/iOS.csproj index 6489af708..48d277972 100644 --- a/src/iOS/iOS.csproj +++ b/src/iOS/iOS.csproj @@ -91,6 +91,7 @@ Entitlements.plist +