mirror of
https://github.com/bitwarden/android.git
synced 2024-12-28 03:48:31 +03:00
PM-3349 PRM-3350 Replaced XZing with Camera.MAUI for QRCodes
This commit is contained in:
parent
62213c0aaf
commit
f1d59210f9
7 changed files with 134 additions and 159 deletions
|
@ -71,6 +71,7 @@
|
|||
<AndroidNativeLibrary Include="Platforms\Android\lib\x86_64\libargon2.so" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Camera.MAUI" Version="1.4.4" />
|
||||
<PackageReference Include="Microsoft.Maui.Controls" Version="$(MauiVersion)" />
|
||||
<PackageReference Include="Microsoft.Maui.Controls.Compatibility" Version="$(MauiVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="7.0.0" />
|
||||
|
@ -88,9 +89,7 @@
|
|||
<PackageReference Include="Plugin.Fingerprint" Version="2.1.5" />
|
||||
<PackageReference Include="SkiaSharp.Views.Maui.Controls" Version="2.88.4-preview.84" />
|
||||
<PackageReference Include="SkiaSharp.Views.Maui.Controls.Compatibility" Version="2.88.4-preview.84" />
|
||||
<PackageReference Include="ZXing.Net.Maui" Version="0.3.0-preview.1" />
|
||||
<PackageReference Include="FFImageLoadingCompat.Maui" Version="0.1.1" />
|
||||
<PackageReference Include="ZXing.Net.Maui.Controls" Version="0.3.0-preview.1" />
|
||||
<PackageReference Include="AsyncAwaitBestPractices.MVVM" Version="6.0.6" />
|
||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.1" />
|
||||
<PackageReference Include="PCLCrypto" Version="2.0.147" />
|
||||
|
|
|
@ -45,11 +45,11 @@
|
|||
<EmbeddedResource Include="Resources\public_suffix_list.dat" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Camera.MAUI" Version="1.4.4" />
|
||||
<PackageReference Include="Microsoft.Maui.Controls" Version="$(MauiVersion)" />
|
||||
<PackageReference Include="Microsoft.Maui.Controls.Compatibility" Version="$(MauiVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="7.0.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="ZXing.Net.Maui.Controls" Version="0.3.0-preview.1" />
|
||||
<PackageReference Include="MessagePack" Version="2.5.124" />
|
||||
<PackageReference Include="CsvHelper" Version="30.0.1" />
|
||||
<PackageReference Include="LiteDB" Version="5.0.17" />
|
||||
|
@ -70,16 +70,12 @@
|
|||
<PackageReference Include="Portable.BouncyCastle" Version="1.9.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">
|
||||
<PackageReference Include="ZXing.Net.Maui" Version="0.3.0-preview.1" />
|
||||
<PackageReference Include="Xamarin.GooglePlayServices.SafetyNet" Version="118.0.1.5" />
|
||||
<PackageReference Include="Plugin.CurrentActivity" Version="2.1.0.4" />
|
||||
<PackageReference Include="Xamarin.AndroidX.AutoFill" Version="1.1.0.18" />
|
||||
<PackageReference Include="Xamarin.Firebase.Messaging" Version="123.1.2.2" />
|
||||
<PackageReference Include="Xamarin.AndroidX.Activity.Ktx" Version="1.7.2.1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">
|
||||
<PackageReference Include="ZXing.Net.Maui" Version="0.3.0-preview.1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Services\Logging\" />
|
||||
<Folder Include="Attributes\" />
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
using CommunityToolkit.Maui;
|
||||
using Camera.MAUI;
|
||||
using CommunityToolkit.Maui;
|
||||
using FFImageLoading.Maui;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Maui.Controls.Compatibility.Hosting;
|
||||
using SkiaSharp.Views.Maui.Controls.Hosting;
|
||||
using ZXing.Net.Maui.Controls;
|
||||
using AppEffects = Bit.App.Effects;
|
||||
|
||||
namespace Bit.Core;
|
||||
|
@ -20,7 +20,7 @@ public static class MauiProgram
|
|||
builder
|
||||
.UseMauiCommunityToolkit()
|
||||
.UseMauiCompatibility()
|
||||
.UseBarcodeReader()
|
||||
.UseMauiCameraView()
|
||||
.UseSkiaSharp()
|
||||
.UseFFImageLoading()
|
||||
.ConfigureEffects(effects =>
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.App.Abstractions;
|
||||
using Bit.App.Abstractions;
|
||||
using Bit.App.Models;
|
||||
using Bit.Core.Resources.Localization;
|
||||
using Bit.App.Utilities;
|
||||
|
@ -9,8 +7,6 @@ using Bit.Core.Enums;
|
|||
using Bit.Core.Utilities;
|
||||
using Microsoft.Maui.Controls.PlatformConfiguration;
|
||||
using Microsoft.Maui.Controls.PlatformConfiguration.iOSSpecific;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
|
||||
namespace Bit.App.Pages
|
||||
{
|
||||
|
@ -62,14 +58,12 @@ namespace Bit.App.Pages
|
|||
_vm.CipherDetailsPage = cipherDetailsPage;
|
||||
_vm.Init();
|
||||
SetActivityIndicator();
|
||||
// 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 (_vm.EditMode && !_vm.CloneMode && Device.RuntimePlatform == Device.Android)
|
||||
if (_vm.EditMode && !_vm.CloneMode && DeviceInfo.Platform == DevicePlatform.Android)
|
||||
{
|
||||
ToolbarItems.Add(_attachmentsItem);
|
||||
ToolbarItems.Add(_deleteItem);
|
||||
}
|
||||
// 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 (DeviceInfo.Platform == DevicePlatform.iOS)
|
||||
{
|
||||
ToolbarItems.Add(_closeItem);
|
||||
if (_vm.EditMode && !_vm.CloneMode)
|
||||
|
@ -267,7 +261,7 @@ namespace Bit.App.Pages
|
|||
{
|
||||
var page = new ScanPage(key =>
|
||||
{
|
||||
Device.BeginInvokeOnMainThread(async () =>
|
||||
MainThread.BeginInvokeOnMainThread(async () =>
|
||||
{
|
||||
await Navigation.PopModalAsync();
|
||||
await _vm.UpdateTotpKeyAsync(key);
|
||||
|
@ -335,8 +329,7 @@ namespace Bit.App.Pages
|
|||
if (_vm.Cipher.Type == CipherType.Login && !_fromAutofill && !addLoginShown.GetValueOrDefault())
|
||||
{
|
||||
await _stateService.SetAddSitePromptShownAsync(true);
|
||||
// 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 (DeviceInfo.Platform == DevicePlatform.iOS)
|
||||
{
|
||||
if (_deviceActionService.SystemMajorVersion() < 12)
|
||||
{
|
||||
|
@ -349,9 +342,9 @@ namespace Bit.App.Pages
|
|||
AppResources.BitwardenAutofillAlert2, AppResources.Ok);
|
||||
}
|
||||
}
|
||||
else if (Device.RuntimePlatform == Device.Android &&
|
||||
!_autofillHandler.AutofillAccessibilityServiceRunning() &&
|
||||
!_autofillHandler.AutofillServiceEnabled())
|
||||
else if (DeviceInfo.Platform == DevicePlatform.Android &&
|
||||
!_autofillHandler.AutofillAccessibilityServiceRunning() &&
|
||||
!_autofillHandler.AutofillServiceEnabled())
|
||||
{
|
||||
await DisplayAlert(AppResources.BitwardenAutofillService,
|
||||
AppResources.BitwardenAutofillServiceAlert2, AppResources.Ok);
|
||||
|
@ -362,8 +355,7 @@ namespace Bit.App.Pages
|
|||
|
||||
private void AdjustToolbar()
|
||||
{
|
||||
// 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 ((_vm.EditMode || _vm.CloneMode) && Device.RuntimePlatform == Device.Android)
|
||||
if ((_vm.EditMode || _vm.CloneMode) && DeviceInfo.Platform == DevicePlatform.Android)
|
||||
{
|
||||
if (_vm.Cipher == null)
|
||||
{
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
xmlns:u="clr-namespace:Bit.App.Utilities"
|
||||
xmlns:controls="clr-namespace:Bit.App.Controls"
|
||||
xmlns:skia="clr-namespace:SkiaSharp.Views.Maui.Controls;assembly=SkiaSharp.Views.Maui.Controls"
|
||||
xmlns:core="clr-namespace:Bit.Core"
|
||||
xmlns:zxing="clr-namespace:ZXing.Net.Maui.Controls;assembly=ZXing.Net.MAUI.Controls"
|
||||
xmlns:core="clr-namespace:Bit.Core"
|
||||
xmlns:maui="clr-namespace:Camera.MAUI;assembly=Camera.MAUI"
|
||||
x:Name="_page"
|
||||
Title="{Binding ScanQrPageTitle}">
|
||||
|
||||
|
@ -34,18 +34,21 @@
|
|||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<!-- TODO: [MAUI-Migration]
|
||||
OnScanResult="OnScanResult"-->
|
||||
<zxing:CameraBarcodeReaderView
|
||||
x:Name="_zxing"
|
||||
HorizontalOptions="FillAndExpand"
|
||||
VerticalOptions="FillAndExpand"
|
||||
AutomationId="zxingScannerView"
|
||||
IsVisible="{Binding ShowScanner}"
|
||||
Grid.Column="0"
|
||||
Grid.Row="0"
|
||||
Grid.RowSpan="3"
|
||||
BarcodesDetected="_zxing_BarcodesDetected"/>
|
||||
<maui:CameraView x:Name="_cameraView"
|
||||
AutomationId="zxingScannerView"
|
||||
HorizontalOptions="Fill"
|
||||
VerticalOptions="Fill"
|
||||
ControlBarcodeResultDuplicate="True"
|
||||
BarCodeDetectionEnabled="True"
|
||||
BarcodeDetected="CameraViewOnBarcodeDetected"
|
||||
BarCodeOptions="{Binding BarCodeOptions}"
|
||||
Cameras="{Binding Cameras, Mode=OneWayToSource}"
|
||||
Camera="{Binding Camera}"
|
||||
AutoStartPreview="{Binding AutoStartPreview}"
|
||||
NumCamerasDetected="{Binding NumCameras, Mode=OneWayToSource}"
|
||||
Grid.Column="0"
|
||||
Grid.Row="0"
|
||||
Grid.RowSpan="3" />
|
||||
<StackLayout
|
||||
VerticalOptions="Center"
|
||||
HorizontalOptions="FillAndExpand"
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
using Bit.App.Utilities;
|
||||
using Bit.Core.Abstractions;
|
||||
using Bit.Core.Utilities;
|
||||
using Camera.MAUI.ZXingHelper;
|
||||
using SkiaSharp;
|
||||
using SkiaSharp.Views.Maui;
|
||||
using ZXing.Net.Maui;
|
||||
|
||||
namespace Bit.App.Pages
|
||||
{
|
||||
|
@ -12,8 +12,6 @@ namespace Bit.App.Pages
|
|||
{
|
||||
private ScanPageViewModel ViewModel => BindingContext as ScanPageViewModel;
|
||||
private readonly Action<string> _callback;
|
||||
private CancellationTokenSource _autofocusCts;
|
||||
private Task _continuousAutofocusTask;
|
||||
private readonly Color _greenColor;
|
||||
private readonly SKColor _blueSKColor;
|
||||
private readonly SKColor _greenSKColor;
|
||||
|
@ -27,10 +25,8 @@ namespace Bit.App.Pages
|
|||
{
|
||||
InitializeComponent();
|
||||
_callback = callback;
|
||||
ViewModel.InitScannerCommand = new Command(() => InitScanner());
|
||||
|
||||
// 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 (DeviceInfo.Platform == DevicePlatform.Android)
|
||||
{
|
||||
ToolbarItems.RemoveAt(0);
|
||||
}
|
||||
|
@ -54,125 +50,47 @@ namespace Bit.App.Pages
|
|||
base.OnDisappearing();
|
||||
}
|
||||
|
||||
// Fix known bug with DelayBetweenAnalyzingFrames & DelayBetweenContinuousScans: https://github.com/Redth/ZXing.Net.Mobile/issues/721
|
||||
private void InitScanner()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!ViewModel.HasCameraPermission || !ViewModel.ShowScanner || _zxing != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//_zxing = new ZXingScannerView();
|
||||
_zxing.Options = new BarcodeReaderOptions
|
||||
{
|
||||
//UseNativeScanning = true,
|
||||
//PossibleFormats = new List<ZXing.BarcodeFormat> { ZXing.BarcodeFormat.QR_CODE },
|
||||
Formats = BarcodeFormat.QrCode,
|
||||
AutoRotate = false,
|
||||
TryInverted = true,
|
||||
//DelayBetweenAnalyzingFrames = 5,
|
||||
//DelayBetweenContinuousScans = 5
|
||||
};
|
||||
//_scannerContainer.Content = _zxing;
|
||||
StartScanner();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Value.Exception(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void StartScanner()
|
||||
{
|
||||
if (_zxing == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (_cameraView == null) { return; }
|
||||
|
||||
//_zxing.OnScanResult -= OnScanResult;
|
||||
//_zxing.OnScanResult += OnScanResult;
|
||||
// TODO: [MAUI-Migration] [Critical]
|
||||
//_zxing.IsScanning = true;
|
||||
ViewModel.StartCameraCommand?.Execute(this);
|
||||
|
||||
// Fix for Autofocus, now it's done every 2 seconds so that the user does't have to do it
|
||||
// https://github.com/Redth/ZXing.Net.Mobile/issues/414
|
||||
_autofocusCts?.Cancel();
|
||||
_autofocusCts = new CancellationTokenSource(TimeSpan.FromMinutes(3));
|
||||
|
||||
var autofocusCts = _autofocusCts;
|
||||
// this task is needed to be awaited OnDisappearing to avoid some crashes
|
||||
// when changing the value of _zxing.IsScanning
|
||||
_continuousAutofocusTask = Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
while (!autofocusCts.IsCancellationRequested)
|
||||
{
|
||||
await Task.Delay(TimeSpan.FromSeconds(2), autofocusCts.Token);
|
||||
await Device.InvokeOnMainThreadAsync(() =>
|
||||
{
|
||||
if (!autofocusCts.IsCancellationRequested)
|
||||
{
|
||||
try
|
||||
{
|
||||
_zxing.AutoFocus();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Value.Exception(ex);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
catch (TaskCanceledException) { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Value.Exception(ex);
|
||||
}
|
||||
}, autofocusCts.Token);
|
||||
_pageIsActive = true;
|
||||
AnimationLoopAsync();
|
||||
}
|
||||
|
||||
private async Task StopScanner()
|
||||
{
|
||||
if (_zxing == null)
|
||||
if (_cameraView == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_autofocusCts?.Cancel();
|
||||
if (_continuousAutofocusTask != null)
|
||||
{
|
||||
await _continuousAutofocusTask;
|
||||
}
|
||||
// TODO: [MAUI-Migration] [Critical]
|
||||
//_zxing.IsScanning = false;
|
||||
//_zxing.OnScanResult -= OnScanResult;
|
||||
_cameraView.BarCodeDetectionEnabled = false;
|
||||
|
||||
await _cameraView.StopCameraAsync();
|
||||
_pageIsActive = false;
|
||||
}
|
||||
|
||||
// TODO: [MAUI-Migration] [Critical]
|
||||
private async void _zxing_BarcodesDetected(System.Object sender, ZXing.Net.Maui.BarcodeDetectionEventArgs e)
|
||||
private async void CameraViewOnBarcodeDetected(object sender, BarcodeEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!e.Results.Any())
|
||||
if (!e.Result.Any())
|
||||
{
|
||||
return;
|
||||
}
|
||||
var result = e.Results[0];
|
||||
var result = e.Result[0];
|
||||
// Stop analysis until we navigate away so we don't keep reading barcodes
|
||||
// TODO: [MAUI-Migration] [Critical]
|
||||
//_zxing.IsAnalyzing = false;
|
||||
var text = result?.Value;
|
||||
_cameraView.BarCodeDetectionEnabled = false;
|
||||
|
||||
var text = result?.Text;
|
||||
if (!string.IsNullOrWhiteSpace(text))
|
||||
{
|
||||
if (text.StartsWith("otpauth://totp"))
|
||||
{
|
||||
if (_qrcodeFound) { return; } //To avoid duplicate barcode detected events
|
||||
await QrCodeFoundAsync();
|
||||
_callback(text);
|
||||
return;
|
||||
|
@ -185,6 +103,7 @@ namespace Bit.App.Pages
|
|||
{
|
||||
if (part.StartsWith("secret="))
|
||||
{
|
||||
if (_qrcodeFound) { return; } //To avoid duplicate barcode detected events
|
||||
await QrCodeFoundAsync();
|
||||
var subResult = part.Substring(7);
|
||||
if (!string.IsNullOrEmpty(subResult))
|
||||
|
@ -196,7 +115,11 @@ namespace Bit.App.Pages
|
|||
}
|
||||
}
|
||||
}
|
||||
_callback(null);
|
||||
|
||||
if (!_qrcodeFound)
|
||||
{
|
||||
_callback(null);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -209,8 +132,6 @@ namespace Bit.App.Pages
|
|||
_qrcodeFound = true;
|
||||
Vibration.Vibrate();
|
||||
await Task.Delay(1000);
|
||||
// TODO: [MAUI-Migration] [Critical]
|
||||
//_zxing.IsScanning = false;
|
||||
}
|
||||
|
||||
private async void Close_Clicked(object sender, System.EventArgs e)
|
||||
|
|
|
@ -1,16 +1,12 @@
|
|||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Windows.Input;
|
||||
using Bit.App.Abstractions;
|
||||
using Bit.Core.Resources.Localization;
|
||||
using Bit.App.Utilities;
|
||||
using Bit.Core.Abstractions;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Utilities;
|
||||
|
||||
using Microsoft.Maui.ApplicationModel;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui;
|
||||
using Camera.MAUI;
|
||||
using Camera.MAUI.ZXingHelper;
|
||||
|
||||
namespace Bit.App.Pages
|
||||
{
|
||||
|
@ -25,6 +21,7 @@ namespace Bit.App.Pages
|
|||
public ScanPageViewModel()
|
||||
{
|
||||
ToggleScanModeCommand = new AsyncCommand(ToggleScanMode, onException: HandleException);
|
||||
StartCameraCommand = new Command(StartCamera);
|
||||
_platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService");
|
||||
_deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
|
||||
_logger = ServiceContainer.Resolve<ILogger>();
|
||||
|
@ -35,29 +32,80 @@ namespace Bit.App.Pages
|
|||
{
|
||||
try
|
||||
{
|
||||
await Device.InvokeOnMainThreadAsync(async () =>
|
||||
await MainThread.InvokeOnMainThreadAsync(async () =>
|
||||
{
|
||||
var hasCameraPermission = await PermissionManager.CheckAndRequestPermissionAsync(new Permissions.Camera());
|
||||
HasCameraPermission = hasCameraPermission == PermissionStatus.Granted;
|
||||
ShowScanner = hasCameraPermission == PermissionStatus.Granted;
|
||||
});
|
||||
|
||||
if (!HasCameraPermission)
|
||||
BarCodeOptions = new BarcodeDecodeOptions
|
||||
{
|
||||
return;
|
||||
}
|
||||
InitScannerCommand.Execute(null);
|
||||
AutoRotate = false, //shouldn't be needed for QRCodes
|
||||
PossibleFormats = { ZXing.BarcodeFormat.QR_CODE },
|
||||
ReadMultipleCodes = false, //runs slower when true and we only need one
|
||||
TryHarder = false, //runs slower when true
|
||||
TryInverted = true
|
||||
};
|
||||
TriggerPropertyChanged(nameof(BarCodeOptions));
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
catch (Exception ex)
|
||||
{
|
||||
HandleException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public ICommand ToggleScanModeCommand { get; set; }
|
||||
public ICommand InitScannerCommand { get; set; }
|
||||
private CameraInfo _camera = null;
|
||||
public CameraInfo Camera
|
||||
{
|
||||
get => _camera;
|
||||
set
|
||||
{
|
||||
_camera = value;
|
||||
TriggerPropertyChanged(nameof(Camera));
|
||||
|
||||
StartCameraCommand?.Execute(this);
|
||||
}
|
||||
}
|
||||
private ObservableCollection<CameraInfo> _cameras = new();
|
||||
public ObservableCollection<CameraInfo> Cameras
|
||||
{
|
||||
get => _cameras;
|
||||
set
|
||||
{
|
||||
_cameras = value;
|
||||
TriggerPropertyChanged(nameof(Cameras));
|
||||
}
|
||||
}
|
||||
public int NumCameras
|
||||
{
|
||||
set
|
||||
{
|
||||
if (value > 0)
|
||||
{
|
||||
Camera = Cameras.First();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public BarcodeDecodeOptions BarCodeOptions { get; set; }
|
||||
public bool AutoStartPreview { get; set; } = false;
|
||||
|
||||
public ICommand StartCameraCommand { get; set; }
|
||||
public ICommand ToggleScanModeCommand { get; set; }
|
||||
|
||||
private bool _hasCameraPermission = false;
|
||||
public bool HasCameraPermission
|
||||
{
|
||||
get => _hasCameraPermission;
|
||||
set
|
||||
{
|
||||
_hasCameraPermission = value;
|
||||
|
||||
StartCameraCommand?.Execute(this);
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasCameraPermission { get; set; }
|
||||
public string ScanQrPageTitle => ShowScanner ? AppResources.ScanQrTitle : AppResources.AuthenticatorKeyScanner;
|
||||
public string CameraInstructionTop => ShowScanner ? AppResources.PointYourCameraAtTheQRCode : AppResources.OnceTheKeyIsSuccessfullyEntered;
|
||||
public string TotpAuthenticationKey
|
||||
|
@ -81,6 +129,23 @@ namespace Bit.App.Pages
|
|||
});
|
||||
}
|
||||
|
||||
private void StartCamera()
|
||||
{
|
||||
if (HasCameraPermission && Camera != null)
|
||||
{
|
||||
// Note: If we need to improve performance on Android we can use _cameraView.StartCamera() directly on ScanPage.xaml.cs
|
||||
// this allows us to set a specific smaller resolution that should help performance and time to scan.
|
||||
// (The supported resolutions are available in the Camera object)
|
||||
// This solution would likely replace the "AutoStartPreview" logic in this Command.
|
||||
|
||||
//Setting AutoStartPreview to false and then true should trigger the CameraView to start
|
||||
AutoStartPreview = false;
|
||||
TriggerPropertyChanged(nameof(AutoStartPreview));
|
||||
AutoStartPreview = true;
|
||||
TriggerPropertyChanged(nameof(AutoStartPreview));
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ToggleScanMode()
|
||||
{
|
||||
var cameraPermission = await PermissionManager.CheckAndRequestPermissionAsync(new Permissions.Camera());
|
||||
|
@ -95,7 +160,6 @@ namespace Bit.App.Pages
|
|||
return;
|
||||
}
|
||||
ShowScanner = !ShowScanner;
|
||||
InitScannerCommand.Execute(null);
|
||||
}
|
||||
|
||||
public FormattedString ToggleScanModeLabel
|
||||
|
@ -119,7 +183,7 @@ namespace Bit.App.Pages
|
|||
|
||||
private void HandleException(Exception ex)
|
||||
{
|
||||
Microsoft.Maui.ApplicationModel.MainThread.InvokeOnMainThreadAsync(async () =>
|
||||
MainThread.InvokeOnMainThreadAsync(async () =>
|
||||
{
|
||||
await _deviceActionService.HideLoadingAsync();
|
||||
await _platformUtilsService.ShowDialogAsync(AppResources.GenericErrorMessage);
|
||||
|
|
Loading…
Reference in a new issue