mirror of
https://github.com/bitwarden/android.git
synced 2024-12-21 00:31:58 +03:00
Added tools extension page to help iOS users activate the action extension.
This commit is contained in:
parent
55ed801fe7
commit
6bb7651ad1
8 changed files with 273 additions and 2 deletions
|
@ -97,6 +97,7 @@
|
||||||
<Compile Include="Models\Data\SiteData.cs" />
|
<Compile Include="Models\Data\SiteData.cs" />
|
||||||
<Compile Include="Models\DomainName.cs" />
|
<Compile Include="Models\DomainName.cs" />
|
||||||
<Compile Include="Models\Folder.cs" />
|
<Compile Include="Models\Folder.cs" />
|
||||||
|
<Compile Include="Models\Page\AppExtensionPageModel.cs" />
|
||||||
<Compile Include="Models\Page\SettingsFolderPageModel.cs" />
|
<Compile Include="Models\Page\SettingsFolderPageModel.cs" />
|
||||||
<Compile Include="Models\Page\PinPageModel.cs" />
|
<Compile Include="Models\Page\PinPageModel.cs" />
|
||||||
<Compile Include="Models\Page\PasswordGeneratorPageModel.cs" />
|
<Compile Include="Models\Page\PasswordGeneratorPageModel.cs" />
|
||||||
|
@ -110,6 +111,7 @@
|
||||||
<Compile Include="Pages\MainPage.cs" />
|
<Compile Include="Pages\MainPage.cs" />
|
||||||
<Compile Include="Pages\Settings\SettingsEditFolderPage.cs" />
|
<Compile Include="Pages\Settings\SettingsEditFolderPage.cs" />
|
||||||
<Compile Include="Pages\Lock\LockFingerprintPage.cs" />
|
<Compile Include="Pages\Lock\LockFingerprintPage.cs" />
|
||||||
|
<Compile Include="Pages\Tools\ToolsExtensionPage.cs" />
|
||||||
<Compile Include="Pages\Tools\ToolsPasswordGeneratorSettingsPage.cs" />
|
<Compile Include="Pages\Tools\ToolsPasswordGeneratorSettingsPage.cs" />
|
||||||
<Compile Include="Pages\Tools\ToolsPasswordGeneratorPage.cs" />
|
<Compile Include="Pages\Tools\ToolsPasswordGeneratorPage.cs" />
|
||||||
<Compile Include="Pages\Tools\ToolsPage.cs" />
|
<Compile Include="Pages\Tools\ToolsPage.cs" />
|
||||||
|
|
|
@ -18,5 +18,8 @@
|
||||||
|
|
||||||
public const string PushInitialPromptShown = "push:initialPromptShown";
|
public const string PushInitialPromptShown = "push:initialPromptShown";
|
||||||
public const string PushLastRegistrationDate = "push:lastRegistrationDate";
|
public const string PushLastRegistrationDate = "push:lastRegistrationDate";
|
||||||
|
|
||||||
|
public const string ExtensionStarted = "extension:started";
|
||||||
|
public const string ExtensionActivated = "extension:activated";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
47
src/App/Models/Page/AppExtensionPageModel.cs
Normal file
47
src/App/Models/Page/AppExtensionPageModel.cs
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using Plugin.Settings.Abstractions;
|
||||||
|
|
||||||
|
namespace Bit.App.Models.Page
|
||||||
|
{
|
||||||
|
public class AppExtensionPageModel : INotifyPropertyChanged
|
||||||
|
{
|
||||||
|
private readonly ISettings _settings;
|
||||||
|
|
||||||
|
public AppExtensionPageModel(ISettings settings)
|
||||||
|
{
|
||||||
|
_settings = settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public event PropertyChangedEventHandler PropertyChanged;
|
||||||
|
|
||||||
|
public bool Started
|
||||||
|
{
|
||||||
|
get { return _settings.GetValueOrDefault(Constants.ExtensionStarted, false); }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_settings.AddOrUpdateValue(Constants.ExtensionStarted, true);
|
||||||
|
PropertyChanged(this, new PropertyChangedEventArgs(nameof(Started)));
|
||||||
|
PropertyChanged(this, new PropertyChangedEventArgs(nameof(NotStarted)));
|
||||||
|
PropertyChanged(this, new PropertyChangedEventArgs(nameof(StartedAndNotActivated)));
|
||||||
|
PropertyChanged(this, new PropertyChangedEventArgs(nameof(StartedAndActivated)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Activated
|
||||||
|
{
|
||||||
|
get { return _settings.GetValueOrDefault(Constants.ExtensionActivated, false); }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_settings.AddOrUpdateValue(Constants.ExtensionActivated, value);
|
||||||
|
PropertyChanged(this, new PropertyChangedEventArgs(nameof(Activated)));
|
||||||
|
PropertyChanged(this, new PropertyChangedEventArgs(nameof(StartedAndNotActivated)));
|
||||||
|
PropertyChanged(this, new PropertyChangedEventArgs(nameof(StartedAndActivated)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool NotStarted => !Started;
|
||||||
|
public bool StartedAndNotActivated => Started && !Activated;
|
||||||
|
public bool StartedAndActivated => Started && Activated;
|
||||||
|
}
|
||||||
|
}
|
197
src/App/Pages/Tools/ToolsExtensionPage.cs
Normal file
197
src/App/Pages/Tools/ToolsExtensionPage.cs
Normal file
|
@ -0,0 +1,197 @@
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Acr.UserDialogs;
|
||||||
|
using Bit.App.Controls;
|
||||||
|
using Bit.App.Models.Page;
|
||||||
|
using Plugin.Settings.Abstractions;
|
||||||
|
using Xamarin.Forms;
|
||||||
|
using XLabs.Ioc;
|
||||||
|
|
||||||
|
namespace Bit.App.Pages
|
||||||
|
{
|
||||||
|
public class ToolsExtensionPage : ExtendedContentPage
|
||||||
|
{
|
||||||
|
private readonly IUserDialogs _userDialogs;
|
||||||
|
private readonly ISettings _settings;
|
||||||
|
|
||||||
|
public ToolsExtensionPage()
|
||||||
|
{
|
||||||
|
_userDialogs = Resolver.Resolve<IUserDialogs>();
|
||||||
|
_settings = Resolver.Resolve<ISettings>();
|
||||||
|
Model = new AppExtensionPageModel(_settings);
|
||||||
|
|
||||||
|
Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public AppExtensionPageModel Model { get; private set; }
|
||||||
|
|
||||||
|
public void Init()
|
||||||
|
{
|
||||||
|
// Not Started
|
||||||
|
|
||||||
|
var notStartedLabel = new Label
|
||||||
|
{
|
||||||
|
Text = "Get instant access to your passwords!",
|
||||||
|
VerticalOptions = LayoutOptions.Start,
|
||||||
|
HorizontalOptions = LayoutOptions.Center,
|
||||||
|
HorizontalTextAlignment = TextAlignment.Center,
|
||||||
|
LineBreakMode = LineBreakMode.WordWrap,
|
||||||
|
FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label))
|
||||||
|
};
|
||||||
|
|
||||||
|
var notStartedSublabel = new Label
|
||||||
|
{
|
||||||
|
Text = "To turn on bitwarden in Safari and other apps, tap \"more\" on the second row of the menu.",
|
||||||
|
VerticalOptions = LayoutOptions.Start,
|
||||||
|
HorizontalOptions = LayoutOptions.Center,
|
||||||
|
HorizontalTextAlignment = TextAlignment.Center,
|
||||||
|
LineBreakMode = LineBreakMode.WordWrap
|
||||||
|
};
|
||||||
|
|
||||||
|
var notStartedImage = new Image
|
||||||
|
{
|
||||||
|
Source = "",
|
||||||
|
VerticalOptions = LayoutOptions.CenterAndExpand,
|
||||||
|
HorizontalOptions = LayoutOptions.Center
|
||||||
|
};
|
||||||
|
|
||||||
|
var notStartedButton = new Button
|
||||||
|
{
|
||||||
|
Text = "Enable App Extension",
|
||||||
|
Command = new Command(() => ActivateExtension()),
|
||||||
|
VerticalOptions = LayoutOptions.End,
|
||||||
|
HorizontalOptions = LayoutOptions.Fill,
|
||||||
|
Style = (Style)Application.Current.Resources["btn-primary"]
|
||||||
|
};
|
||||||
|
|
||||||
|
var notStartedStackLayout = new StackLayout
|
||||||
|
{
|
||||||
|
Orientation = StackOrientation.Vertical,
|
||||||
|
Spacing = 20,
|
||||||
|
Padding = new Thickness(30, 40),
|
||||||
|
Children = { notStartedLabel, notStartedSublabel, notStartedImage, notStartedButton }
|
||||||
|
};
|
||||||
|
|
||||||
|
notStartedStackLayout.SetBinding<AppExtensionPageModel>(IsVisibleProperty, m => m.NotStarted);
|
||||||
|
|
||||||
|
// Not Activated
|
||||||
|
|
||||||
|
var notActivatedLabel = new Label
|
||||||
|
{
|
||||||
|
Text = "Almost done!",
|
||||||
|
VerticalOptions = LayoutOptions.Start,
|
||||||
|
HorizontalOptions = LayoutOptions.Center,
|
||||||
|
HorizontalTextAlignment = TextAlignment.Center,
|
||||||
|
LineBreakMode = LineBreakMode.WordWrap,
|
||||||
|
FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label))
|
||||||
|
};
|
||||||
|
|
||||||
|
var notActivatedSublabel = new Label
|
||||||
|
{
|
||||||
|
Text = "Tap the bitwarden icon in the menu to launch the extension.",
|
||||||
|
VerticalOptions = LayoutOptions.Start,
|
||||||
|
HorizontalOptions = LayoutOptions.Center,
|
||||||
|
HorizontalTextAlignment = TextAlignment.Center,
|
||||||
|
LineBreakMode = LineBreakMode.WordWrap
|
||||||
|
};
|
||||||
|
|
||||||
|
var notActivatedImage = new Image
|
||||||
|
{
|
||||||
|
Source = "",
|
||||||
|
VerticalOptions = LayoutOptions.CenterAndExpand,
|
||||||
|
HorizontalOptions = LayoutOptions.Center
|
||||||
|
};
|
||||||
|
|
||||||
|
var notActivatedButton = new Button
|
||||||
|
{
|
||||||
|
Text = "Enable App Extension",
|
||||||
|
Command = new Command(() => ActivateExtension()),
|
||||||
|
VerticalOptions = LayoutOptions.End,
|
||||||
|
HorizontalOptions = LayoutOptions.Fill,
|
||||||
|
Style = (Style)Application.Current.Resources["btn-primary"]
|
||||||
|
};
|
||||||
|
|
||||||
|
var notActivatedStackLayout = new StackLayout
|
||||||
|
{
|
||||||
|
Orientation = StackOrientation.Vertical,
|
||||||
|
Spacing = 20,
|
||||||
|
Padding = new Thickness(30, 40),
|
||||||
|
Children = { notActivatedLabel, notActivatedSublabel, notActivatedImage, notActivatedButton }
|
||||||
|
};
|
||||||
|
|
||||||
|
notActivatedStackLayout.SetBinding<AppExtensionPageModel>(IsVisibleProperty, m => m.StartedAndNotActivated);
|
||||||
|
|
||||||
|
// Activated
|
||||||
|
|
||||||
|
var activatedLabel = new Label
|
||||||
|
{
|
||||||
|
Text = "You're ready to log in!",
|
||||||
|
VerticalOptions = LayoutOptions.Start,
|
||||||
|
HorizontalOptions = LayoutOptions.Center,
|
||||||
|
HorizontalTextAlignment = TextAlignment.Center,
|
||||||
|
LineBreakMode = LineBreakMode.WordWrap,
|
||||||
|
FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label))
|
||||||
|
};
|
||||||
|
|
||||||
|
var activatedSublabel = new Label
|
||||||
|
{
|
||||||
|
Text = "In Safari, find bitwarden using the share icon (hint: scroll to the right on the second row of the menu).",
|
||||||
|
VerticalOptions = LayoutOptions.Start,
|
||||||
|
HorizontalOptions = LayoutOptions.Center,
|
||||||
|
HorizontalTextAlignment = TextAlignment.Center,
|
||||||
|
LineBreakMode = LineBreakMode.WordWrap
|
||||||
|
};
|
||||||
|
|
||||||
|
var activatedImage = new Image
|
||||||
|
{
|
||||||
|
Source = "",
|
||||||
|
VerticalOptions = LayoutOptions.CenterAndExpand,
|
||||||
|
HorizontalOptions = LayoutOptions.Center
|
||||||
|
};
|
||||||
|
|
||||||
|
var activatedButton = new Button
|
||||||
|
{
|
||||||
|
Text = "See Supported Apps",
|
||||||
|
Command = new Command(() => Device.OpenUri(new Uri("https://bitwarden.com"))),
|
||||||
|
VerticalOptions = LayoutOptions.End,
|
||||||
|
HorizontalOptions = LayoutOptions.Fill,
|
||||||
|
Style = (Style)Application.Current.Resources["btn-primary"]
|
||||||
|
};
|
||||||
|
|
||||||
|
var activatedStackLayout = new StackLayout
|
||||||
|
{
|
||||||
|
Orientation = StackOrientation.Vertical,
|
||||||
|
Spacing = 20,
|
||||||
|
Padding = new Thickness(30, 40),
|
||||||
|
Children = { activatedLabel, activatedSublabel, activatedImage, activatedButton }
|
||||||
|
};
|
||||||
|
|
||||||
|
activatedStackLayout.SetBinding<AppExtensionPageModel>(IsVisibleProperty, m => m.StartedAndActivated);
|
||||||
|
|
||||||
|
var stackLayout = new StackLayout
|
||||||
|
{
|
||||||
|
Children = { notStartedStackLayout, notActivatedStackLayout, activatedStackLayout }
|
||||||
|
};
|
||||||
|
|
||||||
|
if(Device.OS == TargetPlatform.iOS)
|
||||||
|
{
|
||||||
|
ToolbarItems.Add(new DismissModalToolBarItem(this, "Close"));
|
||||||
|
}
|
||||||
|
|
||||||
|
Title = "App Extension";
|
||||||
|
Content = stackLayout;
|
||||||
|
BindingContext = Model;
|
||||||
|
|
||||||
|
MessagingCenter.Subscribe<Application, bool>(Application.Current, "EnabledAppExtension", (sender, enabled) =>
|
||||||
|
{
|
||||||
|
Model.Started = true;
|
||||||
|
Model.Activated = enabled;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ActivateExtension()
|
||||||
|
{
|
||||||
|
MessagingCenter.Send(Application.Current, "ShowAppExtension");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,7 +4,6 @@ using Acr.UserDialogs;
|
||||||
using Bit.App.Abstractions;
|
using Bit.App.Abstractions;
|
||||||
using Bit.App.Controls;
|
using Bit.App.Controls;
|
||||||
using Bit.App.Resources;
|
using Bit.App.Resources;
|
||||||
using Plugin.Connectivity.Abstractions;
|
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
using XLabs.Ioc;
|
using XLabs.Ioc;
|
||||||
|
|
||||||
|
@ -26,6 +25,7 @@ namespace Bit.App.Pages
|
||||||
var generatorCell = new ToolsViewCell("Password Generator", "Automatically generate strong, unique passwords for your logins.", "refresh");
|
var generatorCell = new ToolsViewCell("Password Generator", "Automatically generate strong, unique passwords for your logins.", "refresh");
|
||||||
generatorCell.Tapped += GeneratorCell_Tapped;
|
generatorCell.Tapped += GeneratorCell_Tapped;
|
||||||
var extensionCell = new ToolsViewCell("bitwarden App Extension", "Use bitwarden in Safari and other apps to auto-fill your logins.", "upload");
|
var extensionCell = new ToolsViewCell("bitwarden App Extension", "Use bitwarden in Safari and other apps to auto-fill your logins.", "upload");
|
||||||
|
extensionCell.Tapped += ExtensionCell_Tapped;
|
||||||
var webCell = new ToolsViewCell("bitwarden Web Vault", "Manage your logins from any web browser with the bitwarden web vault.", "globe");
|
var webCell = new ToolsViewCell("bitwarden Web Vault", "Manage your logins from any web browser with the bitwarden web vault.", "globe");
|
||||||
webCell.Tapped += WebCell_Tapped;
|
webCell.Tapped += WebCell_Tapped;
|
||||||
var importCell = new ToolsViewCell("Import Logins", "Quickly bulk import your logins from other password management apps.", "cloudup");
|
var importCell = new ToolsViewCell("Import Logins", "Quickly bulk import your logins from other password management apps.", "cloudup");
|
||||||
|
@ -58,6 +58,11 @@ namespace Bit.App.Pages
|
||||||
Content = table;
|
Content = table;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ExtensionCell_Tapped(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
Navigation.PushModalAsync(new ExtendedNavigationPage(new ToolsExtensionPage()));
|
||||||
|
}
|
||||||
|
|
||||||
private void GeneratorCell_Tapped(object sender, EventArgs e)
|
private void GeneratorCell_Tapped(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
Navigation.PushModalAsync(new ExtendedNavigationPage(new ToolsPasswordGeneratorPage()));
|
Navigation.PushModalAsync(new ExtendedNavigationPage(new ToolsPasswordGeneratorPage()));
|
||||||
|
|
|
@ -87,7 +87,7 @@ namespace Bit.App.Pages
|
||||||
{
|
{
|
||||||
table.RowHeight = -1;
|
table.RowHeight = -1;
|
||||||
table.EstimatedRowHeight = 44;
|
table.EstimatedRowHeight = 44;
|
||||||
ToolbarItems.Add(new DismissModalToolBarItem(this, "Cancel"));
|
ToolbarItems.Add(new DismissModalToolBarItem(this, "Close"));
|
||||||
}
|
}
|
||||||
|
|
||||||
var stackLayout = new StackLayout
|
var stackLayout = new StackLayout
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
|| ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "org.appextension.change-password-action"
|
|| ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "org.appextension.change-password-action"
|
||||||
|| ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "org.appextension.fill-webview-action"
|
|| ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "org.appextension.fill-webview-action"
|
||||||
|| ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "org.appextension.fill-browser-action"
|
|| ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "org.appextension.fill-browser-action"
|
||||||
|
|| ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "com.8bit.bitwarden.extension-setup"
|
||||||
).@count == $extensionItem.attachments.@count
|
).@count == $extensionItem.attachments.@count
|
||||||
).@count == 1</string>
|
).@count == 1</string>
|
||||||
<key>NSExtensionPointName</key>
|
<key>NSExtensionPointName</key>
|
||||||
|
|
|
@ -54,6 +54,22 @@ namespace Bit.iOS
|
||||||
UINavigationBar.Appearance.ShadowImage = new UIImage();
|
UINavigationBar.Appearance.ShadowImage = new UIImage();
|
||||||
UINavigationBar.Appearance.SetBackgroundImage(new UIImage(), UIBarMetrics.Default);
|
UINavigationBar.Appearance.SetBackgroundImage(new UIImage(), UIBarMetrics.Default);
|
||||||
|
|
||||||
|
MessagingCenter.Subscribe<Xamarin.Forms.Application>(Xamarin.Forms.Application.Current, "ShowAppExtension", (sender) =>
|
||||||
|
{
|
||||||
|
var itemProvider = new NSItemProvider(new NSDictionary(), "com.8bit.bitwarden.extension-setup");
|
||||||
|
var extensionItem = new NSExtensionItem();
|
||||||
|
extensionItem.Attachments = new NSItemProvider[] { itemProvider };
|
||||||
|
var activityViewController = new UIActivityViewController(new NSExtensionItem[] { extensionItem }, null);
|
||||||
|
activityViewController.CompletionHandler = (activityType, completed) =>
|
||||||
|
{
|
||||||
|
MessagingCenter.Send(Xamarin.Forms.Application.Current, "EnabledAppExtension",
|
||||||
|
completed && activityType == "com.8bit.bitwarden.find-login-action-extension");
|
||||||
|
};
|
||||||
|
|
||||||
|
UIApplication.SharedApplication.KeyWindow.RootViewController.ModalViewController
|
||||||
|
.PresentViewController(activityViewController, true, null);
|
||||||
|
});
|
||||||
|
|
||||||
return base.FinishedLaunching(app, options);
|
return base.FinishedLaunching(app, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue