Merge branch 'feature/maui-migration' into feature/maui-migration-passkeys
# Conflicts: # src/iOS.Autofill/iOS.Autofill.csproj
5
Directory.Build.props
Normal file
@ -0,0 +1,5 @@
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<MauiVersion>8.0.4-nightly.*</MauiVersion>
|
||||
</PropertyGroup>
|
||||
</Project>
|
6
nuget.config
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<add key="MAUI Nightly builds" value="https://pkgs.dev.azure.com/xamarin/public/_packaging/maui-nightly/nuget/v3/index.json" />
|
||||
</packageSources>
|
||||
</configuration>
|
@ -156,6 +156,15 @@
|
||||
<BundleResource Include="Platforms\Android\Resources\drawable-hdpi\logo_white_legacy.png" />
|
||||
<BundleResource Include="Platforms\Android\Resources\mipmap-xhdpi\ic_launcher.png" />
|
||||
<BundleResource Include="Platforms\Android\Resources\mipmap-xhdpi\ic_launcher_round.png" />
|
||||
<BundleResource Include="Platforms\iOS\Resources\logo.png" />
|
||||
<BundleResource Include="Platforms\iOS\Resources\logo_white%402x.png" />
|
||||
<BundleResource Include="Platforms\iOS\Resources\more_vert%402x.png" />
|
||||
<BundleResource Include="Platforms\iOS\Resources\logo_white%403x.png" />
|
||||
<BundleResource Include="Platforms\iOS\Resources\logo%403x.png" />
|
||||
<BundleResource Include="Platforms\iOS\Resources\more_vert%403x.png" />
|
||||
<BundleResource Include="Platforms\iOS\Resources\more_vert.png" />
|
||||
<BundleResource Include="Platforms\iOS\Resources\logo_white.png" />
|
||||
<BundleResource Include="Platforms\iOS\Resources\logo%402x.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\iOS.Core\iOS.Core.csproj" Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'" />
|
||||
@ -236,4 +245,15 @@
|
||||
<GoogleServicesJson Include="Platforms\Android\google-services.json" />
|
||||
<GoogleServicesJson Include="Platforms\Android\google-services.json.enc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Remove="Platforms\iOS\Resources\logo.png" />
|
||||
<None Remove="Platforms\iOS\Resources\logo_white%402x.png" />
|
||||
<None Remove="Platforms\iOS\Resources\more_vert%402x.png" />
|
||||
<None Remove="Platforms\iOS\Resources\logo_white%403x.png" />
|
||||
<None Remove="Platforms\iOS\Resources\logo%403x.png" />
|
||||
<None Remove="Platforms\iOS\Resources\more_vert%403x.png" />
|
||||
<None Remove="Platforms\iOS\Resources\more_vert.png" />
|
||||
<None Remove="Platforms\iOS\Resources\logo_white.png" />
|
||||
<None Remove="Platforms\iOS\Resources\logo%402x.png" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:versionCode="1" android:versionName="2024.1.0" android:installLocation="internalOnly" package="com.x8bit.bitwarden">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:versionCode="1" android:versionName="2024.1.1" android:installLocation="internalOnly" package="com.x8bit.bitwarden">
|
||||
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="34" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.NFC" />
|
||||
|
@ -54,10 +54,6 @@ namespace Bit.iOS
|
||||
_stateService = ServiceContainer.Resolve<IStateService>("stateService");
|
||||
_eventService = ServiceContainer.Resolve<IEventService>("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);
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.8bit.bitwarden</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>2024.1.0</string>
|
||||
<string>2024.1.1</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>CFBundleIconName</key>
|
||||
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 8.2 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 8.2 KiB |
Before Width: | Height: | Size: 164 B After Width: | Height: | Size: 164 B |
Before Width: | Height: | Size: 242 B After Width: | Height: | Size: 242 B |
Before Width: | Height: | Size: 338 B After Width: | Height: | Size: 338 B |
@ -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<IAccountsManager>("accountsManager");
|
||||
_pushNotificationService = ServiceContainer.Resolve<IPushNotificationService>();
|
||||
_configService = ServiceContainer.Resolve<IConfigService>();
|
||||
_logger = ServiceContainer.Resolve<ILogger>();
|
||||
|
||||
_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<int, bool>(details.DialogId, confirmed));
|
||||
});
|
||||
}
|
||||
#if IOS
|
||||
else if (message.Command == AppHelpers.RESUMED_MESSAGE_COMMAND)
|
||||
{
|
||||
if (DeviceInfo.Platform == DevicePlatform.iOS)
|
||||
{
|
||||
ResumedAsync().FireAndForget();
|
||||
}
|
||||
}
|
||||
else if (message.Command == "slept")
|
||||
{
|
||||
if (DeviceInfo.Platform == DevicePlatform.iOS)
|
||||
{
|
||||
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()));
|
||||
@ -372,6 +371,8 @@ namespace Bit.App
|
||||
public AppOptions Options { get; private set; }
|
||||
|
||||
protected override async void OnStart()
|
||||
{
|
||||
try
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("XF App: OnStart");
|
||||
_isResumed = true;
|
||||
@ -390,23 +391,33 @@ namespace Bit.App
|
||||
{
|
||||
_messagingService.Send(Constants.PasswordlessLoginRequestKey);
|
||||
}
|
||||
if (DeviceInfo.Platform == DevicePlatform.Android)
|
||||
{
|
||||
#if ANDROID
|
||||
await _vaultTimeoutService.CheckVaultTimeoutAsync();
|
||||
// Reset delay on every start
|
||||
_vaultTimeoutService.DelayLockAndLogoutMs = null;
|
||||
}
|
||||
#endif
|
||||
|
||||
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
|
||||
{
|
||||
try
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("XF App: OnSleep");
|
||||
_isResumed = false;
|
||||
if (DeviceInfo.Platform == DevicePlatform.Android)
|
||||
{
|
||||
#if ANDROID
|
||||
var isLocked = await _vaultTimeoutService.IsLockedAsync();
|
||||
if (!isLocked)
|
||||
{
|
||||
@ -417,10 +428,18 @@ namespace Bit.App
|
||||
ClearAutofillUri();
|
||||
}
|
||||
await SleptAsync();
|
||||
#endif
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger?.Exception(ex);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnResume()
|
||||
{
|
||||
try
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("XF App: OnResume");
|
||||
_isResumed = true;
|
||||
@ -428,9 +447,15 @@ namespace Bit.App
|
||||
{
|
||||
_messagingService.Send(Constants.PasswordlessLoginRequestKey);
|
||||
}
|
||||
if (DeviceInfo.Platform == DevicePlatform.Android)
|
||||
{
|
||||
#if ANDROID
|
||||
ResumedAsync().FireAndForget();
|
||||
#endif
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger?.Exception(ex);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
@ -516,6 +541,8 @@ namespace Bit.App
|
||||
Task.Run(() =>
|
||||
{
|
||||
MainThread.BeginInvokeOnMainThread(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
Options.Uri = null;
|
||||
if (isLocked)
|
||||
@ -526,6 +553,12 @@ namespace Bit.App
|
||||
{
|
||||
App.MainPage = new TabsPage();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.LogEvenIfCantBeResolved(ex);
|
||||
throw;
|
||||
}
|
||||
});
|
||||
});
|
||||
return true;
|
||||
@ -549,7 +582,7 @@ namespace Bit.App
|
||||
ThemeManager.SetTheme(Resources);
|
||||
RequestedThemeChanged += (s, a) =>
|
||||
{
|
||||
UpdateThemeAsync();
|
||||
UpdateThemeAsync().FireAndForget();
|
||||
};
|
||||
_isResumed = true;
|
||||
#if IOS
|
||||
@ -567,6 +600,8 @@ namespace Bit.App
|
||||
return;
|
||||
}
|
||||
Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var lastSync = await _syncService.GetLastSyncAsync();
|
||||
if (lastSync == null || ((DateTime.UtcNow - lastSync) > TimeSpan.FromMinutes(30)))
|
||||
@ -574,6 +609,11 @@ namespace Bit.App
|
||||
await Task.Delay(1000);
|
||||
await _syncService.FullSyncAsync(false);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Exception(ex);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
#if IOS
|
||||
ToolbarItems.Add(_moreItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
#else
|
||||
ToolbarItems.Add(_logOut);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public Entry SecretEntry
|
||||
@ -64,6 +73,8 @@ namespace Bit.App.Pages
|
||||
}
|
||||
|
||||
protected override async void OnAppearing()
|
||||
{
|
||||
try
|
||||
{
|
||||
base.OnAppearing();
|
||||
_broadcasterService.Subscribe(nameof(LockPage), message =>
|
||||
@ -108,11 +119,17 @@ namespace Bit.App.Pages
|
||||
var tasks = Task.Run(async () =>
|
||||
{
|
||||
await Task.Delay(500);
|
||||
MainThread.BeginInvokeOnMainThread(async () => await _vm.PromptBiometricAsync());
|
||||
await MainThread.InvokeOnMainThreadAsync(async () => await _vm.PromptBiometricAsync());
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.LogEvenIfCantBeResolved(ex);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private void PerformFocusSecretEntry(int? cursorPosition)
|
||||
{
|
||||
@ -166,14 +183,25 @@ namespace Bit.App.Pages
|
||||
}
|
||||
|
||||
private async void Biometric_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (DoOnce())
|
||||
{
|
||||
await _vm.PromptBiometricAsync();
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.LogEvenIfCantBeResolved(ex);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private async void More_Clicked(object sender, System.EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _accountListOverlay.HideAsync();
|
||||
|
||||
@ -190,6 +218,12 @@ namespace Bit.App.Pages
|
||||
await _vm.LogOutAsync();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.LogEvenIfCantBeResolved(ex);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task UnlockedAsync()
|
||||
{
|
||||
|
@ -14,6 +14,7 @@ namespace Bit.App.Pages
|
||||
{
|
||||
private readonly LazyResolve<IStateService> _stateService = new LazyResolve<IStateService>();
|
||||
private readonly LazyResolve<IDeviceActionService> _deviceActionService = new LazyResolve<IDeviceActionService>();
|
||||
private readonly LazyResolve<ILogger> _logger = new LazyResolve<ILogger>();
|
||||
|
||||
protected int ShowModalAnimationDelay = 400;
|
||||
protected int ShowPageAnimationDelay = 100;
|
||||
@ -47,12 +48,22 @@ namespace Bit.App.Pages
|
||||
protected virtual bool ShouldCheckToPreventOnNavigatedToCalledTwice => false;
|
||||
|
||||
protected override async void OnNavigatedTo(NavigatedToEventArgs args)
|
||||
{
|
||||
try
|
||||
{
|
||||
base.OnNavigatedTo(args);
|
||||
|
||||
if (IsThemeDirty)
|
||||
{
|
||||
UpdateOnThemeChanged();
|
||||
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();
|
||||
@ -65,6 +76,12 @@ namespace Bit.App.Pages
|
||||
|
||||
await InitOnNavigatedToAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Core.Services.LoggerHelper.LogEvenIfCantBeResolved(ex);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual Task InitOnNavigatedToAsync() => Task.CompletedTask;
|
||||
|
||||
@ -115,6 +132,8 @@ namespace Bit.App.Pages
|
||||
ContentView targetView = null)
|
||||
{
|
||||
async Task DoWorkAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
await workFunction.Invoke();
|
||||
if (sourceView != null)
|
||||
@ -129,16 +148,22 @@ namespace Bit.App.Pages
|
||||
}
|
||||
}
|
||||
}
|
||||
if (DeviceInfo.Platform == DevicePlatform.iOS)
|
||||
catch (Exception ex)
|
||||
{
|
||||
await DoWorkAsync();
|
||||
return;
|
||||
_logger.Value.Exception(ex);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
#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)
|
||||
|
@ -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<GeneratedPasswordHistory>());
|
||||
ShowNoData = History.Count == 0;
|
||||
@ -66,7 +66,7 @@ namespace Bit.App.Pages
|
||||
{
|
||||
try
|
||||
{
|
||||
await Device.InvokeOnMainThreadAsync(() => History.ResetWithRange(new List<GeneratedPasswordHistory>()));
|
||||
await MainThread.InvokeOnMainThreadAsync(() => History.ResetWithRange(new List<GeneratedPasswordHistory>()));
|
||||
|
||||
await InitAsync();
|
||||
}
|
||||
|
@ -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<IBroadcasterService>();
|
||||
_logger = ServiceContainer.Resolve<ILogger>();
|
||||
|
||||
_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)
|
||||
{
|
||||
#if IOS
|
||||
ToolbarItems.Add(_closeItem);
|
||||
}
|
||||
#endif
|
||||
ToolbarItems.Add(_selectItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isIos)
|
||||
{
|
||||
#if IOS
|
||||
ToolbarItems.Add(_moreItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
#else
|
||||
ToolbarItems.Add(_historyItem);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
_typePicker.On<Microsoft.Maui.Controls.PlatformConfiguration.iOS>().SetUpdateMode(UpdateMode.WhenFinished);
|
||||
_passwordTypePicker.On<Microsoft.Maui.Controls.PlatformConfiguration.iOS>().SetUpdateMode(UpdateMode.WhenFinished);
|
||||
@ -70,6 +68,8 @@ namespace Bit.App.Pages
|
||||
}
|
||||
|
||||
protected async override void OnAppearing()
|
||||
{
|
||||
try
|
||||
{
|
||||
base.OnAppearing();
|
||||
|
||||
@ -84,10 +84,16 @@ namespace Bit.App.Pages
|
||||
{
|
||||
if (message.Command is ThemeManager.UPDATED_THEME_MESSAGE_KEY)
|
||||
{
|
||||
Device.BeginInvokeOnMainThread(() => _vm.RedrawPassword());
|
||||
MainThread.BeginInvokeOnMainThread(() => _vm.RedrawPassword());
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Exception(ex);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnDisappearing()
|
||||
{
|
||||
@ -100,16 +106,19 @@ 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)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!DoOnce())
|
||||
{
|
||||
@ -123,6 +132,11 @@ namespace Bit.App.Pages
|
||||
await Navigation.PushModalAsync(new Microsoft.Maui.Controls.NavigationPage(page));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Exception(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void Select_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
@ -144,7 +158,7 @@ namespace Bit.App.Pages
|
||||
{
|
||||
await base.UpdateOnThemeChanged();
|
||||
|
||||
await Device.InvokeOnMainThreadAsync(() =>
|
||||
await MainThread.InvokeOnMainThreadAsync(() =>
|
||||
{
|
||||
if (_vm != null)
|
||||
{
|
||||
|
@ -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<ISyncService>("syncService");
|
||||
_vaultTimeoutService = ServiceContainer.Resolve<IVaultTimeoutService>("vaultTimeoutService");
|
||||
_sendService = ServiceContainer.Resolve<ISendService>("sendService");
|
||||
_logger = ServiceContainer.Resolve<ILogger>();
|
||||
|
||||
_vm = BindingContext as SendGroupingsPageViewModel;
|
||||
_vm.Page = this;
|
||||
_vm.MainPage = mainPage;
|
||||
@ -43,25 +46,23 @@ 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)
|
||||
{
|
||||
ToolbarItems.Add(_aboutIconItem);
|
||||
}
|
||||
ToolbarItems.Add(_addItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
#else
|
||||
ToolbarItems.Add(_syncItem);
|
||||
ToolbarItems.Add(_lockItem);
|
||||
ToolbarItems.Add(_aboutTextItem);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
protected override async void OnAppearing()
|
||||
{
|
||||
try
|
||||
{
|
||||
base.OnAppearing();
|
||||
if (_syncService.SyncInProgress)
|
||||
@ -75,12 +76,12 @@ namespace Bit.App.Pages
|
||||
{
|
||||
if (message.Command == "syncStarted")
|
||||
{
|
||||
Device.BeginInvokeOnMainThread(() => IsBusy = true);
|
||||
MainThread.BeginInvokeOnMainThread(() => IsBusy = true);
|
||||
}
|
||||
else if (message.Command == "syncCompleted" || message.Command == "sendUpdated")
|
||||
{
|
||||
await Task.Delay(500);
|
||||
Device.BeginInvokeOnMainThread(() =>
|
||||
await MainThread.InvokeOnMainThreadAsync(() =>
|
||||
{
|
||||
IsBusy = false;
|
||||
if (_vm.LoadedOnce)
|
||||
@ -123,6 +124,12 @@ namespace Bit.App.Pages
|
||||
await CheckAddRequest();
|
||||
}, _mainContent);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Exception(ex);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnDisappearing()
|
||||
{
|
||||
|
@ -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,6 +106,9 @@ namespace Bit.App.Pages
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var authed = await _stateService.IsAuthenticatedAsync();
|
||||
if (!authed)
|
||||
{
|
||||
@ -139,6 +131,13 @@ namespace Bit.App.Pages
|
||||
Loading = true;
|
||||
ShowList = false;
|
||||
SendEnabled = !await AppHelpers.IsSendDisabledByPolicyAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Value.Exception(ex);
|
||||
throw;
|
||||
}
|
||||
|
||||
var groupedSends = new List<SendGroupingsPageListGroup>();
|
||||
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;
|
||||
@ -314,6 +321,8 @@ namespace Bit.App.Pages
|
||||
}
|
||||
|
||||
private async void SendOptionsAsync(SendView send)
|
||||
{
|
||||
try
|
||||
{
|
||||
if ((Page as BaseContentPage).DoOnce())
|
||||
{
|
||||
@ -324,5 +333,11 @@ namespace Bit.App.Pages
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Value.Exception(ex);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ namespace Bit.App.Pages
|
||||
{
|
||||
if (message.Command == "selectSaveFileResult")
|
||||
{
|
||||
Device.BeginInvokeOnMainThread(() =>
|
||||
MainThread.BeginInvokeOnMainThread(() =>
|
||||
{
|
||||
var data = message.Data as Tuple<string, string>;
|
||||
if (data == null)
|
||||
|
@ -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)
|
||||
{
|
||||
#if ANDROID
|
||||
MainThread.BeginInvokeOnMainThread(() =>
|
||||
_emptyPlaceholder.Source = ImageSource.FromFile(ThemeManager.UsingLightTheme ? "empty_login_requests" : "empty_login_requests_dark"));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
{
|
||||
@ -86,6 +87,8 @@ namespace Bit.App.Pages
|
||||
}
|
||||
|
||||
protected override async void OnAppearing()
|
||||
{
|
||||
try
|
||||
{
|
||||
base.OnAppearing();
|
||||
_broadcasterService.Subscribe(nameof(TabsPage), async (message) =>
|
||||
@ -103,6 +106,12 @@ namespace Bit.App.Pages
|
||||
|
||||
await ForcePasswordResetIfNeededAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.LogEvenIfCantBeResolved(ex);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ForcePasswordResetIfNeededAsync()
|
||||
{
|
||||
@ -173,6 +182,8 @@ namespace Bit.App.Pages
|
||||
}
|
||||
|
||||
protected override async void OnCurrentPageChanged()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (CurrentPage is NavigationPage navPage)
|
||||
{
|
||||
@ -192,6 +203,12 @@ namespace Bit.App.Pages
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.LogEvenIfCantBeResolved(ex);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnPageReselected()
|
||||
{
|
||||
|
@ -33,7 +33,7 @@ namespace Bit.App.Pages
|
||||
{
|
||||
if (message.Command == "selectFileResult")
|
||||
{
|
||||
Device.BeginInvokeOnMainThread(() =>
|
||||
MainThread.BeginInvokeOnMainThread(() =>
|
||||
{
|
||||
var data = message.Data as Tuple<byte[], string>;
|
||||
_vm.FileData = data.Item1;
|
||||
|
@ -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
|
||||
{
|
||||
@ -262,9 +263,17 @@ namespace Bit.App.Pages
|
||||
var page = new ScanPage(key =>
|
||||
{
|
||||
MainThread.BeginInvokeOnMainThread(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
await Navigation.PopModalAsync();
|
||||
await _vm.UpdateTotpKeyAsync(key);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LoggerHelper.LogEvenIfCantBeResolved(ex);
|
||||
throw;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -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<string, object> 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<string, string>;
|
||||
if (data == null)
|
||||
|
@ -108,6 +108,8 @@ namespace Bit.App.Pages
|
||||
var previousCts = _searchCancellationTokenSource;
|
||||
var cts = new CancellationTokenSource();
|
||||
Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
List<CipherView> ciphers = null;
|
||||
var searchable = !string.IsNullOrWhiteSpace(searchText) && searchText.Length > 1;
|
||||
@ -155,6 +157,11 @@ namespace Bit.App.Pages
|
||||
ShowNoData = !shouldShowAllWhenEmpty && searchable && Ciphers.Count == 0;
|
||||
ShowList = (searchable || shouldShowAllWhenEmpty) && !ShowNoData;
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Exception(ex);
|
||||
}
|
||||
}, cts.Token);
|
||||
_searchCancellationTokenSource = cts;
|
||||
}
|
||||
|
@ -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<ICipherService>("cipherService");
|
||||
_deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
|
||||
_platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService");
|
||||
_logger = ServiceContainer.Resolve<ILogger>();
|
||||
|
||||
_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)
|
||||
{
|
||||
#if IOS
|
||||
_absLayout.Children.Remove(_fab);
|
||||
ToolbarItems.Add(_addItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
#else
|
||||
ToolbarItems.Add(_syncItem);
|
||||
ToolbarItems.Add(_lockItem);
|
||||
ToolbarItems.Add(_exitItem);
|
||||
}
|
||||
#endif
|
||||
if (deleted || showTotp)
|
||||
{
|
||||
_absLayout.Children.Remove(_fab);
|
||||
@ -80,6 +80,8 @@ namespace Bit.App.Pages
|
||||
}
|
||||
|
||||
protected override async void OnAppearing()
|
||||
{
|
||||
try
|
||||
{
|
||||
base.OnAppearing();
|
||||
if (_syncService.SyncInProgress)
|
||||
@ -184,6 +186,12 @@ namespace Bit.App.Pages
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Exception(ex);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool OnBackButtonPressed()
|
||||
{
|
||||
@ -195,7 +203,9 @@ namespace Bit.App.Pages
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override async void OnDisappearing()
|
||||
protected override void OnDisappearing()
|
||||
{
|
||||
try
|
||||
{
|
||||
base.OnDisappearing();
|
||||
IsBusy = false;
|
||||
@ -204,6 +214,12 @@ namespace Bit.App.Pages
|
||||
_vm.DisableRefreshing();
|
||||
_accountAvatar?.OnDisappearing();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Exception(ex);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private async void RowSelected(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
@ -263,6 +279,8 @@ namespace Bit.App.Pages
|
||||
}
|
||||
|
||||
private async void Search_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _accountListOverlay.HideAsync();
|
||||
if (DoOnce())
|
||||
@ -271,26 +289,54 @@ namespace Bit.App.Pages
|
||||
await Navigation.PushModalAsync(new NavigationPage(page));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Exception(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private async void Sync_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _accountListOverlay.HideAsync();
|
||||
await _vm.SyncAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Exception(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private async void Lock_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _accountListOverlay.HideAsync();
|
||||
await _vaultTimeoutService.LockAsync(true, true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Exception(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private async void Exit_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _accountListOverlay.HideAsync();
|
||||
await _vm.ExitAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Exception(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private async void AddButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
var skipAction = _accountListOverlay.IsVisible && DeviceInfo.Platform == DevicePlatform.Android;
|
||||
await _accountListOverlay.HideAsync();
|
||||
@ -305,6 +351,11 @@ namespace Bit.App.Pages
|
||||
await Navigation.PushModalAsync(new NavigationPage(page));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Exception(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ShowPreviousPageAsync()
|
||||
{
|
||||
|
@ -166,6 +166,9 @@ namespace Bit.App.Pages
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var authed = await _stateService.IsAuthenticatedAsync();
|
||||
if (!authed)
|
||||
{
|
||||
@ -190,6 +193,7 @@ namespace Bit.App.Pages
|
||||
{
|
||||
PageTitle = ShowVaultFilter ? AppResources.Vaults : AppResources.MyVault;
|
||||
}
|
||||
|
||||
_doingLoad = true;
|
||||
LoadedOnce = true;
|
||||
ShowNoData = false;
|
||||
@ -197,10 +201,17 @@ namespace Bit.App.Pages
|
||||
ShowList = false;
|
||||
ShowAddCipherButton = !Deleted;
|
||||
|
||||
_websiteIconsEnabled = await _stateService.GetDisableFaviconAsync() != true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Exception(ex);
|
||||
throw;
|
||||
}
|
||||
|
||||
var groupedItems = new List<GroupingsPageListGroup>();
|
||||
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 (!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
|
||||
return;
|
||||
}
|
||||
|
||||
GroupedItems.ReplaceRange(new List<IGroupingsPageListItem> { new GroupingsPageHeaderListItem(groupedItems[0].Name, groupedItems[0].ItemCount) });
|
||||
GroupedItems.AddRange(items);
|
||||
}
|
||||
else
|
||||
{
|
||||
GroupedItems.Clear();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Exception(ex);
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_doingLoad = false;
|
||||
|
@ -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<PasswordHistoryView>());
|
||||
ShowNoData = History.Count == 0;
|
||||
|
@ -784,13 +784,13 @@
|
||||
<value>Avto-doldurmaq və ya bu elementə baxmaq istəyirsiniz?</value>
|
||||
</data>
|
||||
<data name="BitwardenAutofillServiceMatchConfirm" xml:space="preserve">
|
||||
<value>Bu elementi avto-doldurmaq istədiyinizə əminsiniz? "{0}" ilə tam uyğun gəlmir.</value>
|
||||
<value>Bu elementi avto-doldurmaq istədiyinizə əminsiniz? "{0}" ilə tam uyuşmur.</value>
|
||||
</data>
|
||||
<data name="MatchingItems" xml:space="preserve">
|
||||
<value>Uyğun gələnlər</value>
|
||||
<value>Uyuşan elementlər</value>
|
||||
</data>
|
||||
<data name="PossibleMatchingItems" xml:space="preserve">
|
||||
<value>Uyğun gələ bilənlər</value>
|
||||
<value>Uyuşması mümkün olan elementlər</value>
|
||||
</data>
|
||||
<data name="Search" xml:space="preserve">
|
||||
<value>Axtar</value>
|
||||
@ -1246,10 +1246,10 @@ Skan prosesi avtomatik baş tutacaq.</value>
|
||||
<value>Başlayır</value>
|
||||
</data>
|
||||
<data name="URIMatchDetection" xml:space="preserve">
|
||||
<value>URI uyğunluq aşkarlaması</value>
|
||||
<value>URI uyuşma aşkarlaması</value>
|
||||
</data>
|
||||
<data name="MatchDetection" xml:space="preserve">
|
||||
<value>Uyğunluq aşkarlaması</value>
|
||||
<value>Uyuşmanı aşkarlama</value>
|
||||
<comment>URI match detection for auto-fill.</comment>
|
||||
</data>
|
||||
<data name="YesAndSave" xml:space="preserve">
|
||||
@ -1530,11 +1530,11 @@ Skan prosesi avtomatik baş tutacaq.</value>
|
||||
<comment>Clipboard is the operating system thing where you copy/paste data to on your device.</comment>
|
||||
</data>
|
||||
<data name="DefaultUriMatchDetection" xml:space="preserve">
|
||||
<value>İlkin URI uyğunluq aşkarlaması</value>
|
||||
<value>İlkin URI uyuşma aşkarlaması</value>
|
||||
<comment>Default URI match detection for auto-fill.</comment>
|
||||
</data>
|
||||
<data name="DefaultUriMatchDetectionDescription" xml:space="preserve">
|
||||
<value>Avto-doldurma kimi əməliyyatları icra edərkən giriş etmə prosesi üçün URI uyğunluq aşkarlamasının ilkin yolunu seçin.</value>
|
||||
<value>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.</value>
|
||||
</data>
|
||||
<data name="Theme" xml:space="preserve">
|
||||
<value>Tema</value>
|
||||
@ -2464,7 +2464,7 @@ Skan prosesi avtomatik baş tutacaq.</value>
|
||||
<value>Əlçatımlılıq Xidməti açıqlaması</value>
|
||||
</data>
|
||||
<data name="AccessibilityDisclosureText" xml:space="preserve">
|
||||
<value>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.</value>
|
||||
<value>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.</value>
|
||||
</data>
|
||||
<data name="Accept" xml:space="preserve">
|
||||
<value>Qəbul et</value>
|
||||
@ -2505,7 +2505,7 @@ Bu hesaba keçmək istəyirsiniz?</value>
|
||||
<value>Cihazınıza bir bildiriş göndərildi.</value>
|
||||
</data>
|
||||
<data name="PleaseMakeSureYourVaultIsUnlockedAndTheFingerprintPhraseMatchesOnTheOtherDevice" xml:space="preserve">
|
||||
<value>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.</value>
|
||||
<value>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.</value>
|
||||
</data>
|
||||
<data name="ResendNotification" xml:space="preserve">
|
||||
<value>Bildirişi təkrar göndər</value>
|
||||
@ -2592,13 +2592,13 @@ Bu hesaba keçmək istəyirsiniz?</value>
|
||||
<value>Açarı, mövcud və ya yeni bir elementə əlavə edin</value>
|
||||
</data>
|
||||
<data name="ThereAreNoItemsInYourVaultThatMatchX" xml:space="preserve">
|
||||
<value>Anbarınızda {0} ilə uyğunlaşan heç bir element yoxdur</value>
|
||||
<value>Anbarınızda {0} ilə uyuşan heç bir element yoxdur</value>
|
||||
</data>
|
||||
<data name="SearchForAnItemOrAddANewItem" xml:space="preserve">
|
||||
<value>Bir element axtarın və ya yenisini əlavə edin</value>
|
||||
</data>
|
||||
<data name="ThereAreNoItemsThatMatchTheSearch" xml:space="preserve">
|
||||
<value>Axtarışa uyğun gələn heç bir element yoxdur</value>
|
||||
<value>Axtarışla uyuşan heç bir element yoxdur</value>
|
||||
</data>
|
||||
<data name="US" xml:space="preserve">
|
||||
<value>ABŞ</value>
|
||||
|
@ -878,17 +878,17 @@
|
||||
<comment>The placeholder will show the file size of the attachment. Ex "25 MB"</comment>
|
||||
</data>
|
||||
<data name="AuthenticatorKey" xml:space="preserve">
|
||||
<value>Todennusmenetelmän avain (TOTP)</value>
|
||||
<value>Todennusavain (TOTP)</value>
|
||||
</data>
|
||||
<data name="VerificationCodeTotp" xml:space="preserve">
|
||||
<value>Todennuskoodi (TOTP)</value>
|
||||
<comment>Totp code label</comment>
|
||||
</data>
|
||||
<data name="AuthenticatorKeyAdded" xml:space="preserve">
|
||||
<value>Todennusmenetelmän avain lisätty.</value>
|
||||
<value>Todennusavain on lisätty.</value>
|
||||
</data>
|
||||
<data name="AuthenticatorKeyReadError" xml:space="preserve">
|
||||
<value>Todennusavaimen luku epäonnistui.</value>
|
||||
<value>Todennusavaimen lukeminen ei onnistu.</value>
|
||||
</data>
|
||||
<data name="PointYourCameraAtTheQRCode" xml:space="preserve">
|
||||
<value>Kohdista kamera QR-koodiin.
|
||||
@ -907,7 +907,7 @@ Koodi skannataan automaattisesti.</value>
|
||||
<value>Kopioi TOTP-todennuskoodi</value>
|
||||
</data>
|
||||
<data name="CopyTotpAutomaticallyDescription" xml:space="preserve">
|
||||
<value>Jos kirjautumistieto sisältää kaksivaiheisen TOTP-todennusavaimen, kopioidaan todennuskoodi automaattisesti leikepöydälle automaattisen täytön yhteydessä.</value>
|
||||
<value>Jos kirjautumistieto sisältää kaksivaiheisen todennuksen avaimen, kopioidaan TOTP-todennuskoodi leikepöydälle kohteen automaattisen täytön yhteydessä.</value>
|
||||
</data>
|
||||
<data name="CopyTotpAutomatically" xml:space="preserve">
|
||||
<value>TOTP-koodin kopiointi</value>
|
||||
@ -1853,7 +1853,7 @@ Koodi skannataan automaattisesti.</value>
|
||||
<value>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.</value>
|
||||
</data>
|
||||
<data name="PersonalOwnershipSubmitError" xml:space="preserve">
|
||||
<value>Yrityskäytännön johdosta kohteiden tallennus henkilökohtaiseen holviin ei ole mahdollista. Muuta omistusasetus organisaatiolle ja valitse käytettävissä olevista kokoelmista.</value>
|
||||
<value>Yrityskäytännön vuoksi kohteiden tallennus henkilökohtaiseen holviin ei ole mahdollista. Muuta omistusasetus organisaatiolle ja valitse käytettävissä olevista kokoelmista.</value>
|
||||
</data>
|
||||
<data name="PersonalOwnershipPolicyInEffect" xml:space="preserve">
|
||||
<value>Organisaatiokäytäntö vaikuttaa omistajuusvalintoihisi.</value>
|
||||
@ -2126,7 +2126,7 @@ Koodi skannataan automaattisesti.</value>
|
||||
<value>Varmista, että oletusselaimesi sisältää WebAuthn-tuen ja yritä uudelleen.</value>
|
||||
</data>
|
||||
<data name="ResetPasswordAutoEnrollInviteWarning" xml:space="preserve">
|
||||
<value>Organisaatiolla on käytäntö, joka liittää tilisi automaattisesti salasanan palautusapuun. Liitos sallii organisaation ylläpitäjien vaihtaa pääsalasanasi.</value>
|
||||
<value>Organisaatiolla on yrityskäytäntö, joka liittää tilisi automaattisesti salasanan palautusapuun. Liitos sallii organisaation ylläpitäjien vaihtaa pääsalasanasi.</value>
|
||||
</data>
|
||||
<data name="VaultTimeoutPolicyInEffect" xml:space="preserve">
|
||||
<value>Organisaatiokäytännöt ovat määrittäneet holvisi aikakatkaisun enimmäisajaksi {0} tunti(a) {1} minuutti(a).</value>
|
||||
@ -2273,7 +2273,7 @@ Koodi skannataan automaattisesti.</value>
|
||||
<value>Premium-tilaus vaaditaan</value>
|
||||
</data>
|
||||
<data name="CannotAddAuthenticatorKey" xml:space="preserve">
|
||||
<value>Etkö voi lisätä todennusavainta? </value>
|
||||
<value>Eikä todennusavaimen lisääminen onnistu?</value>
|
||||
</data>
|
||||
<data name="ScanQRCode" xml:space="preserve">
|
||||
<value>Skannaa QR-koodi</value>
|
||||
@ -2282,7 +2282,7 @@ Koodi skannataan automaattisesti.</value>
|
||||
<value>Eikö QR-koodin skannaus onnistu? </value>
|
||||
</data>
|
||||
<data name="AuthenticatorKeyScanner" xml:space="preserve">
|
||||
<value>Todentajan avain</value>
|
||||
<value>Todennusavain</value>
|
||||
</data>
|
||||
<data name="EnterKeyManually" xml:space="preserve">
|
||||
<value>Syötä se manuaalisesti</value>
|
||||
|
@ -885,7 +885,7 @@
|
||||
<comment>Totp code label</comment>
|
||||
</data>
|
||||
<data name="AuthenticatorKeyAdded" xml:space="preserve">
|
||||
<value>Chave de autenticador adicionada.</value>
|
||||
<value>Chave de autenticação adicionada.</value>
|
||||
</data>
|
||||
<data name="AuthenticatorKeyReadError" xml:space="preserve">
|
||||
<value>Não é possível ler a chave de autenticação.</value>
|
||||
|
@ -885,10 +885,10 @@
|
||||
<comment>Totp code label</comment>
|
||||
</data>
|
||||
<data name="AuthenticatorKeyAdded" xml:space="preserve">
|
||||
<value>Ключ проверки подлинности добавлен.</value>
|
||||
<value>Ключ аутентификатора добавлен.</value>
|
||||
</data>
|
||||
<data name="AuthenticatorKeyReadError" xml:space="preserve">
|
||||
<value>Не удается прочитать ключ проверки подлинности.</value>
|
||||
<value>Не удается прочитать ключ аутентификатора.</value>
|
||||
</data>
|
||||
<data name="PointYourCameraAtTheQRCode" xml:space="preserve">
|
||||
<value>Наведите камеру на QR-код.
|
||||
@ -2272,7 +2272,7 @@
|
||||
<value>Требуется подписка Премиум</value>
|
||||
</data>
|
||||
<data name="CannotAddAuthenticatorKey" xml:space="preserve">
|
||||
<value>Не удается добавить ключ проверки подлинности? </value>
|
||||
<value>Не удается добавить ключ аутентификатора? </value>
|
||||
</data>
|
||||
<data name="ScanQRCode" xml:space="preserve">
|
||||
<value>Сканировать QR-код</value>
|
||||
|
@ -858,7 +858,7 @@
|
||||
<comment>"YubiKey" is the product name and should not be translated.</comment>
|
||||
</data>
|
||||
<data name="AddNewAttachment" xml:space="preserve">
|
||||
<value>புதிய இணைப்பை சேர்</value>
|
||||
<value>புதிய இணைப்பைச் சேர்</value>
|
||||
</data>
|
||||
<data name="Attachments" xml:space="preserve">
|
||||
<value>இணைப்புகள்</value>
|
||||
@ -2331,7 +2331,7 @@
|
||||
<value>நேரம்</value>
|
||||
</data>
|
||||
<data name="Near" xml:space="preserve">
|
||||
<value>Near</value>
|
||||
<value>இதற்கருகில்</value>
|
||||
</data>
|
||||
<data name="ConfirmLogIn" xml:space="preserve">
|
||||
<value>உள்நுழைவை உறுதிபடுத்து</value>
|
||||
@ -2772,7 +2772,7 @@
|
||||
<value>இப்போது ஒத்திசை</value>
|
||||
</data>
|
||||
<data name="UnlockOptions" xml:space="preserve">
|
||||
<value>Unlock options</value>
|
||||
<value>பூட்டவிழ்ப்பு விருப்பங்கள்</value>
|
||||
</data>
|
||||
<data name="SessionTimeout" xml:space="preserve">
|
||||
<value>அமர்வு நேரமுடிவு</value>
|
||||
@ -2785,16 +2785,16 @@
|
||||
<comment>A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing.</comment>
|
||||
</data>
|
||||
<data name="OneHourAndOneMinute" xml:space="preserve">
|
||||
<value>One hour and one minute</value>
|
||||
<value>ஒரு மணிநேரம் மற்றும் ஒரு நிமிடம்</value>
|
||||
</data>
|
||||
<data name="OneHourAndXMinute" xml:space="preserve">
|
||||
<value>One hour and {0} minutes</value>
|
||||
<value>ஒரு மணிநேரம் மற்றும் {0} நிமிடங்கள்</value>
|
||||
</data>
|
||||
<data name="XHoursAndOneMinute" xml:space="preserve">
|
||||
<value>{0} hours and one minute</value>
|
||||
<value>{0} மணிநேரம் மற்றும் ஒரு நிமிடம்</value>
|
||||
</data>
|
||||
<data name="XHoursAndYMinutes" xml:space="preserve">
|
||||
<value>{0} hours and {1} minutes</value>
|
||||
<value>{0} மணிநேரம் மற்றும் {1} நிமிடங்கள்</value>
|
||||
</data>
|
||||
<data name="XHours" xml:space="preserve">
|
||||
<value>{0} மணிநேரம்</value>
|
||||
@ -2809,29 +2809,29 @@
|
||||
<value>கூடுதல் தேர்வுகள்</value>
|
||||
</data>
|
||||
<data name="ContinueToWebApp" xml:space="preserve">
|
||||
<value>Continue to web app?</value>
|
||||
<value>வலைச்செயலிக்குத் தொடரவா?</value>
|
||||
</data>
|
||||
<data name="ContinueToX" xml:space="preserve">
|
||||
<value>Continue to {0}?</value>
|
||||
<value>{0}-க்குத் தொடரவா?</value>
|
||||
<comment>The parameter is an URL, like bitwarden.com.</comment>
|
||||
</data>
|
||||
<data name="ContinueToHelpCenter" xml:space="preserve">
|
||||
<value>Continue to Help center?</value>
|
||||
<value>உதவி மையத்திற்குத் தொடரவா?</value>
|
||||
</data>
|
||||
<data name="ContinueToContactSupport" xml:space="preserve">
|
||||
<value>Continue to contact support?</value>
|
||||
<value>ஆதரவைத் தொடர்புகொள்ளத் தொடரவா?</value>
|
||||
</data>
|
||||
<data name="ContinueToAppStore" xml:space="preserve">
|
||||
<value>Continue to app store?</value>
|
||||
</data>
|
||||
<data name="TwoStepLoginDescriptionLong" xml:space="preserve">
|
||||
<value>Make your account more secure by setting up two-step login in the Bitwarden web app.</value>
|
||||
<value>Bitwarden வலைச்செயலியில் இரு-படி உள்நுழைவை அமைத்து உமது கணக்கின் பாதுகாப்பை அதிகரி.</value>
|
||||
</data>
|
||||
<data name="ChangeMasterPasswordDescriptionLong" xml:space="preserve">
|
||||
<value>You can change your master password on the Bitwarden web app.</value>
|
||||
<value>Bitwarden வலைச்செயலியில் உமது பிரதான கடவுச்சொல்லை மாற்றலாம்.</value>
|
||||
</data>
|
||||
<data name="YouCanImportDataToYourVaultOnX" xml:space="preserve">
|
||||
<value>You can import data to your vault on {0}.</value>
|
||||
<value>{0}-இல் உமது பெட்டகத்திற்குத் தரவை இறக்குமதி செய்யலாம்.</value>
|
||||
<comment>The parameter is an URL, like vault.bitwarden.com.</comment>
|
||||
</data>
|
||||
<data name="LearnMoreAboutHowToUseBitwardenOnTheHelpCenter" xml:space="preserve">
|
||||
|
@ -553,7 +553,7 @@
|
||||
<value>Дія після часу очікування сховища</value>
|
||||
</data>
|
||||
<data name="VaultTimeoutLogOutConfirmation" xml:space="preserve">
|
||||
<value>Вихід скасує всі права доступу до вашого сховища і вимагатиме авторизації після завершення часу очікування. Ви дійсно хочете використати цей параметр?</value>
|
||||
<value>Вихід скасує всі права доступу до вашого сховища і вимагатиме автентифікацію після завершення часу очікування. Ви дійсно хочете використати цей параметр?</value>
|
||||
</data>
|
||||
<data name="LoggingIn" xml:space="preserve">
|
||||
<value>Вхід...</value>
|
||||
@ -721,7 +721,7 @@
|
||||
<value>Веб сховище Bitwarden</value>
|
||||
</data>
|
||||
<data name="Lost2FAApp" xml:space="preserve">
|
||||
<value>Втратили доступ до програми перевірки?</value>
|
||||
<value>Втратили доступ до програми автентифікації?</value>
|
||||
</data>
|
||||
<data name="Items" xml:space="preserve">
|
||||
<value>Записи</value>
|
||||
@ -806,11 +806,11 @@
|
||||
<comment>Message shown when trying to launch an app that does not exist on the user's device.</comment>
|
||||
</data>
|
||||
<data name="AuthenticatorAppTitle" xml:space="preserve">
|
||||
<value>Програма авторизації</value>
|
||||
<value>Програма автентифікації</value>
|
||||
<comment>For 2FA</comment>
|
||||
</data>
|
||||
<data name="EnterVerificationCodeApp" xml:space="preserve">
|
||||
<value>Введіть 6-значний код підтвердження з програми авторизації.</value>
|
||||
<value>Введіть 6-значний код підтвердження з програми автентифікації.</value>
|
||||
<comment>For 2FA</comment>
|
||||
</data>
|
||||
<data name="EnterVerificationCodeEmail" xml:space="preserve">
|
||||
@ -822,7 +822,7 @@
|
||||
<comment>For 2FA whenever there are no available providers on this device.</comment>
|
||||
</data>
|
||||
<data name="NoTwoStepAvailable" xml:space="preserve">
|
||||
<value>Цей обліковий запис має увімкнену двоетапну перевірку, однак, жоден із налаштованих провайдерів не підтримується на цьому пристрої. Будь ласка, скористайтеся підтримуваним пристроєм або додайте інших провайдерів, які мають кращу підтримку різних пристроїв (наприклад, програму авторизації).</value>
|
||||
<value>Цей обліковий запис має увімкнену двоетапну перевірку, однак жоден із налаштованих провайдерів не підтримується на цьому пристрої. Будь ласка, скористайтеся підтримуваним пристроєм або додайте інших провайдерів, які мають кращу підтримку різних пристроїв (наприклад, програму автентифікації).</value>
|
||||
</data>
|
||||
<data name="RecoveryCodeTitle" xml:space="preserve">
|
||||
<value>Код відновлення</value>
|
||||
@ -878,17 +878,17 @@
|
||||
<comment>The placeholder will show the file size of the attachment. Ex "25 MB"</comment>
|
||||
</data>
|
||||
<data name="AuthenticatorKey" xml:space="preserve">
|
||||
<value>Ключ авторизації (TOTP)</value>
|
||||
<value>Ключ автентифікації (TOTP)</value>
|
||||
</data>
|
||||
<data name="VerificationCodeTotp" xml:space="preserve">
|
||||
<value>Код підтвердження (TOTP)</value>
|
||||
<comment>Totp code label</comment>
|
||||
</data>
|
||||
<data name="AuthenticatorKeyAdded" xml:space="preserve">
|
||||
<value>Ключ авторизації додано.</value>
|
||||
<value>Ключ автентифікації додано.</value>
|
||||
</data>
|
||||
<data name="AuthenticatorKeyReadError" xml:space="preserve">
|
||||
<value>Не вдається прочитати ключ авторизації.</value>
|
||||
<value>Не вдається прочитати ключ автентифікації.</value>
|
||||
</data>
|
||||
<data name="PointYourCameraAtTheQRCode" xml:space="preserve">
|
||||
<value>Наведіть свою камеру на QR-код.
|
||||
@ -907,7 +907,7 @@
|
||||
<value>Копіювати TOTP</value>
|
||||
</data>
|
||||
<data name="CopyTotpAutomaticallyDescription" xml:space="preserve">
|
||||
<value>Якщо запис має ключ авторизації, копіювати код підтвердження TOTP до буфера обміну під час автозаповнення.</value>
|
||||
<value>Якщо запис має ключ автентифікації, копіювати код підтвердження TOTP до буфера обміну під час автозаповнення.</value>
|
||||
</data>
|
||||
<data name="CopyTotpAutomatically" xml:space="preserve">
|
||||
<value>Автоматично копіювати коди TOTP</value>
|
||||
@ -2110,13 +2110,13 @@
|
||||
<value>FIDO2 WebAuthn</value>
|
||||
</data>
|
||||
<data name="Fido2Instruction" xml:space="preserve">
|
||||
<value>Щоб продовжити, приготуйте свій увімкнений ключ безпеки FIDO2 WebAuthn, потім дотримуйтесь настанов після натискання "Авторизація WebAuthn" на наступному екрані.</value>
|
||||
<value>Щоб продовжити, приготуйте свій ключ безпеки FIDO2 WebAuthn, потім дотримуйтесь настанов після натискання "Автентифікація WebAuthn" на наступному екрані.</value>
|
||||
</data>
|
||||
<data name="Fido2Desc" xml:space="preserve">
|
||||
<value>Авторизація з використанням FIDO2 WebAuthn. Ви можете авторизуватися за допомогою зовнішнього ключа безпеки.</value>
|
||||
<value>Автентифікація з використанням FIDO2 WebAuthn. Ви можете пройти автентифікацію за допомогою зовнішнього ключа безпеки.</value>
|
||||
</data>
|
||||
<data name="Fido2AuthenticateWebAuthn" xml:space="preserve">
|
||||
<value>Авторизація WebAuthn</value>
|
||||
<value>Автентифікація WebAuthn</value>
|
||||
</data>
|
||||
<data name="Fido2ReturnToApp" xml:space="preserve">
|
||||
<value>Повернутися до програми</value>
|
||||
@ -2272,7 +2272,7 @@
|
||||
<value>Необхідна передплата преміум</value>
|
||||
</data>
|
||||
<data name="CannotAddAuthenticatorKey" xml:space="preserve">
|
||||
<value>Не вдається додати ключ авторизації? </value>
|
||||
<value>Не вдається додати ключ автентифікації? </value>
|
||||
</data>
|
||||
<data name="ScanQRCode" xml:space="preserve">
|
||||
<value>Сканувати QR-код</value>
|
||||
@ -2281,7 +2281,7 @@
|
||||
<value>Не вдається сканувати QR-код? </value>
|
||||
</data>
|
||||
<data name="AuthenticatorKeyScanner" xml:space="preserve">
|
||||
<value>Ключ авторизації</value>
|
||||
<value>Ключ автентифікації</value>
|
||||
</data>
|
||||
<data name="EnterKeyManually" xml:space="preserve">
|
||||
<value>Введіть ключ вручну</value>
|
||||
|
@ -885,17 +885,17 @@
|
||||
<comment>Totp code label</comment>
|
||||
</data>
|
||||
<data name="AuthenticatorKeyAdded" xml:space="preserve">
|
||||
<value>验证器密钥已添加。</value>
|
||||
<value>已添加验证器密钥。</value>
|
||||
</data>
|
||||
<data name="AuthenticatorKeyReadError" xml:space="preserve">
|
||||
<value>无法读取验证器密钥。</value>
|
||||
</data>
|
||||
<data name="PointYourCameraAtTheQRCode" xml:space="preserve">
|
||||
<value>将您的摄像头对准 QR 码。
|
||||
<value>将您的摄像头对准二维码。
|
||||
扫描将自动完成。</value>
|
||||
</data>
|
||||
<data name="ScanQrTitle" xml:space="preserve">
|
||||
<value>扫描 QR 码</value>
|
||||
<value>扫描二维码</value>
|
||||
</data>
|
||||
<data name="Camera" xml:space="preserve">
|
||||
<value>相机</value>
|
||||
@ -2275,10 +2275,10 @@
|
||||
<value>无法添加验证器密钥?</value>
|
||||
</data>
|
||||
<data name="ScanQRCode" xml:space="preserve">
|
||||
<value>扫描 QR 码</value>
|
||||
<value>扫描二维码</value>
|
||||
</data>
|
||||
<data name="CannotScanQRCode" xml:space="preserve">
|
||||
<value>无法扫描 QR 码吗? </value>
|
||||
<value>无法扫描二维码吗? </value>
|
||||
</data>
|
||||
<data name="AuthenticatorKeyScanner" xml:space="preserve">
|
||||
<value>验证器密钥</value>
|
||||
|
@ -631,7 +631,7 @@ namespace Bit.Core.Services
|
||||
|
||||
public async Task<SsoPrevalidateResponse> 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);
|
||||
|
@ -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<UIStoryboard> _storyboard = new Lazy<UIStoryboard>(() => 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
|
@ -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()
|
||||
{
|
||||
|
@ -11,7 +11,7 @@
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.8bit.bitwarden.autofill</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>2024.1.0</string>
|
||||
<string>2024.1.1</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>CFBundleLocalizations</key>
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
<EnableDefaultCompileItems>False</EnableDefaultCompileItems>
|
||||
|
||||
<DefineConstants>$(DefineConstants);ENABLED_TAP_GESTURE_RECOGNIZER_MAUI_EMBEDDED_WORKAROUND</DefineConstants>
|
||||
<DefineConstants>$(DefineConstants)</DefineConstants>
|
||||
|
||||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">12.0</SupportedOSPlatformVersion>
|
||||
</PropertyGroup>
|
||||
@ -83,7 +83,6 @@
|
||||
<Compile Include="Models\Context.cs" />
|
||||
<BundleResource Include="Resources\MaterialIcons_Regular.ttf" />
|
||||
<BundleResource Include="Resources\bwi-font.ttf" />
|
||||
<Compile Include="CredentialProviderViewController.TapGestureHack.cs" />
|
||||
<Compile Include="CredentialProviderViewController.Passkeys.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@ -123,13 +122,13 @@
|
||||
<BundleResource Include="Resources\logo_white%403x.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BundleResource Include="..\iOS\Resources\more_vert.png">
|
||||
<BundleResource Include="..\App\Platforms\iOS\Resources\more_vert.png">
|
||||
<Link>Resources\more_vert.png</Link>
|
||||
</BundleResource>
|
||||
<BundleResource Include="..\iOS\Resources\more_vert%402x.png">
|
||||
<BundleResource Include="..\App\Platforms\iOS\Resources\more_vert%402x.png">
|
||||
<Link>Resources\more_vert%402x.png</Link>
|
||||
</BundleResource>
|
||||
<BundleResource Include="..\iOS\Resources\more_vert%403x.png">
|
||||
<BundleResource Include="..\App\Platforms\iOS\Resources\more_vert%403x.png">
|
||||
<Link>Resources\more_vert%403x.png</Link>
|
||||
</BundleResource>
|
||||
</ItemGroup>
|
||||
|
@ -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;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ namespace Bit.iOS.Core.Services
|
||||
|
||||
var dictArr = new NSDictionary<NSString, NSObject>[1];
|
||||
dictArr[0] = new NSDictionary<NSString, NSObject>(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
|
||||
|
@ -11,7 +11,7 @@
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.8bit.bitwarden.find-login-action-extension</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>2024.1.0</string>
|
||||
<string>2024.1.1</string>
|
||||
<key>CFBundleLocalizations</key>
|
||||
<array>
|
||||
<string>en</string>
|
||||
|
@ -100,13 +100,13 @@
|
||||
<BundleResource Include="Resources\yubikey.png" />
|
||||
<BundleResource Include="Resources\yubikey%403x.png" />
|
||||
<BundleResource Include="Resources\yubikey%402x.png" />
|
||||
<BundleResource Include="..\iOS\Resources\more_vert.png">
|
||||
<BundleResource Include="..\App\Platforms\iOS\Resources\more_vert.png">
|
||||
<Link>Resources\more_vert.png</Link>
|
||||
</BundleResource>
|
||||
<BundleResource Include="..\iOS\Resources\more_vert%402x.png">
|
||||
<BundleResource Include="..\App\Platforms\iOS\Resources\more_vert%402x.png">
|
||||
<Link>Resources\more_vert%402x.png</Link>
|
||||
</BundleResource>
|
||||
<BundleResource Include="..\iOS\Resources\more_vert%403x.png">
|
||||
<BundleResource Include="..\App\Platforms\iOS\Resources\more_vert%403x.png">
|
||||
<Link>Resources\more_vert%403x.png</Link>
|
||||
</BundleResource>
|
||||
</ItemGroup>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>XPC!</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>2024.1.0</string>
|
||||
<string>2024.1.1</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>MinimumOSVersion</key>
|
||||
|
@ -70,37 +70,37 @@
|
||||
<Compile Include="LoadingViewController.TapGestureHack.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BundleResource Include="..\iOS\Resources\logo_white%403x.png">
|
||||
<BundleResource Include="..\App\Platforms\iOS\Resources\logo_white%403x.png">
|
||||
<Link>Resources\logo_white%403x.png</Link>
|
||||
</BundleResource>
|
||||
<BundleResource Include="..\iOS\Resources\logo_white%402x.png">
|
||||
<BundleResource Include="..\App\Platforms\iOS\Resources\logo_white%402x.png">
|
||||
<Link>Resources\logo_white%402x.png</Link>
|
||||
</BundleResource>
|
||||
<BundleResource Include="..\iOS\Resources\logo_white.png">
|
||||
<BundleResource Include="..\App\Platforms\iOS\Resources\logo_white.png">
|
||||
<Link>Resources\logo_white.png</Link>
|
||||
</BundleResource>
|
||||
<BundleResource Include="..\iOS\Resources\logo%403x.png">
|
||||
<BundleResource Include="..\App\Platforms\iOS\Resources\logo%403x.png">
|
||||
<Link>Resources\logo%403x.png</Link>
|
||||
</BundleResource>
|
||||
<BundleResource Include="..\iOS\Resources\logo%402x.png">
|
||||
<BundleResource Include="..\App\Platforms\iOS\Resources\logo%402x.png">
|
||||
<Link>Resources\logo%402x.png</Link>
|
||||
</BundleResource>
|
||||
<BundleResource Include="..\iOS\Resources\logo.png">
|
||||
<BundleResource Include="..\App\Platforms\iOS\Resources\logo.png">
|
||||
<Link>Resources\logo.png</Link>
|
||||
</BundleResource>
|
||||
<BundleResource Include="..\iOS\Resources\more_vert.png">
|
||||
<BundleResource Include="..\App\Platforms\iOS\Resources\more_vert.png">
|
||||
<Link>Resources\more_vert.png</Link>
|
||||
</BundleResource>
|
||||
<BundleResource Include="..\iOS\Resources\more_vert%402x.png">
|
||||
<BundleResource Include="..\App\Platforms\iOS\Resources\more_vert%402x.png">
|
||||
<Link>Resources\more_vert%402x.png</Link>
|
||||
</BundleResource>
|
||||
<BundleResource Include="..\iOS\Resources\more_vert%403x.png">
|
||||
<BundleResource Include="..\App\Platforms\iOS\Resources\more_vert%403x.png">
|
||||
<Link>Resources\more_vert%403x.png</Link>
|
||||
</BundleResource>
|
||||
<BundleResource Include="..\iOS\Resources\bwi-font.ttf">
|
||||
<BundleResource Include="..\Core\Resources\Fonts\bwi-font.ttf">
|
||||
<Link>Resources\bwi-font.ttf</Link>
|
||||
</BundleResource>
|
||||
<BundleResource Include="..\iOS\Resources\MaterialIcons_Regular.ttf">
|
||||
<BundleResource Include="..\Core\Resources\Fonts\MaterialIcons_Regular.ttf">
|
||||
<Link>Resources\MaterialIcons_Regular.ttf</Link>
|
||||
</BundleResource>
|
||||
</ItemGroup>
|
||||
|
@ -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<IDeepLinkContext> _deepLinkContext = new LazyResolve<IDeepLinkContext>();
|
||||
|
||||
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
|
||||
{
|
||||
Forms.Init();
|
||||
InitApp();
|
||||
|
||||
_deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
|
||||
_messagingService = ServiceContainer.Resolve<IMessagingService>("messagingService");
|
||||
_broadcasterService = ServiceContainer.Resolve<IBroadcasterService>("broadcasterService");
|
||||
_storageService = ServiceContainer.Resolve<IStorageService>("storageService");
|
||||
_stateService = ServiceContainer.Resolve<IStateService>("stateService");
|
||||
_eventService = ServiceContainer.Resolve<IEventService>("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<bool?>(
|
||||
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<string, object> 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<UIBackgroundFetchResult> 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<INativeLogService>("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<IDeviceActionService>("deviceActionService");
|
||||
ServiceContainer.Init(deviceActionService.DeviceUserAgent, Constants.ClearCiphersCacheKey,
|
||||
Constants.iOSAllClearCipherCacheKeys);
|
||||
iOSCoreHelpers.InitLogger();
|
||||
iOSCoreHelpers.RegisterFinallyBeforeBootstrap();
|
||||
|
||||
_pushHandler = new iOSPushNotificationHandler(
|
||||
ServiceContainer.Resolve<IPushNotificationListenerService>("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<IPushNotificationListenerService>(
|
||||
"pushNotificationListenerService", notificationListenerService);
|
||||
var iosPushNotificationService = new iOSPushNotificationService();
|
||||
ServiceContainer.Register<IPushNotificationService>(
|
||||
"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<string, string>();
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.developer.authentication-services.autofill-credential-provider</key>
|
||||
<true/>
|
||||
<key>com.apple.security.application-groups</key>
|
||||
<array>
|
||||
<string>group.com.8bit.bitwarden</string>
|
||||
</array>
|
||||
<key>keychain-access-groups</key>
|
||||
<array>
|
||||
<string>$(AppIdentifierPrefix)com.8bit.bitwarden</string>
|
||||
</array>
|
||||
<key>com.apple.developer.ubiquity-container-identifiers</key>
|
||||
<array>
|
||||
<string>iCloud.$(CFBundleIdentifier)</string>
|
||||
</array>
|
||||
<key>com.apple.developer.nfc.readersession.formats</key>
|
||||
<array>
|
||||
<string>NDEF</string>
|
||||
<string>TAG</string>
|
||||
</array>
|
||||
<key>com.apple.developer.associated-domains</key>
|
||||
<array>
|
||||
<string>webcredentials:bitwarden.com</string>
|
||||
</array>
|
||||
<key>aps-environment</key>
|
||||
<string>development</string>
|
||||
</dict>
|
||||
</plist>
|
@ -1,141 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>11.0</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>Bitwarden</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>Bitwarden</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.8bit.bitwarden</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>2024.1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>CFBundleIconName</key>
|
||||
<string>AppIcon</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>bitwarden</string>
|
||||
<string>org-appextension-feature-password-management</string>
|
||||
</array>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>com.8bit.bitwarden.url</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>com.8bit.bitwarden</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>otpauth</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleLocalizations</key>
|
||||
<array>
|
||||
<string>en</string>
|
||||
<string>es</string>
|
||||
<string>zh-Hans</string>
|
||||
<string>zh-Hant</string>
|
||||
<string>pt-PT</string>
|
||||
<string>pt-BR</string>
|
||||
<string>sv</string>
|
||||
<string>sk</string>
|
||||
<string>it</string>
|
||||
<string>fi</string>
|
||||
<string>fr</string>
|
||||
<string>ro</string>
|
||||
<string>id</string>
|
||||
<string>hr</string>
|
||||
<string>hu</string>
|
||||
<string>nl</string>
|
||||
<string>tr</string>
|
||||
<string>uk</string>
|
||||
<string>de</string>
|
||||
<string>dk</string>
|
||||
<string>cz</string>
|
||||
<string>nb</string>
|
||||
<string>ja</string>
|
||||
<string>et</string>
|
||||
<string>vi</string>
|
||||
<string>pl</string>
|
||||
<string>ko</string>
|
||||
<string>fa</string>
|
||||
<string>ru</string>
|
||||
<string>be</string>
|
||||
<string>bg</string>
|
||||
<string>ca</string>
|
||||
<string>cs</string>
|
||||
<string>el</string>
|
||||
<string>th</string>
|
||||
</array>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>UIDeviceFamily</key>
|
||||
<array>
|
||||
<integer>1</integer>
|
||||
<integer>2</integer>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile~ipad</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<false/>
|
||||
<key>UIBackgroundModes</key>
|
||||
<array>
|
||||
<string>remote-notification</string>
|
||||
</array>
|
||||
<key>UIStatusBarHidden</key>
|
||||
<true/>
|
||||
<key>UIAppFonts</key>
|
||||
<array>
|
||||
<string>bwi-font.ttf</string>
|
||||
<string>MaterialIcons_Regular.ttf</string>
|
||||
</array>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<dict>
|
||||
<key>arm64</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||
<true/>
|
||||
<key>XSAppIconAssets</key>
|
||||
<string>Resources/Assets.xcassets/AppIcons.appiconset</string>
|
||||
<key>ITSAppUsesNonExemptEncryption</key>
|
||||
<true/>
|
||||
<key>ITSEncryptionExportComplianceCode</key>
|
||||
<string>ecf076d3-4824-4d7b-b716-2a9a47d7d296</string>
|
||||
<key>NSPhotoLibraryUsageDescription</key>
|
||||
<string>This app does not require access to the photo library.</string>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>Scan QR codes</string>
|
||||
<key>NSFaceIDUsageDescription</key>
|
||||
<string>Use Face ID to unlock your vault.</string>
|
||||
<key>NFCReaderUsageDescription</key>
|
||||
<string>Use Yubikeys for two-facor authentication.</string>
|
||||
</dict>
|
||||
</plist>
|
@ -1,91 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="6211" systemVersion="14A298i" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="5">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6204"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<scene sceneID="4">
|
||||
<objects>
|
||||
<viewController id="5" sceneMemberID="viewController" customClass="LaunchScreenViewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="2"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="3"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="6">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" id="16" translatesAutoresizingMaskIntoConstraints="NO" image="LaunchScreen">
|
||||
<rect key="frame" x="159" y="248" width="282" height="44"/>
|
||||
</imageView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint id="19" firstItem="16" firstAttribute="centerY" secondItem="6" secondAttribute="centerY" constant="-30"/>
|
||||
<constraint id="20" firstItem="6" firstAttribute="centerX" secondItem="16" secondAttribute="centerX"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="7" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="-54" y="0.0"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
<resources>
|
||||
<image name="Default.png" width="320" height="480"/>
|
||||
<image name="fa-cogs.png" width="22" height="22"/>
|
||||
<image name="fa-lock.png" width="22" height="22"/>
|
||||
<image name="fa-refresh.png" width="22" height="22"/>
|
||||
<image name="fa_folder_open.png" width="14" height="14"/>
|
||||
<image name="Icon-120.png" width="120" height="120"/>
|
||||
<image name="Icon-152.png" width="152" height="152"/>
|
||||
<image name="Icon-16.png" width="16" height="16"/>
|
||||
<image name="Icon-24.png" width="24" height="24"/>
|
||||
<image name="Icon-32.png" width="32" height="32"/>
|
||||
<image name="Icon-40.png" width="40" height="40"/>
|
||||
<image name="Icon-60.png" width="60" height="60"/>
|
||||
<image name="Icon-64.png" width="64" height="64"/>
|
||||
<image name="Icon-72.png" width="72" height="72"/>
|
||||
<image name="Icon-76.png" width="76" height="76"/>
|
||||
<image name="Icon-Small-40.png" width="40" height="40"/>
|
||||
<image name="Icon-Small-50.png" width="50" height="50"/>
|
||||
<image name="Icon-Small.png" width="29" height="29"/>
|
||||
<image name="Icon.png" width="57" height="57"/>
|
||||
<image name="ion_chevron_right.png" width="14" height="14"/>
|
||||
<image name="ion_plus.png" width="22" height="22"/>
|
||||
<image name="LaunchScreen" width="282" height="44"/>
|
||||
<image name="cogs.png" width="29" height="29"/>
|
||||
<image name="eye.png" width="22" height="22"/>
|
||||
<image name="eye_slash.png" width="22" height="22"/>
|
||||
<image name="more.png" width="28" height="28"/>
|
||||
<image name="more_selected.png" width="28" height="28"/>
|
||||
<image name="plus.png" width="18" height="18"/>
|
||||
<image name="star.png" width="25" height="25"/>
|
||||
<image name="cloudup.png" width="44" height="44"/>
|
||||
<image name="envelope.png" width="18" height="18"/>
|
||||
<image name="globe.png" width="44" height="44"/>
|
||||
<image name="lightbulb-o.png" width="18" height="18"/>
|
||||
<image name="lock.png" width="18" height="18"/>
|
||||
<image name="refresh.png" width="44" height="44"/>
|
||||
<image name="upload.png" width="44" height="44"/>
|
||||
<image name="user.png" width="18" height="18"/>
|
||||
<image name="wrench.png" width="22" height="22"/>
|
||||
<image name="camera.png" width="22" height="22"/>
|
||||
<image name="download.png" width="18" height="18"/>
|
||||
<image name="ext-act.png" width="290" height="252"/>
|
||||
<image name="ext-more.png" width="290" height="252"/>
|
||||
<image name="ext-use.png" width="290" height="252"/>
|
||||
<image name="fa_lock.png" width="25" height="25"/>
|
||||
<image name="fingerprint.png" width="91" height="92"/>
|
||||
<image name="folder.png" width="18" height="18"/>
|
||||
<image name="Icon-83.5.png" width="83.5" height="83.5"/>
|
||||
<image name="lightbulb.png" width="18" height="18"/>
|
||||
<image name="paperclip.png" width="14" height="14"/>
|
||||
<image name="photo.png" width="22" height="22"/>
|
||||
<image name="share.png" width="14" height="14"/>
|
||||
<image name="share_tools.png" width="44" height="44"/>
|
||||
<image name="tools.png" width="26" height="26"/>
|
||||
<image name="trash.png" width="18" height="18"/>
|
||||
<image name="yubikey.png" width="266" height="160"/>
|
||||
</resources>
|
||||
</document>
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
@ -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")]
|
@ -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"
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 738 B |
Before Width: | Height: | Size: 899 B |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 2.0 KiB |
@ -1,6 +0,0 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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
|
Before Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 83 KiB |
Before Width: | Height: | Size: 136 KiB |
Before Width: | Height: | Size: 486 B |
Before Width: | Height: | Size: 931 B |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 486 B |
Before Width: | Height: | Size: 931 B |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 71 KiB |
Before Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 70 KiB |
Before Width: | Height: | Size: 17 KiB |