mirror of
https://github.com/bitwarden/mobile
synced 2026-01-03 17:13:50 +00:00
Removed disclosure from view cell in favor of button. Updated sync logic for incrementals. Store revision date from server record. Apply more accessability font size support for editor and picker controls
This commit is contained in:
@@ -125,10 +125,12 @@ namespace Bit.App
|
||||
}
|
||||
else if(pinUnlock && !string.IsNullOrWhiteSpace(_authService.PIN))
|
||||
{
|
||||
|
||||
if((currentPage?.CurrentPage as LockPinPage) == null)
|
||||
var lockPinPage = (currentPage?.CurrentPage as LockPinPage);
|
||||
if(lockPinPage == null)
|
||||
{
|
||||
await Current.MainPage.Navigation.PushModalAsync(new ExtendedNavigationPage(new LockPinPage()), false);
|
||||
lockPinPage = new LockPinPage();
|
||||
await Current.MainPage.Navigation.PushModalAsync(new ExtendedNavigationPage(lockPinPage), false);
|
||||
lockPinPage.PinControl.Entry.Focus();
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -8,35 +8,10 @@ namespace Bit.App.Controls
|
||||
public static readonly BindableProperty BackgroundColorProperty =
|
||||
BindableProperty.Create(nameof(BackgroundColor), typeof(Color), typeof(ExtendedTextCell), Color.White);
|
||||
|
||||
public static readonly BindableProperty ShowDisclousureProperty =
|
||||
BindableProperty.Create(nameof(DisclousureImage), typeof(bool), typeof(ExtendedTextCell), false);
|
||||
|
||||
public static readonly BindableProperty DisclousureImageProperty =
|
||||
BindableProperty.Create(nameof(DisclousureImage), typeof(string), typeof(ExtendedTextCell), string.Empty);
|
||||
|
||||
public Color BackgroundColor
|
||||
{
|
||||
get { return (Color)GetValue(BackgroundColorProperty); }
|
||||
set { SetValue(BackgroundColorProperty, value); }
|
||||
}
|
||||
|
||||
public bool ShowDisclousure
|
||||
{
|
||||
get { return (bool)GetValue(ShowDisclousureProperty); }
|
||||
set { SetValue(ShowDisclousureProperty, value); }
|
||||
}
|
||||
|
||||
public string DisclousureImage
|
||||
{
|
||||
get { return (string)GetValue(DisclousureImageProperty); }
|
||||
set { SetValue(DisclousureImageProperty, value); }
|
||||
}
|
||||
|
||||
public event EventHandler DisclousureTapped;
|
||||
|
||||
public void OnDisclousureTapped()
|
||||
{
|
||||
DisclousureTapped?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Bit.App.Controls
|
||||
{
|
||||
public class LabeledDetailCell : ExtendedViewCell
|
||||
public class LabeledDetailCell : ViewCell
|
||||
{
|
||||
public LabeledDetailCell()
|
||||
{
|
||||
@@ -20,19 +20,33 @@ namespace Bit.App.Controls
|
||||
Style = (Style)Application.Current.Resources["text-muted"],
|
||||
};
|
||||
|
||||
var stackLayout = new StackLayout
|
||||
var labelDetailStackLayout = new StackLayout
|
||||
{
|
||||
Padding = new Thickness(20, 5),
|
||||
HorizontalOptions = LayoutOptions.FillAndExpand,
|
||||
HorizontalOptions = LayoutOptions.StartAndExpand,
|
||||
VerticalOptions = LayoutOptions.FillAndExpand,
|
||||
Children = { Label, Detail },
|
||||
Padding = new Thickness(15, 5, 5, 5),
|
||||
Spacing = 0
|
||||
};
|
||||
|
||||
View = stackLayout;
|
||||
Button = new Button
|
||||
{
|
||||
HorizontalOptions = LayoutOptions.End,
|
||||
VerticalOptions = LayoutOptions.FillAndExpand,
|
||||
WidthRequest = 50
|
||||
};
|
||||
|
||||
var containerStackLayout = new StackLayout
|
||||
{
|
||||
Orientation = StackOrientation.Horizontal,
|
||||
Children = { labelDetailStackLayout, Button }
|
||||
};
|
||||
|
||||
View = containerStackLayout;
|
||||
}
|
||||
|
||||
public Label Label { get; private set; }
|
||||
public Label Detail { get; private set; }
|
||||
public Button Button { get; private set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ namespace Bit.App.Controls
|
||||
Value = new Label
|
||||
{
|
||||
Text = valueText,
|
||||
FontSize = Device.GetNamedSize(NamedSize.Default, typeof(Label)),
|
||||
LineBreakMode = LineBreakMode.TailTruncation,
|
||||
VerticalOptions = LayoutOptions.CenterAndExpand
|
||||
};
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace Bit.App.Controls
|
||||
Label = new Label
|
||||
{
|
||||
HorizontalTextAlignment = TextAlignment.Center,
|
||||
FontSize = 30,
|
||||
FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label)),
|
||||
FontFamily = "Courier"
|
||||
};
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ namespace Bit.App.Models.Data
|
||||
Id = folder.Id;
|
||||
UserId = userId;
|
||||
Name = folder.Name;
|
||||
RevisionDateTime = folder.RevisionDate;
|
||||
}
|
||||
|
||||
public FolderData(CipherResponse cipher, string userId)
|
||||
@@ -37,6 +38,7 @@ namespace Bit.App.Models.Data
|
||||
Id = cipher.Id;
|
||||
UserId = userId;
|
||||
Name = data.Name;
|
||||
RevisionDateTime = cipher.RevisionDate;
|
||||
}
|
||||
|
||||
[PrimaryKey]
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
using SQLite;
|
||||
using Bit.App.Abstractions;
|
||||
using Bit.App.Models.Api;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Bit.App.Models.Data
|
||||
{
|
||||
@@ -36,6 +35,7 @@ namespace Bit.App.Models.Data
|
||||
Password = site.Password;
|
||||
Notes = site.Notes;
|
||||
Favorite = site.Favorite;
|
||||
RevisionDateTime = site.RevisionDate;
|
||||
}
|
||||
|
||||
public SiteData(CipherResponse cipher, string userId)
|
||||
@@ -55,6 +55,7 @@ namespace Bit.App.Models.Data
|
||||
Password = data.Password;
|
||||
Notes = data.Notes;
|
||||
Favorite = cipher.Favorite;
|
||||
RevisionDateTime = cipher.RevisionDate;
|
||||
}
|
||||
|
||||
[PrimaryKey]
|
||||
|
||||
@@ -53,6 +53,7 @@ namespace Bit.App.Pages
|
||||
|
||||
var tgr = new TapGestureRecognizer();
|
||||
tgr.Tapped += Tgr_Tapped;
|
||||
PinControl.Label.GestureRecognizers.Add(tgr);
|
||||
|
||||
Title = "Verify PIN";
|
||||
Content = stackLayout;
|
||||
|
||||
@@ -44,6 +44,7 @@ namespace Bit.App.Pages
|
||||
|
||||
var tgr = new TapGestureRecognizer();
|
||||
tgr.Tapped += Tgr_Tapped;
|
||||
PinControl.Label.GestureRecognizers.Add(tgr);
|
||||
|
||||
Title = "Set PIN";
|
||||
Content = stackLayout;
|
||||
|
||||
@@ -12,7 +12,6 @@ using XLabs.Ioc;
|
||||
using Bit.App.Utilities;
|
||||
using PushNotification.Plugin.Abstractions;
|
||||
using Plugin.Settings.Abstractions;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Bit.App.Pages
|
||||
{
|
||||
@@ -59,7 +58,6 @@ namespace Bit.App.Pages
|
||||
|
||||
if(Device.OS == TargetPlatform.iOS)
|
||||
{
|
||||
listView.Margin = new Thickness(0, 0, -15, 0);
|
||||
listView.RowHeight = -1;
|
||||
}
|
||||
|
||||
@@ -195,7 +193,7 @@ namespace Bit.App.Pages
|
||||
_page = page;
|
||||
|
||||
// Adding whitespace to Delete action to account for the negative margin offset on the listview
|
||||
var deleteAction = new MenuItem { Text = AppResources.Delete + " ", IsDestructive = true };
|
||||
var deleteAction = new MenuItem { Text = AppResources.Delete, IsDestructive = true };
|
||||
deleteAction.SetBinding(MenuItem.CommandParameterProperty, new Binding("."));
|
||||
deleteAction.Clicked += page.DeleteClickedAsync;
|
||||
|
||||
@@ -210,9 +208,8 @@ namespace Bit.App.Pages
|
||||
ContextActions.Add(deleteAction);
|
||||
ContextActions.Add(moreAction);
|
||||
|
||||
DisclousureTapped += VaultListViewCell_DisclousureTapped;
|
||||
ShowDisclousure = true;
|
||||
DisclousureImage = "more";
|
||||
Button.Image = "more";
|
||||
Button.Command = new Command(() => ShowMore());
|
||||
}
|
||||
|
||||
public VaultListPageModel.Site SiteParameter
|
||||
@@ -228,10 +225,9 @@ namespace Bit.App.Pages
|
||||
_page.MoreClickedAsync(site);
|
||||
}
|
||||
|
||||
private void VaultListViewCell_DisclousureTapped(object sender, EventArgs e)
|
||||
private void ShowMore()
|
||||
{
|
||||
var cell = sender as VaultListViewCell;
|
||||
_page.MoreClickedAsync(cell.SiteParameter);
|
||||
_page.MoreClickedAsync(SiteParameter);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -264,6 +260,7 @@ namespace Bit.App.Pages
|
||||
};
|
||||
|
||||
View = stackLayout;
|
||||
Height = 40;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,15 +156,10 @@ namespace Bit.App.Services
|
||||
|
||||
var siteTask = SyncSitesAsync(ciphers.Result.Revised.Where(c => c.Type == Enums.CipherType.Site), false);
|
||||
var folderTask = SyncFoldersAsync(ciphers.Result.Revised.Where(c => c.Type == Enums.CipherType.Folder), false);
|
||||
var deleteTask = DeleteCiphersAsync(ciphers.Result.Deleted);
|
||||
|
||||
foreach(var cipherId in ciphers.Result.Deleted)
|
||||
{
|
||||
await _siteRepository.DeleteAsync(cipherId);
|
||||
}
|
||||
|
||||
await Task.WhenAll(siteTask, folderTask);
|
||||
|
||||
if(folderTask.Exception != null || siteTask.Exception != null)
|
||||
await Task.WhenAll(siteTask, folderTask, deleteTask);
|
||||
if(folderTask.Exception != null || siteTask.Exception != null || deleteTask.Exception != null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -179,14 +174,15 @@ namespace Bit.App.Services
|
||||
|
||||
foreach(var serverFolder in serverFolders)
|
||||
{
|
||||
var data = new FolderData(serverFolder, _authService.UserId);
|
||||
var existingLocalFolder = localFolders.SingleOrDefault(f => f.Id == serverFolder.Id);
|
||||
if(existingLocalFolder == null)
|
||||
{
|
||||
var data = new FolderData(serverFolder, _authService.UserId);
|
||||
await _folderRepository.InsertAsync(data);
|
||||
}
|
||||
else
|
||||
else if(existingLocalFolder.RevisionDateTime != serverFolder.RevisionDate)
|
||||
{
|
||||
var data = new FolderData(serverFolder, _authService.UserId);
|
||||
await _folderRepository.UpdateAsync(data);
|
||||
}
|
||||
}
|
||||
@@ -208,14 +204,15 @@ namespace Bit.App.Services
|
||||
|
||||
foreach(var serverSite in serverSites)
|
||||
{
|
||||
var data = new SiteData(serverSite, _authService.UserId);
|
||||
var existingLocalSite = localSites.SingleOrDefault(s => s.Id == serverSite.Id);
|
||||
if(existingLocalSite == null)
|
||||
{
|
||||
var data = new SiteData(serverSite, _authService.UserId);
|
||||
await _siteRepository.InsertAsync(data);
|
||||
}
|
||||
else
|
||||
else if(existingLocalSite.RevisionDateTime != serverSite.RevisionDate)
|
||||
{
|
||||
var data = new SiteData(serverSite, _authService.UserId);
|
||||
await _siteRepository.UpdateAsync(data);
|
||||
}
|
||||
}
|
||||
@@ -230,5 +227,16 @@ namespace Bit.App.Services
|
||||
await _siteRepository.DeleteAsync(site.Id);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task DeleteCiphersAsync(IEnumerable<string> cipherIds)
|
||||
{
|
||||
var tasks = new List<Task>();
|
||||
foreach(var cipherId in cipherIds)
|
||||
{
|
||||
tasks.Add(_siteRepository.DeleteAsync(cipherId));
|
||||
tasks.Add(_folderRepository.DeleteAsync(cipherId));
|
||||
}
|
||||
await Task.WhenAll(tasks);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user