Enhanced autofill settings (#1150)
* enhanced autofill settings * cleanup
|
@ -255,13 +255,13 @@ namespace Bit.Droid.Accessibility
|
||||||
|
|
||||||
if (!AccessibilityHelpers.OverlayPermitted())
|
if (!AccessibilityHelpers.OverlayPermitted())
|
||||||
{
|
{
|
||||||
if (!AccessibilityHelpers.IsAutofillTileAdded)
|
if (Build.VERSION.SdkInt <= BuildVersionCodes.M)
|
||||||
{
|
{
|
||||||
// The user has the option of only using the autofill tile and leaving the overlay permission
|
// The user has the option of only using the autofill tile and leaving the overlay permission
|
||||||
// disabled, so only show this toast if they're using accessibility without overlay permission and
|
// disabled, so only show this toast if they're using accessibility without overlay permission on
|
||||||
// have _not_ added the autofill tile
|
// a version of Android without quick-action tile support
|
||||||
System.Diagnostics.Debug.WriteLine(">>> Overlay Permission not granted");
|
System.Diagnostics.Debug.WriteLine(">>> Overlay Permission not granted");
|
||||||
Toast.MakeText(this, AppResources.AccessibilityOverlayPermissionAlert, ToastLength.Long).Show();
|
Toast.MakeText(this, AppResources.AccessibilityDrawOverPermissionAlert, ToastLength.Long).Show();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -161,28 +161,10 @@
|
||||||
<None Include="upload-keystore.jks.enc" />
|
<None Include="upload-keystore.jks.enc" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<AndroidResource Include="Resources\drawable-hdpi\accessibility_overlay.png" />
|
|
||||||
<AndroidResource Include="Resources\drawable-hdpi\accessibility_permission.png" />
|
|
||||||
<AndroidResource Include="Resources\drawable-hdpi\accessibility_step1.png" />
|
|
||||||
<AndroidResource Include="Resources\drawable-hdpi\accessibility_step2.png" />
|
|
||||||
<AndroidResource Include="Resources\drawable-hdpi\autofill_enable.png" />
|
|
||||||
<AndroidResource Include="Resources\drawable-hdpi\autofill_use.png" />
|
|
||||||
<AndroidResource Include="Resources\drawable-hdpi\logo_legacy.png" />
|
<AndroidResource Include="Resources\drawable-hdpi\logo_legacy.png" />
|
||||||
<AndroidResource Include="Resources\drawable-hdpi\logo_white_legacy.png" />
|
<AndroidResource Include="Resources\drawable-hdpi\logo_white_legacy.png" />
|
||||||
<AndroidResource Include="Resources\drawable-xhdpi\accessibility_overlay.png" />
|
|
||||||
<AndroidResource Include="Resources\drawable-xhdpi\accessibility_permission.png" />
|
|
||||||
<AndroidResource Include="Resources\drawable-xhdpi\accessibility_step1.png" />
|
|
||||||
<AndroidResource Include="Resources\drawable-xhdpi\accessibility_step2.png" />
|
|
||||||
<AndroidResource Include="Resources\drawable-xhdpi\autofill_enable.png" />
|
|
||||||
<AndroidResource Include="Resources\drawable-xhdpi\autofill_use.png" />
|
|
||||||
<AndroidResource Include="Resources\drawable-xhdpi\logo_legacy.png" />
|
<AndroidResource Include="Resources\drawable-xhdpi\logo_legacy.png" />
|
||||||
<AndroidResource Include="Resources\drawable-xhdpi\logo_white_legacy.png" />
|
<AndroidResource Include="Resources\drawable-xhdpi\logo_white_legacy.png" />
|
||||||
<AndroidResource Include="Resources\drawable-xxhdpi\accessibility_overlay.png" />
|
|
||||||
<AndroidResource Include="Resources\drawable-xxhdpi\accessibility_permission.png" />
|
|
||||||
<AndroidResource Include="Resources\drawable-xxhdpi\accessibility_step1.png" />
|
|
||||||
<AndroidResource Include="Resources\drawable-xxhdpi\accessibility_step2.png" />
|
|
||||||
<AndroidResource Include="Resources\drawable-xxhdpi\autofill_enable.png" />
|
|
||||||
<AndroidResource Include="Resources\drawable-xxhdpi\autofill_use.png" />
|
|
||||||
<AndroidResource Include="Resources\drawable-xxhdpi\logo_legacy.png" />
|
<AndroidResource Include="Resources\drawable-xxhdpi\logo_legacy.png" />
|
||||||
<AndroidResource Include="Resources\drawable-xxhdpi\logo_white_legacy.png" />
|
<AndroidResource Include="Resources\drawable-xxhdpi\logo_white_legacy.png" />
|
||||||
<AndroidResource Include="Resources\drawable\card.xml" />
|
<AndroidResource Include="Resources\drawable\card.xml" />
|
||||||
|
|
|
@ -143,13 +143,13 @@ namespace Bit.Droid.Autofill
|
||||||
}
|
}
|
||||||
|
|
||||||
public static FillResponse BuildFillResponse(Parser parser, List<FilledItem> items, bool locked,
|
public static FillResponse BuildFillResponse(Parser parser, List<FilledItem> items, bool locked,
|
||||||
FillRequest fillRequest = null)
|
bool inlineAutofillEnabled, FillRequest fillRequest = null)
|
||||||
{
|
{
|
||||||
// Acquire inline presentation specs on Android 11+
|
// Acquire inline presentation specs on Android 11+
|
||||||
IList<InlinePresentationSpec> inlinePresentationSpecs = null;
|
IList<InlinePresentationSpec> inlinePresentationSpecs = null;
|
||||||
var inlinePresentationSpecsCount = 0;
|
var inlinePresentationSpecsCount = 0;
|
||||||
var inlineMaxSuggestedCount = 0;
|
var inlineMaxSuggestedCount = 0;
|
||||||
if (fillRequest != null && (int)Build.VERSION.SdkInt >= 30)
|
if (inlineAutofillEnabled && fillRequest != null && (int)Build.VERSION.SdkInt >= 30)
|
||||||
{
|
{
|
||||||
var inlineSuggestionsRequest = fillRequest.InlineSuggestionsRequest;
|
var inlineSuggestionsRequest = fillRequest.InlineSuggestionsRequest;
|
||||||
inlineMaxSuggestedCount = inlineSuggestionsRequest?.MaxSuggestionCount ?? 0;
|
inlineMaxSuggestedCount = inlineSuggestionsRequest?.MaxSuggestionCount ?? 0;
|
||||||
|
|
|
@ -47,6 +47,8 @@ namespace Bit.Droid.Autofill
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var inlineAutofillEnabled = await _storageService.GetAsync<bool?>(Constants.InlineAutofillEnabledKey) ?? true;
|
||||||
|
|
||||||
if (_vaultTimeoutService == null)
|
if (_vaultTimeoutService == null)
|
||||||
{
|
{
|
||||||
_vaultTimeoutService = ServiceContainer.Resolve<IVaultTimeoutService>("vaultTimeoutService");
|
_vaultTimeoutService = ServiceContainer.Resolve<IVaultTimeoutService>("vaultTimeoutService");
|
||||||
|
@ -64,7 +66,7 @@ namespace Bit.Droid.Autofill
|
||||||
}
|
}
|
||||||
|
|
||||||
// build response
|
// build response
|
||||||
var response = AutofillHelpers.BuildFillResponse(parser, items, locked, request);
|
var response = AutofillHelpers.BuildFillResponse(parser, items, locked, inlineAutofillEnabled, request);
|
||||||
callback.OnSuccess(response);
|
callback.OnSuccess(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Before Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 9.9 KiB |
Before Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 57 KiB |
Before Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 46 KiB |
|
@ -378,6 +378,34 @@ namespace Bit.Droid.Services
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void DisableAutofillService()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var activity = (MainActivity)CrossCurrentActivity.Current.Activity;
|
||||||
|
var type = Java.Lang.Class.FromType(typeof(AutofillManager));
|
||||||
|
var manager = activity.GetSystemService(type) as AutofillManager;
|
||||||
|
manager.DisableAutofillServices();
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AutofillServicesEnabled()
|
||||||
|
{
|
||||||
|
if (Build.VERSION.SdkInt <= BuildVersionCodes.M)
|
||||||
|
{
|
||||||
|
// Android 5-6: Both accessibility & overlay are required or nothing happens
|
||||||
|
return AutofillAccessibilityServiceRunning() && AutofillAccessibilityOverlayPermitted();
|
||||||
|
}
|
||||||
|
if (Build.VERSION.SdkInt == BuildVersionCodes.N)
|
||||||
|
{
|
||||||
|
// Android 7: Only accessibility is required (overlay is optional when using quick-action tile)
|
||||||
|
return AutofillAccessibilityServiceRunning();
|
||||||
|
}
|
||||||
|
// Android 8+: Either autofill or accessibility is required
|
||||||
|
return AutofillServiceEnabled() || AutofillAccessibilityServiceRunning();
|
||||||
|
}
|
||||||
|
|
||||||
public string GetBuildNumber()
|
public string GetBuildNumber()
|
||||||
{
|
{
|
||||||
return Application.Context.ApplicationContext.PackageManager.GetPackageInfo(
|
return Application.Context.ApplicationContext.PackageManager.GetPackageInfo(
|
||||||
|
|
|
@ -36,6 +36,8 @@ namespace Bit.App.Abstractions
|
||||||
bool AutofillAccessibilityServiceRunning();
|
bool AutofillAccessibilityServiceRunning();
|
||||||
bool AutofillAccessibilityOverlayPermitted();
|
bool AutofillAccessibilityOverlayPermitted();
|
||||||
bool AutofillServiceEnabled();
|
bool AutofillServiceEnabled();
|
||||||
|
void DisableAutofillService();
|
||||||
|
bool AutofillServicesEnabled();
|
||||||
string GetBuildNumber();
|
string GetBuildNumber();
|
||||||
void OpenAccessibilitySettings();
|
void OpenAccessibilitySettings();
|
||||||
void OpenAccessibilityOverlayPermissionSettings();
|
void OpenAccessibilityOverlayPermissionSettings();
|
||||||
|
|
|
@ -57,8 +57,8 @@
|
||||||
<Compile Update="Pages\Settings\ExtensionPage.xaml.cs">
|
<Compile Update="Pages\Settings\ExtensionPage.xaml.cs">
|
||||||
<DependentUpon>ExtensionPage.xaml</DependentUpon>
|
<DependentUpon>ExtensionPage.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Update="Pages\Settings\AutofillServicePage.xaml.cs">
|
<Compile Update="Pages\Settings\AutofillServicesPage.xaml.cs">
|
||||||
<DependentUpon>AutofillServicePage.xaml</DependentUpon>
|
<DependentUpon>AutofillServicesPage.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Update="Pages\Settings\FolderAddEditPage.xaml.cs">
|
<Compile Update="Pages\Settings\FolderAddEditPage.xaml.cs">
|
||||||
<DependentUpon>FolderAddEditPage.xaml</DependentUpon>
|
<DependentUpon>FolderAddEditPage.xaml</DependentUpon>
|
||||||
|
@ -72,9 +72,6 @@
|
||||||
<Compile Update="Pages\Settings\OptionsPage.xaml.cs">
|
<Compile Update="Pages\Settings\OptionsPage.xaml.cs">
|
||||||
<DependentUpon>OptionsPage.xaml</DependentUpon>
|
<DependentUpon>OptionsPage.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Update="Pages\Settings\AccessibilityServicePage.xaml.cs">
|
|
||||||
<DependentUpon>AccessibilityServicePage.xaml</DependentUpon>
|
|
||||||
</Compile>
|
|
||||||
<Compile Update="Pages\Settings\SyncPage.xaml.cs">
|
<Compile Update="Pages\Settings\SyncPage.xaml.cs">
|
||||||
<DependentUpon>SyncPage.xaml</DependentUpon>
|
<DependentUpon>SyncPage.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
|
|
@ -1,109 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8" ?>
|
|
||||||
<pages:BaseContentPage
|
|
||||||
xmlns="http://xamarin.com/schemas/2014/forms"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
|
||||||
x:Class="Bit.App.Pages.AccessibilityServicePage"
|
|
||||||
xmlns:pages="clr-namespace:Bit.App.Pages"
|
|
||||||
xmlns:u="clr-namespace:Bit.App.Utilities"
|
|
||||||
x:DataType="pages:AccessibilityServicePageViewModel"
|
|
||||||
Title="{Binding PageTitle}">
|
|
||||||
<ContentPage.BindingContext>
|
|
||||||
<pages:AccessibilityServicePageViewModel />
|
|
||||||
</ContentPage.BindingContext>
|
|
||||||
|
|
||||||
<ContentPage.Resources>
|
|
||||||
<ResourceDictionary>
|
|
||||||
<u:InverseBoolConverter x:Key="inverseBool" />
|
|
||||||
</ResourceDictionary>
|
|
||||||
</ContentPage.Resources>
|
|
||||||
|
|
||||||
<ScrollView>
|
|
||||||
<StackLayout Spacing="20"
|
|
||||||
Padding="10, 30"
|
|
||||||
VerticalOptions="FillAndExpand">
|
|
||||||
<Label Text="{u:I18n AutofillAccessibilityDescription}"
|
|
||||||
VerticalOptions="Start"
|
|
||||||
HorizontalTextAlignment="Center"
|
|
||||||
LineBreakMode="WordWrap" />
|
|
||||||
<StackLayout IsVisible="{Binding Enabled, Converter={StaticResource inverseBool}}"
|
|
||||||
VerticalOptions="CenterAndExpand"
|
|
||||||
HorizontalOptions="Center"
|
|
||||||
Spacing="20">
|
|
||||||
<StackLayout Orientation="Horizontal" HorizontalOptions="Center">
|
|
||||||
<Label Text="{u:I18n Status}" />
|
|
||||||
<Label Text="{u:I18n Disabled}"
|
|
||||||
StyleClass="text-danger, text-bold" />
|
|
||||||
</StackLayout>
|
|
||||||
<Image Source="accessibility_step1.png"
|
|
||||||
HorizontalOptions="Center"
|
|
||||||
Margin="0, 20, 0, 0"
|
|
||||||
WidthRequest="300"
|
|
||||||
HeightRequest="98" />
|
|
||||||
<Label Text="{u:I18n BitwardenAutofillServiceStep1}"
|
|
||||||
HorizontalTextAlignment="Center"
|
|
||||||
LineBreakMode="WordWrap"
|
|
||||||
StyleClass="text-sm" />
|
|
||||||
<Image Source="accessibility_step2.png"
|
|
||||||
HorizontalOptions="Center"
|
|
||||||
Margin="0, 10, 0, 0"
|
|
||||||
WidthRequest="300"
|
|
||||||
HeightRequest="67" />
|
|
||||||
<Label Text="{u:I18n BitwardenAutofillServiceStep2}"
|
|
||||||
HorizontalTextAlignment="Center"
|
|
||||||
LineBreakMode="WordWrap"
|
|
||||||
StyleClass="text-sm" />
|
|
||||||
</StackLayout>
|
|
||||||
<StackLayout IsVisible="{Binding EnabledWithoutPermission}"
|
|
||||||
VerticalOptions="CenterAndExpand"
|
|
||||||
HorizontalOptions="Center"
|
|
||||||
Spacing="20">
|
|
||||||
<StackLayout Orientation="Horizontal" HorizontalOptions="Center">
|
|
||||||
<Label Text="{u:I18n Status}" />
|
|
||||||
<Label Text="{u:I18n Disabled}"
|
|
||||||
StyleClass="text-danger, text-bold" />
|
|
||||||
</StackLayout>
|
|
||||||
<Image Source="accessibility_permission.png"
|
|
||||||
HorizontalOptions="Center"
|
|
||||||
Margin="0, 20, 0, 0"
|
|
||||||
WidthRequest="300"
|
|
||||||
HeightRequest="142" />
|
|
||||||
<Label Text="{u:I18n BitwardenAutofillServiceStep3}"
|
|
||||||
HorizontalTextAlignment="Center"
|
|
||||||
LineBreakMode="WordWrap"
|
|
||||||
StyleClass="text-sm" />
|
|
||||||
</StackLayout>
|
|
||||||
<StackLayout IsVisible="{Binding EnabledAndPermitted}"
|
|
||||||
VerticalOptions="CenterAndExpand"
|
|
||||||
HorizontalOptions="Center"
|
|
||||||
Spacing="20">
|
|
||||||
<StackLayout Orientation="Horizontal" HorizontalOptions="Center">
|
|
||||||
<Label Text="{u:I18n Status}" />
|
|
||||||
<Label Text="{u:I18n Enabled}"
|
|
||||||
StyleClass="text-success, text-bold" />
|
|
||||||
</StackLayout>
|
|
||||||
<Image Source="accessibility_overlay.png"
|
|
||||||
HorizontalOptions="Center"
|
|
||||||
Margin="0, 20, 0, 0"
|
|
||||||
WidthRequest="300"
|
|
||||||
HeightRequest="172" />
|
|
||||||
<Label Text="{u:I18n BitwardenAutofillServiceOverlay}"
|
|
||||||
HorizontalTextAlignment="Center"
|
|
||||||
LineBreakMode="WordWrap"
|
|
||||||
StyleClass="text-sm" />
|
|
||||||
</StackLayout>
|
|
||||||
<StackLayout Spacing="10">
|
|
||||||
<Button Text="{u:I18n BitwardenAutofillServiceOpenAccessibilitySettings}"
|
|
||||||
Clicked="Settings_Clicked"
|
|
||||||
HorizontalOptions="Fill"
|
|
||||||
VerticalOptions="End"
|
|
||||||
IsVisible="{Binding Enabled, Converter={StaticResource inverseBool}}"></Button>
|
|
||||||
<Button Text="{u:I18n BitwardenAutofillServiceOpenOverlayPermissionSettings}"
|
|
||||||
Clicked="OverlayPermissionSettings_Clicked"
|
|
||||||
HorizontalOptions="Fill"
|
|
||||||
VerticalOptions="End"
|
|
||||||
IsVisible="{Binding Permitted, Converter={StaticResource inverseBool}}"></Button>
|
|
||||||
</StackLayout>
|
|
||||||
</StackLayout>
|
|
||||||
</ScrollView>
|
|
||||||
|
|
||||||
</pages:BaseContentPage>
|
|
|
@ -1,66 +0,0 @@
|
||||||
using Bit.App.Abstractions;
|
|
||||||
using Bit.App.Resources;
|
|
||||||
using Bit.Core.Utilities;
|
|
||||||
|
|
||||||
namespace Bit.App.Pages
|
|
||||||
{
|
|
||||||
public class AccessibilityServicePageViewModel : BaseViewModel
|
|
||||||
{
|
|
||||||
private readonly IDeviceActionService _deviceActionService;
|
|
||||||
|
|
||||||
private bool _enabled;
|
|
||||||
private bool _permitted;
|
|
||||||
|
|
||||||
public AccessibilityServicePageViewModel()
|
|
||||||
{
|
|
||||||
_deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
|
|
||||||
PageTitle = AppResources.AutofillAccessibilityService;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Enabled
|
|
||||||
{
|
|
||||||
get => _enabled;
|
|
||||||
set => SetProperty(ref _enabled, value,
|
|
||||||
additionalPropertyNames: new string[]
|
|
||||||
{
|
|
||||||
nameof(EnabledWithoutPermission),
|
|
||||||
nameof(EnabledAndPermitted)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Permitted
|
|
||||||
{
|
|
||||||
get => _permitted;
|
|
||||||
set => SetProperty(ref _permitted, value,
|
|
||||||
additionalPropertyNames: new string[]
|
|
||||||
{
|
|
||||||
nameof(EnabledWithoutPermission),
|
|
||||||
nameof(EnabledAndPermitted)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool EnabledWithoutPermission => Enabled && !Permitted;
|
|
||||||
|
|
||||||
public bool EnabledAndPermitted => Enabled && Permitted;
|
|
||||||
|
|
||||||
public void OpenSettings()
|
|
||||||
{
|
|
||||||
_deviceActionService.OpenAccessibilitySettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OpenOverlayPermissionSettings()
|
|
||||||
{
|
|
||||||
_deviceActionService.OpenAccessibilityOverlayPermissionSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateEnabled()
|
|
||||||
{
|
|
||||||
Enabled = _deviceActionService.AutofillAccessibilityServiceRunning();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdatePermitted()
|
|
||||||
{
|
|
||||||
Permitted = _deviceActionService.AutofillAccessibilityOverlayPermitted();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,66 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8" ?>
|
|
||||||
<pages:BaseContentPage
|
|
||||||
xmlns="http://xamarin.com/schemas/2014/forms"
|
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
|
||||||
x:Class="Bit.App.Pages.AutofillServicePage"
|
|
||||||
xmlns:pages="clr-namespace:Bit.App.Pages"
|
|
||||||
xmlns:u="clr-namespace:Bit.App.Utilities"
|
|
||||||
x:DataType="pages:AutofillServicePageViewModel"
|
|
||||||
Title="{Binding PageTitle}">
|
|
||||||
<ContentPage.BindingContext>
|
|
||||||
<pages:AutofillServicePageViewModel />
|
|
||||||
</ContentPage.BindingContext>
|
|
||||||
|
|
||||||
<ContentPage.Resources>
|
|
||||||
<ResourceDictionary>
|
|
||||||
<u:InverseBoolConverter x:Key="inverseBool" />
|
|
||||||
</ResourceDictionary>
|
|
||||||
</ContentPage.Resources>
|
|
||||||
|
|
||||||
<ScrollView>
|
|
||||||
<StackLayout Spacing="20"
|
|
||||||
Padding="10, 30"
|
|
||||||
VerticalOptions="FillAndExpand">
|
|
||||||
<Label Text="{u:I18n AutofillServiceDescription}"
|
|
||||||
VerticalOptions="Start"
|
|
||||||
HorizontalTextAlignment="Center"
|
|
||||||
LineBreakMode="WordWrap" />
|
|
||||||
<StackLayout IsVisible="{Binding Enabled, Converter={StaticResource inverseBool}}"
|
|
||||||
VerticalOptions="CenterAndExpand"
|
|
||||||
HorizontalOptions="Center"
|
|
||||||
Spacing="20">
|
|
||||||
<StackLayout Orientation="Horizontal" HorizontalOptions="CenterAndExpand">
|
|
||||||
<Label Text="{u:I18n Status}" />
|
|
||||||
<Label Text="{u:I18n Disabled}"
|
|
||||||
StyleClass="text-danger, text-bold" />
|
|
||||||
</StackLayout>
|
|
||||||
<Image Source="autofill_enable.png"
|
|
||||||
HorizontalOptions="Center"
|
|
||||||
Margin="0, 20, 0, 0"
|
|
||||||
WidthRequest="300"
|
|
||||||
HeightRequest="118" />
|
|
||||||
</StackLayout>
|
|
||||||
<StackLayout IsVisible="{Binding Enabled}"
|
|
||||||
VerticalOptions="CenterAndExpand"
|
|
||||||
HorizontalOptions="Center"
|
|
||||||
Spacing="20">
|
|
||||||
<StackLayout Orientation="Horizontal" HorizontalOptions="Center">
|
|
||||||
<Label Text="{u:I18n Status}" />
|
|
||||||
<Label Text="{u:I18n Enabled}"
|
|
||||||
StyleClass="text-success, text-bold" />
|
|
||||||
</StackLayout>
|
|
||||||
<Image Source="autofill_use.png"
|
|
||||||
HorizontalOptions="Center"
|
|
||||||
Margin="0, 20, 0, 0"
|
|
||||||
WidthRequest="300"
|
|
||||||
HeightRequest="128" />
|
|
||||||
</StackLayout>
|
|
||||||
<Button Text="{u:I18n BitwardenAutofillServiceOpenAutofillSettings}"
|
|
||||||
Clicked="Settings_Clicked"
|
|
||||||
HorizontalOptions="Fill"
|
|
||||||
VerticalOptions="End"
|
|
||||||
IsVisible="{Binding Enabled, Converter={StaticResource inverseBool}}"></Button>
|
|
||||||
</StackLayout>
|
|
||||||
</ScrollView>
|
|
||||||
|
|
||||||
</pages:BaseContentPage>
|
|
|
@ -1,52 +0,0 @@
|
||||||
using System;
|
|
||||||
using Xamarin.Forms;
|
|
||||||
|
|
||||||
namespace Bit.App.Pages
|
|
||||||
{
|
|
||||||
public partial class AutofillServicePage : BaseContentPage
|
|
||||||
{
|
|
||||||
private readonly AutofillServicePageViewModel _vm;
|
|
||||||
private readonly SettingsPage _settingsPage;
|
|
||||||
private DateTime? _timerStarted = null;
|
|
||||||
private TimeSpan _timerMaxLength = TimeSpan.FromMinutes(5);
|
|
||||||
|
|
||||||
public AutofillServicePage(SettingsPage settingsPage)
|
|
||||||
{
|
|
||||||
InitializeComponent();
|
|
||||||
_vm = BindingContext as AutofillServicePageViewModel;
|
|
||||||
_vm.Page = this;
|
|
||||||
_settingsPage = settingsPage;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnAppearing()
|
|
||||||
{
|
|
||||||
_vm.UpdateEnabled();
|
|
||||||
_timerStarted = DateTime.UtcNow;
|
|
||||||
Device.StartTimer(new TimeSpan(0, 0, 2), () =>
|
|
||||||
{
|
|
||||||
if (_timerStarted == null || (DateTime.UtcNow - _timerStarted) > _timerMaxLength)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
_vm.UpdateEnabled();
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
base.OnAppearing();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnDisappearing()
|
|
||||||
{
|
|
||||||
_timerStarted = null;
|
|
||||||
_settingsPage.BuildList();
|
|
||||||
base.OnDisappearing();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Settings_Clicked(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
if (DoOnce())
|
|
||||||
{
|
|
||||||
_vm.OpenSettings();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,35 +0,0 @@
|
||||||
using Bit.App.Abstractions;
|
|
||||||
using Bit.App.Resources;
|
|
||||||
using Bit.Core.Utilities;
|
|
||||||
|
|
||||||
namespace Bit.App.Pages
|
|
||||||
{
|
|
||||||
public class AutofillServicePageViewModel : BaseViewModel
|
|
||||||
{
|
|
||||||
private readonly IDeviceActionService _deviceActionService;
|
|
||||||
|
|
||||||
private bool _enabled;
|
|
||||||
|
|
||||||
public AutofillServicePageViewModel()
|
|
||||||
{
|
|
||||||
_deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
|
|
||||||
PageTitle = AppResources.AutofillService;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Enabled
|
|
||||||
{
|
|
||||||
get => _enabled;
|
|
||||||
set => SetProperty(ref _enabled, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OpenSettings()
|
|
||||||
{
|
|
||||||
_deviceActionService.OpenAutofillSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateEnabled()
|
|
||||||
{
|
|
||||||
Enabled = _deviceActionService.AutofillServiceEnabled();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
133
src/App/Pages/Settings/AutofillServicesPage.xaml
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<pages:BaseContentPage
|
||||||
|
xmlns="http://xamarin.com/schemas/2014/forms"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||||
|
x:Class="Bit.App.Pages.AutofillServicesPage"
|
||||||
|
xmlns:pages="clr-namespace:Bit.App.Pages"
|
||||||
|
xmlns:u="clr-namespace:Bit.App.Utilities"
|
||||||
|
x:DataType="pages:AutofillServicesPageViewModel"
|
||||||
|
Title="{Binding PageTitle}">
|
||||||
|
<ContentPage.BindingContext>
|
||||||
|
<pages:AutofillServicesPageViewModel />
|
||||||
|
</ContentPage.BindingContext>
|
||||||
|
|
||||||
|
<ScrollView>
|
||||||
|
<StackLayout Padding="0" Spacing="20">
|
||||||
|
<StackLayout
|
||||||
|
StyleClass="box"
|
||||||
|
IsVisible="{Binding AutofillServiceVisible}">
|
||||||
|
<StackLayout StyleClass="box-row, box-row-switch">
|
||||||
|
<Label
|
||||||
|
Text="{u:I18n AutofillService}"
|
||||||
|
StyleClass="box-label, box-label-regular"
|
||||||
|
HorizontalOptions="StartAndExpand" />
|
||||||
|
<RelativeLayout HorizontalOptions="End">
|
||||||
|
<Switch
|
||||||
|
x:Name="AutofillServiceSwitch"
|
||||||
|
IsToggled="{Binding AutofillServiceToggled}"
|
||||||
|
StyleClass="box-value"
|
||||||
|
HorizontalOptions="End" />
|
||||||
|
<Button
|
||||||
|
Clicked="ToggleAutofillService"
|
||||||
|
BackgroundColor="Transparent"
|
||||||
|
RelativeLayout.XConstraint="0"
|
||||||
|
RelativeLayout.YConstraint="0"
|
||||||
|
RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToView, ElementName=AutofillServiceSwitch, Property=Width}"
|
||||||
|
RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToView, ElementName=AutofillServiceSwitch, Property=Height}" />
|
||||||
|
</RelativeLayout>
|
||||||
|
</StackLayout>
|
||||||
|
<Label
|
||||||
|
Text="{u:I18n AutofillServiceDescription}"
|
||||||
|
StyleClass="box-footer-label, box-footer-label-switch" />
|
||||||
|
</StackLayout>
|
||||||
|
<StackLayout
|
||||||
|
StyleClass="box"
|
||||||
|
IsVisible="{Binding InlineAutofillVisible}">
|
||||||
|
<StackLayout StyleClass="box-row, box-row-switch">
|
||||||
|
<Label
|
||||||
|
Text="{u:I18n InlineAutofill}"
|
||||||
|
StyleClass="box-label, box-label-regular"
|
||||||
|
IsEnabled="{Binding InlineAutofillEnabled}"
|
||||||
|
HorizontalOptions="StartAndExpand" />
|
||||||
|
<RelativeLayout HorizontalOptions="End">
|
||||||
|
<Switch
|
||||||
|
x:Name="InlineAutofillSwitch"
|
||||||
|
IsEnabled="{Binding InlineAutofillEnabled}"
|
||||||
|
IsToggled="{Binding InlineAutofillToggled}"
|
||||||
|
StyleClass="box-value"
|
||||||
|
HorizontalOptions="End" />
|
||||||
|
<Button
|
||||||
|
Clicked="ToggleInlineAutofill"
|
||||||
|
IsEnabled="{Binding InlineAutofillEnabled}"
|
||||||
|
BackgroundColor="Transparent"
|
||||||
|
RelativeLayout.XConstraint="0"
|
||||||
|
RelativeLayout.YConstraint="0"
|
||||||
|
RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToView, ElementName=InlineAutofillSwitch, Property=Width}"
|
||||||
|
RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToView, ElementName=InlineAutofillSwitch, Property=Height}" />
|
||||||
|
</RelativeLayout>
|
||||||
|
</StackLayout>
|
||||||
|
<Label
|
||||||
|
Text="{u:I18n InlineAutofillDescription}"
|
||||||
|
StyleClass="box-footer-label, box-footer-label-switch"
|
||||||
|
IsEnabled="{Binding InlineAutofillEnabled}"/>
|
||||||
|
</StackLayout>
|
||||||
|
<StackLayout StyleClass="box">
|
||||||
|
<StackLayout StyleClass="box-row, box-row-switch">
|
||||||
|
<Label
|
||||||
|
Text="{u:I18n Accessibility}"
|
||||||
|
StyleClass="box-label, box-label-regular"
|
||||||
|
HorizontalOptions="StartAndExpand" />
|
||||||
|
<RelativeLayout HorizontalOptions="End">
|
||||||
|
<Switch
|
||||||
|
x:Name="AccessibilitySwitch"
|
||||||
|
IsToggled="{Binding AccessibilityToggled}"
|
||||||
|
StyleClass="box-value"
|
||||||
|
HorizontalOptions="End" />
|
||||||
|
<Button
|
||||||
|
Clicked="ToggleAccessibility"
|
||||||
|
BackgroundColor="Transparent"
|
||||||
|
RelativeLayout.XConstraint="0"
|
||||||
|
RelativeLayout.YConstraint="0"
|
||||||
|
RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToView, ElementName=AccessibilitySwitch, Property=Width}"
|
||||||
|
RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToView, ElementName=AccessibilitySwitch, Property=Height}" />
|
||||||
|
</RelativeLayout>
|
||||||
|
</StackLayout>
|
||||||
|
<Label
|
||||||
|
Text="{Binding AccessibilityDescriptionLabel}"
|
||||||
|
StyleClass="box-footer-label, box-footer-label-switch" />
|
||||||
|
</StackLayout>
|
||||||
|
<StackLayout
|
||||||
|
StyleClass="box"
|
||||||
|
IsVisible="{Binding DrawOverVisible}">
|
||||||
|
<StackLayout StyleClass="box-row, box-row-switch">
|
||||||
|
<Label
|
||||||
|
Text="{u:I18n DrawOver}"
|
||||||
|
StyleClass="box-label, box-label-regular"
|
||||||
|
IsEnabled="{Binding DrawOverEnabled}"
|
||||||
|
HorizontalOptions="StartAndExpand" />
|
||||||
|
<RelativeLayout HorizontalOptions="End">
|
||||||
|
<Switch
|
||||||
|
x:Name="DrawOverSwitch"
|
||||||
|
IsEnabled="{Binding DrawOverEnabled}"
|
||||||
|
IsToggled="{Binding DrawOverToggled}"
|
||||||
|
StyleClass="box-value"
|
||||||
|
HorizontalOptions="End" />
|
||||||
|
<Button
|
||||||
|
Clicked="ToggleDrawOver"
|
||||||
|
IsEnabled="{Binding DrawOverEnabled}"
|
||||||
|
BackgroundColor="Transparent"
|
||||||
|
RelativeLayout.XConstraint="0"
|
||||||
|
RelativeLayout.YConstraint="0"
|
||||||
|
RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToView, ElementName=DrawOverSwitch, Property=Width}"
|
||||||
|
RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToView, ElementName=DrawOverSwitch, Property=Height}" />
|
||||||
|
</RelativeLayout>
|
||||||
|
</StackLayout>
|
||||||
|
<Label
|
||||||
|
Text="{Binding DrawOverDescriptionLabel}"
|
||||||
|
StyleClass="box-footer-label, box-footer-label-switch"
|
||||||
|
IsEnabled="{Binding InlineAutofillEnabled}"/>
|
||||||
|
</StackLayout>
|
||||||
|
</StackLayout>
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
|
</pages:BaseContentPage>
|
|
@ -3,34 +3,33 @@ using Xamarin.Forms;
|
||||||
|
|
||||||
namespace Bit.App.Pages
|
namespace Bit.App.Pages
|
||||||
{
|
{
|
||||||
public partial class AccessibilityServicePage : BaseContentPage
|
public partial class AutofillServicesPage : BaseContentPage
|
||||||
{
|
{
|
||||||
private readonly AccessibilityServicePageViewModel _vm;
|
private readonly AutofillServicesPageViewModel _vm;
|
||||||
private readonly SettingsPage _settingsPage;
|
private readonly SettingsPage _settingsPage;
|
||||||
private DateTime? _timerStarted = null;
|
private DateTime? _timerStarted = null;
|
||||||
private TimeSpan _timerMaxLength = TimeSpan.FromMinutes(5);
|
private TimeSpan _timerMaxLength = TimeSpan.FromMinutes(5);
|
||||||
|
|
||||||
public AccessibilityServicePage(SettingsPage settingsPage)
|
public AutofillServicesPage(SettingsPage settingsPage)
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
_vm = BindingContext as AccessibilityServicePageViewModel;
|
_vm = BindingContext as AutofillServicesPageViewModel;
|
||||||
_vm.Page = this;
|
_vm.Page = this;
|
||||||
_settingsPage = settingsPage;
|
_settingsPage = settingsPage;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnAppearing()
|
protected async override void OnAppearing()
|
||||||
{
|
{
|
||||||
|
await _vm.InitAsync();
|
||||||
_vm.UpdateEnabled();
|
_vm.UpdateEnabled();
|
||||||
_vm.UpdatePermitted();
|
|
||||||
_timerStarted = DateTime.UtcNow;
|
_timerStarted = DateTime.UtcNow;
|
||||||
Device.StartTimer(new TimeSpan(0, 0, 3), () =>
|
Device.StartTimer(new TimeSpan(0, 0, 0, 0, 500), () =>
|
||||||
{
|
{
|
||||||
if (_timerStarted == null || (DateTime.UtcNow - _timerStarted) > _timerMaxLength)
|
if (_timerStarted == null || (DateTime.UtcNow - _timerStarted) > _timerMaxLength)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
_vm.UpdateEnabled();
|
_vm.UpdateEnabled();
|
||||||
_vm.UpdatePermitted();
|
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
base.OnAppearing();
|
base.OnAppearing();
|
||||||
|
@ -43,19 +42,32 @@ namespace Bit.App.Pages
|
||||||
base.OnDisappearing();
|
base.OnDisappearing();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Settings_Clicked(object sender, EventArgs e)
|
private void ToggleAutofillService(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
if (DoOnce())
|
if (DoOnce())
|
||||||
{
|
{
|
||||||
_vm.OpenSettings();
|
_vm.ToggleAutofillService();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OverlayPermissionSettings_Clicked(object sender, EventArgs e)
|
private void ToggleInlineAutofill(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
_vm.ToggleInlineAutofill();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ToggleAccessibility(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
if (DoOnce())
|
if (DoOnce())
|
||||||
{
|
{
|
||||||
_vm.OpenOverlayPermissionSettings();
|
_vm.ToggleAccessibility();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ToggleDrawOver(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (DoOnce())
|
||||||
|
{
|
||||||
|
_vm.ToggleDrawOver();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
201
src/App/Pages/Settings/AutofillServicesPageViewModel.cs
Normal file
|
@ -0,0 +1,201 @@
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Bit.App.Abstractions;
|
||||||
|
using Bit.App.Resources;
|
||||||
|
using Bit.App.Services;
|
||||||
|
using Bit.Core;
|
||||||
|
using Bit.Core.Abstractions;
|
||||||
|
using Bit.Core.Utilities;
|
||||||
|
|
||||||
|
namespace Bit.App.Pages
|
||||||
|
{
|
||||||
|
public class AutofillServicesPageViewModel : BaseViewModel
|
||||||
|
{
|
||||||
|
private readonly IDeviceActionService _deviceActionService;
|
||||||
|
private readonly IStorageService _storageService;
|
||||||
|
private readonly MobileI18nService _i18nService;
|
||||||
|
|
||||||
|
private bool _autofillServiceToggled;
|
||||||
|
private bool _inlineAutofillToggled;
|
||||||
|
private bool _accessibilityToggled;
|
||||||
|
private bool _drawOverToggled;
|
||||||
|
private bool _inited;
|
||||||
|
|
||||||
|
public AutofillServicesPageViewModel()
|
||||||
|
{
|
||||||
|
_deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
|
||||||
|
_storageService = ServiceContainer.Resolve<IStorageService>("storageService");
|
||||||
|
_i18nService = ServiceContainer.Resolve<II18nService>("i18nService") as MobileI18nService;
|
||||||
|
PageTitle = AppResources.AutofillServices;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Autofill Service
|
||||||
|
|
||||||
|
public bool AutofillServiceVisible
|
||||||
|
{
|
||||||
|
get => _deviceActionService.SystemMajorVersion() >= 26;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AutofillServiceToggled
|
||||||
|
{
|
||||||
|
get => _autofillServiceToggled;
|
||||||
|
set => SetProperty(ref _autofillServiceToggled, value,
|
||||||
|
additionalPropertyNames: new string[]
|
||||||
|
{
|
||||||
|
nameof(InlineAutofillEnabled)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Inline Autofill
|
||||||
|
|
||||||
|
public bool InlineAutofillVisible
|
||||||
|
{
|
||||||
|
get => _deviceActionService.SystemMajorVersion() >= 30;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool InlineAutofillEnabled
|
||||||
|
{
|
||||||
|
get => AutofillServiceToggled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool InlineAutofillToggled
|
||||||
|
{
|
||||||
|
get => _inlineAutofillToggled;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (SetProperty(ref _inlineAutofillToggled, value))
|
||||||
|
{
|
||||||
|
var task = UpdateInlineAutofillToggledAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Accessibility
|
||||||
|
|
||||||
|
public string AccessibilityDescriptionLabel
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_deviceActionService.SystemMajorVersion() <= 22)
|
||||||
|
{
|
||||||
|
// Android 5
|
||||||
|
return _i18nService.T("AccessibilityDescription");
|
||||||
|
}
|
||||||
|
if (_deviceActionService.SystemMajorVersion() == 23)
|
||||||
|
{
|
||||||
|
// Android 6
|
||||||
|
return _i18nService.T("AccessibilityDescription2");
|
||||||
|
}
|
||||||
|
if (_deviceActionService.SystemMajorVersion() == 24 || _deviceActionService.SystemMajorVersion() == 25)
|
||||||
|
{
|
||||||
|
// Android 7
|
||||||
|
return _i18nService.T("AccessibilityDescription3");
|
||||||
|
}
|
||||||
|
// Android 8+
|
||||||
|
return _i18nService.T("AccessibilityDescription4");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AccessibilityToggled
|
||||||
|
{
|
||||||
|
get => _accessibilityToggled;
|
||||||
|
set => SetProperty(ref _accessibilityToggled, value,
|
||||||
|
additionalPropertyNames: new string[]
|
||||||
|
{
|
||||||
|
nameof(DrawOverEnabled)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Draw-Over
|
||||||
|
|
||||||
|
public bool DrawOverVisible
|
||||||
|
{
|
||||||
|
get => _deviceActionService.SystemMajorVersion() >= 23;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string DrawOverDescriptionLabel
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_deviceActionService.SystemMajorVersion() <= 23)
|
||||||
|
{
|
||||||
|
// Android 6
|
||||||
|
return _i18nService.T("DrawOverDescription");
|
||||||
|
}
|
||||||
|
if (_deviceActionService.SystemMajorVersion() == 24 || _deviceActionService.SystemMajorVersion() == 25)
|
||||||
|
{
|
||||||
|
// Android 7
|
||||||
|
return _i18nService.T("DrawOverDescription2");
|
||||||
|
}
|
||||||
|
// Android 8+
|
||||||
|
return _i18nService.T("DrawOverDescription3");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool DrawOverEnabled
|
||||||
|
{
|
||||||
|
get => AccessibilityToggled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool DrawOverToggled
|
||||||
|
{
|
||||||
|
get => _drawOverToggled;
|
||||||
|
set => SetProperty(ref _drawOverToggled, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public async Task InitAsync()
|
||||||
|
{
|
||||||
|
InlineAutofillToggled = await _storageService.GetAsync<bool?>(Constants.InlineAutofillEnabledKey) ?? true;
|
||||||
|
_inited = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ToggleAutofillService()
|
||||||
|
{
|
||||||
|
if (!AutofillServiceToggled)
|
||||||
|
{
|
||||||
|
_deviceActionService.OpenAutofillSettings();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_deviceActionService.DisableAutofillService();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ToggleInlineAutofill()
|
||||||
|
{
|
||||||
|
InlineAutofillToggled = !InlineAutofillToggled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ToggleAccessibility()
|
||||||
|
{
|
||||||
|
_deviceActionService.OpenAccessibilitySettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ToggleDrawOver()
|
||||||
|
{
|
||||||
|
_deviceActionService.OpenAccessibilityOverlayPermissionSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateEnabled()
|
||||||
|
{
|
||||||
|
AutofillServiceToggled = _deviceActionService.AutofillServiceEnabled();
|
||||||
|
AccessibilityToggled = _deviceActionService.AutofillAccessibilityServiceRunning();
|
||||||
|
DrawOverToggled = _deviceActionService.AutofillAccessibilityOverlayPermitted();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task UpdateInlineAutofillToggledAsync()
|
||||||
|
{
|
||||||
|
if (_inited)
|
||||||
|
{
|
||||||
|
await _storageService.SaveAsync(Constants.InlineAutofillEnabledKey, InlineAutofillToggled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -57,13 +57,9 @@ namespace Bit.App.Pages
|
||||||
{
|
{
|
||||||
await Navigation.PushModalAsync(new NavigationPage(new SyncPage()));
|
await Navigation.PushModalAsync(new NavigationPage(new SyncPage()));
|
||||||
}
|
}
|
||||||
else if (item.Name == AppResources.AutofillAccessibilityService)
|
else if (item.Name == AppResources.AutofillServices)
|
||||||
{
|
{
|
||||||
await Navigation.PushModalAsync(new NavigationPage(new AccessibilityServicePage(this)));
|
await Navigation.PushModalAsync(new NavigationPage(new AutofillServicesPage(this)));
|
||||||
}
|
|
||||||
else if (item.Name == AppResources.AutofillService)
|
|
||||||
{
|
|
||||||
await Navigation.PushModalAsync(new NavigationPage(new AutofillServicePage(this)));
|
|
||||||
}
|
}
|
||||||
else if (item.Name == AppResources.PasswordAutofill)
|
else if (item.Name == AppResources.PasswordAutofill)
|
||||||
{
|
{
|
||||||
|
|
|
@ -326,22 +326,10 @@ namespace Bit.App.Pages
|
||||||
var autofillItems = new List<SettingsPageListItem>();
|
var autofillItems = new List<SettingsPageListItem>();
|
||||||
if (Device.RuntimePlatform == Device.Android)
|
if (Device.RuntimePlatform == Device.Android)
|
||||||
{
|
{
|
||||||
if (_deviceActionService.SupportsAutofillService())
|
|
||||||
{
|
|
||||||
autofillItems.Add(new SettingsPageListItem
|
|
||||||
{
|
|
||||||
Name = AppResources.AutofillService,
|
|
||||||
SubLabel = _deviceActionService.AutofillServiceEnabled() ?
|
|
||||||
AppResources.Enabled : AppResources.Disabled
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
var accessibilityEnabled = _deviceActionService.AutofillAccessibilityServiceRunning() &&
|
|
||||||
_deviceActionService.AutofillAccessibilityOverlayPermitted();
|
|
||||||
autofillItems.Add(new SettingsPageListItem
|
autofillItems.Add(new SettingsPageListItem
|
||||||
{
|
{
|
||||||
Name = AppResources.AutofillAccessibilityService,
|
Name = AppResources.AutofillServices,
|
||||||
SubLabel = accessibilityEnabled ?
|
SubLabel = _deviceActionService.AutofillServicesEnabled() ?
|
||||||
AppResources.Enabled : AppResources.Disabled
|
AppResources.Enabled : AppResources.Disabled
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
78
src/App/Resources/AppResources.Designer.cs
generated
|
@ -3074,5 +3074,83 @@ namespace Bit.App.Resources {
|
||||||
return ResourceManager.GetString("PrivacyPolicy", resourceCulture);
|
return ResourceManager.GetString("PrivacyPolicy", resourceCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string AccessibilityDrawOverPermissionAlert {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("AccessibilityDrawOverPermissionAlert", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string AutofillServices {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("AutofillServices", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string InlineAutofill {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("InlineAutofill", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string InlineAutofillDescription {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("InlineAutofillDescription", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string Accessibility {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Accessibility", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string AccessibilityDescription {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("AccessibilityDescription", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string AccessibilityDescription2 {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("AccessibilityDescription2", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string AccessibilityDescription3 {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("AccessibilityDescription3", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string AccessibilityDescription4 {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("AccessibilityDescription4", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string DrawOver {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("DrawOver", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string DrawOverDescription {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("DrawOverDescription", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string DrawOverDescription2 {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("DrawOverDescription2", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string DrawOverDescription3 {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("DrawOverDescription3", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1744,4 +1744,43 @@
|
||||||
<data name="PrivacyPolicy" xml:space="preserve">
|
<data name="PrivacyPolicy" xml:space="preserve">
|
||||||
<value>Privacy Policy</value>
|
<value>Privacy Policy</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="AccessibilityDrawOverPermissionAlert" xml:space="preserve">
|
||||||
|
<value>Bitwarden needs attention - Enable "Draw-Over" in "Auto-fill Services" from Bitwarden Settings</value>
|
||||||
|
</data>
|
||||||
|
<data name="AutofillServices" xml:space="preserve">
|
||||||
|
<value>Auto-fill Services</value>
|
||||||
|
</data>
|
||||||
|
<data name="InlineAutofill" xml:space="preserve">
|
||||||
|
<value>Use Inline Autofill</value>
|
||||||
|
</data>
|
||||||
|
<data name="InlineAutofillDescription" xml:space="preserve">
|
||||||
|
<value>Use inline autofill if your selected IME (keyboard) supports it. If your configuration is not supported (or this option is disabled), the default Autofill overlay will be used.</value>
|
||||||
|
</data>
|
||||||
|
<data name="Accessibility" xml:space="preserve">
|
||||||
|
<value>Use Accessibility</value>
|
||||||
|
</data>
|
||||||
|
<data name="AccessibilityDescription" xml:space="preserve">
|
||||||
|
<value>Use the Bitwarden Accessibility Service to auto-fill your logins across apps and the web. When enabled, we'll display a popup when login fields are selected.</value>
|
||||||
|
</data>
|
||||||
|
<data name="AccessibilityDescription2" xml:space="preserve">
|
||||||
|
<value>Use the Bitwarden Accessibility Service to auto-fill your logins across apps and the web. (Requires Draw-Over to be enabled as well)</value>
|
||||||
|
</data>
|
||||||
|
<data name="AccessibilityDescription3" xml:space="preserve">
|
||||||
|
<value>Use the Bitwarden Accessibility Service to use the Autofill Quick-Action Tile, and/or show a popup using Draw-Over (if enabled).</value>
|
||||||
|
</data>
|
||||||
|
<data name="AccessibilityDescription4" xml:space="preserve">
|
||||||
|
<value>Required to use the Autofill Quick-Action Tile, or to augment the Autofill Service by using Draw-Over (if enabled).</value>
|
||||||
|
</data>
|
||||||
|
<data name="DrawOver" xml:space="preserve">
|
||||||
|
<value>Use Draw-Over</value>
|
||||||
|
</data>
|
||||||
|
<data name="DrawOverDescription" xml:space="preserve">
|
||||||
|
<value>When enabled, allows the Bitwarden Accessibility Service to display a popup when login fields are selected.</value>
|
||||||
|
</data>
|
||||||
|
<data name="DrawOverDescription2" xml:space="preserve">
|
||||||
|
<value>If enabled, the Bitwarden Accessibility Service will display a popup when login fields are selected to assist with auto-filling your logins.</value>
|
||||||
|
</data>
|
||||||
|
<data name="DrawOverDescription3" xml:space="preserve">
|
||||||
|
<value>If enabled, accessibility will show a popup to augment the Autofill Service for older apps that don't support the Android Autofill Framework.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
|
@ -35,6 +35,7 @@ namespace Bit.App.Services
|
||||||
Constants.iOSAutoFillClearCiphersCacheKey,
|
Constants.iOSAutoFillClearCiphersCacheKey,
|
||||||
Constants.iOSExtensionClearCiphersCacheKey,
|
Constants.iOSExtensionClearCiphersCacheKey,
|
||||||
Constants.EnvironmentUrlsKey,
|
Constants.EnvironmentUrlsKey,
|
||||||
|
Constants.InlineAutofillEnabledKey,
|
||||||
};
|
};
|
||||||
|
|
||||||
private readonly HashSet<string> _migrateToPreferences = new HashSet<string>
|
private readonly HashSet<string> _migrateToPreferences = new HashSet<string>
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
public static string TriedV1Resync = "triedV1Resync";
|
public static string TriedV1Resync = "triedV1Resync";
|
||||||
public static string EventCollectionKey = "eventCollection";
|
public static string EventCollectionKey = "eventCollection";
|
||||||
public static string PreviousPageKey = "previousPage";
|
public static string PreviousPageKey = "previousPage";
|
||||||
|
public static string InlineAutofillEnabledKey = "inlineAutofillEnabled";
|
||||||
public const int SelectFileRequestCode = 42;
|
public const int SelectFileRequestCode = 42;
|
||||||
public const int SelectFilePermissionRequestCode = 43;
|
public const int SelectFilePermissionRequestCode = 43;
|
||||||
public const int SaveFileRequestCode = 44;
|
public const int SaveFileRequestCode = 44;
|
||||||
|
|
|
@ -392,6 +392,16 @@ namespace Bit.iOS.Core.Services
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void DisableAutofillService()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AutofillServicesEnabled()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
public string GetBuildNumber()
|
public string GetBuildNumber()
|
||||||
{
|
{
|
||||||
return NSBundle.MainBundle.InfoDictionary["CFBundleVersion"].ToString();
|
return NSBundle.MainBundle.InfoDictionary["CFBundleVersion"].ToString();
|
||||||
|
|