1
0
mirror of https://github.com/bitwarden/mobile synced 2025-12-05 23:53:33 +00:00
Files
mobile/src/App/Pages/Vault/ScanPage.xaml.cs
2022-06-13 12:57:07 +01:00

124 lines
4.0 KiB
C#

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Bit.Core.Abstractions;
using Bit.Core.Utilities;
using Xamarin.Essentials;
using Xamarin.Forms;
namespace Bit.App.Pages
{
public partial class ScanPage : BaseContentPage
{
private readonly Action<string> _callback;
private CancellationTokenSource _autofocusCts;
private Task _continuousAutofocusTask;
private readonly LazyResolve<ILogger> _logger = new LazyResolve<ILogger>("logger");
public ScanPage(Action<string> callback)
{
_callback = callback;
InitializeComponent();
_zxing.Options = new ZXing.Mobile.MobileBarcodeScanningOptions
{
UseNativeScanning = true,
PossibleFormats = new List<ZXing.BarcodeFormat> { ZXing.BarcodeFormat.QR_CODE },
AutoRotate = false,
TryInverted = true
};
if (Device.RuntimePlatform == Device.Android)
{
ToolbarItems.RemoveAt(0);
}
}
protected override void OnAppearing()
{
base.OnAppearing();
_zxing.IsScanning = true;
// 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;
_continuousAutofocusTask = Task.Run(async () =>
{
try
{
while (!autofocusCts.IsCancellationRequested)
{
await Task.Delay(TimeSpan.FromSeconds(2), autofocusCts.Token);
Device.BeginInvokeOnMainThread(() =>
{
if (!autofocusCts.IsCancellationRequested)
{
_zxing.AutoFocus();
}
});
}
}
catch (TaskCanceledException) { }
catch (Exception ex)
{
_logger.Value.Exception(ex);
}
}, autofocusCts.Token);
}
protected override async void OnDisappearing()
{
_autofocusCts?.Cancel();
await _continuousAutofocusTask;
_zxing.IsScanning = false;
base.OnDisappearing();
}
private void OnScanResult(ZXing.Result result)
{
// Stop analysis until we navigate away so we don't keep reading barcodes
_zxing.IsAnalyzing = false;
_zxing.IsScanning = false;
var text = result?.Text;
if (!string.IsNullOrWhiteSpace(text))
{
if (text.StartsWith("otpauth://totp"))
{
Vibration.Vibrate();
_callback(text);
return;
}
else if (Uri.TryCreate(text, UriKind.Absolute, out Uri uri) &&
!string.IsNullOrWhiteSpace(uri?.Query))
{
var queryParts = uri.Query.Substring(1).ToLowerInvariant().Split('&');
foreach (var part in queryParts)
{
if (part.StartsWith("secret="))
{
Vibration.Vibrate();
_callback(part.Substring(7)?.ToUpperInvariant());
return;
}
}
}
}
_callback(null);
}
private async void Close_Clicked(object sender, System.EventArgs e)
{
if (DoOnce())
{
await Navigation.PopModalAsync();
}
}
}
}