2019-05-29 15:08:47 +02:00
|
|
|
|
using Bit.App.Abstractions;
|
|
|
|
|
using Bit.App.Resources;
|
2019-05-29 20:23:55 +02:00
|
|
|
|
using Bit.App.Utilities;
|
2019-05-29 15:36:57 +02:00
|
|
|
|
using Bit.Core;
|
2019-05-29 15:08:47 +02:00
|
|
|
|
using Bit.Core.Abstractions;
|
2019-05-29 20:11:15 +02:00
|
|
|
|
using Bit.Core.Enums;
|
2019-05-29 15:08:47 +02:00
|
|
|
|
using Bit.Core.Utilities;
|
2019-05-29 20:11:15 +02:00
|
|
|
|
using System.Collections.Generic;
|
2019-05-29 15:08:47 +02:00
|
|
|
|
using System.Threading.Tasks;
|
2019-05-29 21:50:20 +02:00
|
|
|
|
using Xamarin.Forms;
|
2019-05-29 15:08:47 +02:00
|
|
|
|
|
|
|
|
|
namespace Bit.App.Pages
|
|
|
|
|
{
|
|
|
|
|
public class OptionsPageViewModel : BaseViewModel
|
|
|
|
|
{
|
|
|
|
|
private readonly IDeviceActionService _deviceActionService;
|
|
|
|
|
private readonly IPlatformUtilsService _platformUtilsService;
|
2019-05-29 15:36:57 +02:00
|
|
|
|
private readonly IStorageService _storageService;
|
|
|
|
|
private readonly ITotpService _totpService;
|
|
|
|
|
private readonly IStateService _stateService;
|
2019-05-29 21:50:20 +02:00
|
|
|
|
private readonly IMessagingService _messagingService;
|
2019-05-29 15:36:57 +02:00
|
|
|
|
|
2019-05-30 18:37:35 +02:00
|
|
|
|
|
2019-06-03 16:45:27 +02:00
|
|
|
|
private bool _autofillDisableSavePrompt;
|
|
|
|
|
private string _autofillBlacklistedUris;
|
2019-05-29 15:36:57 +02:00
|
|
|
|
private bool _disableFavicon;
|
|
|
|
|
private bool _disableAutoTotpCopy;
|
2019-05-29 20:11:15 +02:00
|
|
|
|
private int _clearClipboardSelectedIndex;
|
|
|
|
|
private int _themeSelectedIndex;
|
|
|
|
|
private int _uriMatchSelectedIndex;
|
2019-05-29 20:23:55 +02:00
|
|
|
|
private bool _inited;
|
2019-05-30 18:37:35 +02:00
|
|
|
|
private bool _updatingAutofill;
|
2019-06-04 05:20:59 +02:00
|
|
|
|
private bool _showAndroidAutofillSettings;
|
2019-05-29 20:11:15 +02:00
|
|
|
|
|
2019-05-29 15:08:47 +02:00
|
|
|
|
public OptionsPageViewModel()
|
|
|
|
|
{
|
|
|
|
|
_deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
|
|
|
|
|
_platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService");
|
2019-05-29 15:36:57 +02:00
|
|
|
|
_storageService = ServiceContainer.Resolve<IStorageService>("storageService");
|
|
|
|
|
_totpService = ServiceContainer.Resolve<ITotpService>("totpService");
|
|
|
|
|
_stateService = ServiceContainer.Resolve<IStateService>("stateService");
|
2019-05-29 21:50:20 +02:00
|
|
|
|
_messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService");
|
2019-05-29 15:08:47 +02:00
|
|
|
|
|
|
|
|
|
PageTitle = AppResources.Options;
|
2019-07-02 05:44:47 +02:00
|
|
|
|
var iosIos = Device.RuntimePlatform == Device.iOS;
|
2019-05-29 20:11:15 +02:00
|
|
|
|
|
|
|
|
|
ClearClipboardOptions = new List<KeyValuePair<int?, string>>
|
|
|
|
|
{
|
|
|
|
|
new KeyValuePair<int?, string>(null, AppResources.Never),
|
|
|
|
|
new KeyValuePair<int?, string>(10, AppResources.TenSeconds),
|
|
|
|
|
new KeyValuePair<int?, string>(20, AppResources.TwentySeconds),
|
|
|
|
|
new KeyValuePair<int?, string>(30, AppResources.ThirtySeconds),
|
2019-07-02 05:44:47 +02:00
|
|
|
|
new KeyValuePair<int?, string>(60, AppResources.OneMinute)
|
2019-05-29 20:11:15 +02:00
|
|
|
|
};
|
2020-03-28 14:16:28 +01:00
|
|
|
|
if (!iosIos)
|
2019-07-02 05:44:47 +02:00
|
|
|
|
{
|
|
|
|
|
ClearClipboardOptions.Add(new KeyValuePair<int?, string>(120, AppResources.TwoMinutes));
|
|
|
|
|
ClearClipboardOptions.Add(new KeyValuePair<int?, string>(300, AppResources.FiveMinutes));
|
|
|
|
|
}
|
2019-05-29 20:11:15 +02:00
|
|
|
|
ThemeOptions = new List<KeyValuePair<string, string>>
|
|
|
|
|
{
|
|
|
|
|
new KeyValuePair<string, string>(null, AppResources.Default),
|
|
|
|
|
new KeyValuePair<string, string>("light", AppResources.Light),
|
|
|
|
|
new KeyValuePair<string, string>("dark", AppResources.Dark),
|
2019-06-24 20:49:47 +02:00
|
|
|
|
new KeyValuePair<string, string>("black", AppResources.Black),
|
|
|
|
|
new KeyValuePair<string, string>("nord", "Nord"),
|
2019-05-29 20:11:15 +02:00
|
|
|
|
};
|
|
|
|
|
UriMatchOptions = new List<KeyValuePair<UriMatchType?, string>>
|
|
|
|
|
{
|
|
|
|
|
new KeyValuePair<UriMatchType?, string>(UriMatchType.Domain, AppResources.BaseDomain),
|
|
|
|
|
new KeyValuePair<UriMatchType?, string>(UriMatchType.Host, AppResources.Host),
|
|
|
|
|
new KeyValuePair<UriMatchType?, string>(UriMatchType.StartsWith, AppResources.StartsWith),
|
|
|
|
|
new KeyValuePair<UriMatchType?, string>(UriMatchType.RegularExpression, AppResources.RegEx),
|
|
|
|
|
new KeyValuePair<UriMatchType?, string>(UriMatchType.Exact, AppResources.Exact),
|
|
|
|
|
new KeyValuePair<UriMatchType?, string>(UriMatchType.Never, AppResources.Never),
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public List<KeyValuePair<int?, string>> ClearClipboardOptions { get; set; }
|
|
|
|
|
public List<KeyValuePair<string, string>> ThemeOptions { get; set; }
|
|
|
|
|
public List<KeyValuePair<UriMatchType?, string>> UriMatchOptions { get; set; }
|
|
|
|
|
|
|
|
|
|
public int ClearClipboardSelectedIndex
|
|
|
|
|
{
|
|
|
|
|
get => _clearClipboardSelectedIndex;
|
|
|
|
|
set
|
|
|
|
|
{
|
2020-03-28 14:16:28 +01:00
|
|
|
|
if (SetProperty(ref _clearClipboardSelectedIndex, value))
|
2019-05-29 20:11:15 +02:00
|
|
|
|
{
|
|
|
|
|
var task = SaveClipboardChangedAsync();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public int ThemeSelectedIndex
|
|
|
|
|
{
|
|
|
|
|
get => _themeSelectedIndex;
|
|
|
|
|
set
|
|
|
|
|
{
|
2020-03-28 14:16:28 +01:00
|
|
|
|
if (SetProperty(ref _themeSelectedIndex, value))
|
2019-05-29 20:11:15 +02:00
|
|
|
|
{
|
|
|
|
|
var task = SaveThemeAsync();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public int UriMatchSelectedIndex
|
|
|
|
|
{
|
|
|
|
|
get => _uriMatchSelectedIndex;
|
|
|
|
|
set
|
|
|
|
|
{
|
2020-03-28 14:16:28 +01:00
|
|
|
|
if (SetProperty(ref _uriMatchSelectedIndex, value))
|
2019-05-29 20:11:15 +02:00
|
|
|
|
{
|
|
|
|
|
var task = SaveDefaultUriAsync();
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-05-29 15:08:47 +02:00
|
|
|
|
}
|
2019-05-29 15:36:57 +02:00
|
|
|
|
|
|
|
|
|
public bool DisableFavicon
|
|
|
|
|
{
|
|
|
|
|
get => _disableFavicon;
|
|
|
|
|
set
|
|
|
|
|
{
|
2020-03-28 14:16:28 +01:00
|
|
|
|
if (SetProperty(ref _disableFavicon, value))
|
2019-05-29 15:36:57 +02:00
|
|
|
|
{
|
|
|
|
|
var task = UpdateDisableFaviconAsync();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool DisableAutoTotpCopy
|
|
|
|
|
{
|
|
|
|
|
get => _disableAutoTotpCopy;
|
|
|
|
|
set
|
|
|
|
|
{
|
2020-03-28 14:16:28 +01:00
|
|
|
|
if (SetProperty(ref _disableAutoTotpCopy, value))
|
2019-05-29 15:36:57 +02:00
|
|
|
|
{
|
|
|
|
|
var task = UpdateAutoTotpCopyAsync();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-03 16:45:27 +02:00
|
|
|
|
public bool AutofillDisableSavePrompt
|
|
|
|
|
{
|
|
|
|
|
get => _autofillDisableSavePrompt;
|
|
|
|
|
set
|
|
|
|
|
{
|
2020-03-28 14:16:28 +01:00
|
|
|
|
if (SetProperty(ref _autofillDisableSavePrompt, value))
|
2019-06-03 16:45:27 +02:00
|
|
|
|
{
|
|
|
|
|
var task = UpdateAutofillDisableSavePromptAsync();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public string AutofillBlacklistedUris
|
|
|
|
|
{
|
|
|
|
|
get => _autofillBlacklistedUris;
|
|
|
|
|
set => SetProperty(ref _autofillBlacklistedUris, value);
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-04 05:20:59 +02:00
|
|
|
|
public bool ShowAndroidAutofillSettings
|
|
|
|
|
{
|
|
|
|
|
get => _showAndroidAutofillSettings;
|
|
|
|
|
set => SetProperty(ref _showAndroidAutofillSettings, value);
|
2019-06-03 16:45:27 +02:00
|
|
|
|
}
|
|
|
|
|
|
2019-05-29 15:36:57 +02:00
|
|
|
|
public async Task InitAsync()
|
|
|
|
|
{
|
2019-06-03 16:45:27 +02:00
|
|
|
|
AutofillDisableSavePrompt = (await _storageService.GetAsync<bool?>(
|
|
|
|
|
Constants.AutofillDisableSavePromptKey)).GetValueOrDefault();
|
|
|
|
|
var blacklistedUrisList = await _storageService.GetAsync<List<string>>(
|
|
|
|
|
Constants.AutofillBlacklistedUrisKey);
|
|
|
|
|
AutofillBlacklistedUris = blacklistedUrisList != null ? string.Join(", ", blacklistedUrisList) : null;
|
2019-05-29 15:36:57 +02:00
|
|
|
|
DisableAutoTotpCopy = !(await _totpService.IsAutoCopyEnabledAsync());
|
2019-05-30 18:37:35 +02:00
|
|
|
|
DisableFavicon = (await _storageService.GetAsync<bool?>(Constants.DisableFaviconKey)).GetValueOrDefault();
|
2019-05-29 20:11:15 +02:00
|
|
|
|
var theme = await _storageService.GetAsync<string>(Constants.ThemeKey);
|
|
|
|
|
ThemeSelectedIndex = ThemeOptions.FindIndex(k => k.Key == theme);
|
|
|
|
|
var defaultUriMatch = await _storageService.GetAsync<int?>(Constants.DefaultUriMatch);
|
|
|
|
|
UriMatchSelectedIndex = defaultUriMatch == null ? 0 :
|
|
|
|
|
UriMatchOptions.FindIndex(k => (int?)k.Key == defaultUriMatch);
|
|
|
|
|
var clearClipboard = await _storageService.GetAsync<int?>(Constants.ClearClipboardKey);
|
|
|
|
|
ClearClipboardSelectedIndex = ClearClipboardOptions.FindIndex(k => k.Key == clearClipboard);
|
2019-05-29 20:23:55 +02:00
|
|
|
|
_inited = true;
|
2019-05-29 15:36:57 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async Task UpdateAutoTotpCopyAsync()
|
|
|
|
|
{
|
2020-03-28 14:16:28 +01:00
|
|
|
|
if (_inited)
|
2019-05-29 20:23:55 +02:00
|
|
|
|
{
|
|
|
|
|
await _storageService.SaveAsync(Constants.DisableAutoTotpCopyKey, DisableAutoTotpCopy);
|
|
|
|
|
}
|
2019-05-29 15:36:57 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async Task UpdateDisableFaviconAsync()
|
|
|
|
|
{
|
2020-03-28 14:16:28 +01:00
|
|
|
|
if (_inited)
|
2019-05-29 20:23:55 +02:00
|
|
|
|
{
|
|
|
|
|
await _storageService.SaveAsync(Constants.DisableFaviconKey, DisableFavicon);
|
|
|
|
|
await _stateService.SaveAsync(Constants.DisableFaviconKey, DisableFavicon);
|
|
|
|
|
}
|
2019-05-29 15:36:57 +02:00
|
|
|
|
}
|
2019-05-29 20:11:15 +02:00
|
|
|
|
|
|
|
|
|
private async Task SaveClipboardChangedAsync()
|
|
|
|
|
{
|
2020-03-28 14:16:28 +01:00
|
|
|
|
if (_inited && ClearClipboardSelectedIndex > -1)
|
2019-05-29 20:11:15 +02:00
|
|
|
|
{
|
|
|
|
|
await _storageService.SaveAsync(Constants.ClearClipboardKey,
|
|
|
|
|
ClearClipboardOptions[ClearClipboardSelectedIndex].Key);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async Task SaveThemeAsync()
|
|
|
|
|
{
|
2020-03-28 14:16:28 +01:00
|
|
|
|
if (_inited && ThemeSelectedIndex > -1)
|
2019-05-29 20:11:15 +02:00
|
|
|
|
{
|
2019-05-29 20:23:55 +02:00
|
|
|
|
var theme = ThemeOptions[ThemeSelectedIndex].Key;
|
|
|
|
|
await _storageService.SaveAsync(Constants.ThemeKey, theme);
|
2020-03-28 14:16:28 +01:00
|
|
|
|
if (Device.RuntimePlatform == Device.Android)
|
2019-05-29 21:50:20 +02:00
|
|
|
|
{
|
2019-05-30 05:02:30 +02:00
|
|
|
|
await _deviceActionService.ShowLoadingAsync(AppResources.Restarting);
|
|
|
|
|
await Task.Delay(1000);
|
2019-05-29 21:50:20 +02:00
|
|
|
|
}
|
|
|
|
|
_messagingService.Send("updatedTheme", theme);
|
2020-03-28 14:16:28 +01:00
|
|
|
|
if (Device.RuntimePlatform == Device.iOS)
|
2019-06-24 23:32:24 +02:00
|
|
|
|
{
|
|
|
|
|
await Task.Delay(500);
|
|
|
|
|
await _platformUtilsService.ShowDialogAsync(AppResources.ThemeAppliedOnRestart);
|
|
|
|
|
}
|
2019-05-29 20:11:15 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async Task SaveDefaultUriAsync()
|
|
|
|
|
{
|
2020-03-28 14:16:28 +01:00
|
|
|
|
if (_inited && UriMatchSelectedIndex > -1)
|
2019-05-29 20:11:15 +02:00
|
|
|
|
{
|
2019-05-30 14:45:39 +02:00
|
|
|
|
await _storageService.SaveAsync(Constants.DefaultUriMatch,
|
|
|
|
|
(int?)UriMatchOptions[UriMatchSelectedIndex].Key);
|
2019-05-29 20:11:15 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
2019-06-03 16:45:27 +02:00
|
|
|
|
|
|
|
|
|
private async Task UpdateAutofillDisableSavePromptAsync()
|
|
|
|
|
{
|
2020-03-28 14:16:28 +01:00
|
|
|
|
if (_inited)
|
2019-06-03 16:45:27 +02:00
|
|
|
|
{
|
|
|
|
|
await _storageService.SaveAsync(Constants.AutofillDisableSavePromptKey, AutofillDisableSavePrompt);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task UpdateAutofillBlacklistedUris()
|
|
|
|
|
{
|
2020-03-28 14:16:28 +01:00
|
|
|
|
if (_inited)
|
2019-06-03 16:45:27 +02:00
|
|
|
|
{
|
2020-03-28 14:16:28 +01:00
|
|
|
|
if (string.IsNullOrWhiteSpace(AutofillBlacklistedUris))
|
2019-06-03 16:45:27 +02:00
|
|
|
|
{
|
|
|
|
|
await _storageService.RemoveAsync(Constants.AutofillBlacklistedUrisKey);
|
|
|
|
|
AutofillBlacklistedUris = null;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
var csv = AutofillBlacklistedUris;
|
|
|
|
|
var urisList = new List<string>();
|
2020-03-28 14:16:28 +01:00
|
|
|
|
foreach (var uri in csv.Split(','))
|
2019-06-03 16:45:27 +02:00
|
|
|
|
{
|
2020-03-28 14:16:28 +01:00
|
|
|
|
if (string.IsNullOrWhiteSpace(uri))
|
2019-06-03 16:45:27 +02:00
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2019-06-03 16:57:08 +02:00
|
|
|
|
var cleanedUri = uri.Replace(System.Environment.NewLine, string.Empty).Trim();
|
2020-03-28 14:16:28 +01:00
|
|
|
|
if (!cleanedUri.StartsWith("http://") && !cleanedUri.StartsWith("https://") &&
|
2019-06-03 16:57:08 +02:00
|
|
|
|
!cleanedUri.StartsWith(Constants.AndroidAppProtocol))
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
urisList.Add(cleanedUri);
|
2019-06-03 16:45:27 +02:00
|
|
|
|
}
|
|
|
|
|
await _storageService.SaveAsync(Constants.AutofillBlacklistedUrisKey, urisList);
|
|
|
|
|
AutofillBlacklistedUris = string.Join(", ", urisList);
|
|
|
|
|
}
|
|
|
|
|
catch { }
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-05-29 15:08:47 +02:00
|
|
|
|
}
|
|
|
|
|
}
|