mirror of
https://dev.azure.com/TeilRad/sharee.bike%20App/_git/Code
synced 2025-06-21 21:46:27 +02:00
Code updated to 3.0.238
This commit is contained in:
parent
3302d80678
commit
9c6a1fa92b
257 changed files with 7763 additions and 2861 deletions
|
@ -7,11 +7,12 @@ using System.ComponentModel;
|
|||
using System.Threading.Tasks;
|
||||
using TINK.Model;
|
||||
using TINK.Model.Connector;
|
||||
using TINK.Model.Repository.Exception;
|
||||
using TINK.Repository.Exception;
|
||||
using TINK.View;
|
||||
using TINK.ViewModel.Settings;
|
||||
using System.Linq;
|
||||
using TINK.MultilingualResources;
|
||||
using TINK.ViewModel.Info;
|
||||
|
||||
namespace TINK.ViewModel.Account
|
||||
{
|
||||
|
@ -25,7 +26,7 @@ namespace TINK.ViewModel.Account
|
|||
/// <summary>
|
||||
/// Reference on view servcie to show modal notifications and to perform navigation.
|
||||
/// </summary>
|
||||
private IViewService m_oViewService;
|
||||
private readonly IViewService m_oViewService;
|
||||
|
||||
/// <summary>
|
||||
/// Holds the exception which occurred getting bikes occupied information.
|
||||
|
@ -282,6 +283,17 @@ namespace TINK.ViewModel.Account
|
|||
IsConnected = TinkApp.GetIsConnected();
|
||||
await TinkApp.GetConnector(IsConnected).Command.DoLogout();
|
||||
}
|
||||
catch (UnsupportedCopriVersionDetectedException)
|
||||
{
|
||||
await m_oViewService.DisplayAlert(
|
||||
AppResources.MessageLogoutErrorTitle,
|
||||
string.Format(AppResources.MessageAppVersionIsOutdated, ContactPageViewModel.GetAppName(TinkApp.Uris.ActiveUri)),
|
||||
AppResources.MessageAnswerOk);
|
||||
|
||||
// Restart polling again.
|
||||
await m_oViewUpdateManager.StartUpdateAyncPeridically(Polling.ToImmutable());
|
||||
return;
|
||||
}
|
||||
catch (Exception l_oException)
|
||||
{
|
||||
// Copri server is not reachable.
|
||||
|
@ -315,7 +327,11 @@ namespace TINK.ViewModel.Account
|
|||
try
|
||||
{
|
||||
// Switch to map view after log out.
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
m_oViewService.ShowPage(ViewTypes.MapPage);
|
||||
#else
|
||||
await m_oViewService.ShowPage("//MapPage");
|
||||
#endif
|
||||
}
|
||||
catch (Exception p_oException)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.");
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace TINK.ViewModel
|
|||
/// <returns>Display text</returns>
|
||||
public string GetReservedInfo(
|
||||
TimeSpan? remainingTime,
|
||||
int? station = null,
|
||||
string station = null,
|
||||
string code = null)
|
||||
{
|
||||
if (remainingTime == null)
|
||||
|
@ -40,7 +40,7 @@ namespace TINK.ViewModel
|
|||
/// <returns>Display text</returns>
|
||||
public string GetBookedInfo(
|
||||
DateTime? from,
|
||||
int? station = null,
|
||||
string station = null,
|
||||
string code = null)
|
||||
{
|
||||
if (from == null)
|
||||
|
|
|
@ -22,6 +22,8 @@ using Plugin.Permissions.Abstractions;
|
|||
using Plugin.BLE.Abstractions.Contracts;
|
||||
using TINK.MultilingualResources;
|
||||
using Plugin.Permissions;
|
||||
using TINK.Model.Station;
|
||||
using TINK.Model.Device;
|
||||
|
||||
namespace TINK.ViewModel.BikesAtStation
|
||||
{
|
||||
|
@ -31,14 +33,9 @@ namespace TINK.ViewModel.BikesAtStation
|
|||
public class BikesAtStationPageViewModel : BikesViewModel, INotifyCollectionChanged, INotifyPropertyChanged
|
||||
{
|
||||
/// <summary>
|
||||
/// Reference on view servcie to show modal notifications and to perform navigation.
|
||||
/// Holds the selected station;
|
||||
/// </summary>
|
||||
private IViewService m_oViewService;
|
||||
|
||||
/// <summary>
|
||||
/// Holds the Id of the selected station;
|
||||
/// </summary>
|
||||
private readonly int? m_oStation;
|
||||
private readonly IStation m_oStation;
|
||||
|
||||
/// <summary> Holds a reference to the external trigger service. </summary>
|
||||
private Action<string> OpenUrlInExternalBrowser { get; }
|
||||
|
@ -47,6 +44,7 @@ namespace TINK.ViewModel.BikesAtStation
|
|||
/// Constructs bike collection view model.
|
||||
/// </summary>
|
||||
/// <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 permisions.</param>
|
||||
/// <param name="bluetoothLE">Holds object to query bluetooth state.</param>
|
||||
/// <param name="runtimPlatform">Specifies on which platform code is run.</param>
|
||||
|
@ -57,13 +55,14 @@ namespace TINK.ViewModel.BikesAtStation
|
|||
/// <param name="l_oBikesAll">All bikes at given station.</param>
|
||||
/// <param name="openUrlInExternalBrowser">Action to open an external browser.</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 methodes on GUI.</param>
|
||||
public BikesAtStationPageViewModel(
|
||||
User user,
|
||||
IPermissions permissions,
|
||||
IBluetoothLE bluetoothLE,
|
||||
string runtimPlatform,
|
||||
int? selectedStation,
|
||||
IStation selectedStation,
|
||||
Func<bool> isConnectedDelegate,
|
||||
Func<bool, IConnector> connectorFactory,
|
||||
IGeolocation geolocation,
|
||||
|
@ -71,18 +70,16 @@ namespace TINK.ViewModel.BikesAtStation
|
|||
PollingParameters polling,
|
||||
Action<string> openUrlInExternalBrowser,
|
||||
Action<SendOrPostCallback, object> postAction,
|
||||
IViewService viewService) : base(user, permissions, bluetoothLE, runtimPlatform, isConnectedDelegate, connectorFactory, geolocation, lockService, polling, postAction, viewService, () => new BikeAtStationInUseStateInfoProvider())
|
||||
ISmartDevice smartDevice,
|
||||
IViewService viewService) : base(user, permissions, bluetoothLE, runtimPlatform, isConnectedDelegate, connectorFactory, geolocation, lockService, polling, postAction, smartDevice, viewService, () => new BikeAtStationInUseStateInfoProvider())
|
||||
{
|
||||
m_oViewService = viewService
|
||||
?? throw new ArgumentException("Can not instantiate bikes at station page view model- object. No view available.");
|
||||
|
||||
OpenUrlInExternalBrowser = openUrlInExternalBrowser
|
||||
?? throw new ArgumentException("Can not instantiate login page view model- object. No user external browse service available.");
|
||||
|
||||
m_oStation = selectedStation;
|
||||
|
||||
Title = string.Format(m_oStation != null
|
||||
? string.Format(AppResources.MarkingBikesAtStationTitle, m_oStation.ToString())
|
||||
Title = string.Format(m_oStation?.StationName != null
|
||||
? m_oStation.StationName
|
||||
: string.Empty);
|
||||
|
||||
CollectionChanged += (sender, eventargs) =>
|
||||
|
@ -161,19 +158,32 @@ namespace TINK.ViewModel.BikesAtStation
|
|||
{
|
||||
get
|
||||
{
|
||||
return new Xamarin.Forms.Command(() => OpenLoginPage());
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
return new Xamarin.Forms.Command(() => OpenLoginPageAsync());
|
||||
#else
|
||||
return new Xamarin.Forms.Command(async () => await OpenLoginPageAsync());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens login page.
|
||||
/// </summary>
|
||||
public void OpenLoginPage()
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
public void OpenLoginPageAsync()
|
||||
#else
|
||||
public async Task OpenLoginPageAsync()
|
||||
#endif
|
||||
{
|
||||
try
|
||||
{
|
||||
// Switch to map page
|
||||
m_oViewService.ShowPage(ViewTypes.LoginPage);
|
||||
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
ViewService.ShowPage(ViewTypes.LoginPage);
|
||||
#else
|
||||
await ViewService.ShowPage("//LoginPage");
|
||||
#endif
|
||||
}
|
||||
catch (Exception p_oException)
|
||||
{
|
||||
|
@ -188,7 +198,7 @@ namespace TINK.ViewModel.BikesAtStation
|
|||
/// </summary>
|
||||
public async Task OnAppearing()
|
||||
{
|
||||
Log.ForContext<BikesAtStationPageViewModel>().Information($"Bikes at station {m_oStation} is appearing, either due to tap on a station or to app being shown again.");
|
||||
Log.ForContext<BikesAtStationPageViewModel>().Information($"Bikes at station {m_oStation?.StationName} is appearing, either due to tap on a station or to app being shown again.");
|
||||
|
||||
ActionText = "Einen Moment bitte...";
|
||||
|
||||
|
@ -201,15 +211,15 @@ namespace TINK.ViewModel.BikesAtStation
|
|||
|
||||
Exception = bikesAll.Exception; // Update communication error from query for bikes at station.
|
||||
|
||||
var bikesAtStation = bikesAll.Response.GetAtStation(m_oStation);
|
||||
var bikesAtStation = bikesAll.Response.GetAtStation(m_oStation.Id);
|
||||
var lockIdList = bikesAtStation
|
||||
.GetLockIt()
|
||||
.Cast<BikeInfo>()
|
||||
.Select(x => x.LockInfo)
|
||||
.ToList();
|
||||
|
||||
Title = string.Format(m_oStation != null
|
||||
? m_oStation.ToString()
|
||||
Title = string.Format(m_oStation?.StationName != null
|
||||
? m_oStation.StationName
|
||||
: string.Empty);
|
||||
|
||||
if (LockService is ILocksServiceFake serviceFake)
|
||||
|
@ -223,14 +233,14 @@ namespace TINK.ViewModel.BikesAtStation
|
|||
if (bikesAtStation.GetLockIt().Count > 0
|
||||
&& RuntimePlatform == Device.Android)
|
||||
{
|
||||
var status = await Permissions.CheckPermissionStatusAsync<LocationPermission>();
|
||||
var status = await PermissionsService.CheckPermissionStatusAsync<LocationPermission>();
|
||||
if (status != PermissionStatus.Granted)
|
||||
{
|
||||
var permissionResult = await Permissions.RequestPermissionAsync<LocationPermission>();
|
||||
var permissionResult = await PermissionsService.RequestPermissionAsync<LocationPermission>();
|
||||
|
||||
if (permissionResult != PermissionStatus.Granted)
|
||||
{
|
||||
var dialogResult = await m_oViewService.DisplayAlert(
|
||||
var dialogResult = await ViewService.DisplayAlert(
|
||||
AppResources.MessageTitleHint,
|
||||
AppResources.MessageBikesManagementLocationPermissionOpenDialog,
|
||||
AppResources.MessageAnswerYes,
|
||||
|
@ -249,13 +259,13 @@ namespace TINK.ViewModel.BikesAtStation
|
|||
}
|
||||
|
||||
// Open permissions dialog.
|
||||
Permissions.OpenAppSettings();
|
||||
PermissionsService.OpenAppSettings();
|
||||
}
|
||||
}
|
||||
|
||||
if (Geolocation.IsGeolcationEnabled == false)
|
||||
{
|
||||
await m_oViewService.DisplayAlert(
|
||||
await ViewService.DisplayAlert(
|
||||
AppResources.MessageTitleHint,
|
||||
AppResources.MessageBikesManagementLocationActivation,
|
||||
AppResources.MessageAnswerOk);
|
||||
|
@ -270,9 +280,9 @@ namespace TINK.ViewModel.BikesAtStation
|
|||
}
|
||||
|
||||
// Check if bluetooth is activated.
|
||||
if (await BluetoothLE.GetBluetoothState() != BluetoothState.On)
|
||||
if (await BluetoothService.GetBluetoothState() != BluetoothState.On)
|
||||
{
|
||||
await m_oViewService.DisplayAlert(
|
||||
await ViewService.DisplayAlert(
|
||||
AppResources.MessageTitleHint,
|
||||
AppResources.MessageBikesManagementBluetoothActivation,
|
||||
AppResources.MessageAnswerOk);
|
||||
|
@ -319,14 +329,14 @@ namespace TINK.ViewModel.BikesAtStation
|
|||
PostAction(
|
||||
unused =>
|
||||
{
|
||||
ActionText = "Aktualisiere...";
|
||||
ActionText = AppResources.ActivityTextUpdating;
|
||||
IsConnected = IsConnectedDelegate();
|
||||
},
|
||||
null);
|
||||
|
||||
var result = ConnectorFactory(IsConnected).Query.GetBikesAsync().Result;
|
||||
|
||||
BikeCollection bikes = result.Response.GetAtStation(m_oStation);
|
||||
BikeCollection bikes = result.Response.GetAtStation(m_oStation.Id);
|
||||
|
||||
var exception = result.Exception;
|
||||
if (exception != null)
|
||||
|
|
79
TINKLib/ViewModel/FeesAndBikes/HelpContactViewModel.cs
Normal file
79
TINKLib/ViewModel/FeesAndBikes/HelpContactViewModel.cs
Normal file
|
@ -0,0 +1,79 @@
|
|||
using System.ComponentModel;
|
||||
using Xamarin.Forms;
|
||||
using TINK.Services.CopriApi.ServerUris;
|
||||
using System;
|
||||
|
||||
namespace TINK.ViewModel.Contact
|
||||
{
|
||||
public class HelpContactViewModel : INotifyPropertyChanged
|
||||
{
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
/// <summary> Gets the platfrom specific prefix. </summary>
|
||||
private Func<string, string> ResourceProvider { get; set; }
|
||||
|
||||
/// <summary> Holds value wether site caching is on or off.</summary>
|
||||
bool IsSiteCachingOn { get; }
|
||||
|
||||
/// <summary> Constructs view model.</summary>
|
||||
/// <param name="isSiteCachingOn">Set of user permissions</param>
|
||||
/// <param name="resourceProvider">Delegate to get an an embedded html ressource. Used as fallback if download from web page does not work and cache is empty.</param>
|
||||
public HelpContactViewModel(
|
||||
string hostName,
|
||||
bool isSiteCachingOn,
|
||||
Func<string, string> resourceProvider)
|
||||
{
|
||||
HostName = hostName;
|
||||
IsSiteCachingOn = isSiteCachingOn;
|
||||
|
||||
ResourceProvider = resourceProvider
|
||||
?? throw new ArgumentException($"Can not instantiate {typeof(HelpContactViewModel)}-object. No ressource provider availalbe.");
|
||||
|
||||
}
|
||||
|
||||
/// <summary> Holds the name of the host.</summary>
|
||||
private string HostName { get; }
|
||||
|
||||
/// <summary> Called when page is shown. </summary>
|
||||
public async void OnAppearing()
|
||||
{
|
||||
RentBikeText = new HtmlWebViewSource
|
||||
{
|
||||
Html = HostName.GetIsCopri()
|
||||
? ResourceProvider("HtmlResouces.V02.InfoRentBike.html")
|
||||
: await ViewModelHelper.GetSource($"https://{HostName}/{CopriHelper.SHAREE_SILTEFOLDERNAME}/tariff_info_1.html", IsSiteCachingOn)
|
||||
};
|
||||
|
||||
TypesOfBikesText = new HtmlWebViewSource
|
||||
{
|
||||
Html = HostName.GetIsCopri()
|
||||
? ResourceProvider("HtmlResouces.V02.InfoTypesOfBikes.html")
|
||||
: await ViewModelHelper.GetSource($"https://{HostName}/{CopriHelper.SHAREE_SILTEFOLDERNAME}/bike_info.html", IsSiteCachingOn)
|
||||
};
|
||||
}
|
||||
|
||||
private HtmlWebViewSource rentBikeText;
|
||||
|
||||
private HtmlWebViewSource typesOfBikesText;
|
||||
|
||||
public HtmlWebViewSource RentBikeText
|
||||
{
|
||||
get => rentBikeText;
|
||||
set
|
||||
{
|
||||
rentBikeText = value;
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(RentBikeText)));
|
||||
}
|
||||
}
|
||||
|
||||
public HtmlWebViewSource TypesOfBikesText
|
||||
{
|
||||
get => typesOfBikesText;
|
||||
set
|
||||
{
|
||||
typesOfBikesText = value;
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(TypesOfBikesText)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,7 +10,7 @@ namespace TINK.ViewModel
|
|||
/// <returns>Display text</returns>
|
||||
string GetReservedInfo(
|
||||
TimeSpan? p_oRemainingTime,
|
||||
int? p_strStation = null,
|
||||
string p_strStation = null,
|
||||
string p_strCode = null);
|
||||
|
||||
/// <summary>
|
||||
|
@ -19,7 +19,7 @@ namespace TINK.ViewModel
|
|||
/// <returns>Display text</returns>
|
||||
string GetBookedInfo(
|
||||
DateTime? p_oFrom,
|
||||
int? p_strStation = null,
|
||||
string p_strStation = null,
|
||||
string p_strCode = null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -140,16 +140,16 @@ namespace TINK.ViewModel.Info.BikeInfo
|
|||
|
||||
/// <summary> Gets the carousel page items</summary>
|
||||
public IList<CourouselPageItemViewModel> CarouselItems { get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Commang object to bind login button to view model.
|
||||
/// </summary>
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
private Action CloseAction
|
||||
{
|
||||
get
|
||||
{
|
||||
return () => m_oViewService.ShowPage(ViewTypes.MapPage);
|
||||
}
|
||||
}
|
||||
=> () => m_oViewService.ShowPage(ViewTypes.MapPage);
|
||||
#else
|
||||
private Action CloseAction
|
||||
=> async () => await m_oViewService.ShowPage("//MapPage");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ using TINK.Model.User.Account;
|
|||
using System.ComponentModel;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.Model.Repository.Exception;
|
||||
using TINK.Repository.Exception;
|
||||
using Serilog;
|
||||
using TINK.ViewModel.Map;
|
||||
using Plugin.Connectivity;
|
||||
|
@ -14,6 +14,7 @@ using TINK.Model;
|
|||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using TINK.MultilingualResources;
|
||||
using TINK.ViewModel.Info;
|
||||
|
||||
namespace TINK.ViewModel
|
||||
{
|
||||
|
@ -22,7 +23,7 @@ namespace TINK.ViewModel
|
|||
/// <summary>
|
||||
/// Reference on view servcie to show modal notifications and to perform navigation.
|
||||
/// </summary>
|
||||
private IViewService m_oViewService;
|
||||
private readonly IViewService m_oViewService;
|
||||
|
||||
#if BACKSTYLE
|
||||
/// <summary> Reference to naviagion object to navigate back to map page when login succeeded. </summary>
|
||||
|
@ -168,7 +169,7 @@ namespace TINK.ViewModel
|
|||
{
|
||||
get
|
||||
{
|
||||
return new Command(async () => await TryLogin());
|
||||
return new Command(async () => await Login());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -208,9 +209,9 @@ namespace TINK.ViewModel
|
|||
/// User request to log in.
|
||||
/// </summary>
|
||||
#if BACKSTYLE
|
||||
public async void TryLogin()
|
||||
public async void Login()
|
||||
#else
|
||||
public async Task TryLogin()
|
||||
public async Task Login()
|
||||
#endif
|
||||
{
|
||||
try
|
||||
|
@ -224,7 +225,7 @@ namespace TINK.ViewModel
|
|||
// Do login.
|
||||
var l_oAccount = await TinkApp.GetConnector(CrossConnectivity.Current.IsConnected).Command.DoLogin(MailAddress, Password, TinkApp.ActiveUser.DeviceId);
|
||||
|
||||
TinkApp.ActiveUser.Login(l_oAccount);
|
||||
await TinkApp.ActiveUser.Login(l_oAccount);
|
||||
|
||||
// Update map page filter because user might be of both groups TINK an Konrad.
|
||||
TinkApp.GroupFilterMapPage =
|
||||
|
@ -252,6 +253,15 @@ namespace TINK.ViewModel
|
|||
|
||||
return;
|
||||
}
|
||||
catch (UnsupportedCopriVersionDetectedException)
|
||||
{
|
||||
await m_oViewService.DisplayAlert(
|
||||
AppResources.MessageLoginErrorTitle,
|
||||
string.Format(AppResources.MessageAppVersionIsOutdated, ContactPageViewModel.GetAppName(TinkApp.Uris.ActiveUri)),
|
||||
AppResources.MessageAnswerOk);
|
||||
|
||||
return;
|
||||
}
|
||||
catch (Exception l_oException)
|
||||
{
|
||||
// Copri server is not reachable.
|
||||
|
@ -307,12 +317,20 @@ namespace TINK.ViewModel
|
|||
if (!TinkApp.ActiveUser.Group.Contains(Model.Connector.FilterHelper.FILTERTINKGENERAL))
|
||||
{
|
||||
// No need to show "Anleitung TINK Räder" because user can not use tink.
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
m_oViewService.ShowPage(ViewTypes.MapPage);
|
||||
#else
|
||||
await m_oViewService.ShowPage("//MapPage");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
// Swich to map page
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
m_oViewService.ShowPage(ViewTypes.BikeInfoCarouselPage, AppResources.MarkingLoginInstructions);
|
||||
#else
|
||||
await m_oViewService.ShowPage("//MapPage");
|
||||
#endif
|
||||
}
|
||||
catch (Exception p_oException)
|
||||
{
|
||||
|
|
|
@ -4,7 +4,7 @@ using TINK.Model.Station;
|
|||
using System;
|
||||
using System.Linq;
|
||||
using TINK.Model.Bike;
|
||||
using TINK.Model.Repository.Exception;
|
||||
using TINK.Repository.Exception;
|
||||
using TINK.Model;
|
||||
using Serilog;
|
||||
using System.Collections.Generic;
|
||||
|
@ -12,7 +12,9 @@ using System.Threading.Tasks;
|
|||
using System.ComponentModel;
|
||||
using Xamarin.Forms.GoogleMaps;
|
||||
using System.Collections.ObjectModel;
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
using TINK.View.MasterDetail;
|
||||
#endif
|
||||
using TINK.Settings;
|
||||
using TINK.Model.Connector;
|
||||
using TINK.Model.Services.CopriApi;
|
||||
|
@ -24,6 +26,9 @@ using TINK.MultilingualResources;
|
|||
using TINK.Services.BluetoothLock;
|
||||
using TINK.Model.Services.CopriApi.ServerUris;
|
||||
using TINK.ViewModel.Info;
|
||||
using TINK.Repository;
|
||||
using Plugin.Permissions.Abstractions;
|
||||
using TINK.Model.Services.Geolocation;
|
||||
|
||||
#if !TRYNOTBACKSTYLE
|
||||
#endif
|
||||
|
@ -43,6 +48,18 @@ namespace TINK.ViewModel.Map
|
|||
/// </summary>
|
||||
private Exception m_oException;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Service to query/ manage permissions (location) of the app.
|
||||
/// </summary>
|
||||
private IPermissions PermissionsService { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Service to manage bluetooth stack.
|
||||
/// </summary>
|
||||
private Plugin.BLE.Abstractions.Contracts.IBluetoothLE BluetoothService { get; set; }
|
||||
|
||||
|
||||
/// <summary> Notifies view about changes. </summary>
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
|
@ -58,9 +75,10 @@ namespace TINK.ViewModel.Map
|
|||
/// <summary>Delegate to perform navigation.</summary>
|
||||
private INavigation m_oNavigation;
|
||||
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
/// <summary>Delegate to perform navigation.</summary>
|
||||
private INavigationMasterDetail m_oNavigationMasterDetail;
|
||||
|
||||
#endif
|
||||
private ObservableCollection<Pin> pins;
|
||||
|
||||
public ObservableCollection<Pin> Pins
|
||||
|
@ -81,7 +99,9 @@ namespace TINK.ViewModel.Map
|
|||
|
||||
/// <summary> False if user tabed on station marker to show bikes at a given station.</summary>
|
||||
private bool isMapPageEnabled = false;
|
||||
|
||||
|
||||
Model.Services.Geolocation.IGeolocation GeolocationService { get; }
|
||||
|
||||
/// <summary> False if user tabed on station marker to show bikes at a given station.</summary>
|
||||
public bool IsMapPageEnabled {
|
||||
get => isMapPageEnabled;
|
||||
|
@ -97,30 +117,44 @@ namespace TINK.ViewModel.Map
|
|||
|
||||
/// <summary> Prevents an invalid instane to be created. </summary>
|
||||
/// <param name="tinkApp"> Reference to tink app model.</param>
|
||||
/// <param name="p_oMoveToRegionDelegate">Delegate to center map and set zoom level.</param>
|
||||
/// <param name="p_oViewService">View service to notify user.</param>
|
||||
/// <param name="p_oNavigation">Interface to navigate.</param>
|
||||
/// <param name="moveToRegionDelegate">Delegate to center map and set zoom level.</param>
|
||||
/// <param name="viewService">View service to notify user.</param>
|
||||
/// <param name="navigation">Interface to navigate.</param>
|
||||
public MapPageViewModel(
|
||||
ITinkApp tinkApp,
|
||||
Action<MapSpan> p_oMoveToRegionDelegate,
|
||||
IViewService p_oViewService,
|
||||
INavigation p_oNavigation)
|
||||
IPermissions permissionsService,
|
||||
Plugin.BLE.Abstractions.Contracts.IBluetoothLE bluetoothService,
|
||||
IGeolocation geolocationService,
|
||||
Action<MapSpan> moveToRegionDelegate,
|
||||
IViewService viewService,
|
||||
INavigation navigation)
|
||||
{
|
||||
TinkApp = tinkApp
|
||||
?? throw new ArgumentException("Can not instantiate map page view model- object. No tink app object available.");
|
||||
|
||||
m_oMoveToRegionDelegate = p_oMoveToRegionDelegate
|
||||
PermissionsService = permissionsService ??
|
||||
throw new ArgumentException($"Can not instantiate {nameof(MapPageViewModel)}. Permissions service object must never be null.");
|
||||
|
||||
BluetoothService = bluetoothService ??
|
||||
throw new ArgumentException($"Can not instantiate {nameof(MapPageViewModel)}. Bluetooth service object must never be null.");
|
||||
|
||||
GeolocationService = geolocationService ??
|
||||
throw new ArgumentException($"Can not instantiate {nameof(MapPageViewModel)}. Geolocation service object must never be null.");
|
||||
|
||||
m_oMoveToRegionDelegate = moveToRegionDelegate
|
||||
?? throw new ArgumentException("Can not instantiate map page view model- object. No move delegate available.");
|
||||
|
||||
m_oViewService = p_oViewService
|
||||
m_oViewService = viewService
|
||||
?? throw new ArgumentException("Can not instantiate map page view model- object. No view available.");
|
||||
|
||||
m_oNavigation = p_oNavigation
|
||||
m_oNavigation = navigation
|
||||
?? throw new ArgumentException("Can not instantiate map page view model- object. No navigation service available.");
|
||||
|
||||
m_oViewUpdateManager = new IdlePollingUpdateTaskManager();
|
||||
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
m_oNavigationMasterDetail = new EmptyNavigationMasterDetail();
|
||||
#endif
|
||||
|
||||
Polling = PollingParameters.NoPolling;
|
||||
|
||||
|
@ -143,42 +177,46 @@ namespace TINK.ViewModel.Map
|
|||
}
|
||||
}
|
||||
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
/// <summary> Delegate to perform navigation.</summary>
|
||||
public INavigationMasterDetail NavigationMasterDetail
|
||||
{
|
||||
set { m_oNavigationMasterDetail = value; }
|
||||
}
|
||||
#endif
|
||||
|
||||
public Command<PinClickedEventArgs> PinClickedCommand => new Command<PinClickedEventArgs>(
|
||||
args =>
|
||||
{
|
||||
OnStationClicked(int.Parse(args.Pin.Tag.ToString()));
|
||||
OnStationClicked(args.Pin.Tag.ToString());
|
||||
args.Handled = true; // Prevents map to be centered to selected pin.
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
/// One time setup: Sets pins into map and connects to events.
|
||||
/// </summary>
|
||||
private void InitializePins(StationDictionary p_oStations)
|
||||
private void InitializePins(StationDictionary stations)
|
||||
{
|
||||
// Add pins to stations.
|
||||
Log.ForContext<MapPageViewModel>().Debug($"Request to draw {p_oStations.Count} pins.");
|
||||
foreach (var l_oStation in p_oStations)
|
||||
Log.ForContext<MapPageViewModel>().Debug($"Request to draw {stations.Count} pins.");
|
||||
foreach (var station in stations)
|
||||
{
|
||||
if (l_oStation.Position == null)
|
||||
if (station.Position == null)
|
||||
{
|
||||
// There should be no reason for a position object to be null but this alreay occurred in past.
|
||||
Log.ForContext<MapPageViewModel>().Error("Postion object of station {@l_oStation} is null.", l_oStation);
|
||||
Log.ForContext<MapPageViewModel>().Error("Postion object of station {@l_oStation} is null.", station);
|
||||
continue;
|
||||
}
|
||||
|
||||
var l_oPin = new Pin
|
||||
{
|
||||
Position = new Xamarin.Forms.GoogleMaps.Position(l_oStation.Position.Latitude, l_oStation.Position.Longitude),
|
||||
Label = l_oStation.Id > CUSTOM_ICONS_COUNT
|
||||
? l_oStation.GetStationName()
|
||||
|
||||
Position = new Xamarin.Forms.GoogleMaps.Position(station.Position.Latitude, station.Position.Longitude),
|
||||
Label = long.TryParse(station.Id, out long stationId) && stationId > CUSTOM_ICONS_COUNT
|
||||
? station.GetStationName()
|
||||
: string.Empty, // Stations with custom icons have already a id marker. No need for a label.
|
||||
Tag = l_oStation.Id,
|
||||
|
||||
Tag = station.Id,
|
||||
IsVisible = false, // Set to false to prevent showing default icons (flickering).
|
||||
};
|
||||
|
||||
|
@ -187,41 +225,41 @@ namespace TINK.ViewModel.Map
|
|||
}
|
||||
|
||||
/// <summary> Update all stations from TINK. </summary>
|
||||
/// <param name="p_oStationsColorList">List of colors to apply.</param>
|
||||
private void UpdatePinsColor(IList<Color> p_oStationsColorList)
|
||||
/// <param name="stationsColorList">List of colors to apply.</param>
|
||||
private void UpdatePinsColor(IList<Color> stationsColorList)
|
||||
{
|
||||
Log.ForContext<MapPageViewModel>().Debug($"Starting update of stations pins color for {p_oStationsColorList.Count} stations...");
|
||||
Log.ForContext<MapPageViewModel>().Debug($"Starting update of stations pins color for {stationsColorList.Count} stations...");
|
||||
|
||||
// Update colors of pins.
|
||||
for (int l_iPinIndex = 0; l_iPinIndex < p_oStationsColorList.Count; l_iPinIndex++)
|
||||
for (int pinIndex = 0; pinIndex < stationsColorList.Count; pinIndex++)
|
||||
{
|
||||
var l_iStationId = int.Parse(Pins[l_iPinIndex].Tag.ToString());
|
||||
|
||||
var indexPartPrefix = l_iStationId <= CUSTOM_ICONS_COUNT
|
||||
? $"{l_iStationId}" // there is a station marker with index letter for given station id
|
||||
var indexPartPrefix = int.TryParse(Pins[pinIndex].Tag.ToString(), out int stationId)
|
||||
&& stationId <= CUSTOM_ICONS_COUNT
|
||||
? $"{stationId}" // there is a station marker with index letter for given station id
|
||||
: "Open"; // there is no station marker. Use open marker.
|
||||
|
||||
var colorPartPrefix = GetRessourceNameColorPart(p_oStationsColorList[l_iPinIndex]);
|
||||
var colorPartPrefix = GetRessourceNameColorPart(stationsColorList[pinIndex]);
|
||||
|
||||
var l_iName = $"{indexPartPrefix.ToString().PadLeft(2, '0')}_{colorPartPrefix}{(DeviceInfo.Platform == DevicePlatform.Android ? ".png" : string.Empty)}";
|
||||
try
|
||||
{
|
||||
Pins[l_iPinIndex].Icon = BitmapDescriptorFactory.FromBundle(l_iName);
|
||||
Pins[pinIndex].Icon = BitmapDescriptorFactory.FromBundle(l_iName);
|
||||
}
|
||||
catch (Exception l_oException)
|
||||
{
|
||||
Log.ForContext<MapPageViewModel>().Error("Station icon {l_strName} can not be loaded. {@l_oException}.", l_oException);
|
||||
Pins[l_iPinIndex].Label = l_iStationId.ToString();
|
||||
Pins[l_iPinIndex].Icon = BitmapDescriptorFactory.DefaultMarker(p_oStationsColorList[l_iPinIndex]);
|
||||
Pins[pinIndex].Label = stationId.ToString();
|
||||
Pins[pinIndex].Icon = BitmapDescriptorFactory.DefaultMarker(stationsColorList[pinIndex]);
|
||||
}
|
||||
|
||||
Pins[l_iPinIndex].IsVisible = true;
|
||||
Pins[pinIndex].IsVisible = true;
|
||||
}
|
||||
|
||||
var pinsCount = Pins.Count;
|
||||
for (int pinIndex = p_oStationsColorList.Count; pinIndex < pinsCount; pinIndex++)
|
||||
for (int pinIndex = stationsColorList.Count; pinIndex < pinsCount; pinIndex++)
|
||||
{
|
||||
Log.ForContext<MapPageViewModel>().Error($"Unexpected count of pins detected. Expected {p_oStationsColorList.Count} but is {pinsCount}.");
|
||||
Log.ForContext<MapPageViewModel>().Error($"Unexpected count of pins detected. Expected {stationsColorList.Count} but is {pinsCount}.");
|
||||
Pins[pinIndex].IsVisible = false;
|
||||
}
|
||||
|
||||
|
@ -229,31 +267,31 @@ namespace TINK.ViewModel.Map
|
|||
}
|
||||
|
||||
/// <summary> Gets the color related part of the ressrouce name.</summary>
|
||||
/// <param name="p_oColor">Color to get name for.</param>
|
||||
/// <param name="color">Color to get name for.</param>
|
||||
/// <returns>Resource name.</returns>
|
||||
private static string GetRessourceNameColorPart(Color p_oColor)
|
||||
private static string GetRessourceNameColorPart(Color color)
|
||||
{
|
||||
if (p_oColor == Color.Blue)
|
||||
if (color == Color.Blue)
|
||||
{
|
||||
return "Blue";
|
||||
}
|
||||
|
||||
if (p_oColor == Color.Green)
|
||||
if (color == Color.Green)
|
||||
{
|
||||
return "Green";
|
||||
}
|
||||
|
||||
if (p_oColor == Color.LightBlue)
|
||||
if (color == Color.LightBlue)
|
||||
{
|
||||
return "LightBlue";
|
||||
}
|
||||
|
||||
if (p_oColor == Color.Red)
|
||||
if (color == Color.Red)
|
||||
{
|
||||
return "Red";
|
||||
}
|
||||
|
||||
return p_oColor.ToString();
|
||||
return color.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -283,13 +321,12 @@ namespace TINK.ViewModel.Map
|
|||
ActionText = AppResources.ActivityTextMyBikesLoadingBikes;
|
||||
|
||||
// Check location permission
|
||||
var _permissions = TinkApp.Permissions;
|
||||
var status = await _permissions.CheckPermissionStatusAsync<LocationPermission>();
|
||||
var status = await PermissionsService.CheckPermissionStatusAsync<LocationPermission>();
|
||||
if (TinkApp.CenterMapToCurrentLocation
|
||||
&& !TinkApp.GeolocationServices.Active.IsSimulation
|
||||
&& !GeolocationService.IsSimulation
|
||||
&& status != Plugin.Permissions.Abstractions.PermissionStatus.Granted)
|
||||
{
|
||||
var permissionResult = await _permissions.RequestPermissionAsync<LocationPermission>();
|
||||
var permissionResult = await PermissionsService.RequestPermissionAsync<LocationPermission>();
|
||||
|
||||
if (permissionResult != Plugin.Permissions.Abstractions.PermissionStatus.Granted)
|
||||
{
|
||||
|
@ -302,7 +339,7 @@ namespace TINK.ViewModel.Map
|
|||
if (dialogResult)
|
||||
{
|
||||
// User decided to give access to locations permissions.
|
||||
_permissions.OpenAppSettings();
|
||||
PermissionsService.OpenAppSettings();
|
||||
ActionText = "";
|
||||
IsRunning = false;
|
||||
IsMapPageEnabled = true;
|
||||
|
@ -317,7 +354,7 @@ namespace TINK.ViewModel.Map
|
|||
try
|
||||
{
|
||||
currentLocation = TinkApp.CenterMapToCurrentLocation
|
||||
? await TinkApp.GeolocationServices.Active.GetAsync()
|
||||
? await GeolocationService.GetAsync()
|
||||
: null;
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
@ -332,6 +369,16 @@ namespace TINK.ViewModel.Map
|
|||
IsConnected = TinkApp.GetIsConnected();
|
||||
var resultStationsAndBikes = await TinkApp.GetConnector(IsConnected).Query.GetBikesAndStationsAsync();
|
||||
|
||||
TinkApp.Stations = resultStationsAndBikes.Response.StationsAll;
|
||||
|
||||
if (Pins.Count > 0 && Pins.Count != resultStationsAndBikes.Response.StationsAll.Count)
|
||||
{
|
||||
// Either
|
||||
// - user logged in/ logged out which might lead to more/ less stations beeing available
|
||||
// - new stations were added/ existing ones remove
|
||||
Pins.Clear();
|
||||
}
|
||||
|
||||
// Check if there are alreay any pins to the map
|
||||
// i.e detecte first call of member OnAppearing after construction
|
||||
if (Pins.Count <= 0)
|
||||
|
@ -341,13 +388,23 @@ namespace TINK.ViewModel.Map
|
|||
// Map was not yet initialized.
|
||||
// Get stations from Copri
|
||||
Log.ForContext<MapPageViewModel>().Verbose("No pins detected on page.");
|
||||
if (resultStationsAndBikes.Response.StationsAll.CopriVersion >= new Version(4, 1))
|
||||
if (resultStationsAndBikes.Response.StationsAll.CopriVersion < CopriCallsStatic.UnsupportedVersionLower)
|
||||
{
|
||||
await m_oViewService.DisplayAlert(
|
||||
"Warnung",
|
||||
string.Format(AppResources.MessageAppVersionIsOutdated, ContactPageViewModel.GetAppName(TinkApp.Uris.ActiveUri)),
|
||||
"OK");
|
||||
|
||||
AppResources.MessageWaring,
|
||||
string.Format(AppResources.MessageCopriVersionIsOutdated, ContactPageViewModel.GetAppName(TinkApp.Uris.ActiveUri)),
|
||||
AppResources.MessageAnswerOk);
|
||||
|
||||
Log.ForContext<MapPageViewModel>().Error($"Outdated version of app detected. Version expected is {resultStationsAndBikes.Response.StationsAll.CopriVersion}.");
|
||||
}
|
||||
|
||||
if (resultStationsAndBikes.Response.StationsAll.CopriVersion >= CopriCallsStatic.UnsupportedVersionUpper)
|
||||
{
|
||||
await m_oViewService.DisplayAlert(
|
||||
AppResources.MessageWaring,
|
||||
string.Format(AppResources.MessageAppVersionIsOutdated, ContactPageViewModel.GetAppName(TinkApp.Uris.ActiveUri)),
|
||||
AppResources.MessageAnswerOk);
|
||||
|
||||
Log.ForContext<MapPageViewModel>().Error($"Outdated version of app detected. Version expected is {resultStationsAndBikes.Response.StationsAll.CopriVersion}.");
|
||||
}
|
||||
|
||||
|
@ -360,7 +417,7 @@ namespace TINK.ViewModel.Map
|
|||
|
||||
if (resultStationsAndBikes.Exception?.GetType() == typeof(AuthcookieNotDefinedException))
|
||||
{
|
||||
Log.ForContext<MapPageViewModel>().Error("Map page is shown (probable for the first time after startup of app) and COPRI copri an auth cookie not defined error.{@l_oException}", resultStationsAndBikes.Exception);
|
||||
Log.ForContext<MapPageViewModel>().Error("Map page is shown (probable for the first time after startup of app) and COPRI auth cookie is not defined. {@l_oException}", resultStationsAndBikes.Exception);
|
||||
|
||||
// COPRI reports an auth cookie error.
|
||||
await m_oViewService.DisplayAlert(
|
||||
|
@ -375,12 +432,12 @@ namespace TINK.ViewModel.Map
|
|||
// Update pin colors.
|
||||
Log.ForContext<MapPageViewModel>().Verbose("Starting update pins color...");
|
||||
|
||||
var l_oColors = GetStationColors(
|
||||
var colors = GetStationColors(
|
||||
Pins.Select(x => x.Tag.ToString()).ToList(),
|
||||
resultStationsAndBikes.Response.Bikes);
|
||||
|
||||
// Update pins color form count of bikes located at station.
|
||||
UpdatePinsColor(l_oColors);
|
||||
UpdatePinsColor(colors);
|
||||
|
||||
m_oViewUpdateManager = CreateUpdateTask();
|
||||
|
||||
|
@ -476,7 +533,7 @@ namespace TINK.ViewModel.Map
|
|||
TinkApp.PostAction(
|
||||
unused =>
|
||||
{
|
||||
ActionText = "Aktualisiere...";
|
||||
ActionText = AppResources.ActivityTextUpdating;
|
||||
IsConnected = TinkApp.GetIsConnected();
|
||||
},
|
||||
null);
|
||||
|
@ -546,7 +603,7 @@ namespace TINK.ViewModel.Map
|
|||
|
||||
/// <summary> User clicked on a bike. </summary>
|
||||
/// <param name="selectedStationId">Id of station user clicked on.</param>
|
||||
public async void OnStationClicked(int selectedStationId)
|
||||
public async void OnStationClicked(string selectedStationId)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -555,7 +612,8 @@ namespace TINK.ViewModel.Map
|
|||
// Lock action to prevent multiple instances of "BikeAtStation" being opened.
|
||||
IsMapPageEnabled = false;
|
||||
|
||||
TinkApp.SelectedStation = selectedStationId;
|
||||
TinkApp.SelectedStation = TinkApp.Stations.FirstOrDefault(x => x.Id == selectedStationId)
|
||||
?? new Station(selectedStationId, new List<string>(), null); // Station might not be in list StationDictinaly because this list is not updatd in background task.
|
||||
|
||||
#if TRYNOTBACKSTYLE
|
||||
m_oNavigation.ShowPage(
|
||||
|
@ -585,13 +643,13 @@ namespace TINK.ViewModel.Map
|
|||
/// <summary>
|
||||
/// Gets the list of station color for all stations.
|
||||
/// </summary>
|
||||
/// <param name="p_oStationsId">Station id list to get color for.</param>
|
||||
/// <param name="stationsId">Station id list to get color for.</param>
|
||||
/// <returns></returns>
|
||||
private static IList<Color> GetStationColors(
|
||||
IEnumerable<string> p_oStationsId,
|
||||
IEnumerable<string> stationsId,
|
||||
BikeCollection bikesAll)
|
||||
{
|
||||
if (p_oStationsId == null)
|
||||
if (stationsId == null)
|
||||
{
|
||||
Log.ForContext<MapPageViewModel>().Debug("No stations available to update color for.");
|
||||
return new List<Color>();
|
||||
|
@ -601,41 +659,33 @@ namespace TINK.ViewModel.Map
|
|||
{
|
||||
// If object is null an error occurred querrying bikes availalbe or bikes occpied which results in an unknown state.
|
||||
Log.ForContext<MapPageViewModel>().Error("No bikes available to determine pins color.");
|
||||
return new List<Color>(p_oStationsId.Select(x => Color.Blue));
|
||||
return new List<Color>(stationsId.Select(x => Color.Blue));
|
||||
}
|
||||
|
||||
// Get state for each station.
|
||||
var l_oColors = new List<Color>();
|
||||
foreach (var l_strStationId in p_oStationsId)
|
||||
var colors = new List<Color>();
|
||||
foreach (var stationId in stationsId)
|
||||
{
|
||||
if (int.TryParse(l_strStationId, out int l_iStationId) == false)
|
||||
{
|
||||
// Station id is not valid.
|
||||
Log.ForContext<MapPageViewModel>().Error($"A station id {l_strStationId} is invalid (not integer).");
|
||||
l_oColors.Add(Color.Blue);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get color of given station.
|
||||
var l_oBikesAtStation = bikesAll.Where(x => x.CurrentStation == l_iStationId);
|
||||
if (l_oBikesAtStation.FirstOrDefault(x => x.State.Value != Model.State.InUseStateEnum.Disposable) != null)
|
||||
var bikesAtStation = bikesAll.Where(x => x.CurrentStation == stationId).ToList();
|
||||
if (bikesAtStation.FirstOrDefault(x => x.State.Value != Model.State.InUseStateEnum.Disposable) != null)
|
||||
{
|
||||
// There is at least one requested or booked bike
|
||||
l_oColors.Add(Color.LightBlue);
|
||||
colors.Add(Color.LightBlue);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (l_oBikesAtStation.ToList().Count > 0)
|
||||
if (bikesAtStation.ToList().Count > 0)
|
||||
{
|
||||
// There is at least one bike available
|
||||
l_oColors.Add(Color.Green);
|
||||
colors.Add(Color.Green);
|
||||
continue;
|
||||
}
|
||||
|
||||
l_oColors.Add(Color.Red);
|
||||
colors.Add(Color.Red);
|
||||
}
|
||||
|
||||
return l_oColors;
|
||||
return colors;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -733,12 +783,14 @@ namespace TINK.ViewModel.Map
|
|||
if (Exception != null)
|
||||
{
|
||||
// An error occurred getting data from copri.
|
||||
return Exception.GetShortErrorInfoText();
|
||||
return TinkApp.IsReportLevelVerbose
|
||||
? Exception.GetShortErrorInfoText()
|
||||
: AppResources.ActivityTextException;
|
||||
}
|
||||
|
||||
if (!IsConnected)
|
||||
{
|
||||
return "Offline.";
|
||||
return AppResources.ActivityTextConnectionStateOffline;
|
||||
}
|
||||
|
||||
return ActionText ?? string.Empty;
|
||||
|
@ -806,13 +858,12 @@ namespace TINK.ViewModel.Map
|
|||
Pins.Clear();
|
||||
|
||||
// Check location permission
|
||||
var _permissions = TinkApp.Permissions;
|
||||
var status = await _permissions.CheckPermissionStatusAsync<LocationPermission>();
|
||||
var status = await PermissionsService.CheckPermissionStatusAsync<LocationPermission>();
|
||||
if (TinkApp.CenterMapToCurrentLocation
|
||||
&& !TinkApp.GeolocationServices.Active.IsSimulation
|
||||
&& !GeolocationService.IsSimulation
|
||||
&& status != Plugin.Permissions.Abstractions.PermissionStatus.Granted)
|
||||
{
|
||||
var permissionResult = await _permissions.RequestPermissionAsync<LocationPermission>();
|
||||
var permissionResult = await PermissionsService.RequestPermissionAsync<LocationPermission>();
|
||||
|
||||
if (permissionResult != Plugin.Permissions.Abstractions.PermissionStatus.Granted)
|
||||
{
|
||||
|
@ -825,7 +876,7 @@ namespace TINK.ViewModel.Map
|
|||
if (dialogResult)
|
||||
{
|
||||
// User decided to give access to locations permissions.
|
||||
_permissions.OpenAppSettings();
|
||||
PermissionsService.OpenAppSettings();
|
||||
IsMapPageEnabled = true;
|
||||
ActionText = "";
|
||||
return;
|
||||
|
@ -835,7 +886,7 @@ namespace TINK.ViewModel.Map
|
|||
// Do not use property .State to get bluetooth state due
|
||||
// to issue https://hausource.visualstudio.com/TINK/_workitems/edit/116 /
|
||||
// see https://github.com/xabre/xamarin-bluetooth-le/issues/112#issuecomment-380994887
|
||||
if (await CrossBluetoothLE.Current.GetBluetoothState() != Plugin.BLE.Abstractions.Contracts.BluetoothState.On)
|
||||
if (await BluetoothService.GetBluetoothState() != Plugin.BLE.Abstractions.Contracts.BluetoothState.On)
|
||||
{
|
||||
await m_oViewService.DisplayAlert(
|
||||
AppResources.MessageTitleHint,
|
||||
|
@ -852,7 +903,7 @@ namespace TINK.ViewModel.Map
|
|||
try
|
||||
{
|
||||
currentLocation = TinkApp.CenterMapToCurrentLocation
|
||||
? await TinkApp.GeolocationServices.Active.GetAsync()
|
||||
? await GeolocationService.GetAsync()
|
||||
: null;
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace TINK.ViewModel
|
|||
/// <returns>Display text</returns>
|
||||
public string GetReservedInfo(
|
||||
TimeSpan? remainingTime,
|
||||
int? stationId = null,
|
||||
string stationId = null,
|
||||
string code = null)
|
||||
{
|
||||
if (remainingTime == null)
|
||||
|
@ -38,20 +38,20 @@ namespace TINK.ViewModel
|
|||
return string.Format(AppResources.StatusTextReservationExpiredCodeLocationMaxReservationTime, code, stationId, StateRequestedInfo.MaximumReserveTime.Minutes);
|
||||
}
|
||||
|
||||
if (stationId.HasValue)
|
||||
if (!string.IsNullOrEmpty(stationId))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(code))
|
||||
{
|
||||
return string.Format(
|
||||
AppResources.StatusTextReservationExpiredCodeLocationReservationTime,
|
||||
code,
|
||||
ViewModelHelper.GetStationName(stationId.Value),
|
||||
ViewModelHelper.GetStationName(stationId),
|
||||
remainingTime.Value.Minutes);
|
||||
}
|
||||
|
||||
return string.Format(
|
||||
AppResources.StatusTextReservationExpiredLocationReservationTime,
|
||||
ViewModelHelper.GetStationName(stationId.Value),
|
||||
ViewModelHelper.GetStationName(stationId),
|
||||
remainingTime.Value.Minutes);
|
||||
}
|
||||
|
||||
|
@ -67,7 +67,7 @@ namespace TINK.ViewModel
|
|||
/// <returns>Display text</returns>
|
||||
public string GetBookedInfo(
|
||||
DateTime? from,
|
||||
int? stationId = null,
|
||||
string stationId = null,
|
||||
string code = null)
|
||||
{
|
||||
if (from == null)
|
||||
|
@ -77,12 +77,12 @@ namespace TINK.ViewModel
|
|||
|
||||
if (!string.IsNullOrEmpty(code))
|
||||
{
|
||||
if(stationId.HasValue)
|
||||
if(!string.IsNullOrEmpty(stationId))
|
||||
{
|
||||
return string.Format(
|
||||
AppResources.StatusTextBookedCodeLocationSince,
|
||||
code,
|
||||
ViewModelHelper.GetStationName(stationId.Value),
|
||||
ViewModelHelper.GetStationName(stationId),
|
||||
from.Value.ToString(BikeViewModelBase.TIMEFORMAT));
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ using Plugin.Permissions;
|
|||
using Plugin.Permissions.Abstractions;
|
||||
using Plugin.BLE.Abstractions.Contracts;
|
||||
using TINK.MultilingualResources;
|
||||
using TINK.Model.Device;
|
||||
|
||||
namespace TINK.ViewModel.MyBikes
|
||||
{
|
||||
|
@ -31,6 +32,7 @@ namespace TINK.ViewModel.MyBikes
|
|||
/// 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="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>
|
||||
|
@ -39,6 +41,7 @@ namespace TINK.ViewModel.MyBikes
|
|||
/// <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="viewService">Interface to actuate methodes on GUI.</param>
|
||||
public MyBikesPageViewModel(
|
||||
User p_oUser,
|
||||
|
@ -51,7 +54,8 @@ namespace TINK.ViewModel.MyBikes
|
|||
ILocksService lockService,
|
||||
PollingParameters p_oPolling,
|
||||
Action<SendOrPostCallback, object> postAction,
|
||||
IViewService viewService) : base(p_oUser, permissions, bluetoothLE, runtimPlatform, isConnectedDelegate, connectorFactory, geolocation, lockService, p_oPolling, postAction, viewService, () => new MyBikeInUseStateInfoProvider())
|
||||
ISmartDevice smartDevice,
|
||||
IViewService viewService) : base(p_oUser, permissions, bluetoothLE, runtimPlatform, isConnectedDelegate, connectorFactory, geolocation, lockService, p_oPolling, postAction, smartDevice, viewService, () => new MyBikeInUseStateInfoProvider())
|
||||
{
|
||||
CollectionChanged += (sender, eventargs) =>
|
||||
{
|
||||
|
@ -115,10 +119,10 @@ namespace TINK.ViewModel.MyBikes
|
|||
&& RuntimePlatform == Device.Android)
|
||||
{
|
||||
// Check location permission
|
||||
var status = await Permissions.CheckPermissionStatusAsync<LocationPermission>();
|
||||
var status = await PermissionsService.CheckPermissionStatusAsync<LocationPermission>();
|
||||
if (status != PermissionStatus.Granted)
|
||||
{
|
||||
var permissionResult = await Permissions.RequestPermissionAsync<LocationPermission>();
|
||||
var permissionResult = await PermissionsService.RequestPermissionAsync<LocationPermission>();
|
||||
|
||||
if (permissionResult != PermissionStatus.Granted)
|
||||
{
|
||||
|
@ -141,7 +145,7 @@ namespace TINK.ViewModel.MyBikes
|
|||
}
|
||||
|
||||
// Open permissions dialog.
|
||||
Permissions.OpenAppSettings();
|
||||
PermissionsService.OpenAppSettings();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -163,7 +167,7 @@ namespace TINK.ViewModel.MyBikes
|
|||
}
|
||||
|
||||
// Bluetooth state
|
||||
if (await BluetoothLE.GetBluetoothState() != BluetoothState.On)
|
||||
if (await BluetoothService.GetBluetoothState() != BluetoothState.On)
|
||||
{
|
||||
await ViewService.DisplayAlert(
|
||||
AppResources.MessageTitleHint,
|
||||
|
@ -230,7 +234,7 @@ namespace TINK.ViewModel.MyBikes
|
|||
PostAction(
|
||||
unused =>
|
||||
{
|
||||
ActionText = "Aktualisiere...";
|
||||
ActionText = AppResources.ActivityTextUpdating;
|
||||
IsConnected = IsConnectedDelegate();
|
||||
},
|
||||
null);
|
||||
|
|
|
@ -3,8 +3,7 @@ using System;
|
|||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.Model.Repository.Exception;
|
||||
using TINK.Model.Repository.Request;
|
||||
using TINK.Repository.Exception;
|
||||
|
||||
namespace TINK.ViewModel
|
||||
{
|
||||
|
|
|
@ -6,7 +6,7 @@ using System.ComponentModel;
|
|||
using System.Threading.Tasks;
|
||||
using TINK.Model;
|
||||
using TINK.Model.Connector;
|
||||
using TINK.Model.Repository.Exception;
|
||||
using TINK.Repository.Exception;
|
||||
using TINK.Model.Services.Geolocation;
|
||||
using TINK.Settings;
|
||||
using TINK.View;
|
||||
|
@ -16,6 +16,7 @@ using System.Linq;
|
|||
using TINK.Model.User.Account;
|
||||
using TINK.Services.BluetoothLock;
|
||||
using Xamarin.Forms;
|
||||
using TINK.Services;
|
||||
|
||||
namespace TINK.ViewModel
|
||||
{
|
||||
|
@ -51,12 +52,17 @@ namespace TINK.ViewModel
|
|||
/// </summary>
|
||||
private LogEventLevel m_oMinimumLogEventLevel;
|
||||
|
||||
/// <summary> Gets a value indicating whether reporting level is verbose or not.</summary>
|
||||
public bool IsReportLevelVerbose { get; set; }
|
||||
|
||||
/// <summary> List of copri server uris.</summary>
|
||||
public ServicesViewModel Themes { get; }
|
||||
|
||||
/// <summary> Reference on the tink app instance. </summary>
|
||||
private ITinkApp TinkApp { get; }
|
||||
|
||||
IServicesContainer<IGeolocation> GeoloctionServicesContainer { get; }
|
||||
|
||||
/// <summary> Constructs a settings page view model object.</summary>
|
||||
/// <param name="tinkApp"> Reference to tink app model.</param>
|
||||
/// <param name="p_oUser"></param>
|
||||
|
@ -69,16 +75,22 @@ namespace TINK.ViewModel
|
|||
/// <param name="p_oViewService">Interface to view</param>
|
||||
public SettingsPageViewModel(
|
||||
ITinkApp tinkApp,
|
||||
IServicesContainer<IGeolocation> geoloctionServicesContainer,
|
||||
IViewService p_oViewService)
|
||||
{
|
||||
TinkApp = tinkApp
|
||||
?? throw new ArgumentException("Can not instantiate settings page view model- object. No tink app object available.");
|
||||
|
||||
GeoloctionServicesContainer = geoloctionServicesContainer
|
||||
?? throw new ArgumentException($"Can not instantiate {nameof(SettingsPageViewModel)}- object. Geolocation services container object must not be null.");
|
||||
|
||||
m_oViewService = p_oViewService
|
||||
?? throw new ArgumentException("Can not instantiate settings page view model- object. No user view service available.");
|
||||
|
||||
m_oMinimumLogEventLevel = TinkApp.MinimumLogEventLevel;
|
||||
|
||||
IsReportLevelVerbose = TinkApp.IsReportLevelVerbose;
|
||||
|
||||
CenterMapToCurrentLocation = TinkApp.CenterMapToCurrentLocation;
|
||||
|
||||
ExternalFolder = TinkApp.ExternalFolder;
|
||||
|
@ -140,12 +152,12 @@ namespace TINK.ViewModel
|
|||
TinkApp.LocksServices.Active.GetType().FullName));
|
||||
|
||||
GeolocationServices = new ServicesViewModel(
|
||||
TinkApp.GeolocationServices.Select(x => x.GetType().FullName),
|
||||
GeoloctionServicesContainer.Select(x => x.GetType().FullName),
|
||||
new Dictionary<string, string> {
|
||||
{ typeof(LastKnownGeolocationService).FullName, "Smartdevice-LastKnowGeolocation" },
|
||||
{ typeof(GeolocationService).FullName, "Smartdevice-MediumAccuracy" },
|
||||
{ typeof(SimulatedGeolocationService).FullName, "Simulation-AlwaysSamePosition" } },
|
||||
TinkApp.GeolocationServices.Active.GetType().FullName);
|
||||
GeoloctionServicesContainer.Active.GetType().FullName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -212,7 +224,7 @@ namespace TINK.ViewModel
|
|||
/// </summary>
|
||||
public string DeviceIdentifier
|
||||
{
|
||||
get { return TinkApp.Device.GetIdentifier(); }
|
||||
get { return TinkApp.SmartDevice.Identifier; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -259,9 +271,11 @@ namespace TINK.ViewModel
|
|||
TinkApp.MinimumLogEventLevel = m_oMinimumLogEventLevel; // Update value to be serialized.
|
||||
TinkApp.UpdateLoggingLevel(m_oMinimumLogEventLevel); // Update logging server.
|
||||
|
||||
TinkApp.IsReportLevelVerbose = IsReportLevelVerbose;
|
||||
|
||||
TinkApp.LocksServices.SetActive(LocksServices.Services.Active);
|
||||
|
||||
TinkApp.GeolocationServices.SetActive(GeolocationServices.Active);
|
||||
GeoloctionServicesContainer.SetActive(GeolocationServices.Active);
|
||||
|
||||
TinkApp.LocksServices.SetTimeOut(TimeSpan.FromSeconds(LocksServices.ConnectTimeoutSec));
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
using Serilog;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.Model.Repository.Exception;
|
||||
using TINK.Repository.Exception;
|
||||
using TINK.Model.Device;
|
||||
using TINK.Model.State;
|
||||
using TINK.Model.Station;
|
||||
|
@ -10,8 +10,7 @@ using TINK.Model.User;
|
|||
using Xamarin.Forms;
|
||||
|
||||
using TINK.Model.Bikes.Bike.BC;
|
||||
using TINK.Model.Repository;
|
||||
using TINK.Repository.Exception;
|
||||
using TINK.Repository;
|
||||
using System.Net;
|
||||
using TINK.MultilingualResources;
|
||||
|
||||
|
@ -28,21 +27,21 @@ namespace TINK.ViewModel
|
|||
/// <summary>
|
||||
/// Gets station name from station object.
|
||||
/// </summary>
|
||||
/// <param name="p_oStation">Station to get id from</param>
|
||||
/// <param name="station">Station to get id from</param>
|
||||
/// <returns></returns>
|
||||
public static string GetStationName(this IStation p_oStation)
|
||||
public static string GetStationName(this IStation station)
|
||||
{
|
||||
if (p_oStation == null)
|
||||
if (station == null)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(p_oStation.StationName))
|
||||
if (!string.IsNullOrEmpty(station.StationName))
|
||||
{
|
||||
return $"{p_oStation.StationName}, Nr. {p_oStation.Id}.";
|
||||
return $"{station.StationName}, Nr. {station.Id}.";
|
||||
}
|
||||
|
||||
return GetStationName(p_oStation.Id);
|
||||
return GetStationName(station.Id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -50,9 +49,9 @@ namespace TINK.ViewModel
|
|||
/// </summary>
|
||||
/// <param name="p_oStation">Station to get id from</param>
|
||||
/// <returns></returns>
|
||||
public static string GetStationName(int p_iStationId)
|
||||
public static string GetStationName(string station)
|
||||
{
|
||||
return string.Format("{0} {1}", USER_FIENDLY_STATIONNUMBER_PREFIX, p_iStationId);
|
||||
return string.Format("{0} {1}", USER_FIENDLY_STATIONNUMBER_PREFIX, station);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -65,17 +64,29 @@ namespace TINK.ViewModel
|
|||
return int.Parse(p_strStationName.Replace(USER_FIENDLY_STATIONNUMBER_PREFIX, "").Trim());
|
||||
}
|
||||
|
||||
/// <summary> Get full display name of a bike which includes id. </summary>
|
||||
/// <remarks>
|
||||
/// If name is empty return Id as name.
|
||||
/// </remarks>
|
||||
/// <param name="bike">bike to get name for.</param>
|
||||
/// <returns>Display name of bike.</returns>
|
||||
public static string GetFullDisplayName(this IBikeInfoMutable bike)
|
||||
=> $"{(!string.IsNullOrEmpty(bike.Description) ? $"{bike.Description}, " : string.Empty)}Nr. {bike.Id}";
|
||||
|
||||
/// <summary> Get the display name of a bike. </summary>
|
||||
/// <param name="bike">bike to get name for.</param>
|
||||
/// <returns>Display name of bike.</returns>
|
||||
public static string GetDisplayName(this IBikeInfoMutable bike)
|
||||
{
|
||||
var l_oId = bike.Id;
|
||||
var l_oIsDemo = bike.IsDemo;
|
||||
=> $"{(!string.IsNullOrEmpty(bike.Description) ? $"{bike.Description}" : $"{bike.Id}")}";
|
||||
|
||||
// Not known how many whells cargo bike has.
|
||||
return $"{(!string.IsNullOrEmpty(bike.Description) ? $"{bike.Description}, " : string.Empty)}Nr. {l_oId}";
|
||||
}
|
||||
/// <summary> Get the display id of a bike.</summary>
|
||||
/// <remarks>
|
||||
/// If name is empty id is used as name. For this reason return nothing in this case to avoid duplicate output of id.
|
||||
/// </remarks>
|
||||
/// <param name="bike">bike to get name for.</param>
|
||||
/// <returns>Display name of bike.</returns>
|
||||
public static string GetDisplayId(this IBikeInfoMutable bike)
|
||||
=> $"{(!string.IsNullOrEmpty(bike.Description) ? $"{bike.Id}" : string.Empty)}";
|
||||
|
||||
/// <summary>
|
||||
/// Maps state to color.
|
||||
|
@ -108,6 +119,7 @@ namespace TINK.ViewModel
|
|||
}
|
||||
|
||||
// An error occurred getting bikes information.
|
||||
#if USCSHARP9
|
||||
switch (exception)
|
||||
{
|
||||
case WebConnectFailureException:
|
||||
|
@ -119,10 +131,30 @@ namespace TINK.ViewModel
|
|||
case DeserializationException:
|
||||
return AppResources.ActivityTextErrorDeserializationException;
|
||||
case WebException webException:
|
||||
return string.Format(AppResources.ActivityTextErrorWebException, webException.Status);
|
||||
return webException.Status == WebExceptionStatus.ProtocolError && webException.Response is HttpWebResponse webResponse
|
||||
? string.Format(AppResources.ActivityTextErrorWebExceptionProtocolError, webResponse.StatusDescription)
|
||||
: string.Format(AppResources.ActivityTextErrorWebExceptionGeneralError, webException.Status.ToString());
|
||||
default:
|
||||
return AppResources.ActivityTextErrorException;
|
||||
}
|
||||
#else
|
||||
if (exception is WebConnectFailureException)
|
||||
return AppResources.ActivityTextErrorWebConnectFailureException;
|
||||
if (exception is InvalidResponseException)
|
||||
return AppResources.ActivityTextErrorInvalidResponseException;
|
||||
if (exception is WebForbiddenException)
|
||||
return AppResources.ActivityTextErrorWebForbiddenException;
|
||||
if (exception is DeserializationException)
|
||||
return AppResources.ActivityTextErrorDeserializationException;
|
||||
if (exception is WebException webException)
|
||||
{
|
||||
return webException.Status == WebExceptionStatus.ProtocolError && webException.Response is HttpWebResponse webResponse
|
||||
? string.Format(AppResources.ActivityTextErrorWebExceptionProtocolError, webResponse.StatusDescription)
|
||||
: string.Format(AppResources.ActivityTextErrorWebExceptionGeneralError, webException.Status.ToString());
|
||||
}
|
||||
|
||||
return AppResources.ActivityTextErrorException;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ using System.ComponentModel;
|
|||
|
||||
namespace TINK.ViewModel.WhatsNew
|
||||
{
|
||||
public class WhatsNewViewModel : INotifyPropertyChanged
|
||||
public class WhatsNewViewModel
|
||||
{
|
||||
/// <summary> Constructs view model. </summary>
|
||||
/// <param name="currentVersion"></param>
|
||||
|
@ -95,12 +95,9 @@ namespace TINK.ViewModel.WhatsNew
|
|||
}
|
||||
|
||||
/// <summary>Reference to view service object.</summary>
|
||||
private IViewService ViewService;
|
||||
private readonly IViewService ViewService;
|
||||
|
||||
/// <summary>Reference to view service object.</summary>
|
||||
private Action ShowMasterDetail { get; }
|
||||
|
||||
/// <summary> Fired whenever a property changes.</summary>
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue