mirror of
https://github.com/bitwarden/android.git
synced 2024-12-18 23:31:52 +03:00
Wired up view page functionality. Expanded LabeledValueCell. Created custom group template for vault list page.
This commit is contained in:
parent
d288116b39
commit
4e906f9370
12 changed files with 155 additions and 49 deletions
|
@ -11,6 +11,9 @@ namespace Bit.App.Controls
|
|||
public static readonly BindableProperty EnableSelectionProperty =
|
||||
BindableProperty.Create(nameof(EnableSelection), typeof(bool), typeof(ExtendedTableView), true);
|
||||
|
||||
public static readonly BindableProperty SeparatorColorProperty =
|
||||
BindableProperty.Create(nameof(SeparatorColor), typeof(Color), typeof(ExtendedTableView), Color.FromHex("d2d6de"));
|
||||
|
||||
public bool EnableScrolling
|
||||
{
|
||||
get { return (bool)GetValue(EnableScrollingProperty); }
|
||||
|
@ -23,6 +26,12 @@ namespace Bit.App.Controls
|
|||
set { SetValue(EnableSelectionProperty, value); }
|
||||
}
|
||||
|
||||
public Color SeparatorColor
|
||||
{
|
||||
get { return (Color)GetValue(SeparatorColorProperty); }
|
||||
set { SetValue(SeparatorColorProperty, value); }
|
||||
}
|
||||
|
||||
public int EstimatedRowHeight { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,20 +9,13 @@ namespace Bit.App.Controls
|
|||
{
|
||||
public class LabeledValueCell : ViewCell
|
||||
{
|
||||
private readonly IUserDialogs _userDialogs;
|
||||
private readonly IClipboardService _clipboardService;
|
||||
|
||||
public LabeledValueCell(
|
||||
string labelText,
|
||||
string labelText = null,
|
||||
string valueText = null,
|
||||
bool copyValue = false,
|
||||
bool password = false,
|
||||
bool launch = false)
|
||||
string button1Text = null,
|
||||
string button2Text = null)
|
||||
{
|
||||
_userDialogs = Resolver.Resolve<IUserDialogs>();
|
||||
_clipboardService = Resolver.Resolve<IClipboardService>();
|
||||
|
||||
var stackLayout = new StackLayout
|
||||
StackLayout = new StackLayout
|
||||
{
|
||||
Padding = new Thickness(15, 15, 15, 0),
|
||||
BackgroundColor = Color.White
|
||||
|
@ -37,7 +30,7 @@ namespace Bit.App.Controls
|
|||
TextColor = Color.FromHex("777777")
|
||||
};
|
||||
|
||||
stackLayout.Children.Add(Label);
|
||||
StackLayout.Children.Add(Label);
|
||||
}
|
||||
|
||||
Value = new Label
|
||||
|
@ -52,46 +45,42 @@ namespace Bit.App.Controls
|
|||
{
|
||||
Orientation = StackOrientation.Horizontal
|
||||
};
|
||||
|
||||
valueStackLayout.Children.Add(Value);
|
||||
|
||||
if(copyValue)
|
||||
if(button1Text != null)
|
||||
{
|
||||
var copyButton = new Button
|
||||
Button1 = new Button
|
||||
{
|
||||
Text = AppResources.Copy,
|
||||
Text = button1Text,
|
||||
HorizontalOptions = LayoutOptions.End,
|
||||
VerticalOptions = LayoutOptions.Center,
|
||||
Command = new Command(() => Copy())
|
||||
VerticalOptions = LayoutOptions.Center
|
||||
};
|
||||
|
||||
valueStackLayout.Children.Add(copyButton);
|
||||
valueStackLayout.Children.Add(Button1);
|
||||
}
|
||||
|
||||
if(launch)
|
||||
if(button2Text != null)
|
||||
{
|
||||
var launchButton = new Button
|
||||
Button2 = new Button
|
||||
{
|
||||
Text = AppResources.Launch,
|
||||
Text = button2Text,
|
||||
HorizontalOptions = LayoutOptions.End,
|
||||
VerticalOptions = LayoutOptions.Center,
|
||||
Command = new Command(() => Device.OpenUri(new Uri(Value.Text)))
|
||||
VerticalOptions = LayoutOptions.Center
|
||||
};
|
||||
|
||||
valueStackLayout.Children.Add(launchButton);
|
||||
valueStackLayout.Children.Add(Button2);
|
||||
}
|
||||
|
||||
stackLayout.Children.Add(valueStackLayout);
|
||||
StackLayout.Children.Add(valueStackLayout);
|
||||
|
||||
View = stackLayout;
|
||||
View = StackLayout;
|
||||
}
|
||||
|
||||
public StackLayout StackLayout { get; private set; }
|
||||
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));
|
||||
}
|
||||
public Button Button1 { get; private set; }
|
||||
public Button Button2 { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ namespace Bit.App.Models.Page
|
|||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(PageTitle)));
|
||||
}
|
||||
}
|
||||
public string PageTitle => Name ?? AppResources.SiteNoName;
|
||||
public string Username
|
||||
{
|
||||
get { return _username; }
|
||||
|
@ -34,8 +35,10 @@ namespace Bit.App.Models.Page
|
|||
{
|
||||
_username = value;
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(Username)));
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(ShowUsername)));
|
||||
}
|
||||
}
|
||||
public bool ShowUsername => !string.IsNullOrWhiteSpace(Username);
|
||||
public string Password
|
||||
{
|
||||
get { return _password; }
|
||||
|
@ -53,8 +56,31 @@ namespace Bit.App.Models.Page
|
|||
{
|
||||
_uri = value;
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(Uri)));
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(UriHost)));
|
||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(ShowUri)));
|
||||
}
|
||||
}
|
||||
public string UriHost
|
||||
{
|
||||
get
|
||||
{
|
||||
if(ShowUri)
|
||||
{
|
||||
try
|
||||
{
|
||||
return new Uri(Uri).Host;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return Uri;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public bool ShowUri => !string.IsNullOrWhiteSpace(Uri);
|
||||
public string Notes
|
||||
{
|
||||
get { return _notes; }
|
||||
|
@ -65,7 +91,7 @@ namespace Bit.App.Models.Page
|
|||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(ShowNotes)));
|
||||
}
|
||||
}
|
||||
public string PageTitle => Name ?? AppResources.SiteNoName;
|
||||
public bool ShowNotes => !string.IsNullOrWhiteSpace(Notes);
|
||||
public bool ShowPassword
|
||||
{
|
||||
get { return _showPassword; }
|
||||
|
@ -79,7 +105,6 @@ namespace Bit.App.Models.Page
|
|||
}
|
||||
public string MaskedPassword => ShowPassword ? Password : Password == null ? null : new string('●', Password.Length);
|
||||
public string ShowHideText => ShowPassword ? AppResources.Hide : AppResources.Show;
|
||||
public bool ShowNotes => !string.IsNullOrWhiteSpace(Notes);
|
||||
|
||||
public void Update(Site site)
|
||||
{
|
||||
|
|
|
@ -44,7 +44,7 @@ namespace Bit.App.Pages
|
|||
}
|
||||
var folderCell = new FormPickerCell(AppResources.Folder, folderOptions.ToArray());
|
||||
|
||||
var notesCell = new FormEditorCell(height:90);
|
||||
var notesCell = new FormEditorCell(height: 90);
|
||||
|
||||
var mainTable = new ExtendedTableView
|
||||
{
|
||||
|
@ -89,9 +89,9 @@ namespace Bit.App.Pages
|
|||
return;
|
||||
}
|
||||
|
||||
if(string.IsNullOrWhiteSpace(uriCell.Entry.Text))
|
||||
if(string.IsNullOrWhiteSpace(passwordCell.Entry.Text))
|
||||
{
|
||||
await DisplayAlert(AppResources.AnErrorHasOccurred, string.Format(AppResources.ValidationFieldRequired, AppResources.URI), AppResources.Ok);
|
||||
await DisplayAlert(AppResources.AnErrorHasOccurred, string.Format(AppResources.ValidationFieldRequired, AppResources.Password), AppResources.Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -127,7 +127,10 @@ namespace Bit.App.Pages
|
|||
Title = AppResources.AddSite;
|
||||
Content = scrollView;
|
||||
ToolbarItems.Add(saveToolBarItem);
|
||||
ToolbarItems.Add(new DismissModalToolBarItem(this, "Cancel"));
|
||||
if(Device.OS == TargetPlatform.iOS)
|
||||
{
|
||||
ToolbarItems.Add(new DismissModalToolBarItem(this, "Cancel"));
|
||||
}
|
||||
|
||||
if(!_connectivity.IsConnected)
|
||||
{
|
||||
|
|
|
@ -111,9 +111,9 @@ namespace Bit.App.Pages
|
|||
return;
|
||||
}
|
||||
|
||||
if(string.IsNullOrWhiteSpace(uriCell.Entry.Text))
|
||||
if(string.IsNullOrWhiteSpace(passwordCell.Entry.Text))
|
||||
{
|
||||
await DisplayAlert(AppResources.AnErrorHasOccurred, string.Format(AppResources.ValidationFieldRequired, AppResources.URI), AppResources.Ok);
|
||||
await DisplayAlert(AppResources.AnErrorHasOccurred, string.Format(AppResources.ValidationFieldRequired, AppResources.Password), AppResources.Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -150,7 +150,10 @@ namespace Bit.App.Pages
|
|||
Title = "Edit Site";
|
||||
Content = scrollView;
|
||||
ToolbarItems.Add(saveToolBarItem);
|
||||
ToolbarItems.Add(new DismissModalToolBarItem(this, "Cancel"));
|
||||
if(Device.OS == TargetPlatform.iOS)
|
||||
{
|
||||
ToolbarItems.Add(new DismissModalToolBarItem(this, "Cancel"));
|
||||
}
|
||||
|
||||
if(!_connectivity.IsConnected)
|
||||
{
|
||||
|
|
|
@ -35,8 +35,15 @@ namespace Bit.App.Pages
|
|||
{
|
||||
ToolbarItems.Add(new AddSiteToolBarItem(this));
|
||||
|
||||
var listView = new ListView { IsGroupingEnabled = true, ItemsSource = Folders };
|
||||
var listView = new ListView
|
||||
{
|
||||
IsGroupingEnabled = true,
|
||||
ItemsSource = Folders,
|
||||
HasUnevenRows = true,
|
||||
SeparatorColor = Color.FromHex("E0E0E0")
|
||||
};
|
||||
listView.GroupDisplayBinding = new Binding("Name");
|
||||
listView.GroupHeaderTemplate = new DataTemplate(() => new VaultListHeaderViewCell(this));
|
||||
listView.ItemSelected += SiteSelected;
|
||||
listView.ItemTemplate = new DataTemplate(() => new VaultListViewCell(this));
|
||||
|
||||
|
@ -171,6 +178,53 @@ namespace Bit.App.Pages
|
|||
this.SetBinding<VaultListPageModel.Site>(DetailProperty, s => s.Username);
|
||||
ContextActions.Add(moreAction);
|
||||
ContextActions.Add(deleteAction);
|
||||
|
||||
TextColor = Color.FromHex("333333");
|
||||
DetailColor = Color.FromHex("777777");
|
||||
}
|
||||
}
|
||||
|
||||
private class VaultListHeaderViewCell : ViewCell
|
||||
{
|
||||
public VaultListHeaderViewCell(VaultListPage page)
|
||||
{
|
||||
var image = new Image
|
||||
{
|
||||
Source = ImageSource.FromFile("fa-folder-open.png"),
|
||||
Margin = new Thickness(16, 8, 0, 8)
|
||||
};
|
||||
|
||||
var label = new Label
|
||||
{
|
||||
FontSize = 14,
|
||||
TextColor = Color.FromHex("777777"),
|
||||
VerticalTextAlignment = TextAlignment.Center
|
||||
};
|
||||
|
||||
label.SetBinding<VaultListPageModel.Folder>(Label.TextProperty, s => s.Name);
|
||||
|
||||
var stackLayout = new StackLayout
|
||||
{
|
||||
Orientation = StackOrientation.Horizontal,
|
||||
BackgroundColor = Color.FromHex("ecf0f5")
|
||||
};
|
||||
|
||||
stackLayout.Children.Add(image);
|
||||
stackLayout.Children.Add(label);
|
||||
|
||||
var borderStackLayout = new StackLayout
|
||||
{
|
||||
Spacing = 0
|
||||
};
|
||||
|
||||
var borderBoxTop = new BoxView { BackgroundColor = Color.FromHex("d2d6de"), HeightRequest = 0.5 };
|
||||
var borderBoxBottom = new BoxView { BackgroundColor = Color.FromHex("d2d6de"), HeightRequest = 0.5 };
|
||||
borderStackLayout.Children.Add(borderBoxTop);
|
||||
borderStackLayout.Children.Add(stackLayout);
|
||||
borderStackLayout.Children.Add(borderBoxBottom);
|
||||
|
||||
View = borderStackLayout;
|
||||
Height = 30;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,26 +32,34 @@ namespace Bit.App.Pages
|
|||
private void Init()
|
||||
{
|
||||
ToolbarItems.Add(new EditSiteToolBarItem(this, _siteId));
|
||||
ToolbarItems.Add(new DismissModalToolBarItem(this));
|
||||
if(Device.OS == TargetPlatform.iOS)
|
||||
{
|
||||
ToolbarItems.Add(new DismissModalToolBarItem(this));
|
||||
}
|
||||
|
||||
// Username
|
||||
var nameCell = new LabeledValueCell(AppResources.Name);
|
||||
nameCell.Value.SetBinding<VaultViewSitePageModel>(Label.TextProperty, s => s.Name);
|
||||
|
||||
// Username
|
||||
var usernameCell = new LabeledValueCell(AppResources.Username, copyValue: true);
|
||||
var usernameCell = new LabeledValueCell(AppResources.Username, button1Text: AppResources.Copy);
|
||||
usernameCell.Value.SetBinding<VaultViewSitePageModel>(Label.TextProperty, s => s.Username);
|
||||
usernameCell.Button1.Command = new Command(() => Copy(Model.Username, AppResources.Username));
|
||||
|
||||
// Password
|
||||
var passwordCell = new LabeledValueCell(AppResources.Password, copyValue: true);
|
||||
passwordCell.Value.SetBinding<VaultViewSitePageModel>(Label.TextProperty, s => s.Password);
|
||||
var passwordCell = new LabeledValueCell(AppResources.Password, button1Text: AppResources.Show, button2Text: AppResources.Copy);
|
||||
passwordCell.Value.SetBinding<VaultViewSitePageModel>(Label.TextProperty, s => s.MaskedPassword);
|
||||
passwordCell.Button1.SetBinding<VaultViewSitePageModel>(Button.TextProperty, s => s.ShowHideText);
|
||||
passwordCell.Button1.Command = new Command(() => Model.ShowPassword = !Model.ShowPassword);
|
||||
passwordCell.Button2.Command = new Command(() => Copy(Model.Password, AppResources.Password));
|
||||
|
||||
// URI
|
||||
var uriCell = new LabeledValueCell(AppResources.URI, launch: true);
|
||||
uriCell.Value.SetBinding<VaultViewSitePageModel>(Label.TextProperty, s => s.Uri);
|
||||
var uriCell = new LabeledValueCell(AppResources.Website, button1Text: AppResources.Launch);
|
||||
uriCell.Value.SetBinding<VaultViewSitePageModel>(Label.TextProperty, s => s.UriHost);
|
||||
uriCell.Button1.Command = new Command(() => Device.OpenUri(new Uri(uriCell.Value.Text)));
|
||||
|
||||
// Notes
|
||||
var notesCell = new LabeledValueCell(AppResources.Notes);
|
||||
var notesCell = new LabeledValueCell();
|
||||
notesCell.Value.SetBinding<VaultViewSitePageModel>(Label.TextProperty, s => s.Notes);
|
||||
|
||||
Table = new ExtendedTableView
|
||||
|
|
|
@ -23,6 +23,7 @@ namespace Bit.iOS.Controls
|
|||
SetSelection(view);
|
||||
UpdateRowHeight(view);
|
||||
UpdateEstimatedRowHeight(view);
|
||||
UpdateSeparatorColor(view);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,5 +88,10 @@ namespace Bit.iOS.Controls
|
|||
Control.EstimatedRowHeight = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateSeparatorColor(ExtendedTableView view)
|
||||
{
|
||||
Control.SeparatorColor = view.SeparatorColor.ToUIColor(UIColor.Gray);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
BIN
src/iOS/Resources/fa-folder-open.png
Normal file
BIN
src/iOS/Resources/fa-folder-open.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 314 B |
BIN
src/iOS/Resources/fa-folder-open@2x.png
Normal file
BIN
src/iOS/Resources/fa-folder-open@2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 456 B |
BIN
src/iOS/Resources/fa-folder-open@3x.png
Normal file
BIN
src/iOS/Resources/fa-folder-open@3x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 623 B |
|
@ -330,6 +330,15 @@
|
|||
<ItemGroup>
|
||||
<ITunesArtwork Include="Resources\iTunesArtwork%402x.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BundleResource Include="Resources\fa-folder-open.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BundleResource Include="Resources\fa-folder-open%402x.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BundleResource Include="Resources\fa-folder-open%403x.png" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
|
|
Loading…
Reference in a new issue