Code updated to 3.0.238

This commit is contained in:
Oliver Hauff 2021-06-26 20:57:55 +02:00
parent 3302d80678
commit 9c6a1fa92b
257 changed files with 7763 additions and 2861 deletions

View file

@ -1,6 +1,7 @@
using System;
using System.ComponentModel;
using TINK.Model.Connector;
using TINK.Model.Device;
using TINK.Model.User;
using TINK.View;
using TINK.ViewModel.Bikes.Bike.BC.RequestHandler;
@ -30,6 +31,7 @@ namespace TINK.ViewModel.Bikes.Bike.BC
/// <summary>
/// Constructs a bike view model object.
/// </summary>
/// <param name="smartDevice">Provides info about the smart device (phone, tablet, ...).</param>
/// <param name="selectedBike">Bike to be displayed.</param>
/// <param name="activeUser">Object holding logged in user or an empty user object.</param>
/// <param name="stateInfoProvider">Provides in use state information.</param>
@ -37,13 +39,14 @@ namespace TINK.ViewModel.Bikes.Bike.BC
public BikeViewModel(
Func<bool> isConnectedDelegate,
Func<bool, IConnector> connectorFactory,
Action<int> bikeRemoveDelegate,
Action<string> bikeRemoveDelegate,
Func<IPollingUpdateTaskManager> viewUpdateManager,
ISmartDevice smartDevice,
IViewService viewService,
BikeInfoMutable selectedBike,
IUser activeUser,
IInUseStateInfoProvider stateInfoProvider,
IBikesViewModel bikesViewModel) : base(isConnectedDelegate, connectorFactory, bikeRemoveDelegate, viewUpdateManager, viewService, selectedBike, activeUser, stateInfoProvider, bikesViewModel)
IBikesViewModel bikesViewModel) : base(isConnectedDelegate, connectorFactory, bikeRemoveDelegate, viewUpdateManager, smartDevice, viewService, selectedBike, activeUser, stateInfoProvider, bikesViewModel)
{
RequestHandler = activeUser.IsLoggedIn
? RequestHandlerFactory.Create(
@ -51,6 +54,7 @@ namespace TINK.ViewModel.Bikes.Bike.BC
isConnectedDelegate,
connectorFactory,
viewUpdateManager,
smartDevice,
viewService,
bikesViewModel,
ActiveUser)
@ -74,6 +78,7 @@ namespace TINK.ViewModel.Bikes.Bike.BC
IsConnectedDelegate,
ConnectorFactory,
ViewUpdateManager,
SmartDevice,
ViewService,
BikesViewModel,
ActiveUser);

View file

@ -1,5 +1,6 @@
using System;
using TINK.Model.Connector;
using TINK.Model.Device;
using TINK.Model.State;
using TINK.Model.User;
using TINK.View;
@ -26,6 +27,9 @@ namespace TINK.ViewModel.Bikes.Bike.BC.RequestHandler
/// </summary>
public string ButtonText { get; }
/// <summary> Provides info about the smart device (phone, tablet, ...).</summary>
protected ISmartDevice SmartDevice;
/// <summary>
/// Reference on view servcie to show modal notifications and to perform navigation.
/// </summary>
@ -70,6 +74,7 @@ namespace TINK.ViewModel.Bikes.Bike.BC.RequestHandler
/// Constructs the reqest handler base.
/// </summary>
/// <param name="selectedBike">Bike which is reserved or for which reservation is canceled.</param>
/// <param name="smartDevice">Provides info about the smart device (phone, tablet, ...).</param>
/// <param name="bikesViewModel">View model to be used by subclasses for progress report and unlocking/ locking view.</param>
public Base(
T selectedBike,
@ -78,6 +83,7 @@ namespace TINK.ViewModel.Bikes.Bike.BC.RequestHandler
Func<bool> isConnectedDelegate,
Func<bool, IConnector> connectorFactory,
Func<IPollingUpdateTaskManager> viewUpdateManager,
ISmartDevice smartDevice,
IViewService viewService,
IBikesViewModel bikesViewModel,
IUser activeUser)
@ -88,6 +94,7 @@ namespace TINK.ViewModel.Bikes.Bike.BC.RequestHandler
IsConnectedDelegate = isConnectedDelegate;
ConnectorFactory = connectorFactory;
ViewUpdateManager = viewUpdateManager;
SmartDevice = smartDevice;
ViewService = viewService;
ActiveUser = activeUser;
IsRemoveBikeRequired = false;

View file

@ -2,16 +2,18 @@
using System;
using System.Threading.Tasks;
using TINK.Model.Connector;
using TINK.Model.Repository.Exception;
using TINK.Repository.Exception;
using TINK.Model.State;
using TINK.Model.User;
using TINK.MultilingualResources;
using TINK.View;
using BikeInfoMutable = TINK.Model.Bike.BC.BikeInfoMutable;
using TINK.Model.Device;
namespace TINK.ViewModel.Bikes.Bike.BC.RequestHandler
{
/// <param name="smartDevice">Provides info about the smart device (phone, tablet, ...)</param>
/// <param name="bikesViewModel">View model to be used for progress report and unlocking/ locking view.</param>
public class Disposable : Base<BikeInfoMutable>, IRequestHandler
{
@ -20,13 +22,14 @@ namespace TINK.ViewModel.Bikes.Bike.BC.RequestHandler
Func<bool> isConnectedDelegate,
Func<bool, IConnector> connectorFactory,
Func<IPollingUpdateTaskManager> viewUpdateManager,
ISmartDevice smartDevice,
IViewService viewService,
IBikesViewModel bikesViewModel,
IUser activeUser) : base(selectedBike, selectedBike.State.Value.GetActionText(), true, isConnectedDelegate, connectorFactory, viewUpdateManager, viewService, bikesViewModel, activeUser)
IUser activeUser) : base(selectedBike, selectedBike.State.Value.GetActionText(), true, isConnectedDelegate, connectorFactory, viewUpdateManager, smartDevice, viewService, bikesViewModel, activeUser)
{
}
/// <summary> Gets the bike state. </summary>
/// <summary> Gets the bike state. </summary>
public override InUseStateEnum State => InUseStateEnum.Disposable;
/// <summary> Request bike. </summary>
@ -38,7 +41,7 @@ namespace TINK.ViewModel.Bikes.Bike.BC.RequestHandler
var l_oResult = await ViewService.DisplayAlert(
string.Empty,
string.Format(AppResources.QuestionReserveBike, SelectedBike.GetDisplayName(), StateRequestedInfo.MaximumReserveTime.Minutes),
string.Format(AppResources.QuestionReserveBike, SelectedBike.GetFullDisplayName(), StateRequestedInfo.MaximumReserveTime.Minutes),
AppResources.MessageAnswerYes,
AppResources.MessageAnswerNo);
@ -110,7 +113,7 @@ namespace TINK.ViewModel.Bikes.Bike.BC.RequestHandler
Log.ForContext<Disposable>().Information("User reserved bike {l_oId} successfully.", SelectedBike.Id);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
}
}

View file

@ -66,8 +66,13 @@ namespace TINK.ViewModel.Bikes.Bike.BC.RequestHandler
try
{
// Switch to map page
// Switch to login page
#if USEMASTERDETAIL || USEFLYOUT
ViewService.ShowPage(ViewTypes.LoginPage);
#else
await ViewService.ShowPage("//LoginPage");
#endif
}
catch (Exception p_oException)
{

View file

@ -2,27 +2,30 @@
using System;
using System.Threading.Tasks;
using TINK.Model.Connector;
using TINK.Model.Repository.Exception;
using TINK.Repository.Exception;
using TINK.Model.State;
using TINK.Model.User;
using TINK.MultilingualResources;
using TINK.View;
using BikeInfoMutable = TINK.Model.Bike.BC.BikeInfoMutable;
using TINK.Model.Device;
namespace TINK.ViewModel.Bikes.Bike.BC.RequestHandler
{
public class Reserved : Base<BikeInfoMutable>, IRequestHandler
{
/// <param name="smartDevice">Provides info about the smart device (phone, tablet, ...)</param>
/// <param name="bikesViewModel">View model to be used for progress report and unlocking/ locking view.</param>
public Reserved(
BikeInfoMutable selectedBike,
Func<bool> isConnectedDelegate,
Func<bool, IConnector> connectorFactory,
Func<IPollingUpdateTaskManager> viewUpdateManager,
ISmartDevice smartDevice,
IViewService viewService,
IBikesViewModel bikesViewModel,
IUser activeUser) : base(selectedBike, AppResources.ActionCancelRequest, true, isConnectedDelegate, connectorFactory, viewUpdateManager, viewService, bikesViewModel, activeUser)
IUser activeUser) : base(selectedBike, AppResources.ActionCancelRequest, true, isConnectedDelegate, connectorFactory, viewUpdateManager, smartDevice, viewService, bikesViewModel, activeUser)
{
}
@ -39,7 +42,7 @@ namespace TINK.ViewModel.Bikes.Bike.BC.RequestHandler
BikesViewModel.ActionText = string.Empty;
var l_oResult = await ViewService.DisplayAlert(
string.Empty,
string.Format("Reservierung für Fahrrad {0} aufheben?", SelectedBike.GetDisplayName()),
string.Format("Reservierung für Fahrrad {0} aufheben?", SelectedBike.GetFullDisplayName()),
"Ja",
"Nein");
@ -109,7 +112,7 @@ namespace TINK.ViewModel.Bikes.Bike.BC.RequestHandler
Log.ForContext<Reserved>().Information("User canceled reservation of bike {l_oId} successfully.", SelectedBike.Id);
BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
}
}

View file

@ -1,5 +1,6 @@
using System;
using TINK.Model.Connector;
using TINK.Model.Device;
using TINK.Model.User;
using TINK.View;
using TINK.ViewModel.Bikes.Bike.BC.RequestHandler;
@ -9,12 +10,14 @@ namespace TINK.ViewModel.Bikes.Bike.BC
{
public static class RequestHandlerFactory
{
/// <param name="smartDevice">Provides info about the smart device (phone, tablet, ...)</param>
/// <param name="bikesViewModel">View model to be used for progress report and unlocking/ locking view.</param>
public static IRequestHandler Create(
BikeInfoMutable selectedBike,
Func<bool> isConnectedDelegate,
Func<bool, IConnector> connectorFactory,
Func<IPollingUpdateTaskManager> viewUpdateManager,
ISmartDevice smartDevice,
IViewService viewService,
IBikesViewModel bikesViewModel,
IUser activeUser)
@ -28,6 +31,7 @@ namespace TINK.ViewModel.Bikes.Bike.BC
isConnectedDelegate,
connectorFactory,
viewUpdateManager,
smartDevice,
viewService,
bikesViewModel,
activeUser);
@ -39,6 +43,7 @@ namespace TINK.ViewModel.Bikes.Bike.BC
isConnectedDelegate,
connectorFactory,
viewUpdateManager,
smartDevice,
viewService,
bikesViewModel,
activeUser);

View file

@ -1,6 +1,7 @@
using System;
using System.ComponentModel;
using TINK.Model.Connector;
using TINK.Model.Device;
using TINK.Model.State;
using TINK.Model.User;
using TINK.MultilingualResources;
@ -25,6 +26,9 @@ namespace TINK.ViewModel.Bikes.Bike
/// </summary>
public const string TIMEFORMAT = "dd. MMMM HH:mm";
/// <summary> Provides info about the smart device (phone, tablet, ...).</summary>
protected ISmartDevice SmartDevice;
/// <summary>
/// Reference on view servcie to show modal notifications and to perform navigation.
/// </summary>
@ -37,7 +41,7 @@ namespace TINK.ViewModel.Bikes.Bike
protected Func<bool> IsConnectedDelegate { get; }
/// <summary> Removes bike from bikes view model. </summary>
protected Action<int> BikeRemoveDelegate { get; }
protected Action<string> BikeRemoveDelegate { get; }
/// <summary> Object to manage update of view model objects from Copri.</summary>
public Func<IPollingUpdateTaskManager> ViewUpdateManager { get; }
@ -74,6 +78,7 @@ namespace TINK.ViewModel.Bikes.Bike
/// <summary>
/// Constructs a bike view model object.
/// </summary>
/// <param name="smartDevice">Provides info about the smart device (phone, tablet, ...).</param>
/// <param name="selectedBike">Bike to be displayed.</param>
/// <param name="activeUser">Object holding logged in user or an empty user object.</param>
/// <param name="stateInfoProvider">Provides in use state information.</param>
@ -81,15 +86,15 @@ namespace TINK.ViewModel.Bikes.Bike
public BikeViewModelBase(
Func<bool> isConnectedDelegate,
Func<bool, IConnector> connectorFactory,
Action<int> bikeRemoveDelegate,
Action<string> bikeRemoveDelegate,
Func<IPollingUpdateTaskManager> viewUpdateManager,
ISmartDevice smartDevice,
IViewService viewService,
BikeInfoMutable selectedBike,
IUser activeUser,
IInUseStateInfoProvider stateInfoProvider,
IBikesViewModel bikesViewModel)
{
IsConnectedDelegate = isConnectedDelegate;
ConnectorFactory = connectorFactory;
@ -98,6 +103,8 @@ namespace TINK.ViewModel.Bikes.Bike
ViewUpdateManager = viewUpdateManager;
SmartDevice = smartDevice;
ViewService = viewService;
bike = selectedBike
@ -153,21 +160,18 @@ namespace TINK.ViewModel.Bikes.Bike
/// <summary>
/// Gets the display name of the bike containing of bike id and type of bike..
/// </summary>
public string Name
{
get
{
return bike.GetDisplayName();
}
}
public string Name => bike.GetDisplayName();
/// <summary>
/// Gets the unique Id of bike or an empty string, if no name is defined to avoid duplicate display of id.
/// </summary>
public string DisplayId => bike.GetDisplayId();
/// <summary>
/// Gets the unique Id of bike used by derived model to determine which bike to remove.
/// </summary>
public int Id
{
get { return bike.Id; }
}
public string Id=> bike.Id;
/// <summary>
/// Returns status of a bike as text.
@ -240,7 +244,7 @@ namespace TINK.ViewModel.Bikes.Bike
/// <returns>Display text</returns>
private string GetReservedInfo(
TimeSpan? p_oRemainingTime,
int? p_strStation = null,
string p_strStation = null,
string p_strCode = null)
{
return StateInfoProvider.GetReservedInfo(p_oRemainingTime, p_strStation, p_strCode);
@ -254,7 +258,7 @@ namespace TINK.ViewModel.Bikes.Bike
/// <returns>Display text</returns>
private string GetBookedInfo(
DateTime? p_oFrom,
int? p_strStation = null,
string p_strStation = null,
string p_strCode = null)
{
return StateInfoProvider.GetBookedInfo(p_oFrom, p_strStation, p_strCode);

View file

@ -4,11 +4,13 @@ using TINK.Services.BluetoothLock;
using TINK.Model.Services.Geolocation;
using TINK.Model.User;
using TINK.View;
using TINK.Model.Device;
namespace TINK.ViewModel.Bikes.Bike
{
public static class BikeViewModelFactory
{
/// <param name="smartDevice">Provides info about the smart device (phone, tablet, ...).</param>
/// <param name="stateInfoProvider">Provides in use state information.</param>
/// <param name="bikesViewModel">View model to be used for progress report and unlocking/ locking view.</param>
public static BikeViewModelBase Create(
@ -16,8 +18,9 @@ namespace TINK.ViewModel.Bikes.Bike
Func<bool, IConnector> connectorFactory,
IGeolocation geolocation,
ILocksService lockService,
Action<int> bikeRemoveDelegate,
Action<string> bikeRemoveDelegate,
Func<IPollingUpdateTaskManager> viewUpdateManager,
ISmartDevice smartDevice,
IViewService viewService,
Model.Bike.BC.BikeInfoMutable bikeInfo,
IUser activeUser,
@ -32,6 +35,7 @@ namespace TINK.ViewModel.Bikes.Bike
lockService,
bikeRemoveDelegate,
viewUpdateManager,
smartDevice,
viewService,
bikeInfo as Model.Bike.BluetoothLock.BikeInfoMutable,
activeUser,
@ -42,6 +46,7 @@ namespace TINK.ViewModel.Bikes.Bike
connectorFactory,
bikeRemoveDelegate,
viewUpdateManager,
smartDevice,
viewService,
bikeInfo,
activeUser,

View file

@ -8,6 +8,7 @@ using TINK.Model.User;
using TINK.View;
using BikeInfoMutable = TINK.Model.Bike.BluetoothLock.BikeInfoMutable;
using System.Threading.Tasks;
using TINK.Model.Device;
namespace TINK.ViewModel.Bikes.Bike.BluetoothLock
{
@ -77,6 +78,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock
/// <summary>
/// Constructs a bike view model object.
/// </summary>
/// <param name="smartDevice">Provides info about the smart device (phone, tablet, ...)</param>
/// <param name="selectedBike">Bike to be displayed.</param>
/// <param name="user">Object holding logged in user or an empty user object.</param>
/// <param name="stateInfoProvider">Provides in use state information.</param>
@ -86,13 +88,14 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock
Func<bool, IConnector> connectorFactory,
IGeolocation geolocation,
ILocksService lockService,
Action<int> bikeRemoveDelegate,
Action<string> bikeRemoveDelegate,
Func<IPollingUpdateTaskManager> viewUpdateManager,
ISmartDevice smartDevice,
IViewService viewService,
BikeInfoMutable selectedBike,
IUser user,
IInUseStateInfoProvider stateInfoProvider,
IBikesViewModel bikesViewModel) : base(isConnectedDelegate, connectorFactory, bikeRemoveDelegate, viewUpdateManager, viewService, selectedBike, user, stateInfoProvider, bikesViewModel)
IBikesViewModel bikesViewModel) : base(isConnectedDelegate, connectorFactory, bikeRemoveDelegate, viewUpdateManager, smartDevice, viewService, selectedBike, user, stateInfoProvider, bikesViewModel)
{
RequestHandler = user.IsLoggedIn
? RequestHandlerFactory.Create(
@ -102,6 +105,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock
geolocation,
lockService,
viewUpdateManager,
smartDevice,
viewService,
bikesViewModel,
user)
@ -132,6 +136,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock
Geolocation,
LockService,
ViewUpdateManager,
SmartDevice,
ViewService,
BikesViewModel,
ActiveUser);

View file

@ -5,6 +5,7 @@ using TINK.Model.Services.Geolocation;
using TINK.Model.State;
using TINK.View;
using TINK.Model.User;
using TINK.Model.Device;
namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{
@ -14,6 +15,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
/// Constructs the reqest handler base.
/// </summary>
/// <param name="selectedBike">Bike which is reserved or for which reservation is canceled.</param>
/// <param name="smartDevice">Provides info about the smart device (phone, tablet, ...)</param>
/// <param name="bikesViewModel">View model to be used for progress report and unlocking/ locking view.</param>
public Base(
Model.Bikes.Bike.BluetoothLock.IBikeInfoMutable selectedBike,
@ -24,9 +26,10 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
IGeolocation geolocation,
ILocksService lockService,
Func<IPollingUpdateTaskManager> viewUpdateManager,
ISmartDevice smartDevice,
IViewService viewService,
IBikesViewModel bikesViewModel,
IUser activeUser) : base(selectedBike, buttonText, isCopriButtonVisible, isConnectedDelegate, connectorFactory, viewUpdateManager, viewService, bikesViewModel, activeUser)
IUser activeUser) : base(selectedBike, buttonText, isCopriButtonVisible, isConnectedDelegate, connectorFactory, viewUpdateManager, smartDevice, viewService, bikesViewModel, activeUser)
{
Geolocation = geolocation
?? throw new ArgumentException($"Can not construct {GetType().Name}-object. Parameter {nameof(geolocation)} must not be null.");

View file

@ -7,19 +7,20 @@ using TINK.View;
using TINK.Model.Services.Geolocation;
using TINK.Services.BluetoothLock;
using Serilog;
using TINK.Model.Repository.Exception;
using TINK.Repository.Exception;
using TINK.Services.BluetoothLock.Exception;
using TINK.MultilingualResources;
using TINK.Model.Bikes.Bike.BluetoothLock;
using TINK.Model.User;
using TINK.Repository.Exception;
using Xamarin.Essentials;
using TINK.Model.Repository.Request;
using TINK.Repository.Request;
using TINK.Model.Device;
namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{
public class BookedClosed : Base, IRequestHandler
{
/// <param name="smartDevice">Provides info about the smart device (phone, tablet, ...)</param>
/// <param name="bikesViewModel">View model to be used for progress report and unlocking/ locking view.</param>
public BookedClosed(
IBikeInfoMutable selectedBike,
@ -28,6 +29,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
IGeolocation geolocation,
ILocksService lockService,
Func<IPollingUpdateTaskManager> viewUpdateManager,
ISmartDevice smartDevice,
IViewService viewService,
IBikesViewModel bikesViewModel,
IUser activeUser) : base(
@ -38,7 +40,8 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
connectorFactory,
geolocation,
lockService,
viewUpdateManager,
viewUpdateManager,
smartDevice,
viewService,
bikesViewModel,
activeUser)
@ -51,13 +54,20 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
public override InUseStateEnum State => InUseStateEnum.Booked;
/// <summary> Return bike. </summary>
public async Task<IRequestHandler> HandleRequestOption1()
public async Task<IRequestHandler> HandleRequestOption1() => await ReturnBike();
/// <summary> Open bike and update COPRI lock state. </summary>
public async Task<IRequestHandler> HandleRequestOption2() => await OpenLock();
/// <summary> Return bike. </summary>
public async Task<IRequestHandler> ReturnBike()
{
BikesViewModel.IsIdle = false;
BikesViewModel.IsIdle = false;
// Ask whether to really return bike?
var l_oResult = await ViewService.DisplayAlert(
string.Empty,
$"Fahrrad {SelectedBike.GetDisplayName()} zurückgeben?",
$"Fahrrad {SelectedBike.GetFullDisplayName()} zurückgeben?",
"Ja",
"Nein");
@ -184,7 +194,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically();
BikesViewModel.ActionText = "";
BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
Log.ForContext<BookedClosed>().Information("User returned bike {bike} successfully.", SelectedBike);
@ -209,7 +219,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
try
{
await ConnectorFactory(IsConnected).Command.DoSubmitFeedback(
new UserFeedbackDto { IsBikeBroken = feedback.IsBikeBroken, Message = feedback.Message },
new UserFeedbackDto { BikeId = SelectedBike.Id, IsBikeBroken = feedback.IsBikeBroken, Message = feedback.Message },
feedBackUri);
}
catch (Exception exception)
@ -226,12 +236,18 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
Log.ForContext<BookedOpen>().Error("User selected availalbe bike {bike} but reserving failed. {@l_oException}", SelectedBike.Id, exception);
}
await ViewService.DisplayAlert(
AppResources.ErrorReturnSubmitFeedbackTitle,
AppResources.ErrorReturnSubmitFeedbackMessage,
AppResources.MessageAnswerOk);
BikesViewModel.ActionText = AppResources.ActivityTextStartingUpdater;
await ViewUpdateManager().StartUpdateAyncPeridically();
BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
#endif
@ -240,11 +256,11 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically();
BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
/// <summary> Open bike and update COPRI lock state. </summary>
public async Task<IRequestHandler> HandleRequestOption2()
public async Task<IRequestHandler> OpenLock()
{
// Unlock bike.
Log.ForContext<BookedClosed>().Information("User request to unlock bike {bike}.", SelectedBike);
@ -272,13 +288,22 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
AppResources.ErrorOpenLockOutOfReadMessage,
"OK");
}
else if (exception is CouldntOpenBoldBlockedException)
else if (exception is CouldntOpenBoldIsBlockedException)
{
Log.ForContext<BookedClosed>().Debug("Lock can not be opened. Bold is blocked. {Exception}", exception);
await ViewService.DisplayAlert(
AppResources.ErrorOpenLockTitle,
AppResources.ErrorOpenLockMessage,
AppResources.ErrorOpenLockBoldBlockedMessage,
"OK");
}
else if (exception is CouldntOpenBoldWasBlockedException)
{
Log.ForContext<BookedClosed>().Debug("Lock can not be opened. Bold was or is blocked. {Exception}", exception);
await ViewService.DisplayAlert(
AppResources.ErrorOpenLockStillOpenTitle,
AppResources.ErrorOpenLockBoldWasBlockedMessage,
"OK");
}
else if (exception is CouldntOpenInconsistentStateExecption inconsistentState
@ -311,13 +336,13 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically();
BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
BikesViewModel.ActionText = AppResources.ActivityTextReadingChargingLevel;
try
{
SelectedBike.LockInfo.BatteryPercentage = (await LockService[SelectedBike.LockInfo.Id].GetBatteryPercentageAsync());
SelectedBike.LockInfo.BatteryPercentage = await LockService[SelectedBike.LockInfo.Id].GetBatteryPercentageAsync();
}
catch (Exception exception)
{
@ -372,7 +397,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically();
BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
}
}

View file

@ -4,7 +4,7 @@ using System.Threading.Tasks;
using TINK.Model.Bike.BluetoothLock;
using TINK.Model.Bikes.Bike.BluetoothLock;
using TINK.Model.Connector;
using TINK.Model.Repository.Exception;
using TINK.Repository.Exception;
using TINK.Services.BluetoothLock;
using TINK.Services.BluetoothLock.Exception;
using TINK.Services.BluetoothLock.Tdo;
@ -13,11 +13,13 @@ using TINK.Model.State;
using TINK.MultilingualResources;
using TINK.View;
using TINK.Model.User;
using TINK.Model.Device;
namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{
public class BookedDisconnected : Base, IRequestHandler
{
/// <param name="smartDevice">Provides info about the smart device (phone, tablet, ...)</param>
/// <param name="bikesViewModel">View model to be used for progress report and unlocking/ locking view.</param>
public BookedDisconnected(
IBikeInfoMutable selectedBike,
@ -26,6 +28,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
IGeolocation geolocation,
ILocksService lockService,
Func<IPollingUpdateTaskManager> viewUpdateManager,
ISmartDevice smartDevice,
IViewService viewService,
IBikesViewModel bikesViewModel,
IUser activeUser) :
@ -38,6 +41,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
geolocation,
lockService,
viewUpdateManager,
smartDevice,
viewService,
bikesViewModel,
activeUser)
@ -49,14 +53,23 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
/// <summary> Gets the bike state. </summary>
public override InUseStateEnum State => InUseStateEnum.Booked;
public Task<IRequestHandler> HandleRequestOption1()
public async Task<IRequestHandler> HandleRequestOption1() => await UnsupportedRequest();
/// <summary> Scan for lock.</summary>
/// <returns></returns>
public async Task<IRequestHandler> HandleRequestOption2() => await ConnectLock();
/// <summary> Requst is not supported, button should be disabled. </summary>
/// <returns></returns>
public async Task<IRequestHandler> UnsupportedRequest()
{
throw new NotSupportedException();
Log.ForContext<BookedDisconnected>().Error("Click of unsupported button click detected.");
return await Task.FromResult<IRequestHandler>(this);
}
/// <summary> Scan for lock.</summary>
/// <returns></returns>
public async Task<IRequestHandler> HandleRequestOption2()
public async Task<IRequestHandler> ConnectLock()
{
// Lock list to avoid multiple taps while copri action is pending.
BikesViewModel.IsIdle = false;
@ -136,11 +149,12 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{
Log.ForContext<BookedDisconnected>().Error("Lock can not be found. {Exception}", exception);
continueConnect = await ViewService.DisplayAlert(
"Fehler bei Verbinden mit Schloss!",
$"{AppResources.ErrorBookedSearchMessage}\r\nDetails:\r\n{exception.Message}",
"Wiederholen",
"Abbrechen");
continueConnect = await ViewService.DisplayAdvancedAlert(
"Fehler bei Verbinden mit Schloss!",
AppResources.ErrorBookedSearchMessage,
exception.Message,
"Wiederholen",
"Abbrechen");
}
if (continueConnect)
@ -187,7 +201,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically();
BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
}
}

View file

@ -7,14 +7,14 @@ using TINK.View;
using TINK.Model.Services.Geolocation;
using TINK.Services.BluetoothLock;
using Serilog;
using TINK.Model.Repository.Exception;
using TINK.Repository.Exception;
using TINK.Services.BluetoothLock.Exception;
using Xamarin.Essentials;
using TINK.MultilingualResources;
using TINK.Model.Bikes.Bike.BluetoothLock;
using TINK.Model.User;
using TINK.Model.Repository.Request;
using TINK.Repository.Exception;
using TINK.Repository.Request;
using TINK.Model.Device;
namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{
@ -28,6 +28,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
IGeolocation geolocation,
ILocksService lockService,
Func<IPollingUpdateTaskManager> viewUpdateManager,
ISmartDevice smartDevice,
IViewService viewService,
IBikesViewModel bikesViewModel,
IUser activeUser) : base(
@ -38,7 +39,8 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
connectorFactory,
geolocation,
lockService,
viewUpdateManager,
viewUpdateManager,
smartDevice,
viewService,
bikesViewModel,
activeUser)
@ -51,14 +53,19 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
public override InUseStateEnum State => InUseStateEnum.Disposable;
/// <summary> Close lock and return bike.</summary>
/// <returns></returns>
public async Task<IRequestHandler> HandleRequestOption1()
public async Task<IRequestHandler> HandleRequestOption1() => await CloseLockAndReturnBike();
/// <summary> Close lock in order to pause ride and update COPRI lock state.</summary>
public async Task<IRequestHandler> HandleRequestOption2() => await CloseLock();
/// <summary> Close lock and return bike.</summary>
public async Task<IRequestHandler> CloseLockAndReturnBike()
{
// Ask whether to really return bike?
BikesViewModel.IsIdle = false;
var l_oResult = await ViewService.DisplayAlert(
string.Empty,
$"Fahrrad {SelectedBike.GetDisplayName()} abschließen und zurückgeben?",
$"Fahrrad {SelectedBike.GetFullDisplayName()} abschließen und zurückgeben?",
"Ja",
"Nein");
@ -132,7 +139,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; // Unlock GUI
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
if (SelectedBike.LockInfo.State != LockingState.Closed)
@ -152,7 +159,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; // Unlock GUI
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
// Get geoposition.
@ -179,7 +186,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; // Unlock GUI
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
// Lock list to avoid multiple taps while copri action is pending.
@ -201,7 +208,8 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
Accuracy = currentLocation.Accuracy ?? double.NaN,
Age = timeStamp.Subtract(currentLocation.Timestamp.DateTime),
}.Build()
: null);
: null,
SmartDevice);
// If canceling bike succedes remove bike because it is not ready to be booked again
IsRemoveBikeRequired = true;
}
@ -261,7 +269,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
Log.ForContext<BookedOpen>().Information("User returned bike {bike} successfully.", SelectedBike);
@ -286,7 +294,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
try
{
await ConnectorFactory(IsConnected).Command.DoSubmitFeedback(
new UserFeedbackDto { IsBikeBroken = feedback.IsBikeBroken, Message = feedback.Message },
new UserFeedbackDto { BikeId = SelectedBike.Id, IsBikeBroken = feedback.IsBikeBroken, Message = feedback.Message },
feedBackUri);
}
catch (Exception exception)
@ -303,12 +311,17 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
Log.ForContext<BookedOpen>().Error("User selected availalbe bike {bike} but reserving failed. {@l_oException}", SelectedBike.Id, exception);
}
await ViewService.DisplayAlert(
AppResources.ErrorReturnSubmitFeedbackTitle,
AppResources.ErrorReturnSubmitFeedbackMessage,
AppResources.MessageAnswerOk);
BikesViewModel.ActionText = AppResources.ActivityTextStartingUpdater;
await ViewUpdateManager().StartUpdateAyncPeridically();
BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
#endif
@ -316,11 +329,11 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically();
BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
/// <summary> Close lock in order to pause ride and update COPRI lock state.</summary>
public async Task<IRequestHandler> HandleRequestOption2()
public async Task<IRequestHandler> CloseLock()
{
// Unlock bike.
BikesViewModel.IsIdle = false;
@ -383,7 +396,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically();
BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
// Get geoposition.
@ -450,7 +463,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically();
BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
}
}

View file

@ -5,21 +5,22 @@ using TINK.Model.Bike.BluetoothLock;
using TINK.Model.Connector;
using TINK.Model.State;
using TINK.View;
using TINK.Model.Repository.Exception;
using TINK.Repository.Exception;
using TINK.Model.Services.Geolocation;
using TINK.Services.BluetoothLock;
using TINK.Services.BluetoothLock.Exception;
using TINK.MultilingualResources;
using TINK.Model.Bikes.Bike.BluetoothLock;
using TINK.Model.User;
using TINK.Repository.Exception;
using Xamarin.Essentials;
using TINK.Model.Repository.Request;
using TINK.Repository.Request;
using TINK.Model.Device;
namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{
public class BookedUnknown : Base, IRequestHandler
{
/// <param name="smartDevice">Provides info about the smart device (phone, tablet, ...).</param>
/// <param name="bikesViewModel">View model to be used for progress report and unlocking/ locking view.</param>
public BookedUnknown(
IBikeInfoMutable selectedBike,
@ -28,6 +29,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
IGeolocation geolocation,
ILocksService lockService,
Func<IPollingUpdateTaskManager> viewUpdateManager,
ISmartDevice smartDevice,
IViewService viewService,
IBikesViewModel bikesViewModel,
IUser activeUser) : base(
@ -39,6 +41,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
geolocation,
lockService,
viewUpdateManager,
smartDevice,
viewService,
bikesViewModel,
activeUser)
@ -51,7 +54,14 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
public override InUseStateEnum State => InUseStateEnum.Booked;
/// <summary> Open bike and update COPRI lock state. </summary>
public async Task<IRequestHandler> HandleRequestOption1()
public async Task<IRequestHandler> HandleRequestOption1() => await OpenLock();
/// <summary> Close lock in order to pause ride and update COPRI lock state.</summary>
public async Task<IRequestHandler> HandleRequestOption2() => await CloseLock();
/// <summary> Open bike and update COPRI lock state. </summary>
public async Task<IRequestHandler> OpenLock()
{
// Unlock bike.
Log.ForContext<BookedUnknown>().Information("User request to unlock bike {bike}.", SelectedBike);
@ -79,13 +89,22 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
AppResources.ErrorOpenLockOutOfReadMessage,
"OK");
}
else if (exception is CouldntOpenBoldBlockedException)
else if (exception is CouldntOpenBoldIsBlockedException)
{
Log.ForContext<BookedUnknown>().Debug("Lock can not be opened. Bold is blocked. {Exception}", exception);
await ViewService.DisplayAlert(
AppResources.ErrorOpenLockTitle,
AppResources.ErrorOpenLockMessage,
AppResources.ErrorOpenLockBoldBlockedMessage,
"OK");
}
else if (exception is CouldntOpenBoldWasBlockedException)
{
Log.ForContext<BookedClosed>().Debug("Lock can not be opened. Bold was or is blocked. {Exception}", exception);
await ViewService.DisplayAlert(
AppResources.ErrorOpenLockStillOpenTitle,
AppResources.ErrorOpenLockBoldWasBlockedMessage,
"OK");
}
else if (exception is CouldntOpenInconsistentStateExecption inconsistentState
@ -118,13 +137,13 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically();
BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
BikesViewModel.ActionText = AppResources.ActivityTextReadingChargingLevel;
try
{
SelectedBike.LockInfo.BatteryPercentage = (await LockService[SelectedBike.LockInfo.Id].GetBatteryPercentageAsync());
SelectedBike.LockInfo.BatteryPercentage = await LockService[SelectedBike.LockInfo.Id].GetBatteryPercentageAsync();
}
catch (Exception exception)
{
@ -179,11 +198,11 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically();
BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
/// <summary> Close lock in order to pause ride and update COPRI lock state.</summary>
public async Task<IRequestHandler> HandleRequestOption2()
public async Task<IRequestHandler> CloseLock()
{
// Unlock bike.
BikesViewModel.IsIdle = false;
@ -246,7 +265,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically();
BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
// Get geoposition.
@ -313,7 +332,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically();
BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
}
}

View file

@ -5,7 +5,7 @@ using TINK.Model.Bike.BluetoothLock;
using TINK.Model.Connector;
using TINK.Model.State;
using TINK.View;
using TINK.Model.Repository.Exception;
using TINK.Repository.Exception;
using TINK.Model.Services.Geolocation;
using TINK.Services.BluetoothLock;
using TINK.Services.BluetoothLock.Tdo;
@ -13,12 +13,13 @@ using TINK.MultilingualResources;
using TINK.Model.Bikes.Bike.BluetoothLock;
using TINK.Services.BluetoothLock.Exception;
using TINK.Model.User;
using TINK.Repository.Exception;
using TINK.Model.Device;
namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{
public class DisposableDisconnected : Base, IRequestHandler
{
/// <param name="smartDevice">Provides info about the smart device (phone, tablet, ...).</param>
/// <param name="bikesViewModel">View model to be used for progress report and unlocking/ locking view.</param>
public DisposableDisconnected(
IBikeInfoMutable selectedBike,
@ -27,6 +28,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
IGeolocation geolocation,
ILocksService lockService,
Func<IPollingUpdateTaskManager> viewUpdateManager,
ISmartDevice smartDevice,
IViewService viewService,
IBikesViewModel bikesViewModel,
IUser activeUser) : base(
@ -38,6 +40,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
geolocation,
lockService,
viewUpdateManager,
smartDevice,
viewService,
bikesViewModel,
activeUser)
@ -50,14 +53,19 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
public override InUseStateEnum State => InUseStateEnum.Disposable;
/// <summary>Reserve bike and connect to lock.</summary>
public async Task<IRequestHandler> HandleRequestOption1()
public async Task<IRequestHandler> HandleRequestOption1() => await ReserverBookAndOpen();
public async Task<IRequestHandler> HandleRequestOption2() => await UnsupportedRequest();
/// <summary>Reserve bike and connect to lock.</summary>
public async Task<IRequestHandler> ReserverBookAndOpen()
{
BikesViewModel.IsIdle = false;
// Ask whether to really book bike?
var alertResult = await ViewService.DisplayAlert(
string.Empty,
string.Format(AppResources.QuestionReserveBike, SelectedBike.GetDisplayName(), StateRequestedInfo.MaximumReserveTime.Minutes),
string.Format(AppResources.QuestionReserveBike, SelectedBike.GetFullDisplayName(), StateRequestedInfo.MaximumReserveTime.Minutes),
AppResources.MessageAnswerYes,
AppResources.MessageAnswerNo);
@ -154,7 +162,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically();
BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
SelectedBike.LockInfo.State = result?.State?.GetLockingState() ?? LockingState.Disconnected;
@ -168,7 +176,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically();
BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
SelectedBike.LockInfo.Guid = result?.Guid ?? new Guid();
@ -179,7 +187,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
// Ask whether to really book bike?
alertResult = await ViewService.DisplayAlert(
string.Empty,
string.Format(AppResources.MessageOpenLockAndBookeBike, SelectedBike.GetDisplayName()),
string.Format(AppResources.MessageOpenLockAndBookeBike, SelectedBike.GetFullDisplayName()),
AppResources.MessageAnswerYes,
AppResources.MessageAnswerNo);
@ -206,7 +214,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically();
BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
Log.ForContext<DisposableDisconnected>().Information("User selected recently requested bike {bike} in order to book.", SelectedBike);
@ -247,7 +255,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
BikesViewModel.ActionText = AppResources.ActivityTextStartingUpdater;
await ViewUpdateManager().StartUpdateAyncPeridically(); // Restart polling again.
BikesViewModel.IsIdle = true; // Unlock GUI
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
// Unlock bike.
@ -268,13 +276,22 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
AppResources.ErrorOpenLockOutOfReadMessage,
"OK");
}
else if (exception is CouldntOpenBoldBlockedException)
else if (exception is CouldntOpenBoldIsBlockedException)
{
Log.ForContext<DisposableDisconnected>().Debug("Lock can not be opened. Bold is blocked. {Exception}", exception);
await ViewService.DisplayAlert(
AppResources.ErrorOpenLockTitle,
AppResources.ErrorOpenLockMessage,
AppResources.ErrorOpenLockBoldBlockedMessage,
"OK");
}
else if (exception is CouldntOpenBoldWasBlockedException)
{
Log.ForContext<BookedClosed>().Debug("Lock can not be opened. Bold was or is blocked. {Exception}", exception);
await ViewService.DisplayAlert(
AppResources.ErrorOpenLockStillOpenTitle,
AppResources.ErrorOpenLockBoldWasBlockedMessage,
"OK");
}
else if (exception is CouldntOpenInconsistentStateExecption inconsistentState
@ -305,7 +322,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
if (SelectedBike.LockInfo.State != LockingState.Open)
@ -316,13 +333,13 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
BikesViewModel.ActionText = "";
BikesViewModel.IsIdle = true; // Unlock GUI
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
BikesViewModel.ActionText = AppResources.ActivityTextReadingChargingLevel;
try
{
SelectedBike.LockInfo.BatteryPercentage = (await LockService[SelectedBike.LockInfo.Id].GetBatteryPercentageAsync());
SelectedBike.LockInfo.BatteryPercentage = await LockService[SelectedBike.LockInfo.Id].GetBatteryPercentageAsync();
}
catch (Exception exception)
{
@ -377,12 +394,15 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically(); // Restart polling again.
BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; // Unlock GUI
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
public Task<IRequestHandler> HandleRequestOption2()
/// <summary> Requst is not supported, button should be disabled. </summary>
/// <returns></returns>
public async Task<IRequestHandler> UnsupportedRequest()
{
throw new NotSupportedException();
Log.ForContext<DisposableDisconnected>().Error("Click of unsupported button click detected.");
return await Task.FromResult<IRequestHandler>(this);
}
}
}

View file

@ -5,13 +5,14 @@ using TINK.Model.Bike.BluetoothLock;
using TINK.Model.Connector;
using TINK.Model.State;
using TINK.View;
using TINK.Model.Repository.Exception;
using TINK.Repository.Exception;
using TINK.Model.Services.Geolocation;
using TINK.Services.BluetoothLock;
using TINK.Services.BluetoothLock.Exception;
using TINK.MultilingualResources;
using TINK.Model.Bikes.Bike.BluetoothLock;
using TINK.Model.User;
using TINK.Model.Device;
namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{
@ -32,6 +33,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
/// - no other device can access lock
/// - app itself should never event attempt to open a lock which is not rented.
/// </remarks>
/// <param name="smartDevice">Provides info about the smart device (phone, tablet, ...)</param>
/// <param name="bikesViewModel">View model to be used for progress report and unlocking/ locking view.</param>
public DisposableOpen(
IBikeInfoMutable selectedBike,
@ -40,6 +42,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
IGeolocation geolocation,
ILocksService lockService,
Func<IPollingUpdateTaskManager> viewUpdateManager,
ISmartDevice smartDevice,
IViewService viewService,
IBikesViewModel bikesViewModel,
IUser activeUser) : base(
@ -51,6 +54,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
geolocation,
lockService,
viewUpdateManager,
smartDevice,
viewService,
bikesViewModel,
activeUser)
@ -64,7 +68,14 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
/// <summary>Books bike by reserving bike, opening lock and booking bike.</summary>
/// <returns>Next request handler.</returns>
public async Task<IRequestHandler> HandleRequestOption1()
public async Task<IRequestHandler> HandleRequestOption1() => await DoBookOrClose();
public async Task<IRequestHandler> HandleRequestOption2() => await UnsupportedRequest();
/// <summary>Books bike by reserving bike, opening lock and booking bike.</summary>
/// <returns>Next request handler.</returns>
public async Task<IRequestHandler> DoBookOrClose()
{
BikesViewModel.IsIdle = false; // Lock list to avoid multiple taps while copri action is pending.
@ -75,7 +86,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
// Ask whether to really book bike or close lock?
var l_oResult = await ViewService.DisplayAlert(
string.Empty,
$"Fahrrad {SelectedBike.GetDisplayName()} mieten oder Schloss schließen?",
$"Fahrrad {SelectedBike.GetFullDisplayName()} mieten oder Schloss schließen?",
"Mieten",
"Schloss schließen");
@ -138,7 +149,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically();
BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
// Disconnect lock.
@ -158,7 +169,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically();
BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
// Lock list to avoid multiple taps while copri action is pending.
@ -167,7 +178,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
BikesViewModel.ActionText = AppResources.ActivityTextReadingChargingLevel;
try
{
SelectedBike.LockInfo.BatteryPercentage = (await LockService[SelectedBike.LockInfo.Id].GetBatteryPercentageAsync());
SelectedBike.LockInfo.BatteryPercentage = await LockService[SelectedBike.LockInfo.Id].GetBatteryPercentageAsync();
}
catch (Exception exception)
{
@ -250,7 +261,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
// Update status text and unlock list of bikes because no more action is pending.
BikesViewModel.ActionText = string.Empty; // Todo: Move this statement in front of finally block because in catch block BikesViewModel.ActionText is already set to empty.
BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
Log.ForContext<DisposableOpen>().Information("User reserved bike {bike} successfully.", SelectedBike);
@ -262,12 +273,14 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
// Update status text and unlock list of bikes because no more action is pending.
BikesViewModel.ActionText = string.Empty; // Todo: Move this statement in front of finally block because in catch block BikesViewModel.ActionText is already set to empty.
BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
public async Task<IRequestHandler> HandleRequestOption2()
/// <summary> Requst is not supported, button should be disabled. </summary>
/// <returns></returns>
public async Task<IRequestHandler> UnsupportedRequest()
{
Log.ForContext<DisposableOpen>().Error("Click of unsupported button detected.");
Log.ForContext<DisposableOpen>().Error("Click of unsupported button click detected.");
return await Task.FromResult<IRequestHandler>(this);
}
}

View file

@ -30,7 +30,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
public bool IsLockitButtonVisible => false;
public string LockitButtonText => this.GetType().Name;
public string LockitButtonText => GetType().Name;
public bool IsConnected => false;
@ -40,7 +40,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
public bool IsButtonVisible => false;
public string ButtonText => this.GetType().Name;
public string ButtonText => GetType().Name;
/// <summary> Gets if the bike has to be remvoed after action has been completed. </summary>
public bool IsRemoveBikeRequired => false;

View file

@ -1,6 +1,5 @@
using Serilog;
using System;
using System.ComponentModel;
using System.Threading.Tasks;
using TINK.Model.State;
using TINK.View;
@ -66,7 +65,11 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock
try
{
// Switch to map page
#if USEMASTERDETAIL || USEFLYOUT
ViewService.ShowPage(ViewTypes.LoginPage);
#else
await ViewService.ShowPage("//LoginPage");
#endif
}
catch (Exception p_oException)
{

View file

@ -2,7 +2,7 @@
using System;
using System.Threading.Tasks;
using TINK.Model.Connector;
using TINK.Model.Repository.Exception;
using TINK.Repository.Exception;
using TINK.Model.Bike.BluetoothLock;
using TINK.Model.State;
using TINK.View;
@ -13,7 +13,7 @@ using TINK.Services.BluetoothLock;
using TINK.Services.BluetoothLock.Exception;
using TINK.MultilingualResources;
using TINK.Model.User;
using TINK.Repository.Exception;
using TINK.Model.Device;
namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{
@ -25,6 +25,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
/// </remarks>
public class ReservedClosed : Base, IRequestHandler
{
/// <param name="smartDevice">Provides info about the smart device (phone, tablet, ...)</param>
/// <param name="bikesViewModel">View model to be used for progress report and unlocking/ locking view.</param>
public ReservedClosed(
IBikeInfoMutable selectedBike,
@ -33,6 +34,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
IGeolocation geolocation,
ILocksService lockService,
Func<IPollingUpdateTaskManager> viewUpdateManager,
ISmartDevice smartDevice,
IViewService viewService,
IBikesViewModel bikesViewModel,
IUser activeUser) : base(
@ -43,7 +45,8 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
connectorFactory,
geolocation,
lockService,
viewUpdateManager,
viewUpdateManager,
smartDevice,
viewService,
bikesViewModel,
activeUser)
@ -56,13 +59,19 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
public override InUseStateEnum State => InUseStateEnum.Reserved;
/// <summary> Cancel reservation. </summary>
public async Task<IRequestHandler> HandleRequestOption1()
public async Task<IRequestHandler> HandleRequestOption1() => await CancelReservation();
/// <summary> Open lock and book bike. </summary>
public async Task<IRequestHandler> HandleRequestOption2() => await OpenLockAndDooBook();
/// <summary> Cancel reservation. </summary>
public async Task<IRequestHandler> CancelReservation()
{
BikesViewModel.IsIdle = false; // Lock list to avoid multiple taps while copri action is pending.
var l_oResult = await ViewService.DisplayAlert(
string.Empty,
string.Format(AppResources.QuestionCancelReservation, SelectedBike.GetDisplayName()),
string.Format(AppResources.QuestionCancelReservation, SelectedBike.GetFullDisplayName()),
AppResources.QuestionAnswerYes,
AppResources.QuestionAnswerNo);
@ -125,7 +134,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically(); // Restart polling again.
BikesViewModel.ActionText = "";
BikesViewModel.IsIdle = true; // Unlock GUI
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
Log.ForContext<BikesViewModel>().Information("User canceled reservation of bike {l_oId} successfully.", SelectedBike.Id);
@ -147,18 +156,18 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically(); // Restart polling again.
BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; // Unlock GUI
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
/// <summary> Open lock and book bike. </summary>
public async Task<IRequestHandler> HandleRequestOption2()
public async Task<IRequestHandler> OpenLockAndDooBook()
{
BikesViewModel.IsIdle = false;
// Ask whether to really book bike?
var l_oResult = await ViewService.DisplayAlert(
string.Empty,
string.Format(AppResources.MessageOpenLockAndBookeBike, SelectedBike.GetDisplayName()),
string.Format(AppResources.MessageOpenLockAndBookeBike, SelectedBike.GetFullDisplayName()),
AppResources.MessageAnswerYes,
AppResources.MessageAnswerNo);
@ -212,7 +221,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
BikesViewModel.ActionText = AppResources.ActivityTextStartingUpdater;
await ViewUpdateManager().StartUpdateAyncPeridically(); // Restart polling again.
BikesViewModel.IsIdle = true; // Unlock GUI
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
// Unlock bike.
@ -233,13 +242,22 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
AppResources.ErrorOpenLockOutOfReadMessage,
"OK");
}
else if (exception is CouldntOpenBoldBlockedException)
else if (exception is CouldntOpenBoldIsBlockedException)
{
Log.ForContext<BookedOpen>().Debug("Lock can not be opened. Bold is blocked. {Exception}", exception);
await ViewService.DisplayAlert(
AppResources.ErrorOpenLockTitle,
AppResources.ErrorOpenLockMessage,
AppResources.ErrorOpenLockBoldBlockedMessage,
"OK");
}
else if (exception is CouldntOpenBoldWasBlockedException)
{
Log.ForContext<BookedClosed>().Debug("Lock can not be opened. Bold was or is blocked. {Exception}", exception);
await ViewService.DisplayAlert(
AppResources.ErrorOpenLockStillOpenTitle,
AppResources.ErrorOpenLockBoldWasBlockedMessage,
"OK");
}
else if (exception is CouldntOpenInconsistentStateExecption inconsistentState
@ -270,7 +288,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
if (SelectedBike.LockInfo.State != LockingState.Open)
@ -281,13 +299,13 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
BikesViewModel.ActionText = "";
BikesViewModel.IsIdle = true; // Unlock GUI
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
BikesViewModel.ActionText = AppResources.ActivityTextReadingChargingLevel;
try
{
SelectedBike.LockInfo.BatteryPercentage = (await LockService[SelectedBike.LockInfo.Id].GetBatteryPercentageAsync());
SelectedBike.LockInfo.BatteryPercentage = await LockService[SelectedBike.LockInfo.Id].GetBatteryPercentageAsync();
}
catch (Exception exception)
{
@ -342,7 +360,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically(); // Restart polling again.
BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; // Unlock GUI
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
}
}

View file

@ -2,7 +2,7 @@
using System;
using System.Threading.Tasks;
using TINK.Model.Connector;
using TINK.Model.Repository.Exception;
using TINK.Repository.Exception;
using TINK.Model.Bike.BluetoothLock;
using TINK.Model.State;
using TINK.View;
@ -13,12 +13,13 @@ using TINK.Services.BluetoothLock.Tdo;
using TINK.MultilingualResources;
using TINK.Model.Bikes.Bike.BluetoothLock;
using TINK.Model.User;
using TINK.Repository.Exception;
using TINK.Model.Device;
namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{
public class ReservedDisconnected : Base, IRequestHandler
{
/// <param name="smartDevice">Provides info about the smart device (phone, tablet, ...)</param>
/// <param name="bikesViewModel">View model to be used for progress report and unlocking/ locking view.</param>
public ReservedDisconnected(
IBikeInfoMutable selectedBike,
@ -27,6 +28,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
IGeolocation geolocation,
ILocksService lockService,
Func<IPollingUpdateTaskManager> viewUpdateManager,
ISmartDevice smartDevice,
IViewService viewService,
IBikesViewModel bikesViewModel,
IUser activeUser) : base(
@ -38,6 +40,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
geolocation,
lockService,
viewUpdateManager,
smartDevice,
viewService,
bikesViewModel,
activeUser)
@ -50,13 +53,20 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
public override InUseStateEnum State => InUseStateEnum.Reserved;
/// <summary> Cancel reservation. </summary>
public async Task<IRequestHandler> HandleRequestOption1()
public async Task<IRequestHandler> HandleRequestOption1() => await CancelReservation();
/// <summary> Connect to reserved bike ask whether to book bike bike or not and if yes open lock. </summary>
/// <returns></returns>
public async Task<IRequestHandler> HandleRequestOption2() => await ConnectLockAndBook();
/// <summary> Cancel reservation. </summary>
public async Task<IRequestHandler> CancelReservation()
{
BikesViewModel.IsIdle = false; // Lock list to avoid multiple taps while copri action is pending.
var alertResult = await ViewService.DisplayAlert(
string.Empty,
string.Format(AppResources.QuestionCancelReservation, SelectedBike.GetDisplayName()),
string.Format(AppResources.QuestionCancelReservation, SelectedBike.GetFullDisplayName()),
AppResources.QuestionAnswerYes,
AppResources.QuestionAnswerNo);
@ -111,7 +121,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically(); // Restart polling again.
BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; // Unlock GUI
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
Log.ForContext<ReservedDisconnected>().Information("User canceled reservation of bike {l_oId} successfully.", SelectedBike.Id);
@ -120,12 +130,12 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically(); // Restart polling again.
BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; // Unlock GUI
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
/// <summary> Connect to reserved bike. </summary>
/// <summary> Connect to reserved bike ask whether to book bike bike or not and if yes open lock. </summary>
/// <returns></returns>
public async Task<IRequestHandler> HandleRequestOption2()
public async Task<IRequestHandler> ConnectLockAndBook()
{
BikesViewModel.IsIdle = false;
Log.ForContext<ReservedDisconnected>().Information("Request to search for {bike} detected.", SelectedBike);
@ -209,11 +219,12 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
else
{
Log.ForContext<ReservedDisconnected>().Error("Lock state can not be retrieved. {Exception}", exception);
continueConnect = await ViewService.DisplayAlert(
"Fehler bei Verbinden mit Schloss!",
$"{AppResources.ErrorReservedSearchMessage}\r\nDetails:\r\n{exception.Message}",
"Wiederholen",
"Abbrechen");
continueConnect = await ViewService.DisplayAdvancedAlert(
"Fehler bei Verbinden mit Schloss!",
AppResources.ErrorReservedSearchMessage,
exception.Message,
"Wiederholen",
"Abbrechen");
}
if (continueConnect)
@ -259,7 +270,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
// Ask whether to really book bike?
var alertResult = await ViewService.DisplayAlert(
string.Empty,
string.Format(AppResources.MessageOpenLockAndBookeBike, SelectedBike.GetDisplayName()),
string.Format(AppResources.MessageOpenLockAndBookeBike, SelectedBike.GetFullDisplayName()),
AppResources.MessageAnswerYes,
AppResources.MessageAnswerNo);
@ -286,7 +297,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically();
BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
Log.ForContext<ReservedDisconnected>().Information("User selected recently requested bike {bike} in order to book.", SelectedBike);
@ -327,7 +338,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
BikesViewModel.ActionText = AppResources.ActivityTextStartingUpdater;
await ViewUpdateManager().StartUpdateAyncPeridically(); // Restart polling again.
BikesViewModel.IsIdle = true; // Unlock GUI
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
// Unlock bike.
@ -348,13 +359,22 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
AppResources.ErrorOpenLockOutOfReadMessage,
"OK");
}
else if (exception is CouldntOpenBoldBlockedException)
else if (exception is CouldntOpenBoldIsBlockedException)
{
Log.ForContext<ReservedDisconnected>().Debug("Lock can not be opened. Bold is blocked. {Exception}", exception);
await ViewService.DisplayAlert(
AppResources.ErrorOpenLockTitle,
AppResources.ErrorOpenLockMessage,
AppResources.ErrorOpenLockBoldBlockedMessage,
"OK");
}
else if (exception is CouldntOpenBoldWasBlockedException)
{
Log.ForContext<BookedClosed>().Debug("Lock can not be opened. Bold was or is blocked. {Exception}", exception);
await ViewService.DisplayAlert(
AppResources.ErrorOpenLockStillOpenTitle,
AppResources.ErrorOpenLockBoldWasBlockedMessage,
"OK");
}
else if (exception is CouldntOpenInconsistentStateExecption inconsistentState
@ -385,7 +405,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
if (SelectedBike.LockInfo.State != LockingState.Open)
@ -396,13 +416,13 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
BikesViewModel.ActionText = "";
BikesViewModel.IsIdle = true; // Unlock GUI
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
BikesViewModel.ActionText = AppResources.ActivityTextReadingChargingLevel;
try
{
SelectedBike.LockInfo.BatteryPercentage = (await LockService[SelectedBike.LockInfo.Id].GetBatteryPercentageAsync());
SelectedBike.LockInfo.BatteryPercentage = await LockService[SelectedBike.LockInfo.Id].GetBatteryPercentageAsync();
}
catch (Exception exception)
{
@ -459,7 +479,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically();
BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; // Unlock GUI
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
}
}

View file

@ -2,7 +2,7 @@
using System;
using System.Threading.Tasks;
using TINK.Model.Connector;
using TINK.Model.Repository.Exception;
using TINK.Repository.Exception;
using TINK.Model.Bike.BluetoothLock;
using TINK.Model.State;
using TINK.View;
@ -12,6 +12,7 @@ using TINK.Services.BluetoothLock.Exception;
using TINK.Model.Bikes.Bike.BluetoothLock;
using TINK.MultilingualResources;
using TINK.Model.User;
using TINK.Model.Device;
namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{
@ -23,6 +24,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
/// - two devices can not simultaneously conect to same lock.
public class ReservedOpen : Base, IRequestHandler
{
/// <param name="smartDevice">Provides info about the smart device (phone, tablet, ...)</param>
/// <param name="bikesViewModel">View model to be used for progress report and unlocking/ locking view.</param>
public ReservedOpen(
IBikeInfoMutable selectedBike,
@ -31,6 +33,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
IGeolocation geolocation,
ILocksService lockService,
Func<IPollingUpdateTaskManager> viewUpdateManager,
ISmartDevice smartDevice,
IViewService viewService,
IBikesViewModel bikesViewModel,
IUser activeUser) : base(
@ -42,6 +45,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
geolocation,
lockService,
viewUpdateManager,
smartDevice,
viewService,
bikesViewModel,
activeUser)
@ -54,13 +58,20 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
public override InUseStateEnum State => InUseStateEnum.Reserved;
/// <summary> Cancel reservation. </summary>
public async Task<IRequestHandler> HandleRequestOption1()
public async Task<IRequestHandler> HandleRequestOption1() => await CloseLockOrDoBook();
/// <summary> Manage sound/ alarm settings. </summary>
/// <returns></returns>
public async Task<IRequestHandler> HandleRequestOption2() => await ManageLockSettings();
/// <summary> Cancel reservation. </summary>
public async Task<IRequestHandler> CloseLockOrDoBook()
{
BikesViewModel.IsIdle = false; // Lock list to avoid multiple taps while copri action is pending.
var l_oResult = await ViewService.DisplayAlert(
string.Empty,
string.Format("Rad {0} abschließen und zurückgeben oder Rad mieten?", SelectedBike.GetDisplayName()),
string.Format("Rad {0} abschließen und zurückgeben oder Rad mieten?", SelectedBike.GetFullDisplayName()),
"Zurückgeben",
"Mieten");
@ -76,7 +87,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
BikesViewModel.ActionText = AppResources.ActivityTextReadingChargingLevel;
try
{
SelectedBike.LockInfo.BatteryPercentage = (await LockService[SelectedBike.LockInfo.Id].GetBatteryPercentageAsync());
SelectedBike.LockInfo.BatteryPercentage = await LockService[SelectedBike.LockInfo.Id].GetBatteryPercentageAsync();
}
catch (Exception exception)
{
@ -145,7 +156,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; // Unlock GUI
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
Log.ForContext<ReservedOpen>().Information("User booked bike {bike} successfully.", SelectedBike);
@ -155,7 +166,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; // Unlock GUI
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
// Close lock and cancel reservation.
@ -214,7 +225,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically(); // Restart polling again.
BikesViewModel.ActionText = "";
BikesViewModel.IsIdle = true; // Unlock GUI
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
BikesViewModel.ActionText = AppResources.ActivityTextCancelingReservation;
@ -255,7 +266,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically(); // Restart polling again.
BikesViewModel.ActionText = "";
BikesViewModel.IsIdle = true; // Unlock GUI
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
Log.ForContext<ReservedOpen>().Information("User canceled reservation of bike {l_oId} successfully.", SelectedBike.Id);
@ -277,12 +288,12 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically(); // Restart polling again.
BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; // Unlock GUI
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
/// <summary> Manage sound/ alarm settings. </summary>
/// <returns></returns>
public async Task<IRequestHandler> HandleRequestOption2()
public async Task<IRequestHandler> ManageLockSettings()
{
// Stop polling before requesting bike.
BikesViewModel.ActionText = AppResources.ActivityTextOneMomentPlease;
@ -384,7 +395,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
exception.Message,
"OK");
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
finally
{
@ -461,7 +472,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
exception.Message,
"OK");
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
finally
{

View file

@ -5,21 +5,22 @@ using TINK.Model.Bike.BluetoothLock;
using TINK.Model.Connector;
using TINK.Model.State;
using TINK.View;
using TINK.Model.Repository.Exception;
using TINK.Repository.Exception;
using TINK.Model.Services.Geolocation;
using TINK.Services.BluetoothLock;
using TINK.Services.BluetoothLock.Exception;
using TINK.MultilingualResources;
using TINK.Model.Bikes.Bike.BluetoothLock;
using TINK.Model.User;
using TINK.Repository.Exception;
using Xamarin.Essentials;
using TINK.Model.Repository.Request;
using TINK.Repository.Request;
using TINK.Model.Device;
namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{
public class ReservedUnknown : Base, IRequestHandler
{
/// <param name="smartDevice">Provides info about the smart device (phone, tablet, ...)</param>
/// <param name="bikesViewModel">View model to be used for progress report and unlocking/ locking view.</param>
public ReservedUnknown(
IBikeInfoMutable selectedBike,
@ -28,6 +29,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
IGeolocation geolocation,
ILocksService lockService,
Func<IPollingUpdateTaskManager> viewUpdateManager,
ISmartDevice smartDevice,
IViewService viewService,
IBikesViewModel bikesViewModel,
IUser activeUser) : base(
@ -39,6 +41,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
geolocation,
lockService,
viewUpdateManager,
smartDevice,
viewService,
bikesViewModel,
activeUser)
@ -79,13 +82,22 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
AppResources.ErrorOpenLockOutOfReadMessage,
"OK");
}
else if (exception is CouldntOpenBoldBlockedException)
else if (exception is CouldntOpenBoldIsBlockedException)
{
Log.ForContext<ReservedUnknown>().Debug("Lock can not be opened. Bold is blocked. {Exception}", exception);
await ViewService.DisplayAlert(
AppResources.ErrorOpenLockTitle,
AppResources.ErrorOpenLockMessage,
AppResources.ErrorOpenLockBoldBlockedMessage,
"OK");
}
else if (exception is CouldntOpenBoldWasBlockedException)
{
Log.ForContext<BookedClosed>().Debug("Lock can not be opened. Bold was or is blocked. {Exception}", exception);
await ViewService.DisplayAlert(
AppResources.ErrorOpenLockStillOpenTitle,
AppResources.ErrorOpenLockBoldWasBlockedMessage,
"OK");
}
else if (exception is CouldntOpenInconsistentStateExecption inconsistentState
@ -118,13 +130,13 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically();
BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
BikesViewModel.ActionText = AppResources.ActivityTextReadingChargingLevel;
try
{
SelectedBike.LockInfo.BatteryPercentage = (await LockService[SelectedBike.LockInfo.Id].GetBatteryPercentageAsync());
SelectedBike.LockInfo.BatteryPercentage = await LockService[SelectedBike.LockInfo.Id].GetBatteryPercentageAsync();
}
catch (Exception exception)
{
@ -179,7 +191,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically();
BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
/// <summary> Close lock in order to pause ride and update COPRI lock state.</summary>
@ -246,7 +258,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically();
BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
// Get geoposition.
@ -313,7 +325,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically();
BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, ViewService, BikesViewModel, ActiveUser);
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
}
}

View file

@ -8,6 +8,7 @@ using TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler;
using TINK.Model.User;
using TINK.MultilingualResources;
using Serilog;
using TINK.Model.Device;
namespace TINK.ViewModel.Bikes.Bike.BluetoothLock
{
@ -19,6 +20,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock
/// <param name="connectorFactory"></param>
/// <param name="bikeRemoveDelegate"></param>
/// <param name="viewUpdateManager"></param>
/// <param name="smartDevice">Provides info about the smart device (phone, tablet, ...)</param>
/// <param name="viewService"></param>
/// <param name="bikesViewModel">View model to be used for progress report and unlocking/ locking view.</param>
/// <returns>Request handler.</returns>
@ -29,6 +31,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock
IGeolocation geolocation,
ILocksService lockService,
Func<IPollingUpdateTaskManager> viewUpdateManager,
ISmartDevice smartDevice,
IViewService viewService,
IBikesViewModel bikesViewModel,
IUser activeUser)
@ -75,6 +78,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock
geolocation,
lockService,
viewUpdateManager,
smartDevice,
viewService,
bikesViewModel,
activeUser);
@ -88,6 +92,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock
geolocation,
lockService,
viewUpdateManager,
smartDevice,
viewService,
bikesViewModel,
activeUser);
@ -107,6 +112,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock
geolocation,
lockService,
viewUpdateManager,
smartDevice,
viewService,
bikesViewModel,
activeUser);
@ -119,6 +125,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock
geolocation,
lockService,
viewUpdateManager,
smartDevice,
viewService,
bikesViewModel,
activeUser);
@ -134,6 +141,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock
geolocation,
lockService,
viewUpdateManager,
smartDevice,
viewService,
bikesViewModel,
activeUser);
@ -147,6 +155,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock
geolocation,
lockService,
viewUpdateManager,
smartDevice,
viewService,
bikesViewModel,
activeUser);
@ -170,6 +179,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock
geolocation,
lockService,
viewUpdateManager,
smartDevice,
viewService,
bikesViewModel,
activeUser);
@ -183,6 +193,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock
geolocation,
lockService,
viewUpdateManager,
smartDevice,
viewService,
bikesViewModel,
activeUser);
@ -196,6 +207,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock
geolocation,
lockService,
viewUpdateManager,
smartDevice,
viewService,
bikesViewModel,
activeUser);
@ -210,6 +222,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock
geolocation,
lockService,
viewUpdateManager,
smartDevice,
viewService,
bikesViewModel,
activeUser);

View file

@ -27,9 +27,13 @@ namespace TINK.ViewModel.Bikes.Bike
// No tariff description details available.
return string.Empty;
#if USCSHARP9
return string.Format(AppResources.MessageBikesManagementTariffDescriptionTariffHeader, Tariff?.Name ?? "-", Tariff?.Number != null ? Tariff.Number : "-");
#else
return string.Format(AppResources.MessageBikesManagementTariffDescriptionTariffHeader, Tariff?.Name ?? "-", Tariff?.Number != null ? Tariff.Number.ToString() : "-");
#endif
}
}
}
/// <summary>
/// Costs per hour in euro.

View file

@ -14,11 +14,16 @@ using TINK.ViewModel.Bikes.Bike;
using TINK.ViewModel.Bikes.Bike.BC;
using Plugin.Permissions.Abstractions;
using Plugin.BLE.Abstractions.Contracts;
using TINK.MultilingualResources;
using TINK.Model.Device;
namespace TINK.ViewModel.Bikes
{
public abstract class BikesViewModel : ObservableCollection<BikeViewModelBase>, IBikesViewModel
{
/// <summary> Provides info about the smart device (phone, tablet, ...).</summary>
protected ISmartDevice SmartDevice;
/// <summary>
/// Reference on view servcie to show modal notifications and to perform navigation.
/// </summary>
@ -73,6 +78,7 @@ namespace TINK.ViewModel.Bikes
/// </summary>
/// </param>
/// <param name="p_oUser">Mail address of active user.</param>
/// <param name="isReportLevelVerbose">True if report level is verbose, false if not.</param>
/// <param name="permissions">Holds object to query location permisions.</param>
/// <param name="bluetoothLE">Holds object to query bluetooth state.</param>
/// <param name="runtimPlatform">Specifies on which platform code is run.</param>
@ -81,6 +87,7 @@ namespace TINK.ViewModel.Bikes
/// <param name="lockService">Service to control lock retrieve info.</param>
/// <param name="p_oPolling"> Holds whether to poll or not and the periode leght is polling is on. </param>
/// <param name="postAction">Executes actions on GUI thread.</param>
/// <param name="smartDevice">Provides info about the smart device (phone, tablet, ...)</param>
/// <param name="p_oViewService">Interface to actuate methodes on GUI.</param>
public BikesViewModel(
User user,
@ -93,19 +100,20 @@ namespace TINK.ViewModel.Bikes
ILocksService lockService,
TINK.Settings.PollingParameters polling,
Action<SendOrPostCallback, object> postAction,
ISmartDevice smartDevice,
IViewService viewService,
Func<IInUseStateInfoProvider> itemFactory)
{
User = user
?? throw new ArgumentException("Can not instantiate bikes page view model- object. No user available.");
RuntimePlatform = runtimPlatform
?? throw new ArgumentException("Can not instantiate bikes page view model- object. No runtime platform information available.");
Permissions = permissions
PermissionsService = permissions
?? throw new ArgumentException("Can not instantiate bikes page view model- object. No permissions available.");
BluetoothLE = bluetoothLE
BluetoothService = bluetoothLE
?? throw new ArgumentException("Can not instantiate bikes page view model- object. No bluetooth available.");
ConnectorFactory = connectorFactory
@ -126,6 +134,9 @@ namespace TINK.ViewModel.Bikes
PostAction = postAction
?? throw new ArgumentException("Can not instantiate bikes page view model- object. No post action available.");
SmartDevice = smartDevice
?? throw new ArgumentException("Can not instantiate bikes page view model- object. No smart device object available.");
ViewService = viewService
?? throw new ArgumentException("Can not instantiate bikes page view model- object. No view available.");
@ -137,7 +148,7 @@ namespace TINK.ViewModel.Bikes
m_oPolling = polling;
IsConnected = IsConnectedDelegate();
isConnected = IsConnectedDelegate();
CollectionChanged += (sender, eventargs) =>
{
@ -170,6 +181,7 @@ namespace TINK.ViewModel.Bikes
LockService,
(id) => Remove(id),
() => m_oViewUpdateManager,
SmartDevice,
ViewService,
l_oBike,
User,
@ -207,12 +219,24 @@ namespace TINK.ViewModel.Bikes
protected User User { get; private set; }
#if USCSHARP9
public bool IsReportLevelVerbose { get; init; }
#else
public bool IsReportLevelVerbose { get; set; }
#endif
/// <summary> Specified whether code is run under iOS or Android.</summary>
protected string RuntimePlatform { get; private set; }
protected IPermissions Permissions { get; private set; }
/// <summary>
/// Service to manage permissions (location) of the app.
/// </summary>
protected IPermissions PermissionsService { get; private set; }
protected IBluetoothLE BluetoothLE { get; private set; }
/// <summary>
/// Service to manage bluetooth stack.
/// </summary>
protected IBluetoothLE BluetoothService { get; private set; }
/// <summary>
/// User which is logged in.
@ -349,12 +373,14 @@ namespace TINK.ViewModel.Bikes
if (Exception != null)
{
// An error occurred getting data from copri.
return Exception.GetShortErrorInfoText();
return IsReportLevelVerbose
? Exception.GetShortErrorInfoText()
: AppResources.ActivityTextException;
}
if (!IsConnected)
{
return "Offline.";
return AppResources.ActivityTextConnectionStateOffline;
}
return ActionText ?? string.Empty;
@ -364,12 +390,12 @@ namespace TINK.ViewModel.Bikes
/// <summary>
/// Removes a bike view model by id.
/// </summary>
/// <param name="p_iId">Id of bike to removed.</param>
public void Remove(int p_iId)
/// <param name="id">Id of bike to removed.</param>
public void Remove(string id)
{
foreach (var bike in BikeCollection)
{
if (bike.Id == p_iId)
if (bike.Id == id)
{
BikeCollection.Remove(bike);
return;
@ -380,13 +406,13 @@ namespace TINK.ViewModel.Bikes
/// <summary>
/// Gets whether a bike is contained in collection of bikes.
/// </summary>
/// <param name="p_iId">Id of bike to check existance.</param>
/// <param name="id">Id of bike to check existance.</param>
/// <returns>True if bike exists.</returns>
private bool Contains(int p_iId)
private bool Contains(string id)
{
foreach (var l_oBike in Items)
{
if (l_oBike.Id == p_iId)
if (l_oBike.Id == id)
{
return true;
}