mirror of
https://github.com/bitwarden/android.git
synced 2024-12-27 11:28:28 +03:00
Merge branch 'feature/maui-migration' of https://github.com/bitwarden/mobile into feature/maui-migration
# Conflicts: # src/Core/Pages/Settings/OtherSettingsPageViewModel.cs
This commit is contained in:
commit
16ada4993c
148 changed files with 1755 additions and 942 deletions
9
.github/CODEOWNERS
vendored
9
.github/CODEOWNERS
vendored
|
@ -20,12 +20,15 @@ src/watchOS @bitwarden/team-vault-dev
|
||||||
## Tools team files ##
|
## Tools team files ##
|
||||||
src/Core/Services/EmailForwarders @bitwarden/team-tools-dev
|
src/Core/Services/EmailForwarders @bitwarden/team-tools-dev
|
||||||
|
|
||||||
|
|
||||||
## Crowdin Sync files ##
|
## Crowdin Sync files ##
|
||||||
src/App/Resources @bitwarden/tech-leads
|
src/App/Resources @bitwarden/team-tools-dev
|
||||||
src/watchOS/bitwarden/bitwarden\ WatchKit\ Extension/Localization @bitwarden/tech-leads
|
src/watchOS/bitwarden/bitwarden\ WatchKit\ Extension/Localization @bitwarden/team-tools-dev
|
||||||
|
store/apple @bitwarden/team-tools-dev
|
||||||
|
store/google @bitwarden/team-tools-dev
|
||||||
|
|
||||||
## Locales ##
|
## Locales ##
|
||||||
src/App/Resources/AppResources.Designer.cs
|
src/App/Resources/AppResources.Designer.cs
|
||||||
src/App/Resources/AppResources.resx
|
src/App/Resources/AppResources.resx
|
||||||
src/watchOS/bitwarden/bitwarden\ WatchKit\ Extension/Localization/en.lproj
|
src/watchOS/bitwarden/bitwarden\ WatchKit\ Extension/Localization/en.lproj
|
||||||
|
store/apple/en
|
||||||
|
store/google/en
|
||||||
|
|
2
.github/workflows/crowdin-pull.yml
vendored
2
.github/workflows/crowdin-pull.yml
vendored
|
@ -24,7 +24,7 @@ jobs:
|
||||||
|
|
||||||
- name: Retrieve secrets
|
- name: Retrieve secrets
|
||||||
id: retrieve-secrets
|
id: retrieve-secrets
|
||||||
uses: bitwarden/gh-actions/get-keyvault-secrets@4a7ddc1b38ca5cb4e3e43578f4df5cabe4f55a67
|
uses: bitwarden/gh-actions/get-keyvault-secrets@main
|
||||||
with:
|
with:
|
||||||
keyvault: "bitwarden-ci"
|
keyvault: "bitwarden-ci"
|
||||||
secrets: "crowdin-api-token, github-gpg-private-key, github-gpg-private-key-passphrase"
|
secrets: "crowdin-api-token, github-gpg-private-key, github-gpg-private-key-passphrase"
|
||||||
|
|
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
|
@ -42,7 +42,7 @@ jobs:
|
||||||
|
|
||||||
- name: Check Release Version
|
- name: Check Release Version
|
||||||
id: version
|
id: version
|
||||||
uses: bitwarden/gh-actions/release-version-check@4a7ddc1b38ca5cb4e3e43578f4df5cabe4f55a67
|
uses: bitwarden/gh-actions/release-version-check@main
|
||||||
with:
|
with:
|
||||||
release-type: ${{ github.event.inputs.release_type }}
|
release-type: ${{ github.event.inputs.release_type }}
|
||||||
project-type: xamarin
|
project-type: xamarin
|
||||||
|
|
12
.github/workflows/version-bump.yml
vendored
12
.github/workflows/version-bump.yml
vendored
|
@ -28,7 +28,7 @@ jobs:
|
||||||
|
|
||||||
- name: Retrieve secrets
|
- name: Retrieve secrets
|
||||||
id: retrieve-secrets
|
id: retrieve-secrets
|
||||||
uses: bitwarden/gh-actions/get-keyvault-secrets@4a7ddc1b38ca5cb4e3e43578f4df5cabe4f55a67
|
uses: bitwarden/gh-actions/get-keyvault-secrets@main
|
||||||
with:
|
with:
|
||||||
keyvault: "bitwarden-ci"
|
keyvault: "bitwarden-ci"
|
||||||
secrets: "github-gpg-private-key, github-gpg-private-key-passphrase"
|
secrets: "github-gpg-private-key, github-gpg-private-key-passphrase"
|
||||||
|
@ -45,31 +45,31 @@ jobs:
|
||||||
run: git switch -c version_bump_${{ github.event.inputs.version_number }}
|
run: git switch -c version_bump_${{ github.event.inputs.version_number }}
|
||||||
|
|
||||||
- name: Bump Version - Android XML
|
- name: Bump Version - Android XML
|
||||||
uses: bitwarden/gh-actions/version-bump@4a7ddc1b38ca5cb4e3e43578f4df5cabe4f55a67
|
uses: bitwarden/gh-actions/version-bump@main
|
||||||
with:
|
with:
|
||||||
version: ${{ github.event.inputs.version_number }}
|
version: ${{ github.event.inputs.version_number }}
|
||||||
file_path: "./src/Android/Properties/AndroidManifest.xml"
|
file_path: "./src/Android/Properties/AndroidManifest.xml"
|
||||||
|
|
||||||
- name: Bump Version - iOS.Autofill
|
- name: Bump Version - iOS.Autofill
|
||||||
uses: bitwarden/gh-actions/version-bump@4a7ddc1b38ca5cb4e3e43578f4df5cabe4f55a67
|
uses: bitwarden/gh-actions/version-bump@main
|
||||||
with:
|
with:
|
||||||
version: ${{ github.event.inputs.version_number }}
|
version: ${{ github.event.inputs.version_number }}
|
||||||
file_path: "./src/iOS.Autofill/Info.plist"
|
file_path: "./src/iOS.Autofill/Info.plist"
|
||||||
|
|
||||||
- name: Bump Version - iOS.Extension
|
- name: Bump Version - iOS.Extension
|
||||||
uses: bitwarden/gh-actions/version-bump@4a7ddc1b38ca5cb4e3e43578f4df5cabe4f55a67
|
uses: bitwarden/gh-actions/version-bump@main
|
||||||
with:
|
with:
|
||||||
version: ${{ github.event.inputs.version_number }}
|
version: ${{ github.event.inputs.version_number }}
|
||||||
file_path: "./src/iOS.Extension/Info.plist"
|
file_path: "./src/iOS.Extension/Info.plist"
|
||||||
|
|
||||||
- name: Bump Version - iOS.ShareExtension
|
- name: Bump Version - iOS.ShareExtension
|
||||||
uses: bitwarden/gh-actions/version-bump@4a7ddc1b38ca5cb4e3e43578f4df5cabe4f55a67
|
uses: bitwarden/gh-actions/version-bump@main
|
||||||
with:
|
with:
|
||||||
version: ${{ github.event.inputs.version_number }}
|
version: ${{ github.event.inputs.version_number }}
|
||||||
file_path: "./src/iOS.ShareExtension/Info.plist"
|
file_path: "./src/iOS.ShareExtension/Info.plist"
|
||||||
|
|
||||||
- name: Bump Version - iOS
|
- name: Bump Version - iOS
|
||||||
uses: bitwarden/gh-actions/version-bump@4a7ddc1b38ca5cb4e3e43578f4df5cabe4f55a67
|
uses: bitwarden/gh-actions/version-bump@main
|
||||||
with:
|
with:
|
||||||
version: ${{ github.event.inputs.version_number }}
|
version: ${{ github.event.inputs.version_number }}
|
||||||
file_path: "./src/iOS/Info.plist"
|
file_path: "./src/iOS/Info.plist"
|
||||||
|
|
2
.github/workflows/workflow-linter.yml
vendored
2
.github/workflows/workflow-linter.yml
vendored
|
@ -8,4 +8,4 @@ on:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
call-workflow:
|
call-workflow:
|
||||||
uses: bitwarden/gh-actions/.github/workflows/workflow-linter.yml@4a7ddc1b38ca5cb4e3e43578f4df5cabe4f55a67
|
uses: bitwarden/gh-actions/.github/workflows/workflow-linter.yml@main
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net;
|
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
using Bit.Core.Models.Domain;
|
using Bit.Core.Models.Data;
|
||||||
using Bit.Core.Models.Request;
|
using Bit.Core.Models.Request;
|
||||||
using Bit.Core.Models.Response;
|
using Bit.Core.Models.Response;
|
||||||
using DeviceType = Bit.Core.Enums.DeviceType;
|
using DeviceType = Bit.Core.Enums.DeviceType;
|
||||||
|
@ -52,7 +51,7 @@ namespace Bit.Core.Abstractions
|
||||||
Task<TResponse> SendAsync<TRequest, TResponse>(HttpMethod method, string path,
|
Task<TResponse> SendAsync<TRequest, TResponse>(HttpMethod method, string path,
|
||||||
TRequest body, bool authed, bool hasResponse, Action<HttpRequestMessage> alterRequest, bool logoutOnUnauthorized = true, bool sendToIdentity = false);
|
TRequest body, bool authed, bool hasResponse, Action<HttpRequestMessage> alterRequest, bool logoutOnUnauthorized = true, bool sendToIdentity = false);
|
||||||
Task<HttpResponseMessage> SendAsync(HttpRequestMessage requestMessage, CancellationToken cancellationToken = default);
|
Task<HttpResponseMessage> SendAsync(HttpRequestMessage requestMessage, CancellationToken cancellationToken = default);
|
||||||
void SetUrls(EnvironmentUrls urls);
|
void SetUrls(EnvironmentUrlData urls);
|
||||||
[Obsolete("Mar 25 2021: This method has been deprecated in favor of direct uploads. This method still exists for backward compatibility with old server versions.")]
|
[Obsolete("Mar 25 2021: This method has been deprecated in favor of direct uploads. This method still exists for backward compatibility with old server versions.")]
|
||||||
Task<CipherResponse> PostCipherAttachmentLegacyAsync(string id, MultipartFormDataContent data);
|
Task<CipherResponse> PostCipherAttachmentLegacyAsync(string id, MultipartFormDataContent data);
|
||||||
Task<AttachmentUploadDataResponse> PostCipherAttachmentAsync(string id, AttachmentRequest request);
|
Task<AttachmentUploadDataResponse> PostCipherAttachmentAsync(string id, AttachmentRequest request);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
using System.Threading.Tasks;
|
using Bit.Core.Models.Data;
|
||||||
using Bit.Core.Models.Data;
|
using BwRegion = Bit.Core.Enums.Region;
|
||||||
|
|
||||||
namespace Bit.Core.Abstractions
|
namespace Bit.Core.Abstractions
|
||||||
{
|
{
|
||||||
|
@ -12,10 +12,12 @@ namespace Bit.Core.Abstractions
|
||||||
string NotificationsUrl { get; set; }
|
string NotificationsUrl { get; set; }
|
||||||
string WebVaultUrl { get; set; }
|
string WebVaultUrl { get; set; }
|
||||||
string EventsUrl { get; set; }
|
string EventsUrl { get; set; }
|
||||||
|
BwRegion SelectedRegion { get; set; }
|
||||||
|
|
||||||
string GetWebVaultUrl(bool returnNullIfDefault = false);
|
string GetWebVaultUrl(bool returnNullIfDefault = false);
|
||||||
string GetWebSendUrl();
|
string GetWebSendUrl();
|
||||||
Task<EnvironmentUrlData> SetUrlsAsync(EnvironmentUrlData urls);
|
string GetCurrentDomain();
|
||||||
Task SetUrlsFromStorageAsync();
|
Task SetUrlsFromStorageAsync();
|
||||||
|
Task<EnvironmentUrlData> SetRegionAsync(BwRegion region, EnvironmentUrlData selfHostedUrls = null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,9 @@
|
||||||
using System;
|
using Bit.Core.Enums;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Bit.Core.Enums;
|
|
||||||
using Bit.Core.Models.Data;
|
using Bit.Core.Models.Data;
|
||||||
using Bit.Core.Models.Domain;
|
using Bit.Core.Models.Domain;
|
||||||
using Bit.Core.Models.Response;
|
using Bit.Core.Models.Response;
|
||||||
using Bit.Core.Models.View;
|
using Bit.Core.Models.View;
|
||||||
using Bit.Core.Services;
|
using BwRegion = Bit.Core.Enums.Region;
|
||||||
|
|
||||||
namespace Bit.Core.Abstractions
|
namespace Bit.Core.Abstractions
|
||||||
{
|
{
|
||||||
|
@ -185,6 +182,10 @@ namespace Bit.Core.Abstractions
|
||||||
void SetConfigs(ConfigResponse value);
|
void SetConfigs(ConfigResponse value);
|
||||||
Task<bool> GetShouldTrustDeviceAsync();
|
Task<bool> GetShouldTrustDeviceAsync();
|
||||||
Task SetShouldTrustDeviceAsync(bool value);
|
Task SetShouldTrustDeviceAsync(bool value);
|
||||||
|
Task SetUserHasMasterPasswordAsync(bool value, string userId = null);
|
||||||
|
Task<BwRegion?> GetActiveUserRegionAsync();
|
||||||
|
Task<BwRegion?> GetPreAuthRegionAsync();
|
||||||
|
Task SetPreAuthRegionAsync(BwRegion value);
|
||||||
[Obsolete("Use GetPinKeyEncryptedUserKeyAsync instead, left for migration purposes")]
|
[Obsolete("Use GetPinKeyEncryptedUserKeyAsync instead, left for migration purposes")]
|
||||||
Task<string> GetPinProtectedAsync(string userId = null);
|
Task<string> GetPinProtectedAsync(string userId = null);
|
||||||
[Obsolete("Use SetPinKeyEncryptedUserKeyAsync instead, left for migration purposes")]
|
[Obsolete("Use SetPinKeyEncryptedUserKeyAsync instead, left for migration purposes")]
|
||||||
|
|
|
@ -178,6 +178,11 @@ namespace Bit.App
|
||||||
new NavigationPage(new UpdateTempPasswordPage()));
|
new NavigationPage(new UpdateTempPasswordPage()));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
else if (message.Command == Constants.ForceSetPassword)
|
||||||
|
{
|
||||||
|
await Device.InvokeOnMainThreadAsync(() => Application.Current.MainPage.Navigation.PushModalAsync(
|
||||||
|
new NavigationPage(new SetPasswordPage(orgIdentifier: (string)message.Data))));
|
||||||
|
}
|
||||||
else if (message.Command == "syncCompleted")
|
else if (message.Command == "syncCompleted")
|
||||||
{
|
{
|
||||||
await _configService.GetAsync(true);
|
await _configService.GetAsync(true);
|
||||||
|
|
|
@ -46,6 +46,7 @@ namespace Bit.Core
|
||||||
public const string PreLoginEmailKey = "preLoginEmailKey";
|
public const string PreLoginEmailKey = "preLoginEmailKey";
|
||||||
public const string ConfigsKey = "configsKey";
|
public const string ConfigsKey = "configsKey";
|
||||||
public const string DisplayEuEnvironmentFlag = "display-eu-environment";
|
public const string DisplayEuEnvironmentFlag = "display-eu-environment";
|
||||||
|
public const string RegionEnvironment = "regionEnvironment";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This key is used to store the value of "ShouldConnectToWatch" of the last user that had logged in
|
/// This key is used to store the value of "ShouldConnectToWatch" of the last user that had logged in
|
||||||
|
@ -56,6 +57,7 @@ namespace Bit.Core
|
||||||
public const string AppLocaleKey = "appLocale";
|
public const string AppLocaleKey = "appLocale";
|
||||||
public const string ClearSensitiveFields = "clearSensitiveFields";
|
public const string ClearSensitiveFields = "clearSensitiveFields";
|
||||||
public const string ForceUpdatePassword = "forceUpdatePassword";
|
public const string ForceUpdatePassword = "forceUpdatePassword";
|
||||||
|
public const string ForceSetPassword = "forceSetPassword";
|
||||||
public const string ShouldTrustDevice = "shouldTrustDevice";
|
public const string ShouldTrustDevice = "shouldTrustDevice";
|
||||||
public const int SelectFileRequestCode = 42;
|
public const int SelectFileRequestCode = 42;
|
||||||
public const int SelectFilePermissionRequestCode = 43;
|
public const int SelectFilePermissionRequestCode = 43;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using Bit.App.Utilities;
|
|
||||||
using Bit.Core.Abstractions;
|
using Bit.Core.Abstractions;
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
|
using CommunityToolkit.Mvvm.Input;
|
||||||
|
|
||||||
namespace Bit.App.Controls
|
namespace Bit.App.Controls
|
||||||
{
|
{
|
||||||
|
@ -37,17 +37,14 @@ namespace Bit.App.Controls
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
ToggleVisibililtyCommand = new AsyncCommand(ToggleVisibilityAsync,
|
ToggleVisibililtyCommand = new AsyncRelayCommand(ToggleVisibilityAsync,
|
||||||
onException: ex => _logger.Value.Exception(ex),
|
AsyncRelayCommandOptions.None);
|
||||||
allowsMultipleExecutions: false);
|
|
||||||
|
|
||||||
SelectAccountCommand = new AsyncCommand<AccountViewCellViewModel>(SelectAccountAsync,
|
SelectAccountCommand = new AsyncRelayCommand<AccountViewCellViewModel>(SelectAccountAsync,
|
||||||
onException: ex => _logger.Value.Exception(ex),
|
AsyncRelayCommandOptions.None);
|
||||||
allowsMultipleExecutions: false);
|
|
||||||
|
|
||||||
LongPressAccountCommand = new AsyncCommand<AccountViewCellViewModel>(LongPressAccountAsync,
|
LongPressAccountCommand = new AsyncRelayCommand<AccountViewCellViewModel>(LongPressAccountAsync,
|
||||||
onException: ex => _logger.Value.Exception(ex),
|
AsyncRelayCommandOptions.None);
|
||||||
allowsMultipleExecutions: false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public AccountSwitchingOverlayViewModel ViewModel => BindingContext as AccountSwitchingOverlayViewModel;
|
public AccountSwitchingOverlayViewModel ViewModel => BindingContext as AccountSwitchingOverlayViewModel;
|
||||||
|
@ -70,13 +67,20 @@ namespace Bit.App.Controls
|
||||||
|
|
||||||
public async Task ToggleVisibilityAsync()
|
public async Task ToggleVisibilityAsync()
|
||||||
{
|
{
|
||||||
if (IsVisible)
|
try
|
||||||
{
|
{
|
||||||
await HideAsync();
|
if (IsVisible)
|
||||||
|
{
|
||||||
|
await HideAsync();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await ShowAsync();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
await ShowAsync();
|
_logger.Value.Exception(ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,12 +176,13 @@ namespace Bit.App.Controls
|
||||||
|
|
||||||
private async Task LongPressAccountAsync(AccountViewCellViewModel item)
|
private async Task LongPressAccountAsync(AccountViewCellViewModel item)
|
||||||
{
|
{
|
||||||
if (!LongPressAccountEnabled || item == null || !item.IsAccount)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
if (!LongPressAccountEnabled || item == null || !item.IsAccount)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
await Task.Delay(100);
|
await Task.Delay(100);
|
||||||
await HideAsync();
|
await HideAsync();
|
||||||
|
|
||||||
|
|
|
@ -17,11 +17,11 @@ namespace Bit.App.Controls
|
||||||
_stateService = stateService;
|
_stateService = stateService;
|
||||||
_messagingService = messagingService;
|
_messagingService = messagingService;
|
||||||
|
|
||||||
SelectAccountCommand = new AsyncCommand<AccountViewCellViewModel>(SelectAccountAsync,
|
SelectAccountCommand = CreateDefaultAsyncRelayCommand<AccountViewCellViewModel>(SelectAccountAsync,
|
||||||
onException: ex => logger.Exception(ex),
|
onException: ex => logger.Exception(ex),
|
||||||
allowsMultipleExecutions: false);
|
allowsMultipleExecutions: false);
|
||||||
|
|
||||||
LongPressAccountCommand = new AsyncCommand<Tuple<ContentPage, AccountViewCellViewModel>>(LongPressAccountAsync,
|
LongPressAccountCommand = CreateDefaultAsyncRelayCommand<Tuple<ContentPage, AccountViewCellViewModel>>(LongPressAccountAsync,
|
||||||
onException: ex => logger.Exception(ex),
|
onException: ex => logger.Exception(ex),
|
||||||
allowsMultipleExecutions: false);
|
allowsMultipleExecutions: false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,10 +6,10 @@ namespace Bit.App.Controls
|
||||||
public class BaseSettingItemView : ContentView
|
public class BaseSettingItemView : ContentView
|
||||||
{
|
{
|
||||||
public static readonly BindableProperty TitleProperty = BindableProperty.Create(
|
public static readonly BindableProperty TitleProperty = BindableProperty.Create(
|
||||||
nameof(Title), typeof(string), typeof(SwitchItemView), null, BindingMode.OneWay);
|
nameof(Title), typeof(string), typeof(SwitchItemView), null);
|
||||||
|
|
||||||
public static readonly BindableProperty SubtitleProperty = BindableProperty.Create(
|
public static readonly BindableProperty SubtitleProperty = BindableProperty.Create(
|
||||||
nameof(Subtitle), typeof(string), typeof(SwitchItemView), null, BindingMode.OneWay);
|
nameof(Subtitle), typeof(string), typeof(SwitchItemView), null);
|
||||||
|
|
||||||
public string Title
|
public string Title
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,7 +7,7 @@ namespace Bit.App.Controls
|
||||||
public partial class SettingChooserItemView : BaseSettingItemView
|
public partial class SettingChooserItemView : BaseSettingItemView
|
||||||
{
|
{
|
||||||
public static readonly BindableProperty DisplayValueProperty = BindableProperty.Create(
|
public static readonly BindableProperty DisplayValueProperty = BindableProperty.Create(
|
||||||
nameof(DisplayValue), typeof(string), typeof(SettingChooserItemView), null, BindingMode.OneWay);
|
nameof(DisplayValue), typeof(string), typeof(SettingChooserItemView), null);
|
||||||
|
|
||||||
public static readonly BindableProperty ChooseCommandProperty = BindableProperty.Create(
|
public static readonly BindableProperty ChooseCommandProperty = BindableProperty.Create(
|
||||||
nameof(ChooseCommand), typeof(ICommand), typeof(ExternalLinkItemView));
|
nameof(ChooseCommand), typeof(ICommand), typeof(ExternalLinkItemView));
|
||||||
|
|
10
src/Core/Enums/Region.cs
Normal file
10
src/Core/Enums/Region.cs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
namespace Bit.Core.Enums
|
||||||
|
{
|
||||||
|
public enum Region
|
||||||
|
{
|
||||||
|
US,
|
||||||
|
EU,
|
||||||
|
SelfHosted
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ namespace Bit.App.Lists.ItemViewModels.CustomFields
|
||||||
_eventService = eventService;
|
_eventService = eventService;
|
||||||
|
|
||||||
CopyFieldCommand = new Command(() => copyFieldCommand?.Execute(Field));
|
CopyFieldCommand = new Command(() => copyFieldCommand?.Execute(Field));
|
||||||
ToggleHiddenValueCommand = new AsyncCommand(ToggleHiddenValueAsync, null, ex =>
|
ToggleHiddenValueCommand = CreateDefaultAsyncRelayCommand(ToggleHiddenValueAsync, null, ex =>
|
||||||
{
|
{
|
||||||
//#if !FDROID
|
//#if !FDROID
|
||||||
// Microsoft.AppCenter.Crashes.Crashes.TrackError(ex);
|
// Microsoft.AppCenter.Crashes.Crashes.TrackError(ex);
|
||||||
|
|
|
@ -1,9 +1,34 @@
|
||||||
namespace Bit.Core.Models.Data
|
using System.Text.RegularExpressions;
|
||||||
|
using Bit.Core.Utilities;
|
||||||
|
using BwRegion = Bit.Core.Enums.Region;
|
||||||
|
|
||||||
|
namespace Bit.Core.Models.Data
|
||||||
{
|
{
|
||||||
public class EnvironmentUrlData
|
public class EnvironmentUrlData
|
||||||
{
|
{
|
||||||
public static EnvironmentUrlData DefaultUS = new EnvironmentUrlData { Base = "https://vault.bitwarden.com" };
|
public static EnvironmentUrlData DefaultUS = new EnvironmentUrlData
|
||||||
public static EnvironmentUrlData DefaultEU = new EnvironmentUrlData { Base = "https://vault.bitwarden.eu" };
|
{
|
||||||
|
Base = "https://vault.bitwarden.com",
|
||||||
|
Api = "https://api.bitwarden.com",
|
||||||
|
Identity = "https://identity.bitwarden.com",
|
||||||
|
Icons = "https://icons.bitwarden.net",
|
||||||
|
WebVault = "https://vault.bitwarden.com",
|
||||||
|
Notifications = "https://notifications.bitwarden.com",
|
||||||
|
Events = "https://events.bitwarden.com",
|
||||||
|
Domain = "bitwarden.com"
|
||||||
|
};
|
||||||
|
|
||||||
|
public static EnvironmentUrlData DefaultEU = new EnvironmentUrlData
|
||||||
|
{
|
||||||
|
Base = "https://vault.bitwarden.eu",
|
||||||
|
Api = "https://api.bitwarden.eu",
|
||||||
|
Identity = "https://identity.bitwarden.eu",
|
||||||
|
Icons = "https://icons.bitwarden.eu",
|
||||||
|
WebVault = "https://vault.bitwarden.eu",
|
||||||
|
Notifications = "https://notifications.bitwarden.eu",
|
||||||
|
Events = "https://events.bitwarden.eu",
|
||||||
|
Domain = "bitwarden.eu"
|
||||||
|
};
|
||||||
|
|
||||||
public string Base { get; set; }
|
public string Base { get; set; }
|
||||||
public string Api { get; set; }
|
public string Api { get; set; }
|
||||||
|
@ -12,6 +37,7 @@
|
||||||
public string Notifications { get; set; }
|
public string Notifications { get; set; }
|
||||||
public string WebVault { get; set; }
|
public string WebVault { get; set; }
|
||||||
public string Events { get; set; }
|
public string Events { get; set; }
|
||||||
|
public string Domain { get; set; }
|
||||||
|
|
||||||
public bool IsEmpty => string.IsNullOrEmpty(Base)
|
public bool IsEmpty => string.IsNullOrEmpty(Base)
|
||||||
&& string.IsNullOrEmpty(Api)
|
&& string.IsNullOrEmpty(Api)
|
||||||
|
@ -20,5 +46,63 @@
|
||||||
&& string.IsNullOrEmpty(Notifications)
|
&& string.IsNullOrEmpty(Notifications)
|
||||||
&& string.IsNullOrEmpty(WebVault)
|
&& string.IsNullOrEmpty(WebVault)
|
||||||
&& string.IsNullOrEmpty(Events);
|
&& string.IsNullOrEmpty(Events);
|
||||||
|
|
||||||
|
public BwRegion Region
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (Base == BwRegion.US.BaseUrl())
|
||||||
|
{
|
||||||
|
return BwRegion.US;
|
||||||
|
}
|
||||||
|
if (Base == BwRegion.EU.BaseUrl())
|
||||||
|
{
|
||||||
|
return BwRegion.EU;
|
||||||
|
}
|
||||||
|
return BwRegion.SelfHosted;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public EnvironmentUrlData FormatUrls()
|
||||||
|
{
|
||||||
|
return new EnvironmentUrlData
|
||||||
|
{
|
||||||
|
Base = FormatUrl(Base),
|
||||||
|
Api = FormatUrl(Api),
|
||||||
|
Identity = FormatUrl(Identity),
|
||||||
|
Icons = FormatUrl(Icons),
|
||||||
|
Notifications = FormatUrl(Notifications),
|
||||||
|
WebVault = FormatUrl(WebVault),
|
||||||
|
Events = FormatUrl(Events)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private string FormatUrl(string url)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(url))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
url = Regex.Replace(url, "\\/+$", string.Empty);
|
||||||
|
if (!url.StartsWith("http://") && !url.StartsWith("https://"))
|
||||||
|
{
|
||||||
|
url = string.Concat("https://", url);
|
||||||
|
}
|
||||||
|
return url.Trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetDomainOrHostname()
|
||||||
|
{
|
||||||
|
var url = WebVault ?? Base ?? Api ?? Identity;
|
||||||
|
if (string.IsNullOrWhiteSpace(url))
|
||||||
|
{
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
if (url.Contains(BwRegion.US.Domain()) || url.Contains(BwRegion.EU.Domain()))
|
||||||
|
{
|
||||||
|
return CoreHelpers.GetDomain(url);
|
||||||
|
}
|
||||||
|
return CoreHelpers.GetHostname(url);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,5 +15,6 @@
|
||||||
public bool ManagePolicies { get; set; }
|
public bool ManagePolicies { get; set; }
|
||||||
public bool ManageSso { get; set; }
|
public bool ManageSso { get; set; }
|
||||||
public bool ManageUsers { get; set; }
|
public bool ManageUsers { get; set; }
|
||||||
|
public bool ManageResetPassword { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
using System;
|
using Bit.Core.Enums;
|
||||||
using Bit.Core.Enums;
|
|
||||||
using Bit.Core.Models.Data;
|
using Bit.Core.Models.Data;
|
||||||
|
using BwRegion = Bit.Core.Enums.Region;
|
||||||
|
|
||||||
namespace Bit.Core.Models.Domain
|
namespace Bit.Core.Models.Domain
|
||||||
{
|
{
|
||||||
|
@ -102,12 +102,14 @@ namespace Bit.Core.Models.Domain
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Region = copy.Region;
|
||||||
EnvironmentUrls = copy.EnvironmentUrls;
|
EnvironmentUrls = copy.EnvironmentUrls;
|
||||||
VaultTimeout = copy.VaultTimeout;
|
VaultTimeout = copy.VaultTimeout;
|
||||||
VaultTimeoutAction = copy.VaultTimeoutAction;
|
VaultTimeoutAction = copy.VaultTimeoutAction;
|
||||||
ScreenCaptureAllowed = copy.ScreenCaptureAllowed;
|
ScreenCaptureAllowed = copy.ScreenCaptureAllowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BwRegion? Region;
|
||||||
public EnvironmentUrlData EnvironmentUrls;
|
public EnvironmentUrlData EnvironmentUrls;
|
||||||
[Obsolete("Feb 10 2023: VaultTimeout has been deprecated in favor of stored prefs to retain value after logout. It remains here to allow for migration during app upgrade.")]
|
[Obsolete("Feb 10 2023: VaultTimeout has been deprecated in favor of stored prefs to retain value after logout. It remains here to allow for migration during app upgrade.")]
|
||||||
public int? VaultTimeout;
|
public int? VaultTimeout;
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
namespace Bit.Core.Models.Domain
|
|
||||||
{
|
|
||||||
public class EnvironmentUrls
|
|
||||||
{
|
|
||||||
public string Base { get; set; }
|
|
||||||
public string Api { get; set; }
|
|
||||||
public string Identity { get; set; }
|
|
||||||
public string Events { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -11,6 +11,12 @@
|
||||||
/// Occurs when a user logs in with a master password that does not meet an organization's master password
|
/// Occurs when a user logs in with a master password that does not meet an organization's master password
|
||||||
/// policy that is enforced on login.
|
/// policy that is enforced on login.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
WeakMasterPasswordOnLogin
|
WeakMasterPasswordOnLogin,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Occurs when a TDE user without a password obtains the password reset permission.
|
||||||
|
/// Set post login & decryption client side and by server in sync (to catch logged in users).
|
||||||
|
/// </summary>
|
||||||
|
TdeUserWithoutPasswordHasPasswordResetPermission,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,11 @@ namespace Bit.Core.Models.Domain
|
||||||
case ForwardedEmailServiceType.DuckDuckGo:
|
case ForwardedEmailServiceType.DuckDuckGo:
|
||||||
return new ForwarderOptions { ApiKey = DuckDuckGoApiKey };
|
return new ForwarderOptions { ApiKey = DuckDuckGoApiKey };
|
||||||
case ForwardedEmailServiceType.Fastmail:
|
case ForwardedEmailServiceType.Fastmail:
|
||||||
return new ForwarderOptions { ApiKey = FastMailApiKey };
|
return new FastmailForwarderOptions
|
||||||
|
{
|
||||||
|
ApiKey = FastMailApiKey,
|
||||||
|
Website = EmailWebsite
|
||||||
|
};
|
||||||
case ForwardedEmailServiceType.FirefoxRelay:
|
case ForwardedEmailServiceType.FirefoxRelay:
|
||||||
return new ForwarderOptions { ApiKey = FirefoxRelayApiAccessToken };
|
return new ForwarderOptions { ApiKey = FirefoxRelayApiAccessToken };
|
||||||
case ForwardedEmailServiceType.SimpleLogin:
|
case ForwardedEmailServiceType.SimpleLogin:
|
||||||
|
|
|
@ -7,7 +7,7 @@ namespace Bit.Core.Models.Request
|
||||||
public string MasterPasswordHash { get; set; }
|
public string MasterPasswordHash { get; set; }
|
||||||
public string Key { get; set; }
|
public string Key { get; set; }
|
||||||
public string MasterPasswordHint { get; set; }
|
public string MasterPasswordHint { get; set; }
|
||||||
public KeysRequest Keys { get; set; }
|
public KeysRequest? Keys { get; set; }
|
||||||
public KdfType Kdf { get; set; }
|
public KdfType Kdf { get; set; }
|
||||||
public int KdfIterations { get; set; }
|
public int KdfIterations { get; set; }
|
||||||
public int? KdfMemory { get; set; }
|
public int? KdfMemory { get; set; }
|
||||||
|
|
|
@ -20,5 +20,6 @@ namespace Bit.Core.Models.Response
|
||||||
public List<ProfileOrganizationResponse> Organizations { get; set; }
|
public List<ProfileOrganizationResponse> Organizations { get; set; }
|
||||||
public bool UsesKeyConnector { get; set; }
|
public bool UsesKeyConnector { get; set; }
|
||||||
public string AvatarColor { get; set; }
|
public string AvatarColor { get; set; }
|
||||||
|
public bool HasManageResetPasswordPermission { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,21 +22,7 @@ namespace Bit.Core.Models.View
|
||||||
Email = a.Profile?.Email;
|
Email = a.Profile?.Email;
|
||||||
Name = a.Profile?.Name;
|
Name = a.Profile?.Name;
|
||||||
AvatarColor = a.Profile?.AvatarColor;
|
AvatarColor = a.Profile?.AvatarColor;
|
||||||
Hostname = ParseEndpoint(a.Settings?.EnvironmentUrls);
|
Hostname = a.Settings?.EnvironmentUrls?.GetDomainOrHostname();
|
||||||
}
|
|
||||||
|
|
||||||
private string ParseEndpoint(EnvironmentUrlData urls)
|
|
||||||
{
|
|
||||||
var url = urls?.WebVault ?? urls?.Base;
|
|
||||||
if (!string.IsNullOrWhiteSpace(url))
|
|
||||||
{
|
|
||||||
if (url.Contains("bitwarden.com") || url.Contains("bitwarden.eu"))
|
|
||||||
{
|
|
||||||
return CoreHelpers.GetDomain(url);
|
|
||||||
}
|
|
||||||
return CoreHelpers.GetHostname(url);
|
|
||||||
}
|
|
||||||
return string.Empty;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsAccount { get; set; }
|
public bool IsAccount { get; set; }
|
||||||
|
|
|
@ -1,11 +1,8 @@
|
||||||
using System;
|
using System.Windows.Input;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows.Input;
|
|
||||||
using Bit.Core.Resources.Localization;
|
using Bit.Core.Resources.Localization;
|
||||||
using Bit.Core.Abstractions;
|
using Bit.Core.Abstractions;
|
||||||
using Bit.Core.Models.Data;
|
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
using Bit.App.Utilities;
|
using BwRegion = Bit.Core.Enums.Region;
|
||||||
|
|
||||||
namespace Bit.App.Pages
|
namespace Bit.App.Pages
|
||||||
{
|
{
|
||||||
|
@ -19,14 +16,25 @@ namespace Bit.App.Pages
|
||||||
_environmentService = ServiceContainer.Resolve<IEnvironmentService>("environmentService");
|
_environmentService = ServiceContainer.Resolve<IEnvironmentService>("environmentService");
|
||||||
|
|
||||||
PageTitle = AppResources.Settings;
|
PageTitle = AppResources.Settings;
|
||||||
BaseUrl = _environmentService.BaseUrl == EnvironmentUrlData.DefaultEU.Base || EnvironmentUrlData.DefaultUS.Base == _environmentService.BaseUrl ?
|
SubmitCommand = CreateDefaultAsyncRelayCommand(SubmitAsync, onException: OnSubmitException, allowsMultipleExecutions: false);
|
||||||
string.Empty : _environmentService.BaseUrl;
|
Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Init()
|
||||||
|
{
|
||||||
|
if (_environmentService.SelectedRegion != BwRegion.SelfHosted ||
|
||||||
|
_environmentService.BaseUrl == BwRegion.US.BaseUrl() ||
|
||||||
|
_environmentService.BaseUrl == BwRegion.EU.BaseUrl())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseUrl = _environmentService.BaseUrl;
|
||||||
WebVaultUrl = _environmentService.WebVaultUrl;
|
WebVaultUrl = _environmentService.WebVaultUrl;
|
||||||
ApiUrl = _environmentService.ApiUrl;
|
ApiUrl = _environmentService.ApiUrl;
|
||||||
IdentityUrl = _environmentService.IdentityUrl;
|
IdentityUrl = _environmentService.IdentityUrl;
|
||||||
IconsUrl = _environmentService.IconsUrl;
|
IconsUrl = _environmentService.IconsUrl;
|
||||||
NotificationsUrls = _environmentService.NotificationsUrl;
|
NotificationsUrls = _environmentService.NotificationsUrl;
|
||||||
SubmitCommand = new AsyncCommand(SubmitAsync, onException: ex => OnSubmitException(ex), allowsMultipleExecutions: false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ICommand SubmitCommand { get; }
|
public ICommand SubmitCommand { get; }
|
||||||
|
@ -46,8 +54,7 @@ namespace Bit.App.Pages
|
||||||
await Page.DisplayAlert(AppResources.AnErrorHasOccurred, AppResources.EnvironmentPageUrlsError, AppResources.Ok);
|
await Page.DisplayAlert(AppResources.AnErrorHasOccurred, AppResources.EnvironmentPageUrlsError, AppResources.Ok);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
var urls = new Core.Models.Data.EnvironmentUrlData
|
||||||
var resUrls = await _environmentService.SetUrlsAsync(new Core.Models.Data.EnvironmentUrlData
|
|
||||||
{
|
{
|
||||||
Base = BaseUrl,
|
Base = BaseUrl,
|
||||||
Api = ApiUrl,
|
Api = ApiUrl,
|
||||||
|
@ -55,7 +62,8 @@ namespace Bit.App.Pages
|
||||||
WebVault = WebVaultUrl,
|
WebVault = WebVaultUrl,
|
||||||
Icons = IconsUrl,
|
Icons = IconsUrl,
|
||||||
Notifications = NotificationsUrls
|
Notifications = NotificationsUrls
|
||||||
});
|
};
|
||||||
|
var resUrls = await _environmentService.SetRegionAsync(urls.Region, urls);
|
||||||
|
|
||||||
// re-set urls since service can change them, ex: prefixing https://
|
// re-set urls since service can change them, ex: prefixing https://
|
||||||
BaseUrl = resUrls.Base;
|
BaseUrl = resUrls.Base;
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
using System.Threading.Tasks;
|
using System.Windows.Input;
|
||||||
using System.Windows.Input;
|
|
||||||
using Bit.App.Abstractions;
|
using Bit.App.Abstractions;
|
||||||
using Bit.Core.Resources.Localization;
|
using Bit.Core.Resources.Localization;
|
||||||
using Bit.Core.Abstractions;
|
using Bit.Core.Abstractions;
|
||||||
using Bit.Core.Exceptions;
|
using Bit.Core.Exceptions;
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
using Bit.App.Utilities;
|
|
||||||
|
|
||||||
namespace Bit.App.Pages
|
namespace Bit.App.Pages
|
||||||
{
|
{
|
||||||
|
@ -25,7 +23,7 @@ namespace Bit.App.Pages
|
||||||
_logger = ServiceContainer.Resolve<ILogger>();
|
_logger = ServiceContainer.Resolve<ILogger>();
|
||||||
|
|
||||||
PageTitle = AppResources.PasswordHint;
|
PageTitle = AppResources.PasswordHint;
|
||||||
SubmitCommand = new AsyncCommand(SubmitAsync,
|
SubmitCommand = CreateDefaultAsyncRelayCommand(SubmitAsync,
|
||||||
onException: ex =>
|
onException: ex =>
|
||||||
{
|
{
|
||||||
_logger.Exception(ex);
|
_logger.Exception(ex);
|
||||||
|
|
|
@ -58,7 +58,6 @@ namespace Bit.App.Pages
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_accountAvatar?.OnAppearing();
|
_accountAvatar?.OnAppearing();
|
||||||
|
|
||||||
if (!_appOptions?.HideAccountSwitcher ?? false)
|
if (!_appOptions?.HideAccountSwitcher ?? false)
|
||||||
{
|
{
|
||||||
await MainThread.InvokeOnMainThreadAsync(async () => _vm.AvatarImageSource = await GetAvatarImageSourceAsync(false));
|
await MainThread.InvokeOnMainThreadAsync(async () => _vm.AvatarImageSource = await GetAvatarImageSourceAsync(false));
|
||||||
|
@ -71,14 +70,14 @@ namespace Bit.App.Pages
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
await _vm.UpdateEnvironment();
|
await _vm.UpdateEnvironmentAsync();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.Value?.Exception(ex);
|
_logger.Value?.Exception(ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnNavigatingFrom(NavigatingFromEventArgs args)
|
protected override void OnNavigatingFrom(NavigatingFromEventArgs args)
|
||||||
{
|
{
|
||||||
base.OnNavigatingFrom(args);
|
base.OnNavigatingFrom(args);
|
||||||
|
@ -89,7 +88,7 @@ namespace Bit.App.Pages
|
||||||
|
|
||||||
protected override bool OnBackButtonPressed()
|
protected override bool OnBackButtonPressed()
|
||||||
{
|
{
|
||||||
if (_accountListOverlay.IsVisible)
|
if (_accountListOverlay.IsVisible)
|
||||||
{
|
{
|
||||||
_accountListOverlay.HideAsync().FireAndForget();
|
_accountListOverlay.HideAsync().FireAndForget();
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -1,23 +1,17 @@
|
||||||
using System;
|
using Bit.App.Abstractions;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Bit.App.Abstractions;
|
|
||||||
using Bit.App.Controls;
|
using Bit.App.Controls;
|
||||||
using Bit.Core.Resources.Localization;
|
using Bit.Core.Resources.Localization;
|
||||||
using Bit.App.Utilities;
|
using Bit.App.Utilities;
|
||||||
using Bit.Core;
|
using Bit.Core;
|
||||||
using Bit.Core.Abstractions;
|
using Bit.Core.Abstractions;
|
||||||
using Bit.Core.Models.Data;
|
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
|
using BwRegion = Bit.Core.Enums.Region;
|
||||||
using Microsoft.Maui.Controls;
|
using CommunityToolkit.Mvvm.Input;
|
||||||
using Microsoft.Maui;
|
|
||||||
|
|
||||||
namespace Bit.App.Pages
|
namespace Bit.App.Pages
|
||||||
{
|
{
|
||||||
public class HomeViewModel : BaseViewModel
|
public class HomeViewModel : BaseViewModel
|
||||||
{
|
{
|
||||||
private const string LOGGING_IN_ON_US = "bitwarden.com";
|
|
||||||
private const string LOGGING_IN_ON_EU = "bitwarden.eu";
|
|
||||||
|
|
||||||
private readonly IStateService _stateService;
|
private readonly IStateService _stateService;
|
||||||
private readonly IMessagingService _messagingService;
|
private readonly IMessagingService _messagingService;
|
||||||
|
@ -50,12 +44,12 @@ namespace Bit.App.Pages
|
||||||
AllowActiveAccountSelection = true
|
AllowActiveAccountSelection = true
|
||||||
};
|
};
|
||||||
RememberEmailCommand = new Command(() => RememberEmail = !RememberEmail);
|
RememberEmailCommand = new Command(() => RememberEmail = !RememberEmail);
|
||||||
ContinueCommand = new AsyncCommand(ContinueToLoginStepAsync, allowsMultipleExecutions: false);
|
ContinueCommand = CreateDefaultAsyncRelayCommand(ContinueToLoginStepAsync, allowsMultipleExecutions: false);
|
||||||
CreateAccountCommand = new AsyncCommand(async () => Device.InvokeOnMainThreadAsync(StartRegisterAction),
|
CreateAccountCommand = CreateDefaultAsyncRelayCommand(async () => Device.InvokeOnMainThreadAsync(StartRegisterAction),
|
||||||
onException: _logger.Exception, allowsMultipleExecutions: false);
|
onException: _logger.Exception, allowsMultipleExecutions: false);
|
||||||
CloseCommand = new AsyncCommand(async () => Device.InvokeOnMainThreadAsync(CloseAction),
|
CloseCommand = CreateDefaultAsyncRelayCommand(async () => Device.InvokeOnMainThreadAsync(CloseAction),
|
||||||
onException: _logger.Exception, allowsMultipleExecutions: false);
|
onException: _logger.Exception, allowsMultipleExecutions: false);
|
||||||
ShowEnvironmentPickerCommand = new AsyncCommand(ShowEnvironmentPickerAsync,
|
ShowEnvironmentPickerCommand = CreateDefaultAsyncRelayCommand(ShowEnvironmentPickerAsync,
|
||||||
onException: _logger.Exception, allowsMultipleExecutions: false);
|
onException: _logger.Exception, allowsMultipleExecutions: false);
|
||||||
InitAsync().FireAndForget();
|
InitAsync().FireAndForget();
|
||||||
}
|
}
|
||||||
|
@ -113,10 +107,10 @@ namespace Bit.App.Pages
|
||||||
public Action StartEnvironmentAction { get; set; }
|
public Action StartEnvironmentAction { get; set; }
|
||||||
public Action CloseAction { get; set; }
|
public Action CloseAction { get; set; }
|
||||||
public Command RememberEmailCommand { get; set; }
|
public Command RememberEmailCommand { get; set; }
|
||||||
public AsyncCommand ContinueCommand { get; }
|
public AsyncRelayCommand ContinueCommand { get; }
|
||||||
public AsyncCommand CloseCommand { get; }
|
public AsyncRelayCommand CloseCommand { get; }
|
||||||
public AsyncCommand CreateAccountCommand { get; }
|
public AsyncRelayCommand CreateAccountCommand { get; }
|
||||||
public AsyncCommand ShowEnvironmentPickerCommand { get; }
|
public AsyncRelayCommand ShowEnvironmentPickerCommand { get; }
|
||||||
|
|
||||||
public async Task InitAsync()
|
public async Task InitAsync()
|
||||||
{
|
{
|
||||||
|
@ -166,10 +160,10 @@ namespace Bit.App.Pages
|
||||||
{
|
{
|
||||||
_displayEuEnvironment = await _configService.GetFeatureFlagBoolAsync(Constants.DisplayEuEnvironmentFlag);
|
_displayEuEnvironment = await _configService.GetFeatureFlagBoolAsync(Constants.DisplayEuEnvironmentFlag);
|
||||||
var options = _displayEuEnvironment
|
var options = _displayEuEnvironment
|
||||||
? new string[] { LOGGING_IN_ON_US, LOGGING_IN_ON_EU, AppResources.SelfHosted }
|
? new string[] { BwRegion.US.Domain(), BwRegion.EU.Domain(), AppResources.SelfHosted }
|
||||||
: new string[] { LOGGING_IN_ON_US, AppResources.SelfHosted };
|
: new string[] { BwRegion.US.Domain(), AppResources.SelfHosted };
|
||||||
|
|
||||||
await Device.InvokeOnMainThreadAsync(async () =>
|
await MainThread.InvokeOnMainThreadAsync(async () =>
|
||||||
{
|
{
|
||||||
var result = await Page.DisplayActionSheet(AppResources.LoggingInOn, AppResources.Cancel, null, options);
|
var result = await Page.DisplayActionSheet(AppResources.LoggingInOn, AppResources.Cancel, null, options);
|
||||||
|
|
||||||
|
@ -184,35 +178,23 @@ namespace Bit.App.Pages
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await _environmentService.SetUrlsAsync(result == LOGGING_IN_ON_EU ? EnvironmentUrlData.DefaultEU : EnvironmentUrlData.DefaultUS);
|
await _environmentService.SetRegionAsync(result == BwRegion.EU.Domain() ? BwRegion.EU : BwRegion.US);
|
||||||
await _configService.GetAsync(true);
|
await _configService.GetAsync(true);
|
||||||
SelectedEnvironmentName = result;
|
SelectedEnvironmentName = result;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task UpdateEnvironment()
|
public async Task UpdateEnvironmentAsync()
|
||||||
{
|
{
|
||||||
var environmentsSaved = await _stateService.GetPreAuthEnvironmentUrlsAsync();
|
var region = _environmentService.SelectedRegion;
|
||||||
if (environmentsSaved == null || environmentsSaved.IsEmpty)
|
if (region == BwRegion.SelfHosted)
|
||||||
{
|
{
|
||||||
await _environmentService.SetUrlsAsync(EnvironmentUrlData.DefaultUS);
|
SelectedEnvironmentName = AppResources.SelfHosted;
|
||||||
environmentsSaved = EnvironmentUrlData.DefaultUS;
|
await _configService.GetAsync(true);
|
||||||
SelectedEnvironmentName = LOGGING_IN_ON_US;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (environmentsSaved.Base == EnvironmentUrlData.DefaultUS.Base)
|
|
||||||
{
|
|
||||||
SelectedEnvironmentName = LOGGING_IN_ON_US;
|
|
||||||
}
|
|
||||||
else if (environmentsSaved.Base == EnvironmentUrlData.DefaultEU.Base)
|
|
||||||
{
|
|
||||||
SelectedEnvironmentName = LOGGING_IN_ON_EU;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await _configService.GetAsync(true);
|
SelectedEnvironmentName = region.Domain();
|
||||||
SelectedEnvironmentName = AppResources.SelfHosted;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -208,13 +208,8 @@ namespace Bit.App.Pages
|
||||||
_logger.Exception(new NullReferenceException("Email not found in storage"));
|
_logger.Exception(new NullReferenceException("Email not found in storage"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var webVault = _environmentService.GetWebVaultUrl(true);
|
|
||||||
if (string.IsNullOrWhiteSpace(webVault))
|
LoggedInAsText = string.Format(AppResources.LoggedInAsOn, _email, _environmentService.GetCurrentDomain());
|
||||||
{
|
|
||||||
webVault = "https://bitwarden.com";
|
|
||||||
}
|
|
||||||
var webVaultHostname = CoreHelpers.GetHostname(webVault);
|
|
||||||
LoggedInAsText = string.Format(AppResources.LoggedInAsOn, _email, webVaultHostname);
|
|
||||||
if (PinEnabled)
|
if (PinEnabled)
|
||||||
{
|
{
|
||||||
PageTitle = AppResources.VerifyPIN;
|
PageTitle = AppResources.VerifyPIN;
|
||||||
|
|
|
@ -55,19 +55,19 @@ namespace Bit.App.Pages
|
||||||
PageTitle = AppResources.LogInInitiated;
|
PageTitle = AppResources.LogInInitiated;
|
||||||
RememberThisDevice = true;
|
RememberThisDevice = true;
|
||||||
|
|
||||||
ApproveWithMyOtherDeviceCommand = new AsyncCommand(() => SetDeviceTrustAndInvokeAsync(LogInWithDeviceAction),
|
ApproveWithMyOtherDeviceCommand = CreateDefaultAsyncRelayCommand(() => SetDeviceTrustAndInvokeAsync(LogInWithDeviceAction),
|
||||||
onException: ex => HandleException(ex),
|
onException: ex => HandleException(ex),
|
||||||
allowsMultipleExecutions: false);
|
allowsMultipleExecutions: false);
|
||||||
|
|
||||||
RequestAdminApprovalCommand = new AsyncCommand(() => SetDeviceTrustAndInvokeAsync(RequestAdminApprovalAction),
|
RequestAdminApprovalCommand = CreateDefaultAsyncRelayCommand(() => SetDeviceTrustAndInvokeAsync(RequestAdminApprovalAction),
|
||||||
onException: ex => HandleException(ex),
|
onException: ex => HandleException(ex),
|
||||||
allowsMultipleExecutions: false);
|
allowsMultipleExecutions: false);
|
||||||
|
|
||||||
ApproveWithMasterPasswordCommand = new AsyncCommand(() => SetDeviceTrustAndInvokeAsync(LogInWithMasterPasswordAction),
|
ApproveWithMasterPasswordCommand = CreateDefaultAsyncRelayCommand(() => SetDeviceTrustAndInvokeAsync(LogInWithMasterPasswordAction),
|
||||||
onException: ex => HandleException(ex),
|
onException: ex => HandleException(ex),
|
||||||
allowsMultipleExecutions: false);
|
allowsMultipleExecutions: false);
|
||||||
|
|
||||||
ContinueCommand = new AsyncCommand(CreateNewSsoUserAsync,
|
ContinueCommand = CreateDefaultAsyncRelayCommand(CreateNewSsoUserAsync,
|
||||||
onException: ex => HandleException(ex),
|
onException: ex => HandleException(ex),
|
||||||
allowsMultipleExecutions: false);
|
allowsMultipleExecutions: false);
|
||||||
|
|
||||||
|
|
|
@ -62,8 +62,8 @@ namespace Bit.App.Pages
|
||||||
PageTitle = AppResources.Bitwarden;
|
PageTitle = AppResources.Bitwarden;
|
||||||
TogglePasswordCommand = new Command(TogglePassword);
|
TogglePasswordCommand = new Command(TogglePassword);
|
||||||
LogInCommand = new Command(async () => await LogInAsync());
|
LogInCommand = new Command(async () => await LogInAsync());
|
||||||
MoreCommand = new AsyncCommand(MoreAsync, onException: _logger.Exception, allowsMultipleExecutions: false);
|
MoreCommand = CreateDefaultAsyncRelayCommand(MoreAsync, onException: _logger.Exception, allowsMultipleExecutions: false);
|
||||||
LogInWithDeviceCommand = new AsyncCommand(() => Device.InvokeOnMainThreadAsync(LogInWithDeviceAction), onException: _logger.Exception, allowsMultipleExecutions: false);
|
LogInWithDeviceCommand = CreateDefaultAsyncRelayCommand(() => MainThread.InvokeOnMainThreadAsync(LogInWithDeviceAction), onException: _logger.Exception, allowsMultipleExecutions: false);
|
||||||
|
|
||||||
AccountSwitchingOverlayViewModel = new AccountSwitchingOverlayViewModel(_stateService, _messagingService, _logger)
|
AccountSwitchingOverlayViewModel = new AccountSwitchingOverlayViewModel(_stateService, _messagingService, _logger)
|
||||||
{
|
{
|
||||||
|
@ -163,7 +163,7 @@ namespace Bit.App.Pages
|
||||||
Email = await _stateService.GetRememberedEmailAsync();
|
Email = await _stateService.GetRememberedEmailAsync();
|
||||||
}
|
}
|
||||||
CanRemoveAccount = await _stateService.GetActiveUserEmailAsync() != Email;
|
CanRemoveAccount = await _stateService.GetActiveUserEmailAsync() != Email;
|
||||||
EnvironmentDomainName = CoreHelpers.GetDomain((await _stateService.GetPreAuthEnvironmentUrlsAsync())?.Base);
|
EnvironmentDomainName = _environmentService.GetCurrentDomain();
|
||||||
IsKnownDevice = await _apiService.GetKnownDeviceAsync(Email, await _appIdService.GetAppIdAsync());
|
IsKnownDevice = await _apiService.GetKnownDeviceAsync(Email, await _appIdService.GetAppIdAsync());
|
||||||
}
|
}
|
||||||
catch (ApiException apiEx) when (apiEx.Error.StatusCode == System.Net.HttpStatusCode.Unauthorized)
|
catch (ApiException apiEx) when (apiEx.Error.StatusCode == System.Net.HttpStatusCode.Unauthorized)
|
||||||
|
|
|
@ -56,11 +56,11 @@ namespace Bit.App.Pages
|
||||||
_cryptoFunctionService = ServiceContainer.Resolve<ICryptoFunctionService>();
|
_cryptoFunctionService = ServiceContainer.Resolve<ICryptoFunctionService>();
|
||||||
_cryptoService = ServiceContainer.Resolve<ICryptoService>();
|
_cryptoService = ServiceContainer.Resolve<ICryptoService>();
|
||||||
|
|
||||||
CreatePasswordlessLoginCommand = new AsyncCommand(CreatePasswordlessLoginAsync,
|
CreatePasswordlessLoginCommand = CreateDefaultAsyncRelayCommand(CreatePasswordlessLoginAsync,
|
||||||
onException: ex => HandleException(ex),
|
onException: ex => HandleException(ex),
|
||||||
allowsMultipleExecutions: false);
|
allowsMultipleExecutions: false);
|
||||||
|
|
||||||
CloseCommand = new AsyncCommand(() => MainThread.InvokeOnMainThreadAsync(CloseAction),
|
CloseCommand = CreateDefaultAsyncRelayCommand(() => MainThread.InvokeOnMainThreadAsync(CloseAction),
|
||||||
onException: _logger.Exception,
|
onException: _logger.Exception,
|
||||||
allowsMultipleExecutions: false);
|
allowsMultipleExecutions: false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,10 +39,10 @@ namespace Bit.App.Pages
|
||||||
|
|
||||||
PageTitle = AppResources.LogInRequested;
|
PageTitle = AppResources.LogInRequested;
|
||||||
|
|
||||||
AcceptRequestCommand = new AsyncCommand(() => PasswordlessLoginAsync(true),
|
AcceptRequestCommand = CreateDefaultAsyncRelayCommand(() => PasswordlessLoginAsync(true),
|
||||||
onException: ex => HandleException(ex),
|
onException: ex => HandleException(ex),
|
||||||
allowsMultipleExecutions: false);
|
allowsMultipleExecutions: false);
|
||||||
RejectRequestCommand = new AsyncCommand(() => PasswordlessLoginAsync(false),
|
RejectRequestCommand = CreateDefaultAsyncRelayCommand(() => PasswordlessLoginAsync(false),
|
||||||
onException: ex => HandleException(ex),
|
onException: ex => HandleException(ex),
|
||||||
allowsMultipleExecutions: false);
|
allowsMultipleExecutions: false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,7 @@ namespace Bit.App.Pages
|
||||||
_cryptoService = ServiceContainer.Resolve<ICryptoService>();
|
_cryptoService = ServiceContainer.Resolve<ICryptoService>();
|
||||||
|
|
||||||
PageTitle = AppResources.Bitwarden;
|
PageTitle = AppResources.Bitwarden;
|
||||||
LogInCommand = new AsyncCommand(LogInAsync, allowsMultipleExecutions: false);
|
LogInCommand = CreateDefaultAsyncRelayCommand(LogInAsync, allowsMultipleExecutions: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string OrgIdentifier
|
public string OrgIdentifier
|
||||||
|
@ -231,19 +231,18 @@ namespace Bit.App.Pages
|
||||||
StartDeviceApprovalOptionsAction?.Invoke();
|
StartDeviceApprovalOptionsAction?.Invoke();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// If user doesn't have a MP, but has reset password permission, they must set a MP
|
|
||||||
if (!decryptOptions.HasMasterPassword &&
|
|
||||||
decryptOptions.TrustedDeviceOption.HasManageResetPasswordPermission)
|
|
||||||
{
|
|
||||||
StartSetPasswordAction?.Invoke();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Update temp password only if the device is trusted and therefore has a decrypted User Key set
|
// Update temp password only if the device is trusted and therefore has a decrypted User Key set
|
||||||
if (response.ForcePasswordReset)
|
if (response.ForcePasswordReset)
|
||||||
{
|
{
|
||||||
UpdateTempPasswordAction?.Invoke();
|
UpdateTempPasswordAction?.Invoke();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// If user doesn't have a MP, but has reset password permission, they must set a MP
|
||||||
|
if (!decryptOptions.HasMasterPassword &&
|
||||||
|
decryptOptions.TrustedDeviceOption.HasManageResetPasswordPermission)
|
||||||
|
{
|
||||||
|
await _stateService.SetForcePasswordResetReasonAsync(ForcePasswordResetReason.TdeUserWithoutPasswordHasPasswordResetPermission);
|
||||||
|
}
|
||||||
// Device is trusted and has keys, so we can decrypt
|
// Device is trusted and has keys, so we can decrypt
|
||||||
_syncService.FullSyncAsync(true).FireAndForget();
|
_syncService.FullSyncAsync(true).FireAndForget();
|
||||||
SsoAuthSuccessAction?.Invoke();
|
SsoAuthSuccessAction?.Invoke();
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
<StackLayout Spacing="20">
|
<StackLayout Spacing="20">
|
||||||
<StackLayout StyleClass="box">
|
<StackLayout StyleClass="box">
|
||||||
<StackLayout StyleClass="box-row">
|
<StackLayout StyleClass="box-row">
|
||||||
<Label Text="{u:I18n SetMasterPasswordSummary}"
|
<Label Text="{Binding SetMasterPasswordSummary}"
|
||||||
StyleClass="text-md"
|
StyleClass="text-md"
|
||||||
HorizontalTextAlignment="Start"></Label>
|
HorizontalTextAlignment="Start"></Label>
|
||||||
</StackLayout>
|
</StackLayout>
|
||||||
|
|
|
@ -1,11 +1,7 @@
|
||||||
using System;
|
using System.Text;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Bit.App.Abstractions;
|
using Bit.App.Abstractions;
|
||||||
using Bit.Core.Resources.Localization;
|
using Bit.Core.Resources.Localization;
|
||||||
using Bit.App.Utilities;
|
|
||||||
using Bit.Core;
|
using Bit.Core;
|
||||||
using Bit.Core.Abstractions;
|
using Bit.Core.Abstractions;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
|
@ -13,9 +9,6 @@ using Bit.Core.Exceptions;
|
||||||
using Bit.Core.Models.Domain;
|
using Bit.Core.Models.Domain;
|
||||||
using Bit.Core.Models.Request;
|
using Bit.Core.Models.Request;
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
using Microsoft.Maui.Networking;
|
|
||||||
using Microsoft.Maui.Controls;
|
|
||||||
using Microsoft.Maui;
|
|
||||||
|
|
||||||
namespace Bit.App.Pages
|
namespace Bit.App.Pages
|
||||||
{
|
{
|
||||||
|
@ -29,6 +22,7 @@ namespace Bit.App.Pages
|
||||||
private readonly IPolicyService _policyService;
|
private readonly IPolicyService _policyService;
|
||||||
private readonly IPasswordGenerationService _passwordGenerationService;
|
private readonly IPasswordGenerationService _passwordGenerationService;
|
||||||
private readonly II18nService _i18nService;
|
private readonly II18nService _i18nService;
|
||||||
|
private readonly ISyncService _syncService;
|
||||||
|
|
||||||
private bool _showPassword;
|
private bool _showPassword;
|
||||||
private bool _isPolicyInEffect;
|
private bool _isPolicyInEffect;
|
||||||
|
@ -47,6 +41,7 @@ namespace Bit.App.Pages
|
||||||
_passwordGenerationService =
|
_passwordGenerationService =
|
||||||
ServiceContainer.Resolve<IPasswordGenerationService>("passwordGenerationService");
|
ServiceContainer.Resolve<IPasswordGenerationService>("passwordGenerationService");
|
||||||
_i18nService = ServiceContainer.Resolve<II18nService>("i18nService");
|
_i18nService = ServiceContainer.Resolve<II18nService>("i18nService");
|
||||||
|
_syncService = ServiceContainer.Resolve<ISyncService>();
|
||||||
|
|
||||||
PageTitle = AppResources.SetMasterPassword;
|
PageTitle = AppResources.SetMasterPassword;
|
||||||
TogglePasswordCommand = new Command(TogglePassword);
|
TogglePasswordCommand = new Command(TogglePassword);
|
||||||
|
@ -101,11 +96,17 @@ namespace Bit.App.Pages
|
||||||
public Action CloseAction { get; set; }
|
public Action CloseAction { get; set; }
|
||||||
public string OrgIdentifier { get; set; }
|
public string OrgIdentifier { get; set; }
|
||||||
public string OrgId { get; set; }
|
public string OrgId { get; set; }
|
||||||
|
public ForcePasswordResetReason? ForceSetPasswordReason { get; private set; }
|
||||||
|
|
||||||
|
public string SetMasterPasswordSummary => ForceSetPasswordReason == ForcePasswordResetReason.TdeUserWithoutPasswordHasPasswordResetPermission
|
||||||
|
? AppResources.YourOrganizationPermissionsWereUpdatedRequeringYouToSetAMasterPassword
|
||||||
|
: AppResources.YourOrganizationRequiresYouToSetAMasterPassword;
|
||||||
|
|
||||||
public async Task InitAsync()
|
public async Task InitAsync()
|
||||||
{
|
{
|
||||||
await CheckPasswordPolicy();
|
await CheckPasswordPolicy();
|
||||||
|
ForceSetPasswordReason = await _stateService.GetForcePasswordResetReasonAsync();
|
||||||
|
TriggerPropertyChanged(nameof(SetMasterPasswordSummary));
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var response = await _apiService.GetOrganizationAutoEnrollStatusAsync(OrgIdentifier);
|
var response = await _apiService.GetOrganizationAutoEnrollStatusAsync(OrgIdentifier);
|
||||||
|
@ -172,8 +173,7 @@ namespace Bit.App.Pages
|
||||||
|
|
||||||
var (newUserKey, newProtectedUserKey) = await _cryptoService.EncryptUserKeyWithMasterKeyAsync(newMasterKey,
|
var (newUserKey, newProtectedUserKey) = await _cryptoService.EncryptUserKeyWithMasterKeyAsync(newMasterKey,
|
||||||
await _cryptoService.GetUserKeyAsync() ?? await _cryptoService.MakeUserKeyAsync());
|
await _cryptoService.GetUserKeyAsync() ?? await _cryptoService.MakeUserKeyAsync());
|
||||||
|
var keysRequest = await GetKeysForSetPasswordRequestAsync(newUserKey);
|
||||||
var (newPublicKey, newProtectedPrivateKey) = await _cryptoService.MakeKeyPairAsync(newUserKey);
|
|
||||||
var request = new SetPasswordRequest
|
var request = new SetPasswordRequest
|
||||||
{
|
{
|
||||||
MasterPasswordHash = masterPasswordHash,
|
MasterPasswordHash = masterPasswordHash,
|
||||||
|
@ -184,16 +184,12 @@ namespace Bit.App.Pages
|
||||||
KdfMemory = kdfConfig.Memory,
|
KdfMemory = kdfConfig.Memory,
|
||||||
KdfParallelism = kdfConfig.Parallelism,
|
KdfParallelism = kdfConfig.Parallelism,
|
||||||
OrgIdentifier = OrgIdentifier,
|
OrgIdentifier = OrgIdentifier,
|
||||||
Keys = new KeysRequest
|
Keys = keysRequest
|
||||||
{
|
|
||||||
PublicKey = newPublicKey,
|
|
||||||
EncryptedPrivateKey = newProtectedPrivateKey.EncryptedString
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await _deviceActionService.ShowLoadingAsync(AppResources.CreatingAccount);
|
await _deviceActionService.ShowLoadingAsync(AppResources.Loading);
|
||||||
// Set Password and relevant information
|
// Set Password and relevant information
|
||||||
await _apiService.SetPasswordAsync(request);
|
await _apiService.SetPasswordAsync(request);
|
||||||
await _stateService.SetKdfConfigurationAsync(kdfConfig);
|
await _stateService.SetKdfConfigurationAsync(kdfConfig);
|
||||||
|
@ -201,7 +197,13 @@ namespace Bit.App.Pages
|
||||||
await _cryptoService.SetMasterKeyAsync(newMasterKey);
|
await _cryptoService.SetMasterKeyAsync(newMasterKey);
|
||||||
await _cryptoService.SetMasterKeyHashAsync(localMasterPasswordHash);
|
await _cryptoService.SetMasterKeyHashAsync(localMasterPasswordHash);
|
||||||
await _cryptoService.SetMasterKeyEncryptedUserKeyAsync(newProtectedUserKey.EncryptedString);
|
await _cryptoService.SetMasterKeyEncryptedUserKeyAsync(newProtectedUserKey.EncryptedString);
|
||||||
await _cryptoService.SetUserPrivateKeyAsync(newProtectedPrivateKey.EncryptedString);
|
|
||||||
|
// Set private key only for new JIT provisioned users in MP encryption orgs
|
||||||
|
// Existing TDE users will have private key set on sync or on login
|
||||||
|
if (keysRequest != null)
|
||||||
|
{
|
||||||
|
await _cryptoService.SetUserPrivateKeyAsync(keysRequest.EncryptedPrivateKey);
|
||||||
|
}
|
||||||
|
|
||||||
if (ResetPasswordAutoEnroll)
|
if (ResetPasswordAutoEnroll)
|
||||||
{
|
{
|
||||||
|
@ -222,6 +224,9 @@ namespace Bit.App.Pages
|
||||||
await _apiService.PutOrganizationUserResetPasswordEnrollmentAsync(OrgId, userId, resetRequest);
|
await _apiService.PutOrganizationUserResetPasswordEnrollmentAsync(OrgId, userId, resetRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await _stateService.SetForcePasswordResetReasonAsync(null);
|
||||||
|
await _stateService.SetUserHasMasterPasswordAsync(true);
|
||||||
|
await _syncService.FullSyncAsync(true);
|
||||||
await _deviceActionService.HideLoadingAsync();
|
await _deviceActionService.HideLoadingAsync();
|
||||||
SetPasswordSuccessAction?.Invoke();
|
SetPasswordSuccessAction?.Invoke();
|
||||||
}
|
}
|
||||||
|
@ -236,6 +241,21 @@ namespace Bit.App.Pages
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<KeysRequest> GetKeysForSetPasswordRequestAsync(UserKey newUserKey)
|
||||||
|
{
|
||||||
|
if (ForceSetPasswordReason == ForcePasswordResetReason.TdeUserWithoutPasswordHasPasswordResetPermission)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var (newPublicKey, newProtectedPrivateKey) = await _cryptoService.MakeKeyPairAsync(newUserKey);
|
||||||
|
return new KeysRequest
|
||||||
|
{
|
||||||
|
PublicKey = newPublicKey,
|
||||||
|
EncryptedPrivateKey = newProtectedPrivateKey.EncryptedString
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
public void TogglePassword()
|
public void TogglePassword()
|
||||||
{
|
{
|
||||||
ShowPassword = !ShowPassword;
|
ShowPassword = !ShowPassword;
|
||||||
|
|
|
@ -10,6 +10,7 @@ using Bit.App.Utilities;
|
||||||
using Bit.Core.Abstractions;
|
using Bit.Core.Abstractions;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
using Bit.Core.Exceptions;
|
using Bit.Core.Exceptions;
|
||||||
|
using Bit.Core.Models.Domain;
|
||||||
using Bit.Core.Models.Request;
|
using Bit.Core.Models.Request;
|
||||||
using Bit.Core.Services;
|
using Bit.Core.Services;
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
|
@ -62,7 +63,7 @@ namespace Bit.App.Pages
|
||||||
|
|
||||||
PageTitle = AppResources.TwoStepLogin;
|
PageTitle = AppResources.TwoStepLogin;
|
||||||
SubmitCommand = new Command(async () => await SubmitAsync());
|
SubmitCommand = new Command(async () => await SubmitAsync());
|
||||||
MoreCommand = new AsyncCommand(MoreAsync, onException: _logger.Exception, allowsMultipleExecutions: false);
|
MoreCommand = CreateDefaultAsyncRelayCommand(MoreAsync, onException: _logger.Exception, allowsMultipleExecutions: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string TotpInstruction
|
public string TotpInstruction
|
||||||
|
@ -338,20 +339,18 @@ Device.RuntimePlatform == Device.iOS ? AppResources.YubiKeyInstructionIos :
|
||||||
StartDeviceApprovalOptionsAction?.Invoke();
|
StartDeviceApprovalOptionsAction?.Invoke();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// If user doesn't have a MP, but has reset password permission, they must set a MP
|
|
||||||
if (!decryptOptions.HasMasterPassword &&
|
|
||||||
decryptOptions.TrustedDeviceOption.HasManageResetPasswordPermission)
|
|
||||||
{
|
|
||||||
StartSetPasswordAction?.Invoke();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Update temp password only if the device is trusted and therefore has a decrypted User Key set
|
// Update temp password only if the device is trusted and therefore has a decrypted User Key set
|
||||||
if (result.ForcePasswordReset)
|
if (result.ForcePasswordReset)
|
||||||
{
|
{
|
||||||
UpdateTempPasswordAction?.Invoke();
|
UpdateTempPasswordAction?.Invoke();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// If user doesn't have a MP, but has reset password permission, they must set a MP
|
||||||
|
if (!decryptOptions.HasMasterPassword &&
|
||||||
|
decryptOptions.TrustedDeviceOption.HasManageResetPasswordPermission)
|
||||||
|
{
|
||||||
|
await _stateService.SetForcePasswordResetReasonAsync(ForcePasswordResetReason.TdeUserWithoutPasswordHasPasswordResetPermission);
|
||||||
|
}
|
||||||
// Device is trusted and has keys, so we can decrypt
|
// Device is trusted and has keys, so we can decrypt
|
||||||
_syncService.FullSyncAsync(true).FireAndForget();
|
_syncService.FullSyncAsync(true).FireAndForget();
|
||||||
await TwoFactorAuthSuccessAsync();
|
await TwoFactorAuthSuccessAsync();
|
||||||
|
|
|
@ -11,6 +11,7 @@ using Bit.Core.Utilities;
|
||||||
using Microsoft.Maui.Controls;
|
using Microsoft.Maui.Controls;
|
||||||
using Microsoft.Maui;
|
using Microsoft.Maui;
|
||||||
using Bit.App.Utilities;
|
using Bit.App.Utilities;
|
||||||
|
using CommunityToolkit.Mvvm.Input;
|
||||||
|
|
||||||
namespace Bit.App.Pages
|
namespace Bit.App.Pages
|
||||||
{
|
{
|
||||||
|
@ -25,14 +26,14 @@ namespace Bit.App.Pages
|
||||||
PageTitle = AppResources.UpdateMasterPassword;
|
PageTitle = AppResources.UpdateMasterPassword;
|
||||||
TogglePasswordCommand = new Command(TogglePassword);
|
TogglePasswordCommand = new Command(TogglePassword);
|
||||||
ToggleConfirmPasswordCommand = new Command(ToggleConfirmPassword);
|
ToggleConfirmPasswordCommand = new Command(ToggleConfirmPassword);
|
||||||
SubmitCommand = new AsyncCommand(SubmitAsync,
|
SubmitCommand = CreateDefaultAsyncRelayCommand(SubmitAsync,
|
||||||
onException: ex => HandleException(ex),
|
onException: ex => HandleException(ex),
|
||||||
allowsMultipleExecutions: false);
|
allowsMultipleExecutions: false);
|
||||||
|
|
||||||
_userVerificationService = ServiceContainer.Resolve<IUserVerificationService>();
|
_userVerificationService = ServiceContainer.Resolve<IUserVerificationService>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public AsyncCommand SubmitCommand { get; }
|
public AsyncRelayCommand SubmitCommand { get; }
|
||||||
public Command TogglePasswordCommand { get; }
|
public Command TogglePasswordCommand { get; }
|
||||||
public Command ToggleConfirmPasswordCommand { get; }
|
public Command ToggleConfirmPasswordCommand { get; }
|
||||||
public Action UpdateTempPasswordSuccessAction { get; set; }
|
public Action UpdateTempPasswordSuccessAction { get; set; }
|
||||||
|
|
|
@ -39,8 +39,8 @@ namespace Bit.App.Pages
|
||||||
PageTitle = AppResources.VerificationCode;
|
PageTitle = AppResources.VerificationCode;
|
||||||
|
|
||||||
TogglePasswordCommand = new Command(TogglePassword);
|
TogglePasswordCommand = new Command(TogglePassword);
|
||||||
MainActionCommand = new AsyncCommand(MainActionAsync, allowsMultipleExecutions: false);
|
MainActionCommand = CreateDefaultAsyncRelayCommand(MainActionAsync, allowsMultipleExecutions: false);
|
||||||
RequestOTPCommand = new AsyncCommand(RequestOTPAsync, allowsMultipleExecutions: false);
|
RequestOTPCommand = CreateDefaultAsyncRelayCommand(RequestOTPAsync, allowsMultipleExecutions: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ShowPassword
|
public bool ShowPassword
|
||||||
|
|
|
@ -1,27 +1,13 @@
|
||||||
using System;
|
using Bit.App.Controls;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows.Input;
|
|
||||||
using Bit.App.Abstractions;
|
|
||||||
using Bit.App.Controls;
|
|
||||||
using Bit.Core.Resources.Localization;
|
using Bit.Core.Resources.Localization;
|
||||||
using Bit.Core.Abstractions;
|
|
||||||
using Bit.Core.Exceptions;
|
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
|
|
||||||
using Microsoft.Maui.Networking;
|
|
||||||
using Microsoft.Maui.Controls;
|
|
||||||
using Microsoft.Maui;
|
|
||||||
using Bit.App.Utilities;
|
|
||||||
|
|
||||||
namespace Bit.App.Pages
|
namespace Bit.App.Pages
|
||||||
{
|
{
|
||||||
public abstract class BaseViewModel : ExtendedViewModel
|
public abstract class BaseViewModel : ExtendedViewModel
|
||||||
{
|
{
|
||||||
private string _pageTitle = string.Empty;
|
private string _pageTitle = string.Empty;
|
||||||
private AvatarImageSource _avatar;
|
private AvatarImageSource _avatar;
|
||||||
private LazyResolve<IDeviceActionService> _deviceActionService = new LazyResolve<IDeviceActionService>();
|
|
||||||
private LazyResolve<IPlatformUtilsService> _platformUtilsService = new LazyResolve<IPlatformUtilsService>();
|
|
||||||
private LazyResolve<ILogger> _logger = new LazyResolve<ILogger>();
|
|
||||||
|
|
||||||
public string PageTitle
|
public string PageTitle
|
||||||
{
|
{
|
||||||
|
@ -37,29 +23,6 @@ namespace Bit.App.Pages
|
||||||
|
|
||||||
public ContentPage Page { get; set; }
|
public ContentPage Page { get; set; }
|
||||||
|
|
||||||
protected void HandleException(Exception ex, string message = null)
|
|
||||||
{
|
|
||||||
if (ex is ApiException apiException && apiException.Error != null)
|
|
||||||
{
|
|
||||||
message = apiException.Error.GetSingleMessage();
|
|
||||||
}
|
|
||||||
|
|
||||||
Microsoft.Maui.ApplicationModel.MainThread.InvokeOnMainThreadAsync(async () =>
|
|
||||||
{
|
|
||||||
await _deviceActionService.Value.HideLoadingAsync();
|
|
||||||
await _platformUtilsService.Value.ShowDialogAsync(message ?? AppResources.GenericErrorMessage);
|
|
||||||
}).FireAndForget();
|
|
||||||
_logger.Value.Exception(ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected AsyncCommand CreateDefaultAsyncCommnad(Func<Task> execute, Func<bool> canExecute = null)
|
|
||||||
{
|
|
||||||
return new AsyncCommand(execute,
|
|
||||||
canExecute,
|
|
||||||
ex => HandleException(ex),
|
|
||||||
allowsMultipleExecutions: false);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async Task<bool> HasConnectivityAsync()
|
protected async Task<bool> HasConnectivityAsync()
|
||||||
{
|
{
|
||||||
if (Connectivity.NetworkAccess == NetworkAccess.None)
|
if (Connectivity.NetworkAccess == NetworkAccess.None)
|
||||||
|
|
|
@ -89,11 +89,11 @@ namespace Bit.App.Pages
|
||||||
};
|
};
|
||||||
|
|
||||||
UsernameTypePromptHelpCommand = new Command(UsernameTypePromptHelp);
|
UsernameTypePromptHelpCommand = new Command(UsernameTypePromptHelp);
|
||||||
RegenerateCommand = new AsyncCommand(RegenerateAsync, onException: ex => OnSubmitException(ex), allowsMultipleExecutions: false);
|
RegenerateCommand = CreateDefaultAsyncRelayCommand(RegenerateAsync, onException: ex => OnSubmitException(ex), allowsMultipleExecutions: false);
|
||||||
RegenerateUsernameCommand = new AsyncCommand(RegenerateUsernameAsync, onException: ex => OnSubmitException(ex), allowsMultipleExecutions: false);
|
RegenerateUsernameCommand = CreateDefaultAsyncRelayCommand(RegenerateUsernameAsync, onException: ex => OnSubmitException(ex), allowsMultipleExecutions: false);
|
||||||
ToggleForwardedEmailHiddenValueCommand = new Command(() => ShowForwardedEmailApiSecret = !ShowForwardedEmailApiSecret);
|
ToggleForwardedEmailHiddenValueCommand = new Command(() => ShowForwardedEmailApiSecret = !ShowForwardedEmailApiSecret);
|
||||||
CopyCommand = new AsyncCommand(CopyAsync, onException: ex => _logger.Value.Exception(ex), allowsMultipleExecutions: false);
|
CopyCommand = CreateDefaultAsyncRelayCommand(CopyAsync, onException: ex => _logger.Value.Exception(ex), allowsMultipleExecutions: false);
|
||||||
CloseCommand = new AsyncCommand(CloseAsync, onException: ex => _logger.Value.Exception(ex), allowsMultipleExecutions: false);
|
CloseCommand = CreateDefaultAsyncRelayCommand(CloseAsync, onException: ex => _logger.Value.Exception(ex), allowsMultipleExecutions: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<GeneratorType> GeneratorTypeOptions { get; set; }
|
public List<GeneratorType> GeneratorTypeOptions { get; set; }
|
||||||
|
|
|
@ -2,8 +2,7 @@
|
||||||
using Bit.Core.Resources.Localization;
|
using Bit.Core.Resources.Localization;
|
||||||
using Bit.Core.Abstractions;
|
using Bit.Core.Abstractions;
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
|
using CommunityToolkit.Mvvm.Input;
|
||||||
using Bit.App.Utilities;
|
|
||||||
|
|
||||||
namespace Bit.App.Pages
|
namespace Bit.App.Pages
|
||||||
{
|
{
|
||||||
|
@ -33,10 +32,10 @@ namespace Bit.App.Pages
|
||||||
_onSelectionChangingAsync = onSelectionChangingAsync;
|
_onSelectionChangingAsync = onSelectionChangingAsync;
|
||||||
_title = title;
|
_title = title;
|
||||||
|
|
||||||
SelectOptionCommand = new AsyncCommand(SelectOptionAsync, canExecuteSelectOptionCommand, onSelectOptionCommandException, allowsMultipleExecutions: false);
|
SelectOptionCommand = CreateDefaultAsyncRelayCommand(SelectOptionAsync, canExecuteSelectOptionCommand, onSelectOptionCommandException, allowsMultipleExecutions: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AsyncCommand SelectOptionCommand { get; }
|
public AsyncRelayCommand SelectOptionCommand { get; }
|
||||||
|
|
||||||
public TKey SelectedKey => _selectedKey;
|
public TKey SelectedKey => _selectedKey;
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
using System;
|
using System.Windows.Input;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows.Input;
|
|
||||||
using Bit.App.Abstractions;
|
using Bit.App.Abstractions;
|
||||||
using Bit.Core.Resources.Localization;
|
using Bit.Core.Resources.Localization;
|
||||||
using Bit.Core;
|
using Bit.Core;
|
||||||
using Bit.Core.Abstractions;
|
using Bit.Core.Abstractions;
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
using Microsoft.Maui.ApplicationModel;
|
using CommunityToolkit.Mvvm.Input;
|
||||||
using Bit.App.Utilities;
|
|
||||||
|
|
||||||
namespace Bit.App.Pages
|
namespace Bit.App.Pages
|
||||||
{
|
{
|
||||||
|
@ -29,32 +26,32 @@ namespace Bit.App.Pages
|
||||||
var environmentService = ServiceContainer.Resolve<IEnvironmentService>();
|
var environmentService = ServiceContainer.Resolve<IEnvironmentService>();
|
||||||
var clipboardService = ServiceContainer.Resolve<IClipboardService>();
|
var clipboardService = ServiceContainer.Resolve<IClipboardService>();
|
||||||
|
|
||||||
ToggleSubmitCrashLogsCommand = CreateDefaultAsyncCommnad(ToggleSubmitCrashLogsAsync);
|
ToggleSubmitCrashLogsCommand = CreateDefaultAsyncRelayCommand(ToggleSubmitCrashLogsAsync, allowsMultipleExecutions: false);
|
||||||
|
|
||||||
GoToHelpCenterCommand = CreateDefaultAsyncCommnad(
|
GoToHelpCenterCommand = CreateDefaultAsyncRelayCommand(
|
||||||
() => LaunchUriAsync(AppResources.LearnMoreAboutHowToUseBitwardenOnTheHelpCenter,
|
() => LaunchUriAsync(AppResources.LearnMoreAboutHowToUseBitwardenOnTheHelpCenter,
|
||||||
AppResources.ContinueToHelpCenter,
|
AppResources.ContinueToHelpCenter,
|
||||||
ExternalLinksConstants.HELP_CENTER));
|
ExternalLinksConstants.HELP_CENTER), allowsMultipleExecutions: false);
|
||||||
|
|
||||||
ContactBitwardenSupportCommand = CreateDefaultAsyncCommnad(
|
ContactBitwardenSupportCommand = CreateDefaultAsyncRelayCommand(
|
||||||
() => LaunchUriAsync(AppResources.ContactSupportDescriptionLong,
|
() => LaunchUriAsync(AppResources.ContactSupportDescriptionLong,
|
||||||
AppResources.ContinueToContactSupport,
|
AppResources.ContinueToContactSupport,
|
||||||
ExternalLinksConstants.CONTACT_SUPPORT));
|
ExternalLinksConstants.CONTACT_SUPPORT), allowsMultipleExecutions: false);
|
||||||
|
|
||||||
GoToWebVaultCommand = CreateDefaultAsyncCommnad(
|
GoToWebVaultCommand = CreateDefaultAsyncRelayCommand(
|
||||||
() => LaunchUriAsync(AppResources.ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp,
|
() => LaunchUriAsync(AppResources.ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp,
|
||||||
AppResources.ContinueToWebApp,
|
AppResources.ContinueToWebApp,
|
||||||
environmentService.GetWebVaultUrl()));
|
environmentService.GetWebVaultUrl()), allowsMultipleExecutions: false);
|
||||||
|
|
||||||
GoToLearnAboutOrgsCommand = CreateDefaultAsyncCommnad(
|
GoToLearnAboutOrgsCommand = CreateDefaultAsyncRelayCommand(
|
||||||
() => LaunchUriAsync(AppResources.LearnAboutOrganizationsDescriptionLong,
|
() => LaunchUriAsync(AppResources.LearnAboutOrganizationsDescriptionLong,
|
||||||
string.Format(AppResources.ContinueToX, ExternalLinksConstants.BITWARDEN_WEBSITE),
|
string.Format(AppResources.ContinueToX, ExternalLinksConstants.BITWARDEN_WEBSITE),
|
||||||
ExternalLinksConstants.HELP_ABOUT_ORGANIZATIONS));
|
ExternalLinksConstants.HELP_ABOUT_ORGANIZATIONS), allowsMultipleExecutions: false);
|
||||||
|
|
||||||
RateTheAppCommand = CreateDefaultAsyncCommnad(RateAppAsync);
|
RateTheAppCommand = CreateDefaultAsyncRelayCommand(RateAppAsync, allowsMultipleExecutions: false);
|
||||||
|
|
||||||
CopyAppInfoCommand = CreateDefaultAsyncCommnad(
|
CopyAppInfoCommand = CreateDefaultAsyncRelayCommand(
|
||||||
() => clipboardService.CopyTextAsync(AppInfo));
|
() => clipboardService.CopyTextAsync(AppInfo), allowsMultipleExecutions: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ShouldSubmitCrashLogs
|
public bool ShouldSubmitCrashLogs
|
||||||
|
@ -80,7 +77,7 @@ namespace Bit.App.Pages
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public AsyncCommand ToggleSubmitCrashLogsCommand { get; }
|
public AsyncRelayCommand ToggleSubmitCrashLogsCommand { get; }
|
||||||
public ICommand GoToHelpCenterCommand { get; }
|
public ICommand GoToHelpCenterCommand { get; }
|
||||||
public ICommand ContactBitwardenSupportCommand { get; }
|
public ICommand ContactBitwardenSupportCommand { get; }
|
||||||
public ICommand GoToWebVaultCommand { get; }
|
public ICommand GoToWebVaultCommand { get; }
|
||||||
|
@ -97,7 +94,7 @@ namespace Bit.App.Pages
|
||||||
MainThread.BeginInvokeOnMainThread(() =>
|
MainThread.BeginInvokeOnMainThread(() =>
|
||||||
{
|
{
|
||||||
TriggerPropertyChanged(nameof(ShouldSubmitCrashLogs));
|
TriggerPropertyChanged(nameof(ShouldSubmitCrashLogs));
|
||||||
ToggleSubmitCrashLogsCommand.RaiseCanExecuteChanged();
|
ToggleSubmitCrashLogsCommand.NotifyCanExecuteChanged();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,10 @@
|
||||||
using System;
|
using System.Windows.Input;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows.Input;
|
|
||||||
using Bit.App.Abstractions;
|
using Bit.App.Abstractions;
|
||||||
using Bit.Core.Resources.Localization;
|
using Bit.Core.Resources.Localization;
|
||||||
using Bit.App.Utilities;
|
using Bit.App.Utilities;
|
||||||
using Bit.Core.Abstractions;
|
using Bit.Core.Abstractions;
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
using Microsoft.Maui.ApplicationModel;
|
using CommunityToolkit.Mvvm.Input;
|
||||||
using Microsoft.Maui.Controls;
|
|
||||||
using Microsoft.Maui;
|
|
||||||
|
|
||||||
namespace Bit.App.Pages
|
namespace Bit.App.Pages
|
||||||
{
|
{
|
||||||
|
@ -64,7 +58,7 @@ namespace Bit.App.Pages
|
||||||
() => _inited,
|
() => _inited,
|
||||||
ex => HandleException(ex));
|
ex => HandleException(ex));
|
||||||
|
|
||||||
ToggleShowWebsiteIconsCommand = CreateDefaultAsyncCommnad(ToggleShowWebsiteIconsAsync, () => _inited);
|
ToggleShowWebsiteIconsCommand = CreateDefaultAsyncRelayCommand(ToggleShowWebsiteIconsAsync, () => _inited, allowsMultipleExecutions: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PickerViewModel<string> LanguagePickerViewModel { get; }
|
public PickerViewModel<string> LanguagePickerViewModel { get; }
|
||||||
|
@ -87,7 +81,7 @@ namespace Bit.App.Pages
|
||||||
|
|
||||||
public bool IsShowWebsiteIconsEnabled => ToggleShowWebsiteIconsCommand.CanExecute(null);
|
public bool IsShowWebsiteIconsEnabled => ToggleShowWebsiteIconsCommand.CanExecute(null);
|
||||||
|
|
||||||
public AsyncCommand ToggleShowWebsiteIconsCommand { get; }
|
public AsyncRelayCommand ToggleShowWebsiteIconsCommand { get; }
|
||||||
|
|
||||||
public async Task InitAsync()
|
public async Task InitAsync()
|
||||||
{
|
{
|
||||||
|
@ -102,10 +96,10 @@ namespace Bit.App.Pages
|
||||||
|
|
||||||
MainThread.BeginInvokeOnMainThread(() =>
|
MainThread.BeginInvokeOnMainThread(() =>
|
||||||
{
|
{
|
||||||
ToggleShowWebsiteIconsCommand.RaiseCanExecuteChanged();
|
ToggleShowWebsiteIconsCommand.NotifyCanExecuteChanged();
|
||||||
LanguagePickerViewModel.SelectOptionCommand.RaiseCanExecuteChanged();
|
LanguagePickerViewModel.SelectOptionCommand.NotifyCanExecuteChanged();
|
||||||
ThemePickerViewModel.SelectOptionCommand.RaiseCanExecuteChanged();
|
ThemePickerViewModel.SelectOptionCommand.NotifyCanExecuteChanged();
|
||||||
DefaultDarkThemePickerViewModel.SelectOptionCommand.RaiseCanExecuteChanged();
|
DefaultDarkThemePickerViewModel.SelectOptionCommand.NotifyCanExecuteChanged();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
using System.Threading.Tasks;
|
using System.Windows.Input;
|
||||||
using System.Windows.Input;
|
|
||||||
using Bit.Core.Resources.Localization;
|
using Bit.Core.Resources.Localization;
|
||||||
using Microsoft.Maui.ApplicationModel;
|
using CommunityToolkit.Mvvm.Input;
|
||||||
using Microsoft.Maui.Controls;
|
|
||||||
using Microsoft.Maui;
|
|
||||||
using Bit.App.Utilities;
|
|
||||||
|
|
||||||
namespace Bit.App.Pages
|
namespace Bit.App.Pages
|
||||||
{
|
{
|
||||||
|
@ -16,8 +12,7 @@ namespace Bit.App.Pages
|
||||||
private bool _useDrawOver;
|
private bool _useDrawOver;
|
||||||
private bool _askToAddLogin;
|
private bool _askToAddLogin;
|
||||||
|
|
||||||
public bool SupportsAndroidAutofillServices => // TODO Xamarin.Forms.Device.RuntimePlatform is no longer supported. Use Microsoft.Maui.Devices.DeviceInfo.Platform instead. For more details see https://learn.microsoft.com/en-us/dotnet/maui/migration/forms-projects#device-changes
|
public bool SupportsAndroidAutofillServices => DeviceInfo.Platform == DevicePlatform.Android && _deviceActionService.SupportsAutofillServices();
|
||||||
Device.RuntimePlatform == Device.Android && _deviceActionService.SupportsAutofillServices();
|
|
||||||
|
|
||||||
public bool UseAutofillServices
|
public bool UseAutofillServices
|
||||||
{
|
{
|
||||||
|
@ -45,8 +40,7 @@ Device.RuntimePlatform == Device.Android && _deviceActionService.SupportsAutofil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ShowUseAccessibilityToggle => // TODO Xamarin.Forms.Device.RuntimePlatform is no longer supported. Use Microsoft.Maui.Devices.DeviceInfo.Platform instead. For more details see https://learn.microsoft.com/en-us/dotnet/maui/migration/forms-projects#device-changes
|
public bool ShowUseAccessibilityToggle => DeviceInfo.Platform == DevicePlatform.Android;
|
||||||
Device.RuntimePlatform == Device.Android;
|
|
||||||
|
|
||||||
public string UseAccessibilityDescription => _deviceActionService.GetAutofillAccessibilityDescription();
|
public string UseAccessibilityDescription => _deviceActionService.GetAutofillAccessibilityDescription();
|
||||||
|
|
||||||
|
@ -90,21 +84,21 @@ Device.RuntimePlatform == Device.Android;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public AsyncCommand ToggleUseAutofillServicesCommand { get; private set; }
|
public AsyncRelayCommand ToggleUseAutofillServicesCommand { get; private set; }
|
||||||
public AsyncCommand ToggleUseInlineAutofillCommand { get; private set; }
|
public AsyncRelayCommand ToggleUseInlineAutofillCommand { get; private set; }
|
||||||
public AsyncCommand ToggleUseAccessibilityCommand { get; private set; }
|
public AsyncRelayCommand ToggleUseAccessibilityCommand { get; private set; }
|
||||||
public AsyncCommand ToggleUseDrawOverCommand { get; private set; }
|
public AsyncRelayCommand ToggleUseDrawOverCommand { get; private set; }
|
||||||
public AsyncCommand ToggleAskToAddLoginCommand { get; private set; }
|
public AsyncRelayCommand ToggleAskToAddLoginCommand { get; private set; }
|
||||||
public ICommand GoToBlockAutofillUrisCommand { get; private set; }
|
public ICommand GoToBlockAutofillUrisCommand { get; private set; }
|
||||||
|
|
||||||
private void InitAndroidCommands()
|
private void InitAndroidCommands()
|
||||||
{
|
{
|
||||||
ToggleUseAutofillServicesCommand = CreateDefaultAsyncCommnad(() => MainThread.InvokeOnMainThreadAsync(() => ToggleUseAutofillServices()), () => _inited);
|
ToggleUseAutofillServicesCommand = CreateDefaultAsyncRelayCommand(() => MainThread.InvokeOnMainThreadAsync(() => ToggleUseAutofillServices()), () => _inited, allowsMultipleExecutions: false);
|
||||||
ToggleUseInlineAutofillCommand = CreateDefaultAsyncCommnad(() => MainThread.InvokeOnMainThreadAsync(() => ToggleUseInlineAutofillEnabledAsync()), () => _inited);
|
ToggleUseInlineAutofillCommand = CreateDefaultAsyncRelayCommand(() => MainThread.InvokeOnMainThreadAsync(() => ToggleUseInlineAutofillEnabledAsync()), () => _inited, allowsMultipleExecutions: false);
|
||||||
ToggleUseAccessibilityCommand = CreateDefaultAsyncCommnad(ToggleUseAccessibilityAsync, () => _inited);
|
ToggleUseAccessibilityCommand = CreateDefaultAsyncRelayCommand(ToggleUseAccessibilityAsync, () => _inited, allowsMultipleExecutions: false);
|
||||||
ToggleUseDrawOverCommand = CreateDefaultAsyncCommnad(() => MainThread.InvokeOnMainThreadAsync(() => ToggleDrawOver()), () => _inited);
|
ToggleUseDrawOverCommand = CreateDefaultAsyncRelayCommand(() => MainThread.InvokeOnMainThreadAsync(() => ToggleDrawOver()), () => _inited, allowsMultipleExecutions: false);
|
||||||
ToggleAskToAddLoginCommand = CreateDefaultAsyncCommnad(ToggleAskToAddLoginAsync, () => _inited);
|
ToggleAskToAddLoginCommand = CreateDefaultAsyncRelayCommand(ToggleAskToAddLoginAsync, () => _inited, allowsMultipleExecutions: false);
|
||||||
GoToBlockAutofillUrisCommand = CreateDefaultAsyncCommnad(() => Page.Navigation.PushAsync(new BlockAutofillUrisPage()));
|
GoToBlockAutofillUrisCommand = CreateDefaultAsyncRelayCommand(() => Page.Navigation.PushAsync(new BlockAutofillUrisPage()), allowsMultipleExecutions: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task InitAndroidAutofillSettingsAsync()
|
private async Task InitAndroidAutofillSettingsAsync()
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
using System.Collections.Generic;
|
using System.Windows.Input;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows.Input;
|
|
||||||
using Bit.App.Abstractions;
|
using Bit.App.Abstractions;
|
||||||
using Bit.Core.Resources.Localization;
|
using Bit.Core.Resources.Localization;
|
||||||
using Bit.Core.Abstractions;
|
using Bit.Core.Abstractions;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
using Microsoft.Maui.ApplicationModel;
|
using CommunityToolkit.Mvvm.Input;
|
||||||
using Bit.App.Utilities;
|
|
||||||
|
|
||||||
namespace Bit.App.Pages
|
namespace Bit.App.Pages
|
||||||
{
|
{
|
||||||
|
@ -36,7 +33,7 @@ namespace Bit.App.Pages
|
||||||
() => _inited,
|
() => _inited,
|
||||||
ex => HandleException(ex));
|
ex => HandleException(ex));
|
||||||
|
|
||||||
ToggleCopyTotpAutomaticallyCommand = CreateDefaultAsyncCommnad(ToggleCopyTotpAutomaticallyAsync, () => _inited);
|
ToggleCopyTotpAutomaticallyCommand = CreateDefaultAsyncRelayCommand(ToggleCopyTotpAutomaticallyAsync, () => _inited, allowsMultipleExecutions: false);
|
||||||
|
|
||||||
InitAndroidCommands();
|
InitAndroidCommands();
|
||||||
InitIOSCommands();
|
InitIOSCommands();
|
||||||
|
@ -56,7 +53,7 @@ namespace Bit.App.Pages
|
||||||
|
|
||||||
public PickerViewModel<UriMatchType> DefaultUriMatchDetectionPickerViewModel { get; }
|
public PickerViewModel<UriMatchType> DefaultUriMatchDetectionPickerViewModel { get; }
|
||||||
|
|
||||||
public AsyncCommand ToggleCopyTotpAutomaticallyCommand { get; private set; }
|
public AsyncRelayCommand ToggleCopyTotpAutomaticallyCommand { get; private set; }
|
||||||
|
|
||||||
public async Task InitAsync()
|
public async Task InitAsync()
|
||||||
{
|
{
|
||||||
|
@ -72,11 +69,11 @@ namespace Bit.App.Pages
|
||||||
{
|
{
|
||||||
TriggerPropertyChanged(nameof(CopyTotpAutomatically));
|
TriggerPropertyChanged(nameof(CopyTotpAutomatically));
|
||||||
|
|
||||||
ToggleUseAutofillServicesCommand.RaiseCanExecuteChanged();
|
ToggleUseAutofillServicesCommand.NotifyCanExecuteChanged();
|
||||||
ToggleUseInlineAutofillCommand.RaiseCanExecuteChanged();
|
ToggleUseInlineAutofillCommand.NotifyCanExecuteChanged();
|
||||||
ToggleUseAccessibilityCommand.RaiseCanExecuteChanged();
|
ToggleUseAccessibilityCommand.NotifyCanExecuteChanged();
|
||||||
ToggleUseDrawOverCommand.RaiseCanExecuteChanged();
|
ToggleUseDrawOverCommand.NotifyCanExecuteChanged();
|
||||||
DefaultUriMatchDetectionPickerViewModel.SelectOptionCommand.RaiseCanExecuteChanged();
|
DefaultUriMatchDetectionPickerViewModel.SelectOptionCommand.NotifyCanExecuteChanged();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,21 +1,18 @@
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using Microsoft.Maui.Controls;
|
|
||||||
using Microsoft.Maui;
|
|
||||||
|
|
||||||
namespace Bit.App.Pages
|
namespace Bit.App.Pages
|
||||||
{
|
{
|
||||||
public partial class AutofillSettingsPageViewModel
|
public partial class AutofillSettingsPageViewModel
|
||||||
{
|
{
|
||||||
public bool SupportsiOSAutofill => // TODO Xamarin.Forms.Device.RuntimePlatform is no longer supported. Use Microsoft.Maui.Devices.DeviceInfo.Platform instead. For more details see https://learn.microsoft.com/en-us/dotnet/maui/migration/forms-projects#device-changes
|
public bool SupportsiOSAutofill => DeviceInfo.Platform == DevicePlatform.iOS && _deviceActionService.SupportsAutofillServices();
|
||||||
Device.RuntimePlatform == Device.iOS && _deviceActionService.SupportsAutofillServices();
|
|
||||||
|
|
||||||
public ICommand GoToPasswordAutofillCommand { get; private set; }
|
public ICommand GoToPasswordAutofillCommand { get; private set; }
|
||||||
public ICommand GoToAppExtensionCommand { get; private set; }
|
public ICommand GoToAppExtensionCommand { get; private set; }
|
||||||
|
|
||||||
private void InitIOSCommands()
|
private void InitIOSCommands()
|
||||||
{
|
{
|
||||||
GoToPasswordAutofillCommand = CreateDefaultAsyncCommnad(() => Page.Navigation.PushModalAsync(new NavigationPage(new AutofillPage())));
|
GoToPasswordAutofillCommand = CreateDefaultAsyncRelayCommand(() => Page.Navigation.PushModalAsync(new NavigationPage(new AutofillPage())), allowsMultipleExecutions: false);
|
||||||
GoToAppExtensionCommand = CreateDefaultAsyncCommnad(() => Page.Navigation.PushModalAsync(new NavigationPage(new ExtensionPage())));
|
GoToAppExtensionCommand = CreateDefaultAsyncRelayCommand(() => Page.Navigation.PushModalAsync(new NavigationPage(new ExtensionPage())), allowsMultipleExecutions: false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,11 +28,11 @@ namespace Bit.App.Pages
|
||||||
_stateService = ServiceContainer.Resolve<IStateService>();
|
_stateService = ServiceContainer.Resolve<IStateService>();
|
||||||
_deviceActionService = ServiceContainer.Resolve<IDeviceActionService>();
|
_deviceActionService = ServiceContainer.Resolve<IDeviceActionService>();
|
||||||
|
|
||||||
AddUriCommand = new AsyncCommand(AddUriAsync,
|
AddUriCommand = CreateDefaultAsyncRelayCommand(AddUriAsync,
|
||||||
onException: ex => HandleException(ex),
|
onException: ex => HandleException(ex),
|
||||||
allowsMultipleExecutions: false);
|
allowsMultipleExecutions: false);
|
||||||
|
|
||||||
EditUriCommand = new AsyncCommand<BlockAutofillUriItemViewModel>(EditUriAsync,
|
EditUriCommand = CreateDefaultAsyncRelayCommand<BlockAutofillUriItemViewModel>(EditUriAsync,
|
||||||
onException: ex => HandleException(ex),
|
onException: ex => HandleException(ex),
|
||||||
allowsMultipleExecutions: false);
|
allowsMultipleExecutions: false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ using Microsoft.Maui.ApplicationModel;
|
||||||
using Microsoft.Maui.Controls;
|
using Microsoft.Maui.Controls;
|
||||||
using Microsoft.Maui;
|
using Microsoft.Maui;
|
||||||
using Bit.App.Utilities;
|
using Bit.App.Utilities;
|
||||||
|
using CommunityToolkit.Mvvm.Input;
|
||||||
|
|
||||||
namespace Bit.App.Pages
|
namespace Bit.App.Pages
|
||||||
{
|
{
|
||||||
|
@ -34,11 +35,11 @@ namespace Bit.App.Pages
|
||||||
PageTitle = AppResources.PendingLogInRequests;
|
PageTitle = AppResources.PendingLogInRequests;
|
||||||
LoginRequests = new ObservableRangeCollection<PasswordlessLoginResponse>();
|
LoginRequests = new ObservableRangeCollection<PasswordlessLoginResponse>();
|
||||||
|
|
||||||
AnswerRequestCommand = new AsyncCommand<PasswordlessLoginResponse>(PasswordlessLoginAsync,
|
AnswerRequestCommand = CreateDefaultAsyncRelayCommand<PasswordlessLoginResponse>(PasswordlessLoginAsync,
|
||||||
onException: ex => HandleException(ex),
|
onException: ex => HandleException(ex),
|
||||||
allowsMultipleExecutions: false);
|
allowsMultipleExecutions: false);
|
||||||
|
|
||||||
DeclineAllRequestsCommand = new AsyncCommand(DeclineAllRequestsAsync,
|
DeclineAllRequestsCommand = CreateDefaultAsyncRelayCommand(DeclineAllRequestsAsync,
|
||||||
onException: ex => HandleException(ex),
|
onException: ex => HandleException(ex),
|
||||||
allowsMultipleExecutions: false);
|
allowsMultipleExecutions: false);
|
||||||
|
|
||||||
|
@ -47,9 +48,9 @@ namespace Bit.App.Pages
|
||||||
|
|
||||||
public ICommand RefreshCommand { get; }
|
public ICommand RefreshCommand { get; }
|
||||||
|
|
||||||
public AsyncCommand<PasswordlessLoginResponse> AnswerRequestCommand { get; }
|
public AsyncRelayCommand<PasswordlessLoginResponse> AnswerRequestCommand { get; }
|
||||||
|
|
||||||
public AsyncCommand DeclineAllRequestsCommand { get; }
|
public AsyncRelayCommand DeclineAllRequestsCommand { get; }
|
||||||
|
|
||||||
public ObservableRangeCollection<PasswordlessLoginResponse> LoginRequests { get; }
|
public ObservableRangeCollection<PasswordlessLoginResponse> LoginRequests { get; }
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,7 @@
|
||||||
Title="{u:I18n AllowScreenCapture}"
|
Title="{u:I18n AllowScreenCapture}"
|
||||||
IsToggled="{Binding IsScreenCaptureAllowed}"
|
IsToggled="{Binding IsScreenCaptureAllowed}"
|
||||||
IsEnabled="{Binding CanToggleeScreenCaptureAllowed}"
|
IsEnabled="{Binding CanToggleeScreenCaptureAllowed}"
|
||||||
|
IsVisible="{OnPlatform Android=True, iOS=False}"
|
||||||
AutomationId="AllowScreenCaptureSwitch"
|
AutomationId="AllowScreenCaptureSwitch"
|
||||||
StyleClass="settings-item-view"
|
StyleClass="settings-item-view"
|
||||||
HorizontalOptions="FillAndExpand" />
|
HorizontalOptions="FillAndExpand" />
|
||||||
|
|
|
@ -1,16 +1,8 @@
|
||||||
using System;
|
using System.Windows.Input;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows.Input;
|
|
||||||
using Bit.App.Abstractions;
|
using Bit.App.Abstractions;
|
||||||
using Bit.Core.Resources.Localization;
|
|
||||||
using Bit.Core.Abstractions;
|
using Bit.Core.Abstractions;
|
||||||
|
using Bit.Core.Resources.Localization;
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
|
|
||||||
using Microsoft.Maui.ApplicationModel;
|
|
||||||
using Microsoft.Maui.Controls;
|
|
||||||
using Microsoft.Maui;
|
|
||||||
using Bit.App.Utilities;
|
|
||||||
using CommunityToolkit.Mvvm.Input;
|
using CommunityToolkit.Mvvm.Input;
|
||||||
|
|
||||||
namespace Bit.App.Pages
|
namespace Bit.App.Pages
|
||||||
|
@ -43,19 +35,21 @@ namespace Bit.App.Pages
|
||||||
_watchDeviceService = ServiceContainer.Resolve<IWatchDeviceService>();
|
_watchDeviceService = ServiceContainer.Resolve<IWatchDeviceService>();
|
||||||
_logger = ServiceContainer.Resolve<ILogger>();
|
_logger = ServiceContainer.Resolve<ILogger>();
|
||||||
|
|
||||||
SyncCommand = CreateDefaultAsyncCommnad(SyncAsync, () => _inited);
|
SyncCommand = CreateDefaultAsyncRelayCommand(SyncAsync, CanExecuteIfInited, allowsMultipleExecutions: false);
|
||||||
ToggleIsScreenCaptureAllowedCommand = CreateDefaultAsyncCommnad(ToggleIsScreenCaptureAllowedAsync, () => _inited);
|
ToggleIsScreenCaptureAllowedCommand = CreateDefaultAsyncRelayCommand(ToggleIsScreenCaptureAllowedAsync, CanExecuteIfInited, allowsMultipleExecutions: false);
|
||||||
ToggleShouldConnectToWatchCommand = CreateDefaultAsyncCommnad(ToggleShouldConnectToWatchAsync, () => _inited);
|
ToggleShouldConnectToWatchCommand = CreateDefaultAsyncRelayCommand(ToggleShouldConnectToWatchAsync, CanExecuteIfInited, allowsMultipleExecutions: false);
|
||||||
|
|
||||||
ClearClipboardPickerViewModel = new PickerViewModel<int>(
|
ClearClipboardPickerViewModel = new PickerViewModel<int>(
|
||||||
_deviceActionService,
|
_deviceActionService,
|
||||||
_logger,
|
_logger,
|
||||||
OnClearClipboardChangingAsync,
|
OnClearClipboardChangingAsync,
|
||||||
AppResources.ClearClipboard,
|
AppResources.ClearClipboard,
|
||||||
() => _inited,
|
CanExecuteIfInited,
|
||||||
ex => HandleException(ex));
|
ex => HandleException(ex));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool CanExecuteIfInited() => _inited;
|
||||||
|
|
||||||
public bool EnableSyncOnRefresh
|
public bool EnableSyncOnRefresh
|
||||||
{
|
{
|
||||||
get => _syncOnRefresh;
|
get => _syncOnRefresh;
|
||||||
|
@ -104,9 +98,9 @@ namespace Bit.App.Pages
|
||||||
|
|
||||||
public bool CanToggleShouldConnectToWatch => ToggleShouldConnectToWatchCommand.CanExecute(null);
|
public bool CanToggleShouldConnectToWatch => ToggleShouldConnectToWatchCommand.CanExecute(null);
|
||||||
|
|
||||||
public AsyncCommand SyncCommand { get; }
|
public AsyncRelayCommand SyncCommand { get; }
|
||||||
public AsyncCommand ToggleIsScreenCaptureAllowedCommand { get; }
|
public AsyncRelayCommand ToggleIsScreenCaptureAllowedCommand { get; }
|
||||||
public AsyncCommand ToggleShouldConnectToWatchCommand { get; }
|
public AsyncRelayCommand ToggleShouldConnectToWatchCommand { get; }
|
||||||
|
|
||||||
public async Task InitAsync()
|
public async Task InitAsync()
|
||||||
{
|
{
|
||||||
|
@ -125,10 +119,10 @@ namespace Bit.App.Pages
|
||||||
{
|
{
|
||||||
TriggerPropertyChanged(nameof(IsScreenCaptureAllowed));
|
TriggerPropertyChanged(nameof(IsScreenCaptureAllowed));
|
||||||
TriggerPropertyChanged(nameof(ShouldConnectToWatch));
|
TriggerPropertyChanged(nameof(ShouldConnectToWatch));
|
||||||
SyncCommand.RaiseCanExecuteChanged();
|
SyncCommand.NotifyCanExecuteChanged();
|
||||||
ClearClipboardPickerViewModel.SelectOptionCommand.RaiseCanExecuteChanged();
|
ClearClipboardPickerViewModel.SelectOptionCommand.NotifyCanExecuteChanged();
|
||||||
ToggleIsScreenCaptureAllowedCommand.RaiseCanExecuteChanged();
|
ToggleIsScreenCaptureAllowedCommand.NotifyCanExecuteChanged();
|
||||||
ToggleShouldConnectToWatchCommand.RaiseCanExecuteChanged();
|
ToggleShouldConnectToWatchCommand.NotifyCanExecuteChanged();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,8 +136,7 @@ namespace Bit.App.Pages
|
||||||
[30] = AppResources.ThirtySeconds,
|
[30] = AppResources.ThirtySeconds,
|
||||||
[60] = AppResources.OneMinute
|
[60] = AppResources.OneMinute
|
||||||
};
|
};
|
||||||
// TODO Xamarin.Forms.Device.RuntimePlatform is no longer supported. Use Microsoft.Maui.Devices.DeviceInfo.Platform instead. For more details see https://learn.microsoft.com/en-us/dotnet/maui/migration/forms-projects#device-changes
|
if (DeviceInfo.Platform != DevicePlatform.iOS)
|
||||||
if (Device.RuntimePlatform != Device.iOS)
|
|
||||||
{
|
{
|
||||||
clearClipboardOptions.Add(120, AppResources.TwoMinutes);
|
clearClipboardOptions.Add(120, AppResources.TwoMinutes);
|
||||||
clearClipboardOptions.Add(300, AppResources.FiveMinutes);
|
clearClipboardOptions.Add(300, AppResources.FiveMinutes);
|
||||||
|
|
|
@ -67,7 +67,7 @@
|
||||||
<controls:CustomLabel
|
<controls:CustomLabel
|
||||||
Text="{u:I18n SessionTimeout}"
|
Text="{u:I18n SessionTimeout}"
|
||||||
StyleClass="settings-header" />
|
StyleClass="settings-header" />
|
||||||
|
|
||||||
<Frame
|
<Frame
|
||||||
IsVisible="{Binding ShowVaultTimeoutPolicyInfo}"
|
IsVisible="{Binding ShowVaultTimeoutPolicyInfo}"
|
||||||
Padding="10"
|
Padding="10"
|
||||||
|
@ -109,8 +109,10 @@
|
||||||
|
|
||||||
<controls:SettingChooserItemView
|
<controls:SettingChooserItemView
|
||||||
Title="{u:I18n SessionTimeoutAction}"
|
Title="{u:I18n SessionTimeoutAction}"
|
||||||
|
Subtitle="{Binding SetUpUnlockMethodLabel}"
|
||||||
DisplayValue="{Binding VaultTimeoutActionPickerViewModel.SelectedValue}"
|
DisplayValue="{Binding VaultTimeoutActionPickerViewModel.SelectedValue}"
|
||||||
ChooseCommand="{Binding VaultTimeoutActionPickerViewModel.SelectOptionCommand}"
|
ChooseCommand="{Binding VaultTimeoutActionPickerViewModel.SelectOptionCommand}"
|
||||||
|
IsEnabled="{Binding IsVaultTimeoutActionLockAllowed}"
|
||||||
AutomationId="VaultTimeoutActionChooser"
|
AutomationId="VaultTimeoutActionChooser"
|
||||||
StyleClass="settings-item-view"
|
StyleClass="settings-item-view"
|
||||||
HorizontalOptions="FillAndExpand"/>
|
HorizontalOptions="FillAndExpand"/>
|
||||||
|
@ -147,6 +149,7 @@
|
||||||
|
|
||||||
<controls:CustomLabel
|
<controls:CustomLabel
|
||||||
Text="{u:I18n LockNow}"
|
Text="{u:I18n LockNow}"
|
||||||
|
IsVisible="{Binding IsVaultTimeoutActionLockAllowed}"
|
||||||
StyleClass="settings-navigatable-label"
|
StyleClass="settings-navigatable-label"
|
||||||
AutomationId="LockNowLabel">
|
AutomationId="LockNowLabel">
|
||||||
<Label.GestureRecognizers>
|
<Label.GestureRecognizers>
|
||||||
|
|
|
@ -1,8 +1,4 @@
|
||||||
using System;
|
using System.Windows.Input;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows.Input;
|
|
||||||
using Bit.App.Abstractions;
|
using Bit.App.Abstractions;
|
||||||
using Bit.App.Pages.Accounts;
|
using Bit.App.Pages.Accounts;
|
||||||
using Bit.Core.Resources.Localization;
|
using Bit.Core.Resources.Localization;
|
||||||
|
@ -12,10 +8,7 @@ using Bit.Core.Abstractions;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
using Bit.Core.Models.Domain;
|
using Bit.Core.Models.Domain;
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
|
using CommunityToolkit.Mvvm.Input;
|
||||||
using Microsoft.Maui.ApplicationModel;
|
|
||||||
using Microsoft.Maui.Controls;
|
|
||||||
using Microsoft.Maui;
|
|
||||||
|
|
||||||
namespace Bit.App.Pages
|
namespace Bit.App.Pages
|
||||||
{
|
{
|
||||||
|
@ -77,19 +70,19 @@ namespace Bit.App.Pages
|
||||||
_logger,
|
_logger,
|
||||||
OnVaultTimeoutActionChangingAsync,
|
OnVaultTimeoutActionChangingAsync,
|
||||||
AppResources.SessionTimeoutAction,
|
AppResources.SessionTimeoutAction,
|
||||||
() => _inited && !HasVaultTimeoutActionPolicy,
|
() => _inited && !HasVaultTimeoutActionPolicy && IsVaultTimeoutActionLockAllowed,
|
||||||
ex => HandleException(ex));
|
ex => HandleException(ex));
|
||||||
|
|
||||||
ToggleUseThisDeviceToApproveLoginRequestsCommand = CreateDefaultAsyncCommnad(ToggleUseThisDeviceToApproveLoginRequestsAsync, () => _inited);
|
ToggleUseThisDeviceToApproveLoginRequestsCommand = CreateDefaultAsyncRelayCommand(ToggleUseThisDeviceToApproveLoginRequestsAsync, () => _inited, allowsMultipleExecutions: false);
|
||||||
GoToPendingLogInRequestsCommand = CreateDefaultAsyncCommnad(() => Page.Navigation.PushModalAsync(new NavigationPage(new LoginPasswordlessRequestsListPage())));
|
GoToPendingLogInRequestsCommand = CreateDefaultAsyncRelayCommand(() => Page.Navigation.PushModalAsync(new NavigationPage(new LoginPasswordlessRequestsListPage())), allowsMultipleExecutions: false);
|
||||||
ToggleCanUnlockWithBiometricsCommand = CreateDefaultAsyncCommnad(ToggleCanUnlockWithBiometricsAsync, () => _inited);
|
ToggleCanUnlockWithBiometricsCommand = CreateDefaultAsyncRelayCommand(ToggleCanUnlockWithBiometricsAsync, () => _inited, allowsMultipleExecutions: false);
|
||||||
ToggleCanUnlockWithPinCommand = CreateDefaultAsyncCommnad(ToggleCanUnlockWithPinAsync, () => _inited);
|
ToggleCanUnlockWithPinCommand = CreateDefaultAsyncRelayCommand(ToggleCanUnlockWithPinAsync, () => _inited, allowsMultipleExecutions: false);
|
||||||
ShowAccountFingerprintPhraseCommand = CreateDefaultAsyncCommnad(ShowAccountFingerprintPhraseAsync);
|
ShowAccountFingerprintPhraseCommand = CreateDefaultAsyncRelayCommand(ShowAccountFingerprintPhraseAsync, allowsMultipleExecutions: false);
|
||||||
GoToTwoStepLoginCommand = CreateDefaultAsyncCommnad(() => GoToWebVaultSettingsAsync(AppResources.TwoStepLoginDescriptionLong, AppResources.ContinueToWebApp));
|
GoToTwoStepLoginCommand = CreateDefaultAsyncRelayCommand(() => GoToWebVaultSettingsAsync(AppResources.TwoStepLoginDescriptionLong, AppResources.ContinueToWebApp), allowsMultipleExecutions: false);
|
||||||
GoToChangeMasterPasswordCommand = CreateDefaultAsyncCommnad(() => GoToWebVaultSettingsAsync(AppResources.ChangeMasterPasswordDescriptionLong, AppResources.ContinueToWebApp));
|
GoToChangeMasterPasswordCommand = CreateDefaultAsyncRelayCommand(() => GoToWebVaultSettingsAsync(AppResources.ChangeMasterPasswordDescriptionLong, AppResources.ContinueToWebApp), allowsMultipleExecutions: false);
|
||||||
LockCommand = CreateDefaultAsyncCommnad(() => _vaultTimeoutService.LockAsync(true, true));
|
LockCommand = CreateDefaultAsyncRelayCommand(() => _vaultTimeoutService.LockAsync(true, true), allowsMultipleExecutions: false);
|
||||||
LogOutCommand = CreateDefaultAsyncCommnad(LogOutAsync);
|
LogOutCommand = CreateDefaultAsyncRelayCommand(LogOutAsync, allowsMultipleExecutions: false);
|
||||||
DeleteAccountCommand = CreateDefaultAsyncCommnad(() => Page.Navigation.PushModalAsync(new NavigationPage(new DeleteAccountPage())));
|
DeleteAccountCommand = CreateDefaultAsyncRelayCommand(() => Page.Navigation.PushModalAsync(new NavigationPage(new DeleteAccountPage())), allowsMultipleExecutions: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool UseThisDeviceToApproveLoginRequests
|
public bool UseThisDeviceToApproveLoginRequests
|
||||||
|
@ -114,8 +107,7 @@ namespace Bit.App.Pages
|
||||||
}
|
}
|
||||||
|
|
||||||
var biometricName = AppResources.Biometrics;
|
var biometricName = AppResources.Biometrics;
|
||||||
// TODO Xamarin.Forms.Device.RuntimePlatform is no longer supported. Use Microsoft.Maui.Devices.DeviceInfo.Platform instead. For more details see https://learn.microsoft.com/en-us/dotnet/maui/migration/forms-projects#device-changes
|
if (DeviceInfo.Platform == DevicePlatform.iOS)
|
||||||
if (Device.RuntimePlatform == Device.iOS)
|
|
||||||
{
|
{
|
||||||
biometricName = _deviceActionService.SupportsFaceBiometric()
|
biometricName = _deviceActionService.SupportsFaceBiometric()
|
||||||
? AppResources.FaceID
|
? AppResources.FaceID
|
||||||
|
@ -131,6 +123,7 @@ namespace Bit.App.Pages
|
||||||
get => _canUnlockWithBiometrics;
|
get => _canUnlockWithBiometrics;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
|
TriggerVaultTimeoutActionLockAllowedPropertyChanged();
|
||||||
if (SetProperty(ref _canUnlockWithBiometrics, value))
|
if (SetProperty(ref _canUnlockWithBiometrics, value))
|
||||||
{
|
{
|
||||||
((ICommand)ToggleCanUnlockWithBiometricsCommand).Execute(null);
|
((ICommand)ToggleCanUnlockWithBiometricsCommand).Execute(null);
|
||||||
|
@ -143,6 +136,7 @@ namespace Bit.App.Pages
|
||||||
get => _canUnlockWithPin;
|
get => _canUnlockWithPin;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
|
TriggerVaultTimeoutActionLockAllowedPropertyChanged();
|
||||||
if (SetProperty(ref _canUnlockWithPin, value))
|
if (SetProperty(ref _canUnlockWithPin, value))
|
||||||
{
|
{
|
||||||
((ICommand)ToggleCanUnlockWithPinCommand).Execute(null);
|
((ICommand)ToggleCanUnlockWithPinCommand).Execute(null);
|
||||||
|
@ -150,6 +144,10 @@ namespace Bit.App.Pages
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsVaultTimeoutActionLockAllowed => _hasMasterPassword || _canUnlockWithBiometrics || _canUnlockWithPin;
|
||||||
|
|
||||||
|
public string SetUpUnlockMethodLabel => IsVaultTimeoutActionLockAllowed ? null : AppResources.SetUpAnUnlockOptionToChangeYourVaultTimeoutAction;
|
||||||
|
|
||||||
public TimeSpan? CustomVaultTimeoutTime
|
public TimeSpan? CustomVaultTimeoutTime
|
||||||
{
|
{
|
||||||
get => _customVaultTimeoutTime;
|
get => _customVaultTimeoutTime;
|
||||||
|
@ -166,6 +164,7 @@ namespace Bit.App.Pages
|
||||||
MainThread.BeginInvokeOnMainThread(() => SetProperty(ref _customVaultTimeoutTime, oldValue));
|
MainThread.BeginInvokeOnMainThread(() => SetProperty(ref _customVaultTimeoutTime, oldValue));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
TriggerVaultTimeoutActionLockAllowedPropertyChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,22 +204,19 @@ namespace Bit.App.Pages
|
||||||
|
|
||||||
public bool ShowChangeMasterPassword { get; private set; }
|
public bool ShowChangeMasterPassword { get; private set; }
|
||||||
|
|
||||||
private bool IsVaultTimeoutActionLockAllowed => _hasMasterPassword || _canUnlockWithBiometrics || _canUnlockWithPin;
|
|
||||||
|
|
||||||
private int? CurrentVaultTimeout => GetRawVaultTimeoutFrom(VaultTimeoutPickerViewModel.SelectedKey);
|
private int? CurrentVaultTimeout => GetRawVaultTimeoutFrom(VaultTimeoutPickerViewModel.SelectedKey);
|
||||||
|
|
||||||
private bool IncludeLinksWithSubscriptionInfo => // TODO Xamarin.Forms.Device.RuntimePlatform is no longer supported. Use Microsoft.Maui.Devices.DeviceInfo.Platform instead. For more details see https://learn.microsoft.com/en-us/dotnet/maui/migration/forms-projects#device-changes
|
private bool IncludeLinksWithSubscriptionInfo => DeviceInfo.Platform != DevicePlatform.iOS;
|
||||||
Device.RuntimePlatform != Device.iOS;
|
|
||||||
|
|
||||||
private bool HasVaultTimeoutActionPolicy => !string.IsNullOrEmpty(_vaultTimeoutActionPolicy);
|
private bool HasVaultTimeoutActionPolicy => !string.IsNullOrEmpty(_vaultTimeoutActionPolicy);
|
||||||
|
|
||||||
public PickerViewModel<int> VaultTimeoutPickerViewModel { get; }
|
public PickerViewModel<int> VaultTimeoutPickerViewModel { get; }
|
||||||
public PickerViewModel<VaultTimeoutAction> VaultTimeoutActionPickerViewModel { get; }
|
public PickerViewModel<VaultTimeoutAction> VaultTimeoutActionPickerViewModel { get; }
|
||||||
|
|
||||||
public AsyncCommand ToggleUseThisDeviceToApproveLoginRequestsCommand { get; }
|
public AsyncRelayCommand ToggleUseThisDeviceToApproveLoginRequestsCommand { get; }
|
||||||
public ICommand GoToPendingLogInRequestsCommand { get; }
|
public ICommand GoToPendingLogInRequestsCommand { get; }
|
||||||
public AsyncCommand ToggleCanUnlockWithBiometricsCommand { get; }
|
public AsyncRelayCommand ToggleCanUnlockWithBiometricsCommand { get; }
|
||||||
public AsyncCommand ToggleCanUnlockWithPinCommand { get; }
|
public AsyncRelayCommand ToggleCanUnlockWithPinCommand { get; }
|
||||||
public ICommand ShowAccountFingerprintPhraseCommand { get; }
|
public ICommand ShowAccountFingerprintPhraseCommand { get; }
|
||||||
public ICommand GoToTwoStepLoginCommand { get; }
|
public ICommand GoToTwoStepLoginCommand { get; }
|
||||||
public ICommand GoToChangeMasterPasswordCommand { get; }
|
public ICommand GoToChangeMasterPasswordCommand { get; }
|
||||||
|
@ -256,11 +252,12 @@ Device.RuntimePlatform != Device.iOS;
|
||||||
TriggerPropertyChanged(nameof(VaultTimeoutPolicyDescription));
|
TriggerPropertyChanged(nameof(VaultTimeoutPolicyDescription));
|
||||||
TriggerPropertyChanged(nameof(ShowChangeMasterPassword));
|
TriggerPropertyChanged(nameof(ShowChangeMasterPassword));
|
||||||
TriggerUpdateCustomVaultTimeoutPicker();
|
TriggerUpdateCustomVaultTimeoutPicker();
|
||||||
ToggleUseThisDeviceToApproveLoginRequestsCommand.RaiseCanExecuteChanged();
|
TriggerVaultTimeoutActionLockAllowedPropertyChanged();
|
||||||
ToggleCanUnlockWithBiometricsCommand.RaiseCanExecuteChanged();
|
ToggleUseThisDeviceToApproveLoginRequestsCommand.NotifyCanExecuteChanged();
|
||||||
ToggleCanUnlockWithPinCommand.RaiseCanExecuteChanged();
|
ToggleCanUnlockWithBiometricsCommand.NotifyCanExecuteChanged();
|
||||||
VaultTimeoutPickerViewModel.SelectOptionCommand.RaiseCanExecuteChanged();
|
ToggleCanUnlockWithPinCommand.NotifyCanExecuteChanged();
|
||||||
VaultTimeoutActionPickerViewModel.SelectOptionCommand.RaiseCanExecuteChanged();
|
VaultTimeoutPickerViewModel.SelectOptionCommand.NotifyCanExecuteChanged();
|
||||||
|
VaultTimeoutActionPickerViewModel.SelectOptionCommand.NotifyCanExecuteChanged();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,7 +272,7 @@ Device.RuntimePlatform != Device.iOS;
|
||||||
_maximumVaultTimeoutPolicy = maximumVaultTimeoutPolicy?.GetInt(Policy.MINUTES_KEY);
|
_maximumVaultTimeoutPolicy = maximumVaultTimeoutPolicy?.GetInt(Policy.MINUTES_KEY);
|
||||||
_vaultTimeoutActionPolicy = maximumVaultTimeoutPolicy?.GetString(Policy.ACTION_KEY);
|
_vaultTimeoutActionPolicy = maximumVaultTimeoutPolicy?.GetString(Policy.ACTION_KEY);
|
||||||
|
|
||||||
MainThread.BeginInvokeOnMainThread(VaultTimeoutActionPickerViewModel.SelectOptionCommand.RaiseCanExecuteChanged);
|
MainThread.BeginInvokeOnMainThread(VaultTimeoutActionPickerViewModel.SelectOptionCommand.NotifyCanExecuteChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task InitVaultTimeoutPickerAsync()
|
private async Task InitVaultTimeoutPickerAsync()
|
||||||
|
@ -308,6 +305,7 @@ Device.RuntimePlatform != Device.iOS;
|
||||||
{
|
{
|
||||||
_customVaultTimeoutTime = TimeSpan.FromMinutes(vaultTimeout);
|
_customVaultTimeoutTime = TimeSpan.FromMinutes(vaultTimeout);
|
||||||
}
|
}
|
||||||
|
TriggerVaultTimeoutActionLockAllowedPropertyChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task InitVaultTimeoutActionPickerAsync()
|
private async Task InitVaultTimeoutActionPickerAsync()
|
||||||
|
@ -327,6 +325,7 @@ Device.RuntimePlatform != Device.iOS;
|
||||||
}
|
}
|
||||||
|
|
||||||
VaultTimeoutActionPickerViewModel.Init(options, timeoutAction, IsVaultTimeoutActionLockAllowed ? VaultTimeoutAction.Lock : VaultTimeoutAction.Logout);
|
VaultTimeoutActionPickerViewModel.Init(options, timeoutAction, IsVaultTimeoutActionLockAllowed ? VaultTimeoutAction.Lock : VaultTimeoutAction.Logout);
|
||||||
|
TriggerVaultTimeoutActionLockAllowedPropertyChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ToggleUseThisDeviceToApproveLoginRequestsAsync()
|
private async Task ToggleUseThisDeviceToApproveLoginRequestsAsync()
|
||||||
|
@ -363,15 +362,15 @@ Device.RuntimePlatform != Device.iOS;
|
||||||
{
|
{
|
||||||
if (!_canUnlockWithBiometrics)
|
if (!_canUnlockWithBiometrics)
|
||||||
{
|
{
|
||||||
|
MainThread.BeginInvokeOnMainThread(() => TriggerPropertyChanged(nameof(CanUnlockWithBiometrics)));
|
||||||
await UpdateVaultTimeoutActionIfNeededAsync();
|
await UpdateVaultTimeoutActionIfNeededAsync();
|
||||||
await _biometricsService.SetCanUnlockWithBiometricsAsync(CanUnlockWithBiometrics);
|
await _biometricsService.SetCanUnlockWithBiometricsAsync(CanUnlockWithBiometrics);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Xamarin.Forms.Device.RuntimePlatform is no longer supported. Use Microsoft.Maui.Devices.DeviceInfo.Platform instead. For more details see https://learn.microsoft.com/en-us/dotnet/maui/migration/forms-projects#device-changes
|
|
||||||
if (!_supportsBiometric
|
if (!_supportsBiometric
|
||||||
||
|
||
|
||||||
!await _platformUtilsService.AuthenticateBiometricAsync(null, Device.RuntimePlatform == Device.Android ? "." : null))
|
!await _platformUtilsService.AuthenticateBiometricAsync(null, DeviceInfo.Platform == DevicePlatform.Android ? "." : null))
|
||||||
{
|
{
|
||||||
_canUnlockWithBiometrics = false;
|
_canUnlockWithBiometrics = false;
|
||||||
MainThread.BeginInvokeOnMainThread(() => TriggerPropertyChanged(nameof(CanUnlockWithBiometrics)));
|
MainThread.BeginInvokeOnMainThread(() => TriggerPropertyChanged(nameof(CanUnlockWithBiometrics)));
|
||||||
|
@ -379,11 +378,12 @@ Device.RuntimePlatform != Device.iOS;
|
||||||
}
|
}
|
||||||
|
|
||||||
await _biometricsService.SetCanUnlockWithBiometricsAsync(CanUnlockWithBiometrics);
|
await _biometricsService.SetCanUnlockWithBiometricsAsync(CanUnlockWithBiometrics);
|
||||||
|
await InitVaultTimeoutActionPickerAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task ToggleCanUnlockWithPinAsync()
|
public async Task ToggleCanUnlockWithPinAsync()
|
||||||
{
|
{
|
||||||
if (!CanUnlockWithPin)
|
if (!_canUnlockWithPin)
|
||||||
{
|
{
|
||||||
await _vaultTimeoutService.ClearAsync();
|
await _vaultTimeoutService.ClearAsync();
|
||||||
await UpdateVaultTimeoutActionIfNeededAsync();
|
await UpdateVaultTimeoutActionIfNeededAsync();
|
||||||
|
@ -407,10 +407,12 @@ Device.RuntimePlatform != Device.iOS;
|
||||||
AppResources.No);
|
AppResources.No);
|
||||||
|
|
||||||
await _userPinService.SetupPinAsync(newPin, requireMasterPasswordOnRestart);
|
await _userPinService.SetupPinAsync(newPin, requireMasterPasswordOnRestart);
|
||||||
|
await InitVaultTimeoutActionPickerAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task UpdateVaultTimeoutActionIfNeededAsync()
|
private async Task UpdateVaultTimeoutActionIfNeededAsync()
|
||||||
{
|
{
|
||||||
|
TriggerVaultTimeoutActionLockAllowedPropertyChanged();
|
||||||
if (IsVaultTimeoutActionLockAllowed)
|
if (IsVaultTimeoutActionLockAllowed)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
@ -471,6 +473,16 @@ Device.RuntimePlatform != Device.iOS;
|
||||||
TriggerPropertyChanged(nameof(CustomVaultTimeoutTime));
|
TriggerPropertyChanged(nameof(CustomVaultTimeoutTime));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void TriggerVaultTimeoutActionLockAllowedPropertyChanged()
|
||||||
|
{
|
||||||
|
MainThread.BeginInvokeOnMainThread(() =>
|
||||||
|
{
|
||||||
|
TriggerPropertyChanged(nameof(IsVaultTimeoutActionLockAllowed));
|
||||||
|
TriggerPropertyChanged(nameof(SetUpUnlockMethodLabel));
|
||||||
|
VaultTimeoutActionPickerViewModel.SelectOptionCommand.NotifyCanExecuteChanged();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private int? GetRawVaultTimeoutFrom(int vaultTimeoutPickerKey)
|
private int? GetRawVaultTimeoutFrom(int vaultTimeoutPickerKey)
|
||||||
{
|
{
|
||||||
if (vaultTimeoutPickerKey == NEVER_SESSION_TIMEOUT_VALUE)
|
if (vaultTimeoutPickerKey == NEVER_SESSION_TIMEOUT_VALUE)
|
||||||
|
@ -505,7 +517,7 @@ Device.RuntimePlatform != Device.iOS;
|
||||||
|
|
||||||
await _vaultTimeoutService.SetVaultTimeoutOptionsAsync(CurrentVaultTimeout, timeoutActionKey);
|
await _vaultTimeoutService.SetVaultTimeoutOptionsAsync(CurrentVaultTimeout, timeoutActionKey);
|
||||||
_messagingService.Send(AppHelpers.VAULT_TIMEOUT_ACTION_CHANGED_MESSAGE_COMMAND);
|
_messagingService.Send(AppHelpers.VAULT_TIMEOUT_ACTION_CHANGED_MESSAGE_COMMAND);
|
||||||
|
TriggerVaultTimeoutActionLockAllowedPropertyChanged();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using Bit.App.Utilities;
|
using Bit.App.Utilities;
|
||||||
using Bit.Core.Resources.Localization;
|
using Bit.Core.Resources.Localization;
|
||||||
|
using CommunityToolkit.Mvvm.Input;
|
||||||
|
|
||||||
namespace Bit.App.Pages
|
namespace Bit.App.Pages
|
||||||
{
|
{
|
||||||
|
@ -7,7 +8,7 @@ namespace Bit.App.Pages
|
||||||
{
|
{
|
||||||
public SettingsPageViewModel()
|
public SettingsPageViewModel()
|
||||||
{
|
{
|
||||||
ExecuteSettingItemCommand = new AsyncCommand<SettingsPageListItem>(item => item.ExecuteAsync(),
|
ExecuteSettingItemCommand = CreateDefaultAsyncRelayCommand<SettingsPageListItem>(item => item.ExecuteAsync(),
|
||||||
onException: ex => HandleException(ex),
|
onException: ex => HandleException(ex),
|
||||||
allowsMultipleExecutions: false);
|
allowsMultipleExecutions: false);
|
||||||
|
|
||||||
|
@ -24,7 +25,7 @@ namespace Bit.App.Pages
|
||||||
|
|
||||||
public List<SettingsPageListItem> SettingsItems { get; }
|
public List<SettingsPageListItem> SettingsItems { get; }
|
||||||
|
|
||||||
public AsyncCommand<SettingsPageListItem> ExecuteSettingItemCommand { get; }
|
public AsyncRelayCommand<SettingsPageListItem> ExecuteSettingItemCommand { get; }
|
||||||
|
|
||||||
private async Task NavigateToAsync(Page page)
|
private async Task NavigateToAsync(Page page)
|
||||||
{
|
{
|
||||||
|
|
|
@ -22,15 +22,15 @@ namespace Bit.App.Pages
|
||||||
_platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>();
|
_platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>();
|
||||||
_environmentService = ServiceContainer.Resolve<IEnvironmentService>();
|
_environmentService = ServiceContainer.Resolve<IEnvironmentService>();
|
||||||
|
|
||||||
GoToFoldersCommand = new AsyncCommand(() => Page.Navigation.PushModalAsync(new NavigationPage(new FoldersPage())),
|
GoToFoldersCommand = CreateDefaultAsyncRelayCommand(() => Page.Navigation.PushModalAsync(new NavigationPage(new FoldersPage())),
|
||||||
onException: ex => HandleException(ex),
|
onException: ex => HandleException(ex),
|
||||||
allowsMultipleExecutions: false);
|
allowsMultipleExecutions: false);
|
||||||
|
|
||||||
GoToExportVaultCommand = new AsyncCommand(() => Page.Navigation.PushModalAsync(new NavigationPage(new ExportVaultPage())),
|
GoToExportVaultCommand = CreateDefaultAsyncRelayCommand(() => Page.Navigation.PushModalAsync(new NavigationPage(new ExportVaultPage())),
|
||||||
onException: ex => HandleException(ex),
|
onException: ex => HandleException(ex),
|
||||||
allowsMultipleExecutions: false);
|
allowsMultipleExecutions: false);
|
||||||
|
|
||||||
GoToImportItemsCommand = new AsyncCommand(GoToImportItemsAsync,
|
GoToImportItemsCommand = CreateDefaultAsyncRelayCommand(GoToImportItemsAsync,
|
||||||
onException: ex => HandleException(ex),
|
onException: ex => HandleException(ex),
|
||||||
allowsMultipleExecutions: false);
|
allowsMultipleExecutions: false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
using Bit.App.Effects;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Bit.App.Effects;
|
||||||
using Bit.App.Models;
|
using Bit.App.Models;
|
||||||
using Bit.Core.Resources.Localization;
|
using Bit.Core.Resources.Localization;
|
||||||
using Bit.App.Utilities;
|
using Bit.App.Utilities;
|
||||||
using Bit.Core;
|
using Bit.Core;
|
||||||
using Bit.Core.Abstractions;
|
using Bit.Core.Abstractions;
|
||||||
using Bit.Core.Models.Data;
|
using Bit.Core.Models.Data;
|
||||||
|
using Bit.Core.Models.Domain;
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
|
|
||||||
namespace Bit.App.Pages
|
namespace Bit.App.Pages
|
||||||
|
@ -97,11 +101,38 @@ namespace Bit.App.Pages
|
||||||
_messagingService.Send("convertAccountToKeyConnector");
|
_messagingService.Send("convertAccountToKeyConnector");
|
||||||
}
|
}
|
||||||
|
|
||||||
var forcePasswordResetReason = await _stateService.GetForcePasswordResetReasonAsync();
|
await ForcePasswordResetIfNeededAsync();
|
||||||
|
}
|
||||||
|
|
||||||
if (forcePasswordResetReason.HasValue)
|
private async Task ForcePasswordResetIfNeededAsync()
|
||||||
|
{
|
||||||
|
var forcePasswordResetReason = await _stateService.GetForcePasswordResetReasonAsync();
|
||||||
|
switch (forcePasswordResetReason)
|
||||||
{
|
{
|
||||||
_messagingService.Send(Constants.ForceUpdatePassword);
|
case ForcePasswordResetReason.TdeUserWithoutPasswordHasPasswordResetPermission:
|
||||||
|
// TDE users should only have one org
|
||||||
|
var userOrgs = await _stateService.GetOrganizationsAsync();
|
||||||
|
if (userOrgs != null && userOrgs.Any())
|
||||||
|
{
|
||||||
|
_messagingService.Send(Constants.ForceSetPassword, userOrgs.First().Value.Identifier);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_logger.Value.Error("TDE user needs to set password but has no organizations.");
|
||||||
|
|
||||||
|
var rememberedOrg = _stateService.GetRememberedOrgIdentifierAsync();
|
||||||
|
if (rememberedOrg == null)
|
||||||
|
{
|
||||||
|
_logger.Value.Error("TDE user needs to set password but has no organizations or remembered org identifier.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_messagingService.Send(Constants.ForceSetPassword, rememberedOrg);
|
||||||
|
return;
|
||||||
|
case ForcePasswordResetReason.AdminForcePasswordReset:
|
||||||
|
case ForcePasswordResetReason.WeakMasterPasswordOnLogin:
|
||||||
|
_messagingService.Send(Constants.ForceUpdatePassword);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ namespace Bit.App.Pages
|
||||||
_logger = ServiceContainer.Resolve<ILogger>();
|
_logger = ServiceContainer.Resolve<ILogger>();
|
||||||
Attachments = new ExtendedObservableCollection<AttachmentView>();
|
Attachments = new ExtendedObservableCollection<AttachmentView>();
|
||||||
DeleteAttachmentCommand = new Command<AttachmentView>(DeleteAsync);
|
DeleteAttachmentCommand = new Command<AttachmentView>(DeleteAsync);
|
||||||
SubmitAsyncCommand = new AsyncCommand(SubmitAsync, allowsMultipleExecutions: false);
|
SubmitAsyncCommand = CreateDefaultAsyncRelayCommand(SubmitAsync, allowsMultipleExecutions: false);
|
||||||
PageTitle = AppResources.Attachments;
|
PageTitle = AppResources.Attachments;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ using Bit.Core.Exceptions;
|
||||||
using Bit.Core.Models.View;
|
using Bit.Core.Models.View;
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
using Bit.App.Utilities;
|
using Bit.App.Utilities;
|
||||||
|
using CommunityToolkit.Mvvm.Input;
|
||||||
|
|
||||||
namespace Bit.App.Pages
|
namespace Bit.App.Pages
|
||||||
{
|
{
|
||||||
|
@ -28,7 +29,7 @@ namespace Bit.App.Pages
|
||||||
_auditService = ServiceContainer.Resolve<IAuditService>("auditService");
|
_auditService = ServiceContainer.Resolve<IAuditService>("auditService");
|
||||||
_logger = ServiceContainer.Resolve<ILogger>("logger");
|
_logger = ServiceContainer.Resolve<ILogger>("logger");
|
||||||
|
|
||||||
CheckPasswordCommand = new AsyncCommand(CheckPasswordAsync, allowsMultipleExecutions: false);
|
CheckPasswordCommand = CreateDefaultAsyncRelayCommand(CheckPasswordAsync, allowsMultipleExecutions: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CipherView Cipher
|
public CipherView Cipher
|
||||||
|
@ -39,7 +40,7 @@ namespace Bit.App.Pages
|
||||||
|
|
||||||
public string CreationDate => string.Format(AppResources.CreatedXY, Cipher?.CreationDate.ToShortDateString(), Cipher?.CreationDate.ToShortTimeString());
|
public string CreationDate => string.Format(AppResources.CreatedXY, Cipher?.CreationDate.ToShortDateString(), Cipher?.CreationDate.ToShortTimeString());
|
||||||
|
|
||||||
public AsyncCommand CheckPasswordCommand { get; }
|
public AsyncRelayCommand CheckPasswordCommand { get; }
|
||||||
|
|
||||||
protected async Task CheckPasswordAsync()
|
protected async Task CheckPasswordAsync()
|
||||||
{
|
{
|
||||||
|
|
|
@ -16,6 +16,7 @@ using Bit.Core.Utilities;
|
||||||
using Microsoft.Maui.Controls;
|
using Microsoft.Maui.Controls;
|
||||||
using Microsoft.Maui;
|
using Microsoft.Maui;
|
||||||
using Bit.App.Utilities;
|
using Bit.App.Utilities;
|
||||||
|
using CommunityToolkit.Mvvm.Input;
|
||||||
|
|
||||||
#nullable enable
|
#nullable enable
|
||||||
|
|
||||||
|
@ -99,8 +100,8 @@ namespace Bit.App.Pages
|
||||||
UriOptionsCommand = new Command<LoginUriView>(UriOptions);
|
UriOptionsCommand = new Command<LoginUriView>(UriOptions);
|
||||||
FieldOptionsCommand = new Command<ICustomFieldItemViewModel>(FieldOptions);
|
FieldOptionsCommand = new Command<ICustomFieldItemViewModel>(FieldOptions);
|
||||||
PasswordPromptHelpCommand = new Command(PasswordPromptHelp);
|
PasswordPromptHelpCommand = new Command(PasswordPromptHelp);
|
||||||
CopyCommand = new AsyncCommand(CopyTotpClipboardAsync, onException: ex => _logger.Exception(ex), allowsMultipleExecutions: false);
|
CopyCommand = CreateDefaultAsyncRelayCommand(CopyTotpClipboardAsync, onException: ex => _logger.Exception(ex), allowsMultipleExecutions: false);
|
||||||
GenerateUsernameCommand = new AsyncCommand(GenerateUsernameAsync, onException: ex => OnGenerateUsernameException(ex), allowsMultipleExecutions: false);
|
GenerateUsernameCommand = CreateDefaultAsyncRelayCommand(GenerateUsernameAsync, onException: ex => OnGenerateUsernameException(ex), allowsMultipleExecutions: false);
|
||||||
Uris = new ExtendedObservableCollection<LoginUriView>();
|
Uris = new ExtendedObservableCollection<LoginUriView>();
|
||||||
Fields = new ExtendedObservableCollection<ICustomFieldItemViewModel>();
|
Fields = new ExtendedObservableCollection<ICustomFieldItemViewModel>();
|
||||||
Collections = new ExtendedObservableCollection<CollectionViewModel>();
|
Collections = new ExtendedObservableCollection<CollectionViewModel>();
|
||||||
|
@ -163,8 +164,8 @@ namespace Bit.App.Pages
|
||||||
public Command UriOptionsCommand { get; set; }
|
public Command UriOptionsCommand { get; set; }
|
||||||
public Command FieldOptionsCommand { get; set; }
|
public Command FieldOptionsCommand { get; set; }
|
||||||
public Command PasswordPromptHelpCommand { get; set; }
|
public Command PasswordPromptHelpCommand { get; set; }
|
||||||
public AsyncCommand CopyCommand { get; set; }
|
public AsyncRelayCommand CopyCommand { get; set; }
|
||||||
public AsyncCommand GenerateUsernameCommand { get; set; }
|
public AsyncRelayCommand GenerateUsernameCommand { get; set; }
|
||||||
public string CipherId { get; set; }
|
public string CipherId { get; set; }
|
||||||
public string OrganizationId { get; set; }
|
public string OrganizationId { get; set; }
|
||||||
public string FolderId { get; set; }
|
public string FolderId { get; set; }
|
||||||
|
|
|
@ -14,7 +14,7 @@ using Bit.Core.Enums;
|
||||||
using Bit.Core.Exceptions;
|
using Bit.Core.Exceptions;
|
||||||
using Bit.Core.Models.View;
|
using Bit.Core.Models.View;
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
|
using CommunityToolkit.Mvvm.Input;
|
||||||
using Microsoft.Maui.Controls;
|
using Microsoft.Maui.Controls;
|
||||||
using Microsoft.Maui;
|
using Microsoft.Maui;
|
||||||
|
|
||||||
|
@ -66,15 +66,15 @@ namespace Bit.App.Pages
|
||||||
_clipboardService = ServiceContainer.Resolve<IClipboardService>("clipboardService");
|
_clipboardService = ServiceContainer.Resolve<IClipboardService>("clipboardService");
|
||||||
_watchDeviceService = ServiceContainer.Resolve<IWatchDeviceService>();
|
_watchDeviceService = ServiceContainer.Resolve<IWatchDeviceService>();
|
||||||
|
|
||||||
CopyCommand = new AsyncCommand<string>((id) => CopyAsync(id, null), onException: ex => _logger.Exception(ex), allowsMultipleExecutions: false);
|
CopyCommand = CreateDefaultAsyncRelayCommand<string>((id) => CopyAsync(id, null), onException: ex => _logger.Exception(ex), allowsMultipleExecutions: false);
|
||||||
CopyUriCommand = new AsyncCommand<LoginUriView>(uriView => CopyAsync("LoginUri", uriView.Uri), onException: ex => _logger.Exception(ex), allowsMultipleExecutions: false);
|
CopyUriCommand = CreateDefaultAsyncRelayCommand<LoginUriView>(uriView => CopyAsync("LoginUri", uriView.Uri), onException: ex => _logger.Exception(ex), allowsMultipleExecutions: false);
|
||||||
CopyFieldCommand = new AsyncCommand<FieldView>(field => CopyAsync(field.Type == FieldType.Hidden ? "H_FieldValue" : "FieldValue", field.Value), onException: ex => _logger.Exception(ex), allowsMultipleExecutions: false);
|
CopyFieldCommand = CreateDefaultAsyncRelayCommand<FieldView>(field => CopyAsync(field.Type == FieldType.Hidden ? "H_FieldValue" : "FieldValue", field.Value), onException: ex => _logger.Exception(ex), allowsMultipleExecutions: false);
|
||||||
LaunchUriCommand = new Command<ILaunchableView>(LaunchUri);
|
LaunchUriCommand = new Command<ILaunchableView>(LaunchUri);
|
||||||
CloneCommand = new AsyncCommand(CloneAsync, onException: ex => HandleException(ex), allowsMultipleExecutions: false);
|
CloneCommand = CreateDefaultAsyncRelayCommand(CloneAsync, onException: ex => HandleException(ex), allowsMultipleExecutions: false);
|
||||||
TogglePasswordCommand = new Command(TogglePassword);
|
TogglePasswordCommand = new Command(TogglePassword);
|
||||||
ToggleCardNumberCommand = new Command(ToggleCardNumber);
|
ToggleCardNumberCommand = new Command(ToggleCardNumber);
|
||||||
ToggleCardCodeCommand = new Command(ToggleCardCode);
|
ToggleCardCodeCommand = new Command(ToggleCardCode);
|
||||||
DownloadAttachmentCommand = new AsyncCommand<AttachmentView>(DownloadAttachmentAsync, allowsMultipleExecutions: false);
|
DownloadAttachmentCommand = CreateDefaultAsyncRelayCommand<AttachmentView>(DownloadAttachmentAsync, allowsMultipleExecutions: false);
|
||||||
|
|
||||||
PageTitle = AppResources.ViewItem;
|
PageTitle = AppResources.ViewItem;
|
||||||
}
|
}
|
||||||
|
@ -87,7 +87,7 @@ namespace Bit.App.Pages
|
||||||
public Command TogglePasswordCommand { get; set; }
|
public Command TogglePasswordCommand { get; set; }
|
||||||
public Command ToggleCardNumberCommand { get; set; }
|
public Command ToggleCardNumberCommand { get; set; }
|
||||||
public Command ToggleCardCodeCommand { get; set; }
|
public Command ToggleCardCodeCommand { get; set; }
|
||||||
public AsyncCommand<AttachmentView> DownloadAttachmentCommand { get; set; }
|
public AsyncRelayCommand<AttachmentView> DownloadAttachmentCommand { get; set; }
|
||||||
public string CipherId { get; set; }
|
public string CipherId { get; set; }
|
||||||
protected override string[] AdditionalPropertiesToRaiseOnCipherChanged => new string[]
|
protected override string[] AdditionalPropertiesToRaiseOnCipherChanged => new string[]
|
||||||
{
|
{
|
||||||
|
|
|
@ -45,13 +45,13 @@ namespace Bit.App.Pages
|
||||||
_logger = ServiceContainer.Resolve<ILogger>();
|
_logger = ServiceContainer.Resolve<ILogger>();
|
||||||
|
|
||||||
GroupedItems = new ObservableRangeCollection<IGroupingsPageListItem>();
|
GroupedItems = new ObservableRangeCollection<IGroupingsPageListItem>();
|
||||||
CipherOptionsCommand = new AsyncCommand<CipherView>(cipher => AppHelpers.CipherListOptions(Page, cipher, _passwordRepromptService),
|
CipherOptionsCommand = CreateDefaultAsyncRelayCommand<CipherView>(cipher => AppHelpers.CipherListOptions(Page, cipher, _passwordRepromptService),
|
||||||
onException: ex => HandleException(ex),
|
onException: ex => HandleException(ex),
|
||||||
allowsMultipleExecutions: false);
|
allowsMultipleExecutions: false);
|
||||||
SelectCipherCommand = new AsyncCommand<IGroupingsPageListItem>(SelectCipherAsync,
|
SelectCipherCommand = CreateDefaultAsyncRelayCommand<IGroupingsPageListItem>(SelectCipherAsync,
|
||||||
onException: ex => HandleException(ex),
|
onException: ex => HandleException(ex),
|
||||||
allowsMultipleExecutions: false);
|
allowsMultipleExecutions: false);
|
||||||
AddCipherCommand = new AsyncCommand(AddCipherAsync,
|
AddCipherCommand = CreateDefaultAsyncRelayCommand(AddCipherAsync,
|
||||||
onException: ex => HandleException(ex),
|
onException: ex => HandleException(ex),
|
||||||
allowsMultipleExecutions: false);
|
allowsMultipleExecutions: false);
|
||||||
|
|
||||||
|
|
|
@ -52,10 +52,10 @@ namespace Bit.App.Pages
|
||||||
_logger = ServiceContainer.Resolve<ILogger>("logger");
|
_logger = ServiceContainer.Resolve<ILogger>("logger");
|
||||||
|
|
||||||
Ciphers = new ExtendedObservableCollection<CipherView>();
|
Ciphers = new ExtendedObservableCollection<CipherView>();
|
||||||
CipherOptionsCommand = new AsyncCommand<CipherView>(cipher => Utilities.AppHelpers.CipherListOptions(Page, cipher, _passwordRepromptService),
|
CipherOptionsCommand = CreateDefaultAsyncRelayCommand<CipherView>(cipher => Utilities.AppHelpers.CipherListOptions(Page, cipher, _passwordRepromptService),
|
||||||
onException: ex => HandleException(ex),
|
onException: ex => HandleException(ex),
|
||||||
allowsMultipleExecutions: false);
|
allowsMultipleExecutions: false);
|
||||||
AddCipherCommand = new AsyncCommand(AddCipherAsync,
|
AddCipherCommand = CreateDefaultAsyncRelayCommand(AddCipherAsync,
|
||||||
onException: ex => HandleException(ex),
|
onException: ex => HandleException(ex),
|
||||||
allowsMultipleExecutions: false);
|
allowsMultipleExecutions: false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ using Bit.App.Utilities;
|
||||||
using Bit.Core.Abstractions;
|
using Bit.Core.Abstractions;
|
||||||
using Bit.Core.Models.View;
|
using Bit.Core.Models.View;
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
|
using CommunityToolkit.Mvvm.Input;
|
||||||
using Microsoft.Maui.ApplicationModel;
|
using Microsoft.Maui.ApplicationModel;
|
||||||
using Microsoft.Maui.Controls;
|
using Microsoft.Maui.Controls;
|
||||||
using Microsoft.Maui;
|
using Microsoft.Maui;
|
||||||
|
@ -37,13 +37,13 @@ namespace Bit.App.Pages
|
||||||
|
|
||||||
Cipher = cipherView;
|
Cipher = cipherView;
|
||||||
WebsiteIconsEnabled = websiteIconsEnabled;
|
WebsiteIconsEnabled = websiteIconsEnabled;
|
||||||
CopyCommand = new AsyncCommand(CopyToClipboardAsync,
|
CopyCommand = CreateDefaultAsyncRelayCommand(CopyToClipboardAsync,
|
||||||
onException: ex => _logger.Value.Exception(ex),
|
onException: ex => _logger.Value.Exception(ex),
|
||||||
allowsMultipleExecutions: false);
|
allowsMultipleExecutions: false);
|
||||||
_totpTickHelper = new TotpHelper(cipherView);
|
_totpTickHelper = new TotpHelper(cipherView);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AsyncCommand CopyCommand { get; set; }
|
public AsyncRelayCommand CopyCommand { get; set; }
|
||||||
|
|
||||||
public CipherView Cipher
|
public CipherView Cipher
|
||||||
{
|
{
|
||||||
|
|
|
@ -71,10 +71,10 @@ namespace Bit.App.Pages
|
||||||
Refreshing = true;
|
Refreshing = true;
|
||||||
await LoadAsync();
|
await LoadAsync();
|
||||||
});
|
});
|
||||||
CipherOptionsCommand = new AsyncCommand<CipherView>(cipher => AppHelpers.CipherListOptions(Page, cipher, _passwordRepromptService),
|
CipherOptionsCommand = CreateDefaultAsyncRelayCommand<CipherView>(cipher => AppHelpers.CipherListOptions(Page, cipher, _passwordRepromptService),
|
||||||
onException: ex => _logger.Exception(ex),
|
onException: ex => _logger.Exception(ex),
|
||||||
allowsMultipleExecutions: false);
|
allowsMultipleExecutions: false);
|
||||||
VaultFilterCommand = new AsyncCommand(VaultFilterOptionsAsync,
|
VaultFilterCommand = CreateDefaultAsyncRelayCommand(VaultFilterOptionsAsync,
|
||||||
onException: ex => _logger.Exception(ex),
|
onException: ex => _logger.Exception(ex),
|
||||||
allowsMultipleExecutions: false);
|
allowsMultipleExecutions: false);
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ namespace Bit.App.Pages
|
||||||
|
|
||||||
public ScanPageViewModel()
|
public ScanPageViewModel()
|
||||||
{
|
{
|
||||||
ToggleScanModeCommand = new AsyncCommand(ToggleScanMode, onException: HandleException);
|
ToggleScanModeCommand = CreateDefaultAsyncRelayCommand(ToggleScanMode, onException: HandleException);
|
||||||
StartCameraCommand = new Command(StartCamera);
|
StartCameraCommand = new Command(StartCamera);
|
||||||
_platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService");
|
_platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService");
|
||||||
_deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
|
_deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
|
||||||
|
|
|
@ -37,7 +37,7 @@ namespace Bit.App.Pages
|
||||||
OrganizationOptions = new List<KeyValuePair<string, string>>();
|
OrganizationOptions = new List<KeyValuePair<string, string>>();
|
||||||
PageTitle = AppResources.MoveToOrganization;
|
PageTitle = AppResources.MoveToOrganization;
|
||||||
|
|
||||||
MoveCommand = new AsyncCommand(MoveAsync, onException: ex => HandleException(ex), allowsMultipleExecutions: false);
|
MoveCommand = CreateDefaultAsyncRelayCommand(MoveAsync, onException: ex => HandleException(ex), allowsMultipleExecutions: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string CipherId { get; set; }
|
public string CipherId { get; set; }
|
||||||
|
|
|
@ -25,7 +25,7 @@ namespace Bit.App.Pages
|
||||||
|
|
||||||
public VaultFilterViewModel()
|
public VaultFilterViewModel()
|
||||||
{
|
{
|
||||||
VaultFilterCommand = new AsyncCommand(VaultFilterOptionsAsync,
|
VaultFilterCommand = CreateDefaultAsyncRelayCommand(VaultFilterOptionsAsync,
|
||||||
onException: ex => logger.Exception(ex),
|
onException: ex => logger.Exception(ex),
|
||||||
allowsMultipleExecutions: false);
|
allowsMultipleExecutions: false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6227,6 +6227,15 @@ namespace Bit.Core.Resources.Localization {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Set up an unlock option to change your vault timeout action..
|
||||||
|
/// </summary>
|
||||||
|
public static string SetUpAnUnlockOptionToChangeYourVaultTimeoutAction {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("SetUpAnUnlockOptionToChangeYourVaultTimeoutAction", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Set up TOTP.
|
/// Looks up a localized string similar to Set up TOTP.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -7766,6 +7775,24 @@ namespace Bit.Core.Resources.Localization {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Your organization permissions were updated, requiring you to set a master password..
|
||||||
|
/// </summary>
|
||||||
|
public static string YourOrganizationPermissionsWereUpdatedRequeringYouToSetAMasterPassword {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("YourOrganizationPermissionsWereUpdatedRequeringYouToSetAMasterPassword", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Your organization requires you to set a master password..
|
||||||
|
/// </summary>
|
||||||
|
public static string YourOrganizationRequiresYouToSetAMasterPassword {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("YourOrganizationRequiresYouToSetAMasterPassword", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Your request has been sent to your admin..
|
/// Looks up a localized string similar to Your request has been sent to your admin..
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -2861,4 +2861,13 @@ Wil u na die rekening omskakel?</value>
|
||||||
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
||||||
<value>Account logged out.</value>
|
<value>Account logged out.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="YourOrganizationPermissionsWereUpdatedRequeringYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Your organization permissions were updated, requiring you to set a master password.</value>
|
||||||
|
</data>
|
||||||
|
<data name="YourOrganizationRequiresYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Your organization requires you to set a master password.</value>
|
||||||
|
</data>
|
||||||
|
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||||
|
<value>Set up an unlock option to change your vault timeout action.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
|
@ -2751,109 +2751,109 @@
|
||||||
<value>جارٍ تسجيل الدخول</value>
|
<value>جارٍ تسجيل الدخول</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Vault" xml:space="preserve">
|
<data name="Vault" xml:space="preserve">
|
||||||
<value>Vault</value>
|
<value>الخزنة</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Appearance" xml:space="preserve">
|
<data name="Appearance" xml:space="preserve">
|
||||||
<value>Appearance</value>
|
<value>المظهر</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AccountSecurity" xml:space="preserve">
|
<data name="AccountSecurity" xml:space="preserve">
|
||||||
<value>Account security</value>
|
<value>أمان الحساب</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="BitwardenHelpCenter" xml:space="preserve">
|
<data name="BitwardenHelpCenter" xml:space="preserve">
|
||||||
<value>Bitwarden Help Center</value>
|
<value>مركز المساعدة Bitwarden</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ContactBitwardenSupport" xml:space="preserve">
|
<data name="ContactBitwardenSupport" xml:space="preserve">
|
||||||
<value>Contact Bitwarden support</value>
|
<value>اتصل بالدعم Bitwarden</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="CopyAppInformation" xml:space="preserve">
|
<data name="CopyAppInformation" xml:space="preserve">
|
||||||
<value>Copy app information</value>
|
<value>نسخ معلومات التطبيق</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SyncNow" xml:space="preserve">
|
<data name="SyncNow" xml:space="preserve">
|
||||||
<value>Sync now</value>
|
<value>المزامنة الآن</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="UnlockOptions" xml:space="preserve">
|
<data name="UnlockOptions" xml:space="preserve">
|
||||||
<value>Unlock options</value>
|
<value>خيارات فتح القفل</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SessionTimeout" xml:space="preserve">
|
<data name="SessionTimeout" xml:space="preserve">
|
||||||
<value>Session timeout</value>
|
<value>مهلة الجلسة</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SessionTimeoutAction" xml:space="preserve">
|
<data name="SessionTimeoutAction" xml:space="preserve">
|
||||||
<value>Session timeout action</value>
|
<value>إجراء مهلة الجلسة</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AccountFingerprintPhrase" xml:space="preserve">
|
<data name="AccountFingerprintPhrase" xml:space="preserve">
|
||||||
<value>Account fingerprint phrase</value>
|
<value>عبارة بصمة الحساب</value>
|
||||||
<comment>A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing.</comment>
|
<comment>A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="OneHourAndOneMinute" xml:space="preserve">
|
<data name="OneHourAndOneMinute" xml:space="preserve">
|
||||||
<value>One hour and one minute</value>
|
<value>ساعة واحدة ودقيقة واحدة</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="OneHourAndXMinute" xml:space="preserve">
|
<data name="OneHourAndXMinute" xml:space="preserve">
|
||||||
<value>One hour and {0} minutes</value>
|
<value>ساعة واحدة و {0} دقيقة</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="XHoursAndOneMinute" xml:space="preserve">
|
<data name="XHoursAndOneMinute" xml:space="preserve">
|
||||||
<value>{0} hours and one minute</value>
|
<value>{0} ساعات ودقيقة واحدة</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="XHoursAndYMinutes" xml:space="preserve">
|
<data name="XHoursAndYMinutes" xml:space="preserve">
|
||||||
<value>{0} hours and {1} minutes</value>
|
<value>{0} ساعات و {1} دقيقة</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="XHours" xml:space="preserve">
|
<data name="XHours" xml:space="preserve">
|
||||||
<value>{0} hours</value>
|
<value>{0} ساعات</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AutofillServicesExplanationLong" xml:space="preserve">
|
<data name="AutofillServicesExplanationLong" xml:space="preserve">
|
||||||
<value>The Android Autofill Framework is used to assist in filling login information into other apps on your device.</value>
|
<value>يتم استخدام إطار التعبئة التلقائية لأندرويد للمساعدة في ملء معلومات تسجيل الدخول في تطبيقات أخرى على جهازك.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="UseInlineAutofillExplanationLong" xml:space="preserve">
|
<data name="UseInlineAutofillExplanationLong" xml:space="preserve">
|
||||||
<value>Use inline autofill if your selected keyboard supports it. Otherwise, use the default overlay.</value>
|
<value>استخدم التعبئة التلقائية المضمنة إذا كانت لوحة المفاتيح المحددة تدعمها. وإلا استخدم التراكب الافتراضي.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AdditionalOptions" xml:space="preserve">
|
<data name="AdditionalOptions" xml:space="preserve">
|
||||||
<value>Additional options</value>
|
<value>خيارات إضافية</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ContinueToWebApp" xml:space="preserve">
|
<data name="ContinueToWebApp" xml:space="preserve">
|
||||||
<value>Continue to web app?</value>
|
<value>متابعة إلى تطبيق الويب؟</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ContinueToX" xml:space="preserve">
|
<data name="ContinueToX" xml:space="preserve">
|
||||||
<value>Continue to {0}?</value>
|
<value>الإستمرار إلى {0}؟</value>
|
||||||
<comment>The parameter is an URL, like bitwarden.com.</comment>
|
<comment>The parameter is an URL, like bitwarden.com.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="ContinueToHelpCenter" xml:space="preserve">
|
<data name="ContinueToHelpCenter" xml:space="preserve">
|
||||||
<value>Continue to Help center?</value>
|
<value>هل تريد المتابعة إلى مركز المساعدة؟</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ContinueToContactSupport" xml:space="preserve">
|
<data name="ContinueToContactSupport" xml:space="preserve">
|
||||||
<value>Continue to contact support?</value>
|
<value>مواصلة الاتصال بالدعم؟</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ContinueToAppStore" xml:space="preserve">
|
<data name="ContinueToAppStore" xml:space="preserve">
|
||||||
<value>Continue to app store?</value>
|
<value>هل تريد المتابعة إلى متجر التطبيقات؟</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TwoStepLoginDescriptionLong" xml:space="preserve">
|
<data name="TwoStepLoginDescriptionLong" xml:space="preserve">
|
||||||
<value>Make your account more secure by setting up two-step login in the Bitwarden web app.</value>
|
<value>اجعل حسابك أكثر أمنا من خلال إعداد تسجيل الدخول بخطوتين في تطبيق Bitwarden على شبكة الإنترنت.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ChangeMasterPasswordDescriptionLong" xml:space="preserve">
|
<data name="ChangeMasterPasswordDescriptionLong" xml:space="preserve">
|
||||||
<value>You can change your master password on the Bitwarden web app.</value>
|
<value>يمكنك تغيير كلمة المرور الرئيسية الخاصة بك على تطبيق ويب Bitwarden.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="YouCanImportDataToYourVaultOnX" xml:space="preserve">
|
<data name="YouCanImportDataToYourVaultOnX" xml:space="preserve">
|
||||||
<value>You can import data to your vault on {0}.</value>
|
<value>يمكنك استيراد البيانات إلى خزانتك على {0}.</value>
|
||||||
<comment>The parameter is an URL, like vault.bitwarden.com.</comment>
|
<comment>The parameter is an URL, like vault.bitwarden.com.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="LearnMoreAboutHowToUseBitwardenOnTheHelpCenter" xml:space="preserve">
|
<data name="LearnMoreAboutHowToUseBitwardenOnTheHelpCenter" xml:space="preserve">
|
||||||
<value>Learn more about how to use Bitwarden on the Help center.</value>
|
<value>تعرف على المزيد حول كيفية استخدام Bitwarden في مركز المساعدة.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ContactSupportDescriptionLong" xml:space="preserve">
|
<data name="ContactSupportDescriptionLong" xml:space="preserve">
|
||||||
<value>Can’t find what you are looking for? Reach out to Bitwarden support on bitwarden.com.</value>
|
<value>لا يمكن العثور على ما تبحث عنه؟ قم بالتواصل مع دعم Bitwarden على bitwarden.com.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
|
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
|
||||||
<value>Explore more features of your Bitwarden account on the web app.</value>
|
<value>استكشف المزيد من الميزات لحساب Bitwarden الخاص بك على تطبيق الويب.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LearnAboutOrganizationsDescriptionLong" xml:space="preserve">
|
<data name="LearnAboutOrganizationsDescriptionLong" xml:space="preserve">
|
||||||
<value>Bitwarden allows you to share your vault items with others by using an organization. Learn more on the bitwarden.com website.</value>
|
<value>يتيح لك Bitwarden مشاركة عناصر خزنتك مع الآخرين باستخدام حساب المؤسسة. تعرف على المزيد على موقع bitwarden.com على شبكة الإنترنت.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="RateAppDescriptionLong" xml:space="preserve">
|
<data name="RateAppDescriptionLong" xml:space="preserve">
|
||||||
<value>Help others find out if Bitwarden is right for them. Visit the app store and leave a rating now.</value>
|
<value>ساعد الآخرين في معرفة ما إذا كان Bitwarden مناسبا لهم. قم بزيارة متجر التطبيقات وترك التقييم الآن.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="DefaultDarkThemeDescriptionLong" xml:space="preserve">
|
<data name="DefaultDarkThemeDescriptionLong" xml:space="preserve">
|
||||||
<value>Choose the dark theme to use when your device’s dark mode is in use</value>
|
<value>اختر السمة المظلمة لاستخدامها عند استخدام الوضع المظلم لجهازك</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="CreatedXY" xml:space="preserve">
|
<data name="CreatedXY" xml:space="preserve">
|
||||||
<value>Created {0}, {1}</value>
|
<value>أنشئ {0}، {1}</value>
|
||||||
<comment>To state the date/time in which the cipher was created: Created 03/21/2023, 09:25 AM. First parameter is the date and the second parameter is the time.</comment>
|
<comment>To state the date/time in which the cipher was created: Created 03/21/2023, 09:25 AM. First parameter is the date and the second parameter is the time.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="TooManyAttempts" xml:space="preserve">
|
<data name="TooManyAttempts" xml:space="preserve">
|
||||||
|
@ -2862,4 +2862,13 @@
|
||||||
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
||||||
<value>تم تسجيل الخروج من الحساب.</value>
|
<value>تم تسجيل الخروج من الحساب.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="YourOrganizationPermissionsWereUpdatedRequeringYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Your organization permissions were updated, requiring you to set a master password.</value>
|
||||||
|
</data>
|
||||||
|
<data name="YourOrganizationRequiresYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Your organization requires you to set a master password.</value>
|
||||||
|
</data>
|
||||||
|
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||||
|
<value>Set up an unlock option to change your vault timeout action.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
|
@ -2860,4 +2860,13 @@ Bu hesaba keçmək istəyirsiniz?</value>
|
||||||
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
||||||
<value>Hesabdan çıxış edildi.</value>
|
<value>Hesabdan çıxış edildi.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="YourOrganizationPermissionsWereUpdatedRequeringYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Təşkilatınızın icazələri güncəlləndi və bir ana parol ayarlamağınızı tələb edir.</value>
|
||||||
|
</data>
|
||||||
|
<data name="YourOrganizationRequiresYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Təşkilatınız bir ana parol ayarlamağı tələb edir.</value>
|
||||||
|
</data>
|
||||||
|
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||||
|
<value>Anbar vaxt bitməsi əməliyyatınızı dəyişdirmək üçün bir kilid açma seçimi qurun.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
|
@ -2861,4 +2861,13 @@
|
||||||
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
||||||
<value>Account logged out.</value>
|
<value>Account logged out.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="YourOrganizationPermissionsWereUpdatedRequeringYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Your organization permissions were updated, requiring you to set a master password.</value>
|
||||||
|
</data>
|
||||||
|
<data name="YourOrganizationRequiresYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Your organization requires you to set a master password.</value>
|
||||||
|
</data>
|
||||||
|
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||||
|
<value>Set up an unlock option to change your vault timeout action.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
|
@ -2861,4 +2861,13 @@ select Add TOTP to store the key safely</value>
|
||||||
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
||||||
<value>Акаунтът е отписан.</value>
|
<value>Акаунтът е отписан.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="YourOrganizationPermissionsWereUpdatedRequeringYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Правата Ви в организацията бяха променени, необходимо е да зададете главна парола.</value>
|
||||||
|
</data>
|
||||||
|
<data name="YourOrganizationRequiresYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Организацията Ви изисква да зададете главна парола.</value>
|
||||||
|
</data>
|
||||||
|
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||||
|
<value>Задайте начин за отключване, за да може да промените действието при изтичане на времето за достъп до трезора.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
|
@ -2862,4 +2862,13 @@ Do you want to switch to this account?</value>
|
||||||
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
||||||
<value>Account logged out.</value>
|
<value>Account logged out.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="YourOrganizationPermissionsWereUpdatedRequeringYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Your organization permissions were updated, requiring you to set a master password.</value>
|
||||||
|
</data>
|
||||||
|
<data name="YourOrganizationRequiresYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Your organization requires you to set a master password.</value>
|
||||||
|
</data>
|
||||||
|
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||||
|
<value>Set up an unlock option to change your vault timeout action.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
|
@ -2860,4 +2860,13 @@ Skeniranje će biti izvršeno automatski.</value>
|
||||||
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
||||||
<value>Account logged out.</value>
|
<value>Account logged out.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="YourOrganizationPermissionsWereUpdatedRequeringYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Your organization permissions were updated, requiring you to set a master password.</value>
|
||||||
|
</data>
|
||||||
|
<data name="YourOrganizationRequiresYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Your organization requires you to set a master password.</value>
|
||||||
|
</data>
|
||||||
|
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||||
|
<value>Set up an unlock option to change your vault timeout action.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
|
@ -2861,4 +2861,13 @@ Voleu canviar a aquest compte?</value>
|
||||||
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
||||||
<value>S'ha tancat la sessió del compte.</value>
|
<value>S'ha tancat la sessió del compte.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="YourOrganizationPermissionsWereUpdatedRequeringYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Els permisos de la vostra organització s'han actualitzat, cal que establiu una contrasenya mestra.</value>
|
||||||
|
</data>
|
||||||
|
<data name="YourOrganizationRequiresYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>La vostra organització requereix que establiu una contrasenya mestra.</value>
|
||||||
|
</data>
|
||||||
|
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||||
|
<value>Configura una opció de desbloqueig per canviar l'acció de temps d'espera de la caixa forta.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
|
@ -375,7 +375,7 @@
|
||||||
<comment>Validation message for when a form field is left blank and is required to be entered.</comment>
|
<comment>Validation message for when a form field is left blank and is required to be entered.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="ValueHasBeenCopied" xml:space="preserve">
|
<data name="ValueHasBeenCopied" xml:space="preserve">
|
||||||
<value>{0} bylo zkopírováno.</value>
|
<value>{0}: zkopírováno</value>
|
||||||
<comment>Confirmation message after successfully copying a value to the clipboard.</comment>
|
<comment>Confirmation message after successfully copying a value to the clipboard.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="VerifyFingerprint" xml:space="preserve">
|
<data name="VerifyFingerprint" xml:space="preserve">
|
||||||
|
@ -499,7 +499,7 @@
|
||||||
<value>Pro spuštění rozšíření klepněte na ikonu Bitwardenu v menu.</value>
|
<value>Pro spuštění rozšíření klepněte na ikonu Bitwardenu v menu.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ExtensionTurnOn" xml:space="preserve">
|
<data name="ExtensionTurnOn" xml:space="preserve">
|
||||||
<value>Pro zapnutí Bitwardenu v prohlížeči Safari a dalších aplikacích klepněte na ikonu „Další“ v dolní části menu.</value>
|
<value>Pro zapnutí Bitwardenu v prohlížeči Safari a dalších aplikacích klepněte na ikonu "Další“ v dolní části menu.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Favorite" xml:space="preserve">
|
<data name="Favorite" xml:space="preserve">
|
||||||
<value>Oblíbené</value>
|
<value>Oblíbené</value>
|
||||||
|
@ -958,10 +958,10 @@ Načtení proběhne automaticky.</value>
|
||||||
<value>Vlastní prostředí</value>
|
<value>Vlastní prostředí</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="CustomEnvironmentFooter" xml:space="preserve">
|
<data name="CustomEnvironmentFooter" xml:space="preserve">
|
||||||
<value>Pro pokročilé uživatele. Můžete zadat základní URL adresu každé služby zvlášť.</value>
|
<value>Pro pokročilé uživatele. Můžete zadat základní URL každé služby zvlášť.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="EnvironmentSaved" xml:space="preserve">
|
<data name="EnvironmentSaved" xml:space="preserve">
|
||||||
<value>URL adresy vlastního prostředí byly uloženy.</value>
|
<value>URL vlastního prostředí byly uloženy.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="FormattedIncorrectly" xml:space="preserve">
|
<data name="FormattedIncorrectly" xml:space="preserve">
|
||||||
<value>{0} nemá správný formát.</value>
|
<value>{0} nemá správný formát.</value>
|
||||||
|
@ -975,7 +975,7 @@ Načtení proběhne automaticky.</value>
|
||||||
<value>Vlastní hostované prostředí</value>
|
<value>Vlastní hostované prostředí</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SelfHostedEnvironmentFooter" xml:space="preserve">
|
<data name="SelfHostedEnvironmentFooter" xml:space="preserve">
|
||||||
<value>Zadejte základní URL adresu vlastní hostované aplikace Bitwarden.</value>
|
<value>Zadejte základní URL vlastní hostované aplikace Bitwarden.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ServerUrl" xml:space="preserve">
|
<data name="ServerUrl" xml:space="preserve">
|
||||||
<value>URL serveru</value>
|
<value>URL serveru</value>
|
||||||
|
@ -1023,13 +1023,13 @@ Načtení proběhne automaticky.</value>
|
||||||
<value>Adresa 3</value>
|
<value>Adresa 3</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="April" xml:space="preserve">
|
<data name="April" xml:space="preserve">
|
||||||
<value>Duben</value>
|
<value>duben</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="August" xml:space="preserve">
|
<data name="August" xml:space="preserve">
|
||||||
<value>Srpen</value>
|
<value>srpen</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Brand" xml:space="preserve">
|
<data name="Brand" xml:space="preserve">
|
||||||
<value>Značka</value>
|
<value>Vydavatel</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="CardholderName" xml:space="preserve">
|
<data name="CardholderName" xml:space="preserve">
|
||||||
<value>Jméno držitele karty</value>
|
<value>Jméno držitele karty</value>
|
||||||
|
@ -1044,10 +1044,10 @@ Načtení proběhne automaticky.</value>
|
||||||
<value>Stát</value>
|
<value>Stát</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="December" xml:space="preserve">
|
<data name="December" xml:space="preserve">
|
||||||
<value>Prosinec</value>
|
<value>prosinec</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Dr" xml:space="preserve">
|
<data name="Dr" xml:space="preserve">
|
||||||
<value>MUDr.</value>
|
<value>Dr.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ExpirationMonth" xml:space="preserve">
|
<data name="ExpirationMonth" xml:space="preserve">
|
||||||
<value>Měsíc expirace</value>
|
<value>Měsíc expirace</value>
|
||||||
|
@ -1056,19 +1056,19 @@ Načtení proběhne automaticky.</value>
|
||||||
<value>Rok expirace</value>
|
<value>Rok expirace</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="February" xml:space="preserve">
|
<data name="February" xml:space="preserve">
|
||||||
<value>Únor</value>
|
<value>únor</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="FirstName" xml:space="preserve">
|
<data name="FirstName" xml:space="preserve">
|
||||||
<value>Křestní jméno</value>
|
<value>Křestní jméno</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="January" xml:space="preserve">
|
<data name="January" xml:space="preserve">
|
||||||
<value>Leden</value>
|
<value>leden</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="July" xml:space="preserve">
|
<data name="July" xml:space="preserve">
|
||||||
<value>Červenec</value>
|
<value>červenec</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="June" xml:space="preserve">
|
<data name="June" xml:space="preserve">
|
||||||
<value>Červen</value>
|
<value>červen</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LastName" xml:space="preserve">
|
<data name="LastName" xml:space="preserve">
|
||||||
<value>Příjmení</value>
|
<value>Příjmení</value>
|
||||||
|
@ -1080,10 +1080,10 @@ Načtení proběhne automaticky.</value>
|
||||||
<value>Číslo dokladu totožnosti</value>
|
<value>Číslo dokladu totožnosti</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="March" xml:space="preserve">
|
<data name="March" xml:space="preserve">
|
||||||
<value>Březen</value>
|
<value>březen</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="May" xml:space="preserve">
|
<data name="May" xml:space="preserve">
|
||||||
<value>Květen</value>
|
<value>květen</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MiddleName" xml:space="preserve">
|
<data name="MiddleName" xml:space="preserve">
|
||||||
<value>Prostřední jméno</value>
|
<value>Prostřední jméno</value>
|
||||||
|
@ -1101,10 +1101,10 @@ Načtení proběhne automaticky.</value>
|
||||||
<value>Neutrální</value>
|
<value>Neutrální</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="November" xml:space="preserve">
|
<data name="November" xml:space="preserve">
|
||||||
<value>Listopad</value>
|
<value>listopad</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="October" xml:space="preserve">
|
<data name="October" xml:space="preserve">
|
||||||
<value>Říjen</value>
|
<value>říjen</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="PassportNumber" xml:space="preserve">
|
<data name="PassportNumber" xml:space="preserve">
|
||||||
<value>Číslo cestovního pasu</value>
|
<value>Číslo cestovního pasu</value>
|
||||||
|
@ -1113,10 +1113,10 @@ Načtení proběhne automaticky.</value>
|
||||||
<value>Telefon</value>
|
<value>Telefon</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="September" xml:space="preserve">
|
<data name="September" xml:space="preserve">
|
||||||
<value>Září</value>
|
<value>září</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SSN" xml:space="preserve">
|
<data name="SSN" xml:space="preserve">
|
||||||
<value>Číslo sociálního pojištění</value>
|
<value>Rodné číslo</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="StateProvince" xml:space="preserve">
|
<data name="StateProvince" xml:space="preserve">
|
||||||
<value>Kraj / Provincie</value>
|
<value>Kraj / Provincie</value>
|
||||||
|
@ -1298,22 +1298,22 @@ Načtení proběhne automaticky.</value>
|
||||||
<value>Přistupujte k Vašemu trezoru přímo z Vaší klávesnice pro rychlejší automatické vyplnění hesel.</value>
|
<value>Přistupujte k Vašemu trezoru přímo z Vaší klávesnice pro rychlejší automatické vyplnění hesel.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AutofillTurnOn" xml:space="preserve">
|
<data name="AutofillTurnOn" xml:space="preserve">
|
||||||
<value>Pokyny pro zapnutí automatického vyplňování hesel na vašem zařízení:</value>
|
<value>Pokyny pro zapnutí automatického vyplňování hesel na Vašem zařízení:</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AutofillTurnOn1" xml:space="preserve">
|
<data name="AutofillTurnOn1" xml:space="preserve">
|
||||||
<value>1. Přejděte do aplikace "Nastavení" v iOS</value>
|
<value>1. Přejděte do aplikace "Nastavení" v iOS</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AutofillTurnOn2" xml:space="preserve">
|
<data name="AutofillTurnOn2" xml:space="preserve">
|
||||||
<value>2. Klepněte na „Hesla“ > „Volby hesla“</value>
|
<value>2. Klepněte na "Hesla" > "Volby hesla"</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AutofillTurnOn3" xml:space="preserve">
|
<data name="AutofillTurnOn3" xml:space="preserve">
|
||||||
<value>3. Povolte „Automatické vyplnění hesel“</value>
|
<value>3. Zapněte přepínač u položky "Automatické vyplnění hesel"</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AutofillTurnOn4" xml:space="preserve">
|
<data name="AutofillTurnOn4" xml:space="preserve">
|
||||||
<value>4. Najděte sekci „Povolit vyplňování z“</value>
|
<value>4. Najděte sekci "Povolit vyplňování z:"</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AutofillTurnOn5" xml:space="preserve">
|
<data name="AutofillTurnOn5" xml:space="preserve">
|
||||||
<value>5. Zvolte „Bitwarden“</value>
|
<value>5. Zvolte "Bitwarden"</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="PasswordAutofill" xml:space="preserve">
|
<data name="PasswordAutofill" xml:space="preserve">
|
||||||
<value>Automatické vyplňování hesel</value>
|
<value>Automatické vyplňování hesel</value>
|
||||||
|
@ -1562,7 +1562,7 @@ Načtení proběhne automaticky.</value>
|
||||||
<value>Chcete po restartování aplikace vyžadovat hlavní heslo pro odemknutí trezoru?</value>
|
<value>Chcete po restartování aplikace vyžadovat hlavní heslo pro odemknutí trezoru?</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Black" xml:space="preserve">
|
<data name="Black" xml:space="preserve">
|
||||||
<value>Černá</value>
|
<value>Černý</value>
|
||||||
<comment>The color black</comment>
|
<comment>The color black</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="Nord" xml:space="preserve">
|
<data name="Nord" xml:space="preserve">
|
||||||
|
@ -1570,7 +1570,7 @@ Načtení proběhne automaticky.</value>
|
||||||
<comment>'Nord' is the name of a specific color scheme. It should not be translated.</comment>
|
<comment>'Nord' is the name of a specific color scheme. It should not be translated.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="SolarizedDark" xml:space="preserve">
|
<data name="SolarizedDark" xml:space="preserve">
|
||||||
<value>Tmavý – Solarized</value>
|
<value>Tmavý (solární)</value>
|
||||||
<comment>'Solarized Dark' is the name of a specific color scheme. It should not be translated.</comment>
|
<comment>'Solarized Dark' is the name of a specific color scheme. It should not be translated.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="AutofillBlockedUris" xml:space="preserve">
|
<data name="AutofillBlockedUris" xml:space="preserve">
|
||||||
|
@ -1947,7 +1947,7 @@ Načtení proběhne automaticky.</value>
|
||||||
<value>Nové heslo</value>
|
<value>Nové heslo</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="PasswordInfo" xml:space="preserve">
|
<data name="PasswordInfo" xml:space="preserve">
|
||||||
<value>Volitelně vyžadovat heslo pro přístup k tomuto Send.</value>
|
<value>Volitelně bude vyžadovat heslo pro přístup k tomuto Send.</value>
|
||||||
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="RemovePassword" xml:space="preserve">
|
<data name="RemovePassword" xml:space="preserve">
|
||||||
|
@ -1967,7 +1967,7 @@ Načtení proběhne automaticky.</value>
|
||||||
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="DisableSend" xml:space="preserve">
|
<data name="DisableSend" xml:space="preserve">
|
||||||
<value>Deaktivuje tento Send, díky čemuž k němu nebude moci nikdo přistoupit</value>
|
<value>Deaktivovat tento Send (nikdo k němu nebude mít přístup)</value>
|
||||||
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="NoSends" xml:space="preserve">
|
<data name="NoSends" xml:space="preserve">
|
||||||
|
@ -2299,13 +2299,13 @@ Načtení proběhne automaticky.</value>
|
||||||
<value>Nastavení zámku na "Nikdy" ponechá Váš trezor k dispozici komukoli s přístupem k Vašemu zařízení. Používáte-li tuto možnost, měli byste zajistit, aby Vaše zařízení bylo náležitě chráněno.</value>
|
<value>Nastavení zámku na "Nikdy" ponechá Váš trezor k dispozici komukoli s přístupem k Vašemu zařízení. Používáte-li tuto možnost, měli byste zajistit, aby Vaše zařízení bylo náležitě chráněno.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="EnvironmentPageUrlsError" xml:space="preserve">
|
<data name="EnvironmentPageUrlsError" xml:space="preserve">
|
||||||
<value>Jedna nebo více zadaných adres URL jsou neplatné. Zkontrolujte je a opakujte akci znovu.</value>
|
<value>Jedna nebo více zadaných URL jsou neplatné. Zkontrolujte je a opakujte akci znovu.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="GenericErrorMessage" xml:space="preserve">
|
<data name="GenericErrorMessage" xml:space="preserve">
|
||||||
<value>Nepodařilo se nám zpracovat Váš požadavek. Zkuste to znovu nebo nás kontaktujte.</value>
|
<value>Nepodařilo se nám zpracovat Váš požadavek. Zkuste to znovu nebo nás kontaktujte.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AllowScreenCapture" xml:space="preserve">
|
<data name="AllowScreenCapture" xml:space="preserve">
|
||||||
<value>Povolit záznam obrazovky</value>
|
<value>Zapnout záznam obrazovky</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AreYouSureYouWantToEnableScreenCapture" xml:space="preserve">
|
<data name="AreYouSureYouWantToEnableScreenCapture" xml:space="preserve">
|
||||||
<value>Opravdu chcete zapnout záznam obrazovky?</value>
|
<value>Opravdu chcete zapnout záznam obrazovky?</value>
|
||||||
|
@ -2544,7 +2544,7 @@ Chcete se přepnout na tento účet?</value>
|
||||||
<value>Jazyk byl změněn na {0}. Pro zobrazení změn restartujte aplikaci.</value>
|
<value>Jazyk byl změněn na {0}. Pro zobrazení změn restartujte aplikaci.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LanguageChangeRequiresAppRestart" xml:space="preserve">
|
<data name="LanguageChangeRequiresAppRestart" xml:space="preserve">
|
||||||
<value>Změna jazyku vyžaduje restart aplikace</value>
|
<value>Změna jazyka vyžaduje restart aplikace.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="DefaultSystem" xml:space="preserve">
|
<data name="DefaultSystem" xml:space="preserve">
|
||||||
<value>Výchozí (Systémový)</value>
|
<value>Výchozí (Systémový)</value>
|
||||||
|
@ -2860,4 +2860,13 @@ Chcete se přepnout na tento účet?</value>
|
||||||
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
||||||
<value>Účet byl odhlášen.</value>
|
<value>Účet byl odhlášen.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="YourOrganizationPermissionsWereUpdatedRequeringYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Oprávnění Vaší organizace byla aktualizována. To vyžaduje nastavení hlavního hesla.</value>
|
||||||
|
</data>
|
||||||
|
<data name="YourOrganizationRequiresYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Vaše organizace vyžaduje nastavení hlavního hesla.</value>
|
||||||
|
</data>
|
||||||
|
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||||
|
<value>Nastavte volbu odemknutí, abyste změnili časový limit Vašeho trezoru.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
|
@ -2862,4 +2862,13 @@ Do you want to switch to this account?</value>
|
||||||
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
||||||
<value>Account logged out.</value>
|
<value>Account logged out.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="YourOrganizationPermissionsWereUpdatedRequeringYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Your organization permissions were updated, requiring you to set a master password.</value>
|
||||||
|
</data>
|
||||||
|
<data name="YourOrganizationRequiresYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Your organization requires you to set a master password.</value>
|
||||||
|
</data>
|
||||||
|
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||||
|
<value>Set up an unlock option to change your vault timeout action.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
|
@ -2861,4 +2861,13 @@ Vil du skifte til denne konto?</value>
|
||||||
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
||||||
<value>Konto logget ud.</value>
|
<value>Konto logget ud.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="YourOrganizationPermissionsWereUpdatedRequeringYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Organisationstilladelserne er blevet opdateret, og der kræves nu oprettelse af en hovedadgangskode.</value>
|
||||||
|
</data>
|
||||||
|
<data name="YourOrganizationRequiresYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Organisationen kræver, at der oprettes en hovedadgangskode.</value>
|
||||||
|
</data>
|
||||||
|
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||||
|
<value>Opsæt en oplåsningsmetode for at ændre Bokstimeouthandlingen.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
|
@ -946,7 +946,7 @@ Das Scannen erfolgt automatisch.</value>
|
||||||
<value>Du kannst diese Funktion nicht nutzen, solange du deinen Verschlüsselungsschlüssel nicht aktualisiert hast.</value>
|
<value>Du kannst diese Funktion nicht nutzen, solange du deinen Verschlüsselungsschlüssel nicht aktualisiert hast.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="EncryptionKeyMigrationRequiredDescriptionLong" xml:space="preserve">
|
<data name="EncryptionKeyMigrationRequiredDescriptionLong" xml:space="preserve">
|
||||||
<value>Encryption key migration required. Please login through the web vault to update your encryption key.</value>
|
<value>Verschlüsselungscode-Migration erforderlich. Bitte melde dich über den Web-Tresor an, um deinen Verschlüsselungscode zu aktualisieren.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LearnMore" xml:space="preserve">
|
<data name="LearnMore" xml:space="preserve">
|
||||||
<value>Mehr erfahren</value>
|
<value>Mehr erfahren</value>
|
||||||
|
@ -2860,4 +2860,13 @@ Möchtest du zu diesem Konto wechseln?</value>
|
||||||
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
||||||
<value>Konto abgemeldet.</value>
|
<value>Konto abgemeldet.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="YourOrganizationPermissionsWereUpdatedRequeringYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Deine Organisationsberechtigungen wurden aktualisiert und verlangen, dass du ein Master-Passwort festlegen musst.</value>
|
||||||
|
</data>
|
||||||
|
<data name="YourOrganizationRequiresYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Deine Organisation verlangt, dass du ein Master-Passwort festlegen musst.</value>
|
||||||
|
</data>
|
||||||
|
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||||
|
<value>Richte eine Entsperroption ein, um deine Aktion bei Tresor-Timeout zu ändern.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
|
@ -247,8 +247,7 @@
|
||||||
<comment>Description message for the alert when internet connection is required to continue.</comment>
|
<comment>Description message for the alert when internet connection is required to continue.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="InternetConnectionRequiredTitle" xml:space="preserve">
|
<data name="InternetConnectionRequiredTitle" xml:space="preserve">
|
||||||
<value>28/5000
|
<value>Απαιτείται σύνδεση στο διαδίκτυο</value>
|
||||||
Απαιτείται σύνδεση στο διαδίκτυο</value>
|
|
||||||
<comment>Title for the alert when internet connection is required to continue.</comment>
|
<comment>Title for the alert when internet connection is required to continue.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="InvalidMasterPassword" xml:space="preserve">
|
<data name="InvalidMasterPassword" xml:space="preserve">
|
||||||
|
@ -946,7 +945,7 @@
|
||||||
<value>Δεν μπορείτε να χρησιμοποιήσετε αυτήν τη δυνατότητα μέχρι να ενημερώσετε το κλειδί κρυπτογράφησης.</value>
|
<value>Δεν μπορείτε να χρησιμοποιήσετε αυτήν τη δυνατότητα μέχρι να ενημερώσετε το κλειδί κρυπτογράφησης.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="EncryptionKeyMigrationRequiredDescriptionLong" xml:space="preserve">
|
<data name="EncryptionKeyMigrationRequiredDescriptionLong" xml:space="preserve">
|
||||||
<value>Encryption key migration required. Please login through the web vault to update your encryption key.</value>
|
<value>Απαιτείται μεταφορά του κλειδιού κρυπτογράφησης. Παρακαλούμε συνδεθείτε μέσω του web vault για να ενημερώσετε το κλειδί κρυπτογράφησης.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LearnMore" xml:space="preserve">
|
<data name="LearnMore" xml:space="preserve">
|
||||||
<value>Μάθετε Περισσότερα</value>
|
<value>Μάθετε Περισσότερα</value>
|
||||||
|
@ -2623,28 +2622,28 @@
|
||||||
<value>Τρέχων κύριος κωδικός</value>
|
<value>Τρέχων κύριος κωδικός</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LoggedIn" xml:space="preserve">
|
<data name="LoggedIn" xml:space="preserve">
|
||||||
<value>Logged in!</value>
|
<value>Έχετε συνδεθεί!</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ApproveWithMyOtherDevice" xml:space="preserve">
|
<data name="ApproveWithMyOtherDevice" xml:space="preserve">
|
||||||
<value>Approve with my other device</value>
|
<value>Έγκριση μέσω άλλης συσκευής μου</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="RequestAdminApproval" xml:space="preserve">
|
<data name="RequestAdminApproval" xml:space="preserve">
|
||||||
<value>Request admin approval</value>
|
<value>Αίτηση έγκρισης από διαχειριστή</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ApproveWithMasterPassword" xml:space="preserve">
|
<data name="ApproveWithMasterPassword" xml:space="preserve">
|
||||||
<value>Approve with master password</value>
|
<value>Έγκριση με τον κύριο κωδικό πρόσβασης</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TurnOffUsingPublicDevice" xml:space="preserve">
|
<data name="TurnOffUsingPublicDevice" xml:space="preserve">
|
||||||
<value>Turn off using a public device</value>
|
<value>Απενεργοποίηση με χρήση δημόσιας συσκευής</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="RememberThisDevice" xml:space="preserve">
|
<data name="RememberThisDevice" xml:space="preserve">
|
||||||
<value>Remember this device</value>
|
<value>Απομνημόνευση αυτής της συσκευής</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Passkey" xml:space="preserve">
|
<data name="Passkey" xml:space="preserve">
|
||||||
<value>Συνθηματικό</value>
|
<value>Κλειδί πρόσβασης</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Passkeys" xml:space="preserve">
|
<data name="Passkeys" xml:space="preserve">
|
||||||
<value>Συνθηματικά</value>
|
<value>Κλειδιά πρόσβασης</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Application" xml:space="preserve">
|
<data name="Application" xml:space="preserve">
|
||||||
<value>Εφαρμογή</value>
|
<value>Εφαρμογή</value>
|
||||||
|
@ -2659,13 +2658,13 @@
|
||||||
<value>Το κλειδί πρόσβασης δεν θα αντιγραφεί στο κλωνοποιημένο στοιχείο. Θέλετε να συνεχίσετε την κλωνοποίηση αυτού του στοιχείου;</value>
|
<value>Το κλειδί πρόσβασης δεν θα αντιγραφεί στο κλωνοποιημένο στοιχείο. Θέλετε να συνεχίσετε την κλωνοποίηση αυτού του στοιχείου;</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="CopyApplication" xml:space="preserve">
|
<data name="CopyApplication" xml:space="preserve">
|
||||||
<value>Copy application</value>
|
<value>Αντιγραφή εφαρμογής</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AvailableForTwoStepLogin" xml:space="preserve">
|
<data name="AvailableForTwoStepLogin" xml:space="preserve">
|
||||||
<value>Διαθέσιμο για σύνδεση με δύο βήματα</value>
|
<value>Διαθέσιμο για σύνδεση με δύο βήματα</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MasterPasswordRePromptHelp" xml:space="preserve">
|
<data name="MasterPasswordRePromptHelp" xml:space="preserve">
|
||||||
<value>Master password re-prompt help</value>
|
<value>Βοήθεια προτροπής κύριου κωδικού πρόσβασης</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="UnlockingMayFailDueToInsufficientMemoryDecreaseYourKDFMemorySettingsToResolve" xml:space="preserve">
|
<data name="UnlockingMayFailDueToInsufficientMemoryDecreaseYourKDFMemorySettingsToResolve" xml:space="preserve">
|
||||||
<value>Το ξεκλείδωμα μπορεί να αποτύχει λόγω ανεπαρκούς μνήμης. Μειώστε τις ρυθμίσεις μνήμης KDF ή ρυθμίστε το βιομετρικό ξεκλείδωμα για επίλυση.</value>
|
<value>Το ξεκλείδωμα μπορεί να αποτύχει λόγω ανεπαρκούς μνήμης. Μειώστε τις ρυθμίσεις μνήμης KDF ή ρυθμίστε το βιομετρικό ξεκλείδωμα για επίλυση.</value>
|
||||||
|
@ -2677,188 +2676,197 @@
|
||||||
<value>Μη έγκυρο API token</value>
|
<value>Μη έγκυρο API token</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AdminApprovalRequested" xml:space="preserve">
|
<data name="AdminApprovalRequested" xml:space="preserve">
|
||||||
<value>Admin approval requested</value>
|
<value>Ζητήθηκε έγκριση διαχειριστή</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="YourRequestHasBeenSentToYourAdmin" xml:space="preserve">
|
<data name="YourRequestHasBeenSentToYourAdmin" xml:space="preserve">
|
||||||
<value>Your request has been sent to your admin.</value>
|
<value>Το αίτημά σας έχει σταλεί στον διαχειριστή σας.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="YouWillBeNotifiedOnceApproved" xml:space="preserve">
|
<data name="YouWillBeNotifiedOnceApproved" xml:space="preserve">
|
||||||
<value>You will be notified once approved. </value>
|
<value>Θα ειδοποιηθείτε μόλις εγκριθεί. </value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TroubleLoggingIn" xml:space="preserve">
|
<data name="TroubleLoggingIn" xml:space="preserve">
|
||||||
<value>Trouble logging in?</value>
|
<value>Δεν μπορείτε να συνδεθείτε;</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LoggingInAsX" xml:space="preserve">
|
<data name="LoggingInAsX" xml:space="preserve">
|
||||||
<value>Logging in as {0}</value>
|
<value>Σύνδεση ως {0}</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="VaultTimeoutActionChangedToLogOut" xml:space="preserve">
|
<data name="VaultTimeoutActionChangedToLogOut" xml:space="preserve">
|
||||||
<value>Vault timeout action changed to log out</value>
|
<value>Η ενέργεια στη λήξη χρόνου του vault άλλαξε σε αποσύνδεση</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="BlockAutoFill" xml:space="preserve">
|
<data name="BlockAutoFill" xml:space="preserve">
|
||||||
<value>Block auto-fill</value>
|
<value>Αποκλείστε την αυτόματη συμπλήρωση</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AutoFillWillNotBeOfferedForTheseURIs" xml:space="preserve">
|
<data name="AutoFillWillNotBeOfferedForTheseURIs" xml:space="preserve">
|
||||||
<value>Auto-fill will not be offered for these URIs.</value>
|
<value>Η αυτόματη συμπλήρωση δε θα προσφέρεται για αυτά τα URI.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="NewBlockedURI" xml:space="preserve">
|
<data name="NewBlockedURI" xml:space="preserve">
|
||||||
<value>New blocked URI</value>
|
<value>Νέο αποκλεισμένο URI</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="URISaved" xml:space="preserve">
|
<data name="URISaved" xml:space="preserve">
|
||||||
<value>URI saved</value>
|
<value>URI αποθηκεύτηκε</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="InvalidFormatUseHttpsHttpOrAndroidApp" xml:space="preserve">
|
<data name="InvalidFormatUseHttpsHttpOrAndroidApp" xml:space="preserve">
|
||||||
<value>Invalid format. Use https://, http://, or androidapp://</value>
|
<value>Μη έγκυρη μορφή. Χρησιμοποιήστε https://, http://, ή androidapp://</value>
|
||||||
<comment>https://, http://, androidapp:// should not be translated</comment>
|
<comment>https://, http://, androidapp:// should not be translated</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="EditURI" xml:space="preserve">
|
<data name="EditURI" xml:space="preserve">
|
||||||
<value>Edit URI</value>
|
<value>Επεξεργασία του URI</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="EnterURI" xml:space="preserve">
|
<data name="EnterURI" xml:space="preserve">
|
||||||
<value>Enter URI</value>
|
<value>Καταχωρήστε URI</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="FormatXSeparateMultipleURIsWithAComma" xml:space="preserve">
|
<data name="FormatXSeparateMultipleURIsWithAComma" xml:space="preserve">
|
||||||
<value>Format: {0}. Separate multiple URIs with a comma.</value>
|
<value>Μορφή: {0}. Διαχωρίστε τα πολλαπλά URI με κόμμα.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="FormatX" xml:space="preserve">
|
<data name="FormatX" xml:space="preserve">
|
||||||
<value>Format: {0}</value>
|
<value>Μορφή: {0}</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="InvalidURI" xml:space="preserve">
|
<data name="InvalidURI" xml:space="preserve">
|
||||||
<value>Invalid URI</value>
|
<value>Μη έγκυρο URI</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="URIRemoved" xml:space="preserve">
|
<data name="URIRemoved" xml:space="preserve">
|
||||||
<value>URI removed</value>
|
<value>Το URI αφαιρέθηκε</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ThereAreNoBlockedURIs" xml:space="preserve">
|
<data name="ThereAreNoBlockedURIs" xml:space="preserve">
|
||||||
<value>There are no blocked URIs</value>
|
<value>Δεν υπάρχουν αποκλεισμένα URI</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TheURIXIsAlreadyBlocked" xml:space="preserve">
|
<data name="TheURIXIsAlreadyBlocked" xml:space="preserve">
|
||||||
<value>The URI {0} is already blocked</value>
|
<value>Το URI {0} είναι ήδη αποκλεισμένο</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="CannotEditMultipleURIsAtOnce" xml:space="preserve">
|
<data name="CannotEditMultipleURIsAtOnce" xml:space="preserve">
|
||||||
<value>Cannot edit multiple URIs at once</value>
|
<value>Αδυναμία επεξεργασίας πολλαπλών URI ταυτόχρονα</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LoginApproved" xml:space="preserve">
|
<data name="LoginApproved" xml:space="preserve">
|
||||||
<value>Login approved</value>
|
<value>Η σύνδεση εγκρίθηκε</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LogInWithDeviceMustBeSetUpInTheSettingsOfTheBitwardenAppNeedAnotherOption" xml:space="preserve">
|
<data name="LogInWithDeviceMustBeSetUpInTheSettingsOfTheBitwardenAppNeedAnotherOption" xml:space="preserve">
|
||||||
<value>Log in with device must be set up in the settings of the Bitwarden app. Need another option?</value>
|
<value>Η σύνδεση με χρήση συσκευής πρέπει να ρυθμιστεί στις ρυθμίσεις της εφαρμογής Bitwarden. Χρειάζεστε άλλη επιλογή;</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LogInWithDevice" xml:space="preserve">
|
<data name="LogInWithDevice" xml:space="preserve">
|
||||||
<value>Log in with device</value>
|
<value>Σύνδεση με χρήση συσκευής</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LoggingInOn" xml:space="preserve">
|
<data name="LoggingInOn" xml:space="preserve">
|
||||||
<value>Logging in on</value>
|
<value>Σύνδεση στο</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Vault" xml:space="preserve">
|
<data name="Vault" xml:space="preserve">
|
||||||
<value>Vault</value>
|
<value>Vault</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Appearance" xml:space="preserve">
|
<data name="Appearance" xml:space="preserve">
|
||||||
<value>Appearance</value>
|
<value>Εμφάνιση</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AccountSecurity" xml:space="preserve">
|
<data name="AccountSecurity" xml:space="preserve">
|
||||||
<value>Account security</value>
|
<value>Ασφάλεια λογαριασμού</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="BitwardenHelpCenter" xml:space="preserve">
|
<data name="BitwardenHelpCenter" xml:space="preserve">
|
||||||
<value>Bitwarden Help Center</value>
|
<value>Κέντρο Βοήθειας Bitwarden</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ContactBitwardenSupport" xml:space="preserve">
|
<data name="ContactBitwardenSupport" xml:space="preserve">
|
||||||
<value>Contact Bitwarden support</value>
|
<value>Επικοινωνία με την υποστήριξη του Bitwarden</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="CopyAppInformation" xml:space="preserve">
|
<data name="CopyAppInformation" xml:space="preserve">
|
||||||
<value>Copy app information</value>
|
<value>Αντιγραφή πληροφοριών εφαρμογής</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SyncNow" xml:space="preserve">
|
<data name="SyncNow" xml:space="preserve">
|
||||||
<value>Sync now</value>
|
<value>Συγχρονισμός τώρα</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="UnlockOptions" xml:space="preserve">
|
<data name="UnlockOptions" xml:space="preserve">
|
||||||
<value>Unlock options</value>
|
<value>Επιλογές Κλειδώματος</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SessionTimeout" xml:space="preserve">
|
<data name="SessionTimeout" xml:space="preserve">
|
||||||
<value>Session timeout</value>
|
<value>Χρονικό όριο συνεδρίας</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SessionTimeoutAction" xml:space="preserve">
|
<data name="SessionTimeoutAction" xml:space="preserve">
|
||||||
<value>Session timeout action</value>
|
<value>Ενέργεια στη λήξη χρόνου συνεδρίας</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AccountFingerprintPhrase" xml:space="preserve">
|
<data name="AccountFingerprintPhrase" xml:space="preserve">
|
||||||
<value>Account fingerprint phrase</value>
|
<value>"Φράση αποτυπώματος" λογαριασμού</value>
|
||||||
<comment>A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing.</comment>
|
<comment>A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="OneHourAndOneMinute" xml:space="preserve">
|
<data name="OneHourAndOneMinute" xml:space="preserve">
|
||||||
<value>One hour and one minute</value>
|
<value>Μία ώρα και ένα λεπτό</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="OneHourAndXMinute" xml:space="preserve">
|
<data name="OneHourAndXMinute" xml:space="preserve">
|
||||||
<value>One hour and {0} minutes</value>
|
<value>Μία ώρα και {0} λεπτά</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="XHoursAndOneMinute" xml:space="preserve">
|
<data name="XHoursAndOneMinute" xml:space="preserve">
|
||||||
<value>{0} hours and one minute</value>
|
<value>{0} ώρες και ένα λεπτό</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="XHoursAndYMinutes" xml:space="preserve">
|
<data name="XHoursAndYMinutes" xml:space="preserve">
|
||||||
<value>{0} hours and {1} minutes</value>
|
<value>{0} ώρες και {1} λεπτά</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="XHours" xml:space="preserve">
|
<data name="XHours" xml:space="preserve">
|
||||||
<value>{0} hours</value>
|
<value>{0} ώρες</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AutofillServicesExplanationLong" xml:space="preserve">
|
<data name="AutofillServicesExplanationLong" xml:space="preserve">
|
||||||
<value>The Android Autofill Framework is used to assist in filling login information into other apps on your device.</value>
|
<value>Το Android Autofill Framework χρησιμοποιείται για να προσφέρει αυτόματη συμπλήρωση στοιχείων σύνδεσης σε άλλες εφαρμογές στη συσκευή σας.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="UseInlineAutofillExplanationLong" xml:space="preserve">
|
<data name="UseInlineAutofillExplanationLong" xml:space="preserve">
|
||||||
<value>Use inline autofill if your selected keyboard supports it. Otherwise, use the default overlay.</value>
|
<value>Χρησιμοποιήστε την ενσωματωμένη αυτόματη συμπλήρωση αν το πληκτρολόγιο σας την υποστηρίζει. Διαφορετικά, χρησιμοποιήστε την προεπιλεγμένη επικάλυψη.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AdditionalOptions" xml:space="preserve">
|
<data name="AdditionalOptions" xml:space="preserve">
|
||||||
<value>Additional options</value>
|
<value>Πρόσθετες επιλογές</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ContinueToWebApp" xml:space="preserve">
|
<data name="ContinueToWebApp" xml:space="preserve">
|
||||||
<value>Continue to web app?</value>
|
<value>Συνέχεια στην εφαρμογή διαδικτύου;</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ContinueToX" xml:space="preserve">
|
<data name="ContinueToX" xml:space="preserve">
|
||||||
<value>Continue to {0}?</value>
|
<value>Συνέχεια στο {0};</value>
|
||||||
<comment>The parameter is an URL, like bitwarden.com.</comment>
|
<comment>The parameter is an URL, like bitwarden.com.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="ContinueToHelpCenter" xml:space="preserve">
|
<data name="ContinueToHelpCenter" xml:space="preserve">
|
||||||
<value>Continue to Help center?</value>
|
<value>Συνέχεια στο κέντρο βοήθειας;</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ContinueToContactSupport" xml:space="preserve">
|
<data name="ContinueToContactSupport" xml:space="preserve">
|
||||||
<value>Continue to contact support?</value>
|
<value>Συνέχεια στην επικοινωνία με την υποστήριξη;</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ContinueToAppStore" xml:space="preserve">
|
<data name="ContinueToAppStore" xml:space="preserve">
|
||||||
<value>Continue to app store?</value>
|
<value>Συνέχεια στο κατάστημα εφαρμογών;</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TwoStepLoginDescriptionLong" xml:space="preserve">
|
<data name="TwoStepLoginDescriptionLong" xml:space="preserve">
|
||||||
<value>Make your account more secure by setting up two-step login in the Bitwarden web app.</value>
|
<value>Κάντε τον λογαριασμό σας πιο ασφαλή με τη ρύθμιση δύο βημάτων σύνδεσης στην εφαρμογή διαδικτύου Bitwarden.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ChangeMasterPasswordDescriptionLong" xml:space="preserve">
|
<data name="ChangeMasterPasswordDescriptionLong" xml:space="preserve">
|
||||||
<value>You can change your master password on the Bitwarden web app.</value>
|
<value>Μπορείτε να αλλάξετε τον κύριο κωδικό πρόσβασης στην εφαρμογή διαδικτύου Bitwarden.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="YouCanImportDataToYourVaultOnX" xml:space="preserve">
|
<data name="YouCanImportDataToYourVaultOnX" xml:space="preserve">
|
||||||
<value>You can import data to your vault on {0}.</value>
|
<value>Μπορείτε να εισαγάγετε δεδομένα στο vault σας στο {0}.</value>
|
||||||
<comment>The parameter is an URL, like vault.bitwarden.com.</comment>
|
<comment>The parameter is an URL, like vault.bitwarden.com.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="LearnMoreAboutHowToUseBitwardenOnTheHelpCenter" xml:space="preserve">
|
<data name="LearnMoreAboutHowToUseBitwardenOnTheHelpCenter" xml:space="preserve">
|
||||||
<value>Learn more about how to use Bitwarden on the Help center.</value>
|
<value>Μάθετε περισσότερα για το πώς να χρησιμοποιήσετε το Bitwarden στο κέντρο βοήθειας.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ContactSupportDescriptionLong" xml:space="preserve">
|
<data name="ContactSupportDescriptionLong" xml:space="preserve">
|
||||||
<value>Can’t find what you are looking for? Reach out to Bitwarden support on bitwarden.com.</value>
|
<value>Δεν μπορείτε να βρείτε αυτό που ψάχνετε; Επικοινωνήστε με την υποστήριξη Bitwarden στο bitwarden.com.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
|
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
|
||||||
<value>Explore more features of your Bitwarden account on the web app.</value>
|
<value>Εξερευνήστε περισσότερες δυνατότητες του Bitwarden λογαριασμού σας, στην εφαρμογή διαδικτύου.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LearnAboutOrganizationsDescriptionLong" xml:space="preserve">
|
<data name="LearnAboutOrganizationsDescriptionLong" xml:space="preserve">
|
||||||
<value>Bitwarden allows you to share your vault items with others by using an organization. Learn more on the bitwarden.com website.</value>
|
<value>Το Bitwarden σας επιτρέπει να μοιράζεστε τα στοιχεία του vault σας με άλλους, χρησιμοποιώντας έναν λογαριασμό οργανισμού. Μάθετε περισσότερα στην ιστοσελίδα bitwarden.com.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="RateAppDescriptionLong" xml:space="preserve">
|
<data name="RateAppDescriptionLong" xml:space="preserve">
|
||||||
<value>Help others find out if Bitwarden is right for them. Visit the app store and leave a rating now.</value>
|
<value>Βοηθήστε άλλους να μάθουν αν το Bitwarden είναι κατάλληλο για αυτούς. Επισκεφθείτε το κατάστημα εφαρμογών και αφήστε τώρα μια βαθμολογία.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="DefaultDarkThemeDescriptionLong" xml:space="preserve">
|
<data name="DefaultDarkThemeDescriptionLong" xml:space="preserve">
|
||||||
<value>Choose the dark theme to use when your device’s dark mode is in use</value>
|
<value>Επιλέξτε να χρησιμοποιείται το σκούρο θέμα όταν η συσκευή σας βρίσκεται σε σκοτεινή λειτουργία</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="CreatedXY" xml:space="preserve">
|
<data name="CreatedXY" xml:space="preserve">
|
||||||
<value>Created {0}, {1}</value>
|
<value>Δημιουργήθηκε {0}, {1}</value>
|
||||||
<comment>To state the date/time in which the cipher was created: Created 03/21/2023, 09:25 AM. First parameter is the date and the second parameter is the time.</comment>
|
<comment>To state the date/time in which the cipher was created: Created 03/21/2023, 09:25 AM. First parameter is the date and the second parameter is the time.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="TooManyAttempts" xml:space="preserve">
|
<data name="TooManyAttempts" xml:space="preserve">
|
||||||
<value>Too many attempts</value>
|
<value>Πάρα πολλές προσπάθειες</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
||||||
<value>Account logged out.</value>
|
<value>Ο λογαριασμός αποσυνδέθηκε.</value>
|
||||||
|
</data>
|
||||||
|
<data name="YourOrganizationPermissionsWereUpdatedRequeringYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Τα δικαιώματα του οργανισμού σας ενημερώθηκαν, απαιτώντας από εσάς να ορίσετε έναν κύριο κωδικό πρόσβασης.</value>
|
||||||
|
</data>
|
||||||
|
<data name="YourOrganizationRequiresYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Ο οργανισμός σας απαιτεί να ορίσετε έναν κύριο κωδικό πρόσβασης.</value>
|
||||||
|
</data>
|
||||||
|
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||||
|
<value>Ρυθμίστε μια επιλογή κλειδώματος για να αλλάξετε την ενέργεια στη λήξη χρόνου του vault σας.</value>
|
||||||
</data>
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
|
@ -2861,4 +2861,13 @@ Do you want to switch to this account?</value>
|
||||||
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
||||||
<value>Account logged out.</value>
|
<value>Account logged out.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="YourOrganizationPermissionsWereUpdatedRequeringYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Your organization permissions were updated, requiring you to set a master password.</value>
|
||||||
|
</data>
|
||||||
|
<data name="YourOrganizationRequiresYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Your organization requires you to set a master password.</value>
|
||||||
|
</data>
|
||||||
|
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||||
|
<value>Set up an unlock option to change your vault timeout action.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
|
@ -2875,4 +2875,13 @@ Do you want to switch to this account?</value>
|
||||||
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
||||||
<value>Account logged out.</value>
|
<value>Account logged out.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="YourOrganizationPermissionsWereUpdatedRequeringYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Your organization permissions were updated, requiring you to set a master password.</value>
|
||||||
|
</data>
|
||||||
|
<data name="YourOrganizationRequiresYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Your organization requires you to set a master password.</value>
|
||||||
|
</data>
|
||||||
|
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||||
|
<value>Set up an unlock option to change your vault timeout action.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
|
@ -2862,4 +2862,13 @@ seleccione Agregar TOTP para almacenar la clave de forma segura</value>
|
||||||
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
||||||
<value>Account logged out.</value>
|
<value>Account logged out.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="YourOrganizationPermissionsWereUpdatedRequeringYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Your organization permissions were updated, requiring you to set a master password.</value>
|
||||||
|
</data>
|
||||||
|
<data name="YourOrganizationRequiresYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Your organization requires you to set a master password.</value>
|
||||||
|
</data>
|
||||||
|
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||||
|
<value>Set up an unlock option to change your vault timeout action.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
|
@ -2861,4 +2861,13 @@ Soovid selle konto peale lülituda?</value>
|
||||||
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
||||||
<value>Account logged out.</value>
|
<value>Account logged out.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="YourOrganizationPermissionsWereUpdatedRequeringYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Your organization permissions were updated, requiring you to set a master password.</value>
|
||||||
|
</data>
|
||||||
|
<data name="YourOrganizationRequiresYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Your organization requires you to set a master password.</value>
|
||||||
|
</data>
|
||||||
|
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||||
|
<value>Set up an unlock option to change your vault timeout action.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
|
@ -2860,4 +2860,13 @@ Kontu honetara aldatu nahi duzu?</value>
|
||||||
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
||||||
<value>Account logged out.</value>
|
<value>Account logged out.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="YourOrganizationPermissionsWereUpdatedRequeringYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Your organization permissions were updated, requiring you to set a master password.</value>
|
||||||
|
</data>
|
||||||
|
<data name="YourOrganizationRequiresYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Your organization requires you to set a master password.</value>
|
||||||
|
</data>
|
||||||
|
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||||
|
<value>Set up an unlock option to change your vault timeout action.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
|
@ -2862,4 +2862,13 @@
|
||||||
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
||||||
<value>حساب از سیستم خارج شد.</value>
|
<value>حساب از سیستم خارج شد.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="YourOrganizationPermissionsWereUpdatedRequeringYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Your organization permissions were updated, requiring you to set a master password.</value>
|
||||||
|
</data>
|
||||||
|
<data name="YourOrganizationRequiresYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Your organization requires you to set a master password.</value>
|
||||||
|
</data>
|
||||||
|
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||||
|
<value>Set up an unlock option to change your vault timeout action.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
|
@ -2862,4 +2862,13 @@ Haluatko vaihtaa tähän tiliin?</value>
|
||||||
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
||||||
<value>Tili kirjattiin ulos.</value>
|
<value>Tili kirjattiin ulos.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="YourOrganizationPermissionsWereUpdatedRequeringYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Organisaatiosi käyttöoikeuksia muutettiin ja tämän seurauksena sinun on asetettava pääsalasana.</value>
|
||||||
|
</data>
|
||||||
|
<data name="YourOrganizationRequiresYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Organisaatiosi edellyttää, että asetat pääsalasanan.</value>
|
||||||
|
</data>
|
||||||
|
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||||
|
<value>Muuta holvisi aikakatkaisutoimintoa määrittämällä lukituksen avaustapa.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
|
@ -2862,4 +2862,13 @@ Gusto mo bang pumunta sa account na ito?</value>
|
||||||
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
||||||
<value>Account logged out.</value>
|
<value>Account logged out.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="YourOrganizationPermissionsWereUpdatedRequeringYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Your organization permissions were updated, requiring you to set a master password.</value>
|
||||||
|
</data>
|
||||||
|
<data name="YourOrganizationRequiresYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Your organization requires you to set a master password.</value>
|
||||||
|
</data>
|
||||||
|
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||||
|
<value>Set up an unlock option to change your vault timeout action.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
|
@ -455,7 +455,7 @@
|
||||||
<value>Continuer</value>
|
<value>Continuer</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="CreateAccount" xml:space="preserve">
|
<data name="CreateAccount" xml:space="preserve">
|
||||||
<value>Créer un compte</value>
|
<value>Créez un compte</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="CreatingAccount" xml:space="preserve">
|
<data name="CreatingAccount" xml:space="preserve">
|
||||||
<value>Création du compte...</value>
|
<value>Création du compte...</value>
|
||||||
|
@ -686,10 +686,10 @@
|
||||||
<comment>Message shown when interacting with the server</comment>
|
<comment>Message shown when interacting with the server</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="SyncingComplete" xml:space="preserve">
|
<data name="SyncingComplete" xml:space="preserve">
|
||||||
<value>Synchronisation terminée</value>
|
<value>Synchronisation achevée</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SyncingFailed" xml:space="preserve">
|
<data name="SyncingFailed" xml:space="preserve">
|
||||||
<value>Échec de la synchronisation</value>
|
<value>Synchronisation échouée</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SyncVaultNow" xml:space="preserve">
|
<data name="SyncVaultNow" xml:space="preserve">
|
||||||
<value>Synchroniser le coffre maintenant</value>
|
<value>Synchroniser le coffre maintenant</value>
|
||||||
|
@ -778,7 +778,7 @@
|
||||||
<value>Le moyen le plus simple d'ajouter de nouveaux identifiants à votre coffre est d'utiliser le service de saisie automatique Bitwarden. Pour en savoir davantage sur l'utilisation du service de saisie automatique Bitwarden, naviguez jusqu'à l'écran "Paramètres".</value>
|
<value>Le moyen le plus simple d'ajouter de nouveaux identifiants à votre coffre est d'utiliser le service de saisie automatique Bitwarden. Pour en savoir davantage sur l'utilisation du service de saisie automatique Bitwarden, naviguez jusqu'à l'écran "Paramètres".</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Autofill" xml:space="preserve">
|
<data name="Autofill" xml:space="preserve">
|
||||||
<value>Saisir automatiquement</value>
|
<value>Saisie automatique</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AutofillOrView" xml:space="preserve">
|
<data name="AutofillOrView" xml:space="preserve">
|
||||||
<value>Voulez-vous saisir automatiquement ou afficher cet élément ?</value>
|
<value>Voulez-vous saisir automatiquement ou afficher cet élément ?</value>
|
||||||
|
@ -907,7 +907,7 @@ La numérisation se fera automatiquement.</value>
|
||||||
<value>Copier le TOTP</value>
|
<value>Copier le TOTP</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="CopyTotpAutomaticallyDescription" xml:space="preserve">
|
<data name="CopyTotpAutomaticallyDescription" xml:space="preserve">
|
||||||
<value>Si un identifiant a une clé d'authentification, copier le code de vérification TOTP dans votre presse-papier quand vous remplissez automatiquement l'identifiant.</value>
|
<value>Si un identifiant possède une clé d'authentification, copiez le code de vérification TOTP dans votre presse-papiers lorsque vous saisissez automatiquement l'identifiant.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="CopyTotpAutomatically" xml:space="preserve">
|
<data name="CopyTotpAutomatically" xml:space="preserve">
|
||||||
<value>Copier TOTP automatiquement</value>
|
<value>Copier TOTP automatiquement</value>
|
||||||
|
@ -1134,7 +1134,7 @@ La numérisation se fera automatiquement.</value>
|
||||||
<value>Expiration</value>
|
<value>Expiration</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ShowWebsiteIcons" xml:space="preserve">
|
<data name="ShowWebsiteIcons" xml:space="preserve">
|
||||||
<value>Afficher les icônes du site web</value>
|
<value>Afficher les icônes des sites web</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ShowWebsiteIconsDescription" xml:space="preserve">
|
<data name="ShowWebsiteIconsDescription" xml:space="preserve">
|
||||||
<value>Affichez une image reconnaissable à côté de chaque identifiant.</value>
|
<value>Affichez une image reconnaissable à côté de chaque identifiant.</value>
|
||||||
|
@ -1304,13 +1304,13 @@ La numérisation se fera automatiquement.</value>
|
||||||
<value>1. Allez dans l'application "Réglages" d'iOS</value>
|
<value>1. Allez dans l'application "Réglages" d'iOS</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AutofillTurnOn2" xml:space="preserve">
|
<data name="AutofillTurnOn2" xml:space="preserve">
|
||||||
<value>2. Appuyez sur "Mots de passe et comptes"</value>
|
<value>2. Appuyez sur "Mots de passe"</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AutofillTurnOn3" xml:space="preserve">
|
<data name="AutofillTurnOn3" xml:space="preserve">
|
||||||
<value>3. Appuyez sur "Préremplir mots de passe"</value>
|
<value>3. Appuyez sur "Options des mots de passe"</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AutofillTurnOn4" xml:space="preserve">
|
<data name="AutofillTurnOn4" xml:space="preserve">
|
||||||
<value>4. Activez "Préremplir mots de passe"</value>
|
<value>4. Activez "Remplir automatiquement les mots de passe et les clés d'identification"</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AutofillTurnOn5" xml:space="preserve">
|
<data name="AutofillTurnOn5" xml:space="preserve">
|
||||||
<value>5. Sélectionnez "Bitwarden"</value>
|
<value>5. Sélectionnez "Bitwarden"</value>
|
||||||
|
@ -1378,10 +1378,10 @@ La numérisation se fera automatiquement.</value>
|
||||||
<value>Rechercher dans la collection</value>
|
<value>Rechercher dans la collection</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SearchFileSends" xml:space="preserve">
|
<data name="SearchFileSends" xml:space="preserve">
|
||||||
<value>Rechercher des fichiers Sends</value>
|
<value>Rechercher des Send fichier</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SearchTextSends" xml:space="preserve">
|
<data name="SearchTextSends" xml:space="preserve">
|
||||||
<value>Rechercher des textes Sends</value>
|
<value>Rechercher des Sends texte</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SearchGroup" xml:space="preserve">
|
<data name="SearchGroup" xml:space="preserve">
|
||||||
<value>Rechercher {0} :</value>
|
<value>Rechercher {0} :</value>
|
||||||
|
@ -1400,7 +1400,7 @@ La numérisation se fera automatiquement.</value>
|
||||||
<value>Divers</value>
|
<value>Divers</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Ownership" xml:space="preserve">
|
<data name="Ownership" xml:space="preserve">
|
||||||
<value>Propriété</value>
|
<value>Propriétaire</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="WhoOwnsThisItem" xml:space="preserve">
|
<data name="WhoOwnsThisItem" xml:space="preserve">
|
||||||
<value>À qui appartient cet élément ?</value>
|
<value>À qui appartient cet élément ?</value>
|
||||||
|
@ -1431,7 +1431,7 @@ La numérisation se fera automatiquement.</value>
|
||||||
<value>Aucune organisation à lister.</value>
|
<value>Aucune organisation à lister.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MoveToOrgDesc" xml:space="preserve">
|
<data name="MoveToOrgDesc" xml:space="preserve">
|
||||||
<value>Choisissez une organisation vers laquelle vous souhaitez déplacer cet élément. Déplacer un élément vers une organisation transfère la propriété de l'élément à cette organisation. Vous ne serez plus le propriétaire direct de cet élément une fois qu'il aura été déplacé.</value>
|
<value>Choisissez une organisation vers laquelle vous souhaitez déplacer cet élément. Le déplacement vers une organisation transfère le Propriétaire de l'élément à cette organisation. Vous ne serez plus le propriétaire direct de cet élément une fois qu'il aura été déplacé.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="NumberOfWords" xml:space="preserve">
|
<data name="NumberOfWords" xml:space="preserve">
|
||||||
<value>Nombre de mots</value>
|
<value>Nombre de mots</value>
|
||||||
|
@ -1526,7 +1526,7 @@ La numérisation se fera automatiquement.</value>
|
||||||
<comment>Clipboard is the operating system thing where you copy/paste data to on your device.</comment>
|
<comment>Clipboard is the operating system thing where you copy/paste data to on your device.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="ClearClipboardDescription" xml:space="preserve">
|
<data name="ClearClipboardDescription" xml:space="preserve">
|
||||||
<value>Effacer automatiquement de votre presse-papiers les valeurs copiées.</value>
|
<value>Effacez automatiquement les valeurs copiées de votre presse-papiers.</value>
|
||||||
<comment>Clipboard is the operating system thing where you copy/paste data to on your device.</comment>
|
<comment>Clipboard is the operating system thing where you copy/paste data to on your device.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="DefaultUriMatchDetection" xml:space="preserve">
|
<data name="DefaultUriMatchDetection" xml:space="preserve">
|
||||||
|
@ -1750,7 +1750,7 @@ La numérisation se fera automatiquement.</value>
|
||||||
<value>Autoriser la synchronisation au rafraîchissement</value>
|
<value>Autoriser la synchronisation au rafraîchissement</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="EnableSyncOnRefreshDescription" xml:space="preserve">
|
<data name="EnableSyncOnRefreshDescription" xml:space="preserve">
|
||||||
<value>Synchronisation du coffre avec un geste vers le bas</value>
|
<value>Synchronisez le coffre avec un geste vers le bas.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LogInSso" xml:space="preserve">
|
<data name="LogInSso" xml:space="preserve">
|
||||||
<value>Portail de connexion unique d'entreprise</value>
|
<value>Portail de connexion unique d'entreprise</value>
|
||||||
|
@ -1853,10 +1853,10 @@ La numérisation se fera automatiquement.</value>
|
||||||
<value>Si cette option est activée, l'accessibilité affichera une popup pour améliorer le service de remplissage automatique pour les anciennes applications qui ne prennent pas en charge les outils de remplissage automatique d'Android.</value>
|
<value>Si cette option est activée, l'accessibilité affichera une popup pour améliorer le service de remplissage automatique pour les anciennes applications qui ne prennent pas en charge les outils de remplissage automatique d'Android.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="PersonalOwnershipSubmitError" xml:space="preserve">
|
<data name="PersonalOwnershipSubmitError" xml:space="preserve">
|
||||||
<value>En raison d'une Politique d'Entreprise, il vous est interdit d'enregistrer des objets dans votre coffre personnel. Changez l'option Propriété pour une organisation et choisissez parmi les Collections disponibles.</value>
|
<value>En raison d'une politique d'entreprise, il vous est interdit d'enregistrer des éléments dans votre coffre personnel. Changez l'option Propriétaire au profit d'une organisation et choisissez parmi les collections disponibles.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="PersonalOwnershipPolicyInEffect" xml:space="preserve">
|
<data name="PersonalOwnershipPolicyInEffect" xml:space="preserve">
|
||||||
<value>Une politique d'organisation affecte vos options de propriété.</value>
|
<value>Une politique d'organisation affecte vos options de Propriétaire.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Send" xml:space="preserve">
|
<data name="Send" xml:space="preserve">
|
||||||
<value>Send</value>
|
<value>Send</value>
|
||||||
|
@ -1968,7 +1968,7 @@ La numérisation se fera automatiquement.</value>
|
||||||
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="DisableSend" xml:space="preserve">
|
<data name="DisableSend" xml:space="preserve">
|
||||||
<value>Désactiver cet envoi pour que personne ne puisse y accéder.</value>
|
<value>Désactiver ce Send pour que personne ne puisse y accéder</value>
|
||||||
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="NoSends" xml:space="preserve">
|
<data name="NoSends" xml:space="preserve">
|
||||||
|
@ -1998,7 +1998,7 @@ La numérisation se fera automatiquement.</value>
|
||||||
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="AddSend" xml:space="preserve">
|
<data name="AddSend" xml:space="preserve">
|
||||||
<value>Ajouter un Send</value>
|
<value>Nouveau Send</value>
|
||||||
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="AreYouSureDeleteSend" xml:space="preserve">
|
<data name="AreYouSureDeleteSend" xml:space="preserve">
|
||||||
|
@ -2006,7 +2006,7 @@ La numérisation se fera automatiquement.</value>
|
||||||
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="SendDeleted" xml:space="preserve">
|
<data name="SendDeleted" xml:space="preserve">
|
||||||
<value>Le Send a été supprimé.</value>
|
<value>Send supprimé</value>
|
||||||
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="SendUpdated" xml:space="preserve">
|
<data name="SendUpdated" xml:space="preserve">
|
||||||
|
@ -2014,7 +2014,7 @@ La numérisation se fera automatiquement.</value>
|
||||||
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="NewSendCreated" xml:space="preserve">
|
<data name="NewSendCreated" xml:space="preserve">
|
||||||
<value>Nouveau Send créé.</value>
|
<value>Send créé</value>
|
||||||
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="OneDay" xml:space="preserve">
|
<data name="OneDay" xml:space="preserve">
|
||||||
|
@ -2036,7 +2036,7 @@ La numérisation se fera automatiquement.</value>
|
||||||
<value>Personnalisé</value>
|
<value>Personnalisé</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ShareOnSave" xml:space="preserve">
|
<data name="ShareOnSave" xml:space="preserve">
|
||||||
<value>Partager ce Send lors de l'enregistrement.</value>
|
<value>Partagez ce Send au moment de l'enregistrement</value>
|
||||||
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
<comment>'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="SendDisabledWarning" xml:space="preserve">
|
<data name="SendDisabledWarning" xml:space="preserve">
|
||||||
|
@ -2355,7 +2355,7 @@ sélectionnez Ajouter TOTP pour stocker la clé en toute sécurité</value>
|
||||||
<value>Approuver les demandes de connexion</value>
|
<value>Approuver les demandes de connexion</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="UseThisDeviceToApproveLoginRequestsMadeFromOtherDevices" xml:space="preserve">
|
<data name="UseThisDeviceToApproveLoginRequestsMadeFromOtherDevices" xml:space="preserve">
|
||||||
<value>Utiliser cet appareil pour approuver les demandes de connexion faites à partir d'autres appareils.</value>
|
<value>Utiliser cet appareil pour approuver les demandes de connexion faites à partir d'autres appareils</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AllowNotifications" xml:space="preserve">
|
<data name="AllowNotifications" xml:space="preserve">
|
||||||
<value>Autoriser les notifications</value>
|
<value>Autoriser les notifications</value>
|
||||||
|
@ -2546,7 +2546,7 @@ Voulez-vous basculer vers ce compte ?</value>
|
||||||
<value>La langue a été changée en {0}. Veuillez redémarrer l'application pour voir le changement</value>
|
<value>La langue a été changée en {0}. Veuillez redémarrer l'application pour voir le changement</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LanguageChangeRequiresAppRestart" xml:space="preserve">
|
<data name="LanguageChangeRequiresAppRestart" xml:space="preserve">
|
||||||
<value>Le changement de langue nécessite le redémarrage de l'application</value>
|
<value>Le changement de la langue nécessite le redémarrage de l'application.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="DefaultSystem" xml:space="preserve">
|
<data name="DefaultSystem" xml:space="preserve">
|
||||||
<value>Par défaut (système)</value>
|
<value>Par défaut (système)</value>
|
||||||
|
@ -2781,7 +2781,7 @@ Voulez-vous basculer vers ce compte ?</value>
|
||||||
<value>Action après délai d'expiration de la session</value>
|
<value>Action après délai d'expiration de la session</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AccountFingerprintPhrase" xml:space="preserve">
|
<data name="AccountFingerprintPhrase" xml:space="preserve">
|
||||||
<value>La phrase d'empreinte du compte</value>
|
<value>Phrase d'empreinte du compte</value>
|
||||||
<comment>A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing.</comment>
|
<comment>A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="OneHourAndOneMinute" xml:space="preserve">
|
<data name="OneHourAndOneMinute" xml:space="preserve">
|
||||||
|
@ -2862,4 +2862,13 @@ Voulez-vous basculer vers ce compte ?</value>
|
||||||
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
||||||
<value>Compte déconnecté.</value>
|
<value>Compte déconnecté.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="YourOrganizationPermissionsWereUpdatedRequeringYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Les autorisations de votre organisation ont été mises à jour, vous obligeant à définir un mot de passe principal.</value>
|
||||||
|
</data>
|
||||||
|
<data name="YourOrganizationRequiresYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Votre organisation vous demande de définir un mot de passe principal.</value>
|
||||||
|
</data>
|
||||||
|
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||||
|
<value>Configurez une méthode de déverrouillage pour modifier l'action après délai d'expiration de votre coffre.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
|
@ -2862,4 +2862,13 @@ Do you want to switch to this account?</value>
|
||||||
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
||||||
<value>Account logged out.</value>
|
<value>Account logged out.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="YourOrganizationPermissionsWereUpdatedRequeringYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Your organization permissions were updated, requiring you to set a master password.</value>
|
||||||
|
</data>
|
||||||
|
<data name="YourOrganizationRequiresYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Your organization requires you to set a master password.</value>
|
||||||
|
</data>
|
||||||
|
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||||
|
<value>Set up an unlock option to change your vault timeout action.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
|
@ -2864,4 +2864,13 @@ Do you want to switch to this account?</value>
|
||||||
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
||||||
<value>Account logged out.</value>
|
<value>Account logged out.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="YourOrganizationPermissionsWereUpdatedRequeringYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Your organization permissions were updated, requiring you to set a master password.</value>
|
||||||
|
</data>
|
||||||
|
<data name="YourOrganizationRequiresYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Your organization requires you to set a master password.</value>
|
||||||
|
</data>
|
||||||
|
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||||
|
<value>Set up an unlock option to change your vault timeout action.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
|
@ -2862,4 +2862,13 @@ Do you want to switch to this account?</value>
|
||||||
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
||||||
<value>Account logged out.</value>
|
<value>Account logged out.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="YourOrganizationPermissionsWereUpdatedRequeringYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Your organization permissions were updated, requiring you to set a master password.</value>
|
||||||
|
</data>
|
||||||
|
<data name="YourOrganizationRequiresYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Your organization requires you to set a master password.</value>
|
||||||
|
</data>
|
||||||
|
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||||
|
<value>Set up an unlock option to change your vault timeout action.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
|
@ -2423,7 +2423,7 @@
|
||||||
<comment>"Fastmail" is the product name and should not be translated.</comment>
|
<comment>"Fastmail" is the product name and should not be translated.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="ForwardEmail" xml:space="preserve">
|
<data name="ForwardEmail" xml:space="preserve">
|
||||||
<value>ForwardEmail</value>
|
<value>FowardEmail</value>
|
||||||
<comment>"ForwardEmail" is the product name and should not be translated.</comment>
|
<comment>"ForwardEmail" is the product name and should not be translated.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="APIAccessToken" xml:space="preserve">
|
<data name="APIAccessToken" xml:space="preserve">
|
||||||
|
@ -2748,106 +2748,106 @@
|
||||||
<value>Prijava na</value>
|
<value>Prijava na</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Vault" xml:space="preserve">
|
<data name="Vault" xml:space="preserve">
|
||||||
<value>Vault</value>
|
<value>Trezor</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Appearance" xml:space="preserve">
|
<data name="Appearance" xml:space="preserve">
|
||||||
<value>Appearance</value>
|
<value>Izgled</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AccountSecurity" xml:space="preserve">
|
<data name="AccountSecurity" xml:space="preserve">
|
||||||
<value>Account security</value>
|
<value>Sigurnost računa</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="BitwardenHelpCenter" xml:space="preserve">
|
<data name="BitwardenHelpCenter" xml:space="preserve">
|
||||||
<value>Bitwarden Help Center</value>
|
<value>Bitwarden centar za pomoć</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ContactBitwardenSupport" xml:space="preserve">
|
<data name="ContactBitwardenSupport" xml:space="preserve">
|
||||||
<value>Contact Bitwarden support</value>
|
<value>Kontaktiraj Bitwarden pomoć</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="CopyAppInformation" xml:space="preserve">
|
<data name="CopyAppInformation" xml:space="preserve">
|
||||||
<value>Copy app information</value>
|
<value>Kopiraj podake o aplikaciji</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SyncNow" xml:space="preserve">
|
<data name="SyncNow" xml:space="preserve">
|
||||||
<value>Sync now</value>
|
<value>Sinkroniziraj</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="UnlockOptions" xml:space="preserve">
|
<data name="UnlockOptions" xml:space="preserve">
|
||||||
<value>Unlock options</value>
|
<value>Otključaj mogućnosti</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SessionTimeout" xml:space="preserve">
|
<data name="SessionTimeout" xml:space="preserve">
|
||||||
<value>Session timeout</value>
|
<value>Istek sesije</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="SessionTimeoutAction" xml:space="preserve">
|
<data name="SessionTimeoutAction" xml:space="preserve">
|
||||||
<value>Session timeout action</value>
|
<value>Radnja kod isteka sesije</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AccountFingerprintPhrase" xml:space="preserve">
|
<data name="AccountFingerprintPhrase" xml:space="preserve">
|
||||||
<value>Account fingerprint phrase</value>
|
<value>Jedinstvena fraza računa</value>
|
||||||
<comment>A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing.</comment>
|
<comment>A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="OneHourAndOneMinute" xml:space="preserve">
|
<data name="OneHourAndOneMinute" xml:space="preserve">
|
||||||
<value>One hour and one minute</value>
|
<value>Jedan sat i jedna minuta</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="OneHourAndXMinute" xml:space="preserve">
|
<data name="OneHourAndXMinute" xml:space="preserve">
|
||||||
<value>One hour and {0} minutes</value>
|
<value>Jedan sat i {0} minuta</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="XHoursAndOneMinute" xml:space="preserve">
|
<data name="XHoursAndOneMinute" xml:space="preserve">
|
||||||
<value>{0} hours and one minute</value>
|
<value>{0} sat/i i jedna minuta</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="XHoursAndYMinutes" xml:space="preserve">
|
<data name="XHoursAndYMinutes" xml:space="preserve">
|
||||||
<value>{0} hours and {1} minutes</value>
|
<value>{0} sat/i {1} minuta</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="XHours" xml:space="preserve">
|
<data name="XHours" xml:space="preserve">
|
||||||
<value>{0} hours</value>
|
<value>{0} sat/i</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AutofillServicesExplanationLong" xml:space="preserve">
|
<data name="AutofillServicesExplanationLong" xml:space="preserve">
|
||||||
<value>The Android Autofill Framework is used to assist in filling login information into other apps on your device.</value>
|
<value>Android Autofill Framework se koristi za pomoć pri ispunjavanju prijava, platnih kartica i identifikacijskih podataka u drugim aplikacijama na tvojem uređaju.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="UseInlineAutofillExplanationLong" xml:space="preserve">
|
<data name="UseInlineAutofillExplanationLong" xml:space="preserve">
|
||||||
<value>Use inline autofill if your selected keyboard supports it. Otherwise, use the default overlay.</value>
|
<value>Koristi izravnu auto-ispunu ako ga tvoja odabrana tipkovnica podržava. U suprotnom, koristit će se zadana usluga auto-ispune.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AdditionalOptions" xml:space="preserve">
|
<data name="AdditionalOptions" xml:space="preserve">
|
||||||
<value>Additional options</value>
|
<value>Dodatne mogućnosti</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ContinueToWebApp" xml:space="preserve">
|
<data name="ContinueToWebApp" xml:space="preserve">
|
||||||
<value>Continue to web app?</value>
|
<value>Nastavi na web aplikaciju?</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ContinueToX" xml:space="preserve">
|
<data name="ContinueToX" xml:space="preserve">
|
||||||
<value>Continue to {0}?</value>
|
<value>Nastavi na {0}?</value>
|
||||||
<comment>The parameter is an URL, like bitwarden.com.</comment>
|
<comment>The parameter is an URL, like bitwarden.com.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="ContinueToHelpCenter" xml:space="preserve">
|
<data name="ContinueToHelpCenter" xml:space="preserve">
|
||||||
<value>Continue to Help center?</value>
|
<value>Nastavi u centar za pomoć?</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ContinueToContactSupport" xml:space="preserve">
|
<data name="ContinueToContactSupport" xml:space="preserve">
|
||||||
<value>Continue to contact support?</value>
|
<value>Kontaktiraj podršku?</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ContinueToAppStore" xml:space="preserve">
|
<data name="ContinueToAppStore" xml:space="preserve">
|
||||||
<value>Continue to app store?</value>
|
<value>Nastavi u trgovinu aplikacijama?</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TwoStepLoginDescriptionLong" xml:space="preserve">
|
<data name="TwoStepLoginDescriptionLong" xml:space="preserve">
|
||||||
<value>Make your account more secure by setting up two-step login in the Bitwarden web app.</value>
|
<value>Učini svoj račun sigurnijim uključivanjem prijave dvofaktorskom autentifikacijom u Bitwarden web aplikaciji.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ChangeMasterPasswordDescriptionLong" xml:space="preserve">
|
<data name="ChangeMasterPasswordDescriptionLong" xml:space="preserve">
|
||||||
<value>You can change your master password on the Bitwarden web app.</value>
|
<value>Svoju lozinku možeš promijeniti u Bitwarden web aplikaciji.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="YouCanImportDataToYourVaultOnX" xml:space="preserve">
|
<data name="YouCanImportDataToYourVaultOnX" xml:space="preserve">
|
||||||
<value>You can import data to your vault on {0}.</value>
|
<value>Svoje podatke možeš uvesti u trezor na {0}.</value>
|
||||||
<comment>The parameter is an URL, like vault.bitwarden.com.</comment>
|
<comment>The parameter is an URL, like vault.bitwarden.com.</comment>
|
||||||
</data>
|
</data>
|
||||||
<data name="LearnMoreAboutHowToUseBitwardenOnTheHelpCenter" xml:space="preserve">
|
<data name="LearnMoreAboutHowToUseBitwardenOnTheHelpCenter" xml:space="preserve">
|
||||||
<value>Learn more about how to use Bitwarden on the Help center.</value>
|
<value>Za pomoć oko korištenja Bitwardena posjeti centar za pomoć.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ContactSupportDescriptionLong" xml:space="preserve">
|
<data name="ContactSupportDescriptionLong" xml:space="preserve">
|
||||||
<value>Can’t find what you are looking for? Reach out to Bitwarden support on bitwarden.com.</value>
|
<value>Ne možeš naći što te zanima? Kontaktiraj Bitwarden podršku na bitwarden.com.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
|
<data name="ExploreMoreFeaturesOfYourBitwardenAccountOnTheWebApp" xml:space="preserve">
|
||||||
<value>Explore more features of your Bitwarden account on the web app.</value>
|
<value>Pronađi viđe značajki svojeg Bitwarden računa u web aplikaciji.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="LearnAboutOrganizationsDescriptionLong" xml:space="preserve">
|
<data name="LearnAboutOrganizationsDescriptionLong" xml:space="preserve">
|
||||||
<value>Bitwarden allows you to share your vault items with others by using an organization. Learn more on the bitwarden.com website.</value>
|
<value>Bitwarden omogućuje dijeljenje trezora s drugima pomoću organizacijskog računa. Za više informacija posjeti bitwarden.com.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="RateAppDescriptionLong" xml:space="preserve">
|
<data name="RateAppDescriptionLong" xml:space="preserve">
|
||||||
<value>Help others find out if Bitwarden is right for them. Visit the app store and leave a rating now.</value>
|
<value>Želiš preporučiti Bitwarden drugima? Posjeti app store i ostavi recenziju.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="DefaultDarkThemeDescriptionLong" xml:space="preserve">
|
<data name="DefaultDarkThemeDescriptionLong" xml:space="preserve">
|
||||||
<value>Choose the dark theme to use when your device’s dark mode is in use</value>
|
<value>Odaberi tamnu temu kada se tvoj uređaj nalazi u tamnom načinu rada</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="CreatedXY" xml:space="preserve">
|
<data name="CreatedXY" xml:space="preserve">
|
||||||
<value>Stvoreno {0}, {1}</value>
|
<value>Stvoreno {0}, {1}</value>
|
||||||
|
@ -2859,4 +2859,13 @@
|
||||||
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
||||||
<value>Račun odjavljen.</value>
|
<value>Račun odjavljen.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="YourOrganizationPermissionsWereUpdatedRequeringYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Moraš postaviti glavnu lozinku jer su dopuštenja tvoje organizacije ažurirana.</value>
|
||||||
|
</data>
|
||||||
|
<data name="YourOrganizationRequiresYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Tvoja organizacija zahtijeva da postaviš glavnu lozinku.</value>
|
||||||
|
</data>
|
||||||
|
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||||
|
<value>Za promjenu vremena isteka trezora, odredi način otključavanja.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
|
@ -2860,4 +2860,13 @@ Szeretnénk átváltani erre a fiókra?</value>
|
||||||
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
||||||
<value>A fiók kijelentkezett.</value>
|
<value>A fiók kijelentkezett.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="YourOrganizationPermissionsWereUpdatedRequeringYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>A szervezeti jogosultságok frissítésre kerültek, ezért be kell állítani egy mesterjelszót.</value>
|
||||||
|
</data>
|
||||||
|
<data name="YourOrganizationRequiresYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>A szervezet megköveteli egy mesterjelszó beállítását.</value>
|
||||||
|
</data>
|
||||||
|
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||||
|
<value>Állítsunk be egy feloldási módot a széf időkifutási műveletének módosításához.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
|
@ -2861,4 +2861,13 @@ Do you want to switch to this account?</value>
|
||||||
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
||||||
<value>Account logged out.</value>
|
<value>Account logged out.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="YourOrganizationPermissionsWereUpdatedRequeringYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Your organization permissions were updated, requiring you to set a master password.</value>
|
||||||
|
</data>
|
||||||
|
<data name="YourOrganizationRequiresYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Your organization requires you to set a master password.</value>
|
||||||
|
</data>
|
||||||
|
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||||
|
<value>Set up an unlock option to change your vault timeout action.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
|
@ -2695,7 +2695,7 @@ Vuoi passare a questo account?</value>
|
||||||
<value>Azione timeout cassaforte impostata su uscire</value>
|
<value>Azione timeout cassaforte impostata su uscire</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="BlockAutoFill" xml:space="preserve">
|
<data name="BlockAutoFill" xml:space="preserve">
|
||||||
<value>Bocca riempimento automatico</value>
|
<value>Blocca riempimento automatico</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="AutoFillWillNotBeOfferedForTheseURIs" xml:space="preserve">
|
<data name="AutoFillWillNotBeOfferedForTheseURIs" xml:space="preserve">
|
||||||
<value>Il riempimento automatico non sarà offerto per questi URI.</value>
|
<value>Il riempimento automatico non sarà offerto per questi URI.</value>
|
||||||
|
@ -2861,4 +2861,13 @@ Vuoi passare a questo account?</value>
|
||||||
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
||||||
<value>Account uscito.</value>
|
<value>Account uscito.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="YourOrganizationPermissionsWereUpdatedRequeringYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Le autorizzazioni della tua organizzazione sono state aggiornate, obbligandoti a impostare una password principale.</value>
|
||||||
|
</data>
|
||||||
|
<data name="YourOrganizationRequiresYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>La tua organizzazione ti obbliga di impostare di una password principale.</value>
|
||||||
|
</data>
|
||||||
|
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||||
|
<value>Imposta un metodo di sblocco per modificare l'azione timeout cassaforte.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
|
@ -2861,4 +2861,13 @@
|
||||||
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
||||||
<value>アカウントからログアウトしました。</value>
|
<value>アカウントからログアウトしました。</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="YourOrganizationPermissionsWereUpdatedRequeringYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>組織の権限が更新され、マスターパスワードの設定が必要になりました。</value>
|
||||||
|
</data>
|
||||||
|
<data name="YourOrganizationRequiresYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>あなたの組織では、マスターパスワードの設定が義務付けられています。</value>
|
||||||
|
</data>
|
||||||
|
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||||
|
<value>保管庫のタイムアウト動作を変更するには、ロック解除方法を設定してください。</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
|
@ -2862,4 +2862,13 @@ Do you want to switch to this account?</value>
|
||||||
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
<data name="AccountLoggedOutBiometricExceeded" xml:space="preserve">
|
||||||
<value>Account logged out.</value>
|
<value>Account logged out.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="YourOrganizationPermissionsWereUpdatedRequeringYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Your organization permissions were updated, requiring you to set a master password.</value>
|
||||||
|
</data>
|
||||||
|
<data name="YourOrganizationRequiresYouToSetAMasterPassword" xml:space="preserve">
|
||||||
|
<value>Your organization requires you to set a master password.</value>
|
||||||
|
</data>
|
||||||
|
<data name="SetUpAnUnlockOptionToChangeYourVaultTimeoutAction" xml:space="preserve">
|
||||||
|
<value>Set up an unlock option to change your vault timeout action.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue