1
0
mirror of https://github.com/bitwarden/mobile synced 2025-12-27 05:33:23 +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,409 +0,0 @@
using System;
using XLabs.Ioc;
using Foundation;
using UIKit;
using Bit.App.Abstractions;
using Bit.App.Services;
using Bit.iOS.Services;
using Plugin.Connectivity;
using Bit.App.Repositories;
using Plugin.Fingerprint;
using Plugin.Settings.Abstractions;
using System.Diagnostics;
using Xamarin.Forms;
using Bit.iOS.Core.Services;
using Plugin.Connectivity.Abstractions;
using Bit.App.Pages;
using HockeyApp.iOS;
using Bit.iOS.Core;
using SimpleInjector;
using XLabs.Ioc.SimpleInjectorContainer;
using CoreNFC;
using Bit.App.Resources;
using AuthenticationServices;
using System.Threading.Tasks;
using Bit.App.Models;
using System.Linq;
using System.Collections.Generic;
using Bit.iOS.Core.Utilities;
namespace Bit.iOS
{
[Register("AppDelegate")]
public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
{
private NFCNdefReaderSession _nfcSession = null;
private ILockService _lockService;
private IDeviceInfoService _deviceInfoService;
private ICipherService _cipherService;
private iOSPushNotificationHandler _pushHandler = null;
private NFCReaderDelegate _nfcDelegate = null;
public ISettings Settings { get; set; }
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
Forms.Init();
if(!Resolver.IsSet)
{
SetIoc();
}
_lockService = Resolver.Resolve<ILockService>();
_deviceInfoService = Resolver.Resolve<IDeviceInfoService>();
_cipherService = Resolver.Resolve<ICipherService>();
_pushHandler = new iOSPushNotificationHandler(Resolver.Resolve<IPushNotificationListener>());
_nfcDelegate = new NFCReaderDelegate((success, message) => ProcessYubikey(success, message));
var appIdService = Resolver.Resolve<IAppIdService>();
var crashManagerDelegate = new HockeyAppCrashManagerDelegate(
appIdService, Resolver.Resolve<IAuthService>());
var manager = BITHockeyManager.SharedHockeyManager;
manager.Configure("51f96ae568ba45f699a18ad9f63046c3", crashManagerDelegate);
manager.CrashManager.CrashManagerStatus = BITCrashManagerStatus.AutoSend;
manager.UserId = appIdService.AppId;
manager.StartManager();
manager.Authenticator.AuthenticateInstallation();
manager.DisableMetricsManager = manager.DisableFeedbackManager = manager.DisableUpdateManager = true;
LoadApplication(new App.App(
null,
Resolver.Resolve<IAuthService>(),
Resolver.Resolve<IConnectivity>(),
Resolver.Resolve<IDatabaseService>(),
Resolver.Resolve<ISyncService>(),
Resolver.Resolve<ISettings>(),
_lockService,
Resolver.Resolve<ILocalizeService>(),
Resolver.Resolve<IAppInfoService>(),
Resolver.Resolve<IAppSettingsService>(),
Resolver.Resolve<IDeviceActionService>()));
// Appearance stuff
var primaryColor = new UIColor(red: 0.24f, green: 0.55f, blue: 0.74f, alpha: 1.0f);
var grayLight = new UIColor(red: 0.47f, green: 0.47f, blue: 0.47f, alpha: 1.0f);
UINavigationBar.Appearance.ShadowImage = new UIImage();
UINavigationBar.Appearance.SetBackgroundImage(new UIImage(), UIBarMetrics.Default);
UIBarButtonItem.AppearanceWhenContainedIn(new Type[] { typeof(UISearchBar) }).TintColor = primaryColor;
UIButton.AppearanceWhenContainedIn(new Type[] { typeof(UISearchBar) }).SetTitleColor(primaryColor,
UIControlState.Normal);
UIButton.AppearanceWhenContainedIn(new Type[] { typeof(UISearchBar) }).TintColor = primaryColor;
UIStepper.Appearance.TintColor = grayLight;
UISlider.Appearance.TintColor = primaryColor;
MessagingCenter.Subscribe<Xamarin.Forms.Application, ToolsExtensionPage>(
Xamarin.Forms.Application.Current, "ShowAppExtension", (sender, page) =>
{
var itemProvider = new NSItemProvider(new NSDictionary(), Core.Constants.UTTypeAppExtensionSetup);
var extensionItem = new NSExtensionItem();
extensionItem.Attachments = new NSItemProvider[] { itemProvider };
var activityViewController = new UIActivityViewController(new NSExtensionItem[] { extensionItem }, null);
activityViewController.CompletionHandler = (activityType, completed) =>
{
page.EnabledExtension(completed && activityType == "com.8bit.bitwarden.find-login-action-extension");
};
var modal = UIApplication.SharedApplication.KeyWindow.RootViewController.ModalViewController;
if(activityViewController.PopoverPresentationController != null)
{
activityViewController.PopoverPresentationController.SourceView = modal.View;
var frame = UIScreen.MainScreen.Bounds;
frame.Height /= 2;
activityViewController.PopoverPresentationController.SourceRect = frame;
}
modal.PresentViewController(activityViewController, true, null);
});
MessagingCenter.Subscribe<Xamarin.Forms.Application, bool>(
Xamarin.Forms.Application.Current, "ListenYubiKeyOTP", (sender, listen) =>
{
if(_deviceInfoService.NfcEnabled)
{
_nfcSession?.InvalidateSession();
_nfcSession?.Dispose();
_nfcSession = null;
if(listen)
{
_nfcSession = new NFCNdefReaderSession(_nfcDelegate, null, true);
_nfcSession.AlertMessage = AppResources.HoldYubikeyNearTop;
_nfcSession.BeginSession();
}
}
});
UIApplication.SharedApplication.StatusBarHidden = false;
UIApplication.SharedApplication.StatusBarStyle = UIStatusBarStyle.LightContent;
MessagingCenter.Subscribe<Xamarin.Forms.Application, bool>(
Xamarin.Forms.Application.Current, "ShowStatusBar", (sender, show) =>
{
UIApplication.SharedApplication.SetStatusBarHidden(!show, false);
});
MessagingCenter.Subscribe<Xamarin.Forms.Application, bool>(
Xamarin.Forms.Application.Current, "FullSyncCompleted", async (sender, successfully) =>
{
if(_deviceInfoService.Version >= 12 && successfully)
{
await ASHelpers.ReplaceAllIdentities(_cipherService);
}
});
MessagingCenter.Subscribe<Xamarin.Forms.Application, Tuple<string, bool>>(
Xamarin.Forms.Application.Current, "UpsertedCipher", async (sender, data) =>
{
if(_deviceInfoService.Version >= 12)
{
if(await ASHelpers.IdentitiesCanIncremental())
{
if(data.Item2)
{
var identity = await ASHelpers.GetCipherIdentityAsync(data.Item1, _cipherService);
if(identity == null)
{
return;
}
await ASCredentialIdentityStore.SharedStore?.SaveCredentialIdentitiesAsync(
new ASPasswordCredentialIdentity[] { identity });
return;
}
}
await ASHelpers.ReplaceAllIdentities(_cipherService);
}
});
MessagingCenter.Subscribe<Xamarin.Forms.Application, Cipher>(
Xamarin.Forms.Application.Current, "DeletedCipher", async (sender, cipher) =>
{
if(_deviceInfoService.Version >= 12)
{
if(await ASHelpers.IdentitiesCanIncremental())
{
var identity = ASHelpers.ToCredentialIdentity(cipher);
if(identity == null)
{
return;
}
await ASCredentialIdentityStore.SharedStore?.RemoveCredentialIdentitiesAsync(
new ASPasswordCredentialIdentity[] { identity });
return;
}
await ASHelpers.ReplaceAllIdentities(_cipherService);
}
});
MessagingCenter.Subscribe<Xamarin.Forms.Application>(
Xamarin.Forms.Application.Current, "LoggedOut", async (sender) =>
{
if(_deviceInfoService.Version >= 12)
{
await ASCredentialIdentityStore.SharedStore?.RemoveAllCredentialIdentitiesAsync();
}
});
ZXing.Net.Mobile.Forms.iOS.Platform.Init();
return base.FinishedLaunching(app, options);
}
public override void DidEnterBackground(UIApplication uiApplication)
{
var view = new UIView(UIApplication.SharedApplication.KeyWindow.Frame)
{
Tag = 4321
};
var backgroundView = new UIView(UIApplication.SharedApplication.KeyWindow.Frame)
{
BackgroundColor = new UIColor(red: 0.93f, green: 0.94f, blue: 0.96f, alpha: 1.0f)
};
var imageView = new UIImageView(new UIImage("logo.png"))
{
Center = new CoreGraphics.CGPoint(view.Center.X, view.Center.Y - 30)
};
view.AddSubview(backgroundView);
view.AddSubview(imageView);
UIApplication.SharedApplication.KeyWindow.AddSubview(view);
UIApplication.SharedApplication.KeyWindow.BringSubviewToFront(view);
UIApplication.SharedApplication.KeyWindow.EndEditing(true);
UIApplication.SharedApplication.SetStatusBarHidden(true, false);
// Log the date/time we last backgrounded
_lockService.UpdateLastActivity();
// Dispatch Google Analytics
SendGoogleAnalyticsHitsInBackground();
base.DidEnterBackground(uiApplication);
Debug.WriteLine("DidEnterBackground");
}
public override void OnResignActivation(UIApplication uiApplication)
{
base.OnResignActivation(uiApplication);
Debug.WriteLine("OnResignActivation");
}
public override void WillTerminate(UIApplication uiApplication)
{
base.WillTerminate(uiApplication);
Debug.WriteLine("WillTerminate");
}
public override void OnActivated(UIApplication uiApplication)
{
base.OnActivated(uiApplication);
Debug.WriteLine("OnActivated");
UIApplication.SharedApplication.ApplicationIconBadgeNumber = 0;
var view = UIApplication.SharedApplication.KeyWindow.ViewWithTag(4321);
if(view != null)
{
view.RemoveFromSuperview();
UIApplication.SharedApplication.SetStatusBarHidden(false, false);
}
}
public override void WillEnterForeground(UIApplication uiApplication)
{
SendResumedMessage();
base.WillEnterForeground(uiApplication);
Debug.WriteLine("WillEnterForeground");
}
public override bool OpenUrl(UIApplication application, NSUrl url, string sourceApplication,
NSObject annotation)
{
return true;
}
public override void FailedToRegisterForRemoteNotifications(UIApplication application, NSError error)
{
_pushHandler?.OnErrorReceived(error);
}
public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
{
_pushHandler?.OnRegisteredSuccess(deviceToken);
}
public override void DidRegisterUserNotificationSettings(UIApplication application,
UIUserNotificationSettings notificationSettings)
{
application.RegisterForRemoteNotifications();
}
public override void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo,
Action<UIBackgroundFetchResult> completionHandler)
{
_pushHandler?.OnMessageReceived(userInfo);
}
public override void ReceivedRemoteNotification(UIApplication application, NSDictionary userInfo)
{
_pushHandler?.OnMessageReceived(userInfo);
}
private void SendResumedMessage()
{
MessagingCenter.Send(Xamarin.Forms.Application.Current, "Resumed", false);
}
private void SetIoc()
{
var container = new Container();
// Services
container.RegisterSingleton<IDatabaseService, DatabaseService>();
container.RegisterSingleton<ISqlService, SqlService>();
container.RegisterSingleton<ISecureStorageService, KeyChainStorageService>();
container.RegisterSingleton<ICryptoService, CryptoService>();
container.RegisterSingleton<IKeyDerivationService, CommonCryptoKeyDerivationService>();
container.RegisterSingleton<IAuthService, AuthService>();
container.RegisterSingleton<IFolderService, FolderService>();
container.RegisterSingleton<ICollectionService, CollectionService>();
container.RegisterSingleton<ICipherService, CipherService>();
container.RegisterSingleton<ISyncService, SyncService>();
container.RegisterSingleton<IDeviceActionService, DeviceActionService>();
container.RegisterSingleton<IAppIdService, AppIdService>();
container.RegisterSingleton<IPasswordGenerationService, PasswordGenerationService>();
container.RegisterSingleton<ILockService, LockService>();
container.RegisterSingleton<IAppInfoService, AppInfoService>();
container.RegisterSingleton<IGoogleAnalyticsService, GoogleAnalyticsService>();
container.RegisterInstance<IDeviceInfoService>(new DeviceInfoService());
container.RegisterSingleton<ILocalizeService, LocalizeService>();
container.RegisterSingleton<ILogService, LogService>();
container.RegisterSingleton<IHttpService, HttpService>();
container.RegisterSingleton<ITokenService, TokenService>();
container.RegisterSingleton<ISettingsService, SettingsService>();
container.RegisterSingleton<IAppSettingsService, AppSettingsService>();
// Repositories
container.RegisterSingleton<IFolderRepository, FolderRepository>();
container.RegisterSingleton<IFolderApiRepository, FolderApiRepository>();
container.RegisterSingleton<ICipherRepository, CipherRepository>();
container.RegisterSingleton<IAttachmentRepository, AttachmentRepository>();
container.RegisterSingleton<IConnectApiRepository, ConnectApiRepository>();
container.RegisterSingleton<IDeviceApiRepository, DeviceApiRepository>();
container.RegisterSingleton<IAccountsApiRepository, AccountsApiRepository>();
container.RegisterSingleton<ICipherApiRepository, CipherApiRepository>();
container.RegisterSingleton<ISettingsRepository, SettingsRepository>();
container.RegisterSingleton<ISettingsApiRepository, SettingsApiRepository>();
container.RegisterSingleton<ITwoFactorApiRepository, TwoFactorApiRepository>();
container.RegisterSingleton<ISyncApiRepository, SyncApiRepository>();
container.RegisterSingleton<ICollectionRepository, CollectionRepository>();
container.RegisterSingleton<ICipherCollectionRepository, CipherCollectionRepository>();
// Other
container.RegisterInstance(CrossConnectivity.Current);
container.RegisterInstance(CrossFingerprint.Current);
Settings = new Settings("group.com.8bit.bitwarden");
container.RegisterInstance(Settings);
// Push
container.RegisterSingleton<IPushNotificationListener, PushNotificationListener>();
container.RegisterSingleton<IPushNotificationService, iOSPushNotificationService>();
FFImageLoading.Forms.Platform.CachedImageRenderer.Init();
Resolver.SetResolver(new SimpleInjectorResolver(container));
}
/// <summary>
/// This method sends any queued hits when the app enters the background.
/// ref: https://developers.google.com/analytics/devguides/collection/ios/v3/dispatch
/// </summary>
private void SendGoogleAnalyticsHitsInBackground()
{
var taskExpired = false;
var taskId = UIApplication.SharedApplication.BeginBackgroundTask(() =>
{
taskExpired = true;
});
if(taskId == UIApplication.BackgroundTaskInvalid)
{
return;
}
}
private void ProcessYubikey(bool success, string message)
{
if(success)
{
Device.BeginInvokeOnMainThread(() =>
{
MessagingCenter.Send(Xamarin.Forms.Application.Current, "GotYubiKeyOTP", message);
});
}
}
}
}

View File

@@ -1,68 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Bit.iOS.Controls;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(ContentPage), typeof(ContentPageRenderer))]
namespace Bit.iOS.Controls
{
public class ContentPageRenderer : PageRenderer
{
public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
var contentPage = Element as ContentPage;
if(contentPage == null || NavigationController == null)
{
return;
}
var itemsInfo = contentPage.ToolbarItems;
var navigationItem = NavigationController.TopViewController.NavigationItem;
var leftNativeButtons = (navigationItem.LeftBarButtonItems ?? new UIBarButtonItem[] { }).ToList();
var rightNativeButtons = (navigationItem.RightBarButtonItems ?? new UIBarButtonItem[] { }).ToList();
var newLeftButtons = new List<UIBarButtonItem>();
var newRightButtons = new List<UIBarButtonItem>();
rightNativeButtons.ForEach(nativeItem =>
{
// Use reflection to get Xamarin private field "_item"
var field = nativeItem.GetType().GetField("_item", BindingFlags.NonPublic | BindingFlags.Instance);
if(field == null)
{
return;
}
var info = field.GetValue(nativeItem) as ToolbarItem;
if(info == null)
{
return;
}
if(info.Priority < 0)
{
newLeftButtons.Add(nativeItem);
}
else
{
newRightButtons.Add(nativeItem);
}
});
leftNativeButtons.ForEach(nativeItem =>
{
newLeftButtons.Add(nativeItem);
});
navigationItem.RightBarButtonItems = newRightButtons.ToArray();
navigationItem.LeftBarButtonItems = newLeftButtons.ToArray();
}
}
}

View File

@@ -1,60 +0,0 @@
using System;
using Bit.iOS.Controls;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using System.ComponentModel;
[assembly: ExportRenderer(typeof(Button), typeof(CustomButtonRenderer))]
namespace Bit.iOS.Controls
{
public class CustomButtonRenderer : ButtonRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
{
base.OnElementChanged(e);
var view = e.NewElement as Button;
if(Control != null && view != null)
{
UpdateFont();
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if(e.PropertyName == Button.FontProperty.PropertyName)
{
UpdateFont();
}
}
private void UpdateFont()
{
var pointSize = UIFontDescriptor.PreferredBody.PointSize;
var size = Element.FontSize;
if(size == Device.GetNamedSize(NamedSize.Large, typeof(Button)))
{
pointSize *= 1.3f;
}
else if(size == Device.GetNamedSize(NamedSize.Small, typeof(Button)))
{
pointSize *= .8f;
}
else if(size == Device.GetNamedSize(NamedSize.Micro, typeof(Button)))
{
pointSize *= .6f;
}
else if(size != Device.GetNamedSize(NamedSize.Default, typeof(Button)))
{
// not using dynamic font sizes, return
return;
}
Control.Font = UIFont.FromDescriptor(Element.Font.ToUIFont().FontDescriptor, pointSize);
}
}
}

View File

@@ -1,72 +0,0 @@
using System;
using System.ComponentModel;
using Bit.iOS.Controls;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(Label), typeof(CustomLabelRenderer))]
namespace Bit.iOS.Controls
{
public class CustomLabelRenderer : LabelRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
base.OnElementChanged(e);
var view = e.NewElement as Label;
if(Control != null && view != null)
{
UpdateFont();
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if(e.PropertyName == Label.TextColorProperty.PropertyName)
{
UpdateFont();
}
else if(e.PropertyName == Label.FontProperty.PropertyName)
{
UpdateFont();
}
else if(e.PropertyName == Label.TextProperty.PropertyName)
{
UpdateFont();
}
else if(e.PropertyName == Label.FormattedTextProperty.PropertyName)
{
UpdateFont();
}
}
private void UpdateFont()
{
var pointSize = UIFontDescriptor.PreferredBody.PointSize;
var size = Element.FontSize;
if(size == Device.GetNamedSize(NamedSize.Large, typeof(Label)))
{
pointSize *= 1.3f;
}
else if(size == Device.GetNamedSize(NamedSize.Small, typeof(Label)))
{
pointSize *= .8f;
}
else if(size == Device.GetNamedSize(NamedSize.Micro, typeof(Label)))
{
pointSize *= .6f;
}
else if(size != Device.GetNamedSize(NamedSize.Default, typeof(Label)))
{
// not using dynamic font sizes, return
return;
}
Control.Font = UIFont.FromDescriptor(Element.Font.ToUIFont().FontDescriptor, pointSize);
}
}
}

View File

@@ -1,33 +0,0 @@
using Bit.App.Controls;
using Bit.iOS.Controls;
using System.ComponentModel;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(SearchBar), typeof(CustomSearchBarRenderer))]
namespace Bit.iOS.Controls
{
public class CustomSearchBarRenderer : SearchBarRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<SearchBar> e)
{
base.OnElementChanged(e);
var view = e.NewElement;
if(view != null)
{
Control.SearchBarStyle = UISearchBarStyle.Minimal;
Control.BarStyle = UIBarStyle.BlackTranslucent;
Control.ShowsCancelButton = Control.IsFirstResponder;
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
var view = Element;
Control.ShowsCancelButton = Control.IsFirstResponder;
}
}
}

View File

@@ -1,56 +0,0 @@
using System;
using Bit.iOS.Controls;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using System.ComponentModel;
using Bit.App.Controls;
[assembly: ExportRenderer(typeof(ExtendedButton), typeof(ExtendedButtonRenderer))]
namespace Bit.iOS.Controls
{
public class ExtendedButtonRenderer : CustomButtonRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
{
base.OnElementChanged(e);
SetPadding();
SetUppercase();
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if(e.PropertyName == ExtendedButton.PaddingProperty.PropertyName)
{
SetPadding();
}
else if(e.PropertyName == ExtendedButton.UppercaseProperty.PropertyName)
{
SetUppercase();
}
}
private void SetPadding()
{
var element = Element as ExtendedButton;
if(element != null)
{
Control.ContentEdgeInsets = new UIEdgeInsets(
(int)element.Padding.Top,
(int)element.Padding.Left,
(int)element.Padding.Bottom,
(int)element.Padding.Right);
}
}
private void SetUppercase()
{
var element = Element as ExtendedButton;
if(element != null && element.Uppercase)
{
Control.TitleLabel.Text = Control.TitleLabel.Text.ToUpper();
}
}
}
}

View File

@@ -1,26 +0,0 @@
using System;
using System.ComponentModel;
using Bit.App.Controls;
using Bit.iOS.Controls;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(ExtendedEditor), typeof(ExtendedEditorRenderer))]
namespace Bit.iOS.Controls
{
public class ExtendedEditorRenderer : EditorRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Editor> e)
{
base.OnElementChanged(e);
var view = e.NewElement as ExtendedEditor;
if(view != null)
{
var descriptor = UIFontDescriptor.PreferredBody;
Control.Font = UIFont.FromDescriptor(descriptor, descriptor.PointSize);
}
}
}
}

View File

@@ -1,190 +0,0 @@
using System;
using System.ComponentModel;
using Bit.App.Controls;
using Bit.iOS.Controls;
using CoreAnimation;
using CoreGraphics;
using Foundation;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(ExtendedEntry), typeof(ExtendedEntryRenderer))]
namespace Bit.iOS.Controls
{
public class ExtendedEntryRenderer : EntryRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
var view = e.NewElement as ExtendedEntry;
if(view != null)
{
SetBorder(view);
SetMaxLength(view);
UpdateKeyboard();
UpdateFont();
if(view.AllowClear)
{
Control.ClearButtonMode = UITextFieldViewMode.WhileEditing;
}
if(view.DisableAutocapitalize)
{
Control.AutocapitalizationType = UITextAutocapitalizationType.None;
}
if(view.Autocorrect.HasValue)
{
Control.AutocorrectionType = view.Autocorrect.Value ? UITextAutocorrectionType.Yes : UITextAutocorrectionType.No;
}
if(view.HideCursor)
{
Control.TintColor = UIColor.Clear;
}
if(view.TargetReturnType.HasValue)
{
switch(view.TargetReturnType.Value)
{
case App.Enums.ReturnType.Done:
Control.ReturnKeyType = UIReturnKeyType.Done;
break;
case App.Enums.ReturnType.Go:
Control.ReturnKeyType = UIReturnKeyType.Go;
break;
case App.Enums.ReturnType.Next:
Control.ReturnKeyType = UIReturnKeyType.Next;
break;
case App.Enums.ReturnType.Search:
Control.ReturnKeyType = UIReturnKeyType.Search;
break;
case App.Enums.ReturnType.Send:
Control.ReturnKeyType = UIReturnKeyType.Send;
break;
default:
Control.ReturnKeyType = UIReturnKeyType.Default;
break;
}
}
Control.ShouldReturn += (UITextField tf) =>
{
view.InvokeCompleted();
return true;
};
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
var view = (ExtendedEntry)Element;
if(e.PropertyName == ExtendedEntry.HasBorderProperty.PropertyName
|| e.PropertyName == ExtendedEntry.HasOnlyBottomBorderProperty.PropertyName
|| e.PropertyName == ExtendedEntry.BottomBorderColorProperty.PropertyName)
{
SetBorder(view);
}
else if(e.PropertyName == Xamarin.Forms.InputView.KeyboardProperty.PropertyName)
{
UpdateKeyboard();
}
else if(e.PropertyName == Entry.FontAttributesProperty.PropertyName)
{
UpdateFont();
}
else if(e.PropertyName == Entry.FontFamilyProperty.PropertyName)
{
UpdateFont();
}
else if(e.PropertyName == Entry.FontSizeProperty.PropertyName)
{
UpdateFont();
}
}
private void UpdateFont()
{
var descriptor = UIFontDescriptor.PreferredBody;
var pointSize = descriptor.PointSize;
var size = Element.FontSize;
if(size == Device.GetNamedSize(NamedSize.Large, typeof(ExtendedEntry)))
{
pointSize *= 1.3f;
}
else if(size == Device.GetNamedSize(NamedSize.Small, typeof(ExtendedEntry)))
{
pointSize *= .8f;
}
else if(size == Device.GetNamedSize(NamedSize.Micro, typeof(ExtendedEntry)))
{
pointSize *= .6f;
}
else if(size != Device.GetNamedSize(NamedSize.Default, typeof(ExtendedEntry)))
{
// not using dynamic font sizes, return
return;
}
if(!string.IsNullOrWhiteSpace(Element.FontFamily))
{
Control.Font = UIFont.FromName(Element.FontFamily, pointSize);
}
else
{
Control.Font = UIFont.FromDescriptor(descriptor, pointSize);
}
}
private void SetBorder(ExtendedEntry view)
{
if(view.HasOnlyBottomBorder)
{
var borderLayer = new CALayer();
borderLayer.MasksToBounds = true;
borderLayer.Frame = new CGRect(0f, Frame.Height / 2, Frame.Width * 2, 1f);
borderLayer.BorderColor = view.BottomBorderColor.ToCGColor();
borderLayer.BorderWidth = 1f;
Control.Layer.AddSublayer(borderLayer);
Control.BorderStyle = UITextBorderStyle.None;
}
else if(view.HasBorder)
{
Control.BorderStyle = UITextBorderStyle.RoundedRect;
}
else
{
Control.BorderStyle = UITextBorderStyle.None;
}
}
private void SetMaxLength(ExtendedEntry view)
{
Control.ShouldChangeCharacters = (textField, range, replacementString) =>
{
var newLength = textField.Text.Length + replacementString.Length - range.Length;
return newLength <= view.TargetMaxLength;
};
}
private void UpdateKeyboard()
{
if(Element.Keyboard == Keyboard.Numeric)
{
Control.KeyboardType = UIKeyboardType.NumberPad;
}
else
{
Control.ApplyKeyboard(Element.Keyboard);
}
}
}
}

View File

@@ -1,44 +0,0 @@
using Bit.App.Controls;
using System;
using System.ComponentModel;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(ExtendedListView), typeof(Bit.iOS.Controls.ExtendedListViewRenderer))]
namespace Bit.iOS.Controls
{
public class ExtendedListViewRenderer : ListViewRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<ListView> e)
{
base.OnElementChanged(e);
// primary color
Control.SectionIndexColor = new UIColor(red: 0.24f, green: 0.55f, blue: 0.74f, alpha: 1.0f);
if(e.NewElement is ExtendedListView view)
{
SetMargin(view);
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if(e.PropertyName == View.MarginProperty.PropertyName)
{
SetMargin(Element);
}
}
private void SetMargin(ListView view)
{
Control.ContentInset = new UIEdgeInsets(
new nfloat(view.Margin.Top),
new nfloat(view.Margin.Left),
new nfloat(view.Margin.Bottom),
new nfloat(view.Margin.Right));
}
}
}

View File

@@ -1,45 +0,0 @@
using System;
using System.ComponentModel;
using Bit.App.Controls;
using Bit.iOS.Controls;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(ExtendedPicker), typeof(ExtendedPickerRenderer))]
namespace Bit.iOS.Controls
{
public class ExtendedPickerRenderer : PickerRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Picker> e)
{
base.OnElementChanged(e);
var view = e.NewElement as ExtendedPicker;
if(view != null)
{
var descriptor = UIFontDescriptor.PreferredBody;
Control.Font = UIFont.FromDescriptor(descriptor, descriptor.PointSize);
SetBorder(view);
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
var view = (ExtendedPicker)Element;
if(e.PropertyName == ExtendedPicker.HasBorderProperty.PropertyName)
{
SetBorder(view);
}
}
private void SetBorder(ExtendedPicker view)
{
Control.BorderStyle = view.HasBorder ? UITextBorderStyle.RoundedRect : UITextBorderStyle.None;
}
}
}

View File

@@ -1,25 +0,0 @@
using Bit.App.Controls;
using Bit.iOS.Controls;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(ExtendedSwitchCell), typeof(ExtendedSwitchCellRenderer))]
namespace Bit.iOS.Controls
{
public class ExtendedSwitchCellRenderer : SwitchCellRenderer
{
public override UITableViewCell GetCell(Cell item, UITableViewCell reusableCell, UITableView tv)
{
var extendedCell = (ExtendedSwitchCell)item;
var cell = base.GetCell(item, reusableCell, tv);
if(cell != null)
{
cell.BackgroundColor = extendedCell.BackgroundColor.ToUIColor();
}
return cell;
}
}
}

View File

@@ -1,79 +0,0 @@
using System;
using Bit.App.Controls;
using Bit.iOS.Controls;
using Foundation;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(ExtendedTabbedPage), typeof(ExtendedTabbedPageRenderer))]
namespace Bit.iOS.Controls
{
public class ExtendedTabbedPageRenderer : TabbedRenderer
{
protected override void OnElementChanged(VisualElementChangedEventArgs e)
{
base.OnElementChanged(e);
var page = (ExtendedTabbedPage)Element;
TabBar.TintColor = page.TintColor.ToUIColor();
TabBar.BackgroundColor = page.BackgroundColor.ToUIColor();
if(page.NoBorder)
{
// remove top border
// ref: http://stackoverflow.com/questions/14371343/ios-uitabbar-remove-top-shadow-gradient-line
TabBar.SetValueForKeyPath(FromObject(true), new NSString("_hidesShadow"));
}
}
public override void ViewWillAppear(bool animated)
{
if(TabBar?.Items == null)
{
return;
}
if(Element is TabbedPage tabs)
{
for(int i = 0; i < TabBar.Items.Length; i++)
{
UpdateItem(TabBar.Items[i], tabs.Children[i].Icon);
}
}
base.ViewWillAppear(animated);
}
private void UpdateItem(UITabBarItem item, string icon)
{
if(item == null)
{
return;
}
try
{
// Only show icon
// ref: https://stackoverflow.com/questions/26494130/remove-tab-bar-item-text-show-only-image
item.Title = string.Empty;
if(UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Phone)
{
item.ImageInsets = new UIEdgeInsets(6, 0, -6, 0);
}
// Set selected icon
icon = string.Concat(icon, "_selected");
if(item?.SelectedImage?.AccessibilityIdentifier == icon)
{
return;
}
item.SelectedImage = UIImage.FromBundle(icon);
item.SelectedImage.AccessibilityIdentifier = icon;
}
catch { }
}
}
}

View File

@@ -1,181 +0,0 @@
using System;
using System.ComponentModel;
using Bit.App.Controls;
using Bit.iOS.Controls;
using CoreGraphics;
using Foundation;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(ExtendedTableView), typeof(ExtendedTableViewRenderer))]
namespace Bit.iOS.Controls
{
public class ExtendedTableViewRenderer : TableViewRenderer
{
public override SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
{
Control.LayoutIfNeeded();
var size = new Size(Control.ContentSize.Width, Control.ContentSize.Height);
return new SizeRequest(size);
}
protected override void OnElementChanged(ElementChangedEventArgs<TableView> e)
{
base.OnElementChanged(e);
var view = e.NewElement as ExtendedTableView;
if(view != null)
{
SetScrolling(view);
SetSelection(view);
UpdateRowHeight(view);
UpdateEstimatedRowHeight(view);
UpdateSeparatorColor(view);
SetSource();
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
var view = (ExtendedTableView)Element;
if(e.PropertyName == ExtendedTableView.EnableScrollingProperty.PropertyName)
{
SetScrolling(view);
}
else if(e.PropertyName == ExtendedTableView.RowHeightProperty.PropertyName)
{
UpdateRowHeight(view);
}
else if(e.PropertyName == ExtendedTableView.EnableSelectionProperty.PropertyName)
{
SetSelection(view);
}
else if(e.PropertyName == TableView.HasUnevenRowsProperty.PropertyName)
{
SetSource();
}
}
private void SetSource()
{
var view = (ExtendedTableView)Element;
Control.Source = new CustomTableViewModelRenderer(view);
}
private void SetScrolling(ExtendedTableView view)
{
Control.ScrollEnabled = view.EnableScrolling;
}
private void SetSelection(ExtendedTableView view)
{
Control.AllowsSelection = view.EnableSelection;
}
private void UpdateRowHeight(ExtendedTableView view)
{
var rowHeight = view.RowHeight;
if(view.HasUnevenRows && rowHeight == -1)
{
Control.RowHeight = UITableView.AutomaticDimension;
}
else
{
Control.RowHeight = rowHeight <= 0 ? 44 : rowHeight;
}
}
private void UpdateEstimatedRowHeight(ExtendedTableView view)
{
if(view.HasUnevenRows && view.RowHeight == -1)
{
Control.EstimatedRowHeight = view.EstimatedRowHeight;
}
else
{
Control.EstimatedRowHeight = 0;
}
}
private void UpdateSeparatorColor(ExtendedTableView view)
{
Control.SeparatorColor = view.SeparatorColor.ToUIColor(UIColor.Gray);
}
public class CustomTableViewModelRenderer : UnEvenTableViewModelRenderer
{
private readonly ExtendedTableView _view;
private bool _didRedraw = false;
public CustomTableViewModelRenderer(ExtendedTableView model)
: base(model)
{
_view = model;
}
public override async void WillDisplay(UITableView tableView, UITableViewCell cell, NSIndexPath indexPath)
{
// ref https://stackoverflow.com/a/48076188/1090359
if(!_didRedraw && _view.WrappingStackLayout != null)
{
_didRedraw = true;
await _view.WrappingStackLayout()?.RedrawIfNeededAsync(10, false);
}
}
public override nfloat GetHeightForRow(UITableView tableView, NSIndexPath indexPath)
{
if(_view.HasUnevenRows)
{
return UITableView.AutomaticDimension;
}
return base.GetHeightForRow(tableView, indexPath);
}
public override nfloat GetHeightForHeader(UITableView tableView, nint section)
{
if(_view.NoHeader && section == 0)
{
return 0.00001f;
}
return base.GetHeightForHeader(tableView, section);
}
public override UIView GetViewForHeader(UITableView tableView, nint section)
{
if(_view.NoHeader && section == 0)
{
return new UIView(new CGRect(0, 0, 0, 0));
}
return null;
}
public override nfloat GetHeightForFooter(UITableView tableView, nint section)
{
if(_view.NoFooter && (section + 1) == NumberOfSections(tableView))
{
return 0.00001f;
}
return 10f;
}
public override UIView GetViewForFooter(UITableView tableView, nint section)
{
if(_view.NoFooter && (section + 1) == NumberOfSections(tableView))
{
return new UIView(new CGRect(0, 0, 0, 0));
}
return null;
}
}
}
}

View File

@@ -1,90 +0,0 @@
using Bit.App.Controls;
using Bit.iOS.Controls;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using CoreGraphics;
[assembly: ExportRenderer(typeof(ExtendedTextCell), typeof(ExtendedTextCellRenderer))]
namespace Bit.iOS.Controls
{
public class ExtendedTextCellRenderer : TextCellRenderer
{
public override UITableViewCell GetCell(Cell item, UITableViewCell reusableCell, UITableView tv)
{
var extendedCell = (ExtendedTextCell)item;
var cell = base.GetCell(item, reusableCell, tv);
if(cell != null)
{
cell.BackgroundColor = extendedCell.BackgroundColor.ToUIColor();
if(extendedCell.ShowDisclousure)
{
cell.Accessory = UITableViewCellAccessory.DisclosureIndicator;
if(!string.IsNullOrEmpty(extendedCell.DisclousureImage))
{
var detailDisclosureButton = UIButton.FromType(UIButtonType.Custom);
detailDisclosureButton.SetImage(UIImage.FromBundle(extendedCell.DisclousureImage), UIControlState.Normal);
try
{
detailDisclosureButton.SetImage(UIImage.FromBundle(extendedCell.DisclousureImage + "_selected"), UIControlState.Selected);
}
catch
{
detailDisclosureButton.SetImage(UIImage.FromBundle(extendedCell.DisclousureImage), UIControlState.Selected);
}
detailDisclosureButton.Frame = new CGRect(0f, 0f, 50f, 100f);
detailDisclosureButton.TouchUpInside += (sender, e) =>
{
extendedCell.OnDisclousureTapped();
};
cell.AccessoryView = detailDisclosureButton;
}
}
WireUpForceUpdateSizeRequested(item, cell, tv);
UpdateLineBreakMode(cell.DetailTextLabel, extendedCell.DetailLineBreakMode);
}
return cell;
}
private void UpdateLineBreakMode(UILabel label, LineBreakMode lineBreakMode)
{
if(label == null)
{
return;
}
switch(lineBreakMode)
{
case LineBreakMode.NoWrap:
label.LineBreakMode = UILineBreakMode.Clip;
label.Lines = 1;
break;
case LineBreakMode.WordWrap:
label.LineBreakMode = UILineBreakMode.WordWrap;
label.Lines = 0;
break;
case LineBreakMode.CharacterWrap:
label.LineBreakMode = UILineBreakMode.CharacterWrap;
label.Lines = 0;
break;
case LineBreakMode.HeadTruncation:
label.LineBreakMode = UILineBreakMode.HeadTruncation;
label.Lines = 1;
break;
case LineBreakMode.MiddleTruncation:
label.LineBreakMode = UILineBreakMode.MiddleTruncation;
label.Lines = 1;
break;
case LineBreakMode.TailTruncation:
label.LineBreakMode = UILineBreakMode.TailTruncation;
label.Lines = 1;
break;
}
}
}
}

View File

@@ -1,31 +0,0 @@
using Bit.App.Controls;
using Bit.iOS.Controls;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(ExtendedViewCell), typeof(ExtendedViewCellRenderer))]
namespace Bit.iOS.Controls
{
public class ExtendedViewCellRenderer : ViewCellRenderer
{
public override UITableViewCell GetCell(Cell item, UITableViewCell reusableCell, UITableView tv)
{
var extendedCell = (ExtendedViewCell)item;
var cell = base.GetCell(item, reusableCell, tv);
if(cell != null)
{
cell.BackgroundColor = extendedCell.BackgroundColor.ToUIColor();
if(extendedCell.ShowDisclousure)
{
cell.Accessory = UITableViewCellAccessory.DisclosureIndicator;
}
}
WireUpForceUpdateSizeRequested(item, cell, tv);
return cell;
}
}
}

View File

@@ -1,54 +0,0 @@
using System.IO;
using Foundation;
using WebKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using Bit.App.Controls;
using Bit.iOS.Controls;
[assembly: ExportRenderer(typeof(HybridWebView), typeof(HybridWebViewRenderer))]
namespace Bit.iOS.Controls
{
public class HybridWebViewRenderer : ViewRenderer<HybridWebView, WKWebView>, IWKScriptMessageHandler
{
private const string JSFunction =
"function invokeCSharpAction(data){window.webkit.messageHandlers.invokeAction.postMessage(data);}";
private WKUserContentController _userController;
protected override void OnElementChanged(ElementChangedEventArgs<HybridWebView> e)
{
base.OnElementChanged(e);
if(Control == null)
{
_userController = new WKUserContentController();
var script = new WKUserScript(new NSString(JSFunction), WKUserScriptInjectionTime.AtDocumentEnd, false);
_userController.AddUserScript(script);
_userController.AddScriptMessageHandler(this, "invokeAction");
var config = new WKWebViewConfiguration { UserContentController = _userController };
var webView = new WKWebView(Frame, config);
SetNativeControl(webView);
}
if(e.OldElement != null)
{
_userController.RemoveAllUserScripts();
_userController.RemoveScriptMessageHandler("invokeAction");
var hybridWebView = e.OldElement as HybridWebView;
hybridWebView.Cleanup();
}
if(e.NewElement != null)
{
Control.LoadRequest(new NSUrlRequest(new NSUrl(Element.Uri)));
}
}
public void DidReceiveScriptMessage(WKUserContentController userContentController, WKScriptMessage message)
{
Element.InvokeAction(message.Body.ToString());
}
}
}

View File

@@ -1,28 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.developer.authentication-services.autofill-credential-provider</key>
<true/>
<key>com.apple.security.application-groups</key>
<array>
<string>group.com.8bit.bitwarden</string>
</array>
<key>keychain-access-groups</key>
<array>
<string>$(AppIdentifierPrefix)com.8bit.bitwarden</string>
</array>
<key>com.apple.developer.ubiquity-container-identifiers</key>
<array>
<string>iCloud.$(CFBundleIdentifier)</string>
</array>
<key>com.apple.developer.nfc.readersession.formats</key>
<array>
<string>NDEF</string>
</array>
<key>com.apple.developer.associated-domains</key>
<array>
<string>webcredentials:bitwarden.com</string>
</array>
</dict>
</plist>

View File

@@ -1,115 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>MinimumOSVersion</key>
<string>10.0</string>
<key>UIDeviceFamily</key>
<array>
<integer>1</integer>
<integer>2</integer>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>CFBundleDisplayName</key>
<string>Bitwarden</string>
<key>CFBundleIdentifier</key>
<string>com.8bit.bitwarden</string>
<key>CFBundleVersion</key>
<string>46</string>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>CFBundleShortVersionString</key>
<string>1.22.0</string>
<key>UIMainStoryboardFile~ipad</key>
<string>LaunchScreen</string>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>bitwarden</string>
<string>org-appextension-feature-password-management</string>
</array>
<key>CFBundleURLName</key>
<string>com.8bit.bitwarden.url</string>
</dict>
</array>
<key>UIBackgroundModes</key>
<array>
<string>remote-notification</string>
</array>
<key>UIStatusBarHidden</key>
<true/>
<key>ITSAppUsesNonExemptEncryption</key>
<true/>
<key>ITSEncryptionExportComplianceCode</key>
<string>ecf076d3-4824-4d7b-b716-2a9a47d7d296</string>
<key>CFBundleName</key>
<string>Bitwarden</string>
<key>UIRequiredDeviceCapabilities</key>
<dict>
<key>arm64</key>
<true/>
</dict>
<key>CFBundleLocalizations</key>
<array>
<string>en</string>
<string>es</string>
<string>zh-Hans</string>
<string>zh-Hant</string>
<string>pt-PT</string>
<string>pt-BR</string>
<string>sv</string>
<string>sk</string>
<string>it</string>
<string>fi</string>
<string>fr</string>
<string>ro</string>
<string>id</string>
<string>hr</string>
<string>hu</string>
<string>nl</string>
<string>tr</string>
<string>uk</string>
<string>de</string>
<string>dk</string>
<string>cz</string>
<string>nb</string>
<string>ja</string>
<string>et</string>
<string>vi</string>
<string>pl</string>
<string>ko</string>
<string>fa</string>
</array>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>This app does not require access to the photo library.</string>
<key>NSCameraUsageDescription</key>
<string>Scan QR codes</string>
<key>XSAppIconAssets</key>
<string>Resources/Assets.xcassets/AppIcons.appiconset</string>
<key>CFBundleIconName</key>
<string>AppIcon</string>
<key>NSFaceIDUsageDescription</key>
<string>Use Face ID to unlock your vault.</string>
<key>NFCReaderUsageDescription</key>
<string>Use Yubikeys for two-facor authentication.</string>
</dict>
</plist>

View File

@@ -1,92 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="6211" systemVersion="14A298i" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="5">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6204"/>
</dependencies>
<scenes>
<scene sceneID="4">
<objects>
<viewController id="5" sceneMemberID="viewController" customClass="LaunchScreenViewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="2"/>
<viewControllerLayoutGuide type="bottom" id="3"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="6">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<color key="backgroundColor" customColorSpace="calibratedWhite" colorSpace="calibratedRGB" red="0.92549019607843142" green="0.94117647058823528" blue="0.96078431372549022" alpha="1"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" id="16" translatesAutoresizingMaskIntoConstraints="NO" image="logo.png">
<rect key="frame" x="159" y="248" width="282" height="44"/>
</imageView>
</subviews>
<constraints>
<constraint id="19" firstItem="16" firstAttribute="centerY" secondItem="6" secondAttribute="centerY" constant="-30"/>
<constraint id="20" firstItem="6" firstAttribute="centerX" secondItem="16" secondAttribute="centerX"/>
</constraints>
</view>
<connections/>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="7" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-54" y="0.0"/>
</scene>
</scenes>
<resources>
<image name="Default.png" width="320" height="480"/>
<image name="fa-cogs.png" width="22" height="22"/>
<image name="fa-lock.png" width="22" height="22"/>
<image name="fa-refresh.png" width="22" height="22"/>
<image name="fa_folder_open.png" width="14" height="14"/>
<image name="Icon-120.png" width="120" height="120"/>
<image name="Icon-152.png" width="152" height="152"/>
<image name="Icon-16.png" width="16" height="16"/>
<image name="Icon-24.png" width="24" height="24"/>
<image name="Icon-32.png" width="32" height="32"/>
<image name="Icon-40.png" width="40" height="40"/>
<image name="Icon-60.png" width="60" height="60"/>
<image name="Icon-64.png" width="64" height="64"/>
<image name="Icon-72.png" width="72" height="72"/>
<image name="Icon-76.png" width="76" height="76"/>
<image name="Icon-Small-40.png" width="40" height="40"/>
<image name="Icon-Small-50.png" width="50" height="50"/>
<image name="Icon-Small.png" width="29" height="29"/>
<image name="Icon.png" width="57" height="57"/>
<image name="ion_chevron_right.png" width="14" height="14"/>
<image name="ion_plus.png" width="22" height="22"/>
<image name="logo.png" width="282" height="44"/>
<image name="cogs.png" width="29" height="29"/>
<image name="eye.png" width="22" height="22"/>
<image name="eye_slash.png" width="22" height="22"/>
<image name="more.png" width="28" height="28"/>
<image name="more_selected.png" width="28" height="28"/>
<image name="plus.png" width="18" height="18"/>
<image name="star.png" width="25" height="25"/>
<image name="cloudup.png" width="44" height="44"/>
<image name="envelope.png" width="18" height="18"/>
<image name="globe.png" width="44" height="44"/>
<image name="lightbulb-o.png" width="18" height="18"/>
<image name="lock.png" width="18" height="18"/>
<image name="refresh.png" width="44" height="44"/>
<image name="upload.png" width="44" height="44"/>
<image name="user.png" width="18" height="18"/>
<image name="wrench.png" width="22" height="22"/>
<image name="camera.png" width="22" height="22"/>
<image name="download.png" width="18" height="18"/>
<image name="ext-act.png" width="290" height="252"/>
<image name="ext-more.png" width="290" height="252"/>
<image name="ext-use.png" width="290" height="252"/>
<image name="fa_lock.png" width="25" height="25"/>
<image name="fingerprint.png" width="91" height="92"/>
<image name="folder.png" width="18" height="18"/>
<image name="Icon-83.5.png" width="83.5" height="83.5"/>
<image name="lightbulb.png" width="18" height="18"/>
<image name="paperclip.png" width="14" height="14"/>
<image name="photo.png" width="22" height="22"/>
<image name="share.png" width="14" height="14"/>
<image name="share_tools.png" width="44" height="44"/>
<image name="tools.png" width="26" height="26"/>
<image name="trash.png" width="18" height="18"/>
<image name="yubikey.png" width="266" height="160"/>
</resources>
</document>

View File

@@ -1,22 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Foundation;
using UIKit;
namespace Bit.iOS
{
public class Application
{
// This is the main entry point of the application.
static void Main(string[] args)
{
ObjCRuntime.Dlfcn.dlopen(ObjCRuntime.Constants.libSystemLibrary, 0);
// if you want to use a different Application Delegate class from "AppDelegate"
// you can specify it here.
UIApplication.Main(args, null, "AppDelegate");
}
}
}

View File

@@ -1,54 +0,0 @@
using CoreNFC;
using Foundation;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text.RegularExpressions;
namespace Bit.iOS
{
public class NFCReaderDelegate : NFCNdefReaderSessionDelegate
{
private Regex _otpPattern = new Regex("^.*?([cbdefghijklnrtuv]{32,64})$");
private Action<bool, string> _callback;
public NFCReaderDelegate(Action<bool, string> callback)
{
_callback = callback;
}
public override void DidDetect(NFCNdefReaderSession session, NFCNdefMessage[] messages)
{
var results = new List<string>();
foreach(var message in messages)
{
foreach(var record in message.Records)
{
try
{
results.Add(new NSString(record.Payload, NSStringEncoding.UTF8));
}
catch { }
}
}
foreach(var result in results)
{
var matches = _otpPattern.Matches(result);
if(matches.Count > 0 && matches[0].Groups.Count > 1)
{
var otp = matches[0].Groups[1].ToString();
_callback.Invoke(true, otp);
return;
}
}
_callback.Invoke(false, "No tags were read.");
}
public override void DidInvalidate(NFCNdefReaderSession session, NSError error)
{
_callback.Invoke(false, error?.LocalizedDescription);
}
}
}

View File

@@ -1,35 +0,0 @@
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("BitwardeniOS")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("8bit Solutions LLC")]
[assembly: AssemblyProduct("Bitwarden")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("72bdc44f-c588-44f3-b6df-9aace7daafdd")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -1,117 +0,0 @@
{
"images": [
{
"scale": "2x",
"size": "20x20",
"idiom": "iphone",
"filename": "Icon-40.png"
},
{
"scale": "3x",
"size": "20x20",
"idiom": "iphone",
"filename": "Icon-60.png"
},
{
"scale": "2x",
"size": "29x29",
"idiom": "iphone",
"filename": "Icon-58.png"
},
{
"scale": "3x",
"size": "29x29",
"idiom": "iphone",
"filename": "Icon-87.png"
},
{
"scale": "2x",
"size": "40x40",
"idiom": "iphone",
"filename": "Icon-80.png"
},
{
"scale": "3x",
"size": "40x40",
"idiom": "iphone",
"filename": "Icon-120.png"
},
{
"scale": "2x",
"size": "60x60",
"idiom": "iphone",
"filename": "Icon-120.png"
},
{
"scale": "3x",
"size": "60x60",
"idiom": "iphone",
"filename": "Icon-180.png"
},
{
"scale": "1x",
"size": "20x20",
"idiom": "ipad",
"filename": "Icon-20.png"
},
{
"scale": "2x",
"size": "20x20",
"idiom": "ipad",
"filename": "Icon-40.png"
},
{
"scale": "1x",
"size": "29x29",
"idiom": "ipad",
"filename": "Icon-29.png"
},
{
"scale": "2x",
"size": "29x29",
"idiom": "ipad",
"filename": "Icon-58.png"
},
{
"scale": "1x",
"size": "40x40",
"idiom": "ipad",
"filename": "Icon-40.png"
},
{
"scale": "2x",
"size": "40x40",
"idiom": "ipad",
"filename": "Icon-80.png"
},
{
"scale": "1x",
"size": "76x76",
"idiom": "ipad",
"filename": "Icon-76.png"
},
{
"scale": "2x",
"size": "76x76",
"idiom": "ipad",
"filename": "Icon-152.png"
},
{
"scale": "2x",
"size": "83.5x83.5",
"idiom": "ipad",
"filename": "Icon-167.png"
},
{
"scale": "1x",
"size": "1024x1024",
"idiom": "ios-marketing",
"filename": "Icon-1024.png"
}
],
"properties": {},
"info": {
"version": 1,
"author": "xcode"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 800 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 863 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 406 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 659 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 994 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 446 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 741 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1005 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 478 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 802 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 229 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 234 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 350 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 487 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 677 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 779 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 610 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 590 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1005 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 878 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 533 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 941 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 378 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 556 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 707 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 374 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 629 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 884 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 607 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 659 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 437 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 663 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 877 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 388 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 598 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 810 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 401 B

Some files were not shown because too many files have changed in this diff Show More