diff --git a/src/App/Controls/AuthenticatorViewCell/AuthenticatorViewCell.xaml b/src/App/Controls/AuthenticatorViewCell/AuthenticatorViewCell.xaml
index 4d4e82554..2c5a31042 100644
--- a/src/App/Controls/AuthenticatorViewCell/AuthenticatorViewCell.xaml
+++ b/src/App/Controls/AuthenticatorViewCell/AuthenticatorViewCell.xaml
@@ -3,35 +3,92 @@
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Bit.App.Controls.AuthenticatorViewCell"
xmlns:controls="clr-namespace:Bit.App.Controls"
+ xmlns:pages="clr-namespace:Bit.App.Pages"
xmlns:u="clr-namespace:Bit.App.Utilities"
xmlns:ff="clr-namespace:FFImageLoading.Forms;assembly=FFImageLoading.Forms"
xmlns:core="clr-namespace:Bit.Core;assembly=BitwardenCore"
StyleClass="list-row, list-row-platform"
RowSpacing="0"
ColumnSpacing="0"
- x:DataType="controls:AuthenticatorViewCellViewModel">
+ x:DataType="pages:AuthenticatorPageListItem">
+
+
+
+
+
+
+
-
+
-
-
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/App/Controls/AuthenticatorViewCell/AuthenticatorViewCell.xaml.cs b/src/App/Controls/AuthenticatorViewCell/AuthenticatorViewCell.xaml.cs
index 871c8a424..08a96fb72 100644
--- a/src/App/Controls/AuthenticatorViewCell/AuthenticatorViewCell.xaml.cs
+++ b/src/App/Controls/AuthenticatorViewCell/AuthenticatorViewCell.xaml.cs
@@ -1,5 +1,7 @@
using System;
+using Bit.App.Utilities;
using Bit.Core.Models.View;
+using Bit.Core.Utilities;
using Xamarin.Forms;
namespace Bit.App.Controls
@@ -7,64 +9,112 @@ namespace Bit.App.Controls
public partial class AuthenticatorViewCell : ExtendedGrid
{
public static readonly BindableProperty CipherProperty = BindableProperty.Create(
- nameof(Cipher), typeof(CipherView), typeof(AuthenticatorViewCell), default(CipherView), BindingMode.OneWay);
+ nameof(Cipher), typeof(CipherView), typeof(AuthenticatorViewCell), default(CipherView), BindingMode.TwoWay);
public static readonly BindableProperty WebsiteIconsEnabledProperty = BindableProperty.Create(
nameof(WebsiteIconsEnabled), typeof(bool?), typeof(AuthenticatorViewCell));
- public static readonly BindableProperty ButtonCommandProperty = BindableProperty.Create(
- nameof(ButtonCommand), typeof(Command), typeof(AuthenticatorViewCell));
+ public static readonly BindableProperty TotpSecProperty = BindableProperty.Create(
+ nameof(TotpSec), typeof(long), typeof(AuthenticatorViewCell));
+
+ //public static readonly BindableProperty ButtonCommandProperty = BindableProperty.Create(
+ // nameof(ButtonCommand), typeof(Command), typeof(AuthenticatorViewCell));
public AuthenticatorViewCell()
{
InitializeComponent();
}
+ public Command CopyCommand { get; set; }
+
+ public CipherView Cipher
+ {
+ get => GetValue(CipherProperty) as CipherView;
+ set => SetValue(CipherProperty, value);
+ }
+
public bool? WebsiteIconsEnabled
{
get => (bool)GetValue(WebsiteIconsEnabledProperty);
set => SetValue(WebsiteIconsEnabledProperty, value);
}
- public CipherView Cipher
+ public long TotpSec
{
- get => GetValue(CipherProperty) as CipherView;
- set => SetValue(CipherProperty, value);
+ get => (long)GetValue(TotpSecProperty);
+ set => SetValue(TotpSecProperty, value);
}
- public Command ButtonCommand
+ public bool ShowIconImage
{
- get => GetValue(ButtonCommandProperty) as Command;
- set => SetValue(ButtonCommandProperty, value);
+ get => WebsiteIconsEnabled ?? false
+ && !string.IsNullOrWhiteSpace(Cipher.Login?.Uri)
+ && IconImageSource != null;
}
- protected override void OnPropertyChanged(string propertyName = null)
+ private string _iconImageSource = string.Empty;
+ public string IconImageSource
{
- base.OnPropertyChanged(propertyName);
- if (propertyName == CipherProperty.PropertyName)
+ get
{
- if (Cipher == null)
+ if (_iconImageSource == string.Empty) // default value since icon source can return null
{
- return;
+ _iconImageSource = IconImageHelper.GetLoginIconImage(Cipher);
}
- BindingContext = new AuthenticatorViewCellViewModel(Cipher, WebsiteIconsEnabled ?? false);
- }
- else if (propertyName == WebsiteIconsEnabledProperty.PropertyName)
- {
- if (Cipher == null)
- {
- return;
- }
- ((AuthenticatorViewCellViewModel)BindingContext).WebsiteIconsEnabled = WebsiteIconsEnabled ?? false;
+ return _iconImageSource;
}
+
}
+ private string _totpCodeFormatted = "938 928";
+ public string TotpCodeFormatted
+ {
+ get => _totpCodeFormatted;
+ set => _totpCodeFormatted = value;
+ }
+
+
+ //public Command ButtonCommand
+ //{
+ // get => GetValue(ButtonCommandProperty) as Command;
+ // set => SetValue(ButtonCommandProperty, value);
+ //}
+
+ //protected override void OnPropertyChanged(string propertyName = null)
+ //{
+ // base.OnPropertyChanged(propertyName);
+ // if (propertyName == CipherProperty.PropertyName)
+ // {
+ // if (Cipher == null)
+ // {
+ // return;
+ // }
+ // _cipherLabel.Text = Cipher.Name;
+ // }
+ // else if (propertyName == WebsiteIconsEnabledProperty.PropertyName)
+ // {
+ // if (Cipher == null)
+ // {
+ // return;
+ // }
+ // ((AuthenticatorViewCellViewModel)BindingContext).WebsiteIconsEnabled = WebsiteIconsEnabled ?? false;
+ // }
+ // else if (propertyName == TotpSecProperty.PropertyName)
+ // {
+ // if (Cipher == null)
+ // {
+ // return;
+ // }
+ // ((AuthenticatorViewCellViewModel)BindingContext).UpdateTotpSec(TotpSec);
+ // }
+ //}
+
private void MoreButton_Clicked(object sender, EventArgs e)
{
var cipher = ((sender as MiButton)?.BindingContext as AuthenticatorViewCellViewModel)?.Cipher;
if (cipher != null)
{
- ButtonCommand?.Execute(cipher);
+ //ButtonCommand?.Execute(cipher);
}
}
}
diff --git a/src/App/Controls/AuthenticatorViewCell/AuthenticatorViewCellViewModel.cs b/src/App/Controls/AuthenticatorViewCell/AuthenticatorViewCellViewModel.cs
index 0010e6a3b..ad1aaf5e2 100644
--- a/src/App/Controls/AuthenticatorViewCell/AuthenticatorViewCellViewModel.cs
+++ b/src/App/Controls/AuthenticatorViewCell/AuthenticatorViewCellViewModel.cs
@@ -1,3 +1,4 @@
+using System.Threading.Tasks;
using Bit.App.Utilities;
using Bit.Core.Models.View;
using Bit.Core.Utilities;
@@ -8,7 +9,7 @@ namespace Bit.App.Controls
public class AuthenticatorViewCellViewModel : ExtendedViewModel
{
private CipherView _cipher;
- private string _totpCodeFormatted = "938928";
+ private string _totpCodeFormatted = "938 928";
private string _totpSec;
private bool _websiteIconsEnabled;
private string _iconImageSource = string.Empty;
@@ -64,6 +65,39 @@ namespace Bit.App.Controls
}
}
+
+ public void UpdateTotpSec(long totpSec)
+ {
+ _totpSec = totpSec.ToString();
+ }
+
+ //private async Task TotpUpdateCodeAsync()
+ //{
+ // if (Cipher == null || Cipher.Type != Core.Enums.CipherType.Login || Cipher.Login.Totp == null)
+ // {
+ // _totpInterval = null;
+ // return;
+ // }
+ // _totpCode = await _totpService.GetCodeAsync(Cipher.Login.Totp);
+ // if (_totpCode != null)
+ // {
+ // if (_totpCode.Length > 4)
+ // {
+ // var half = (int)Math.Floor(_totpCode.Length / 2M);
+ // TotpCodeFormatted = string.Format("{0} {1}", _totpCode.Substring(0, half),
+ // _totpCode.Substring(half));
+ // }
+ // else
+ // {
+ // TotpCodeFormatted = _totpCode;
+ // }
+ // }
+ // else
+ // {
+ // TotpCodeFormatted = null;
+ // _totpInterval = null;
+ // }
+ //}
}
}
diff --git a/src/App/Pages/Authenticator/AuthenticatorPage.xaml b/src/App/Pages/Authenticator/AuthenticatorPage.xaml
index 21eac5abd..9eb346a34 100644
--- a/src/App/Pages/Authenticator/AuthenticatorPage.xaml
+++ b/src/App/Pages/Authenticator/AuthenticatorPage.xaml
@@ -2,42 +2,96 @@
+ x:DataType="pages:AuthenticatorPageViewModel"
+ Title="{Binding PageTitle}"
+ x:Name="_page">
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
diff --git a/src/App/Pages/Authenticator/AuthenticatorPage.xaml.cs b/src/App/Pages/Authenticator/AuthenticatorPage.xaml.cs
index bd39ab3dc..2ca8971eb 100644
--- a/src/App/Pages/Authenticator/AuthenticatorPage.xaml.cs
+++ b/src/App/Pages/Authenticator/AuthenticatorPage.xaml.cs
@@ -1,5 +1,6 @@
using Bit.App.Resources;
using System;
+using System.Linq;
using System.Threading.Tasks;
using Bit.Core.Abstractions;
using Bit.Core.Utilities;
@@ -7,13 +8,15 @@ using Xamarin.Forms;
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.iOSSpecific;
-namespace Bit.App.Pages.Authenticator
+namespace Bit.App.Pages
{
public partial class AuthenticatorPage : BaseContentPage
{
#region Members
private readonly IBroadcasterService _broadcasterService;
+ private readonly ISyncService _syncService;
+ private readonly ICipherService _cipherService;
private AuthenticatorPageViewModel _vm;
private readonly bool _fromTabPage;
private readonly Action _selectAction;
@@ -23,83 +26,121 @@ namespace Bit.App.Pages.Authenticator
public AuthenticatorPage(bool fromTabPage, Action selectAction = null, TabsPage tabsPage = null)
{
- _tabsPage = tabsPage;
+ //_tabsPage = tabsPage;
InitializeComponent();
- _broadcasterService = ServiceContainer.Resolve("broadcasterService");
+ //_broadcasterService = ServiceContainer.Resolve("broadcasterService");
+ _syncService = ServiceContainer.Resolve("syncService");
+ _cipherService = ServiceContainer.Resolve("cipherService");
_vm = BindingContext as AuthenticatorPageViewModel;
- _vm.Page = this;
- _fromTabPage = fromTabPage;
- _selectAction = selectAction;
- //var isIos = Device.RuntimePlatform == Device.iOS;
- //if (selectAction != null)
- //{
- // if (isIos)
- // {
- // ToolbarItems.Add(_closeItem);
- // }
- // ToolbarItems.Add(_selectItem);
- //}
- //else
- //{
- // if (isIos)
- // {
- // ToolbarItems.Add(_moreItem);
- // }
- // else
- // {
- // ToolbarItems.Add(_historyItem);
- // }
- //}
- //if (isIos)
- //{
- // _typePicker.On().SetUpdateMode(UpdateMode.WhenFinished);
- //}
+ //_vm.Page = this;
+ //_fromTabPage = fromTabPage;
+ //_selectAction = selectAction;
+
+ if (Device.RuntimePlatform == Device.iOS)
+ {
+ _absLayout.Children.Remove(_fab);
+ ToolbarItems.Add(_aboutIconItem);
+ ToolbarItems.Add(_addItem);
+ }
+ else
+ {
+ ToolbarItems.Add(_syncItem);
+ ToolbarItems.Add(_lockItem);
+ ToolbarItems.Add(_aboutTextItem);
+ }
}
public async Task InitAsync()
{
- await _vm.InitAsync();
+ await _vm.LoadAsync();
}
protected async override void OnAppearing()
{
base.OnAppearing();
- if (!_fromTabPage)
+ //if (!_fromTabPage)
+ //{
+ // await InitAsync();
+ //}
+ //_broadcasterService.Subscribe(nameof(GeneratorPage), async (message) =>
+ //{
+ // if (message.Command == "updatedTheme")
+ // {
+ // Device.BeginInvokeOnMainThread(() =>
+ // {
+ // //_vm.RedrawPassword();
+ // });
+ // }
+ //});
+
+ await LoadOnAppearedAsync(_mainLayout, false, async () =>
{
- await InitAsync();
- }
- _broadcasterService.Subscribe(nameof(GeneratorPage), async (message) =>
- {
- if (message.Command == "updatedTheme")
+ if (!_syncService.SyncInProgress || (await _cipherService.GetAllAsync()).Any())
{
- Device.BeginInvokeOnMainThread(() =>
+ try
{
- //_vm.RedrawPassword();
- });
+ await _vm.LoadAsync();
+ }
+ catch (Exception e) when (e.Message.Contains("No key."))
+ {
+ await Task.Delay(1000);
+ await _vm.LoadAsync();
+ }
}
- });
+ else
+ {
+ await Task.Delay(5000);
+ if (!_vm.Loaded)
+ {
+ await _vm.LoadAsync();
+ }
+ }
+
+ AdjustToolbar();
+ //await CheckAddRequest();
+ }, _mainContent);
+
+ }
+
+
+
+ private async void Search_Clicked(object sender, EventArgs e)
+ {
+ if (DoOnce())
+ {
+ // var page = new SendsPage(_vm.Filter, _vm.Type != null);
+ // await Navigation.PushModalAsync(new NavigationPage(page));
+ }
+ }
+
+ private async void Sync_Clicked(object sender, EventArgs e)
+ {
+ // await _vm.SyncAsync();
+ }
+
+ private async void Lock_Clicked(object sender, EventArgs e)
+ {
+ // await _vaultTimeoutService.LockAsync(true, true);
}
- protected override void OnDisappearing()
+ private void About_Clicked(object sender, EventArgs e)
{
- base.OnDisappearing();
- //_broadcasterService.Unsubscribe(nameof(GeneratorPage));
+ // _vm.ShowAbout();
+ }
+
+ private async void AddButton_Clicked(object sender, EventArgs e)
+ {
+ if (DoOnce())
+ {
+ // var page = new SendAddEditPage(null, null, _vm.Type);
+ // await Navigation.PushModalAsync(new NavigationPage(page));
+ }
}
private async void RowSelected(object sender, SelectionChangedEventArgs e)
{
}
- protected override bool OnBackButtonPressed()
- {
- if (Device.RuntimePlatform == Device.Android && _tabsPage != null)
- {
- _tabsPage.ResetToVaultPage();
- return true;
- }
- return base.OnBackButtonPressed();
- }
-
private async void Copy_Clicked(object sender, EventArgs e)
{
//await _vm.CopyAsync();
@@ -120,20 +161,16 @@ namespace Bit.App.Pages.Authenticator
//}
}
- private void Select_Clicked(object sender, EventArgs e)
+ protected override void OnDisappearing()
{
- //_selectAction?.Invoke(_vm.Password);
+ base.OnDisappearing();
+ //_broadcasterService.Unsubscribe(nameof(GeneratorPage));
}
-
- private async void Close_Clicked(object sender, EventArgs e)
+ private void AdjustToolbar()
{
- if (DoOnce())
- {
- await Navigation.PopModalAsync();
- }
+ //_addItem.IsEnabled = !_vm.Deleted;
+ //_addItem.IconImageSource = _vm.Deleted ? null : "plus.png";
}
-
-
}
}
diff --git a/src/App/Pages/Authenticator/AuthenticatorPageListItem.cs b/src/App/Pages/Authenticator/AuthenticatorPageListItem.cs
new file mode 100644
index 000000000..5475a9a90
--- /dev/null
+++ b/src/App/Pages/Authenticator/AuthenticatorPageListItem.cs
@@ -0,0 +1,129 @@
+using System;
+using System.Threading.Tasks;
+using Bit.App.Resources;
+using Bit.App.Utilities;
+using Bit.Core;
+using Bit.Core.Abstractions;
+using Bit.Core.Enums;
+using Bit.Core.Models.View;
+using Bit.Core.Utilities;
+using Xamarin.Forms;
+
+namespace Bit.App.Pages
+{
+ public class AuthenticatorPageListItem : ExtendedViewModel
+ {
+ //private string _totpCode;
+ private readonly ITotpService _totpService;
+
+ //public CipherView Cipher { get; set; }
+ //public CipherType? Type { get; set; }
+ //public int interval { get; set; }
+ //public long TotpSec { get; set; }
+ //private DateTime? _totpInterval = null;
+
+ private CipherView _cipher;
+
+ private bool _websiteIconsEnabled;
+ private string _iconImageSource = string.Empty;
+
+ public int interval { get; set; }
+ private string _totpSec;
+
+ private string _totpCode;
+ private string _totpCodeFormatted = "938 928";
+
+
+ public AuthenticatorPageListItem(CipherView cipherView, bool websiteIconsEnabled)
+ {
+ _totpService = ServiceContainer.Resolve("totpService");
+
+ Cipher = cipherView;
+ WebsiteIconsEnabled = websiteIconsEnabled;
+ interval = _totpService.GetTimeInterval(Cipher.Login.Totp);
+ }
+
+
+ public Command CopyCommand { get; set; }
+
+ public CipherView Cipher
+ {
+ get => _cipher;
+ set => SetProperty(ref _cipher, value);
+ }
+
+ public string TotpCodeFormatted
+ {
+ get => _totpCodeFormatted;
+ set => SetProperty(ref _totpCodeFormatted, value);
+ }
+
+ public string TotpSec
+ {
+ get => _totpSec;
+ set => SetProperty(ref _totpSec, value);
+ }
+
+ public bool WebsiteIconsEnabled
+ {
+ get => _websiteIconsEnabled;
+ set => SetProperty(ref _websiteIconsEnabled, value);
+ }
+
+ public bool ShowIconImage
+ {
+ get => WebsiteIconsEnabled
+ && !string.IsNullOrWhiteSpace(Cipher.Login?.Uri)
+ && IconImageSource != null;
+ }
+
+ public string IconImageSource
+ {
+ get
+ {
+ if (_iconImageSource == string.Empty) // default value since icon source can return null
+ {
+ _iconImageSource = IconImageHelper.GetLoginIconImage(Cipher);
+ }
+ return _iconImageSource;
+ }
+
+ }
+
+ public async Task TotpTickAsync()
+ {
+ var epoc = CoreHelpers.EpocUtcNow() / 1000;
+ var mod = epoc % interval;
+ var totpSec = interval - mod;
+ TotpSec = totpSec.ToString();
+ //TotpLow = totpSec < 7;
+ if (mod == 0)
+ {
+ await TotpUpdateCodeAsync();
+ }
+
+ }
+
+ public async Task TotpUpdateCodeAsync()
+ {
+ _totpCode = await _totpService.GetCodeAsync(Cipher.Login.Totp);
+ if (_totpCode != null)
+ {
+ if (_totpCode.Length > 4)
+ {
+ var half = (int)Math.Floor(_totpCode.Length / 2M);
+ TotpCodeFormatted = string.Format("{0} {1}", _totpCode.Substring(0, half),
+ _totpCode.Substring(half));
+ }
+ else
+ {
+ TotpCodeFormatted = _totpCode;
+ }
+ }
+ else
+ {
+ TotpCodeFormatted = null;
+ }
+ }
+ }
+}
diff --git a/src/App/Pages/Authenticator/AuthenticatorPageViewModel.cs b/src/App/Pages/Authenticator/AuthenticatorPageViewModel.cs
index 729b582fc..ffda90d0b 100644
--- a/src/App/Pages/Authenticator/AuthenticatorPageViewModel.cs
+++ b/src/App/Pages/Authenticator/AuthenticatorPageViewModel.cs
@@ -1,37 +1,48 @@
using System;
using System.Threading.Tasks;
+using System.Linq;
+using Bit.App.Resources;
using Bit.Core.Abstractions;
+using Bit.Core.Models.View;
using Bit.Core.Utilities;
using Xamarin.Forms;
-namespace Bit.App.Pages.Authenticator
+namespace Bit.App.Pages
{
public class AuthenticatorPageViewModel : BaseViewModel
{
#region Members
private readonly IClipboardService _clipboardService;
+ private readonly ITotpService _totpService;
+ private readonly IUserService _userService;
+ private readonly IVaultTimeoutService _vaultTimeoutService;
+ private readonly ICipherService _cipherService;
+
private bool _showList = true;
private bool _refreshing;
- private readonly IStateService _stateService;
- private readonly IVaultTimeoutService _vaultTimeoutService;
-
+ private bool _loaded;
+ private bool _websiteIconsEnabled = true;
+ //private long _totpSec;
#endregion
#region Ctor
public AuthenticatorPageViewModel()
{
- _stateService = ServiceContainer.Resolve("stateService");
+ _cipherService = ServiceContainer.Resolve("cipherService");
+ _userService = ServiceContainer.Resolve("userService");
_vaultTimeoutService = ServiceContainer.Resolve("vaultTimeoutService");
+ _totpService = ServiceContainer.Resolve("totpService");
+
+ PageTitle = AppResources.Authenticator;
+ Items = new ExtendedObservableCollection();
}
#endregion
#region Methods
- public async Task InitAsync() { await LoadAsync(); }
-
public async Task CopyAsync()
{
//await _clipboardService.CopyTextAsync(Password);
@@ -41,7 +52,7 @@ namespace Bit.App.Pages.Authenticator
public async Task LoadAsync()
{
- var authed = await _stateService.IsAuthenticatedAsync();
+ var authed = await _userService.IsAuthenticatedAsync();
if (!authed)
{
return;
@@ -51,15 +62,61 @@ namespace Bit.App.Pages.Authenticator
return;
}
- this.ShowList = true;
- this.Refreshing = false;
+ try
+ {
+ await LoadDataAsync();
+ }
+ finally
+ {
+ ShowList = true;
+ Refreshing = false;
+ }
+ }
+
+ private async Task LoadDataAsync()
+ {
+ var _allCiphers = await _cipherService.GetAllDecryptedAsync();
+ _allCiphers = _allCiphers.Where(c => c.Type == Core.Enums.CipherType.Login && c.Login.Totp != null).ToList();
+ var filteredCiphers = _allCiphers.Select(c => new AuthenticatorPageListItem(c, WebsiteIconsEnabled)).ToList();
+ Items.ResetWithRange(filteredCiphers);
+
+ foreach (AuthenticatorPageListItem item in Items)
+ {
+ item.TotpUpdateCodeAsync();
+ }
+
+ //await TotpUpdateCodeAsync();
+ // var interval = _totpService.GetTimeInterval(Cipher.Login.Totp);
+ // await TotpTickAsync(interval);
+ // _totpInterval = DateTime.UtcNow;
+ Device.StartTimer(new TimeSpan(0, 0, 1), () =>
+ {
+ foreach(AuthenticatorPageListItem item in Items)
+ {
+ item.TotpTickAsync();
+ }
+ return true;
+ });
+ //}
+
+ //private async Task TotpTickAsync(int intervalSeconds)
+ //{
+ // var epoc = CoreHelpers.EpocUtcNow() / 1000;
+ // var mod = epoc % intervalSeconds;
+ // var totpSec = intervalSeconds - mod;
+ // TotpSec = totpSec.ToString();
+ // TotpLow = totpSec < 7;
+ // if (mod == 0)
+ // {
+ // await TotpUpdateCodeAsync();
+ // }
}
#endregion
#region Properties
- public ExtendedObservableCollection Items { get; set; }
+ public ExtendedObservableCollection Items { get; set; }
public Command RefreshCommand { get; set; }
public bool ShowList
@@ -74,6 +131,23 @@ namespace Bit.App.Pages.Authenticator
set => SetProperty(ref _refreshing, value);
}
+ public bool WebsiteIconsEnabled
+ {
+ get => _websiteIconsEnabled;
+ set => SetProperty(ref _websiteIconsEnabled, value);
+ }
+
+ public bool Loaded
+ {
+ get => _loaded;
+ set => SetProperty(ref _loaded, value);
+ }
+ //public long TotpSec
+ //{
+ // get => _totpSec;
+ // set => SetProperty(ref _totpSec, value);
+ //}
+
#endregion
}
}