mirror of
https://github.com/bitwarden/android.git
synced 2024-12-25 02:18:27 +03:00
Vault add/edit/view site updates to table section/cell display.
This commit is contained in:
parent
baeee00a8d
commit
8108f4023a
9 changed files with 101 additions and 49 deletions
|
@ -20,7 +20,7 @@ namespace Bit.App.Controls
|
||||||
|
|
||||||
var stackLayout = new StackLayout
|
var stackLayout = new StackLayout
|
||||||
{
|
{
|
||||||
Padding = new Thickness(15)
|
Padding = new Thickness(15, 10)
|
||||||
};
|
};
|
||||||
|
|
||||||
stackLayout.Children.Add(Editor);
|
stackLayout.Children.Add(Editor);
|
||||||
|
|
|
@ -32,7 +32,7 @@ namespace Bit.App.Controls
|
||||||
|
|
||||||
var stackLayout = new StackLayout
|
var stackLayout = new StackLayout
|
||||||
{
|
{
|
||||||
Padding = new Thickness(15)
|
Padding = new Thickness(15, 10)
|
||||||
};
|
};
|
||||||
|
|
||||||
stackLayout.Children.Add(Label);
|
stackLayout.Children.Add(Label);
|
||||||
|
|
|
@ -30,7 +30,7 @@ namespace Bit.App.Controls
|
||||||
|
|
||||||
var stackLayout = new StackLayout
|
var stackLayout = new StackLayout
|
||||||
{
|
{
|
||||||
Padding = new Thickness(15)
|
Padding = new Thickness(15, 10)
|
||||||
};
|
};
|
||||||
|
|
||||||
stackLayout.Children.Add(Label);
|
stackLayout.Children.Add(Label);
|
||||||
|
|
|
@ -12,7 +12,7 @@ namespace Bit.App.Controls
|
||||||
{
|
{
|
||||||
var containerStackLayout = new StackLayout
|
var containerStackLayout = new StackLayout
|
||||||
{
|
{
|
||||||
Padding = new Thickness(15),
|
Padding = new Thickness(15, 10),
|
||||||
Orientation = StackOrientation.Horizontal
|
Orientation = StackOrientation.Horizontal
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -58,7 +58,8 @@ namespace Bit.App.Controls
|
||||||
{
|
{
|
||||||
Text = button1Text,
|
Text = button1Text,
|
||||||
HorizontalOptions = LayoutOptions.End,
|
HorizontalOptions = LayoutOptions.End,
|
||||||
VerticalOptions = LayoutOptions.Center
|
VerticalOptions = LayoutOptions.Center,
|
||||||
|
Margin = new Thickness(0)
|
||||||
};
|
};
|
||||||
|
|
||||||
buttonStackLayout.Children.Add(Button1);
|
buttonStackLayout.Children.Add(Button1);
|
||||||
|
@ -70,7 +71,8 @@ namespace Bit.App.Controls
|
||||||
{
|
{
|
||||||
Text = button2Text,
|
Text = button2Text,
|
||||||
HorizontalOptions = LayoutOptions.End,
|
HorizontalOptions = LayoutOptions.End,
|
||||||
VerticalOptions = LayoutOptions.Center
|
VerticalOptions = LayoutOptions.Center,
|
||||||
|
Margin = new Thickness(0)
|
||||||
};
|
};
|
||||||
|
|
||||||
buttonStackLayout.Children.Add(Button2);
|
buttonStackLayout.Children.Add(Button2);
|
||||||
|
|
|
@ -11,7 +11,7 @@ namespace Bit.App.Models.Page
|
||||||
private string _password;
|
private string _password;
|
||||||
private string _uri;
|
private string _uri;
|
||||||
private string _notes;
|
private string _notes;
|
||||||
private bool _showPassword;
|
private bool _revealPassword;
|
||||||
|
|
||||||
public VaultViewSitePageModel() { }
|
public VaultViewSitePageModel() { }
|
||||||
|
|
||||||
|
@ -37,6 +37,7 @@ namespace Bit.App.Models.Page
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public bool ShowUsername => !string.IsNullOrWhiteSpace(Username);
|
public bool ShowUsername => !string.IsNullOrWhiteSpace(Username);
|
||||||
|
|
||||||
public string Password
|
public string Password
|
||||||
{
|
{
|
||||||
get { return _password; }
|
get { return _password; }
|
||||||
|
@ -47,6 +48,8 @@ namespace Bit.App.Models.Page
|
||||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(MaskedPassword)));
|
PropertyChanged(this, new PropertyChangedEventArgs(nameof(MaskedPassword)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public bool ShowPassword => !string.IsNullOrWhiteSpace(Password);
|
||||||
|
|
||||||
public string Uri
|
public string Uri
|
||||||
{
|
{
|
||||||
get { return _uri; }
|
get { return _uri; }
|
||||||
|
@ -58,6 +61,8 @@ namespace Bit.App.Models.Page
|
||||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(ShowUri)));
|
PropertyChanged(this, new PropertyChangedEventArgs(nameof(ShowUri)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public bool ShowUri => !string.IsNullOrWhiteSpace(Uri);
|
||||||
|
|
||||||
public string UriHost
|
public string UriHost
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
@ -78,7 +83,6 @@ namespace Bit.App.Models.Page
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ShowUri => !string.IsNullOrWhiteSpace(Uri);
|
|
||||||
public string Notes
|
public string Notes
|
||||||
{
|
{
|
||||||
get { return _notes; }
|
get { return _notes; }
|
||||||
|
@ -90,19 +94,19 @@ namespace Bit.App.Models.Page
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public bool ShowNotes => !string.IsNullOrWhiteSpace(Notes);
|
public bool ShowNotes => !string.IsNullOrWhiteSpace(Notes);
|
||||||
public bool ShowPassword
|
public bool RevealPassword
|
||||||
{
|
{
|
||||||
get { return _showPassword; }
|
get { return _revealPassword; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
_showPassword = value;
|
_revealPassword = value;
|
||||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(ShowPassword)));
|
PropertyChanged(this, new PropertyChangedEventArgs(nameof(RevealPassword)));
|
||||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(MaskedPassword)));
|
PropertyChanged(this, new PropertyChangedEventArgs(nameof(MaskedPassword)));
|
||||||
PropertyChanged(this, new PropertyChangedEventArgs(nameof(ShowHideText)));
|
PropertyChanged(this, new PropertyChangedEventArgs(nameof(ShowHideText)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public string MaskedPassword => ShowPassword ? Password : Password == null ? null : new string('●', Password.Length);
|
public string MaskedPassword => RevealPassword ? Password : Password == null ? null : new string('●', Password.Length);
|
||||||
public string ShowHideText => ShowPassword ? AppResources.Hide : AppResources.Show;
|
public string ShowHideText => RevealPassword ? AppResources.Hide : AppResources.Show;
|
||||||
|
|
||||||
public void Update(Site site)
|
public void Update(Site site)
|
||||||
{
|
{
|
||||||
|
|
|
@ -36,6 +36,9 @@ namespace Bit.App.Pages
|
||||||
var usernameCell = new FormEntryCell(AppResources.Username, nextElement: passwordCell.Entry);
|
var usernameCell = new FormEntryCell(AppResources.Username, nextElement: passwordCell.Entry);
|
||||||
usernameCell.Entry.DisableAutocapitalize = true;
|
usernameCell.Entry.DisableAutocapitalize = true;
|
||||||
usernameCell.Entry.Autocorrect = false;
|
usernameCell.Entry.Autocorrect = false;
|
||||||
|
|
||||||
|
usernameCell.Entry.FontFamily = passwordCell.Entry.FontFamily = "Courier";
|
||||||
|
|
||||||
var uriCell = new FormEntryCell(AppResources.URI, Keyboard.Url, nextElement: usernameCell.Entry);
|
var uriCell = new FormEntryCell(AppResources.URI, Keyboard.Url, nextElement: usernameCell.Entry);
|
||||||
var nameCell = new FormEntryCell(AppResources.Name, nextElement: uriCell.Entry);
|
var nameCell = new FormEntryCell(AppResources.Name, nextElement: uriCell.Entry);
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,9 @@ namespace Bit.App.Pages
|
||||||
usernameCell.Entry.Text = site.Username?.Decrypt();
|
usernameCell.Entry.Text = site.Username?.Decrypt();
|
||||||
usernameCell.Entry.DisableAutocapitalize = true;
|
usernameCell.Entry.DisableAutocapitalize = true;
|
||||||
usernameCell.Entry.Autocorrect = false;
|
usernameCell.Entry.Autocorrect = false;
|
||||||
|
|
||||||
|
usernameCell.Entry.FontFamily = passwordCell.Entry.FontFamily = "Courier";
|
||||||
|
|
||||||
var uriCell = new FormEntryCell(AppResources.URI, Keyboard.Url, nextElement: usernameCell.Entry);
|
var uriCell = new FormEntryCell(AppResources.URI, Keyboard.Url, nextElement: usernameCell.Entry);
|
||||||
uriCell.Entry.Text = site.Uri?.Decrypt();
|
uriCell.Entry.Text = site.Uri?.Decrypt();
|
||||||
var nameCell = new FormEntryCell(AppResources.Name, nextElement: uriCell.Entry);
|
var nameCell = new FormEntryCell(AppResources.Name, nextElement: uriCell.Entry);
|
||||||
|
|
|
@ -28,6 +28,11 @@ namespace Bit.App.Pages
|
||||||
|
|
||||||
private VaultViewSitePageModel Model { get; set; } = new VaultViewSitePageModel();
|
private VaultViewSitePageModel Model { get; set; } = new VaultViewSitePageModel();
|
||||||
private ExtendedTableView Table { get; set; }
|
private ExtendedTableView Table { get; set; }
|
||||||
|
private TableSection SiteInformationSection { get; set; }
|
||||||
|
private TableSection NotesSection { get; set; }
|
||||||
|
public LabeledValueCell UsernameCell { get; set; }
|
||||||
|
public LabeledValueCell PasswordCell { get; set; }
|
||||||
|
public LabeledValueCell UriCell { get; set; }
|
||||||
|
|
||||||
private void Init()
|
private void Init()
|
||||||
{
|
{
|
||||||
|
@ -42,30 +47,39 @@ namespace Bit.App.Pages
|
||||||
nameCell.Value.SetBinding<VaultViewSitePageModel>(Label.TextProperty, s => s.Name);
|
nameCell.Value.SetBinding<VaultViewSitePageModel>(Label.TextProperty, s => s.Name);
|
||||||
|
|
||||||
// Username
|
// Username
|
||||||
var usernameCell = new LabeledValueCell(AppResources.Username, button1Text: AppResources.Copy);
|
UsernameCell = new LabeledValueCell(AppResources.Username, button1Text: AppResources.Copy);
|
||||||
usernameCell.Value.SetBinding<VaultViewSitePageModel>(Label.TextProperty, s => s.Username);
|
UsernameCell.Value.SetBinding<VaultViewSitePageModel>(Label.TextProperty, s => s.Username);
|
||||||
usernameCell.Button1.Command = new Command(() => Copy(Model.Username, AppResources.Username));
|
UsernameCell.Button1.Command = new Command(() => Copy(Model.Username, AppResources.Username));
|
||||||
usernameCell.View.SetBinding<VaultViewSitePageModel>(IsVisibleProperty, s => s.ShowUsername);
|
|
||||||
|
|
||||||
// Password
|
// Password
|
||||||
var passwordCell = new LabeledValueCell(AppResources.Password, button1Text: AppResources.Show, button2Text: AppResources.Copy);
|
PasswordCell = new LabeledValueCell(AppResources.Password, button1Text: AppResources.Show, button2Text: AppResources.Copy);
|
||||||
passwordCell.Value.SetBinding<VaultViewSitePageModel>(Label.TextProperty, s => s.MaskedPassword);
|
PasswordCell.Value.SetBinding<VaultViewSitePageModel>(Label.TextProperty, s => s.MaskedPassword);
|
||||||
passwordCell.Button1.SetBinding<VaultViewSitePageModel>(Button.TextProperty, s => s.ShowHideText);
|
PasswordCell.Button1.SetBinding<VaultViewSitePageModel>(Button.TextProperty, s => s.ShowHideText);
|
||||||
passwordCell.Button1.Command = new Command(() => Model.ShowPassword = !Model.ShowPassword);
|
PasswordCell.Button1.Command = new Command(() => Model.RevealPassword = !Model.RevealPassword);
|
||||||
passwordCell.Button2.Command = new Command(() => Copy(Model.Password, AppResources.Password));
|
PasswordCell.Button2.Command = new Command(() => Copy(Model.Password, AppResources.Password));
|
||||||
|
|
||||||
|
UsernameCell.Value.FontFamily = PasswordCell.Value.FontFamily = "Courier";
|
||||||
|
|
||||||
// URI
|
// URI
|
||||||
var uriCell = new LabeledValueCell(AppResources.Website, button1Text: AppResources.Launch);
|
UriCell = new LabeledValueCell(AppResources.Website, button1Text: AppResources.Launch);
|
||||||
uriCell.Value.SetBinding<VaultViewSitePageModel>(Label.TextProperty, s => s.UriHost);
|
UriCell.Value.SetBinding<VaultViewSitePageModel>(Label.TextProperty, s => s.UriHost);
|
||||||
uriCell.Button1.Command = new Command(() => Device.OpenUri(new Uri(Model.Uri)));
|
UriCell.Button1.Command = new Command(() => Device.OpenUri(new Uri(Model.Uri)));
|
||||||
uriCell.View.SetBinding<VaultViewSitePageModel>(IsVisibleProperty, s => s.ShowUri);
|
|
||||||
|
|
||||||
// Notes
|
// Notes
|
||||||
var notesCell = new LabeledValueCell();
|
var notesCell = new LabeledValueCell();
|
||||||
notesCell.Value.SetBinding<VaultViewSitePageModel>(Label.TextProperty, s => s.Notes);
|
notesCell.Value.SetBinding<VaultViewSitePageModel>(Label.TextProperty, s => s.Notes);
|
||||||
notesCell.View.SetBinding<VaultViewSitePageModel>(IsVisibleProperty, s => s.ShowNotes);
|
|
||||||
notesCell.Value.LineBreakMode = LineBreakMode.WordWrap;
|
notesCell.Value.LineBreakMode = LineBreakMode.WordWrap;
|
||||||
|
|
||||||
|
SiteInformationSection = new TableSection("Site Information")
|
||||||
|
{
|
||||||
|
nameCell
|
||||||
|
};
|
||||||
|
|
||||||
|
NotesSection = new TableSection(AppResources.Notes)
|
||||||
|
{
|
||||||
|
notesCell
|
||||||
|
};
|
||||||
|
|
||||||
Table = new ExtendedTableView
|
Table = new ExtendedTableView
|
||||||
{
|
{
|
||||||
Intent = TableIntent.Settings,
|
Intent = TableIntent.Settings,
|
||||||
|
@ -74,17 +88,8 @@ namespace Bit.App.Pages
|
||||||
EnableSelection = false,
|
EnableSelection = false,
|
||||||
Root = new TableRoot
|
Root = new TableRoot
|
||||||
{
|
{
|
||||||
new TableSection("Site Information")
|
SiteInformationSection,
|
||||||
{
|
NotesSection
|
||||||
nameCell,
|
|
||||||
uriCell,
|
|
||||||
usernameCell,
|
|
||||||
passwordCell
|
|
||||||
},
|
|
||||||
new TableSection(AppResources.Notes)
|
|
||||||
{
|
|
||||||
notesCell
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -110,11 +115,43 @@ namespace Bit.App.Pages
|
||||||
|
|
||||||
Model.Update(site);
|
Model.Update(site);
|
||||||
|
|
||||||
base.OnAppearing();
|
if(!Model.ShowUri)
|
||||||
|
{
|
||||||
|
SiteInformationSection.Remove(UriCell);
|
||||||
|
}
|
||||||
|
else if(!SiteInformationSection.Contains(UriCell))
|
||||||
|
{
|
||||||
|
SiteInformationSection.Add(UriCell);
|
||||||
|
}
|
||||||
|
|
||||||
// Hack to get table row height binding to update. Better way to do this probably?
|
if(!Model.ShowUsername)
|
||||||
Table.Root.Add(new TableSection { new TextCell() });
|
{
|
||||||
Table.Root.RemoveAt(Table.Root.Count - 1);
|
SiteInformationSection.Remove(UsernameCell);
|
||||||
|
}
|
||||||
|
else if(!SiteInformationSection.Contains(UsernameCell))
|
||||||
|
{
|
||||||
|
SiteInformationSection.Add(UsernameCell);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!Model.ShowPassword)
|
||||||
|
{
|
||||||
|
SiteInformationSection.Remove(PasswordCell);
|
||||||
|
}
|
||||||
|
else if(!SiteInformationSection.Contains(PasswordCell))
|
||||||
|
{
|
||||||
|
SiteInformationSection.Add(PasswordCell);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!Model.ShowNotes)
|
||||||
|
{
|
||||||
|
Table.Root.Remove(NotesSection);
|
||||||
|
}
|
||||||
|
else if(!Table.Root.Contains(NotesSection))
|
||||||
|
{
|
||||||
|
Table.Root.Add(NotesSection);
|
||||||
|
}
|
||||||
|
|
||||||
|
base.OnAppearing();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Copy(string copyText, string alertLabel)
|
private void Copy(string copyText, string alertLabel)
|
||||||
|
|
|
@ -27,15 +27,18 @@ namespace Bit.App.Repositories
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var responseContent = await response.Content.ReadAsStringAsync();
|
|
||||||
var errorResponseModel = JsonConvert.DeserializeObject<ErrorResponse>(responseContent);
|
|
||||||
|
|
||||||
var errors = new List<ApiError>();
|
var errors = new List<ApiError>();
|
||||||
foreach(var valError in errorResponseModel.ValidationErrors)
|
if(response.StatusCode == System.Net.HttpStatusCode.BadRequest)
|
||||||
{
|
{
|
||||||
foreach(var errorMessage in valError.Value)
|
var responseContent = await response.Content.ReadAsStringAsync();
|
||||||
|
var errorResponseModel = JsonConvert.DeserializeObject<ErrorResponse>(responseContent);
|
||||||
|
|
||||||
|
foreach(var valError in errorResponseModel.ValidationErrors)
|
||||||
{
|
{
|
||||||
errors.Add(new ApiError { Message = errorMessage });
|
foreach(var errorMessage in valError.Value)
|
||||||
|
{
|
||||||
|
errors.Add(new ApiError { Message = errorMessage });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue