SG-687 Request time not updating (#2108)

* [SG-687] request updates text with timer task and expires after 15 mins.

* [SG-697] PR Fixes

* [SG-687] Ran code format

* [SG-687] PR Fixes

* [SG-687] missed constant replacement

* [SG-687] PR fixes
This commit is contained in:
André Bispo 2022-10-03 17:42:33 +01:00 committed by GitHub
parent bc949fe87a
commit 1db4c4fc8b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 73 additions and 17 deletions

View file

@ -27,5 +27,17 @@ namespace Bit.App.Pages
await Navigation.PopModalAsync(); await Navigation.PopModalAsync();
} }
} }
protected override void OnAppearing()
{
base.OnAppearing();
_vm.StartRequestTimeUpdater();
}
protected override void OnDisappearing()
{
base.OnDisappearing();
_vm.StopRequestTimeUpdater();
}
} }
} }

View file

@ -1,5 +1,7 @@
using System; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Input; using System.Windows.Input;
using Bit.App.Abstractions; using Bit.App.Abstractions;
@ -8,6 +10,7 @@ using Bit.App.Utilities;
using Bit.Core; using Bit.Core;
using Bit.Core.Abstractions; using Bit.Core.Abstractions;
using Bit.Core.Enums; using Bit.Core.Enums;
using Bit.Core.Services;
using Bit.Core.Utilities; using Bit.Core.Utilities;
using Xamarin.CommunityToolkit.ObjectModel; using Xamarin.CommunityToolkit.ObjectModel;
using Xamarin.Forms; using Xamarin.Forms;
@ -21,6 +24,10 @@ namespace Bit.App.Pages
private IPlatformUtilsService _platformUtilsService; private IPlatformUtilsService _platformUtilsService;
private ILogger _logger; private ILogger _logger;
private LoginPasswordlessDetails _resquest; private LoginPasswordlessDetails _resquest;
private CancellationTokenSource _requestTimeCts;
private Task _requestTimeTask;
private const int REQUEST_TIME_UPDATE_PERIOD_IN_MINUTES = 5;
public LoginPasswordlessViewModel() public LoginPasswordlessViewModel()
{ {
@ -63,6 +70,30 @@ namespace Bit.App.Pages
} }
} }
public void StopRequestTimeUpdater()
{
_requestTimeCts?.Cancel();
_requestTimeCts?.Dispose();
}
public void StartRequestTimeUpdater()
{
_requestTimeCts?.Cancel();
_requestTimeCts = new CancellationTokenSource();
_requestTimeTask = new TimerTask(_logger, UpdateRequestTime, _requestTimeCts).RunPeriodic(TimeSpan.FromMinutes(REQUEST_TIME_UPDATE_PERIOD_IN_MINUTES));
}
private async Task UpdateRequestTime()
{
TriggerPropertyChanged(nameof(TimeOfRequestText));
if (DateTime.UtcNow > LoginRequest?.RequestDate.ToUniversalTime().AddMinutes(Constants.PasswordlessNotificationTimeoutInMinutes))
{
StopRequestTimeUpdater();
await _platformUtilsService.ShowDialogAsync(AppResources.LoginRequestHasAlreadyExpired);
await Page.Navigation.PopModalAsync();
}
}
private async Task PasswordlessLoginAsync(bool approveRequest) private async Task PasswordlessLoginAsync(bool approveRequest)
{ {
if (LoginRequest.RequestDate.AddMinutes(Constants.PasswordlessNotificationTimeoutInMinutes) <= DateTime.Now) if (LoginRequest.RequestDate.AddMinutes(Constants.PasswordlessNotificationTimeoutInMinutes) <= DateTime.Now)
@ -77,6 +108,8 @@ namespace Bit.App.Pages
await _deviceActionService.HideLoadingAsync(); await _deviceActionService.HideLoadingAsync();
await Page.Navigation.PopModalAsync(); await Page.Navigation.PopModalAsync();
_platformUtilsService.ShowToast("info", null, approveRequest ? AppResources.LogInAccepted : AppResources.LogInDenied); _platformUtilsService.ShowToast("info", null, approveRequest ? AppResources.LogInAccepted : AppResources.LogInDenied);
StopRequestTimeUpdater();
} }
private string CreateRequestDate(DateTime? requestDate) private string CreateRequestDate(DateTime? requestDate)
@ -86,17 +119,12 @@ namespace Bit.App.Pages
return string.Empty; return string.Empty;
} }
var minutesSinceRequest = requestDate.Value.ToUniversalTime().Minute - DateTime.UtcNow.Minute; if (DateTime.UtcNow < requestDate.Value.ToUniversalTime().AddMinutes(REQUEST_TIME_UPDATE_PERIOD_IN_MINUTES))
if (minutesSinceRequest < 5)
{ {
return AppResources.JustNow; return AppResources.JustNow;
} }
if (minutesSinceRequest < 59)
{
return string.Format(AppResources.XMinutesAgo, minutesSinceRequest);
}
return requestDate.Value.ToShortTimeString(); return string.Format(AppResources.XMinutesAgo, DateTime.UtcNow.Minute - requestDate.Value.ToUniversalTime().Minute);
} }
private void HandleException(Exception ex) private void HandleException(Exception ex)

View file

@ -10,13 +10,21 @@ namespace Bit.App.Utilities
{ {
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly Action _action; private readonly Action _action;
private readonly CancellationTokenSource _cancellationToken; private readonly Func<Task> _actionTask;
private readonly CancellationTokenSource _cancellationTokenSource;
public TimerTask(ILogger logger, Action action, CancellationTokenSource cancellationToken) public TimerTask(ILogger logger, Action action, CancellationTokenSource cancellationTokenSource)
{ {
_logger = logger; _logger = logger;
_action = action ?? throw new ArgumentNullException(); _action = action ?? throw new ArgumentNullException(nameof(action));
_cancellationToken = cancellationToken; _cancellationTokenSource = cancellationTokenSource;
}
public TimerTask(ILogger logger, Func<Task> actionTask, CancellationTokenSource cancellationTokenSource)
{
_logger = logger;
_actionTask = actionTask ?? throw new ArgumentNullException(nameof(actionTask));
_cancellationTokenSource = cancellationTokenSource;
} }
public Task RunPeriodic(TimeSpan? interval = null) public Task RunPeriodic(TimeSpan? interval = null)
@ -26,23 +34,31 @@ namespace Bit.App.Utilities
{ {
try try
{ {
while (!_cancellationToken.IsCancellationRequested) while (!_cancellationTokenSource.IsCancellationRequested)
{ {
await Device.InvokeOnMainThreadAsync(() => await Device.InvokeOnMainThreadAsync(async () =>
{ {
if (!_cancellationToken.IsCancellationRequested) if (!_cancellationTokenSource.IsCancellationRequested)
{ {
try try
{
if (_action != null)
{ {
_action(); _action();
} }
else if (_actionTask != null)
{
await _actionTask();
}
}
catch (Exception ex) catch (Exception ex)
{ {
_cancellationTokenSource?.Cancel();
_logger?.Exception(ex); _logger?.Exception(ex);
} }
} }
}); });
await Task.Delay(interval.Value, _cancellationToken.Token); await Task.Delay(interval.Value, _cancellationTokenSource.Token);
} }
} }
catch (TaskCanceledException) { } catch (TaskCanceledException) { }
@ -50,7 +66,7 @@ namespace Bit.App.Utilities
{ {
_logger?.Exception(ex); _logger?.Exception(ex);
} }
}, _cancellationToken.Token); }, _cancellationTokenSource.Token);
} }
} }
} }