1
0
mirror of https://github.com/bitwarden/mobile synced 2025-12-26 21:23:46 +00:00

reset for v2

This commit is contained in:
Kyle Spearrin
2019-03-27 16:23:00 -04:00
parent 5a7f106e3e
commit 297beac169
1180 changed files with 0 additions and 126197 deletions

View File

@@ -1,16 +0,0 @@
using Bit.App.Resources;
using Bit.App.Utilities;
using Xamarin.Forms;
namespace Bit.App.Controls
{
public class AddCipherToolBarItem : ExtendedToolbarItem
{
public AddCipherToolBarItem(Page page, string folderId)
: base(() => Helpers.AddCipher(page, folderId))
{
Text = AppResources.Add;
Icon = "plus.png";
}
}
}

View File

@@ -1,29 +0,0 @@
using Bit.App.Resources;
using Bit.App.Utilities;
using System;
using Xamarin.Forms;
namespace Bit.App.Controls
{
public class DismissModalToolBarItem : ExtendedToolbarItem, IDisposable
{
private readonly ContentPage _page;
public DismissModalToolBarItem(ContentPage page, string text = null, Action cancelClickedAction = null)
: base(cancelClickedAction)
{
_page = page;
// TODO: init and dispose events from pages
InitEvents();
Text = text ?? AppResources.Close;
Icon = Helpers.ToolbarImage("ion_chevron_left.png");
Priority = -1;
}
protected async override void ClickedItem(object sender, EventArgs e)
{
base.ClickedItem(sender, e);
await _page.Navigation.PopForDeviceAsync();
}
}
}

View File

@@ -1,28 +0,0 @@
using Bit.App.Enums;
using Bit.App.Utilities;
using System;
using Xamarin.Forms;
namespace Bit.App.Controls
{
public class ExtendedButton : Button
{
public static readonly BindableProperty PaddingProperty =
BindableProperty.Create(nameof(Padding), typeof(Thickness), typeof(ExtendedButton), default(Thickness));
public static readonly BindableProperty UppercaseProperty =
BindableProperty.Create(nameof(Uppercase), typeof(bool), typeof(ExtendedButton),
Helpers.OnPlatform(iOS: false, Android: true, Windows: false));
public Thickness Padding
{
get { return (Thickness)GetValue(PaddingProperty); }
set { SetValue(PaddingProperty, value); }
}
public bool Uppercase
{
get { return (bool)GetValue(UppercaseProperty); }
set { SetValue(UppercaseProperty, value); }
}
}
}

View File

@@ -1,81 +0,0 @@
using Bit.App.Abstractions;
using Bit.App.Pages;
using Xamarin.Forms;
using XLabs.Ioc;
namespace Bit.App.Controls
{
public class ExtendedContentPage : ContentPage
{
private ISyncService _syncService;
private IGoogleAnalyticsService _googleAnalyticsService;
private ILockService _lockService;
private IDeviceActionService _deviceActionService;
private IAuthService _authService;
private bool _syncIndicator;
private bool _updateActivity;
private bool _requireAuth;
public ExtendedContentPage(bool syncIndicator = false, bool updateActivity = true, bool requireAuth = true)
{
_syncIndicator = syncIndicator;
_updateActivity = updateActivity;
_requireAuth = requireAuth;
_syncService = Resolver.Resolve<ISyncService>();
_googleAnalyticsService = Resolver.Resolve<IGoogleAnalyticsService>();
_lockService = Resolver.Resolve<ILockService>();
_deviceActionService = Resolver.Resolve<IDeviceActionService>();
_authService = Resolver.Resolve<IAuthService>();
BackgroundColor = Color.FromHex("efeff4");
}
protected async override void OnAppearing()
{
if(_requireAuth && !_authService.IsAuthenticated)
{
Device.BeginInvokeOnMainThread(
() => Application.Current.MainPage = new ExtendedNavigationPage(new HomePage()));
}
if(_syncIndicator)
{
MessagingCenter.Subscribe<Application, bool>(Application.Current, "SyncCompleted",
(sender, success) => Device.BeginInvokeOnMainThread(() => IsBusy = _syncService.SyncInProgress));
MessagingCenter.Subscribe<ISyncService>(Application.Current, "SyncStarted",
(sender) => Device.BeginInvokeOnMainThread(() => IsBusy = _syncService.SyncInProgress));
}
if(_syncIndicator)
{
IsBusy = _syncService.SyncInProgress;
}
_googleAnalyticsService.TrackPage(GetType().Name);
await _lockService.CheckLockAsync(false, true);
base.OnAppearing();
}
protected override void OnDisappearing()
{
if(_syncIndicator)
{
MessagingCenter.Unsubscribe<Application, bool>(Application.Current, "SyncCompleted");
MessagingCenter.Unsubscribe<Application>(Application.Current, "SyncStarted");
}
if(_syncIndicator)
{
IsBusy = false;
}
if(_updateActivity)
{
_lockService.UpdateLastActivity();
}
base.OnDisappearing();
_deviceActionService.DismissKeyboard();
}
}
}

View File

@@ -1,17 +0,0 @@
using System;
using Xamarin.Forms;
namespace Bit.App.Controls
{
public class ExtendedEditor : Editor
{
public static readonly BindableProperty HasBorderProperty =
BindableProperty.Create(nameof(HasBorder), typeof(bool), typeof(ExtendedEditor), true);
public bool HasBorder
{
get { return (bool)GetValue(HasBorderProperty); }
set { SetValue(HasBorderProperty, value); }
}
}
}

View File

@@ -1,86 +0,0 @@
using Bit.App.Enums;
using System;
using Xamarin.Forms;
namespace Bit.App.Controls
{
public class ExtendedEntry : Entry
{
public ExtendedEntry()
{
if(Device.RuntimePlatform == Device.Android)
{
PlaceholderColor = Color.FromHex("c7c7cd");
}
IsPasswordFromToggled = IsPassword;
}
public static readonly BindableProperty HasBorderProperty =
BindableProperty.Create(nameof(HasBorder), typeof(bool), typeof(ExtendedEntry), true);
public static readonly BindableProperty HasOnlyBottomBorderProperty =
BindableProperty.Create(nameof(HasOnlyBottomBorder), typeof(bool), typeof(ExtendedEntry), false);
public static readonly BindableProperty BottomBorderColorProperty =
BindableProperty.Create(nameof(BottomBorderColor), typeof(Color), typeof(ExtendedEntry), Color.Default);
public static readonly BindableProperty TargetMaxLengthProperty =
BindableProperty.Create(nameof(TargetMaxLength), typeof(int), typeof(ExtendedEntry), int.MaxValue);
public bool HasBorder
{
get { return (bool)GetValue(HasBorderProperty); }
set { SetValue(HasBorderProperty, value); }
}
public bool HasOnlyBottomBorder
{
get { return (bool)GetValue(HasOnlyBottomBorderProperty); }
set { SetValue(HasOnlyBottomBorderProperty, value); }
}
public Color BottomBorderColor
{
get { return (Color)GetValue(BottomBorderColorProperty); }
set { SetValue(BottomBorderColorProperty, value); }
}
public int TargetMaxLength
{
get { return (int)GetValue(TargetMaxLengthProperty); }
set { SetValue(TargetMaxLengthProperty, value); }
}
public Enums.ReturnType? TargetReturnType { get; set; }
public bool? Autocorrect { get; set; }
public bool DisableAutocapitalize { get; set; }
public bool AllowClear { get; set; }
public bool HideCursor { get; set; }
public bool NumbersOnly { get; set; }
// Need to overwrite default handler because we cant Invoke otherwise
public new event EventHandler Completed;
public void InvokeCompleted()
{
Completed?.Invoke(this, null);
}
public virtual void InvokeToggleIsPassword()
{
if(ToggleIsPassword == null)
{
IsPassword = IsPasswordFromToggled = !IsPassword;
Focus();
}
else
{
ToggleIsPassword.Invoke(this, null);
}
}
public event EventHandler ToggleIsPassword;
public bool IsPasswordFromToggled { get; set; } = false;
}
}

View File

@@ -1,16 +0,0 @@
using Xamarin.Forms;
namespace Bit.App.Controls
{
public class ExtendedListView : ListView
{
public static readonly BindableProperty BottomPaddingProperty =
BindableProperty.Create(nameof(BottomPadding), typeof(int), typeof(ExtendedTableView), 0);
public ExtendedListView() { }
public ExtendedListView(ListViewCachingStrategy cachingStrategy)
: base(cachingStrategy) { }
public int BottomPadding { get; set; }
}
}

View File

@@ -1,27 +0,0 @@
using System;
using Xamarin.Forms;
namespace Bit.App.Controls
{
public class ExtendedNavigationPage : NavigationPage
{
public ExtendedNavigationPage()
: base()
{
SetDefaults();
}
public ExtendedNavigationPage(Page root)
: base(root)
{
SetDefaults();
}
private void SetDefaults()
{
// default colors for our app
BarBackgroundColor = Color.FromHex("3c8dbc");
BarTextColor = Color.White;
}
}
}

View File

@@ -1,19 +0,0 @@
using System;
using Xamarin.Forms;
namespace Bit.App.Controls
{
public class ExtendedPicker : Picker
{
// TODO: text color
public static readonly BindableProperty HasBorderProperty =
BindableProperty.Create(nameof(HasBorder), typeof(bool), typeof(ExtendedEntry), true);
public bool HasBorder
{
get { return (bool)GetValue(HasBorderProperty); }
set { SetValue(HasBorderProperty, value); }
}
}
}

View File

@@ -1,16 +0,0 @@
using Xamarin.Forms;
namespace Bit.App.Controls
{
public class ExtendedSwitchCell : SwitchCell
{
public static readonly BindableProperty BackgroundColorProperty =
BindableProperty.Create(nameof(BackgroundColor), typeof(Color), typeof(ExtendedSwitchCell), Color.White);
public Color BackgroundColor
{
get { return (Color)GetValue(BackgroundColorProperty); }
set { SetValue(BackgroundColorProperty, value); }
}
}
}

View File

@@ -1,24 +0,0 @@
using System;
using Xamarin.Forms;
namespace Bit.App.Controls
{
public class ExtendedTabbedPage : TabbedPage
{
public ExtendedTabbedPage()
{
BackgroundColor = Color.FromHex("efeff4");
}
public static readonly BindableProperty TintColorProperty =
BindableProperty.Create(nameof(TintColor), typeof(Color), typeof(ExtendedTabbedPage), Color.White);
public Color TintColor
{
get { return (Color)GetValue(TintColorProperty); }
set { SetValue(TintColorProperty, value); }
}
public bool NoBorder { get; set; }
}
}

View File

@@ -1,80 +0,0 @@
using Xamarin.Forms;
using System;
using System.Reflection;
namespace Bit.App.Controls
{
public class ExtendedTableView : TableView
{
public static readonly BindableProperty EnableScrollingProperty =
BindableProperty.Create(nameof(EnableScrolling), typeof(bool), typeof(ExtendedTableView), true);
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 static readonly BindableProperty BottomPaddingProperty =
BindableProperty.Create(nameof(BottomPadding), typeof(int), typeof(ExtendedTableView), 0);
public bool EnableScrolling
{
get { return (bool)GetValue(EnableScrollingProperty); }
set { SetValue(EnableScrollingProperty, value); }
}
public bool EnableSelection
{
get { return (bool)GetValue(EnableSelectionProperty); }
set { SetValue(EnableSelectionProperty, value); }
}
public Color SeparatorColor
{
get { return (Color)GetValue(SeparatorColorProperty); }
set { SetValue(SeparatorColorProperty, value); }
}
public int EstimatedRowHeight { get; set; }
public bool NoHeader { get; set; }
public bool NoFooter { get; set; }
public int BottomPadding { get; set; }
public Func<RedrawableStackLayout> WrappingStackLayout { get; set; }
protected override SizeRequest OnSizeRequest(double widthConstraint, double heightConstraint)
{
if(!VerticalOptions.Expands && Device.RuntimePlatform != Device.UWP)
{
var baseOnSizeRequest = GetVisualElementOnSizeRequest();
return baseOnSizeRequest(widthConstraint, heightConstraint);
}
return base.OnSizeRequest(widthConstraint, heightConstraint);
}
private Func<double, double, SizeRequest> GetVisualElementOnSizeRequest()
{
var handle = typeof(VisualElement).GetMethod(
"OnSizeRequest",
BindingFlags.Instance | BindingFlags.NonPublic,
null,
new Type[] { typeof(double), typeof(double) },
null)?.MethodHandle;
if(!handle.HasValue)
{
throw new ArgumentNullException("handle could not be found.");
}
var pointer = handle.Value.GetFunctionPointer();
if(pointer == null)
{
throw new ArgumentNullException("pointer could not be found.");
}
return (Func<double, double, SizeRequest>)Activator.CreateInstance(
typeof(Func<double, double, SizeRequest>), this, pointer);
}
}
}

View File

@@ -1,60 +0,0 @@
using System;
using Xamarin.Forms;
namespace Bit.App.Controls
{
public class ExtendedTextCell : TextCell
{
public ExtendedTextCell()
{
if(Device.RuntimePlatform == Device.Android)
{
TextColor = Color.Black;
}
DetailColor = Color.FromHex("777777");
}
public static readonly BindableProperty BackgroundColorProperty =
BindableProperty.Create(nameof(BackgroundColor), typeof(Color), typeof(ExtendedTextCell), Color.White);
public static readonly BindableProperty ShowDisclousureProperty =
BindableProperty.Create(nameof(ShowDisclousure), 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 LineBreakMode DetailLineBreakMode { get; set; } = LineBreakMode.TailTruncation;
public event EventHandler DisclousureTapped;
public void OnDisclousureTapped()
{
if(DisclousureTapped == null)
{
OnTapped();
return;
}
DisclousureTapped.Invoke(this, EventArgs.Empty);
}
}
}

View File

@@ -1,30 +0,0 @@
using System;
using Xamarin.Forms;
namespace Bit.App.Controls
{
public class ExtendedToolbarItem : ToolbarItem, IDisposable
{
public ExtendedToolbarItem(Action clickAction = null)
{
ClickAction = clickAction;
}
public Action ClickAction { get; set; }
protected virtual void ClickedItem(object sender, EventArgs e)
{
ClickAction?.Invoke();
}
public void InitEvents()
{
Clicked += ClickedItem;
}
public void Dispose()
{
Clicked -= ClickedItem;
}
}
}

View File

@@ -1,26 +0,0 @@
using System;
using Xamarin.Forms;
namespace Bit.App.Controls
{
public class ExtendedViewCell : ViewCell
{
public static readonly BindableProperty BackgroundColorProperty =
BindableProperty.Create(nameof(BackgroundColor), typeof(Color), typeof(ExtendedViewCell), Color.White);
public static readonly BindableProperty ShowDisclousureProperty =
BindableProperty.Create(nameof(ShowDisclousure), typeof(bool), typeof(ExtendedViewCell), false);
public Color BackgroundColor
{
get { return (Color)GetValue(BackgroundColorProperty); }
set { SetValue(BackgroundColorProperty, value); }
}
public bool ShowDisclousure
{
get { return (bool)GetValue(ShowDisclousureProperty); }
set { SetValue(ShowDisclousureProperty, value); }
}
}
}

View File

@@ -1,24 +0,0 @@
using Refractored.FabControl;
using System;
using Xamarin.Forms;
namespace Bit.App.Controls
{
public class Fab : FloatingActionButtonView
{
public Fab(FabLayout fabLayout, string icon, Action<object, EventArgs> clickedAction)
{
ImageName = icon;
ColorNormal = Color.FromHex("3c8dbc");
ColorPressed = Color.FromHex("3883af");
ColorRipple = Color.FromHex("3883af");
Clicked = clickedAction;
AbsoluteLayout.SetLayoutFlags(this, AbsoluteLayoutFlags.PositionProportional);
AbsoluteLayout.SetLayoutBounds(this, new Rectangle(1, 1, AbsoluteLayout.AutoSize,
AbsoluteLayout.AutoSize));
fabLayout.Children.Add(this);
}
}
}

View File

@@ -1,16 +0,0 @@
using Xamarin.Forms;
namespace Bit.App.Controls
{
public class FabLayout : AbsoluteLayout
{
public FabLayout(View mainView)
{
VerticalOptions = LayoutOptions.FillAndExpand;
HorizontalOptions = LayoutOptions.FillAndExpand;
SetLayoutFlags(mainView, AbsoluteLayoutFlags.All);
SetLayoutBounds(mainView, new Rectangle(0, 0, 1, 1));
Children.Add(mainView);
}
}
}

View File

@@ -1,52 +0,0 @@
using System;
using Xamarin.Forms;
namespace Bit.App.Controls
{
public class FormEditorCell : ExtendedViewCell, IDisposable
{
public FormEditorCell(Keyboard entryKeyboard = null, double? height = null)
{
Editor = new ExtendedEditor
{
Keyboard = entryKeyboard,
HasBorder = false,
FontSize = Device.GetNamedSize(NamedSize.Medium, typeof(Editor))
};
if(height.HasValue)
{
Editor.HeightRequest = height.Value;
}
var stackLayout = new StackLayout
{
Padding = new Thickness(15, 10)
};
stackLayout.Children.Add(Editor);
Editor.AdjustMarginsForDevice();
stackLayout.AdjustPaddingForDevice();
View = stackLayout;
}
public ExtendedEditor Editor { get; private set; }
private void FormEditorCell_Tapped(object sender, EventArgs e)
{
Editor.Focus();
}
public void InitEvents()
{
Tapped += FormEditorCell_Tapped;
}
public void Dispose()
{
Tapped -= FormEditorCell_Tapped;
}
}
}

View File

@@ -1,225 +0,0 @@
using Bit.App.Abstractions;
using FFImageLoading.Forms;
using System;
using System.Collections.Generic;
using Xamarin.Forms;
using XLabs.Ioc;
namespace Bit.App.Controls
{
public class FormEntryCell : ExtendedViewCell, IDisposable
{
private VisualElement _nextElement;
private TapGestureRecognizer _tgr;
private StackLayout _buttonStackLayout = null;
public FormEntryCell(
string labelText,
Keyboard entryKeyboard = null,
bool isPassword = false,
VisualElement nextElement = null,
bool useLabelAsPlaceholder = false,
string imageSource = null,
Thickness? containerPadding = null,
string button1 = null,
string button2 = null)
{
if(!useLabelAsPlaceholder)
{
Label = new Label
{
Text = labelText,
FontSize = Device.GetNamedSize(NamedSize.Small, typeof(Label)),
Style = (Style)Application.Current.Resources["text-muted"],
HorizontalOptions = LayoutOptions.FillAndExpand
};
}
Entry = new ExtendedEntry
{
Keyboard = entryKeyboard,
HasBorder = false,
IsPassword = isPassword,
AllowClear = true,
HorizontalOptions = LayoutOptions.FillAndExpand,
WidthRequest = 1,
FontSize = Device.GetNamedSize(NamedSize.Medium, typeof(Entry))
};
if(useLabelAsPlaceholder)
{
Entry.Placeholder = labelText;
}
NextElement = nextElement;
var imageStackLayout = new StackLayout
{
Padding = containerPadding ?? new Thickness(15, 10),
Orientation = StackOrientation.Horizontal,
Spacing = 10,
HorizontalOptions = LayoutOptions.FillAndExpand,
VerticalOptions = LayoutOptions.FillAndExpand
};
if(imageSource != null)
{
_tgr = new TapGestureRecognizer();
var theImage = new CachedImage
{
Source = imageSource,
HorizontalOptions = LayoutOptions.Start,
VerticalOptions = LayoutOptions.Center,
WidthRequest = 18,
HeightRequest = 18
};
theImage.GestureRecognizers.Add(_tgr);
imageStackLayout.Children.Add(theImage);
}
var formStackLayout = new StackLayout
{
HorizontalOptions = LayoutOptions.FillAndExpand,
VerticalOptions = LayoutOptions.CenterAndExpand
};
if(!useLabelAsPlaceholder)
{
formStackLayout.Children.Add(Label);
}
formStackLayout.Children.Add(Entry);
imageStackLayout.Children.Add(formStackLayout);
if(!string.IsNullOrWhiteSpace(button1) || !string.IsNullOrWhiteSpace(button2))
{
_buttonStackLayout = new StackLayout
{
Orientation = StackOrientation.Horizontal,
VerticalOptions = LayoutOptions.CenterAndExpand,
Spacing = 5
};
imageStackLayout.Children.Add(_buttonStackLayout);
if(!string.IsNullOrWhiteSpace(button1))
{
Button1 = new ExtendedButton { Image = button1 };
_buttonStackLayout.Children.Add(Button1);
Button1.Padding = new Thickness(0);
Button1.BackgroundColor = Color.Transparent;
Button1.WidthRequest = 40;
Button1.VerticalOptions = LayoutOptions.FillAndExpand;
}
if(!string.IsNullOrWhiteSpace(button2))
{
Button2 = new ExtendedButton { Image = button2 };
_buttonStackLayout.Children.Add(Button2);
Button2.Padding = new Thickness(0);
Button2.BackgroundColor = Color.Transparent;
Button2.WidthRequest = 40;
Button2.VerticalOptions = LayoutOptions.FillAndExpand;
}
}
if(Device.RuntimePlatform == Device.Android)
{
var deviceInfo = Resolver.Resolve<IDeviceInfoService>();
if(useLabelAsPlaceholder)
{
if(deviceInfo.Version < 21)
{
Entry.Margin = new Thickness(-9, 1, -9, 0);
}
else if(deviceInfo.Version == 21)
{
Entry.Margin = new Thickness(0, 4, 0, -4);
}
}
else
{
Entry.AdjustMarginsForDevice();
}
if(containerPadding == null)
{
imageStackLayout.AdjustPaddingForDevice();
}
}
else if(Device.RuntimePlatform == Device.UWP)
{
if(_buttonStackLayout != null)
{
_buttonStackLayout.Spacing = 0;
}
}
View = imageStackLayout;
}
public Label Label { get; private set; }
public ExtendedEntry Entry { get; private set; }
public ExtendedButton Button1 { get; private set; }
public ExtendedButton Button2 { get; private set; }
public VisualElement NextElement
{
get => _nextElement;
set
{
_nextElement = value;
if(_nextElement != null && Entry != null)
{
Entry.TargetReturnType = Enums.ReturnType.Next;
}
else if(Entry != null)
{
Entry.TargetReturnType = null;
}
}
}
public Dictionary<string, object> MetaData { get; set; }
public void InitEvents()
{
if(_nextElement != null)
{
Entry.Completed += Entry_Completed;
}
if(_tgr != null)
{
_tgr.Tapped += Tgr_Tapped;
}
Tapped += FormEntryCell_Tapped;
}
private void Tgr_Tapped(object sender, EventArgs e)
{
Entry.Focus();
}
private void FormEntryCell_Tapped(object sender, EventArgs e)
{
Entry.Focus();
}
private void Entry_Completed(object sender, EventArgs e)
{
_nextElement?.Focus();
}
public void Dispose()
{
if(_tgr != null)
{
_tgr.Tapped -= Tgr_Tapped;
}
Tapped -= FormEntryCell_Tapped;
Entry.Completed -= Entry_Completed;
}
}
}

View File

@@ -1,65 +0,0 @@
using System;
using Xamarin.Forms;
namespace Bit.App.Controls
{
public class FormPickerCell : ExtendedViewCell
{
public FormPickerCell(string labelText, string[] pickerItems)
{
Label = new Label
{
Text = labelText,
FontSize = Device.GetNamedSize(NamedSize.Small, typeof(Label)),
TextColor = Color.FromHex("777777")
};
Picker = new ExtendedPicker
{
HasBorder = false
};
foreach(var item in pickerItems)
{
Picker.Items.Add(item);
}
Picker.SelectedIndex = 0;
var stackLayout = new StackLayout
{
Padding = new Thickness(15, 10),
VerticalOptions = LayoutOptions.CenterAndExpand
};
stackLayout.Children.Add(Label);
stackLayout.Children.Add(Picker);
if(Device.RuntimePlatform == Device.Android)
{
stackLayout.Spacing = 0;
}
Picker.AdjustMarginsForDevice();
stackLayout.AdjustPaddingForDevice();
View = stackLayout;
}
public Label Label { get; private set; }
public ExtendedPicker Picker { get; private set; }
private void FormPickerCell_Tapped(object sender, EventArgs e)
{
Picker.Focus();
}
public void InitEvents()
{
Tapped += FormPickerCell_Tapped;
}
public void Dispose()
{
Tapped -= FormPickerCell_Tapped;
}
}
}

View File

@@ -1,47 +0,0 @@
using Xamarin.Forms;
namespace Bit.App.Controls
{
public class FormSwitchCell : ExtendedViewCell
{
public FormSwitchCell(string labelText, string button1 = null)
{
Label = new Label
{
Text = labelText,
HorizontalOptions = LayoutOptions.FillAndExpand,
VerticalTextAlignment = TextAlignment.Center,
TextColor = Color.Black,
FontSize = Device.GetNamedSize(NamedSize.Medium, typeof(Label)),
};
Switch = new Switch
{
VerticalOptions = LayoutOptions.Center
};
var stackLayout = new StackLayout
{
Padding = new Thickness(15, 5),
Orientation = StackOrientation.Horizontal,
Children = { Label, Switch }
};
stackLayout.AdjustPaddingForDevice();
if(!string.IsNullOrWhiteSpace(button1))
{
Button1 = new ExtendedButton { Image = button1 };
stackLayout.Children.Add(Button1);
Button1.BackgroundColor = Color.Transparent;
Button1.Padding = new Thickness(0);
Button1.WidthRequest = 40;
Button1.VerticalOptions = LayoutOptions.FillAndExpand;
}
View = stackLayout;
}
public Switch Switch { get; private set; }
public Label Label { get; set; }
public ExtendedButton Button1 { get; set; }
}
}

View File

@@ -1,34 +0,0 @@
using System;
using Xamarin.Forms;
namespace Bit.App.Controls
{
public class HybridWebView : View
{
private Action<string> _func;
public static readonly BindableProperty UriProperty = BindableProperty.Create(propertyName: nameof(Uri),
returnType: typeof(string), declaringType: typeof(HybridWebView), defaultValue: default(string));
public string Uri
{
get { return (string)GetValue(UriProperty); }
set { SetValue(UriProperty, value); }
}
public void RegisterAction(Action<string> callback)
{
_func = callback;
}
public void Cleanup()
{
_func = null;
}
public void InvokeAction(string data)
{
_func?.Invoke(data);
}
}
}

View File

@@ -1,94 +0,0 @@
using FFImageLoading.Forms;
using System;
using Xamarin.Forms;
namespace Bit.App.Controls
{
public class LabeledDetailCell : ExtendedViewCell
{
public LabeledDetailCell()
{
Icon = new CachedImage
{
WidthRequest = 20,
HeightRequest = 20,
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center,
ErrorPlaceholder = "login.png",
CacheDuration = TimeSpan.FromDays(30),
BitmapOptimizations = true
};
Label = new Label
{
LineBreakMode = LineBreakMode.TailTruncation,
FontSize = Device.GetNamedSize(NamedSize.Medium, typeof(Label))
};
Detail = new Label
{
FontSize = Device.GetNamedSize(NamedSize.Small, typeof(Label)),
LineBreakMode = LineBreakMode.TailTruncation,
Style = (Style)Application.Current.Resources["text-muted"]
};
LabelIcon = new CachedImage
{
WidthRequest = 16,
HeightRequest = 16,
HorizontalOptions = LayoutOptions.Start,
Margin = new Thickness(5, 0, 0, 0)
};
LabelIcon2 = new CachedImage
{
WidthRequest = 16,
HeightRequest = 16,
HorizontalOptions = LayoutOptions.Start,
Margin = new Thickness(5, 0, 0, 0)
};
Button = new ExtendedButton
{
WidthRequest = 60
};
var grid = new Grid
{
ColumnSpacing = 0,
RowSpacing = 0,
Padding = new Thickness(3, 3, 0, 3)
};
grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(40, GridUnitType.Absolute) });
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Auto) });
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Auto) });
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(60, GridUnitType.Absolute) });
grid.Children.Add(Icon, 0, 0);
grid.Children.Add(Label, 1, 0);
grid.Children.Add(Detail, 1, 1);
grid.Children.Add(LabelIcon, 2, 0);
grid.Children.Add(LabelIcon2, 3, 0);
grid.Children.Add(Button, 4, 0);
Grid.SetRowSpan(Icon, 2);
Grid.SetRowSpan(Button, 2);
Grid.SetColumnSpan(Detail, 3);
if(Device.RuntimePlatform == Device.Android)
{
Label.TextColor = Color.Black;
}
View = grid;
}
public CachedImage Icon { get; private set; }
public Label Label { get; private set; }
public Label Detail { get; private set; }
public CachedImage LabelIcon { get; private set; }
public CachedImage LabelIcon2 { get; private set; }
public Button Button { get; private set; }
}
}

View File

@@ -1,59 +0,0 @@
using FFImageLoading.Forms;
using Xamarin.Forms;
namespace Bit.App.Controls
{
public class LabeledRightDetailCell : ExtendedViewCell
{
public LabeledRightDetailCell(bool showIcon = true)
{
Label = new Label
{
LineBreakMode = LineBreakMode.TailTruncation,
FontSize = Device.GetNamedSize(NamedSize.Medium, typeof(Label)),
HorizontalOptions = LayoutOptions.StartAndExpand,
};
Detail = new Label
{
FontSize = Device.GetNamedSize(NamedSize.Small, typeof(Label)),
Style = (Style)Application.Current.Resources["text-muted"],
HorizontalOptions = LayoutOptions.End,
VerticalOptions = LayoutOptions.Center
};
StackLayout = new StackLayout
{
Orientation = StackOrientation.Horizontal,
Padding = new Thickness(15, 10),
Children = { Label, Detail }
};
if(showIcon)
{
Icon = new CachedImage
{
WidthRequest = 16,
HeightRequest = 16,
HorizontalOptions = LayoutOptions.End,
VerticalOptions = LayoutOptions.Center,
Margin = new Thickness(5, 0, 0, 0)
};
StackLayout.Children.Add(Icon);
}
if(Device.RuntimePlatform == Device.Android)
{
Label.TextColor = Color.Black;
}
View = StackLayout;
}
public Label Label { get; private set; }
public Label Detail { get; private set; }
public CachedImage Icon { get; private set; }
public StackLayout StackLayout { get; private set; }
}
}

View File

@@ -1,138 +0,0 @@
using Xamarin.Forms;
namespace Bit.App.Controls
{
public class LabeledValueCell : ExtendedViewCell
{
public LabeledValueCell(
string labelText = null,
string valueText = null,
string button1Image = null,
string button2Image = null,
string subText = null)
{
var containerStackLayout = new StackLayout
{
Padding = new Thickness(15, 10),
Orientation = StackOrientation.Horizontal
};
var labelValueStackLayout = new StackLayout
{
HorizontalOptions = LayoutOptions.StartAndExpand,
VerticalOptions = LayoutOptions.CenterAndExpand
};
if(labelText != null)
{
Label = new Label
{
Text = labelText,
FontSize = Device.GetNamedSize(NamedSize.Small, typeof(Label)),
Style = (Style)Application.Current.Resources["text-muted"]
};
labelValueStackLayout.Children.Add(Label);
}
Value = new Label
{
Text = valueText,
FontSize = Device.GetNamedSize(NamedSize.Medium, typeof(Label)),
LineBreakMode = LineBreakMode.TailTruncation
};
if(Device.RuntimePlatform == Device.Android)
{
Value.TextColor = Color.Black;
}
labelValueStackLayout.Children.Add(Value);
containerStackLayout.Children.Add(labelValueStackLayout);
var buttonStackLayout = new StackLayout
{
Orientation = StackOrientation.Horizontal,
VerticalOptions = LayoutOptions.CenterAndExpand,
Spacing = 5
};
if(subText != null)
{
Sub = new Label
{
FontSize = Device.GetNamedSize(NamedSize.Small, typeof(Label)),
HorizontalOptions = LayoutOptions.End,
VerticalOptions = LayoutOptions.Center
};
buttonStackLayout.Children.Add(Sub);
}
if(button1Image != null)
{
Button1 = new ExtendedButton
{
Image = button1Image,
HorizontalOptions = LayoutOptions.End,
VerticalOptions = LayoutOptions.FillAndExpand,
Margin = new Thickness(0),
Padding = new Thickness(0),
BackgroundColor = Color.Transparent,
WidthRequest = 40
};
buttonStackLayout.Children.Add(Button1);
}
if(button2Image != null)
{
Button2 = new ExtendedButton
{
Image = button2Image,
HorizontalOptions = LayoutOptions.End,
VerticalOptions = LayoutOptions.FillAndExpand,
Margin = new Thickness(0),
Padding = new Thickness(0),
BackgroundColor = Color.Transparent,
WidthRequest = 40
};
buttonStackLayout.Children.Add(Button2);
}
if(Device.RuntimePlatform == Device.Android)
{
containerStackLayout.AdjustPaddingForDevice();
}
else if(Device.RuntimePlatform == Device.UWP)
{
buttonStackLayout.Spacing = 0;
if(Button1 != null)
{
Button1.BackgroundColor = Color.Transparent;
}
if(Button2 != null)
{
Button2.BackgroundColor = Color.Transparent;
}
}
if(Sub != null && Button1 != null)
{
Sub.Margin = new Thickness(0, 0, 10, 0);
}
containerStackLayout.Children.Add(buttonStackLayout);
View = containerStackLayout;
}
public Label Label { get; private set; }
public Label Value { get; private set; }
public Label Sub { get; private set; }
public ExtendedButton Button1 { get; private set; }
public ExtendedButton Button2 { get; private set; }
}
}

View File

@@ -1,61 +0,0 @@
using Bit.App.Utilities;
using System;
using Xamarin.Forms;
namespace Bit.App.Controls
{
public class PinControl
{
public EventHandler OnPinEntered;
public PinControl()
{
Label = new Label
{
HorizontalTextAlignment = TextAlignment.Center,
FontSize = 35,
FontFamily = Helpers.OnPlatform(iOS: "Menlo-Regular", Android: "monospace", Windows: "Courier")
};
Entry = new ExtendedEntry
{
Keyboard = Keyboard.Numeric,
TargetMaxLength = 4,
HideCursor = true,
NumbersOnly = true
};
Entry.BackgroundColor = Entry.TextColor = Color.Transparent;
if(Device.RuntimePlatform == Device.Android)
{
Label.TextColor = Color.Black;
}
else
{
Entry.Margin = new Thickness(0, int.MaxValue, 0, 0);
}
}
public Label Label { get; set; }
public ExtendedEntry Entry { get; set; }
private void Entry_TextChanged(object sender, TextChangedEventArgs e)
{
if(e.NewTextValue.Length >= 4)
{
OnPinEntered.Invoke(this, null);
}
}
public void InitEvents()
{
Entry.TextChanged += Entry_TextChanged;
}
public void Dispose()
{
Entry.TextChanged -= Entry_TextChanged;
}
}
}

View File

@@ -1,27 +0,0 @@
using System;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace Bit.App.Controls
{
public class RedrawableStackLayout : StackLayout
{
private DateTime _lastRedraw = DateTime.MinValue;
private TimeSpan _redrawThreshold = TimeSpan.FromMilliseconds(1000);
public async Task RedrawIfNeededAsync(int delay = 0, bool force = false)
{
var now = DateTime.UtcNow;
if(Device.RuntimePlatform == Device.iOS && (force || (now - _lastRedraw) > _redrawThreshold))
{
_lastRedraw = now;
if(delay > 0)
{
await Task.Delay(delay);
}
InvalidateLayout();
}
}
}
}

View File

@@ -1,45 +0,0 @@
using Bit.App.Utilities;
using Xamarin.Forms;
namespace Bit.App.Controls
{
public class SectionHeaderViewCell : ExtendedViewCell
{
public SectionHeaderViewCell(string bindingName, string countBindingName = null, Thickness? padding = null)
{
var label = new Label
{
FontSize = Device.GetNamedSize(NamedSize.Small, typeof(Label)),
Style = (Style)Application.Current.Resources["text-muted"],
VerticalTextAlignment = TextAlignment.Center,
HorizontalOptions = LayoutOptions.StartAndExpand
};
label.SetBinding(Label.TextProperty, bindingName);
var stackLayout = new StackLayout
{
Padding = padding ?? new Thickness(16, 8),
Children = { label },
Orientation = StackOrientation.Horizontal
};
if(!string.IsNullOrWhiteSpace(countBindingName))
{
var countLabel = new Label
{
LineBreakMode = LineBreakMode.NoWrap,
FontSize = Device.GetNamedSize(NamedSize.Small, typeof(Label)),
Style = (Style)Application.Current.Resources["text-muted"],
HorizontalOptions = LayoutOptions.End,
VerticalTextAlignment = TextAlignment.Center
};
countLabel.SetBinding(Label.TextProperty, countBindingName);
stackLayout.Children.Add(countLabel);
}
View = stackLayout;
BackgroundColor = Color.FromHex("efeff4");
}
}
}

View File

@@ -1,83 +0,0 @@
using Bit.App.Utilities;
using System;
using Xamarin.Forms;
namespace Bit.App.Controls
{
public class StepperCell : ExtendedViewCell
{
private Action _changedAction;
public StepperCell(string labelText, double value, double min, double max, double increment, Action changed = null)
{
_changedAction = changed;
Label = new Label
{
Text = labelText,
HorizontalOptions = LayoutOptions.Start,
VerticalOptions = LayoutOptions.CenterAndExpand,
FontSize = Device.GetNamedSize(NamedSize.Medium, typeof(Label))
};
StepperValueLabel = new Label
{
HorizontalOptions = LayoutOptions.FillAndExpand,
VerticalOptions = LayoutOptions.CenterAndExpand,
HorizontalTextAlignment = TextAlignment.Start,
Text = value.ToString(),
Style = (Style)Application.Current.Resources["text-muted"],
FontSize = Device.GetNamedSize(NamedSize.Medium, typeof(Label))
};
Stepper = new Stepper
{
HorizontalOptions = LayoutOptions.End,
VerticalOptions = LayoutOptions.CenterAndExpand,
Minimum = min,
Maximum = max,
Increment = increment,
Value = value
};
var stackLayout = new StackLayout
{
Orientation = StackOrientation.Horizontal,
Children = { Label, StepperValueLabel, Stepper },
Spacing = 15,
Padding = Helpers.OnPlatform(
iOS: new Thickness(15, 8),
Android: new Thickness(15, 2),
Windows: new Thickness(15, 8))
};
if(Device.RuntimePlatform == Device.Android)
{
Label.TextColor = Color.Black;
}
stackLayout.AdjustPaddingForDevice();
View = stackLayout;
}
public Label Label { get; private set; }
public Label StepperValueLabel { get; private set; }
public Stepper Stepper { get; private set; }
private void Stepper_ValueChanged(object sender, ValueChangedEventArgs e)
{
StepperValueLabel.Text = e.NewValue.ToString();
_changedAction?.Invoke();
}
public void InitEvents()
{
Stepper.ValueChanged += Stepper_ValueChanged;
}
public void Dispose()
{
Stepper.ValueChanged -= Stepper_ValueChanged;
}
}
}

View File

@@ -1,22 +0,0 @@
using Bit.App.Models.Page;
using Xamarin.Forms;
namespace Bit.App.Controls
{
public class VaultAttachmentsViewCell : LabeledRightDetailCell
{
public VaultAttachmentsViewCell()
{
Label.SetBinding(Label.TextProperty, nameof(VaultAttachmentsPageModel.Attachment.Name));
Detail.SetBinding(Label.TextProperty, nameof(VaultAttachmentsPageModel.Attachment.SizeName));
Icon.Source = "trash";
Detail.MinimumWidthRequest = 100;
BackgroundColor = Color.White;
if(Device.RuntimePlatform == Device.iOS)
{
StackLayout.BackgroundColor = Color.White;
}
}
}
}

View File

@@ -1,74 +0,0 @@
using Bit.App.Models.Page;
using FFImageLoading.Forms;
using Xamarin.Forms;
namespace Bit.App.Controls
{
public class VaultGroupingViewCell : ExtendedViewCell
{
public VaultGroupingViewCell()
{
Icon = new CachedImage
{
WidthRequest = 20,
HeightRequest = 20,
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center,
Source = "folder.png",
Margin = new Thickness(0, 0, 10, 0)
};
Label = new Label
{
LineBreakMode = LineBreakMode.TailTruncation,
FontSize = Device.GetNamedSize(NamedSize.Medium, typeof(Label)),
HorizontalOptions = LayoutOptions.StartAndExpand
};
Label.SetBinding(Label.TextProperty, string.Format("{0}.Node.{1}",
nameof(VaultListPageModel.GroupingOrCipher.Grouping), nameof(VaultListPageModel.Grouping.Name)));
CountLabel = new Label
{
LineBreakMode = LineBreakMode.NoWrap,
FontSize = Device.GetNamedSize(NamedSize.Small, typeof(Label)),
Style = (Style)Application.Current.Resources["text-muted"],
HorizontalOptions = LayoutOptions.End
};
CountLabel.SetBinding(Label.TextProperty, string.Format("{0}.Node.{1}",
nameof(VaultListPageModel.GroupingOrCipher.Grouping), nameof(VaultListPageModel.Grouping.Count)));
CountLabel.SetBinding(VisualElement.IsVisibleProperty, string.Format("{0}.Node.{1}",
nameof(VaultListPageModel.GroupingOrCipher.Grouping), nameof(VaultListPageModel.Grouping.ShowCount)));
var stackLayout = new StackLayout
{
Spacing = 0,
Padding = new Thickness(16, 10),
Children = { Icon, Label, CountLabel },
Orientation = StackOrientation.Horizontal
};
if(Device.RuntimePlatform == Device.Android)
{
Label.TextColor = Color.Black;
}
View = stackLayout;
BackgroundColor = Color.White;
}
public CachedImage Icon { get; private set; }
public Label Label { get; private set; }
public Label CountLabel { get; private set; }
protected override void OnBindingContextChanged()
{
if(BindingContext is VaultListPageModel.GroupingOrCipher model)
{
Icon.Source = model.Grouping.Node.Folder ?
$"folder{(model.Grouping.Node.Id == null ? "_o" : string.Empty)}.png" : "cube.png";
}
base.OnBindingContextChanged();
}
}
}

View File

@@ -1,84 +0,0 @@
using Bit.App.Models.Page;
using System;
using Xamarin.Forms;
namespace Bit.App.Controls
{
public class VaultListViewCell : LabeledDetailCell
{
public static readonly BindableProperty CipherParameterProperty = BindableProperty.Create(nameof(CipherParameter),
typeof(VaultListPageModel.Cipher), typeof(VaultListViewCell), null);
public static readonly BindableProperty GroupingOrCipherParameterProperty =
BindableProperty.Create(nameof(GroupingOrCipherParameter), typeof(VaultListPageModel.GroupingOrCipher),
typeof(VaultListViewCell), null);
public VaultListViewCell(Action<VaultListPageModel.Cipher> moreClickedAction, bool groupingOrCipherBinding = false)
{
string bindingPrefix = null;
if(groupingOrCipherBinding)
{
SetBinding(GroupingOrCipherParameterProperty, new Binding("."));
bindingPrefix = string.Concat(nameof(VaultListPageModel.GroupingOrCipher.Cipher), ".");
Button.Command = new Command(() => moreClickedAction?.Invoke(GroupingOrCipherParameter?.Cipher));
}
else
{
SetBinding(CipherParameterProperty, new Binding("."));
Button.Command = new Command(() => moreClickedAction?.Invoke(CipherParameter));
}
Label.SetBinding(Label.TextProperty, bindingPrefix + nameof(VaultListPageModel.Cipher.Name));
Detail.SetBinding(Label.TextProperty, bindingPrefix + nameof(VaultListPageModel.Cipher.Subtitle));
LabelIcon.SetBinding(VisualElement.IsVisibleProperty,
bindingPrefix + nameof(VaultListPageModel.Cipher.Shared));
LabelIcon2.SetBinding(VisualElement.IsVisibleProperty,
bindingPrefix + nameof(VaultListPageModel.Cipher.HasAttachments));
Button.Image = "more.png";
Button.BackgroundColor = Color.Transparent;
LabelIcon.Source = "share.png";
LabelIcon2.Source = "paperclip.png";
BackgroundColor = Color.White;
}
public VaultListPageModel.Cipher CipherParameter
{
get { return GetValue(CipherParameterProperty) as VaultListPageModel.Cipher; }
set { SetValue(CipherParameterProperty, value); }
}
public VaultListPageModel.GroupingOrCipher GroupingOrCipherParameter
{
get { return GetValue(GroupingOrCipherParameterProperty) as VaultListPageModel.GroupingOrCipher; }
set { SetValue(GroupingOrCipherParameterProperty, value); }
}
protected override void OnBindingContextChanged()
{
Icon.Source = null;
VaultListPageModel.Cipher cipher = null;
if(BindingContext is VaultListPageModel.Cipher item)
{
cipher = item;
}
else if(BindingContext is VaultListPageModel.GroupingOrCipher groupingOrCipherItem)
{
cipher = groupingOrCipherItem.Cipher;
}
if(cipher != null)
{
if(cipher.Type == Enums.CipherType.Login)
{
Icon.LoadingPlaceholder = "login.png";
}
Icon.Source = cipher.Icon;
}
base.OnBindingContextChanged();
}
}
}