mirror of
https://github.com/bitwarden/mobile
synced 2025-12-17 16:53:26 +00:00
[SG 547] Mobile username generator iOS.Extension UI changes (#2140)
* [SG-547] - Added button to generate username when using iOS extension * [SG-547] - Missing changes from last commit * SG-547 - Added missing interface method * SG-547 - Added token renovation for iOS.Extension flow * SG-547 Replaced generate buttons for icons * SG-547 Removed unnecessary validation * SG-547 - Fixed PR comments * SG 547 - Missing file from last commit * SG-547 - Fixed PR comments * SG-547 - Renamed method
This commit is contained in:
@@ -5,7 +5,6 @@ using Bit.App.Models;
|
||||
using Bit.App.Pages;
|
||||
using Bit.App.Resources;
|
||||
using Bit.App.Utilities;
|
||||
using Bit.Core;
|
||||
using Bit.Core.Abstractions;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Models.Domain;
|
||||
@@ -55,7 +54,7 @@ namespace Bit.iOS.Core.Controllers
|
||||
public abstract Action Cancel { get; }
|
||||
|
||||
public FormEntryTableViewCell MasterPasswordCell { get; set; } = new FormEntryTableViewCell(
|
||||
AppResources.MasterPassword, useButton: true);
|
||||
AppResources.MasterPassword, buttonsConfig: FormEntryTableViewCell.ButtonsConfig.One);
|
||||
|
||||
public string BiometricIntegrityKey { get; set; }
|
||||
|
||||
@@ -161,13 +160,7 @@ namespace Bit.iOS.Core.Controllers
|
||||
{
|
||||
MasterPasswordCell.TextField.KeyboardType = UIKeyboardType.NumberPad;
|
||||
}
|
||||
MasterPasswordCell.Button.TitleLabel.Font = UIFont.FromName("bwi-font", 28f);
|
||||
MasterPasswordCell.Button.SetTitle(BitwardenIcons.Eye, UIControlState.Normal);
|
||||
MasterPasswordCell.Button.TouchUpInside += (sender, e) =>
|
||||
{
|
||||
MasterPasswordCell.TextField.SecureTextEntry = !MasterPasswordCell.TextField.SecureTextEntry;
|
||||
MasterPasswordCell.Button.SetTitle(MasterPasswordCell.TextField.SecureTextEntry ? BitwardenIcons.Eye : BitwardenIcons.EyeSlash, UIControlState.Normal);
|
||||
};
|
||||
MasterPasswordCell.ConfigureToggleSecureTextCell();
|
||||
}
|
||||
|
||||
if (TableView != null)
|
||||
|
||||
@@ -14,7 +14,6 @@ using Bit.Core.Enums;
|
||||
using Bit.App.Pages;
|
||||
using Bit.App.Models;
|
||||
using Xamarin.Forms;
|
||||
using Bit.Core;
|
||||
|
||||
namespace Bit.iOS.Core.Controllers
|
||||
{
|
||||
@@ -52,7 +51,7 @@ namespace Bit.iOS.Core.Controllers
|
||||
public abstract Action Cancel { get; }
|
||||
|
||||
public FormEntryTableViewCell MasterPasswordCell { get; set; } = new FormEntryTableViewCell(
|
||||
AppResources.MasterPassword, useButton: true);
|
||||
AppResources.MasterPassword, buttonsConfig: FormEntryTableViewCell.ButtonsConfig.One);
|
||||
|
||||
public string BiometricIntegrityKey { get; set; }
|
||||
|
||||
@@ -155,12 +154,7 @@ namespace Bit.iOS.Core.Controllers
|
||||
{
|
||||
MasterPasswordCell.TextField.KeyboardType = UIKeyboardType.NumberPad;
|
||||
}
|
||||
MasterPasswordCell.Button.TitleLabel.Font = UIFont.FromName("bwi-font", 28f);
|
||||
MasterPasswordCell.Button.SetTitle(BitwardenIcons.Eye, UIControlState.Normal);
|
||||
MasterPasswordCell.Button.TouchUpInside += (sender, e) => {
|
||||
MasterPasswordCell.TextField.SecureTextEntry = !MasterPasswordCell.TextField.SecureTextEntry;
|
||||
MasterPasswordCell.Button.SetTitle(MasterPasswordCell.TextField.SecureTextEntry ? BitwardenIcons.Eye : BitwardenIcons.EyeSlash, UIControlState.Normal);
|
||||
};
|
||||
MasterPasswordCell.ConfigureToggleSecureTextCell();
|
||||
}
|
||||
|
||||
TableView.RowHeight = UITableView.AutomaticDimension;
|
||||
|
||||
@@ -1,18 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using AuthenticationServices;
|
||||
using Bit.App.Models;
|
||||
using Bit.App.Pages;
|
||||
using Bit.App.Resources;
|
||||
using Bit.App.Utilities;
|
||||
using Bit.Core;
|
||||
using Bit.Core.Abstractions;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Models.View;
|
||||
using Bit.Core.Utilities;
|
||||
using Bit.iOS.Core.Models;
|
||||
using Bit.iOS.Core.Utilities;
|
||||
using Bit.iOS.Core.Views;
|
||||
using Foundation;
|
||||
using UIKit;
|
||||
using Bit.iOS.Core.Utilities;
|
||||
using Bit.iOS.Core.Models;
|
||||
using System.Threading.Tasks;
|
||||
using AuthenticationServices;
|
||||
using Bit.Core.Abstractions;
|
||||
using Bit.Core.Models.View;
|
||||
using Bit.Core.Utilities;
|
||||
using Bit.Core.Exceptions;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.iOS.Core.Controllers
|
||||
{
|
||||
@@ -29,10 +34,8 @@ namespace Bit.iOS.Core.Controllers
|
||||
|
||||
public AppExtensionContext Context { get; set; }
|
||||
public FormEntryTableViewCell NameCell { get; set; } = new FormEntryTableViewCell(AppResources.Name);
|
||||
public FormEntryTableViewCell UsernameCell { get; set; } = new FormEntryTableViewCell(AppResources.Username);
|
||||
public FormEntryTableViewCell PasswordCell { get; set; } = new FormEntryTableViewCell(AppResources.Password);
|
||||
public UITableViewCell GeneratePasswordCell { get; set; } = new ExtendedUITableViewCell(
|
||||
UITableViewCellStyle.Subtitle, "GeneratePasswordCell");
|
||||
public FormEntryTableViewCell UsernameCell { get; set; } = new FormEntryTableViewCell(AppResources.Username, buttonsConfig: FormEntryTableViewCell.ButtonsConfig.One);
|
||||
public FormEntryTableViewCell PasswordCell { get; set; } = new FormEntryTableViewCell(AppResources.Password, buttonsConfig: FormEntryTableViewCell.ButtonsConfig.Two);
|
||||
public FormEntryTableViewCell UriCell { get; set; } = new FormEntryTableViewCell(AppResources.URI);
|
||||
public SwitchTableViewCell FavoriteCell { get; set; } = new SwitchTableViewCell(AppResources.Favorite);
|
||||
public FormEntryTableViewCell NotesCell { get; set; } = new FormEntryTableViewCell(
|
||||
@@ -67,6 +70,12 @@ namespace Bit.iOS.Core.Controllers
|
||||
UsernameCell.TextField.AutocorrectionType = UITextAutocorrectionType.No;
|
||||
UsernameCell.TextField.SpellCheckingType = UITextSpellCheckingType.No;
|
||||
UsernameCell.TextField.ReturnKeyType = UIReturnKeyType.Next;
|
||||
UsernameCell.Button.TitleLabel.Font = UIFont.FromName("bwi-font", 28f);
|
||||
UsernameCell.Button.SetTitle(BitwardenIcons.Generate, UIControlState.Normal);
|
||||
UsernameCell.Button.TouchUpInside += (sender, e) =>
|
||||
{
|
||||
LaunchUsernameGeneratorFlow();
|
||||
};
|
||||
UsernameCell.TextField.ShouldReturn += (UITextField tf) =>
|
||||
{
|
||||
PasswordCell.TextField.BecomeFirstResponder();
|
||||
@@ -75,17 +84,20 @@ namespace Bit.iOS.Core.Controllers
|
||||
|
||||
PasswordCell.TextField.SecureTextEntry = true;
|
||||
PasswordCell.TextField.ReturnKeyType = UIReturnKeyType.Next;
|
||||
PasswordCell.Button.TitleLabel.Font = UIFont.FromName("bwi-font", 28f);
|
||||
PasswordCell.Button.SetTitle(BitwardenIcons.Generate, UIControlState.Normal);
|
||||
PasswordCell.Button.TouchUpInside += (sender, e) =>
|
||||
{
|
||||
PerformSegue("passwordGeneratorSegue", this);
|
||||
};
|
||||
|
||||
PasswordCell.ConfigureToggleSecureTextCell(true);
|
||||
PasswordCell.TextField.ShouldReturn += (UITextField tf) =>
|
||||
{
|
||||
UriCell.TextField.BecomeFirstResponder();
|
||||
return true;
|
||||
};
|
||||
|
||||
GeneratePasswordCell.TextLabel.Text = AppResources.GeneratePassword;
|
||||
GeneratePasswordCell.TextLabel.TextColor = GeneratePasswordCell.TextLabel.TintColor =
|
||||
ThemeHelpers.TextColor;
|
||||
GeneratePasswordCell.Accessory = UITableViewCellAccessory.DisclosureIndicator;
|
||||
|
||||
UriCell.TextField.Text = Context?.UrlString ?? string.Empty;
|
||||
UriCell.TextField.KeyboardType = UIKeyboardType.Url;
|
||||
UriCell.TextField.ReturnKeyType = UIReturnKeyType.Next;
|
||||
@@ -210,6 +222,26 @@ namespace Bit.iOS.Core.Controllers
|
||||
AppResources.InternetConnectionRequiredMessage, AppResources.Ok);
|
||||
}
|
||||
|
||||
private void LaunchUsernameGeneratorFlow()
|
||||
{
|
||||
var appOptions = new AppOptions { IosExtension = true };
|
||||
var app = new App.App(appOptions);
|
||||
|
||||
var generatorPage = new GeneratorPage(false, selectAction: async (username) =>
|
||||
{
|
||||
UsernameCell.TextField.Text = username;
|
||||
DismissViewController(false, null);
|
||||
}, isUsernameGenerator: true, emailWebsite: NameCell.TextField.Text, appOptions: appOptions);
|
||||
|
||||
ThemeManager.SetTheme(app.Resources);
|
||||
ThemeManager.ApplyResourcesTo(generatorPage);
|
||||
|
||||
var navigationPage = new NavigationPage(generatorPage);
|
||||
var generatorController = navigationPage.CreateViewController();
|
||||
generatorController.ModalPresentationStyle = UIModalPresentationStyle.FullScreen;
|
||||
PresentViewController(generatorController, true, null);
|
||||
}
|
||||
|
||||
public class TableSource : ExtendedUITableViewSource
|
||||
{
|
||||
private LoginAddViewController _controller;
|
||||
@@ -235,10 +267,6 @@ namespace Bit.iOS.Core.Controllers
|
||||
{
|
||||
return _controller.PasswordCell;
|
||||
}
|
||||
else if (indexPath.Row == 3)
|
||||
{
|
||||
return _controller.GeneratePasswordCell;
|
||||
}
|
||||
}
|
||||
else if (indexPath.Section == 1)
|
||||
{
|
||||
@@ -277,7 +305,7 @@ namespace Bit.iOS.Core.Controllers
|
||||
{
|
||||
if (section == 0)
|
||||
{
|
||||
return 4;
|
||||
return 3;
|
||||
}
|
||||
else if (section == 1)
|
||||
{
|
||||
@@ -317,11 +345,6 @@ namespace Bit.iOS.Core.Controllers
|
||||
tableView.DeselectRow(indexPath, true);
|
||||
tableView.EndEditing(true);
|
||||
|
||||
if (indexPath.Section == 0 && indexPath.Row == 3)
|
||||
{
|
||||
_controller.PerformSegue("passwordGeneratorSegue", this);
|
||||
}
|
||||
|
||||
var cell = tableView.CellAt(indexPath);
|
||||
if (cell == null)
|
||||
{
|
||||
|
||||
@@ -379,5 +379,10 @@ namespace Bit.iOS.Core.Services
|
||||
var url = new NSUrl(UIApplication.OpenSettingsUrlString);
|
||||
UIApplication.SharedApplication.OpenUrl(url);
|
||||
}
|
||||
|
||||
public void CloseExtensionPopUp()
|
||||
{
|
||||
GetPresentedViewController().DismissViewController(true, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using Bit.iOS.Core.Controllers;
|
||||
using System;
|
||||
using Bit.Core;
|
||||
using Bit.iOS.Core.Controllers;
|
||||
using Bit.iOS.Core.Utilities;
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using UIKit;
|
||||
|
||||
namespace Bit.iOS.Core.Views
|
||||
@@ -12,14 +12,14 @@ namespace Bit.iOS.Core.Views
|
||||
public UITextField TextField { get; set; }
|
||||
public UITextView TextView { get; set; }
|
||||
public UIButton Button { get; set; }
|
||||
public UIButton SecondButton { get; set; }
|
||||
public event EventHandler ValueChanged;
|
||||
|
||||
|
||||
public FormEntryTableViewCell(
|
||||
string labelName = null,
|
||||
bool useTextView = false,
|
||||
nfloat? height = null,
|
||||
bool useButton = false,
|
||||
ButtonsConfig buttonsConfig = ButtonsConfig.None,
|
||||
bool useLabelAsPlaceholder = false,
|
||||
float leadingConstant = 15f)
|
||||
: base(UITableViewCellStyle.Default, nameof(FormEntryTableViewCell))
|
||||
@@ -85,7 +85,6 @@ namespace Bit.iOS.Core.Views
|
||||
ValueChanged?.Invoke(sender, e);
|
||||
};
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
TextField = new UITextField
|
||||
@@ -110,9 +109,10 @@ namespace Bit.iOS.Core.Views
|
||||
}
|
||||
|
||||
ContentView.Add(TextField);
|
||||
|
||||
ContentView.AddConstraints(new NSLayoutConstraint[] {
|
||||
NSLayoutConstraint.Create(TextField, NSLayoutAttribute.Leading, NSLayoutRelation.Equal, ContentView, NSLayoutAttribute.Leading, 1f, leadingConstant),
|
||||
NSLayoutConstraint.Create(ContentView, NSLayoutAttribute.Trailing, NSLayoutRelation.Equal, TextField, NSLayoutAttribute.Trailing, 1f, useButton ? 55f : 15f),
|
||||
NSLayoutConstraint.Create(ContentView, NSLayoutAttribute.Trailing, NSLayoutRelation.Equal, TextField, NSLayoutAttribute.Trailing, 1f, GetTextFieldToContainerTrailingConstant(buttonsConfig)),
|
||||
NSLayoutConstraint.Create(ContentView, NSLayoutAttribute.Bottom, NSLayoutRelation.Equal, TextField, NSLayoutAttribute.Bottom, 1f, 10f)
|
||||
});
|
||||
|
||||
@@ -148,18 +148,9 @@ namespace Bit.iOS.Core.Views
|
||||
});
|
||||
}
|
||||
|
||||
if (useButton)
|
||||
if(buttonsConfig != ButtonsConfig.None)
|
||||
{
|
||||
Button = new UIButton(UIButtonType.System);
|
||||
Button.Frame = ContentView.Bounds;
|
||||
Button.TranslatesAutoresizingMaskIntoConstraints = false;
|
||||
Button.SetTitleColor(ThemeHelpers.PrimaryColor, UIControlState.Normal);
|
||||
|
||||
ContentView.Add(Button);
|
||||
|
||||
ContentView.BottomAnchor.ConstraintEqualTo(Button.BottomAnchor, 10f).Active = true;
|
||||
ContentView.TrailingAnchor.ConstraintEqualTo(Button.TrailingAnchor, 10f).Active = true;
|
||||
Button.LeadingAnchor.ConstraintEqualTo(TextField.TrailingAnchor, 10f).Active = true;
|
||||
AddButtons(buttonsConfig);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,5 +165,74 @@ namespace Bit.iOS.Core.Views
|
||||
TextField.BecomeFirstResponder();
|
||||
}
|
||||
}
|
||||
|
||||
public void ConfigureToggleSecureTextCell(bool useSecondaryButton = false)
|
||||
{
|
||||
var button = useSecondaryButton ? SecondButton : Button;
|
||||
button.TitleLabel.Font = UIFont.FromName("bwi-font", 28f);
|
||||
button.SetTitle(BitwardenIcons.Eye, UIControlState.Normal);
|
||||
button.TouchUpInside += (sender, e) =>
|
||||
{
|
||||
TextField.SecureTextEntry = !TextField.SecureTextEntry;
|
||||
button.SetTitle(TextField.SecureTextEntry ? BitwardenIcons.Eye : BitwardenIcons.EyeSlash, UIControlState.Normal);
|
||||
};
|
||||
}
|
||||
|
||||
private void AddButtons(ButtonsConfig buttonsConfig)
|
||||
{
|
||||
Button = new UIButton(UIButtonType.System);
|
||||
Button.TranslatesAutoresizingMaskIntoConstraints = false;
|
||||
Button.SetTitleColor(ThemeHelpers.PrimaryColor, UIControlState.Normal);
|
||||
|
||||
ContentView.Add(Button);
|
||||
|
||||
ContentView.BottomAnchor.ConstraintEqualTo(Button.BottomAnchor, 10f).Active = true;
|
||||
|
||||
switch (buttonsConfig)
|
||||
{
|
||||
case ButtonsConfig.One:
|
||||
ContentView.AddConstraints(new NSLayoutConstraint[] {
|
||||
NSLayoutConstraint.Create(ContentView, NSLayoutAttribute.Trailing, NSLayoutRelation.Equal, Button, NSLayoutAttribute.Trailing, 1f, 10f),
|
||||
NSLayoutConstraint.Create(Button, NSLayoutAttribute.Leading, NSLayoutRelation.Equal, TextField, NSLayoutAttribute.Trailing, 1f, 10f)
|
||||
});
|
||||
break;
|
||||
case ButtonsConfig.Two:
|
||||
SecondButton = new UIButton(UIButtonType.System);
|
||||
SecondButton.TranslatesAutoresizingMaskIntoConstraints = false;
|
||||
SecondButton.SetTitleColor(ThemeHelpers.PrimaryColor, UIControlState.Normal);
|
||||
|
||||
ContentView.Add(SecondButton);
|
||||
|
||||
ContentView.AddConstraints(new NSLayoutConstraint[] {
|
||||
NSLayoutConstraint.Create(ContentView, NSLayoutAttribute.Bottom, NSLayoutRelation.Equal, SecondButton, NSLayoutAttribute.Bottom, 1f, 10f),
|
||||
NSLayoutConstraint.Create(SecondButton, NSLayoutAttribute.Leading, NSLayoutRelation.Equal, TextField, NSLayoutAttribute.Trailing, 1f, 9f),
|
||||
NSLayoutConstraint.Create(Button, NSLayoutAttribute.Leading, NSLayoutRelation.Equal, SecondButton, NSLayoutAttribute.Trailing, 1f, 10f),
|
||||
NSLayoutConstraint.Create(ContentView, NSLayoutAttribute.Trailing, NSLayoutRelation.Equal, Button, NSLayoutAttribute.Trailing, 1f, 10f)
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private float GetTextFieldToContainerTrailingConstant(ButtonsConfig buttonsConfig)
|
||||
{
|
||||
switch (buttonsConfig)
|
||||
{
|
||||
case ButtonsConfig.None:
|
||||
return 15f;
|
||||
case ButtonsConfig.One:
|
||||
return 55f;
|
||||
case ButtonsConfig.Two:
|
||||
return 95f;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
public enum ButtonsConfig : byte
|
||||
{
|
||||
None = 0,
|
||||
One = 1,
|
||||
Two = 2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user