Version 3.0.368

This commit is contained in:
Anja 2023-07-04 11:06:38 +02:00
parent 24cdfbb0ca
commit 1a58bf58d3
78 changed files with 3104 additions and 2823 deletions

View file

@ -48,7 +48,7 @@ namespace TINK.ViewModel.Bikes.Bike.BC
IUser activeUser,
IInUseStateInfoProvider stateInfoProvider,
IBikesViewModel bikesViewModel,
Action<string> openUrlInBrowser) : base(isConnectedDelegate, connectorFactory, bikeRemoveDelegate, viewUpdateManager, smartDevice, viewService, selectedBike, activeUser, stateInfoProvider, bikesViewModel, openUrlInBrowser)
Action<string> openUrlInBrowser) : base(isConnectedDelegate, connectorFactory, bikeRemoveDelegate, viewUpdateManager, smartDevice, viewService, selectedBike, activeUser, new ViewContext(PageContext.BikesAtStation), stateInfoProvider, bikesViewModel, openUrlInBrowser)
{
RequestHandler = activeUser.IsLoggedIn
? RequestHandlerFactory.Create(
@ -107,12 +107,10 @@ namespace TINK.ViewModel.Bikes.Bike.BC
public System.Windows.Input.ICommand OnButtonClicked => new Xamarin.Forms.Command(async () =>
{
var lastHandler = RequestHandler;
var lastState = Bike.State.Value;
RequestHandler = await RequestHandler.HandleRequest();
if (lastHandler.IsRemoveBikeRequired)
{
BikeRemoveDelegate(Id);
}
CheckRemoveBike(Id, lastState);
if (lastHandler.GetType() == RequestHandler.GetType())
{

View file

@ -62,10 +62,6 @@ namespace TINK.ViewModel.Bikes.Bike.BC.RequestHandler
}
}
/// <summary> Gets if the bike has to be removed after action has been completed. </summary>
public bool IsRemoveBikeRequired { get; set; }
/// <summary>
/// Constructs the request handler base.
/// </summary>
@ -93,7 +89,6 @@ namespace TINK.ViewModel.Bikes.Bike.BC.RequestHandler
SmartDevice = smartDevice;
ViewService = viewService;
ActiveUser = activeUser;
IsRemoveBikeRequired = false;
BikesViewModel = bikesViewModel
?? throw new ArgumentException($"Can not construct {GetType().Name}-object. {nameof(bikesViewModel)} must not be null.");
}

View file

@ -60,9 +60,6 @@ namespace TINK.ViewModel.Bikes.Bike.BC.RequestHandler
IsConnected = IsConnectedDelegate();
await ConnectorFactory(IsConnected).Command.DoCancelReservation(SelectedBike);
// If canceling bike succeeds remove bike because it is not ready to be booked again
IsRemoveBikeRequired = true;
}
catch (Exception exception)
{

View file

@ -59,6 +59,9 @@ namespace TINK.ViewModel.Bikes.Bike
/// <summary> Reference on the user </summary>
protected IUser ActiveUser { get; }
/// <summary> Holds the view context in which bike view model is used.</summary>
protected ViewContext ViewContext { get; }
/// <summary>
/// Provides context related info.
/// </summary>
@ -89,6 +92,7 @@ namespace TINK.ViewModel.Bikes.Bike
/// <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="viewContext"> Holds the view context in which bike view model is used.</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>
/// <param name="openUrlInBrowser">Delegate to open browser.</param>
@ -101,6 +105,7 @@ namespace TINK.ViewModel.Bikes.Bike
IViewService viewService,
BikeInfoMutable selectedBike,
IUser activeUser,
ViewContext viewContext,
IInUseStateInfoProvider stateInfoProvider,
IBikesViewModel bikesViewModel,
Action<string> openUrlInBrowser)
@ -123,6 +128,8 @@ namespace TINK.ViewModel.Bikes.Bike
ActiveUser = activeUser
?? throw new ArgumentException(string.Format("Can not construct {0}- object, user object is null.", typeof(BikeViewModelBase)));
ViewContext = viewContext;
StateInfoProvider = stateInfoProvider
?? throw new ArgumentException(string.Format("Can not construct {0}- object, user object is null.", typeof(IInUseStateInfoProvider)));
@ -385,5 +392,57 @@ namespace TINK.ViewModel.Bikes.Bike
return string.Empty;
}
}
/// <summary>
/// Check if bike has to be removed and if yes invoke remove delegate.
/// </summary>
/// <param name="Id">Id of bike to remove.</param>
/// <param name="lastState">Previous state used to decide whether to remove bike or not.</param>
public void CheckRemoveBike(string Id, InUseStateEnum lastState)
{
switch (ViewContext.Page)
{
case PageContext.MyBikes:
// Bike is shown on page My Bikes.
switch (Bike.State.Value)
{
case InUseStateEnum.FeedbackPending:
case InUseStateEnum.Reserved:
case InUseStateEnum.Booked:
// Bike has still to be shown at my bikes page to give feedback or manage bike.
break;
default:
BikeRemoveDelegate(Id);
break;
}
break;
case PageContext.BikesAtStation:
// Bike is shown on page Bike At Station.
switch (lastState != InUseStateEnum.Booked)
{
case true:
// Only remove bike if bike was rented before.
break;
default:
switch (ViewContext.StationId == Bike.StationId)
{
case true:
// Do not remove bike if bike is returned a current station.
break;
default:
BikeRemoveDelegate(Id);
break;
}
break;
}
break;
}
}
}
}

View file

@ -11,6 +11,7 @@ namespace TINK.ViewModel.Bikes.Bike
public static class BikeViewModelFactory
{
/// <param name="smartDevice">Provides info about the smart device (phone, tablet, ...).</param>
/// <param name="viewContext"> Holds the view context in which bike view model is used.</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>
/// <param name="openUrlInBrowser">Delegate to open browser.</param>
@ -25,6 +26,7 @@ namespace TINK.ViewModel.Bikes.Bike
IViewService viewService,
Model.Bikes.BikeInfoNS.BC.BikeInfoMutable bikeInfo,
IUser activeUser,
ViewContext viewContext,
IInUseStateInfoProvider stateInfoProvider,
IBikesViewModel bikesViewModel,
Action<string> openUrlInBrowser)
@ -42,6 +44,7 @@ namespace TINK.ViewModel.Bikes.Bike
viewService,
bikeInfo as Model.Bikes.BikeInfoNS.BluetoothLock.BikeInfoMutable,
activeUser,
viewContext,
stateInfoProvider,
bikesViewModel,
openUrlInBrowser);
@ -57,6 +60,7 @@ namespace TINK.ViewModel.Bikes.Bike
viewService,
bikeInfo,
activeUser,
viewContext,
stateInfoProvider,
bikesViewModel,
openUrlInBrowser);

View file

@ -2,7 +2,6 @@ using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using Plugin.Connectivity;
using TINK.Model.Connector;
using TINK.Model.Device;
using TINK.Model.User;
@ -86,6 +85,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock
/// <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="viewContext"> Holds the view context in which bike view model is used.</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>
/// <param name="openUrlInBrowser">Delegate to open browser.</param>
@ -100,9 +100,10 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock
IViewService viewService,
BikeInfoMutable selectedBike,
IUser user,
ViewContext viewContext,
IInUseStateInfoProvider stateInfoProvider,
IBikesViewModel bikesViewModel,
Action<string> openUrlInBrowser) : base(isConnectedDelegate, connectorFactory, bikeRemoveDelegate, viewUpdateManager, smartDevice, viewService, selectedBike, user, stateInfoProvider, bikesViewModel, openUrlInBrowser)
Action<string> openUrlInBrowser) : base(isConnectedDelegate, connectorFactory, bikeRemoveDelegate, viewUpdateManager, smartDevice, viewService, selectedBike, user, viewContext, stateInfoProvider, bikesViewModel, openUrlInBrowser)
{
ShowTrackingInfoCommand = new Xamarin.Forms.Command(async () => {
@ -203,15 +204,13 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock
private async Task ClickButton(Task<IRequestHandler> handleRequest)
{
var lastHandler = RequestHandler;
var lastState = Bike.State.Value;
var lastStateText = StateText;
var lastStateColor = StateColor;
RequestHandler = await handleRequest;
if (lastHandler.IsRemoveBikeRequired)
{
BikeRemoveDelegate(Id);
}
CheckRemoveBike(Id, lastState);
if (RuntimeHelpers.Equals(lastHandler, RequestHandler))
{

View file

@ -181,7 +181,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
Log.ForContext<BookedClosed>().Information("Returning closed bike {Bike} is not possible. Cancel geolocation query failed. {Exception}", SelectedBike, ex);
await ViewService.DisplayAlert(
AppResources.ErrorReturnBikeTitle,
AppResources.ErrorQueryGeolocation,
AppResources.ErrorReturnBikeLockClosedGetGPSExceptionMessage,
AppResources.MessageAnswerOk);
@ -215,9 +215,6 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
bookingFinished = await ConnectorFactory(IsConnected).Command.DoReturn(
SelectedBike,
currentLocationDto);
// If canceling bike succeeds remove bike because it is not ready to be booked again
IsRemoveBikeRequired = true;
}
catch (Exception exception)
{

View file

@ -360,8 +360,6 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
SelectedBike,
currentLocationDto,
SmartDevice);
// If canceling bike succeeds remove bike because it is not ready to be booked again
IsRemoveBikeRequired = true;
}
catch (Exception exception)
{

View file

@ -90,9 +90,6 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
try
{
await ConnectorFactory(IsConnected).Command.DoCancelReservation(SelectedBike);
// If canceling bike succeeds remove bike because it is not ready to be booked again
IsRemoveBikeRequired = true;
}
catch (Exception exception)
{

View file

@ -85,9 +85,6 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
try
{
await ConnectorFactory(IsConnected).Command.DoCancelReservation(SelectedBike);
// If canceling bike succeeds remove bike because it is not ready to be booked again
IsRemoveBikeRequired = true;
}
catch (Exception exception)
{

View file

@ -228,9 +228,6 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
try
{
await ConnectorFactory(IsConnected).Command.DoCancelReservation(SelectedBike);
// If canceling bike succeeds remove bike because it is not ready to be booked again
IsRemoveBikeRequired = true;
}
catch (Exception exception)
{

View file

@ -77,6 +77,7 @@ namespace TINK.ViewModel.Bikes.Bike.CopriLock
/// <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="viewContext"> Holds the view context in which bike view model is used.</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>
/// <param name="openUrlInBrowser">Delegate to open browser.</param>
@ -89,9 +90,10 @@ namespace TINK.ViewModel.Bikes.Bike.CopriLock
IViewService viewService,
BikeInfoMutable selectedBike,
IUser user,
ViewContext viewContext,
IInUseStateInfoProvider stateInfoProvider,
IBikesViewModel bikesViewModel,
Action<string> openUrlInBrowser) : base(isConnectedDelegate, connectorFactory, bikeRemoveDelegate, viewUpdateManager, smartDevice, viewService, selectedBike, user, stateInfoProvider, bikesViewModel, openUrlInBrowser)
Action<string> openUrlInBrowser) : base(isConnectedDelegate, connectorFactory, bikeRemoveDelegate, viewUpdateManager, smartDevice, viewService, selectedBike, user, viewContext, stateInfoProvider, bikesViewModel, openUrlInBrowser)
{
RequestHandler = user.IsLoggedIn
? RequestHandlerFactory.Create(
@ -164,15 +166,13 @@ namespace TINK.ViewModel.Bikes.Bike.CopriLock
private async Task ClickButton(Task<IRequestHandler> handleRequest)
{
var lastHandler = RequestHandler;
var lastState = Bike.State.Value;
var lastStateText = StateText;
var lastStateColor = StateColor;
RequestHandler = await handleRequest;
if (lastHandler.IsRemoveBikeRequired)
{
BikeRemoveDelegate(Id);
}
CheckRemoveBike(Id, lastState);
if (RuntimeHelpers.Equals(lastHandler, RequestHandler))
{

View file

@ -84,9 +84,6 @@ namespace TINK.ViewModel.Bikes.Bike.CopriLock.RequestHandler
try
{
await ConnectorFactory(IsConnected).Command.DoCancelReservation(SelectedBike);
// If canceling bike succeeds remove bike because it is not ready to be booked again
IsRemoveBikeRequired = true;
}
catch (Exception exception)
{

View file

@ -21,8 +21,5 @@ namespace TINK.ViewModel.Bikes.Bike
/// <summary>Gets the is connected state. </summary>
bool IsConnected { get; }
/// <summary> Gets if the bike has to be removed after action has been completed. </summary>
bool IsRemoveBikeRequired { get; }
}
}

View file

@ -79,7 +79,8 @@ namespace TINK.ViewModel.Bikes
/// Constructs bike collection view model.
/// </summary>
/// </param>
/// <param name="p_oUser">Mail address of active user.</param>
/// <param name="user">Mail address of active user.</param>
/// <param name="viewContext"> Holds the view context in which bikes view model is used.</param>
/// <param name="isReportLevelVerbose">True if report level is verbose, false if not.</param>
/// <param name="permissions">Holds object to query location permissions.</param>
/// <param name="bluetoothLE">Holds object to query bluetooth state.</param>
@ -94,6 +95,7 @@ namespace TINK.ViewModel.Bikes
/// <param name="openUrlInBrowser">Delegate to open browser.</param>
public BikesViewModel(
User user,
ViewContext viewContext,
ILocationPermission permissions,
IBluetoothLE bluetoothLE,
string runtimPlatform,
@ -144,6 +146,8 @@ namespace TINK.ViewModel.Bikes
ViewService = viewService
?? throw new ArgumentException("Can not instantiate bikes page view model- object. No view available.");
ViewContext = viewContext;
m_oViewUpdateManager = new IdlePollingUpdateTaskManager();
BikeCollection = new BikeCollectionMutable();
@ -190,6 +194,7 @@ namespace TINK.ViewModel.Bikes
ViewService,
bike,
User,
ViewContext,
m_oItemFactory(),
this,
OpenUrlInBrowser);
@ -230,6 +235,9 @@ namespace TINK.ViewModel.Bikes
protected User User { get; private set; }
/// <summary> Holds the view context in which bikes view model is used.</summary>
private ViewContext ViewContext { get; }
#if USCSHARP9
public bool IsReportLevelVerbose { get; init; }
#else
@ -477,6 +485,6 @@ namespace TINK.ViewModel.Bikes
/// </summary>
public virtual async Task OnDisappearing()
=> await m_oViewUpdateManager.StopUpdatePeridically();
}
}

View file

@ -0,0 +1,47 @@
namespace TINK.ViewModel.Bikes
{
/// Holds the view context in which a view model is used.
public class ViewContext
{
/// <summary>
/// Constructs object.
/// </summary>
/// <param name="page">Value identifying the page to which view model relates to.</param>
/// <param name="stationId">Holds the id of the station if related page is <see cref="PageContext.BikesAtStation"/> ignored otherwise.</param>
public ViewContext(PageContext page, string stationId = null) {
Page = page;
if (page != PageContext.BikesAtStation)
{
// Station id must not contain a value if view context is not bikes at station page.
return;
}
StationId = stationId ?? string.Empty;
}
/// <summary>
/// Holds the page to which view model is related to.
/// </summary>
public PageContext Page { get; }
/// <summary>
/// Holds the id of the station if related page is <see cref="PageContext.BikesAtStation"/> empty otherwise.
/// </summary>
public string StationId { get; } = string.Empty;
}
/// <summary>
/// Holds the view context in which bikes view model is used.
/// </summary>
public enum PageContext
{
/// <summary> Context is bikes at station page. </summary>
BikesAtStation,
/// <summary> Context is find bike page. </summary>
FindBike,
/// <summary> Context is my bikes page. </summary>
MyBikes
}
}

View file

@ -86,7 +86,7 @@ namespace TINK.ViewModel.BikesAtStation
Action<string> openUrlInExternalBrowser,
Action<SendOrPostCallback, object> postAction,
ISmartDevice smartDevice,
IViewService viewService) : base(user, permissions, bluetoothLE, runtimPlatform, isConnectedDelegate, connectorFactory, geolocation, lockService, polling, postAction, smartDevice, viewService, openUrlInExternalBrowser, () => new BikeAtStationInUseStateInfoProvider())
IViewService viewService) : base(user, new ViewContext(PageContext.BikesAtStation, selectedStation.Id), permissions, bluetoothLE, runtimPlatform, isConnectedDelegate, connectorFactory, geolocation, lockService, polling, postAction, smartDevice, viewService, openUrlInExternalBrowser, () => new BikeAtStationInUseStateInfoProvider())
{
Station = selectedStation ?? new NullStation();

View file

@ -108,7 +108,7 @@ namespace TINK.ViewModel.FindBike
/// <summary>
/// Constructs bike collection view model in case information about occupied bikes is available.
/// </summary>
/// <param name="p_oUser">Mail address of active user.</param>
/// <param name="user">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 permissions.</param>
/// <param name="bluetoothLE">Holds object to query bluetooth state.</param>
@ -123,7 +123,7 @@ namespace TINK.ViewModel.FindBike
/// <param name="viewService">Interface to actuate methods on GUI.</param>
/// <param name="openUrlInBrowser">Delegate to open browser.</param>
public FindBikePageViewModel(
User p_oUser,
User user,
ILocationPermission permissions,
IBluetoothLE bluetoothLE,
string runtimPlatform,
@ -136,7 +136,7 @@ namespace TINK.ViewModel.FindBike
Action<SendOrPostCallback, object> postAction,
ISmartDevice smartDevice,
IViewService viewService,
Action<string> openUrlInBrowser) : base(p_oUser, permissions, bluetoothLE, runtimPlatform, isConnectedDelegate, connectorFactory, geolocation, lockService, polling, postAction, smartDevice, viewService, openUrlInBrowser, () => new MyBikeInUseStateInfoProvider())
Action<string> openUrlInBrowser) : base(user, new ViewContext(PageContext.FindBike), permissions, bluetoothLE, runtimPlatform, isConnectedDelegate, connectorFactory, geolocation, lockService, polling, postAction, smartDevice, viewService, openUrlInBrowser, () => new MyBikeInUseStateInfoProvider())
{
CollectionChanged += (sender, eventargs) =>
{
@ -172,8 +172,6 @@ namespace TINK.ViewModel.FindBike
Log.ForContext<FindBikePageViewModel>().Information("User request to show page FindBike- page re-appearing");
ActiveFilteredBikeType = string.Empty;
IsConnected = IsConnectedDelegate();
// Stop polling before getting bikes info.
@ -432,8 +430,6 @@ namespace TINK.ViewModel.FindBike
return;
}
BikeIdUserInput = string.Empty;
}
/// <summary> Create task which updates my bike view model.</summary>

View file

@ -55,7 +55,7 @@ namespace TINK.ViewModel.MyBikes
/// <summary>
/// Constructs bike collection view model in case information about occupied bikes is available.
/// </summary>
/// <param name="p_oUser">Mail address of active user.</param>
/// <param name="user">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 permissions.</param>
/// <param name="bluetoothLE">Holds object to query bluetooth state.</param>
@ -64,13 +64,13 @@ namespace TINK.ViewModel.MyBikes
/// <param name="connectorFactory">Connects system to copri.</param>
/// <param name="lockService">Service to control lock retrieve info.</param>
/// <param name="stations">Stations to get station name from station id.</param>
/// <param name="p_oPolling"> Holds whether to poll or not and the period length is polling is on. </param>
/// <param name="polling"> Holds whether to poll or not and the period length 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="viewService">Interface to actuate methods on GUI.</param>
/// <param name="openUrlInBrowser">Delegate to open browser.</param>
public MyBikesPageViewModel(
User p_oUser,
User user,
ILocationPermission permissions,
IBluetoothLE bluetoothLE,
string runtimPlatform,
@ -79,11 +79,11 @@ namespace TINK.ViewModel.MyBikes
IGeolocationService geolocation,
ILocksService lockService,
IEnumerable<IStation> stations,
PollingParameters p_oPolling,
PollingParameters polling,
Action<SendOrPostCallback, object> postAction,
ISmartDevice smartDevice,
IViewService viewService,
Action<string> openUrlInBrowser) : base(p_oUser, permissions, bluetoothLE, runtimPlatform, isConnectedDelegate, connectorFactory, geolocation, lockService, p_oPolling, postAction, smartDevice, viewService, openUrlInBrowser, () => new MyBikeInUseStateInfoProvider())
Action<string> openUrlInBrowser) : base(user, new ViewContext(PageContext.MyBikes), permissions, bluetoothLE, runtimPlatform, isConnectedDelegate, connectorFactory, geolocation, lockService, polling, postAction, smartDevice, viewService, openUrlInBrowser, () => new MyBikeInUseStateInfoProvider())
{
CollectionChanged += (sender, eventargs) =>
{