diff --git a/Directory.Build.props b/Directory.Build.props new file mode 100644 index 000000000..bf789590a --- /dev/null +++ b/Directory.Build.props @@ -0,0 +1,5 @@ + + + 8.0.4-nightly.* + + \ No newline at end of file diff --git a/nuget.config b/nuget.config new file mode 100644 index 000000000..16502a7fd --- /dev/null +++ b/nuget.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/App/App.csproj b/src/App/App.csproj index d94eb737a..3f7bac275 100644 --- a/src/App/App.csproj +++ b/src/App/App.csproj @@ -156,6 +156,15 @@ + + + + + + + + + @@ -236,4 +245,15 @@ + + + + + + + + + + + diff --git a/src/App/Platforms/Android/AndroidManifest.xml b/src/App/Platforms/Android/AndroidManifest.xml index 58f975681..fe5203eab 100644 --- a/src/App/Platforms/Android/AndroidManifest.xml +++ b/src/App/Platforms/Android/AndroidManifest.xml @@ -1,5 +1,5 @@  - + diff --git a/src/App/Platforms/iOS/AppDelegate.cs b/src/App/Platforms/iOS/AppDelegate.cs index 48ddf1ba2..4961ab97b 100644 --- a/src/App/Platforms/iOS/AppDelegate.cs +++ b/src/App/Platforms/iOS/AppDelegate.cs @@ -54,10 +54,6 @@ namespace Bit.iOS _stateService = ServiceContainer.Resolve("stateService"); _eventService = ServiceContainer.Resolve("eventService"); - //LoadApplication(new App.App(null)); - //iOSCoreHelpers.AppearanceAdjustments(); - //ZXing.Net.Mobile.Forms.iOS.Platform.Init(); - ConnectToWatchIfNeededAsync().FireAndForget(); _broadcasterService.Subscribe(nameof(AppDelegate), async (message) => @@ -221,7 +217,11 @@ namespace Bit.iOS public override void DidEnterBackground(UIApplication uiApplication) { - _stateService?.SetLastActiveTimeAsync(_deviceActionService.GetActiveTime()); + if (_stateService != null && _deviceActionService != null) + { + _stateService.SetLastActiveTimeAsync(_deviceActionService.GetActiveTime()); + } + _messagingService?.Send("slept"); base.DidEnterBackground(uiApplication); } diff --git a/src/App/Platforms/iOS/Info.plist b/src/App/Platforms/iOS/Info.plist index cf0fe5084..da8dfd7d0 100644 --- a/src/App/Platforms/iOS/Info.plist +++ b/src/App/Platforms/iOS/Info.plist @@ -11,7 +11,7 @@ CFBundleIdentifier com.8bit.bitwarden CFBundleShortVersionString - 2024.1.0 + 2024.1.1 CFBundleVersion 1 CFBundleIconName diff --git a/src/iOS/Resources/Assets.xcassets/LaunchScreen.imageset/logo.png b/src/App/Platforms/iOS/Resources/logo.png similarity index 100% rename from src/iOS/Resources/Assets.xcassets/LaunchScreen.imageset/logo.png rename to src/App/Platforms/iOS/Resources/logo.png diff --git a/src/iOS/Resources/Assets.xcassets/LaunchScreen.imageset/logo@2x.png b/src/App/Platforms/iOS/Resources/logo@2x.png similarity index 100% rename from src/iOS/Resources/Assets.xcassets/LaunchScreen.imageset/logo@2x.png rename to src/App/Platforms/iOS/Resources/logo@2x.png diff --git a/src/iOS/Resources/Assets.xcassets/LaunchScreen.imageset/logo@3x.png b/src/App/Platforms/iOS/Resources/logo@3x.png similarity index 100% rename from src/iOS/Resources/Assets.xcassets/LaunchScreen.imageset/logo@3x.png rename to src/App/Platforms/iOS/Resources/logo@3x.png diff --git a/src/iOS/Resources/Assets.xcassets/LaunchScreen.imageset/logo_white.png b/src/App/Platforms/iOS/Resources/logo_white.png similarity index 100% rename from src/iOS/Resources/Assets.xcassets/LaunchScreen.imageset/logo_white.png rename to src/App/Platforms/iOS/Resources/logo_white.png diff --git a/src/iOS/Resources/Assets.xcassets/LaunchScreen.imageset/logo_white@2x.png b/src/App/Platforms/iOS/Resources/logo_white@2x.png similarity index 100% rename from src/iOS/Resources/Assets.xcassets/LaunchScreen.imageset/logo_white@2x.png rename to src/App/Platforms/iOS/Resources/logo_white@2x.png diff --git a/src/iOS/Resources/Assets.xcassets/LaunchScreen.imageset/logo_white@3x.png b/src/App/Platforms/iOS/Resources/logo_white@3x.png similarity index 100% rename from src/iOS/Resources/Assets.xcassets/LaunchScreen.imageset/logo_white@3x.png rename to src/App/Platforms/iOS/Resources/logo_white@3x.png diff --git a/src/iOS/Resources/more_vert.png b/src/App/Platforms/iOS/Resources/more_vert.png similarity index 100% rename from src/iOS/Resources/more_vert.png rename to src/App/Platforms/iOS/Resources/more_vert.png diff --git a/src/iOS/Resources/more_vert@2x.png b/src/App/Platforms/iOS/Resources/more_vert@2x.png similarity index 100% rename from src/iOS/Resources/more_vert@2x.png rename to src/App/Platforms/iOS/Resources/more_vert@2x.png diff --git a/src/iOS/Resources/more_vert@3x.png b/src/App/Platforms/iOS/Resources/more_vert@3x.png similarity index 100% rename from src/iOS/Resources/more_vert@3x.png rename to src/App/Platforms/iOS/Resources/more_vert@3x.png diff --git a/src/Core/App.xaml.cs b/src/Core/App.xaml.cs index 38709023f..7b18301ec 100644 --- a/src/Core/App.xaml.cs +++ b/src/Core/App.xaml.cs @@ -35,6 +35,8 @@ namespace Bit.App private readonly IAccountsManager _accountsManager; private readonly IPushNotificationService _pushNotificationService; private readonly IConfigService _configService; + private readonly ILogger _logger; + private static bool _isResumed; // these variables are static because the app is launching new activities on notification click, creating new instances of App. private static bool _pendingCheckPasswordlessLoginRequests; @@ -155,6 +157,7 @@ namespace Bit.App _accountsManager = ServiceContainer.Resolve("accountsManager"); _pushNotificationService = ServiceContainer.Resolve(); _configService = ServiceContainer.Resolve(); + _logger = ServiceContainer.Resolve(); _accountsManager.Init(() => Options, this); @@ -169,7 +172,7 @@ namespace Bit.App var confirmed = true; var confirmText = string.IsNullOrWhiteSpace(details.ConfirmText) ? AppResources.Ok : details.ConfirmText; - MainThread.BeginInvokeOnMainThread(async () => + await MainThread.InvokeOnMainThreadAsync(async () => { if (!string.IsNullOrWhiteSpace(details.CancelText)) { @@ -183,20 +186,16 @@ namespace Bit.App _messagingService.Send("showDialogResolve", new Tuple(details.DialogId, confirmed)); }); } +#if IOS else if (message.Command == AppHelpers.RESUMED_MESSAGE_COMMAND) { - if (DeviceInfo.Platform == DevicePlatform.iOS) - { - ResumedAsync().FireAndForget(); - } + ResumedAsync().FireAndForget(); } else if (message.Command == "slept") { - if (DeviceInfo.Platform == DevicePlatform.iOS) - { - await SleptAsync(); - } + await SleptAsync(); } +#endif else if (message.Command == "migrated") { await Task.Delay(1000); @@ -213,7 +212,7 @@ namespace Bit.App Options.OtpData = new OtpData((string)message.Data); } - MainThread.InvokeOnMainThreadAsync(async () => + await MainThread.InvokeOnMainThreadAsync(async () => { if (MainPage is TabsPage tabsPage) { @@ -249,7 +248,7 @@ namespace Bit.App } else if (message.Command == "convertAccountToKeyConnector") { - MainThread.BeginInvokeOnMainThread(async () => + await MainThread.InvokeOnMainThreadAsync(async () => { await MainPage.Navigation.PushModalAsync( new NavigationPage(new RemoveMasterPasswordPage())); @@ -257,7 +256,7 @@ namespace Bit.App } else if (message.Command == Constants.ForceUpdatePassword) { - MainThread.BeginInvokeOnMainThread(async () => + await MainThread.InvokeOnMainThreadAsync(async () => { await MainPage.Navigation.PushModalAsync( new NavigationPage(new UpdateTempPasswordPage())); @@ -373,40 +372,52 @@ namespace Bit.App protected override async void OnStart() { - System.Diagnostics.Debug.WriteLine("XF App: OnStart"); - _isResumed = true; - await ClearCacheIfNeededAsync(); - Prime(); - if (string.IsNullOrWhiteSpace(Options.Uri)) + try { - var updated = await AppHelpers.PerformUpdateTasksAsync(_syncService, _deviceActionService, - _stateService); - if (!updated) + System.Diagnostics.Debug.WriteLine("XF App: OnStart"); + _isResumed = true; + await ClearCacheIfNeededAsync(); + Prime(); + if (string.IsNullOrWhiteSpace(Options.Uri)) { - SyncIfNeeded(); + var updated = await AppHelpers.PerformUpdateTasksAsync(_syncService, _deviceActionService, + _stateService); + if (!updated) + { + SyncIfNeeded(); + } } - } - if (_pendingCheckPasswordlessLoginRequests) - { - _messagingService.Send(Constants.PasswordlessLoginRequestKey); - } - if (DeviceInfo.Platform == DevicePlatform.Android) - { + if (_pendingCheckPasswordlessLoginRequests) + { + _messagingService.Send(Constants.PasswordlessLoginRequestKey); + } + #if ANDROID await _vaultTimeoutService.CheckVaultTimeoutAsync(); // Reset delay on every start _vaultTimeoutService.DelayLockAndLogoutMs = null; - } + #endif - await _configService.GetAsync(); - _messagingService.Send("startEventTimer"); + await _configService.GetAsync(); + _messagingService.Send("startEventTimer"); + } + catch (Exception ex) + { + _logger?.Exception(ex); + throw; + } } +#if ANDROID protected override async void OnSleep() +#else + protected override void OnSleep() +#endif { - System.Diagnostics.Debug.WriteLine("XF App: OnSleep"); - _isResumed = false; - if (DeviceInfo.Platform == DevicePlatform.Android) + try { + System.Diagnostics.Debug.WriteLine("XF App: OnSleep"); + _isResumed = false; +#if ANDROID var isLocked = await _vaultTimeoutService.IsLockedAsync(); if (!isLocked) { @@ -417,20 +428,34 @@ namespace Bit.App ClearAutofillUri(); } await SleptAsync(); +#endif + } + catch (Exception ex) + { + _logger?.Exception(ex); + throw; } } protected override void OnResume() { - System.Diagnostics.Debug.WriteLine("XF App: OnResume"); - _isResumed = true; - if (_pendingCheckPasswordlessLoginRequests) - { - _messagingService.Send(Constants.PasswordlessLoginRequestKey); - } - if (DeviceInfo.Platform == DevicePlatform.Android) + try { + System.Diagnostics.Debug.WriteLine("XF App: OnResume"); + _isResumed = true; + if (_pendingCheckPasswordlessLoginRequests) + { + _messagingService.Send(Constants.PasswordlessLoginRequestKey); + } +#if ANDROID ResumedAsync().FireAndForget(); +#endif + + } + catch (Exception ex) + { + _logger?.Exception(ex); + throw; } } @@ -517,14 +542,22 @@ namespace Bit.App { MainThread.BeginInvokeOnMainThread(() => { - Options.Uri = null; - if (isLocked) + try { - App.MainPage = new NavigationPage(new LockPage()); + Options.Uri = null; + if (isLocked) + { + App.MainPage = new NavigationPage(new LockPage()); + } + else + { + App.MainPage = new TabsPage(); + } } - else + catch (Exception ex) { - App.MainPage = new TabsPage(); + LoggerHelper.LogEvenIfCantBeResolved(ex); + throw; } }); }); @@ -549,7 +582,7 @@ namespace Bit.App ThemeManager.SetTheme(Resources); RequestedThemeChanged += (s, a) => { - UpdateThemeAsync(); + UpdateThemeAsync().FireAndForget(); }; _isResumed = true; #if IOS @@ -568,11 +601,18 @@ namespace Bit.App } Task.Run(async () => { - var lastSync = await _syncService.GetLastSyncAsync(); - if (lastSync == null || ((DateTime.UtcNow - lastSync) > TimeSpan.FromMinutes(30))) + try { - await Task.Delay(1000); - await _syncService.FullSyncAsync(false); + var lastSync = await _syncService.GetLastSyncAsync(); + if (lastSync == null || ((DateTime.UtcNow - lastSync) > TimeSpan.FromMinutes(30))) + { + await Task.Delay(1000); + await _syncService.FullSyncAsync(false); + } + } + catch (Exception ex) + { + _logger.Exception(ex); } }); } diff --git a/src/Core/Pages/Accounts/HomePageViewModel.cs b/src/Core/Pages/Accounts/HomePageViewModel.cs index 13686ee99..193c2bd85 100644 --- a/src/Core/Pages/Accounts/HomePageViewModel.cs +++ b/src/Core/Pages/Accounts/HomePageViewModel.cs @@ -165,7 +165,7 @@ namespace Bit.App.Pages await MainThread.InvokeOnMainThreadAsync(async () => { - var result = await Page.DisplayActionSheet(AppResources.LoggingInOn, AppResources.Cancel, null, options); + var result = await _deviceActionService.Value.DisplayActionSheetAsync(AppResources.LoggingInOn, AppResources.Cancel, null, options); if (result is null || result == AppResources.Cancel) { diff --git a/src/Core/Pages/Accounts/LockPage.xaml.cs b/src/Core/Pages/Accounts/LockPage.xaml.cs index 0cf421abe..6861f7bc2 100644 --- a/src/Core/Pages/Accounts/LockPage.xaml.cs +++ b/src/Core/Pages/Accounts/LockPage.xaml.cs @@ -4,6 +4,7 @@ using Bit.App.Utilities; using Bit.Core; using Bit.Core.Abstractions; using Bit.Core.Utilities; +using Bit.Core.Services; namespace Bit.App.Pages { @@ -26,16 +27,24 @@ namespace Bit.App.Pages _vm = BindingContext as LockPageViewModel; _vm.CheckPendingAuthRequests = checkPendingAuthRequests; _vm.Page = this; - _vm.UnlockedAction = () => MainThread.BeginInvokeOnMainThread(async () => await UnlockedAsync()); + _vm.UnlockedAction = () => MainThread.BeginInvokeOnMainThread(async () => + { + try + { + await UnlockedAsync(); + } + catch (Exception ex) + { + LoggerHelper.LogEvenIfCantBeResolved(ex); + throw; + } + }); - if (DeviceInfo.Platform == DevicePlatform.iOS) - { - ToolbarItems.Add(_moreItem); - } - else - { - ToolbarItems.Add(_logOut); - } +#if IOS + ToolbarItems.Add(_moreItem); +#else + ToolbarItems.Add(_logOut); +#endif } public Entry SecretEntry @@ -65,52 +74,60 @@ namespace Bit.App.Pages protected override async void OnAppearing() { - base.OnAppearing(); - _broadcasterService.Subscribe(nameof(LockPage), message => + try { - if (message.Command == Constants.ClearSensitiveFields) + base.OnAppearing(); + _broadcasterService.Subscribe(nameof(LockPage), message => { - MainThread.BeginInvokeOnMainThread(_vm.ResetPinPasswordFields); - } - }); - if (_appeared) - { - return; - } - - _appeared = true; - _mainContent.Content = _mainLayout; - - //Workaround: This delay allows the Avatar to correctly load on iOS. The cause of this issue is also likely connected with the race conditions issue when using loading modals in iOS - await Task.Delay(50); - - _accountAvatar?.OnAppearing(); - - _vm.AvatarImageSource = await GetAvatarImageSourceAsync(); - - await _vm.InitAsync(); - - _vm.FocusSecretEntry += PerformFocusSecretEntry; - - if (!_vm.BiometricEnabled) - { - RequestFocus(SecretEntry); - } - else - { - if (!_vm.HasMasterPassword && !_vm.PinEnabled) - { - _passwordGrid.IsVisible = false; - _unlockButton.IsVisible = false; - } - if (_autoPromptBiometric) - { - var tasks = Task.Run(async () => + if (message.Command == Constants.ClearSensitiveFields) { - await Task.Delay(500); - MainThread.BeginInvokeOnMainThread(async () => await _vm.PromptBiometricAsync()); - }); + MainThread.BeginInvokeOnMainThread(_vm.ResetPinPasswordFields); + } + }); + if (_appeared) + { + return; } + + _appeared = true; + _mainContent.Content = _mainLayout; + + //Workaround: This delay allows the Avatar to correctly load on iOS. The cause of this issue is also likely connected with the race conditions issue when using loading modals in iOS + await Task.Delay(50); + + _accountAvatar?.OnAppearing(); + + _vm.AvatarImageSource = await GetAvatarImageSourceAsync(); + + await _vm.InitAsync(); + + _vm.FocusSecretEntry += PerformFocusSecretEntry; + + if (!_vm.BiometricEnabled) + { + RequestFocus(SecretEntry); + } + else + { + if (!_vm.HasMasterPassword && !_vm.PinEnabled) + { + _passwordGrid.IsVisible = false; + _unlockButton.IsVisible = false; + } + if (_autoPromptBiometric) + { + var tasks = Task.Run(async () => + { + await Task.Delay(500); + await MainThread.InvokeOnMainThreadAsync(async () => await _vm.PromptBiometricAsync()); + }); + } + } + } + catch (Exception ex) + { + LoggerHelper.LogEvenIfCantBeResolved(ex); + throw; } } @@ -167,27 +184,44 @@ namespace Bit.App.Pages private async void Biometric_Clicked(object sender, EventArgs e) { - if (DoOnce()) + try { - await _vm.PromptBiometricAsync(); + if (DoOnce()) + { + await _vm.PromptBiometricAsync(); + } + + } + catch (Exception ex) + { + LoggerHelper.LogEvenIfCantBeResolved(ex); + throw; } } private async void More_Clicked(object sender, System.EventArgs e) { - await _accountListOverlay.HideAsync(); - - if (!DoOnce()) + try { - return; + await _accountListOverlay.HideAsync(); + + if (!DoOnce()) + { + return; + } + + var selection = await DisplayActionSheet(AppResources.Options, + AppResources.Cancel, null, AppResources.LogOut); + + if (selection == AppResources.LogOut) + { + await _vm.LogOutAsync(); + } } - - var selection = await DisplayActionSheet(AppResources.Options, - AppResources.Cancel, null, AppResources.LogOut); - - if (selection == AppResources.LogOut) + catch (Exception ex) { - await _vm.LogOutAsync(); + LoggerHelper.LogEvenIfCantBeResolved(ex); + throw; } } diff --git a/src/Core/Pages/BaseContentPage.cs b/src/Core/Pages/BaseContentPage.cs index fcb1ca1f9..d04c8a852 100644 --- a/src/Core/Pages/BaseContentPage.cs +++ b/src/Core/Pages/BaseContentPage.cs @@ -14,6 +14,7 @@ namespace Bit.App.Pages { private readonly LazyResolve _stateService = new LazyResolve(); private readonly LazyResolve _deviceActionService = new LazyResolve(); + private readonly LazyResolve _logger = new LazyResolve(); protected int ShowModalAnimationDelay = 400; protected int ShowPageAnimationDelay = 100; @@ -48,22 +49,38 @@ namespace Bit.App.Pages protected override async void OnNavigatedTo(NavigatedToEventArgs args) { - base.OnNavigatedTo(args); - - if (IsThemeDirty) + try { - UpdateOnThemeChanged(); + base.OnNavigatedTo(args); + + if (IsThemeDirty) + { + try + { + await UpdateOnThemeChanged(); + } + catch (Exception ex) + { + Core.Services.LoggerHelper.LogEvenIfCantBeResolved(ex); + // Don't rethrow on theme changed so the user can still continue on the app. + } + } + + await SaveActivityAsync(); + + if (ShouldCheckToPreventOnNavigatedToCalledTwice && _hasInitedOnNavigatedTo) + { + return; + } + _hasInitedOnNavigatedTo = true; + + await InitOnNavigatedToAsync(); } - - await SaveActivityAsync(); - - if (ShouldCheckToPreventOnNavigatedToCalledTwice && _hasInitedOnNavigatedTo) + catch (Exception ex) { - return; + Core.Services.LoggerHelper.LogEvenIfCantBeResolved(ex); + throw; } - _hasInitedOnNavigatedTo = true; - - await InitOnNavigatedToAsync(); } protected virtual Task InitOnNavigatedToAsync() => Task.CompletedTask; @@ -116,29 +133,37 @@ namespace Bit.App.Pages { async Task DoWorkAsync() { - await workFunction.Invoke(); - if (sourceView != null) + try { - if (targetView != null) + await workFunction.Invoke(); + if (sourceView != null) { - targetView.Content = sourceView; - } - else - { - Content = sourceView; + if (targetView != null) + { + targetView.Content = sourceView; + } + else + { + Content = sourceView; + } } } + catch (Exception ex) + { + _logger.Value.Exception(ex); + throw; + } } - if (DeviceInfo.Platform == DevicePlatform.iOS) - { - await DoWorkAsync(); - return; - } + +#if IOS + await DoWorkAsync(); +#else await Task.Run(async () => { await Task.Delay(fromModal ? ShowModalAnimationDelay : ShowPageAnimationDelay); MainThread.BeginInvokeOnMainThread(async () => await DoWorkAsync()); }); +#endif } protected void RequestFocus(InputView input) diff --git a/src/Core/Pages/Generator/GeneratorHistoryPageViewModel.cs b/src/Core/Pages/Generator/GeneratorHistoryPageViewModel.cs index ec03c7451..8ec43fcdb 100644 --- a/src/Core/Pages/Generator/GeneratorHistoryPageViewModel.cs +++ b/src/Core/Pages/Generator/GeneratorHistoryPageViewModel.cs @@ -42,7 +42,7 @@ namespace Bit.App.Pages public async Task InitAsync() { var history = await _passwordGenerationService.GetHistoryAsync(); - Device.BeginInvokeOnMainThread(() => + MainThread.BeginInvokeOnMainThread(() => { History.ResetWithRange(history ?? new List()); ShowNoData = History.Count == 0; @@ -66,7 +66,7 @@ namespace Bit.App.Pages { try { - await Device.InvokeOnMainThreadAsync(() => History.ResetWithRange(new List())); + await MainThread.InvokeOnMainThreadAsync(() => History.ResetWithRange(new List())); await InitAsync(); } diff --git a/src/Core/Pages/Generator/GeneratorPage.xaml.cs b/src/Core/Pages/Generator/GeneratorPage.xaml.cs index e0d336642..8ddb61dc3 100644 --- a/src/Core/Pages/Generator/GeneratorPage.xaml.cs +++ b/src/Core/Pages/Generator/GeneratorPage.xaml.cs @@ -15,6 +15,7 @@ namespace Bit.App.Pages public partial class GeneratorPage : BaseContentPage, IThemeDirtablePage { private readonly IBroadcasterService _broadcasterService; + private readonly ILogger _logger; private GeneratorPageViewModel _vm; private readonly bool _fromTabPage; @@ -26,6 +27,8 @@ namespace Bit.App.Pages _tabsPage = tabsPage; InitializeComponent(); _broadcasterService = ServiceContainer.Resolve(); + _logger = ServiceContainer.Resolve(); + _vm = BindingContext as GeneratorPageViewModel; _vm.Page = this; _fromTabPage = fromTabPage; @@ -35,26 +38,21 @@ namespace Bit.App.Pages _vm.EmailWebsite = emailWebsite; _vm.EditMode = editMode; _vm.IosExtension = appOptions?.IosExtension ?? false; - // 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 - var isIos = Device.RuntimePlatform == Device.iOS; + if (selectAction != null) { - if (isIos) - { - ToolbarItems.Add(_closeItem); - } +#if IOS + ToolbarItems.Add(_closeItem); +#endif ToolbarItems.Add(_selectItem); } else { - if (isIos) - { - ToolbarItems.Add(_moreItem); - } - else - { - ToolbarItems.Add(_historyItem); - } +#if IOS + ToolbarItems.Add(_moreItem); +#else + ToolbarItems.Add(_historyItem); +#endif } _typePicker.On().SetUpdateMode(UpdateMode.WhenFinished); _passwordTypePicker.On().SetUpdateMode(UpdateMode.WhenFinished); @@ -71,22 +69,30 @@ namespace Bit.App.Pages protected async override void OnAppearing() { - base.OnAppearing(); - - lblPassword.IsVisible = true; - - if (!_fromTabPage) + try { - await InitAsync(); - } + base.OnAppearing(); - _broadcasterService.Subscribe(nameof(GeneratorPage), (message) => - { - if (message.Command is ThemeManager.UPDATED_THEME_MESSAGE_KEY) + lblPassword.IsVisible = true; + + if (!_fromTabPage) { - Device.BeginInvokeOnMainThread(() => _vm.RedrawPassword()); + await InitAsync(); } - }); + + _broadcasterService.Subscribe(nameof(GeneratorPage), (message) => + { + if (message.Command is ThemeManager.UPDATED_THEME_MESSAGE_KEY) + { + MainThread.BeginInvokeOnMainThread(() => _vm.RedrawPassword()); + } + }); + } + catch (Exception ex) + { + _logger.Exception(ex); + throw; + } } protected override void OnDisappearing() @@ -100,27 +106,35 @@ namespace Bit.App.Pages protected override bool OnBackButtonPressed() { - // 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 (Device.RuntimePlatform == Device.Android && _tabsPage != null) +#if ANDROID + if (_tabsPage != null) { _tabsPage.ResetToVaultPage(); return true; } +#endif return base.OnBackButtonPressed(); } private async void More_Clicked(object sender, EventArgs e) { - if (!DoOnce()) + try { - return; + if (!DoOnce()) + { + return; + } + var selection = await DisplayActionSheet(AppResources.Options, AppResources.Cancel, + null, AppResources.PasswordHistory); + if (selection == AppResources.PasswordHistory) + { + var page = new GeneratorHistoryPage(); + await Navigation.PushModalAsync(new Microsoft.Maui.Controls.NavigationPage(page)); + } } - var selection = await DisplayActionSheet(AppResources.Options, AppResources.Cancel, - null, AppResources.PasswordHistory); - if (selection == AppResources.PasswordHistory) + catch (Exception ex) { - var page = new GeneratorHistoryPage(); - await Navigation.PushModalAsync(new Microsoft.Maui.Controls.NavigationPage(page)); + _logger.Exception(ex); } } @@ -144,7 +158,7 @@ namespace Bit.App.Pages { await base.UpdateOnThemeChanged(); - await Device.InvokeOnMainThreadAsync(() => + await MainThread.InvokeOnMainThreadAsync(() => { if (_vm != null) { diff --git a/src/Core/Pages/Send/SendGroupingsPage/SendGroupingsPage.xaml.cs b/src/Core/Pages/Send/SendGroupingsPage/SendGroupingsPage.xaml.cs index e9b0eacdd..f7320d8fb 100644 --- a/src/Core/Pages/Send/SendGroupingsPage/SendGroupingsPage.xaml.cs +++ b/src/Core/Pages/Send/SendGroupingsPage/SendGroupingsPage.xaml.cs @@ -18,6 +18,7 @@ namespace Bit.App.Pages private readonly ISyncService _syncService; private readonly IVaultTimeoutService _vaultTimeoutService; private readonly ISendService _sendService; + private readonly ILogger _logger; private readonly SendGroupingsPageViewModel _vm; private readonly string _pageName; @@ -33,6 +34,8 @@ namespace Bit.App.Pages _syncService = ServiceContainer.Resolve("syncService"); _vaultTimeoutService = ServiceContainer.Resolve("vaultTimeoutService"); _sendService = ServiceContainer.Resolve("sendService"); + _logger = ServiceContainer.Resolve(); + _vm = BindingContext as SendGroupingsPageViewModel; _vm.Page = this; _vm.MainPage = mainPage; @@ -43,85 +46,89 @@ namespace Bit.App.Pages _vm.PageTitle = pageTitle; } - // 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 (Device.RuntimePlatform == Device.iOS) +#if IOS + _absLayout.Children.Remove(_fab); + if (type == null) { - _absLayout.Children.Remove(_fab); - if (type == null) - { - ToolbarItems.Add(_aboutIconItem); - } - ToolbarItems.Add(_addItem); - } - else - { - ToolbarItems.Add(_syncItem); - ToolbarItems.Add(_lockItem); - ToolbarItems.Add(_aboutTextItem); + ToolbarItems.Add(_aboutIconItem); } + ToolbarItems.Add(_addItem); +#else + ToolbarItems.Add(_syncItem); + ToolbarItems.Add(_lockItem); + ToolbarItems.Add(_aboutTextItem); +#endif } protected override async void OnAppearing() { - base.OnAppearing(); - if (_syncService.SyncInProgress) + try { - IsBusy = true; - } - - _broadcasterService.Subscribe(_pageName, async (message) => - { - try + base.OnAppearing(); + if (_syncService.SyncInProgress) { - if (message.Command == "syncStarted") - { - Device.BeginInvokeOnMainThread(() => IsBusy = true); - } - else if (message.Command == "syncCompleted" || message.Command == "sendUpdated") - { - await Task.Delay(500); - Device.BeginInvokeOnMainThread(() => - { - IsBusy = false; - if (_vm.LoadedOnce) - { - var task = _vm.LoadAsync(); - } - }); - } + IsBusy = true; } - catch (Exception ex) - { - LoggerHelper.LogEvenIfCantBeResolved(ex); - } - }); - await LoadOnAppearedAsync(_mainLayout, false, async () => - { - if (!_syncService.SyncInProgress || (await _sendService.GetAllAsync()).Any()) + _broadcasterService.Subscribe(_pageName, async (message) => { try { - await _vm.LoadAsync(); + if (message.Command == "syncStarted") + { + MainThread.BeginInvokeOnMainThread(() => IsBusy = true); + } + else if (message.Command == "syncCompleted" || message.Command == "sendUpdated") + { + await Task.Delay(500); + await MainThread.InvokeOnMainThreadAsync(() => + { + IsBusy = false; + if (_vm.LoadedOnce) + { + var task = _vm.LoadAsync(); + } + }); + } } - catch (Exception e) when (e.Message.Contains("No key.")) + catch (Exception ex) { - await Task.Delay(1000); - await _vm.LoadAsync(); + LoggerHelper.LogEvenIfCantBeResolved(ex); } - } - else - { - await Task.Delay(5000); - if (!_vm.Loaded) - { - await _vm.LoadAsync(); - } - } + }); - AdjustToolbar(); - await CheckAddRequest(); - }, _mainContent); + await LoadOnAppearedAsync(_mainLayout, false, async () => + { + if (!_syncService.SyncInProgress || (await _sendService.GetAllAsync()).Any()) + { + try + { + await _vm.LoadAsync(); + } + catch (Exception e) when (e.Message.Contains("No key.")) + { + await Task.Delay(1000); + await _vm.LoadAsync(); + } + } + else + { + await Task.Delay(5000); + if (!_vm.Loaded) + { + await _vm.LoadAsync(); + } + } + + AdjustToolbar(); + await CheckAddRequest(); + }, _mainContent); + } + catch (Exception ex) + { + _logger.Exception(ex); + throw; + } } protected override void OnDisappearing() diff --git a/src/Core/Pages/Send/SendGroupingsPage/SendGroupingsPageViewModel.cs b/src/Core/Pages/Send/SendGroupingsPage/SendGroupingsPageViewModel.cs index 1050e223d..239f9421e 100644 --- a/src/Core/Pages/Send/SendGroupingsPage/SendGroupingsPageViewModel.cs +++ b/src/Core/Pages/Send/SendGroupingsPage/SendGroupingsPageViewModel.cs @@ -1,22 +1,11 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Bit.App.Abstractions; -using Bit.Core.Resources.Localization; +using Bit.App.Abstractions; using Bit.App.Utilities; -using Bit.Core; using Bit.Core.Abstractions; using Bit.Core.Enums; using Bit.Core.Models.View; +using Bit.Core.Resources.Localization; using Bit.Core.Utilities; -using DeviceType = Bit.Core.Enums.DeviceType; -using Microsoft.Maui.Networking; -using Microsoft.Maui.Devices; -using Microsoft.Maui.Controls; -using Microsoft.Maui; - namespace Bit.App.Pages { public class SendGroupingsPageViewModel : BaseViewModel @@ -117,28 +106,38 @@ namespace Bit.App.Pages { return; } - var authed = await _stateService.IsAuthenticatedAsync(); - if (!authed) + + try { - return; + var authed = await _stateService.IsAuthenticatedAsync(); + if (!authed) + { + return; + } + if (await _vaultTimeoutService.IsLockedAsync()) + { + return; + } + if (await _stateService.GetSyncOnRefreshAsync() && Refreshing && !SyncRefreshing) + { + SyncRefreshing = true; + await _syncService.FullSyncAsync(false); + return; + } + + _doingLoad = true; + LoadedOnce = true; + ShowNoData = false; + Loading = true; + ShowList = false; + SendEnabled = !await AppHelpers.IsSendDisabledByPolicyAsync(); } - if (await _vaultTimeoutService.IsLockedAsync()) + catch (Exception ex) { - return; - } - if (await _stateService.GetSyncOnRefreshAsync() && Refreshing && !SyncRefreshing) - { - SyncRefreshing = true; - await _syncService.FullSyncAsync(false); - return; + _logger.Value.Exception(ex); + throw; } - _doingLoad = true; - LoadedOnce = true; - ShowNoData = false; - Loading = true; - ShowList = false; - SendEnabled = !await AppHelpers.IsSendDisabledByPolicyAsync(); var groupedSends = new List(); var page = Page as SendGroupingsPage; @@ -146,8 +145,11 @@ namespace Bit.App.Pages { await LoadDataAsync(); - // 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 - var uppercaseGroupNames = Device.RuntimePlatform == Device.iOS; +#if IOS + var uppercaseGroupNames = true; +#else + var uppercaseGroupNames = false; +#endif if (MainPage) { groupedSends.Add(new SendGroupingsPageListGroup( @@ -208,6 +210,11 @@ namespace Bit.App.Pages } } } + catch (Exception ex) + { + _logger.Value.Exception(ex); + throw; + } finally { _doingLoad = false; @@ -315,14 +322,22 @@ namespace Bit.App.Pages private async void SendOptionsAsync(SendView send) { - if ((Page as BaseContentPage).DoOnce()) + try { - var selection = await AppHelpers.SendListOptions(Page, send); - if (selection == AppResources.RemovePassword || selection == AppResources.Delete) + if ((Page as BaseContentPage).DoOnce()) { - await LoadAsync(); + var selection = await AppHelpers.SendListOptions(Page, send); + if (selection == AppResources.RemovePassword || selection == AppResources.Delete) + { + await LoadAsync(); + } } } + catch (Exception ex) + { + _logger.Value.Exception(ex); + throw; + } } } } diff --git a/src/Core/Pages/Settings/ExportVaultPage.xaml.cs b/src/Core/Pages/Settings/ExportVaultPage.xaml.cs index 4d7a4276c..be8d8f94e 100644 --- a/src/Core/Pages/Settings/ExportVaultPage.xaml.cs +++ b/src/Core/Pages/Settings/ExportVaultPage.xaml.cs @@ -29,7 +29,7 @@ namespace Bit.App.Pages { if (message.Command == "selectSaveFileResult") { - Device.BeginInvokeOnMainThread(() => + MainThread.BeginInvokeOnMainThread(() => { var data = message.Data as Tuple; if (data == null) diff --git a/src/Core/Pages/Settings/LoginPasswordlessRequestsListPage.xaml.cs b/src/Core/Pages/Settings/LoginPasswordlessRequestsListPage.xaml.cs index c3c25583c..0a68ab640 100644 --- a/src/Core/Pages/Settings/LoginPasswordlessRequestsListPage.xaml.cs +++ b/src/Core/Pages/Settings/LoginPasswordlessRequestsListPage.xaml.cs @@ -49,12 +49,10 @@ namespace Bit.App.Pages private void UpdatePlaceholder() { - // 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 (Device.RuntimePlatform == Device.Android) - { - MainThread.BeginInvokeOnMainThread(() => - _emptyPlaceholder.Source = ImageSource.FromFile(ThemeManager.UsingLightTheme ? "empty_login_requests" : "empty_login_requests_dark")); - } +#if ANDROID + MainThread.BeginInvokeOnMainThread(() => + _emptyPlaceholder.Source = ImageSource.FromFile(ThemeManager.UsingLightTheme ? "empty_login_requests" : "empty_login_requests_dark")); +#endif } } } diff --git a/src/Core/Pages/TabsPage.cs b/src/Core/Pages/TabsPage.cs index c9d02e320..0371b44a9 100644 --- a/src/Core/Pages/TabsPage.cs +++ b/src/Core/Pages/TabsPage.cs @@ -10,6 +10,7 @@ using Bit.Core.Abstractions; using Bit.Core.Models.Data; using Bit.Core.Models.Domain; using Bit.Core.Utilities; +using Bit.Core.Services; namespace Bit.App.Pages { @@ -87,21 +88,29 @@ namespace Bit.App.Pages protected override async void OnAppearing() { - base.OnAppearing(); - _broadcasterService.Subscribe(nameof(TabsPage), async (message) => + try { - if (message.Command == "syncCompleted") + base.OnAppearing(); + _broadcasterService.Subscribe(nameof(TabsPage), async (message) => { - MainThread.BeginInvokeOnMainThread(async () => await UpdateVaultButtonTitleAsync()); + if (message.Command == "syncCompleted") + { + MainThread.BeginInvokeOnMainThread(async () => await UpdateVaultButtonTitleAsync()); + } + }); + await UpdateVaultButtonTitleAsync(); + if (await _keyConnectorService.UserNeedsMigrationAsync()) + { + _messagingService.Send("convertAccountToKeyConnector"); } - }); - await UpdateVaultButtonTitleAsync(); - if (await _keyConnectorService.UserNeedsMigrationAsync()) - { - _messagingService.Send("convertAccountToKeyConnector"); - } - await ForcePasswordResetIfNeededAsync(); + await ForcePasswordResetIfNeededAsync(); + } + catch (Exception ex) + { + LoggerHelper.LogEvenIfCantBeResolved(ex); + throw; + } } private async Task ForcePasswordResetIfNeededAsync() @@ -174,23 +183,31 @@ namespace Bit.App.Pages protected override async void OnCurrentPageChanged() { - if (CurrentPage is NavigationPage navPage) + try { - if (_groupingsPage?.RootPage is GroupingsPage groupingsPage) + if (CurrentPage is NavigationPage navPage) { - await groupingsPage.HideAccountSwitchingOverlayAsync(); - } + if (_groupingsPage?.RootPage is GroupingsPage groupingsPage) + { + await groupingsPage.HideAccountSwitchingOverlayAsync(); + } - _messagingService.Send(ThemeManager.UPDATED_THEME_MESSAGE_KEY); - if (navPage.RootPage is GroupingsPage) - { - // Load something? - } - else if (navPage.RootPage is GeneratorPage genPage) - { - await genPage.InitAsync(); + _messagingService.Send(ThemeManager.UPDATED_THEME_MESSAGE_KEY); + if (navPage.RootPage is GroupingsPage) + { + // Load something? + } + else if (navPage.RootPage is GeneratorPage genPage) + { + await genPage.InitAsync(); + } } } + catch (Exception ex) + { + LoggerHelper.LogEvenIfCantBeResolved(ex); + throw; + } } public void OnPageReselected() diff --git a/src/Core/Pages/Vault/AttachmentsPage.xaml.cs b/src/Core/Pages/Vault/AttachmentsPage.xaml.cs index 319a2ffdd..9e56148db 100644 --- a/src/Core/Pages/Vault/AttachmentsPage.xaml.cs +++ b/src/Core/Pages/Vault/AttachmentsPage.xaml.cs @@ -33,7 +33,7 @@ namespace Bit.App.Pages { if (message.Command == "selectFileResult") { - Device.BeginInvokeOnMainThread(() => + MainThread.BeginInvokeOnMainThread(() => { var data = message.Data as Tuple; _vm.FileData = data.Item1; diff --git a/src/Core/Pages/Vault/CipherAddEditPage.xaml.cs b/src/Core/Pages/Vault/CipherAddEditPage.xaml.cs index 792e4a63a..1ff0be66c 100644 --- a/src/Core/Pages/Vault/CipherAddEditPage.xaml.cs +++ b/src/Core/Pages/Vault/CipherAddEditPage.xaml.cs @@ -7,6 +7,7 @@ using Bit.Core.Enums; using Bit.Core.Utilities; using Microsoft.Maui.Controls.PlatformConfiguration; using Microsoft.Maui.Controls.PlatformConfiguration.iOSSpecific; +using Bit.Core.Services; namespace Bit.App.Pages { @@ -263,8 +264,16 @@ namespace Bit.App.Pages { MainThread.BeginInvokeOnMainThread(async () => { - await Navigation.PopModalAsync(); - await _vm.UpdateTotpKeyAsync(key); + try + { + await Navigation.PopModalAsync(); + await _vm.UpdateTotpKeyAsync(key); + } + catch (Exception ex) + { + LoggerHelper.LogEvenIfCantBeResolved(ex); + throw; + } }); }); diff --git a/src/Core/Pages/Vault/CipherDetailsPage.xaml.cs b/src/Core/Pages/Vault/CipherDetailsPage.xaml.cs index 79a783011..f10fbee58 100644 --- a/src/Core/Pages/Vault/CipherDetailsPage.xaml.cs +++ b/src/Core/Pages/Vault/CipherDetailsPage.xaml.cs @@ -63,12 +63,12 @@ namespace Bit.App.Pages { if (message.Command == "syncStarted") { - Device.BeginInvokeOnMainThread(() => IsBusy = true); + MainThread.BeginInvokeOnMainThread(() => IsBusy = true); } else if (message.Command == "syncCompleted") { await Task.Delay(500); - Device.BeginInvokeOnMainThread(() => + MainThread.BeginInvokeOnMainThread(() => { IsBusy = false; if (message.Data is Dictionary data && data.ContainsKey("successfully")) @@ -83,7 +83,7 @@ namespace Bit.App.Pages } else if (message.Command == "selectSaveFileResult") { - Device.BeginInvokeOnMainThread(() => + MainThread.BeginInvokeOnMainThread(() => { var data = message.Data as Tuple; if (data == null) diff --git a/src/Core/Pages/Vault/CiphersPageViewModel.cs b/src/Core/Pages/Vault/CiphersPageViewModel.cs index 44c786fd4..8a30deb8a 100644 --- a/src/Core/Pages/Vault/CiphersPageViewModel.cs +++ b/src/Core/Pages/Vault/CiphersPageViewModel.cs @@ -109,52 +109,59 @@ namespace Bit.App.Pages var cts = new CancellationTokenSource(); Task.Run(async () => { - List ciphers = null; - var searchable = !string.IsNullOrWhiteSpace(searchText) && searchText.Length > 1; - var shouldShowAllWhenEmpty = ShowAllIfSearchTextEmpty && string.IsNullOrEmpty(searchText); - if (searchable || shouldShowAllWhenEmpty) + try { - if (timeout != null) + List ciphers = null; + var searchable = !string.IsNullOrWhiteSpace(searchText) && searchText.Length > 1; + var shouldShowAllWhenEmpty = ShowAllIfSearchTextEmpty && string.IsNullOrEmpty(searchText); + if (searchable || shouldShowAllWhenEmpty) { - await Task.Delay(timeout.Value); - } - if (searchText != (Page as CiphersPage).SearchBar.Text - && - !shouldShowAllWhenEmpty) - { - return; - } + if (timeout != null) + { + await Task.Delay(timeout.Value); + } + if (searchText != (Page as CiphersPage).SearchBar.Text + && + !shouldShowAllWhenEmpty) + { + return; + } - previousCts?.Cancel(); - try - { - var vaultFilteredCiphers = await GetAllCiphersAsync(); - if (!shouldShowAllWhenEmpty) + previousCts?.Cancel(); + try { - ciphers = await _searchService.SearchCiphersAsync(searchText, - Filter ?? (c => c.IsDeleted == Deleted), vaultFilteredCiphers, cts.Token); + var vaultFilteredCiphers = await GetAllCiphersAsync(); + if (!shouldShowAllWhenEmpty) + { + ciphers = await _searchService.SearchCiphersAsync(searchText, + Filter ?? (c => c.IsDeleted == Deleted), vaultFilteredCiphers, cts.Token); + } + else + { + ciphers = vaultFilteredCiphers; + } + cts.Token.ThrowIfCancellationRequested(); } - else + catch (OperationCanceledException) { - ciphers = vaultFilteredCiphers; + return; } - cts.Token.ThrowIfCancellationRequested(); } - catch (OperationCanceledException) + if (ciphers == null) { - return; + ciphers = new List(); } + MainThread.BeginInvokeOnMainThread(() => + { + Ciphers.ResetWithRange(ciphers.Select(c => new CipherItemViewModel(c, _websiteIconsEnabled)).ToList()); + ShowNoData = !shouldShowAllWhenEmpty && searchable && Ciphers.Count == 0; + ShowList = (searchable || shouldShowAllWhenEmpty) && !ShowNoData; + }); } - if (ciphers == null) + catch (Exception ex) { - ciphers = new List(); + _logger.Exception(ex); } - MainThread.BeginInvokeOnMainThread(() => - { - Ciphers.ResetWithRange(ciphers.Select(c => new CipherItemViewModel(c, _websiteIconsEnabled)).ToList()); - ShowNoData = !shouldShowAllWhenEmpty && searchable && Ciphers.Count == 0; - ShowList = (searchable || shouldShowAllWhenEmpty) && !ShowNoData; - }); }, cts.Token); _searchCancellationTokenSource = cts; } diff --git a/src/Core/Pages/Vault/GroupingsPage/GroupingsPage.xaml.cs b/src/Core/Pages/Vault/GroupingsPage/GroupingsPage.xaml.cs index 137626807..46d65d87c 100644 --- a/src/Core/Pages/Vault/GroupingsPage/GroupingsPage.xaml.cs +++ b/src/Core/Pages/Vault/GroupingsPage/GroupingsPage.xaml.cs @@ -1,9 +1,9 @@ using Bit.App.Abstractions; using Bit.App.Controls; -using Bit.Core.Resources.Localization; using Bit.Core.Abstractions; using Bit.Core.Enums; using Bit.Core.Models.Data; +using Bit.Core.Resources.Localization; using Bit.Core.Services; using Bit.Core.Utilities; @@ -19,6 +19,7 @@ namespace Bit.App.Pages private readonly ICipherService _cipherService; private readonly IDeviceActionService _deviceActionService; private readonly IPlatformUtilsService _platformUtilsService; + private readonly ILogger _logger; private readonly GroupingsPageViewModel _vm; private readonly string _pageName; @@ -39,6 +40,8 @@ namespace Bit.App.Pages _cipherService = ServiceContainer.Resolve("cipherService"); _deviceActionService = ServiceContainer.Resolve("deviceActionService"); _platformUtilsService = ServiceContainer.Resolve("platformUtilsService"); + _logger = ServiceContainer.Resolve(); + _vm = BindingContext as GroupingsPageViewModel; _vm.Page = this; _vm.MainPage = mainPage; @@ -57,17 +60,14 @@ namespace Bit.App.Pages _vm.VaultFilterDescription = vaultFilterSelection; } - if (DeviceInfo.Platform == DevicePlatform.iOS) - { - _absLayout.Children.Remove(_fab); - ToolbarItems.Add(_addItem); - } - else - { - ToolbarItems.Add(_syncItem); - ToolbarItems.Add(_lockItem); - ToolbarItems.Add(_exitItem); - } +#if IOS + _absLayout.Children.Remove(_fab); + ToolbarItems.Add(_addItem); +#else + ToolbarItems.Add(_syncItem); + ToolbarItems.Add(_lockItem); + ToolbarItems.Add(_exitItem); +#endif if (deleted || showTotp) { _absLayout.Children.Remove(_fab); @@ -81,107 +81,115 @@ namespace Bit.App.Pages protected override async void OnAppearing() { - base.OnAppearing(); - if (_syncService.SyncInProgress) + try { - IsBusy = true; - } - - _accountAvatar?.OnAppearing(); - if (_vm.MainPage) - { - _vm.AvatarImageSource = await GetAvatarImageSourceAsync(); - } - - _broadcasterService.Subscribe(_pageName, async (message) => - { - try + base.OnAppearing(); + if (_syncService.SyncInProgress) { - if (message.Command == "syncStarted") + IsBusy = true; + } + + _accountAvatar?.OnAppearing(); + if (_vm.MainPage) + { + _vm.AvatarImageSource = await GetAvatarImageSourceAsync(); + } + + _broadcasterService.Subscribe(_pageName, async (message) => + { + try { - MainThread.BeginInvokeOnMainThread(() => IsBusy = true); - } - else if (message.Command == "syncCompleted") - { - await Task.Delay(500); - if (_vm.MainPage) + if (message.Command == "syncStarted") { - _vm.AvatarImageSource = await GetAvatarImageSourceAsync(); + MainThread.BeginInvokeOnMainThread(() => IsBusy = true); } - MainThread.BeginInvokeOnMainThread(() => + else if (message.Command == "syncCompleted") { - IsBusy = false; - if (_vm.LoadedOnce) + await Task.Delay(500); + if (_vm.MainPage) { - var task = _vm.LoadAsync(); + _vm.AvatarImageSource = await GetAvatarImageSourceAsync(); } - }); + MainThread.BeginInvokeOnMainThread(() => + { + IsBusy = false; + if (_vm.LoadedOnce) + { + var task = _vm.LoadAsync(); + } + }); + } } - } - catch (Exception ex) - { - LoggerHelper.LogEvenIfCantBeResolved(ex); - } - }); - - await LoadOnAppearedAsync(_mainLayout, false, async () => - { - if (_previousPage == null) - { - if (!_syncService.SyncInProgress || (await _cipherService.GetAllAsync()).Any()) + catch (Exception ex) { - try - { - await _vm.LoadAsync(); - } - catch (Exception e) when (e.Message.Contains("No key.")) - { - await Task.Delay(1000); - await _vm.LoadAsync(); - } + LoggerHelper.LogEvenIfCantBeResolved(ex); } - else + }); + + await LoadOnAppearedAsync(_mainLayout, false, async () => + { + if (_previousPage == null) { - await Task.Delay(5000); - if (!_vm.Loaded) + if (!_syncService.SyncInProgress || (await _cipherService.GetAllAsync()).Any()) { - await _vm.LoadAsync(); + try + { + await _vm.LoadAsync(); + } + catch (Exception e) when (e.Message.Contains("No key.")) + { + await Task.Delay(1000); + await _vm.LoadAsync(); + } + } + else + { + await Task.Delay(5000); + if (!_vm.Loaded) + { + await _vm.LoadAsync(); + } } } - } - await ShowPreviousPageAsync(); - AdjustToolbar(); - }, _mainContent); + await ShowPreviousPageAsync(); + AdjustToolbar(); + }, _mainContent); - if (!_vm.MainPage) - { - return; - } - - // Push registration - var lastPushRegistration = await _stateService.GetPushLastRegistrationDateAsync(); - lastPushRegistration = lastPushRegistration.GetValueOrDefault(DateTime.MinValue); - if (DeviceInfo.Platform == DevicePlatform.iOS) - { - var pushPromptShow = await _stateService.GetPushInitialPromptShownAsync(); - if (!pushPromptShow.GetValueOrDefault(false)) + if (!_vm.MainPage) { - await _stateService.SetPushInitialPromptShownAsync(true); - await DisplayAlert(AppResources.EnableAutomaticSyncing, AppResources.PushNotificationAlert, - AppResources.OkGotIt); + return; } - if (!pushPromptShow.GetValueOrDefault(false) || - DateTime.UtcNow - lastPushRegistration > TimeSpan.FromDays(1)) + + // Push registration + var lastPushRegistration = await _stateService.GetPushLastRegistrationDateAsync(); + lastPushRegistration = lastPushRegistration.GetValueOrDefault(DateTime.MinValue); + if (DeviceInfo.Platform == DevicePlatform.iOS) { - await _pushNotificationService.RegisterAsync(); + var pushPromptShow = await _stateService.GetPushInitialPromptShownAsync(); + if (!pushPromptShow.GetValueOrDefault(false)) + { + await _stateService.SetPushInitialPromptShownAsync(true); + await DisplayAlert(AppResources.EnableAutomaticSyncing, AppResources.PushNotificationAlert, + AppResources.OkGotIt); + } + if (!pushPromptShow.GetValueOrDefault(false) || + DateTime.UtcNow - lastPushRegistration > TimeSpan.FromDays(1)) + { + await _pushNotificationService.RegisterAsync(); + } + } + else if (DeviceInfo.Platform == DevicePlatform.Android) + { + if (DateTime.UtcNow - lastPushRegistration > TimeSpan.FromDays(1)) + { + await _pushNotificationService.RegisterAsync(); + } } } - else if (DeviceInfo.Platform == DevicePlatform.Android) + catch (Exception ex) { - if (DateTime.UtcNow - lastPushRegistration > TimeSpan.FromDays(1)) - { - await _pushNotificationService.RegisterAsync(); - } + _logger.Exception(ex); + throw; } } @@ -195,14 +203,22 @@ namespace Bit.App.Pages return false; } - protected override async void OnDisappearing() + protected override void OnDisappearing() { - base.OnDisappearing(); - IsBusy = false; - _vm.StopCiphersTotpTick().FireAndForget(); - _broadcasterService.Unsubscribe(_pageName); - _vm.DisableRefreshing(); - _accountAvatar?.OnDisappearing(); + try + { + base.OnDisappearing(); + IsBusy = false; + _vm.StopCiphersTotpTick().FireAndForget(); + _broadcasterService.Unsubscribe(_pageName); + _vm.DisableRefreshing(); + _accountAvatar?.OnDisappearing(); + } + catch (Exception ex) + { + _logger.Exception(ex); + throw; + } } private async void RowSelected(object sender, SelectionChangedEventArgs e) @@ -264,45 +280,80 @@ namespace Bit.App.Pages private async void Search_Clicked(object sender, EventArgs e) { - await _accountListOverlay.HideAsync(); - if (DoOnce()) + try { - var page = new CiphersPage(_vm.Filter, _vm.MainPage ? null : _vm.PageTitle, deleted: _vm.Deleted); - await Navigation.PushModalAsync(new NavigationPage(page)); + await _accountListOverlay.HideAsync(); + if (DoOnce()) + { + var page = new CiphersPage(_vm.Filter, _vm.MainPage ? null : _vm.PageTitle, deleted: _vm.Deleted); + await Navigation.PushModalAsync(new NavigationPage(page)); + } + } + catch (Exception ex) + { + _logger.Exception(ex); } } private async void Sync_Clicked(object sender, EventArgs e) { - await _accountListOverlay.HideAsync(); - await _vm.SyncAsync(); + try + { + await _accountListOverlay.HideAsync(); + await _vm.SyncAsync(); + } + catch (Exception ex) + { + _logger.Exception(ex); + } } private async void Lock_Clicked(object sender, EventArgs e) { - await _accountListOverlay.HideAsync(); - await _vaultTimeoutService.LockAsync(true, true); + try + { + await _accountListOverlay.HideAsync(); + await _vaultTimeoutService.LockAsync(true, true); + } + catch (Exception ex) + { + _logger.Exception(ex); + } } private async void Exit_Clicked(object sender, EventArgs e) { - await _accountListOverlay.HideAsync(); - await _vm.ExitAsync(); + try + { + await _accountListOverlay.HideAsync(); + await _vm.ExitAsync(); + } + catch (Exception ex) + { + _logger.Exception(ex); + } } private async void AddButton_Clicked(object sender, EventArgs e) { - var skipAction = _accountListOverlay.IsVisible && DeviceInfo.Platform == DevicePlatform.Android; - await _accountListOverlay.HideAsync(); - if (skipAction) + try { - // Account list in the process of closing via tapping on invisible FAB, skip this attempt - return; + var skipAction = _accountListOverlay.IsVisible && DeviceInfo.Platform == DevicePlatform.Android; + await _accountListOverlay.HideAsync(); + if (skipAction) + { + // Account list in the process of closing via tapping on invisible FAB, skip this attempt + return; + } + if (!_vm.Deleted && DoOnce()) + { + var page = new CipherAddEditPage(null, _vm.Type, _vm.FolderId, _vm.CollectionId, _vm.GetVaultFilterOrgId()); + await Navigation.PushModalAsync(new NavigationPage(page)); + } } - if (!_vm.Deleted && DoOnce()) + catch (Exception ex) { - var page = new CipherAddEditPage(null, _vm.Type, _vm.FolderId, _vm.CollectionId, _vm.GetVaultFilterOrgId()); - await Navigation.PushModalAsync(new NavigationPage(page)); + _logger.Exception(ex); } } diff --git a/src/Core/Pages/Vault/GroupingsPage/GroupingsPageViewModel.cs b/src/Core/Pages/Vault/GroupingsPage/GroupingsPageViewModel.cs index 801eb261c..a249b0b35 100644 --- a/src/Core/Pages/Vault/GroupingsPage/GroupingsPageViewModel.cs +++ b/src/Core/Pages/Vault/GroupingsPage/GroupingsPageViewModel.cs @@ -166,41 +166,52 @@ namespace Bit.App.Pages { return; } - var authed = await _stateService.IsAuthenticatedAsync(); - if (!authed) - { - return; - } - if (await _vaultTimeoutService.IsLockedAsync()) - { - return; - } - if (await _stateService.GetSyncOnRefreshAsync() && Refreshing && !SyncRefreshing) - { - SyncRefreshing = true; - await _syncService.SyncPasswordlessLoginRequestsAsync(); - await _syncService.FullSyncAsync(false); - return; - } - _deviceActionService.SetScreenCaptureAllowedAsync().FireAndForget(); - - await InitVaultFilterAsync(MainPage); - if (MainPage) + try { - PageTitle = ShowVaultFilter ? AppResources.Vaults : AppResources.MyVault; + var authed = await _stateService.IsAuthenticatedAsync(); + if (!authed) + { + return; + } + if (await _vaultTimeoutService.IsLockedAsync()) + { + return; + } + if (await _stateService.GetSyncOnRefreshAsync() && Refreshing && !SyncRefreshing) + { + SyncRefreshing = true; + await _syncService.SyncPasswordlessLoginRequestsAsync(); + await _syncService.FullSyncAsync(false); + return; + } + + _deviceActionService.SetScreenCaptureAllowedAsync().FireAndForget(); + + await InitVaultFilterAsync(MainPage); + if (MainPage) + { + PageTitle = ShowVaultFilter ? AppResources.Vaults : AppResources.MyVault; + } + + _doingLoad = true; + LoadedOnce = true; + ShowNoData = false; + Loading = true; + ShowList = false; + ShowAddCipherButton = !Deleted; + + _websiteIconsEnabled = await _stateService.GetDisableFaviconAsync() != true; + } + catch (Exception ex) + { + _logger.Exception(ex); + throw; } - _doingLoad = true; - LoadedOnce = true; - ShowNoData = false; - Loading = true; - ShowList = false; - ShowAddCipherButton = !Deleted; var groupedItems = new List(); var page = Page as GroupingsPage; - _websiteIconsEnabled = await _stateService.GetDisableFaviconAsync() != true; try { await LoadDataAsync(); @@ -307,11 +318,6 @@ namespace Bit.App.Pages await MainThread.InvokeOnMainThreadAsync(() => { -#if IOS - // HACK: [PS-536] Fix to avoid blank list after back navigation on unlocking with previous page info - // because of update to XF v5.0.0.2401 - GroupedItems.Clear(); -#endif GroupedItems.ReplaceRange(items); }); } @@ -335,23 +341,22 @@ namespace Bit.App.Pages await MainThread.InvokeOnMainThreadAsync(() => { - if (groupedItems.Any()) - { -#if IOS - // HACK: [PS-536] Fix to avoid blank list after back navigation on unlocking with previous page info - // because of update to XF v5.0.0.2401 - GroupedItems.Clear(); -#endif - GroupedItems.ReplaceRange(new List { new GroupingsPageHeaderListItem(groupedItems[0].Name, groupedItems[0].ItemCount) }); - GroupedItems.AddRange(items); - } - else + if (!groupedItems.Any()) { GroupedItems.Clear(); + return; } + + GroupedItems.ReplaceRange(new List { new GroupingsPageHeaderListItem(groupedItems[0].Name, groupedItems[0].ItemCount) }); + GroupedItems.AddRange(items); }); } } + catch (Exception ex) + { + _logger.Exception(ex); + throw; + } finally { _doingLoad = false; diff --git a/src/Core/Pages/Vault/PasswordHistoryPageViewModel.cs b/src/Core/Pages/Vault/PasswordHistoryPageViewModel.cs index bfc699ba9..3ab5a182a 100644 --- a/src/Core/Pages/Vault/PasswordHistoryPageViewModel.cs +++ b/src/Core/Pages/Vault/PasswordHistoryPageViewModel.cs @@ -42,7 +42,7 @@ namespace Bit.App.Pages { var cipher = await _cipherService.GetAsync(CipherId); var decCipher = await cipher.DecryptAsync(); - Device.BeginInvokeOnMainThread(() => + MainThread.BeginInvokeOnMainThread(() => { History.ResetWithRange(decCipher.PasswordHistory ?? new List()); ShowNoData = History.Count == 0; diff --git a/src/Core/Resources/Localization/AppResources.az.resx b/src/Core/Resources/Localization/AppResources.az.resx index 1aa8777fb..a30511650 100644 --- a/src/Core/Resources/Localization/AppResources.az.resx +++ b/src/Core/Resources/Localization/AppResources.az.resx @@ -784,13 +784,13 @@ Avto-doldurmaq və ya bu elementə baxmaq istəyirsiniz? - Bu elementi avto-doldurmaq istədiyinizə əminsiniz? "{0}" ilə tam uyğun gəlmir. + Bu elementi avto-doldurmaq istədiyinizə əminsiniz? "{0}" ilə tam uyuşmur. - Uyğun gələnlər + Uyuşan elementlər - Uyğun gələ bilənlər + Uyuşması mümkün olan elementlər Axtar @@ -1246,10 +1246,10 @@ Skan prosesi avtomatik baş tutacaq. Başlayır - URI uyğunluq aşkarlaması + URI uyuşma aşkarlaması - Uyğunluq aşkarlaması + Uyuşmanı aşkarlama URI match detection for auto-fill. @@ -1530,11 +1530,11 @@ Skan prosesi avtomatik baş tutacaq. Clipboard is the operating system thing where you copy/paste data to on your device. - İlkin URI uyğunluq aşkarlaması + İlkin URI uyuşma aşkarlaması Default URI match detection for auto-fill. - Avto-doldurma kimi əməliyyatları icra edərkən giriş etmə prosesi üçün URI uyğunluq aşkarlamasının ilkin yolunu seçin. + Avto-doldurma kimi əməliyyatları icra edərkən giriş etmə prosesi üçün URI uyuşma aşkarlamasının idarə edliəcəyi ilkin yolu seçin. Tema @@ -2464,7 +2464,7 @@ Skan prosesi avtomatik baş tutacaq. Əlçatımlılıq Xidməti açıqlaması - Bitwarden, tətbiqlərdə və veb saytlarda giriş sahələrini axtarmaq üçün Əlçatımlılıq Xidmətini istifadə edir, daha sonra tətbiq və ya sayt üçün uyğunluq aşkar etdikdə istifadəçi adı və parolun daxil edilməsi üçün müvafiq sahə kimliklərini yaradır. Xidmət tərəfindən bizə təqdim edilən məlumatların heç birini saxlamırıq, kimlik məlumatlarının daxil edilməsindən kənar ekrandakı hər hansısa elementə nəzarət etməyə cəhd etmirik. + Bitwarden, tətbiqlərdə və veb saytlarda giriş sahələrini axtarmaq üçün Əlçatımlılıq Xidmətini istifadə edir, daha sonra tətbiq və ya sayt üçün uyuşma tapdıqda istifadəçi adı və parolun daxil edilməsi üçün müvafiq sahə kimliklərini yaradır. Xidmət tərəfindən bizə təqdim edilən məlumatların heç birini saxlamırıq, kimlik məlumatlarının daxil edilməsindən kənar ekrandakı hər hansısa elementə nəzarət etməyə cəhd etmirik. Qəbul et @@ -2505,7 +2505,7 @@ Bu hesaba keçmək istəyirsiniz? Cihazınıza bir bildiriş göndərildi. - Lütfən anbarınızın kilidinin açıq olduğuna və Barmaq izi ifadəsinin digər cihazda uyğun gəldiyinə əmin olun. + Lütfən anbarınızın kilidinin açıq olduğuna və Barmaq izi ifadəsinin digər cihazla uyuşduğuna əmin olun. Bildirişi təkrar göndər @@ -2592,13 +2592,13 @@ Bu hesaba keçmək istəyirsiniz? Açarı, mövcud və ya yeni bir elementə əlavə edin - Anbarınızda {0} ilə uyğunlaşan heç bir element yoxdur + Anbarınızda {0} ilə uyuşan heç bir element yoxdur Bir element axtarın və ya yenisini əlavə edin - Axtarışa uyğun gələn heç bir element yoxdur + Axtarışla uyuşan heç bir element yoxdur ABŞ diff --git a/src/Core/Resources/Localization/AppResources.fi.resx b/src/Core/Resources/Localization/AppResources.fi.resx index fb90ef63c..cee8da7bd 100644 --- a/src/Core/Resources/Localization/AppResources.fi.resx +++ b/src/Core/Resources/Localization/AppResources.fi.resx @@ -878,17 +878,17 @@ The placeholder will show the file size of the attachment. Ex "25 MB" - Todennusmenetelmän avain (TOTP) + Todennusavain (TOTP) Todennuskoodi (TOTP) Totp code label - Todennusmenetelmän avain lisätty. + Todennusavain on lisätty. - Todennusavaimen luku epäonnistui. + Todennusavaimen lukeminen ei onnistu. Kohdista kamera QR-koodiin. @@ -907,7 +907,7 @@ Koodi skannataan automaattisesti. Kopioi TOTP-todennuskoodi - Jos kirjautumistieto sisältää kaksivaiheisen TOTP-todennusavaimen, kopioidaan todennuskoodi automaattisesti leikepöydälle automaattisen täytön yhteydessä. + Jos kirjautumistieto sisältää kaksivaiheisen todennuksen avaimen, kopioidaan TOTP-todennuskoodi leikepöydälle kohteen automaattisen täytön yhteydessä. TOTP-koodin kopiointi @@ -1853,7 +1853,7 @@ Koodi skannataan automaattisesti. Jos käytössä, esteettömyyspalvelu näyttää pikavalintapalkin laajentaakseen automaattisen täytön palvelun toiminnan kattamaan myös vanhemmat sovellukset, jotka eivät tue Android Autofill Framework -rajapintaa. - Yrityskäytännön johdosta kohteiden tallennus henkilökohtaiseen holviin ei ole mahdollista. Muuta omistusasetus organisaatiolle ja valitse käytettävissä olevista kokoelmista. + Yrityskäytännön vuoksi kohteiden tallennus henkilökohtaiseen holviin ei ole mahdollista. Muuta omistusasetus organisaatiolle ja valitse käytettävissä olevista kokoelmista. Organisaatiokäytäntö vaikuttaa omistajuusvalintoihisi. @@ -2126,7 +2126,7 @@ Koodi skannataan automaattisesti. Varmista, että oletusselaimesi sisältää WebAuthn-tuen ja yritä uudelleen. - Organisaatiolla on käytäntö, joka liittää tilisi automaattisesti salasanan palautusapuun. Liitos sallii organisaation ylläpitäjien vaihtaa pääsalasanasi. + Organisaatiolla on yrityskäytäntö, joka liittää tilisi automaattisesti salasanan palautusapuun. Liitos sallii organisaation ylläpitäjien vaihtaa pääsalasanasi. Organisaatiokäytännöt ovat määrittäneet holvisi aikakatkaisun enimmäisajaksi {0} tunti(a) {1} minuutti(a). @@ -2273,7 +2273,7 @@ Koodi skannataan automaattisesti. Premium-tilaus vaaditaan - Etkö voi lisätä todennusavainta? + Eikä todennusavaimen lisääminen onnistu? Skannaa QR-koodi @@ -2282,7 +2282,7 @@ Koodi skannataan automaattisesti. Eikö QR-koodin skannaus onnistu? - Todentajan avain + Todennusavain Syötä se manuaalisesti diff --git a/src/Core/Resources/Localization/AppResources.hi.resx b/src/Core/Resources/Localization/AppResources.hi.resx index c05c99a84..977063eae 100644 --- a/src/Core/Resources/Localization/AppResources.hi.resx +++ b/src/Core/Resources/Localization/AppResources.hi.resx @@ -385,10 +385,10 @@ मास्टर पासवर्ड दें - पिन दें + पिन वेरिफिकेशन करें - संस्करण + वर्ज़न देखें @@ -556,7 +556,7 @@ लॉगआउट करने के बाद तिजोरी में जाना मुमकिन नहीं होगा और टाइमआउट के बाद ऑनलाइन ऑथेंटिकेशन की ज़रूरत होगी। इस सेटिंग का इस्तेमाल करें? - लॉगइन कर रहे है... + लॉगइन कर रहे... Message shown when interacting with the server @@ -894,13 +894,13 @@ कैमरा क्यूआर कोड के तरफ करें। स्कैन अपनेआप होगा। - क्यूआर कोड को स्कैन करें + क्यूआर कोड स्कैन करें कैमरा - फोटों + फोटो टीओटीपी कॉपी करें @@ -1188,7 +1188,7 @@ फेस आईडी वेरिफाइ करें - विंडोज़ हैल्लो + विंडोज़ हैलो हम एंड्रॉइड ऑटोफिल सेटिंग अपनेआप नहीं खोल पा रहे। ऑटोफिल सेटिंग में जाने के लिए एंड्रॉइड सेटिंग > सिस्टम > भाषा और इंपुट > एडवांस > ऑटोफिल सर्विस पर जाएं। @@ -1248,24 +1248,24 @@ युआरआई मैच डिटेक्शन - Match detection + मैच डिटेक्शन URI match detection for auto-fill. - Yes, and save + हां, और सेव करें Auto-fill and save - संगठन + ग्रुप An entity of multiple related people (ex. a team or business organization). Hold your Yubikey near the top of the device. - पुनः कोशिश करें + वापस कोशिश करें To continue, hold your YubiKey NEO against the back of the device. @@ -1274,7 +1274,7 @@ The accessibility service may be helpful to use when apps do not support the standard auto-fill service. - Password updated + पासवर्ड अपडेट किया गया ex. Date this password was updated @@ -1297,49 +1297,49 @@ Access your vault directly from your keyboard to quickly autofill passwords. - To set up password auto-fill on your device, follow these instructions: + अपने डिवाइस पर पासवर्ड ऑटो-फिल सेट करने के लिए इन स्टेप को फॉलो करें: - 1. Go to the iOS "Settings" app + 1. आईओएस के "सेटिंग" ऐप में जाएं - 2. Tap "Passwords" + 2. "पासवर्ड" पर टैप करें - 3. Tap "AutoFill Passwords" + 3. "पासवर्ड ऑटोफिल करें" पर टैप करें - 4. Turn on AutoFill + 4. ऑटोफिल ऑन करें - 5. Select "Bitwarden" + 5. "बिटवार्डन" चुनें - Password auto-fill + पासवर्ड ऑटो-फिल The easiest way to add new logins to your vault is by using the Bitwarden Password AutoFill extension. Learn more about using the Bitwarden Password AutoFill extension by navigating to the "Settings" screen. - Invalid email address. + गलत ईमेल पता। - पत्ते + कार्ड - पहचान + आईडी - लॉग इन + लॉगइन - सुरक्षित नोट + सेक्योर नोट - सभी आइटम + सारे आइटम - URIs + यूआरआई Plural form of a URI @@ -1356,16 +1356,16 @@ This password was not found in any known data breaches. It should be safe to use. - Identity name + आईडी का नाम - मूल्य + वैल्यू पासवर्ड इतिहास - प्रकार + टाइप No passwords to list. @@ -1383,32 +1383,32 @@ Search text Sends - Search {0} + {0} सर्च करें ex: Search Logins - प्रकार + टाइप - नीचे ले जाएँ + नीचे ले जाएं - ऊपर ले जाएँ + ऊपर ले जाएं - विविध + बाकी - Ownership + मालिकी - Who owns this item? + इस आइटम का मालिक कौन है? There are no collections to list. - {0} moved to {1}. + {0} {1} पर ट्रांस्फर किया गया। ex: Item moved to Organization. @@ -1421,7 +1421,7 @@ शेयर करें - Share Item + आइटम शेयर करें Move to Organization @@ -1433,27 +1433,27 @@ Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved. - Number of words + टोटल शब्द - Passphrase + पासफ्रेज़ - Word separator + वर्ड सेपरेटर - स्पष्ट + साफ करें To clear something out. example: To clear browser history. - Generator + जेनरेटर Short for "Password Generator" There are no folders to list. - Fingerprint phrase + फिंगरप्रिंट फ्रेज़ 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. @@ -1464,22 +1464,22 @@ Bitwarden allows you to share your vault items with others by using an organization account. Would you like to visit the bitwarden.com website to learn more? - निर्यात तिजोरी + तिजोरी एक्सपोर्ट करें - अब ताला + अभी लॉक करें पिन - अनलॉक + खोलें - Unlock vault + तिजोरी खोलें - 30 मिनिट + 30 मिनट Set your PIN code for unlocking Bitwarden. Your PIN settings will be reset if you ever fully log out of the application. @@ -1498,7 +1498,7 @@ Your vault is locked. Verify your identity to continue. - अँधेरा + अंधेरा A dark color @@ -1515,13 +1515,13 @@ 30 सेकंड - 30 सेकंड + 20 सेकंड 2 मिनट - क्लिपबोर्ड साझा करें + क्लिपबोर्ड साफ करें Clipboard is the operating system thing where you copy/paste data to on your device. @@ -1540,25 +1540,25 @@ Color theme - Change the application's color theme. + ऐप का थीम बदलें। - Default (System) + डिफॉल्ट (सिस्टम) - Default dark theme + डिफॉल्ट डार्क थीम नोट कॉपी करें - निकास + निकलें - Are you sure you want to exit Bitwarden? + पक्का निकलें? - एप्लीकेशन पुनर्प्रारंभ करते समय मास्टर पासवर्ड पूछे? + ऐप रीस्टार्ट करने पर मास्टर पासवर्ड पूछें? काला @@ -1569,7 +1569,7 @@ 'Nord' is the name of a specific color scheme. It should not be translated. - Solarized Dark + सोलराइज़्ड डार्क 'Solarized Dark' is the name of a specific color scheme. It should not be translated. @@ -1582,7 +1582,7 @@ Ask to add an item if one isn't found in your vault. - On app restart + ऐप रिस्टार्ट पर Auto-fill makes it easy to securely access your Bitwarden vault from other websites and apps. It looks like you have not set up an auto-fill service for Bitwarden. Set up auto-fill for Bitwarden from the "Settings" screen. @@ -1598,10 +1598,10 @@ नंबर शामिल करें - डाउन्लोड + डाउनलोड करें - साझा किया गया + शेयर किया गया दृश्यता बदलें @@ -1613,7 +1613,7 @@ बायोमेट्रिक सत्यापन - बॉयोमेट्रिक्स + बायोमेट्रिक Use biometrics to unlock @@ -1625,7 +1625,7 @@ 3. On the Android App Settings screen for Bitwarden, go to the "Display over other apps" options (under Advanced) and tap the toggle to allow overlay support. - अनुमति + परमिशन Open Overlay Permission Settings @@ -1634,13 +1634,13 @@ 3. On the Android App Settings screen for Bitwarden, select "Display over other apps" (under "Advanced") and switch on the toggle to allow the overlay. - अस्वीकृत + मना किया गया - प्रदान की गई + दिया गया - फाइल प्रारुप + फाइल फॉर्मेट अपने कोष्ठ डेटा निर्यात करने के लिए अपना मास्टर पासवर्ड दर्ज करें। @@ -1649,7 +1649,7 @@ Send a verification code to your email - Code sent! + कोड भेजा गया! Confirm your identity to continue. @@ -1668,7 +1668,7 @@ Title for the alert to confirm vault exports. - चेतावनी + खबरदार There was a problem exporting your vault. If the problem persists, you'll need to export from the web vault. @@ -1677,14 +1677,14 @@ Vault exported successfully - क्लोन + क्लोन बनाएं Clone an entity (verb). One or more organization policies are affecting your generator settings - खुला + खोलें Button text for an open operation (verb). @@ -1704,27 +1704,27 @@ Message shown when interacting with the server - Item has been sent to trash. + आइटम कचरे में डाला गया। Confirmation message after successfully soft-deleting a login - पुनः वापस लायें + रिस्टोर करें Restores an entity (verb). - Restoring... + रिस्टोर कर रहे... Message shown when interacting with the server - Item restored + आइटम रिस्टोर किया गया Confirmation message after successfully restoring a soft-deleted item - ट्रैश + कचरा (noun) Location of deleted items which have not yet been permanently deleted - Search trash + कचरा सर्च करें (action prompt) Label for the search text field when viewing the trash folder @@ -1732,27 +1732,27 @@ Confirmation alert message when permanently deleteing a cipher. - Do you really want to restore this item? + ये आइटम रिस्टोर करें? Confirmation alert message when restoring a soft-deleted cipher. - Do you really want to send to the trash? + कचरे में डालें? Confirmation alert message when soft-deleting a cipher. - Biometric unlock for this account is disabled pending verification of master password. + मास्टर पासवर्ड का वेरिफिकेशन खत्म ना होने तक इस अकाउंट के लिए बायोमेट्रिक बंद है। - Autofill biometric unlock for this account is disabled pending verification of master password. + मास्टर पासवर्ड का वेरिफिकेशन खत्म ना होने तक इस अकाउंट के लिए बायोमेट्रिक ऑटोफिल बंद है। - Allow sync on refresh + रिफ्रेश पर सिंक करने दें Syncing vault with pull down gesture. - Enterprise single sign-on + बिज़नेस सिंगल साइन-ऑन Quickly log in using your organization's single sign-on portal. Please enter your organization's identifier to begin. @@ -1764,7 +1764,7 @@ Currently unable to login with SSO - Set master password + मास्टर पासवर्ड सेट करें In order to complete logging in with SSO, please set a master password to access and protect your vault. @@ -1776,7 +1776,7 @@ Minimum complexity score of {0} - Minimum length of {0} + कम-से-कम लंबाई {0} Contain one or more uppercase characters @@ -1797,20 +1797,20 @@ Password does not meet organization requirements. Please check the policy information and try again. - लोड रहा है... + लोड हो रहा है By activating this switch you agree to the following: - Terms of Service and Privacy Policy have not been acknowledged. + सेवा की शर्ते और प्राइवसी पॉलिसी माने नहीं गए हैं। - Terms of Service + सेवा की शर्ते - Privacy Policy + प्राइवसी पॉलिसी Bitwarden needs attention - Turn on "Draw-Over" in "Auto-fill Services" from Bitwarden Settings @@ -1840,7 +1840,7 @@ Required to use the Autofill Quick-Action Tile, or to augment the Autofill Service by using Draw-Over (if turned on). - Use draw-over + ड्रॉ-ओवर इस्तेमाल करें Allows the Bitwarden Accessibility Service to display a popup when login fields are selected. @@ -1862,11 +1862,11 @@ 'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated. - All Sends + सारे सेंड 'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated. - सेंड्स + सेंड 'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated. @@ -1905,10 +1905,10 @@ Text type is not selected, tap to select. - Deletion date + हटाने की तारीख - Deletion time + हटाने का टाइम The Send will be permanently deleted on the specified date and time. @@ -1918,7 +1918,7 @@ Pending deletion - Expiration date + एक्सपायरी डेट Expiration time @@ -1928,7 +1928,7 @@ 'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated. - Expired + एक्सपायर हो गया Maximum access count @@ -1944,14 +1944,14 @@ Current access count - New password + नया पासवर्ड Optionally require a password for users to access this Send. 'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated. - Remove password + पासवर्ड हटाएं Are you sure you want to remove the password? @@ -1975,29 +1975,29 @@ 'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated. - Add a Send + सेंड डालें 'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated. - Copy link + लिंक कॉपी करें - Share link + लिंक शेयर करें - Send link + लिंक सेंड करें 'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated. - Search Sends + सेंड सर्च करें 'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated. - Edit Send + सेंड बदलें 'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated. - New Send + नया सेंड 'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated. @@ -2005,15 +2005,15 @@ 'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated. - Send deleted + सेंड हटाया गया 'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated. - Send saved + सेंड सेव किया गया 'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated. - Send created + सेंड बनाया गया 'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated. @@ -2043,7 +2043,7 @@ 'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated. - About Send + सेंड के बारे में 'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated. @@ -2071,7 +2071,7 @@ This action is protected, to continue please re-enter your master password to verify your identity. - Captcha required + कैप्चा चाहिए Captcha failed. Please try again. @@ -2104,10 +2104,10 @@ Leave organization - Leave {0}? + {0} छोड़ें? - FIDO2 WebAuthn + एफआईडीओ2 वेब ऑथेंटिकेशन To continue, have your FIDO2 WebAuthn compatible security key ready, then follow the instructions after clicking 'Authenticate WebAuthn' on the next screen. @@ -2119,7 +2119,7 @@ Authenticate WebAuthn - Return to app + ऐप पर वापस जाएं Please make sure your default browser supports WebAuthn and try again. @@ -2143,22 +2143,22 @@ One or more organization policies prevents your from exporting your individual vault. - Add account + अकाउंट डालें - Unlocked + खुला हुआ बंद - Logged out + लॉगआउट हो गए Switched to next available account - Account locked + अकाउंट लॉक हुआ Account logged out successfully @@ -2167,7 +2167,7 @@ Account removed successfully - Delete account + अकाउंट डिलीट करें Deleting your account is permanent @@ -2188,7 +2188,7 @@ Request one-time password - Send code + कोड भेजें भेज रहे @@ -2197,13 +2197,13 @@ Copy Send link on save - Sending code + कोड भेज रहे - Verifying + वेरिफिकेशन चल रहा - Resend code + कोड वापस भेजें A verification code was sent to your email @@ -2215,7 +2215,7 @@ Enter the verification code that was sent to your email - Submit crash logs + क्रैश लॉग भेजें Help Bitwarden improve app stability by submitting crash reports. @@ -2233,13 +2233,13 @@ Lowercase (A to Z) - Numbers (0 to 9) + नंबर (0 से 9) - Special characters (!@#$%^&*) + खास कैरक्टर (!@#$%^&*) - Tap to go back + वापस जाने के लिए टैप करें Password is visible, tap to hide. @@ -2251,16 +2251,16 @@ Filter items by vault - All vaults + सारे तिजोरी तिजोरी - Vault: {0} + तिजोरी: {0} - सब + सारे टीओटीपी @@ -2275,10 +2275,10 @@ Cannot add authenticator key? - Scan QR Code + क्यूआर कोड स्कैन करें - Cannot scan QR Code? + क्यूआर कोड स्कैन नहीं हो रहा? Authenticator key @@ -2287,10 +2287,10 @@ Enter key manually - Add TOTP + टीओटीपी जोड़ें - Set up TOTP + टीओटीपी सेट करें Once the key is successfully entered, @@ -2306,7 +2306,7 @@ select Add TOTP to store the key safely We were unable to process your request. Please try again or contact us. - Allow screen capture + स्क्रीनशॉट लेने दें Are you sure you want to turn on screen capture? @@ -2321,25 +2321,25 @@ select Add TOTP to store the key safely Login attempt by {0} on {1} - Device type + डिवाइस टाइप - IP address + आईपी पता - समय + टाइम - पास + लोकेशन: - Confirm login + लॉगइन कंफर्म करें - Deny login + लॉगइन ना करने दें - Just now + अभी-अभी {0} minutes ago @@ -2348,7 +2348,7 @@ select Add TOTP to store the key safely Login confirmed - Login denied + लॉगइन करने से रोका गया लॉगइन मांग माने @@ -2363,7 +2363,7 @@ select Add TOTP to store the key safely नए लॉगइन मांग के लिए पुश सूचना लें - ना, शुक्रिया + ना, रहने दें {0} के लिए लॉगइन कोशिश पक्का करें @@ -2372,13 +2372,13 @@ select Add TOTP to store the key safely सारे सूचनाएं - पासवर्ड प्रकार + पासवर्ड टाइप क्या बनाएं? - यूज़रनाम प्रकार + यूज़रनेम टाइप प्लस पता किया गया ईमेल @@ -2390,7 +2390,7 @@ select Add TOTP to store the key safely ईमेल नकलीनाम फॉरवर्ड किया गया - बेतरतीब शब्द + रैंडम शब्द ईमेल (ज़रूरी) @@ -2402,7 +2402,7 @@ select Add TOTP to store the key safely एपीआई चाबी (ज़रूरी) - सेवा + सर्विस addy.io @@ -2425,7 +2425,7 @@ select Add TOTP to store the key safely "Fastmail" is the product name and should not be translated. - ForwardEmail + फॉरवर्डईमेल "ForwardEmail" is the product name and should not be translated. @@ -2456,7 +2456,7 @@ select Add TOTP to store the key safely बाहरी फॉरवर्ड सेवा से ईमेल नकलीनाम बनाएं। - बेतरतीब + रैंडम घड़ी से जुड़े @@ -2471,7 +2471,7 @@ select Add TOTP to store the key safely मानें - नकारें + मना करें Login request has already expired. @@ -2482,7 +2482,7 @@ select Add TOTP to store the key safely Do you want to switch to this account? - New around here? + यहां पर नए हैं? Get master password hint @@ -2491,7 +2491,7 @@ Do you want to switch to this account? Logging in as {0} on {1} - Not you? + वो आप नहीं थे? Log in with master password @@ -2602,16 +2602,16 @@ Do you want to switch to this account? कोई भी चीज़ खोज शब्द से मेल नहीं खाता - अमेरिकी संयुक्त राज्य + यूएस - यूरोपीय संघ + ईयू - खुद-होस्ट + सेल्फ-होस्ट - डाटा इलाका + डाटा लोकेशन इलाका @@ -2623,7 +2623,7 @@ Do you want to switch to this account? चालू मुख्य पासवर्ड - Logged in! + लॉगइन हो गए! Approve with my other device @@ -2638,16 +2638,16 @@ Do you want to switch to this account? Turn off using a public device - Remember this device + इस डिवाइस को याद रखें - Passkey + पासकी - Passkeys + पासकी - Application + ऐप You cannot edit passkey application because it would invalidate the passkey @@ -2671,10 +2671,10 @@ Do you want to switch to this account? Unlocking may fail due to insufficient memory. Decrease your KDF memory settings or set up biometric unlock to resolve. - Invalid API key + गलत एपीआई चाबी - Invalid API token + गलत एपीआई टोकन Admin approval requested @@ -2704,29 +2704,29 @@ Do you want to switch to this account? New blocked URI - URI saved + यूआरआई सेव किया Invalid format. Use https://, http://, or androidapp:// https://, http://, androidapp:// should not be translated - Edit URI + यूआरआई बदलें - Enter URI + यूआरआई डालें Format: {0}. Separate multiple URIs with a comma. - Format: {0} + फॉर्मेट: {0} - Invalid URI + गलत यूआरआई - URI removed + यूआरआई हटाया गया There are no blocked URIs @@ -2738,7 +2738,7 @@ Do you want to switch to this account? Cannot edit multiple URIs at once - Login approved + लॉगइन का परमिशन मिला Log in with device must be set up in the settings of the Bitwarden app. Need another option? @@ -2747,19 +2747,19 @@ Do you want to switch to this account? Log in with device - Logging in on + यहां लॉगइन कर रहे - Vault + तिजोरी - Appearance + दिखावट Account security - Bitwarden Help Center + बिटवार्डन हेल्प सेंटर Contact Bitwarden support @@ -2768,10 +2768,10 @@ Do you want to switch to this account? Copy app information - Sync now + अभी सिंक करें - Unlock options + खोलने के तरीके Session timeout @@ -2784,19 +2784,19 @@ Do you want to switch to this account? 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. - One hour and one minute + एक घंटा और एक मिनट - One hour and {0} minutes + एक घंटा और {0} मिनट - {0} hours and one minute + {0} घंटे और एक मिनट - {0} hours and {1} minutes + {0} घंटे और {1} मिनट - {0} hours + {0} घंटे The Android Autofill Framework is used to assist in filling login information into other apps on your device. @@ -2808,10 +2808,10 @@ Do you want to switch to this account? Additional options - Continue to web app? + वेब ऐप पर जाएं? - Continue to {0}? + {0} पर जाएं? The parameter is an URL, like bitwarden.com. @@ -2824,17 +2824,17 @@ Do you want to switch to this account? Continue to app store? - Make your account more secure by setting up two-step login in the Bitwarden web app. + बिटवार्डन वेब ऐप में टू-स्टेप लॉगइन सेट करके अपने अकाउंट को ज़्यादा सेक्योर बनाएं। - You can change your master password on the Bitwarden web app. + बिटवार्डन वेब ऐप में अपना मास्टर पासवर्ड आसानी से बदलें। - You can import data to your vault on {0}. + {0} पर अपने तिजोरी में आसानी से डाटा इंपोर्ट करें। The parameter is an URL, like vault.bitwarden.com. - Learn more about how to use Bitwarden on the Help center. + बिटवार्डन को बेहतर तरीके से इस्तेमाल करने के लिए हमारे हेल्प सेंटर पर जाएं। Can’t find what you are looking for? Reach out to Bitwarden support on bitwarden.com. @@ -2852,7 +2852,7 @@ Do you want to switch to this account? Choose the dark theme to use when your device’s dark mode is in use - Created {0}, {1} + {0}, {1} पर बनाया गया 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. diff --git a/src/Core/Resources/Localization/AppResources.pt-PT.resx b/src/Core/Resources/Localization/AppResources.pt-PT.resx index bcd1c77cb..e853eb399 100644 --- a/src/Core/Resources/Localization/AppResources.pt-PT.resx +++ b/src/Core/Resources/Localization/AppResources.pt-PT.resx @@ -885,7 +885,7 @@ Totp code label - Chave de autenticador adicionada. + Chave de autenticação adicionada. Não é possível ler a chave de autenticação. diff --git a/src/Core/Resources/Localization/AppResources.ru.resx b/src/Core/Resources/Localization/AppResources.ru.resx index 1ccd10664..6a3822249 100644 --- a/src/Core/Resources/Localization/AppResources.ru.resx +++ b/src/Core/Resources/Localization/AppResources.ru.resx @@ -885,10 +885,10 @@ Totp code label - Ключ проверки подлинности добавлен. + Ключ аутентификатора добавлен. - Не удается прочитать ключ проверки подлинности. + Не удается прочитать ключ аутентификатора. Наведите камеру на QR-код. @@ -2272,7 +2272,7 @@ Требуется подписка Премиум - Не удается добавить ключ проверки подлинности? + Не удается добавить ключ аутентификатора? Сканировать QR-код diff --git a/src/Core/Resources/Localization/AppResources.ta.resx b/src/Core/Resources/Localization/AppResources.ta.resx index 8196a8bd8..aac414db1 100644 --- a/src/Core/Resources/Localization/AppResources.ta.resx +++ b/src/Core/Resources/Localization/AppResources.ta.resx @@ -858,7 +858,7 @@ "YubiKey" is the product name and should not be translated. - புதிய இணைப்பை சேர் + புதிய இணைப்பைச் சேர் இணைப்புகள் @@ -2331,7 +2331,7 @@ நேரம் - Near + இதற்கருகில் உள்நுழைவை உறுதிபடுத்து @@ -2772,7 +2772,7 @@ இப்போது ஒத்திசை - Unlock options + பூட்டவிழ்ப்பு விருப்பங்கள் அமர்வு நேரமுடிவு @@ -2785,16 +2785,16 @@ 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. - One hour and one minute + ஒரு மணிநேரம் மற்றும் ஒரு நிமிடம் - One hour and {0} minutes + ஒரு மணிநேரம் மற்றும் {0} நிமிடங்கள் - {0} hours and one minute + {0} மணிநேரம் மற்றும் ஒரு நிமிடம் - {0} hours and {1} minutes + {0} மணிநேரம் மற்றும் {1} நிமிடங்கள் {0} மணிநேரம் @@ -2809,29 +2809,29 @@ கூடுதல் தேர்வுகள் - Continue to web app? + வலைச்செயலிக்குத் தொடரவா? - Continue to {0}? + {0}-க்குத் தொடரவா? The parameter is an URL, like bitwarden.com. - Continue to Help center? + உதவி மையத்திற்குத் தொடரவா? - Continue to contact support? + ஆதரவைத் தொடர்புகொள்ளத் தொடரவா? Continue to app store? - Make your account more secure by setting up two-step login in the Bitwarden web app. + Bitwarden வலைச்செயலியில் இரு-படி உள்நுழைவை அமைத்து உமது கணக்கின் பாதுகாப்பை அதிகரி. - You can change your master password on the Bitwarden web app. + Bitwarden வலைச்செயலியில் உமது பிரதான கடவுச்சொல்லை மாற்றலாம். - You can import data to your vault on {0}. + {0}-இல் உமது பெட்டகத்திற்குத் தரவை இறக்குமதி செய்யலாம். The parameter is an URL, like vault.bitwarden.com. diff --git a/src/Core/Resources/Localization/AppResources.uk.resx b/src/Core/Resources/Localization/AppResources.uk.resx index 9467ea138..ede3e1741 100644 --- a/src/Core/Resources/Localization/AppResources.uk.resx +++ b/src/Core/Resources/Localization/AppResources.uk.resx @@ -553,7 +553,7 @@ Дія після часу очікування сховища - Вихід скасує всі права доступу до вашого сховища і вимагатиме авторизації після завершення часу очікування. Ви дійсно хочете використати цей параметр? + Вихід скасує всі права доступу до вашого сховища і вимагатиме автентифікацію після завершення часу очікування. Ви дійсно хочете використати цей параметр? Вхід... @@ -721,7 +721,7 @@ Веб сховище Bitwarden - Втратили доступ до програми перевірки? + Втратили доступ до програми автентифікації? Записи @@ -806,11 +806,11 @@ Message shown when trying to launch an app that does not exist on the user's device. - Програма авторизації + Програма автентифікації For 2FA - Введіть 6-значний код підтвердження з програми авторизації. + Введіть 6-значний код підтвердження з програми автентифікації. For 2FA @@ -822,7 +822,7 @@ For 2FA whenever there are no available providers on this device. - Цей обліковий запис має увімкнену двоетапну перевірку, однак, жоден із налаштованих провайдерів не підтримується на цьому пристрої. Будь ласка, скористайтеся підтримуваним пристроєм або додайте інших провайдерів, які мають кращу підтримку різних пристроїв (наприклад, програму авторизації). + Цей обліковий запис має увімкнену двоетапну перевірку, однак жоден із налаштованих провайдерів не підтримується на цьому пристрої. Будь ласка, скористайтеся підтримуваним пристроєм або додайте інших провайдерів, які мають кращу підтримку різних пристроїв (наприклад, програму автентифікації). Код відновлення @@ -878,17 +878,17 @@ The placeholder will show the file size of the attachment. Ex "25 MB" - Ключ авторизації (TOTP) + Ключ автентифікації (TOTP) Код підтвердження (TOTP) Totp code label - Ключ авторизації додано. + Ключ автентифікації додано. - Не вдається прочитати ключ авторизації. + Не вдається прочитати ключ автентифікації. Наведіть свою камеру на QR-код. @@ -907,7 +907,7 @@ Копіювати TOTP - Якщо запис має ключ авторизації, копіювати код підтвердження TOTP до буфера обміну під час автозаповнення. + Якщо запис має ключ автентифікації, копіювати код підтвердження TOTP до буфера обміну під час автозаповнення. Автоматично копіювати коди TOTP @@ -2110,13 +2110,13 @@ FIDO2 WebAuthn - Щоб продовжити, приготуйте свій увімкнений ключ безпеки FIDO2 WebAuthn, потім дотримуйтесь настанов після натискання "Авторизація WebAuthn" на наступному екрані. + Щоб продовжити, приготуйте свій ключ безпеки FIDO2 WebAuthn, потім дотримуйтесь настанов після натискання "Автентифікація WebAuthn" на наступному екрані. - Авторизація з використанням FIDO2 WebAuthn. Ви можете авторизуватися за допомогою зовнішнього ключа безпеки. + Автентифікація з використанням FIDO2 WebAuthn. Ви можете пройти автентифікацію за допомогою зовнішнього ключа безпеки. - Авторизація WebAuthn + Автентифікація WebAuthn Повернутися до програми @@ -2272,7 +2272,7 @@ Необхідна передплата преміум - Не вдається додати ключ авторизації? + Не вдається додати ключ автентифікації? Сканувати QR-код @@ -2281,7 +2281,7 @@ Не вдається сканувати QR-код? - Ключ авторизації + Ключ автентифікації Введіть ключ вручну diff --git a/src/Core/Resources/Localization/AppResources.zh-Hans.resx b/src/Core/Resources/Localization/AppResources.zh-Hans.resx index 00b6e76c4..0fa4bbbf9 100644 --- a/src/Core/Resources/Localization/AppResources.zh-Hans.resx +++ b/src/Core/Resources/Localization/AppResources.zh-Hans.resx @@ -885,17 +885,17 @@ Totp code label - 验证器密钥已添加。 + 已添加验证器密钥。 无法读取验证器密钥。 - 将您的摄像头对准 QR 码。 + 将您的摄像头对准二维码。 扫描将自动完成。 - 扫描 QR 码 + 扫描二维码 相机 @@ -2275,10 +2275,10 @@ 无法添加验证器密钥? - 扫描 QR 码 + 扫描二维码 - 无法扫描 QR 码吗? + 无法扫描二维码吗? 验证器密钥 diff --git a/src/Core/Services/ApiService.cs b/src/Core/Services/ApiService.cs index 54434168c..e1240ff23 100644 --- a/src/Core/Services/ApiService.cs +++ b/src/Core/Services/ApiService.cs @@ -631,7 +631,7 @@ namespace Bit.Core.Services public async Task PreValidateSsoAsync(string identifier) { - var path = "/account/prevalidate?domainHint=" + WebUtility.UrlEncode(identifier); + var path = "/sso/prevalidate?domainHint=" + WebUtility.UrlEncode(identifier); using (var requestMessage = new HttpRequestMessage()) { requestMessage.Version = new Version(1, 0); diff --git a/src/iOS.Autofill/CredentialProviderViewController.TapGestureHack.cs b/src/iOS.Autofill/CredentialProviderViewController.TapGestureHack.cs deleted file mode 100644 index b1330ce8d..000000000 --- a/src/iOS.Autofill/CredentialProviderViewController.TapGestureHack.cs +++ /dev/null @@ -1,51 +0,0 @@ -#if ENABLED_TAP_GESTURE_RECOGNIZER_MAUI_EMBEDDED_WORKAROUND - -using System; -using AuthenticationServices; -using Bit.App.Abstractions; -using Bit.Core.Utilities; -using Bit.iOS.Autofill.Models; -using Bit.iOS.Core.Utilities; -using Microsoft.Maui.Controls; -using Microsoft.Maui.Platform; -using UIKit; - -namespace Bit.iOS.Autofill -{ - public partial class CredentialProviderViewController : ASCredentialProviderViewController, IAccountsManagerHost - { - const string STORYBOARD_NAME = "MainInterface"; - Lazy _storyboard = new Lazy(() => UIStoryboard.FromName(STORYBOARD_NAME, null)); - - public void InitWithContext(Context context) - { - _context = context; - } - - public void DismissLockAndContinue() - { - if (UIApplication.SharedApplication.KeyWindow is null) - { - return; - } - - UIApplication.SharedApplication.KeyWindow.RootViewController = _storyboard.Value.InstantiateInitialViewController(); - - if (UIApplication.SharedApplication.KeyWindow?.RootViewController is CredentialProviderViewController cpvc) - { - cpvc.InitWithContext(_context); - cpvc.OnLockDismissedAsync().FireAndForget(); - } - } - - private void NavigateToPage(ContentPage page) - { - var navigationPage = new NavigationPage(page); - - var window = new Window(navigationPage); - window.ToHandler(MauiContextSingleton.Instance.MauiContext); - } - } -} - -#endif diff --git a/src/iOS.Autofill/CredentialProviderViewController.cs b/src/iOS.Autofill/CredentialProviderViewController.cs index 432820510..fc7d461fc 100644 --- a/src/iOS.Autofill/CredentialProviderViewController.cs +++ b/src/iOS.Autofill/CredentialProviderViewController.cs @@ -17,6 +17,8 @@ using CoreFoundation; using CoreNFC; using Foundation; using Microsoft.Maui.ApplicationModel; +using Microsoft.Maui.Controls; +using Microsoft.Maui.Platform; using UIKit; namespace Bit.iOS.Autofill @@ -313,7 +315,6 @@ namespace Bit.iOS.Autofill } } -#if !ENABLED_TAP_GESTURE_RECOGNIZER_MAUI_EMBEDDED_WORKAROUND public async void DismissLockAndContinue() { DismissViewController(false, async () => await OnLockDismissedAsync()); @@ -327,7 +328,6 @@ namespace Bit.iOS.Autofill PresentViewController(uiController, true, null); } -#endif public async Task OnLockDismissedAsync() { diff --git a/src/iOS.Autofill/Info.plist b/src/iOS.Autofill/Info.plist index a52e4ed12..771f8d735 100644 --- a/src/iOS.Autofill/Info.plist +++ b/src/iOS.Autofill/Info.plist @@ -11,7 +11,7 @@ CFBundleIdentifier com.8bit.bitwarden.autofill CFBundleShortVersionString - 2024.1.0 + 2024.1.1 CFBundleVersion 1 CFBundleLocalizations diff --git a/src/iOS.Autofill/iOS.Autofill.csproj b/src/iOS.Autofill/iOS.Autofill.csproj index 99080d832..6a0b8d429 100644 --- a/src/iOS.Autofill/iOS.Autofill.csproj +++ b/src/iOS.Autofill/iOS.Autofill.csproj @@ -10,7 +10,7 @@ False - $(DefineConstants);ENABLED_TAP_GESTURE_RECOGNIZER_MAUI_EMBEDDED_WORKAROUND + $(DefineConstants) 12.0 @@ -83,7 +83,6 @@ - @@ -123,13 +122,13 @@ - + Resources\more_vert.png - + Resources\more_vert%402x.png - + Resources\more_vert%403x.png diff --git a/src/iOS.Core/Controllers/BaseLockPasswordViewController.cs b/src/iOS.Core/Controllers/BaseLockPasswordViewController.cs index 53161a44c..e01502558 100644 --- a/src/iOS.Core/Controllers/BaseLockPasswordViewController.cs +++ b/src/iOS.Core/Controllers/BaseLockPasswordViewController.cs @@ -204,7 +204,18 @@ namespace Bit.iOS.Core.Controllers var tasks = Task.Run(async () => { await Task.Delay(500); - NSRunLoop.Main.BeginInvokeOnMainThread(async () => await PromptBiometricAsync()); + NSRunLoop.Main.BeginInvokeOnMainThread(async () => + { + try + { + await PromptBiometricAsync(); + } + catch (Exception ex) + { + LoggerHelper.LogEvenIfCantBeResolved(ex); + throw; + } + }); }); } } diff --git a/src/iOS.Core/Services/ClipboardService.cs b/src/iOS.Core/Services/ClipboardService.cs index 0db6b1150..ae72ef194 100644 --- a/src/iOS.Core/Services/ClipboardService.cs +++ b/src/iOS.Core/Services/ClipboardService.cs @@ -31,7 +31,7 @@ namespace Bit.iOS.Core.Services var dictArr = new NSDictionary[1]; dictArr[0] = new NSDictionary(new NSString(UTType.UTF8PlainText), new NSString(text)); - Device.BeginInvokeOnMainThread(() => UIPasteboard.General.SetItems(dictArr, new UIPasteboardOptions + MainThread.BeginInvokeOnMainThread(() => UIPasteboard.General.SetItems(dictArr, new UIPasteboardOptions { LocalOnly = true, ExpirationDate = clearSeconds > 0 ? NSDate.FromTimeIntervalSinceNow(clearSeconds) : null diff --git a/src/iOS.Extension/Info.plist b/src/iOS.Extension/Info.plist index 1d56ec22d..ccb7c47e5 100644 --- a/src/iOS.Extension/Info.plist +++ b/src/iOS.Extension/Info.plist @@ -11,7 +11,7 @@ CFBundleIdentifier com.8bit.bitwarden.find-login-action-extension CFBundleShortVersionString - 2024.1.0 + 2024.1.1 CFBundleLocalizations en diff --git a/src/iOS.Extension/iOS.Extension.csproj b/src/iOS.Extension/iOS.Extension.csproj index 0ee903fff..f374b47be 100644 --- a/src/iOS.Extension/iOS.Extension.csproj +++ b/src/iOS.Extension/iOS.Extension.csproj @@ -100,13 +100,13 @@ - + Resources\more_vert.png - + Resources\more_vert%402x.png - + Resources\more_vert%403x.png diff --git a/src/iOS.ShareExtension/Info.plist b/src/iOS.ShareExtension/Info.plist index a5715607a..577133ce6 100644 --- a/src/iOS.ShareExtension/Info.plist +++ b/src/iOS.ShareExtension/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType XPC! CFBundleShortVersionString - 2024.1.0 + 2024.1.1 CFBundleVersion 1 MinimumOSVersion diff --git a/src/iOS.ShareExtension/iOS.ShareExtension.csproj b/src/iOS.ShareExtension/iOS.ShareExtension.csproj index fa5976b9f..b8718e428 100644 --- a/src/iOS.ShareExtension/iOS.ShareExtension.csproj +++ b/src/iOS.ShareExtension/iOS.ShareExtension.csproj @@ -70,37 +70,37 @@ - + Resources\logo_white%403x.png - + Resources\logo_white%402x.png - + Resources\logo_white.png - + Resources\logo%403x.png - + Resources\logo%402x.png - + Resources\logo.png - + Resources\more_vert.png - + Resources\more_vert%402x.png - + Resources\more_vert%403x.png - + Resources\bwi-font.ttf - + Resources\MaterialIcons_Regular.ttf diff --git a/src/iOS/AppDelegate.cs b/src/iOS/AppDelegate.cs deleted file mode 100644 index 7ce15f48b..000000000 --- a/src/iOS/AppDelegate.cs +++ /dev/null @@ -1,413 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using AuthenticationServices; -using Bit.App.Abstractions; -using Bit.App.Pages; -using Bit.App.Services; -using Bit.App.Utilities; -using Bit.Core; -using Bit.Core.Abstractions; -using Bit.Core.Enums; -using Bit.Core.Services; -using Bit.Core.Utilities; -using Bit.iOS.Core.Services; -using Bit.iOS.Core.Utilities; -using Bit.iOS.Services; -using CoreNFC; -using Foundation; -using UIKit; -using WatchConnectivity; -using Xamarin.Forms; -using Xamarin.Forms.Platform.iOS; - -namespace Bit.iOS -{ - [Register("AppDelegate")] - public partial class AppDelegate : FormsApplicationDelegate - { - const int SPLASH_VIEW_TAG = 4321; - - private NFCNdefReaderSession _nfcSession = null; - private iOSPushNotificationHandler _pushHandler = null; - private Core.NFCReaderDelegate _nfcDelegate = null; - private NSTimer _clipboardTimer = null; - private nint _clipboardBackgroundTaskId; - private NSTimer _eventTimer = null; - private nint _eventBackgroundTaskId; - - private IDeviceActionService _deviceActionService; - private IMessagingService _messagingService; - private IBroadcasterService _broadcasterService; - private IStorageService _storageService; - private IStateService _stateService; - private IEventService _eventService; - - private LazyResolve _deepLinkContext = new LazyResolve(); - - public override bool FinishedLaunching(UIApplication app, NSDictionary options) - { - Forms.Init(); - InitApp(); - - _deviceActionService = ServiceContainer.Resolve("deviceActionService"); - _messagingService = ServiceContainer.Resolve("messagingService"); - _broadcasterService = ServiceContainer.Resolve("broadcasterService"); - _storageService = ServiceContainer.Resolve("storageService"); - _stateService = ServiceContainer.Resolve("stateService"); - _eventService = ServiceContainer.Resolve("eventService"); - - LoadApplication(new App.App(null)); - iOSCoreHelpers.AppearanceAdjustments(); - ZXing.Net.Mobile.Forms.iOS.Platform.Init(); - - ConnectToWatchIfNeededAsync().FireAndForget(); - - _broadcasterService.Subscribe(nameof(AppDelegate), async (message) => - { - try - { - if (message.Command == "startEventTimer") - { - StartEventTimer(); - } - else if (message.Command == "stopEventTimer") - { - var task = StopEventTimerAsync(); - } - else if (message.Command is ThemeManager.UPDATED_THEME_MESSAGE_KEY) - { - Device.BeginInvokeOnMainThread(() => - { - iOSCoreHelpers.AppearanceAdjustments(); - }); - } - else if (message.Command == "listenYubiKeyOTP") - { - iOSCoreHelpers.ListenYubiKey((bool)message.Data, _deviceActionService, _nfcSession, _nfcDelegate); - } - else if (message.Command == "unlocked") - { - var needsAutofillReplacement = await _storageService.GetAsync( - Core.Constants.AutofillNeedsIdentityReplacementKey); - if (needsAutofillReplacement.GetValueOrDefault()) - { - await ASHelpers.ReplaceAllIdentities(); - } - } - else if (message.Command == "showAppExtension") - { - Device.BeginInvokeOnMainThread(() => ShowAppExtension((ExtensionPageViewModel)message.Data)); - } - else if (message.Command == "syncCompleted") - { - if (message.Data is Dictionary data && data.ContainsKey("successfully")) - { - var success = data["successfully"] as bool?; - if (success.GetValueOrDefault() && _deviceActionService.SystemMajorVersion() >= 12) - { - await ASHelpers.ReplaceAllIdentities(); - } - } - } - else if (message.Command == "addedCipher" || message.Command == "editedCipher" || - message.Command == "restoredCipher") - { - if (_deviceActionService.SystemMajorVersion() >= 12) - { - if (await ASHelpers.IdentitiesCanIncremental()) - { - var cipherId = message.Data as string; - if (message.Command == "addedCipher" && !string.IsNullOrWhiteSpace(cipherId)) - { - var identity = await ASHelpers.GetCipherIdentityAsync(cipherId); - if (identity == null) - { - return; - } - await ASCredentialIdentityStore.SharedStore?.SaveCredentialIdentitiesAsync( - new ASPasswordCredentialIdentity[] { identity }); - return; - } - } - await ASHelpers.ReplaceAllIdentities(); - } - } - else if (message.Command == "deletedCipher" || message.Command == "softDeletedCipher") - { - if (_deviceActionService.SystemMajorVersion() >= 12) - { - if (await ASHelpers.IdentitiesCanIncremental()) - { - var identity = ASHelpers.ToCredentialIdentity( - message.Data as Bit.Core.Models.View.CipherView); - if (identity == null) - { - return; - } - await ASCredentialIdentityStore.SharedStore?.RemoveCredentialIdentitiesAsync( - new ASPasswordCredentialIdentity[] { identity }); - return; - } - await ASHelpers.ReplaceAllIdentities(); - } - } - else if (message.Command == "logout") - { - if (_deviceActionService.SystemMajorVersion() >= 12) - { - await ASCredentialIdentityStore.SharedStore?.RemoveAllCredentialIdentitiesAsync(); - } - } - else if ((message.Command == "softDeletedCipher" || message.Command == "restoredCipher") - && _deviceActionService.SystemMajorVersion() >= 12) - { - await ASHelpers.ReplaceAllIdentities(); - } - else if (message.Command == AppHelpers.VAULT_TIMEOUT_ACTION_CHANGED_MESSAGE_COMMAND) - { - var timeoutAction = await _stateService.GetVaultTimeoutActionAsync(); - if (timeoutAction == VaultTimeoutAction.Logout) - { - await ASCredentialIdentityStore.SharedStore?.RemoveAllCredentialIdentitiesAsync(); - } - else - { - await ASHelpers.ReplaceAllIdentities(); - } - } - } - catch (Exception ex) - { - LoggerHelper.LogEvenIfCantBeResolved(ex); - } - }); - - return base.FinishedLaunching(app, options); - } - - public override void OnResignActivation(UIApplication uiApplication) - { - var view = new UIView(UIApplication.SharedApplication.KeyWindow.Frame) - { - Tag = SPLASH_VIEW_TAG - }; - var backgroundView = new UIView(UIApplication.SharedApplication.KeyWindow.Frame) - { - BackgroundColor = ThemeManager.GetResourceColor("SplashBackgroundColor").ToUIColor() - }; - var logo = new UIImage(!ThemeManager.UsingLightTheme ? "logo_white.png" : "logo.png"); - var imageView = new UIImageView(logo) - { - Center = new CoreGraphics.CGPoint(view.Center.X, view.Center.Y - 30) - }; - view.AddSubview(backgroundView); - view.AddSubview(imageView); - UIApplication.SharedApplication.KeyWindow.AddSubview(view); - UIApplication.SharedApplication.KeyWindow.BringSubviewToFront(view); - UIApplication.SharedApplication.KeyWindow.EndEditing(true); - base.OnResignActivation(uiApplication); - } - - public override void DidEnterBackground(UIApplication uiApplication) - { - _stateService?.SetLastActiveTimeAsync(_deviceActionService.GetActiveTime()); - _messagingService?.Send("slept"); - base.DidEnterBackground(uiApplication); - } - - public override void OnActivated(UIApplication uiApplication) - { - base.OnActivated(uiApplication); - UIApplication.SharedApplication.ApplicationIconBadgeNumber = 0; - UIApplication.SharedApplication.KeyWindow? - .ViewWithTag(SPLASH_VIEW_TAG)? - .RemoveFromSuperview(); - - ThemeManager.UpdateThemeOnPagesAsync(); - } - - public override void WillEnterForeground(UIApplication uiApplication) - { - _messagingService?.Send(AppHelpers.RESUMED_MESSAGE_COMMAND); - base.WillEnterForeground(uiApplication); - } - - public override bool OpenUrl(UIApplication application, NSUrl url, string sourceApplication, - NSObject annotation) - { - return true; - } - - public override bool OpenUrl(UIApplication app, NSUrl url, NSDictionary options) - { - return _deepLinkContext.Value.OnNewUri(url) || Xamarin.Essentials.Platform.OpenUrl(app, url, options); - } - - public override bool ContinueUserActivity(UIApplication application, NSUserActivity userActivity, - UIApplicationRestorationHandler completionHandler) - { - if (Xamarin.Essentials.Platform.ContinueUserActivity(application, userActivity, completionHandler)) - { - return true; - } - return base.ContinueUserActivity(application, userActivity, completionHandler); - } - - public override void FailedToRegisterForRemoteNotifications(UIApplication application, NSError error) - { - _pushHandler?.OnErrorReceived(error); - } - - public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken) - { - _pushHandler?.OnRegisteredSuccess(deviceToken); - } - - public override void DidRegisterUserNotificationSettings(UIApplication application, - UIUserNotificationSettings notificationSettings) - { - application.RegisterForRemoteNotifications(); - } - - public override void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo, - Action completionHandler) - { - _pushHandler?.OnMessageReceived(userInfo); - } - - public override void ReceivedRemoteNotification(UIApplication application, NSDictionary userInfo) - { - _pushHandler?.OnMessageReceived(userInfo); - } - - public void InitApp() - { - if (ServiceContainer.RegisteredServices.Count > 0) - { - return; - } - - // Migration services - ServiceContainer.Register("nativeLogService", new ConsoleLogService()); - - // Note: This might cause a race condition. Investigate more. - Task.Run(() => - { - FFImageLoading.Forms.Platform.CachedImageRenderer.Init(); - FFImageLoading.ImageService.Instance.Initialize(new FFImageLoading.Config.Configuration - { - FadeAnimationEnabled = false, - FadeAnimationForCachedImages = false - }); - }); - - iOSCoreHelpers.RegisterLocalServices(); - RegisterPush(); - var deviceActionService = ServiceContainer.Resolve("deviceActionService"); - ServiceContainer.Init(deviceActionService.DeviceUserAgent, Constants.ClearCiphersCacheKey, - Constants.iOSAllClearCipherCacheKeys); - iOSCoreHelpers.InitLogger(); - iOSCoreHelpers.RegisterFinallyBeforeBootstrap(); - - _pushHandler = new iOSPushNotificationHandler( - ServiceContainer.Resolve("pushNotificationListenerService")); - _nfcDelegate = new Core.NFCReaderDelegate((success, message) => - _messagingService.Send("gotYubiKeyOTP", message)); - - iOSCoreHelpers.Bootstrap(async () => await ApplyManagedSettingsAsync()); - } - - private void RegisterPush() - { - var notificationListenerService = new PushNotificationListenerService(); - ServiceContainer.Register( - "pushNotificationListenerService", notificationListenerService); - var iosPushNotificationService = new iOSPushNotificationService(); - ServiceContainer.Register( - "pushNotificationService", iosPushNotificationService); - } - - private void ShowAppExtension(ExtensionPageViewModel extensionPageViewModel) - { - var itemProvider = new NSItemProvider(new NSDictionary(), Core.Constants.UTTypeAppExtensionSetup); - var extensionItem = new NSExtensionItem - { - Attachments = new NSItemProvider[] { itemProvider } - }; - var activityViewController = new UIActivityViewController(new NSExtensionItem[] { extensionItem }, null) - { - CompletionHandler = (activityType, completed) => - { - extensionPageViewModel.EnabledExtension(completed && activityType == iOSCoreHelpers.AppExtensionId); - } - }; - var modal = UIApplication.SharedApplication.KeyWindow.RootViewController.ModalViewController; - if (activityViewController.PopoverPresentationController != null) - { - activityViewController.PopoverPresentationController.SourceView = modal.View; - var frame = UIScreen.MainScreen.Bounds; - frame.Height /= 2; - activityViewController.PopoverPresentationController.SourceRect = frame; - } - modal.PresentViewController(activityViewController, true, null); - } - - private void StartEventTimer() - { - _eventTimer?.Invalidate(); - _eventTimer?.Dispose(); - _eventTimer = null; - Device.BeginInvokeOnMainThread(() => - { - _eventTimer = NSTimer.CreateScheduledTimer(60, true, timer => - { - var task = Task.Run(() => _eventService.UploadEventsAsync()); - }); - }); - } - - private async Task StopEventTimerAsync() - { - _eventTimer?.Invalidate(); - _eventTimer?.Dispose(); - _eventTimer = null; - if (_eventBackgroundTaskId > 0) - { - UIApplication.SharedApplication.EndBackgroundTask(_eventBackgroundTaskId); - _eventBackgroundTaskId = 0; - } - _eventBackgroundTaskId = UIApplication.SharedApplication.BeginBackgroundTask(() => - { - UIApplication.SharedApplication.EndBackgroundTask(_eventBackgroundTaskId); - _eventBackgroundTaskId = 0; - }); - await _eventService.UploadEventsAsync(); - UIApplication.SharedApplication.EndBackgroundTask(_eventBackgroundTaskId); - _eventBackgroundTaskId = 0; - } - - private async Task ApplyManagedSettingsAsync() - { - var userDefaults = NSUserDefaults.StandardUserDefaults; - var managedSettings = userDefaults.DictionaryForKey("com.apple.configuration.managed"); - if (managedSettings != null && managedSettings.Count > 0) - { - var dict = new Dictionary(); - foreach (var setting in managedSettings) - { - dict.Add(setting.Key.ToString(), setting.Value?.ToString()); - } - await AppHelpers.SetPreconfiguredSettingsAsync(dict); - } - } - - private async Task ConnectToWatchIfNeededAsync() - { - if (_stateService != null && await _stateService.GetShouldConnectToWatchAsync()) - { - WCSessionManager.SharedManager.StartSession(); - } - } - } -} diff --git a/src/iOS/Entitlements.plist b/src/iOS/Entitlements.plist deleted file mode 100644 index fcf986d4b..000000000 --- a/src/iOS/Entitlements.plist +++ /dev/null @@ -1,31 +0,0 @@ - - - - - com.apple.developer.authentication-services.autofill-credential-provider - - com.apple.security.application-groups - - group.com.8bit.bitwarden - - keychain-access-groups - - $(AppIdentifierPrefix)com.8bit.bitwarden - - com.apple.developer.ubiquity-container-identifiers - - iCloud.$(CFBundleIdentifier) - - com.apple.developer.nfc.readersession.formats - - NDEF - TAG - - com.apple.developer.associated-domains - - webcredentials:bitwarden.com - - aps-environment - development - - diff --git a/src/iOS/Info.plist b/src/iOS/Info.plist deleted file mode 100644 index cf0fe5084..000000000 --- a/src/iOS/Info.plist +++ /dev/null @@ -1,141 +0,0 @@ - - - - - MinimumOSVersion - 11.0 - CFBundleDisplayName - Bitwarden - CFBundleName - Bitwarden - CFBundleIdentifier - com.8bit.bitwarden - CFBundleShortVersionString - 2024.1.0 - CFBundleVersion - 1 - CFBundleIconName - AppIcon - CFBundleURLTypes - - - CFBundleURLSchemes - - bitwarden - org-appextension-feature-password-management - - CFBundleTypeRole - Editor - CFBundleURLName - com.8bit.bitwarden.url - - - CFBundleURLName - com.8bit.bitwarden - CFBundleURLSchemes - - otpauth - - - - CFBundleLocalizations - - en - es - zh-Hans - zh-Hant - pt-PT - pt-BR - sv - sk - it - fi - fr - ro - id - hr - hu - nl - tr - uk - de - dk - cz - nb - ja - et - vi - pl - ko - fa - ru - be - bg - ca - cs - el - th - - CFBundleDevelopmentRegion - en - UIDeviceFamily - - 1 - 2 - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - UIInterfaceOrientationPortraitUpsideDown - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - LaunchScreen - UIMainStoryboardFile~ipad - LaunchScreen - UIViewControllerBasedStatusBarAppearance - - UIBackgroundModes - - remote-notification - - UIStatusBarHidden - - UIAppFonts - - bwi-font.ttf - MaterialIcons_Regular.ttf - - UIRequiredDeviceCapabilities - - arm64 - - - CADisableMinimumFrameDurationOnPhone - - XSAppIconAssets - Resources/Assets.xcassets/AppIcons.appiconset - ITSAppUsesNonExemptEncryption - - ITSEncryptionExportComplianceCode - ecf076d3-4824-4d7b-b716-2a9a47d7d296 - NSPhotoLibraryUsageDescription - This app does not require access to the photo library. - NSCameraUsageDescription - Scan QR codes - NSFaceIDUsageDescription - Use Face ID to unlock your vault. - NFCReaderUsageDescription - Use Yubikeys for two-facor authentication. - - diff --git a/src/iOS/LaunchScreen.storyboard b/src/iOS/LaunchScreen.storyboard deleted file mode 100644 index 6cec090bc..000000000 --- a/src/iOS/LaunchScreen.storyboard +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/iOS/Main.cs b/src/iOS/Main.cs deleted file mode 100644 index 13f65ed2e..000000000 --- a/src/iOS/Main.cs +++ /dev/null @@ -1,13 +0,0 @@ -using UIKit; - -namespace Bit.iOS -{ - public class Application - { - static void Main(string[] args) - { - ObjCRuntime.Dlfcn.dlopen(ObjCRuntime.Constants.libSystemLibrary, 0); - UIApplication.Main(args, null, "AppDelegate"); - } - } -} diff --git a/src/iOS/Properties/AssemblyInfo.cs b/src/iOS/Properties/AssemblyInfo.cs deleted file mode 100644 index 55f4a249c..000000000 --- a/src/iOS/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Reflection; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("BitwardeniOS")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Bitwarden Inc.")] -[assembly: AssemblyProduct("Bitwarden")] -[assembly: AssemblyCopyright("Copyright © 2016")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("72bdc44f-c588-44f3-b6df-9aace7daafdd")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/iOS/Resources/Assets.xcassets/AppIcons.appiconset/Contents.json b/src/iOS/Resources/Assets.xcassets/AppIcons.appiconset/Contents.json deleted file mode 100644 index 5b671eb96..000000000 --- a/src/iOS/Resources/Assets.xcassets/AppIcons.appiconset/Contents.json +++ /dev/null @@ -1,117 +0,0 @@ -{ - "images": [ - { - "scale": "2x", - "size": "20x20", - "idiom": "iphone", - "filename": "Icon-40.png" - }, - { - "scale": "3x", - "size": "20x20", - "idiom": "iphone", - "filename": "Icon-60.png" - }, - { - "scale": "2x", - "size": "29x29", - "idiom": "iphone", - "filename": "Icon-58.png" - }, - { - "scale": "3x", - "size": "29x29", - "idiom": "iphone", - "filename": "Icon-87.png" - }, - { - "scale": "2x", - "size": "40x40", - "idiom": "iphone", - "filename": "Icon-80.png" - }, - { - "scale": "3x", - "size": "40x40", - "idiom": "iphone", - "filename": "Icon-120.png" - }, - { - "scale": "2x", - "size": "60x60", - "idiom": "iphone", - "filename": "Icon-120.png" - }, - { - "scale": "3x", - "size": "60x60", - "idiom": "iphone", - "filename": "Icon-180.png" - }, - { - "scale": "1x", - "size": "20x20", - "idiom": "ipad", - "filename": "Icon-20.png" - }, - { - "scale": "2x", - "size": "20x20", - "idiom": "ipad", - "filename": "Icon-40.png" - }, - { - "scale": "1x", - "size": "29x29", - "idiom": "ipad", - "filename": "Icon-29.png" - }, - { - "scale": "2x", - "size": "29x29", - "idiom": "ipad", - "filename": "Icon-58.png" - }, - { - "scale": "1x", - "size": "40x40", - "idiom": "ipad", - "filename": "Icon-40.png" - }, - { - "scale": "2x", - "size": "40x40", - "idiom": "ipad", - "filename": "Icon-80.png" - }, - { - "scale": "1x", - "size": "76x76", - "idiom": "ipad", - "filename": "Icon-76.png" - }, - { - "scale": "2x", - "size": "76x76", - "idiom": "ipad", - "filename": "Icon-152.png" - }, - { - "scale": "2x", - "size": "83.5x83.5", - "idiom": "ipad", - "filename": "Icon-167.png" - }, - { - "scale": "1x", - "size": "1024x1024", - "idiom": "ios-marketing", - "filename": "Icon-1024.png" - } - ], - "properties": {}, - "info": { - "version": 1, - "author": "xcode" - } -} \ No newline at end of file diff --git a/src/iOS/Resources/Assets.xcassets/AppIcons.appiconset/Icon-1024.png b/src/iOS/Resources/Assets.xcassets/AppIcons.appiconset/Icon-1024.png deleted file mode 100644 index e96f62fce..000000000 Binary files a/src/iOS/Resources/Assets.xcassets/AppIcons.appiconset/Icon-1024.png and /dev/null differ diff --git a/src/iOS/Resources/Assets.xcassets/AppIcons.appiconset/Icon-120.png b/src/iOS/Resources/Assets.xcassets/AppIcons.appiconset/Icon-120.png deleted file mode 100644 index 337b432b9..000000000 Binary files a/src/iOS/Resources/Assets.xcassets/AppIcons.appiconset/Icon-120.png and /dev/null differ diff --git a/src/iOS/Resources/Assets.xcassets/AppIcons.appiconset/Icon-152.png b/src/iOS/Resources/Assets.xcassets/AppIcons.appiconset/Icon-152.png deleted file mode 100644 index 7897addad..000000000 Binary files a/src/iOS/Resources/Assets.xcassets/AppIcons.appiconset/Icon-152.png and /dev/null differ diff --git a/src/iOS/Resources/Assets.xcassets/AppIcons.appiconset/Icon-167.png b/src/iOS/Resources/Assets.xcassets/AppIcons.appiconset/Icon-167.png deleted file mode 100644 index ec8b7b847..000000000 Binary files a/src/iOS/Resources/Assets.xcassets/AppIcons.appiconset/Icon-167.png and /dev/null differ diff --git a/src/iOS/Resources/Assets.xcassets/AppIcons.appiconset/Icon-180.png b/src/iOS/Resources/Assets.xcassets/AppIcons.appiconset/Icon-180.png deleted file mode 100644 index d600969a7..000000000 Binary files a/src/iOS/Resources/Assets.xcassets/AppIcons.appiconset/Icon-180.png and /dev/null differ diff --git a/src/iOS/Resources/Assets.xcassets/AppIcons.appiconset/Icon-20.png b/src/iOS/Resources/Assets.xcassets/AppIcons.appiconset/Icon-20.png deleted file mode 100644 index b6ad05447..000000000 Binary files a/src/iOS/Resources/Assets.xcassets/AppIcons.appiconset/Icon-20.png and /dev/null differ diff --git a/src/iOS/Resources/Assets.xcassets/AppIcons.appiconset/Icon-29.png b/src/iOS/Resources/Assets.xcassets/AppIcons.appiconset/Icon-29.png deleted file mode 100644 index a99a4d604..000000000 Binary files a/src/iOS/Resources/Assets.xcassets/AppIcons.appiconset/Icon-29.png and /dev/null differ diff --git a/src/iOS/Resources/Assets.xcassets/AppIcons.appiconset/Icon-40.png b/src/iOS/Resources/Assets.xcassets/AppIcons.appiconset/Icon-40.png deleted file mode 100644 index f7eff8ec7..000000000 Binary files a/src/iOS/Resources/Assets.xcassets/AppIcons.appiconset/Icon-40.png and /dev/null differ diff --git a/src/iOS/Resources/Assets.xcassets/AppIcons.appiconset/Icon-58.png b/src/iOS/Resources/Assets.xcassets/AppIcons.appiconset/Icon-58.png deleted file mode 100644 index a2fe7df1a..000000000 Binary files a/src/iOS/Resources/Assets.xcassets/AppIcons.appiconset/Icon-58.png and /dev/null differ diff --git a/src/iOS/Resources/Assets.xcassets/AppIcons.appiconset/Icon-60.png b/src/iOS/Resources/Assets.xcassets/AppIcons.appiconset/Icon-60.png deleted file mode 100644 index 94a506341..000000000 Binary files a/src/iOS/Resources/Assets.xcassets/AppIcons.appiconset/Icon-60.png and /dev/null differ diff --git a/src/iOS/Resources/Assets.xcassets/AppIcons.appiconset/Icon-76.png b/src/iOS/Resources/Assets.xcassets/AppIcons.appiconset/Icon-76.png deleted file mode 100644 index d7b8f6775..000000000 Binary files a/src/iOS/Resources/Assets.xcassets/AppIcons.appiconset/Icon-76.png and /dev/null differ diff --git a/src/iOS/Resources/Assets.xcassets/AppIcons.appiconset/Icon-80.png b/src/iOS/Resources/Assets.xcassets/AppIcons.appiconset/Icon-80.png deleted file mode 100644 index bc264ce75..000000000 Binary files a/src/iOS/Resources/Assets.xcassets/AppIcons.appiconset/Icon-80.png and /dev/null differ diff --git a/src/iOS/Resources/Assets.xcassets/AppIcons.appiconset/Icon-87.png b/src/iOS/Resources/Assets.xcassets/AppIcons.appiconset/Icon-87.png deleted file mode 100644 index 4ab4bfa00..000000000 Binary files a/src/iOS/Resources/Assets.xcassets/AppIcons.appiconset/Icon-87.png and /dev/null differ diff --git a/src/iOS/Resources/Assets.xcassets/Contents.json b/src/iOS/Resources/Assets.xcassets/Contents.json deleted file mode 100644 index 73c00596a..000000000 --- a/src/iOS/Resources/Assets.xcassets/Contents.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/src/iOS/Resources/Assets.xcassets/LaunchScreen.imageset/Contents.json b/src/iOS/Resources/Assets.xcassets/LaunchScreen.imageset/Contents.json deleted file mode 100644 index b38b8e9c2..000000000 --- a/src/iOS/Resources/Assets.xcassets/LaunchScreen.imageset/Contents.json +++ /dev/null @@ -1,68 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "dark" - } - ], - "idiom" : "universal" - }, - { - "filename" : "logo.png", - "idiom" : "universal", - "scale" : "1x" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "dark" - } - ], - "filename" : "logo_white.png", - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "logo@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "dark" - } - ], - "filename" : "logo_white@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "logo@3x.png", - "idiom" : "universal", - "scale" : "3x" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "dark" - } - ], - "filename" : "logo_white@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/src/iOS/Resources/Assets.xcassets/empty_items_state.imageset/Contents.json b/src/iOS/Resources/Assets.xcassets/empty_items_state.imageset/Contents.json deleted file mode 100644 index 2c8771189..000000000 --- a/src/iOS/Resources/Assets.xcassets/empty_items_state.imageset/Contents.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "images" : [ - { - "filename" : "Empty-items-state.pdf", - "idiom" : "universal" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "dark" - } - ], - "filename" : "Empty-items-state-dark.pdf", - "idiom" : "universal" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - }, - "properties" : { - "preserves-vector-representation" : true - } -} diff --git a/src/iOS/Resources/Assets.xcassets/empty_items_state.imageset/Empty-items-state-dark.pdf b/src/iOS/Resources/Assets.xcassets/empty_items_state.imageset/Empty-items-state-dark.pdf deleted file mode 100644 index f68a9a3b6..000000000 Binary files a/src/iOS/Resources/Assets.xcassets/empty_items_state.imageset/Empty-items-state-dark.pdf and /dev/null differ diff --git a/src/iOS/Resources/Assets.xcassets/empty_items_state.imageset/Empty-items-state.pdf b/src/iOS/Resources/Assets.xcassets/empty_items_state.imageset/Empty-items-state.pdf deleted file mode 100644 index 1aa4dc22f..000000000 Binary files a/src/iOS/Resources/Assets.xcassets/empty_items_state.imageset/Empty-items-state.pdf and /dev/null differ diff --git a/src/iOS/Resources/Assets.xcassets/empty_login_requests.imageset/Contents.json b/src/iOS/Resources/Assets.xcassets/empty_login_requests.imageset/Contents.json deleted file mode 100644 index 920c75d19..000000000 --- a/src/iOS/Resources/Assets.xcassets/empty_login_requests.imageset/Contents.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "images" : [ - { - "filename" : "empty_login_requests.pdf", - "idiom" : "universal" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "dark" - } - ], - "filename" : "empty_login_requests_dark.pdf", - "idiom" : "universal" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - }, - "properties" : { - "preserves-vector-representation" : true - } -} diff --git a/src/iOS/Resources/Assets.xcassets/empty_login_requests.imageset/empty_login_requests.pdf b/src/iOS/Resources/Assets.xcassets/empty_login_requests.imageset/empty_login_requests.pdf deleted file mode 100644 index 38f66ca78..000000000 Binary files a/src/iOS/Resources/Assets.xcassets/empty_login_requests.imageset/empty_login_requests.pdf and /dev/null differ diff --git a/src/iOS/Resources/Assets.xcassets/empty_login_requests.imageset/empty_login_requests_dark.pdf b/src/iOS/Resources/Assets.xcassets/empty_login_requests.imageset/empty_login_requests_dark.pdf deleted file mode 100644 index dd31f3373..000000000 Binary files a/src/iOS/Resources/Assets.xcassets/empty_login_requests.imageset/empty_login_requests_dark.pdf and /dev/null differ diff --git a/src/iOS/Resources/Assets.xcassets/ic_warning.imageset/Contents.json b/src/iOS/Resources/Assets.xcassets/ic_warning.imageset/Contents.json deleted file mode 100644 index 5a1234c62..000000000 --- a/src/iOS/Resources/Assets.xcassets/ic_warning.imageset/Contents.json +++ /dev/null @@ -1,608 +0,0 @@ -{ - "images" : [ - { - "filename" : "ic_warning-1.pdf", - "idiom" : "universal" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "light" - } - ], - "idiom" : "universal" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "dark" - } - ], - "idiom" : "universal" - }, - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "light" - } - ], - "idiom" : "universal", - "scale" : "1x" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "dark" - } - ], - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "light" - } - ], - "idiom" : "universal", - "scale" : "2x" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "dark" - } - ], - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "light" - } - ], - "idiom" : "universal", - "scale" : "3x" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "dark" - } - ], - "idiom" : "universal", - "scale" : "3x" - }, - { - "idiom" : "iphone" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "light" - } - ], - "idiom" : "iphone" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "dark" - } - ], - "idiom" : "iphone" - }, - { - "idiom" : "iphone", - "scale" : "1x" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "light" - } - ], - "idiom" : "iphone", - "scale" : "1x" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "dark" - } - ], - "idiom" : "iphone", - "scale" : "1x" - }, - { - "idiom" : "iphone", - "scale" : "2x" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "light" - } - ], - "idiom" : "iphone", - "scale" : "2x" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "dark" - } - ], - "idiom" : "iphone", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "scale" : "3x" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "light" - } - ], - "idiom" : "iphone", - "scale" : "3x" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "dark" - } - ], - "idiom" : "iphone", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "scale" : "1x", - "subtype" : "retina4" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "light" - } - ], - "idiom" : "iphone", - "scale" : "1x", - "subtype" : "retina4" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "dark" - } - ], - "idiom" : "iphone", - "scale" : "1x", - "subtype" : "retina4" - }, - { - "idiom" : "iphone", - "scale" : "2x", - "subtype" : "retina4" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "light" - } - ], - "idiom" : "iphone", - "scale" : "2x", - "subtype" : "retina4" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "dark" - } - ], - "idiom" : "iphone", - "scale" : "2x", - "subtype" : "retina4" - }, - { - "idiom" : "iphone", - "scale" : "3x", - "subtype" : "retina4" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "light" - } - ], - "idiom" : "iphone", - "scale" : "3x", - "subtype" : "retina4" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "dark" - } - ], - "idiom" : "iphone", - "scale" : "3x", - "subtype" : "retina4" - }, - { - "idiom" : "ipad" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "light" - } - ], - "idiom" : "ipad" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "dark" - } - ], - "idiom" : "ipad" - }, - { - "idiom" : "ipad", - "scale" : "1x" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "light" - } - ], - "idiom" : "ipad", - "scale" : "1x" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "dark" - } - ], - "idiom" : "ipad", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "scale" : "2x" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "light" - } - ], - "idiom" : "ipad", - "scale" : "2x" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "dark" - } - ], - "idiom" : "ipad", - "scale" : "2x" - }, - { - "idiom" : "car" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "light" - } - ], - "idiom" : "car" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "dark" - } - ], - "idiom" : "car" - }, - { - "idiom" : "car", - "scale" : "2x" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "light" - } - ], - "idiom" : "car", - "scale" : "2x" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "dark" - } - ], - "idiom" : "car", - "scale" : "2x" - }, - { - "idiom" : "car", - "scale" : "3x" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "light" - } - ], - "idiom" : "car", - "scale" : "3x" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "dark" - } - ], - "idiom" : "car", - "scale" : "3x" - }, - { - "idiom" : "mac" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "light" - } - ], - "idiom" : "mac" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "dark" - } - ], - "idiom" : "mac" - }, - { - "idiom" : "mac", - "scale" : "1x" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "light" - } - ], - "idiom" : "mac", - "scale" : "1x" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "dark" - } - ], - "idiom" : "mac", - "scale" : "1x" - }, - { - "idiom" : "mac", - "scale" : "2x" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "light" - } - ], - "idiom" : "mac", - "scale" : "2x" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "dark" - } - ], - "idiom" : "mac", - "scale" : "2x" - }, - { - "idiom" : "watch" - }, - { - "idiom" : "watch", - "screen-width" : "<=145" - }, - { - "idiom" : "watch", - "screen-width" : ">161" - }, - { - "idiom" : "watch", - "screen-width" : ">145" - }, - { - "idiom" : "watch", - "screen-width" : ">183" - }, - { - "idiom" : "watch", - "scale" : "2x" - }, - { - "idiom" : "watch", - "scale" : "2x", - "screen-width" : "<=145" - }, - { - "idiom" : "watch", - "scale" : "2x", - "screen-width" : ">161" - }, - { - "idiom" : "watch", - "scale" : "2x", - "screen-width" : ">145" - }, - { - "idiom" : "watch", - "scale" : "2x", - "screen-width" : ">183" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "light" - } - ], - "idiom" : "watch" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "dark" - } - ], - "idiom" : "watch" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "light" - } - ], - "idiom" : "watch", - "scale" : "2x" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "dark" - } - ], - "idiom" : "watch", - "scale" : "2x" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "light" - } - ], - "idiom" : "watch", - "scale" : "2x", - "screen-width" : "<=145" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "dark" - } - ], - "idiom" : "watch", - "scale" : "2x", - "screen-width" : "<=145" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "light" - } - ], - "idiom" : "watch", - "scale" : "2x", - "screen-width" : ">145" - }, - { - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "dark" - } - ], - "idiom" : "watch", - "scale" : "2x", - "screen-width" : ">145" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/src/iOS/Resources/Assets.xcassets/ic_warning.imageset/ic_warning-1.pdf b/src/iOS/Resources/Assets.xcassets/ic_warning.imageset/ic_warning-1.pdf deleted file mode 100644 index a42df1f85..000000000 --- a/src/iOS/Resources/Assets.xcassets/ic_warning.imageset/ic_warning-1.pdf +++ /dev/null @@ -1,119 +0,0 @@ -%PDF-1.7 - -1 0 obj - << >> -endobj - -2 0 obj - << /Length 3 0 R >> -stream -/DeviceRGB CS -/DeviceRGB cs -q -1.000000 0.000000 -0.000000 1.000000 0.000000 -0.004333 cm -0.866667 0.294118 0.223529 scn -24.979254 0.004448 m -2.740886 0.004448 l -2.256652 0.000004 1.780215 0.127985 1.360950 0.376835 c -0.941685 0.625685 0.595185 0.983850 0.356966 1.415783 c -0.120480 1.834383 -0.003394 2.309866 0.000071 2.793346 c -0.003536 3.276825 0.132607 3.750528 0.374291 4.165575 c -11.493476 23.511885 l -11.737758 23.932262 12.084259 24.279764 12.499193 24.521503 c -12.914126 24.763245 13.382767 24.890335 13.860070 24.890335 c -14.337375 24.890335 14.806015 24.763245 15.220948 24.521503 c -15.635882 24.279764 15.982384 23.932262 16.226665 23.511885 c -27.345852 4.165575 l -27.587534 3.750528 27.717470 3.276825 27.720068 2.793346 c -27.722668 2.309866 27.599663 1.834383 27.363176 1.415783 c -27.124958 0.983850 26.778458 0.624796 26.359192 0.376835 c -25.939928 0.128874 25.463488 0.000004 24.979254 0.004448 c -24.979254 0.004448 l -h -13.860070 23.111946 m -13.684222 23.114613 13.510106 23.069286 13.356780 22.981300 c -13.203454 22.893314 13.075248 22.764446 12.985158 22.608913 c -1.867706 3.262606 l -1.782813 3.116850 1.737768 2.949764 1.737768 2.780014 c -1.737768 2.610262 1.782813 2.443178 1.867706 2.297422 c -1.956063 2.138336 2.084268 2.006802 2.239327 1.916149 c -2.394386 1.825497 2.570235 1.779282 2.747816 1.781948 c -24.979254 1.781948 l -25.157701 1.779282 25.333551 1.825497 25.487745 1.916149 c -25.641937 2.006802 25.771009 2.138336 25.859367 2.297422 c -25.944260 2.443178 25.989302 2.610262 25.989302 2.780014 c -25.989302 2.949764 25.944260 3.116850 25.859367 3.262606 c -14.734983 22.608913 l -14.644894 22.764446 14.516687 22.892426 14.363361 22.981300 c -14.210035 23.070175 14.035919 23.114613 13.860070 23.111946 c -13.860070 23.111946 l -h -13.860070 7.887661 m -13.630514 7.887661 13.409620 7.980980 13.247631 8.148064 c -13.085643 8.315149 12.993821 8.540892 12.993821 8.776411 c -12.993821 16.904917 l -12.993821 17.140434 13.084776 17.367065 13.247631 17.533262 c -13.410486 17.699459 13.630514 17.793667 13.860070 17.793667 c -14.089627 17.793667 14.310521 17.700348 14.472510 17.533262 c -14.634499 17.366177 14.726320 17.140434 14.726320 16.904917 c -14.726320 8.776411 l -14.726320 8.540892 14.635365 8.314260 14.472510 8.148064 c -14.309655 7.981867 14.089627 7.887661 13.860070 7.887661 c -h -13.860070 3.493681 m -14.427464 3.493681 14.887444 3.965607 14.887444 4.547737 c -14.887444 5.129869 14.427464 5.601795 13.860070 5.601795 c -13.292677 5.601795 12.832698 5.129869 12.832698 4.547737 c -12.832698 3.965607 13.292677 3.493681 13.860070 3.493681 c -h -f -n -Q - -endstream -endobj - -3 0 obj - 2568 -endobj - -4 0 obj - << /Annots [] - /Type /Page - /MediaBox [ 0.000000 0.000000 27.720123 24.886002 ] - /Resources 1 0 R - /Contents 2 0 R - /Parent 5 0 R - >> -endobj - -5 0 obj - << /Kids [ 4 0 R ] - /Count 1 - /Type /Pages - >> -endobj - -6 0 obj - << /Pages 5 0 R - /Type /Catalog - >> -endobj - -xref -0 7 -0000000000 65535 f -0000000010 00000 n -0000000034 00000 n -0000002658 00000 n -0000002681 00000 n -0000002854 00000 n -0000002928 00000 n -trailer -<< /ID [ (some) (id) ] - /Root 6 0 R - /Size 7 ->> -startxref -2987 -%%EOF \ No newline at end of file diff --git a/src/iOS/Resources/MaterialIcons_Regular.ttf b/src/iOS/Resources/MaterialIcons_Regular.ttf deleted file mode 100644 index 7015564ad..000000000 Binary files a/src/iOS/Resources/MaterialIcons_Regular.ttf and /dev/null differ diff --git a/src/iOS/Resources/autofill-kb.png b/src/iOS/Resources/autofill-kb.png deleted file mode 100644 index fa12a0873..000000000 Binary files a/src/iOS/Resources/autofill-kb.png and /dev/null differ diff --git a/src/iOS/Resources/autofill-kb@2x.png b/src/iOS/Resources/autofill-kb@2x.png deleted file mode 100644 index 6539330b0..000000000 Binary files a/src/iOS/Resources/autofill-kb@2x.png and /dev/null differ diff --git a/src/iOS/Resources/autofill-kb@3x.png b/src/iOS/Resources/autofill-kb@3x.png deleted file mode 100644 index 07d8f3ce5..000000000 Binary files a/src/iOS/Resources/autofill-kb@3x.png and /dev/null differ diff --git a/src/iOS/Resources/bwi-font.ttf b/src/iOS/Resources/bwi-font.ttf deleted file mode 100644 index f9b63283e..000000000 Binary files a/src/iOS/Resources/bwi-font.ttf and /dev/null differ diff --git a/src/iOS/Resources/cog_environment.png b/src/iOS/Resources/cog_environment.png deleted file mode 100644 index 95d6271b8..000000000 Binary files a/src/iOS/Resources/cog_environment.png and /dev/null differ diff --git a/src/iOS/Resources/cog_environment@2x.png b/src/iOS/Resources/cog_environment@2x.png deleted file mode 100644 index 8d884844f..000000000 Binary files a/src/iOS/Resources/cog_environment@2x.png and /dev/null differ diff --git a/src/iOS/Resources/cog_environment@3x.png b/src/iOS/Resources/cog_environment@3x.png deleted file mode 100644 index a46070614..000000000 Binary files a/src/iOS/Resources/cog_environment@3x.png and /dev/null differ diff --git a/src/iOS/Resources/cog_settings.png b/src/iOS/Resources/cog_settings.png deleted file mode 100644 index 95d6271b8..000000000 Binary files a/src/iOS/Resources/cog_settings.png and /dev/null differ diff --git a/src/iOS/Resources/cog_settings@2x.png b/src/iOS/Resources/cog_settings@2x.png deleted file mode 100644 index 8d884844f..000000000 Binary files a/src/iOS/Resources/cog_settings@2x.png and /dev/null differ diff --git a/src/iOS/Resources/cog_settings@3x.png b/src/iOS/Resources/cog_settings@3x.png deleted file mode 100644 index a46070614..000000000 Binary files a/src/iOS/Resources/cog_settings@3x.png and /dev/null differ diff --git a/src/iOS/Resources/ext-act.png b/src/iOS/Resources/ext-act.png deleted file mode 100644 index be97e5b28..000000000 Binary files a/src/iOS/Resources/ext-act.png and /dev/null differ diff --git a/src/iOS/Resources/ext-act@2x.png b/src/iOS/Resources/ext-act@2x.png deleted file mode 100644 index d8f294e54..000000000 Binary files a/src/iOS/Resources/ext-act@2x.png and /dev/null differ diff --git a/src/iOS/Resources/ext-act@3x.png b/src/iOS/Resources/ext-act@3x.png deleted file mode 100644 index bd9a411a1..000000000 Binary files a/src/iOS/Resources/ext-act@3x.png and /dev/null differ diff --git a/src/iOS/Resources/ext-more.png b/src/iOS/Resources/ext-more.png deleted file mode 100644 index 64763ea3d..000000000 Binary files a/src/iOS/Resources/ext-more.png and /dev/null differ diff --git a/src/iOS/Resources/ext-more@2x.png b/src/iOS/Resources/ext-more@2x.png deleted file mode 100644 index 67c326055..000000000 Binary files a/src/iOS/Resources/ext-more@2x.png and /dev/null differ diff --git a/src/iOS/Resources/ext-more@3x.png b/src/iOS/Resources/ext-more@3x.png deleted file mode 100644 index 2982b9cd0..000000000 Binary files a/src/iOS/Resources/ext-more@3x.png and /dev/null differ diff --git a/src/iOS/Resources/ext-use.png b/src/iOS/Resources/ext-use.png deleted file mode 100644 index 4b0a90f72..000000000 Binary files a/src/iOS/Resources/ext-use.png and /dev/null differ diff --git a/src/iOS/Resources/ext-use@2x.png b/src/iOS/Resources/ext-use@2x.png deleted file mode 100644 index 93ee7f492..000000000 Binary files a/src/iOS/Resources/ext-use@2x.png and /dev/null differ diff --git a/src/iOS/Resources/ext-use@3x.png b/src/iOS/Resources/ext-use@3x.png deleted file mode 100644 index 35869465e..000000000 Binary files a/src/iOS/Resources/ext-use@3x.png and /dev/null differ diff --git a/src/iOS/Resources/generate.png b/src/iOS/Resources/generate.png deleted file mode 100644 index 332f01a69..000000000 Binary files a/src/iOS/Resources/generate.png and /dev/null differ diff --git a/src/iOS/Resources/generate@2x.png b/src/iOS/Resources/generate@2x.png deleted file mode 100644 index 6cda8a1ba..000000000 Binary files a/src/iOS/Resources/generate@2x.png and /dev/null differ diff --git a/src/iOS/Resources/generate@3x.png b/src/iOS/Resources/generate@3x.png deleted file mode 100644 index 6461e66aa..000000000 Binary files a/src/iOS/Resources/generate@3x.png and /dev/null differ diff --git a/src/iOS/Resources/info.png b/src/iOS/Resources/info.png deleted file mode 100644 index a29247af1..000000000 Binary files a/src/iOS/Resources/info.png and /dev/null differ diff --git a/src/iOS/Resources/info@2x.png b/src/iOS/Resources/info@2x.png deleted file mode 100644 index c844ebbc2..000000000 Binary files a/src/iOS/Resources/info@2x.png and /dev/null differ diff --git a/src/iOS/Resources/info@3x.png b/src/iOS/Resources/info@3x.png deleted file mode 100644 index 3adc029dc..000000000 Binary files a/src/iOS/Resources/info@3x.png and /dev/null differ diff --git a/src/iOS/Resources/lock.png b/src/iOS/Resources/lock.png deleted file mode 100644 index fc6e60dff..000000000 Binary files a/src/iOS/Resources/lock.png and /dev/null differ diff --git a/src/iOS/Resources/lock@2x.png b/src/iOS/Resources/lock@2x.png deleted file mode 100644 index c14ad933a..000000000 Binary files a/src/iOS/Resources/lock@2x.png and /dev/null differ diff --git a/src/iOS/Resources/lock@3x.png b/src/iOS/Resources/lock@3x.png deleted file mode 100644 index 335a6254b..000000000 Binary files a/src/iOS/Resources/lock@3x.png and /dev/null differ diff --git a/src/iOS/Resources/login.png b/src/iOS/Resources/login.png deleted file mode 100644 index bd28d760d..000000000 Binary files a/src/iOS/Resources/login.png and /dev/null differ diff --git a/src/iOS/Resources/login@2x.png b/src/iOS/Resources/login@2x.png deleted file mode 100644 index 9229cc3a5..000000000 Binary files a/src/iOS/Resources/login@2x.png and /dev/null differ diff --git a/src/iOS/Resources/login@3x.png b/src/iOS/Resources/login@3x.png deleted file mode 100644 index aa85485e4..000000000 Binary files a/src/iOS/Resources/login@3x.png and /dev/null differ diff --git a/src/iOS/Resources/logo.png b/src/iOS/Resources/logo.png deleted file mode 100644 index 33ced5b12..000000000 Binary files a/src/iOS/Resources/logo.png and /dev/null differ diff --git a/src/iOS/Resources/logo@2x.png b/src/iOS/Resources/logo@2x.png deleted file mode 100644 index 2a0ba60b9..000000000 Binary files a/src/iOS/Resources/logo@2x.png and /dev/null differ diff --git a/src/iOS/Resources/logo@3x.png b/src/iOS/Resources/logo@3x.png deleted file mode 100644 index 904731676..000000000 Binary files a/src/iOS/Resources/logo@3x.png and /dev/null differ diff --git a/src/iOS/Resources/logo_white.png b/src/iOS/Resources/logo_white.png deleted file mode 100644 index b5856a638..000000000 Binary files a/src/iOS/Resources/logo_white.png and /dev/null differ diff --git a/src/iOS/Resources/logo_white@2x.png b/src/iOS/Resources/logo_white@2x.png deleted file mode 100644 index 7424b6f77..000000000 Binary files a/src/iOS/Resources/logo_white@2x.png and /dev/null differ diff --git a/src/iOS/Resources/logo_white@3x.png b/src/iOS/Resources/logo_white@3x.png deleted file mode 100644 index 7d76d07d2..000000000 Binary files a/src/iOS/Resources/logo_white@3x.png and /dev/null differ diff --git a/src/iOS/Resources/more.png b/src/iOS/Resources/more.png deleted file mode 100644 index c54bb2da0..000000000 Binary files a/src/iOS/Resources/more.png and /dev/null differ diff --git a/src/iOS/Resources/more@2x.png b/src/iOS/Resources/more@2x.png deleted file mode 100644 index 0b5b03261..000000000 Binary files a/src/iOS/Resources/more@2x.png and /dev/null differ diff --git a/src/iOS/Resources/more@3x.png b/src/iOS/Resources/more@3x.png deleted file mode 100644 index d587310ba..000000000 Binary files a/src/iOS/Resources/more@3x.png and /dev/null differ diff --git a/src/iOS/Resources/plus.png b/src/iOS/Resources/plus.png deleted file mode 100644 index 11393f70c..000000000 Binary files a/src/iOS/Resources/plus.png and /dev/null differ diff --git a/src/iOS/Resources/plus@2x.png b/src/iOS/Resources/plus@2x.png deleted file mode 100644 index 0878e0596..000000000 Binary files a/src/iOS/Resources/plus@2x.png and /dev/null differ diff --git a/src/iOS/Resources/plus@3x.png b/src/iOS/Resources/plus@3x.png deleted file mode 100644 index e767f90ce..000000000 Binary files a/src/iOS/Resources/plus@3x.png and /dev/null differ diff --git a/src/iOS/Resources/search.png b/src/iOS/Resources/search.png deleted file mode 100644 index 88f7f757c..000000000 Binary files a/src/iOS/Resources/search.png and /dev/null differ diff --git a/src/iOS/Resources/search@2x.png b/src/iOS/Resources/search@2x.png deleted file mode 100644 index 1c4ea4e6d..000000000 Binary files a/src/iOS/Resources/search@2x.png and /dev/null differ diff --git a/src/iOS/Resources/search@3x.png b/src/iOS/Resources/search@3x.png deleted file mode 100644 index 819beb4f9..000000000 Binary files a/src/iOS/Resources/search@3x.png and /dev/null differ diff --git a/src/iOS/Resources/send.png b/src/iOS/Resources/send.png deleted file mode 100644 index 37d7bae67..000000000 Binary files a/src/iOS/Resources/send.png and /dev/null differ diff --git a/src/iOS/Resources/send@2x.png b/src/iOS/Resources/send@2x.png deleted file mode 100644 index d5cb621a3..000000000 Binary files a/src/iOS/Resources/send@2x.png and /dev/null differ diff --git a/src/iOS/Resources/send@3x.png b/src/iOS/Resources/send@3x.png deleted file mode 100644 index 030e9684e..000000000 Binary files a/src/iOS/Resources/send@3x.png and /dev/null differ diff --git a/src/iOS/Resources/yubikey.png b/src/iOS/Resources/yubikey.png deleted file mode 100644 index 437f35825..000000000 Binary files a/src/iOS/Resources/yubikey.png and /dev/null differ diff --git a/src/iOS/Resources/yubikey@2x.png b/src/iOS/Resources/yubikey@2x.png deleted file mode 100644 index 3350d588e..000000000 Binary files a/src/iOS/Resources/yubikey@2x.png and /dev/null differ diff --git a/src/iOS/Resources/yubikey@3x.png b/src/iOS/Resources/yubikey@3x.png deleted file mode 100644 index 7a748b996..000000000 Binary files a/src/iOS/Resources/yubikey@3x.png and /dev/null differ diff --git a/src/iOS/Services/iOSPushNotificationHandler.cs b/src/iOS/Services/iOSPushNotificationHandler.cs deleted file mode 100644 index b19fe17e0..000000000 --- a/src/iOS/Services/iOSPushNotificationHandler.cs +++ /dev/null @@ -1,132 +0,0 @@ -using System; -using System.Diagnostics; -using Bit.App.Abstractions; -using Bit.App.Models; -using Bit.Core; -using Bit.Core.Enums; -using Bit.Core.Services; -using CoreData; -using Foundation; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using UserNotifications; -using Xamarin.Forms; - -namespace Bit.iOS.Services -{ - public class iOSPushNotificationHandler : NSObject, IUNUserNotificationCenterDelegate - { - private const string TokenSetting = "token"; - const string TAG = "##PUSH NOTIFICATIONS"; - - private readonly IPushNotificationListenerService _pushNotificationListenerService; - - public iOSPushNotificationHandler( - IPushNotificationListenerService pushNotificationListenerService) - { - _pushNotificationListenerService = pushNotificationListenerService; - } - - public void OnMessageReceived(NSDictionary userInfo) - { - try - { - Debug.WriteLine($"{TAG} - OnMessageReceived."); - - var json = DictionaryToJson(userInfo); - var values = JObject.Parse(json); - var keyAps = new NSString("aps"); - if (userInfo.ContainsKey(keyAps) && userInfo.ValueForKey(keyAps) is NSDictionary aps) - { - foreach (var apsKey in aps) - { - if (!values.TryGetValue(apsKey.Key.ToString(), out JToken temp)) - { - values.Add(apsKey.Key.ToString(), apsKey.Value.ToString()); - } - } - } - _pushNotificationListenerService.OnMessageAsync(values, Device.iOS); - } - catch (Exception ex) - { - Logger.Instance.Exception(ex); - } - } - - public void OnErrorReceived(NSError error) - { - Debug.WriteLine($"{TAG} - Registration Failed."); - _pushNotificationListenerService.OnError(error.LocalizedDescription, Device.iOS); - } - - public void OnRegisteredSuccess(NSData token) - { - Debug.WriteLine($"{TAG} - Successfully Registered."); - - var hexDeviceToken = BitConverter.ToString(token.ToArray()) - .Replace("-", string.Empty) - .ToLowerInvariant(); - - Debug.WriteLine($"{TAG} - Token: {hexDeviceToken}"); - - UNUserNotificationCenter.Current.Delegate = this; - - _pushNotificationListenerService.OnRegisteredAsync(hexDeviceToken, Device.iOS); - NSUserDefaults.StandardUserDefaults.SetString(hexDeviceToken, TokenSetting); - NSUserDefaults.StandardUserDefaults.Synchronize(); - } - - private static string DictionaryToJson(NSDictionary dictionary) - { - var json = NSJsonSerialization.Serialize(dictionary, NSJsonWritingOptions.PrettyPrinted, out NSError error); - return json.ToString(NSStringEncoding.UTF8); - } - - // To receive notifications in foreground on iOS 10 devices. - [Export("userNotificationCenter:willPresentNotification:withCompletionHandler:")] - public void WillPresentNotification(UNUserNotificationCenter center, UNNotification notification, Action completionHandler) - { - Debug.WriteLine($"{TAG} WillPresentNotification {notification?.Request?.Content?.UserInfo}"); - OnMessageReceived(notification?.Request?.Content?.UserInfo); - completionHandler(UNNotificationPresentationOptions.Alert); - } - - [Export("userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:")] - public void DidReceiveNotificationResponse(UNUserNotificationCenter center, UNNotificationResponse response, Action completionHandler) - { - Debug.WriteLine($"{TAG} DidReceiveNotificationResponse {response?.Notification?.Request?.Content?.UserInfo}"); - if ((response?.Notification?.Request?.Content?.UserInfo) == null) - { - completionHandler(); - return; - } - - var userInfo = response?.Notification?.Request?.Content?.UserInfo; - OnMessageReceived(userInfo); - - if (userInfo.TryGetValue(NSString.FromObject(Constants.NotificationData), out NSObject nsObject)) - { - var token = JToken.Parse(NSString.FromObject(nsObject).ToString()); - var typeToken = token.SelectToken(Constants.NotificationDataType); - if (response.IsDefaultAction) - { - if (typeToken.ToString() == PasswordlessNotificationData.TYPE) - { - _pushNotificationListenerService.OnNotificationTapped(token.ToObject()); - } - } - else if (response.IsDismissAction) - { - if (typeToken.ToString() == PasswordlessNotificationData.TYPE) - { - _pushNotificationListenerService.OnNotificationDismissed(token.ToObject()); - } - } - } - - // Inform caller it has been handled - completionHandler(); - } - } -} diff --git a/src/iOS/Services/iOSPushNotificationService.cs b/src/iOS/Services/iOSPushNotificationService.cs deleted file mode 100644 index aec24657b..000000000 --- a/src/iOS/Services/iOSPushNotificationService.cs +++ /dev/null @@ -1,122 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Threading.Tasks; -using Bit.App.Abstractions; -using Bit.App.Models; -using Bit.App.Resources; -using Bit.App.Services; -using Bit.Core; -using Bit.Core.Services; -using Foundation; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using UIKit; -using UserNotifications; - -namespace Bit.iOS.Services -{ - public class iOSPushNotificationService : NSObject, IPushNotificationService, IUNUserNotificationCenterDelegate - { - private const string TokenSetting = "token"; - const string TAG = "##PUSH NOTIFICATIONS"; - - public Task GetTokenAsync() - { - return Task.FromResult(NSUserDefaults.StandardUserDefaults.StringForKey(TokenSetting)); - } - - public bool IsRegisteredForPush => UIApplication.SharedApplication.IsRegisteredForRemoteNotifications; - - public async Task AreNotificationsSettingsEnabledAsync() - { - var settings = await UNUserNotificationCenter.Current.GetNotificationSettingsAsync(); - return settings.AlertSetting == UNNotificationSetting.Enabled; - } - - public async Task RegisterAsync() - { - Debug.WriteLine($"{TAG} RegisterAsync"); - - var tcs = new TaskCompletionSource(); - - var authOptions = UNAuthorizationOptions.Alert | UNAuthorizationOptions.Badge | UNAuthorizationOptions.Sound; - UNUserNotificationCenter.Current.RequestAuthorization(authOptions, (granted, error) => - { - if (error != null) - { - Debug.WriteLine($"{TAG} {error}"); - } - else - { - Debug.WriteLine($"{TAG} {granted}"); - } - - tcs.SetResult(granted); - }); - - if (await tcs.Task) - { - Debug.WriteLine($"{TAG} RegisterForRemoteNotifications"); - UIApplication.SharedApplication.RegisterForRemoteNotifications(); - } - } - - public Task UnregisterAsync() - { - Debug.WriteLine($"{TAG} UnregisterAsync"); - - UIApplication.SharedApplication.UnregisterForRemoteNotifications(); - // TODO: unregister call - // _pushNotificationListener.OnUnregistered(Device.iOS); - NSUserDefaults.StandardUserDefaults.SetString(string.Empty, TokenSetting); - NSUserDefaults.StandardUserDefaults.Synchronize(); - return Task.FromResult(0); - } - - public void SendLocalNotification(string title, string message, BaseNotificationData data) - { - if (string.IsNullOrEmpty(data.Id)) - { - throw new ArgumentNullException("notificationId cannot be null or empty."); - } - - var content = new UNMutableNotificationContent() - { - Title = title, - Body = message, - CategoryIdentifier = Constants.iOSNotificationCategoryId - }; - - if (data != null) - { - content.UserInfo = NSDictionary.FromObjectAndKey(NSData.FromString(JsonConvert.SerializeObject(data), NSStringEncoding.UTF8), new NSString(Constants.NotificationData)); - } - - var actions = new UNNotificationAction[] { UNNotificationAction.FromIdentifier(Constants.iOSNotificationClearActionId, AppResources.Clear, UNNotificationActionOptions.Foreground) }; - var category = UNNotificationCategory.FromIdentifier(Constants.iOSNotificationCategoryId, actions, new string[] { }, UNNotificationCategoryOptions.CustomDismissAction); - UNUserNotificationCenter.Current.SetNotificationCategories(new NSSet(category)); - - var request = UNNotificationRequest.FromIdentifier(data.Id, content, null); - UNUserNotificationCenter.Current.AddNotificationRequest(request, (err) => - { - if (err != null) - { - Logger.Instance.Exception(new Exception($"Failed to schedule notification: {err}")); - } - }); - } - - public void DismissLocalNotification(string notificationId) - { - if (string.IsNullOrEmpty(notificationId)) - { - return; - } - - UNUserNotificationCenter.Current.RemovePendingNotificationRequests(new string[] { notificationId }); - UNUserNotificationCenter.Current.RemoveDeliveredNotifications(new string[] { notificationId }); - } - } -} \ No newline at end of file diff --git a/src/iOS/iOS.csproj b/src/iOS/iOS.csproj deleted file mode 100644 index 4a21e24df..000000000 --- a/src/iOS/iOS.csproj +++ /dev/null @@ -1,437 +0,0 @@ - - - - Debug - iPhoneSimulator - 8.0.30703 - 2.0 - {599E0201-420A-4C3E-A7BA-5349F72E0B15} - {FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - {6143fdea-f3c2-4a09-aafa-6e230626515e} - Exe - Bit.iOS - Resources - BitwardeniOS - NSUrlSessionHandler - - - - - true - full - false - bin\iPhoneSimulator\Debug - DEBUG;__UNIFIED__;__MOBILE__;__IOS__ - prompt - 4 - false - x86_64 - None - true - true - --nodevcodeshare --http-message-handler=NSUrlSessionHandler -gcc_flags "-L${ProjectDir}/../../lib/ios -largon2 -force_load ${ProjectDir}/../../lib/ios/libargon2.a" - Entitlements.plist - - - none - true - bin\iPhoneSimulator\Release - prompt - 4 - Full - x86_64 - false - --nodevcodeshare --http-message-handler=NSUrlSessionHandler --linkskip=BitwardeniOS --linkskip=BitwardeniOSCore --linkskip=BitwardeniOSAutofill --linkskip=BitwardeniOSExtension --linkskip=BitwardenApp --linkskip=BitwardenCore --linkskip=LiteDB --linkskip=CsvHelper --linkskip=BitwardeniOSShareExtension -gcc_flags "-L${ProjectDir}/../../lib/ios -largon2 -force_load ${ProjectDir}/../../lib/ios/libargon2.a" - true - Entitlements.plist - - - true - full - false - bin\iPhone\Debug - DEBUG - prompt - 4 - false - ARM64 - iPhone Developer - true - Entitlements.plist - None - false - --nodevcodeshare --http-message-handler=NSUrlSessionHandler -gcc_flags "-L${ProjectDir}/../../lib/ios -largon2 -force_load ${ProjectDir}/../../lib/ios/libargon2.a" - true - - - none - true - bin\iPhone\Release - prompt - 4 - ARM64 - false - iPhone Developer - Entitlements.plist - Full - --nodevcodeshare --http-message-handler=NSUrlSessionHandler --linkskip=BitwardeniOS --linkskip=BitwardeniOSCore --linkskip=BitwardeniOSAutofill --linkskip=BitwardeniOSExtension --linkskip=BitwardenApp --linkskip=BitwardenCore --linkskip=LiteDB --linkskip=CsvHelper --linkskip=BitwardeniOSShareExtension -gcc_flags "-L${ProjectDir}/../../lib/ios -largon2 -force_load ${ProjectDir}/../../lib/ios/libargon2.a" - true - - - none - True - bin\iPhone\Ad-Hoc - prompt - 4 - False - ARM64 - True - iPhone Distribution - Entitlements.plist - Full - --nodevcodeshare --http-message-handler=NSUrlSessionHandler --linkskip=BitwardeniOS --linkskip=BitwardeniOSCore --linkskip=BitwardeniOSAutofill --linkskip=BitwardeniOSExtension --linkskip=BitwardenApp --linkskip=BitwardenCore --linkskip=LiteDB --linkskip=CsvHelper --linkskip=BitwardeniOSShareExtension -gcc_flags "-L${ProjectDir}/../../lib/ios -largon2 -force_load ${ProjectDir}/../../lib/ios/libargon2.a" - Automatic:AdHoc - - - none - True - bin\iPhone\AppStore - prompt - 4 - False - ARM64 - Automatic:AppStore - iPhone Distribution - Entitlements.plist - --nodevcodeshare --http-message-handler=NSUrlSessionHandler --linkskip=BitwardeniOS --linkskip=BitwardeniOSCore --linkskip=BitwardeniOSAutofill --linkskip=BitwardeniOSExtension --linkskip=BitwardenApp --linkskip=BitwardenCore --linkskip=LiteDB --linkskip=CsvHelper --linkskip=BitwardeniOSShareExtension -gcc_flags "-L${ProjectDir}/../../lib/ios -largon2 -force_load ${ProjectDir}/../../lib/ios/libargon2.a" - true - Full - - - bin\iPhoneSimulator\FDroid\ - __IOS__;__MOBILE__;__UNIFIED__; - true - AnyCPU - false - prompt - MinimumRecommendedRules.ruleset - --nodevcodeshare --http-message-handler=NSUrlSessionHandler --linkskip=BitwardeniOS --linkskip=BitwardeniOSCore --linkskip=BitwardeniOSAutofill --linkskip=BitwardeniOSExtension --linkskip=BitwardenApp --linkskip=BitwardenCore --linkskip=LiteDB --linkskip=CsvHelper -gcc_flags "-L${ProjectDir}/../../lib/ios -largon2 -force_load ${ProjectDir}/../../lib/ios/libargon2.a" - true - SdkOnly - - - bin\iPhone\FDroid\ - __IOS__;__MOBILE__;__UNIFIED__; - true - AnyCPU - false - prompt - MinimumRecommendedRules.ruleset - SdkOnly - ARMv7 - - - - - - $(Home)/Library/Developer/Xcode/DerivedData/bitwarden-cbtqsueryycvflfzbsoteofskiyr/Build/Products - $([System.IO.Path]::GetFullPath('$(MSBuildProjectDirectory)\..'))/watchOS/bitwarden.xcarchive/Products/Applications/bitwarden.app/Watch - Bitwarden.app - watchsimulator - watchos - $(WatchAppBuildPath)/$(Configuration)-$(WatchAppConfiguration)/$(WatchAppBundle) - $(WatchAppBuildPath)/$(WatchAppBundle) - - - - - - - - - - - - - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1.8.0 - - - - - - {EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C} - App - - - {4b8a8c41-9820-4341-974c-41e65b7f4366} - Core - - - {8a3ecd75-3ec8-4cb3-b3a2-a73a724c279a} - iOS.Autofill - true - false - - - {e71f3053-056c-4381-9638-048ed73bdff6} - iOS.Core - false - false - - - {324be76c-38fa-4f11-8bb1-95c7b3b1b545} - iOS.Extension - true - false - - - true - {F8C3F648-EA5A-4719-8005-85D1690B1655} - iOS.ShareExtension - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - false - - - - - false - - - - - false - - - - - false - - - - - false - - - - - false - - - - - false - - - - - false - - - - - false - - - - - false - - - - - false - - - - - false - - - - - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <_ResolvedWatchAppReferences Include="$(WatchAppBundleFullPath)" /> - - - <_ResolvedWatchAppReferences Include="$(WatchAppBundleFullPath)" /> - - - --deep - - - - - - \ No newline at end of file diff --git a/src/watchOS/bitwarden/bitwarden WatchKit Extension/Localization/hi.lproj/Localizable.strings b/src/watchOS/bitwarden/bitwarden WatchKit Extension/Localization/hi.lproj/Localizable.strings index 9c752e53d..1c0adb770 100644 --- a/src/watchOS/bitwarden/bitwarden WatchKit Extension/Localization/hi.lproj/Localizable.strings +++ b/src/watchOS/bitwarden/bitwarden WatchKit Extension/Localization/hi.lproj/Localizable.strings @@ -5,6 +5,6 @@ "SyncingItemsContainingVerificationCodes" = "वेरीफिकेशन कोड वाले चीज़ें सिंक कर रहे"; "UnlockBitwardenOnYourIPhoneToViewVerificationCodes" = "वेरीफिकेशन कोड देखने के लिए अपने आईफोन पे बिटवार्डन खोलें"; "SetUpBitwardenToViewItemsContainingVerificationCodes" = "वेरीफिकेशन कोड वाले चीज़ें देखने के लिए बिटवार्डन सेट करें"; -"Search" = "खोजें"; -"NoItemsFound" = "कोई चीज़ नहीं मिला"; +"Search" = "सर्च करें"; +"NoItemsFound" = "कोई आइटम नहीं मिला"; "SetUpAppleWatchPasscodeInOrderToUseBitwarden" = "बिटवार्डन इस्तेमाल करने के लिए एप्पल वॉच पासकोड सेट करें"; diff --git a/store/apple/fi/copy.resx b/store/apple/fi/copy.resx index 4d851a467..e2f948829 100644 --- a/store/apple/fi/copy.resx +++ b/store/apple/fi/copy.resx @@ -132,7 +132,7 @@ Luo usein käyttämillesi sivustoille automaattisesti vahvoja, yksilöllisiä ja Bitwarden Send -ominaisuudella lähetät tietoa nopeasti salattuna — tiedostoja ja tekstiä — suoraan kenelle tahansa. -Yritystoimintaan Bitwarden tarjoaa tilaukset Tiimeille ja Yrityksille, jotta salasanojen jakaminen kollegoiden kesken on turvallista. +Yritystoimintaan Bitwarden tarjoaa yrityksille Teams- ja Enterprise-tilaukset, jotta salasanojen jakaminen kollegoiden kesken on turvallista. Miksi Bitwarden?: diff --git a/store/google/fi/copy.resx b/store/google/fi/copy.resx index a99b29406..39ca48724 100644 --- a/store/google/fi/copy.resx +++ b/store/google/fi/copy.resx @@ -136,7 +136,7 @@ Luo usein käyttämillesi sivustoille automaattisesti vahvoja, yksilöllisiä ja Bitwarden Send -ominaisuudella lähetät tietoa nopeasti salattuna — tiedostoja ja tekstiä — suoraan kenelle tahansa. -Yritystoimintaan Bitwarden tarjoaa tilaukset Tiimeille ja Yrityksille, jotta salasanojen jakaminen kollegoiden kesken on turvallista. +Yritystoimintaan Bitwarden tarjoaa yrityksille Teams- ja Enterprise-tilaukset, jotta salasanojen jakaminen kollegoiden kesken on turvallista. Miksi Bitwarden?: