mirror of
https://dev.azure.com/TeilRad/sharee.bike%20App/_git/Code
synced 2025-04-22 21:06:30 +02:00
Version 3.0.373
This commit is contained in:
parent
f1cbab1d0a
commit
06428d96d9
87 changed files with 1796 additions and 1208 deletions
|
@ -13,10 +13,8 @@ using TINK.Model.Bikes;
|
|||
using TINK.Model.Bikes.BikeInfoNS.BikeNS;
|
||||
using TINK.Model.Bikes.BikeInfoNS.BluetoothLock;
|
||||
using TINK.Model.Connector;
|
||||
using TINK.Model.Connector.Filter;
|
||||
using TINK.Model.Device;
|
||||
using TINK.Model.Services.CopriApi;
|
||||
using TINK.Model.State;
|
||||
using TINK.Model.Stations.StationNS;
|
||||
using TINK.Model.User;
|
||||
using TINK.MultilingualResources;
|
||||
|
@ -29,7 +27,6 @@ using TINK.Settings;
|
|||
using TINK.View;
|
||||
using TINK.ViewModel.Bikes;
|
||||
using TINK.ViewModel.Map;
|
||||
using Xamarin.Essentials;
|
||||
using Xamarin.Forms;
|
||||
using Command = Xamarin.Forms.Command;
|
||||
|
||||
|
@ -77,7 +74,7 @@ namespace TINK.ViewModel.FindBike
|
|||
public BikeCollection Bikes { get; set; }
|
||||
|
||||
/// <summary> Do not allow to select bike if id is not set.</summary>
|
||||
public bool IsSelectBikeEnabled => IsIdle && BikeIdUserInput != null && BikeIdUserInput.Length > 0;
|
||||
public bool IsSelectBikeEnabled => IsIdle && BikeIdUserInput != null && BikeIdUserInput.Length > 1 && BikeIdUserInput.Any(x => char.IsLetter(x)) && BikeIdUserInput.Any(x => char.IsDigit(x));
|
||||
|
||||
/// <summary> Hide id input fields as soon as bike is found.</summary>
|
||||
public bool IsSelectBikeVisible => BikeCollection != null && BikeCollection.Count == 0;
|
||||
|
@ -85,6 +82,9 @@ namespace TINK.ViewModel.FindBike
|
|||
/// <summary> Holds the stations to get station names form station ids. </summary>
|
||||
private IEnumerable<IStation> Stations { get; }
|
||||
|
||||
/// <summary> Reference on the tink app instance. </summary>
|
||||
private ITinkApp TinkApp { get; }
|
||||
|
||||
/// <summary>
|
||||
/// True if ListView of Bikes is refreshing after user pulled;
|
||||
/// </summary>
|
||||
|
@ -124,6 +124,7 @@ namespace TINK.ViewModel.FindBike
|
|||
/// <param name="openUrlInBrowser">Delegate to open browser.</param>
|
||||
public FindBikePageViewModel(
|
||||
User user,
|
||||
ITinkApp tinkApp,
|
||||
ILocationPermission permissions,
|
||||
IBluetoothLE bluetoothLE,
|
||||
string runtimPlatform,
|
||||
|
@ -145,6 +146,9 @@ namespace TINK.ViewModel.FindBike
|
|||
|
||||
Stations = stations ?? throw new ArgumentException(nameof(stations));
|
||||
|
||||
TinkApp = tinkApp
|
||||
?? throw new ArgumentException("Can not instantiate settings page view model- object. No tink app object available.");
|
||||
|
||||
RefreshCommand = new Command(async () => {
|
||||
|
||||
IsRefreshing = false;
|
||||
|
@ -215,99 +219,136 @@ namespace TINK.ViewModel.FindBike
|
|||
}
|
||||
|
||||
/// <summary> Command object to bind select bike button to view model. </summary>
|
||||
public System.Windows.Input.ICommand OnSelectBikeRequest => new Xamarin.Forms.Command(async () => await SelectBike(), () => IsSelectBikeEnabled);
|
||||
public System.Windows.Input.ICommand OnSelectBikeRequest => new Xamarin.Forms.Command(async () => await SelectBike());
|
||||
|
||||
/// <summary> Select a bike by ID</summary>
|
||||
public async Task SelectBike()
|
||||
{
|
||||
// Get List of bike to be able to connect to.
|
||||
ActionText = AppResources.ActivityTextFindBikeLoadingBikes;
|
||||
IsIdle = false;
|
||||
|
||||
IsConnected = IsConnectedDelegate();
|
||||
|
||||
Result<BikeCollection> bikes = null;
|
||||
try
|
||||
if (!IsSelectBikeEnabled)
|
||||
{
|
||||
bikes = await ConnectorFactory(IsConnected).Query.GetBikesAsync();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
if (exception is WebConnectFailureException)
|
||||
{
|
||||
// Copri server is not reachable.
|
||||
Log.ForContext<FindBikePageViewModel>().Information("Getting bikes failed (Copri server not reachable).");
|
||||
|
||||
await ViewService.DisplayAlert(
|
||||
AppResources.ErrorSelectBikeTitle,
|
||||
AppResources.ErrorNoWeb,
|
||||
AppResources.MessageAnswerOk);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.ForContext<FindBikePageViewModel>().Error("Getting bikes failed. {Exception}", exception);
|
||||
|
||||
await ViewService.DisplayAlert(
|
||||
AppResources.ErrorSelectBikeTitle,
|
||||
exception.Message,
|
||||
AppResources.MessageAnswerOk);
|
||||
}
|
||||
|
||||
ActionText = string.Empty;
|
||||
IsIdle = true;
|
||||
await ViewService.DisplayAlert(
|
||||
String.Empty,
|
||||
AppResources.ErrorSelectBikeInputNotSufficent,
|
||||
AppResources.MessageAnswerOk);
|
||||
return;
|
||||
}
|
||||
finally
|
||||
else
|
||||
{
|
||||
Exception = bikes?.Exception ?? null; // Update communication error from query for bikes occupied.
|
||||
Bikes = bikes.Response;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var selectedBike = Bikes.FirstOrDefault(x => x.Id.Equals(BikeIdUserInput.Trim(), StringComparison.OrdinalIgnoreCase));
|
||||
// Get List of bike to be able to connect to.
|
||||
ActionText = AppResources.ActivityTextFindBikeLoadingBikes;
|
||||
IsIdle = false;
|
||||
|
||||
if (selectedBike == null)
|
||||
IsConnected = IsConnectedDelegate();
|
||||
|
||||
Result<BikeCollection> bikes = null;
|
||||
try
|
||||
{
|
||||
await ViewService.DisplayAlert(
|
||||
AppResources.MessageHintTitle,
|
||||
string.Format(AppResources.ErrorSelectBikeNoBikeFound, BikeIdUserInput),
|
||||
AppResources.MessageAnswerOk);
|
||||
bikes = await ConnectorFactory(IsConnected).Query.GetBikesAsync();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
if (exception is WebConnectFailureException)
|
||||
{
|
||||
// Copri server is not reachable.
|
||||
Log.ForContext<FindBikePageViewModel>().Information("Getting bikes failed (Copri server not reachable).");
|
||||
|
||||
await ViewService.DisplayAlert(
|
||||
AppResources.ErrorSelectBikeTitle,
|
||||
AppResources.ErrorNoWeb,
|
||||
AppResources.MessageAnswerOk);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.ForContext<FindBikePageViewModel>().Error("Getting bikes failed. {Exception}", exception);
|
||||
|
||||
await ViewService.DisplayAlert(
|
||||
AppResources.ErrorSelectBikeTitle,
|
||||
exception.Message,
|
||||
AppResources.MessageAnswerOk);
|
||||
}
|
||||
|
||||
ActionText = string.Empty;
|
||||
IsIdle = true;
|
||||
return;
|
||||
}
|
||||
|
||||
var bikeCollection = new BikeCollection(new Dictionary<string, Model.Bikes.BikeInfoNS.BC.BikeInfo> { { selectedBike.Id, selectedBike } });
|
||||
|
||||
var lockIdList = bikeCollection
|
||||
.GetLockIt()
|
||||
.Cast<BikeInfo>()
|
||||
.Select(x => x.LockInfo)
|
||||
.ToList();
|
||||
|
||||
if (LockService is ILocksServiceFake serviceFake)
|
||||
finally
|
||||
{
|
||||
serviceFake.UpdateSimulation(bikeCollection);
|
||||
Exception = bikes?.Exception ?? null; // Update communication error from query for bikes occupied.
|
||||
Bikes = bikes.Response;
|
||||
}
|
||||
|
||||
// Check bluetooth and location permission and states
|
||||
ActionText = AppResources.ActivityTextCheckBluetoothState;
|
||||
|
||||
if (bikeCollection.FirstOrDefault(x => x is BikeInfo btBike) != null
|
||||
//&& RuntimePlatform == Device.Android
|
||||
)
|
||||
try
|
||||
{
|
||||
// Check location permission
|
||||
var status = await PermissionsService.CheckStatusAsync();
|
||||
if (status != Status.Granted)
|
||||
{
|
||||
if (RuntimePlatform == Device.Android)
|
||||
{
|
||||
var permissionResult = await PermissionsService.RequestAsync();
|
||||
var selectedBike = Bikes.FirstOrDefault(x => x.Id.Equals(BikeIdUserInput.Trim(), StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (permissionResult != Status.Granted)
|
||||
if (selectedBike == null)
|
||||
{
|
||||
await ViewService.DisplayAlert(
|
||||
AppResources.ErrorSelectBikeTitle,
|
||||
TinkApp.Flavor == AppFlavor.MeinKonrad
|
||||
? $"{string.Format(AppResources.ErrorSelectBikeNoBikeFound, BikeIdUserInput)}\r\n\r\n{string.Format(AppResources.ErrorSelectBikeNoBikeFoundBikeTypeHint, ActiveFilteredBikeType)}"
|
||||
: string.Format(AppResources.ErrorSelectBikeNoBikeFound, BikeIdUserInput),
|
||||
AppResources.MessageAnswerOk);
|
||||
|
||||
ActionText = string.Empty;
|
||||
IsIdle = true;
|
||||
return;
|
||||
}
|
||||
|
||||
var bikeCollection = new BikeCollection(new Dictionary<string, Model.Bikes.BikeInfoNS.BC.BikeInfo> { { selectedBike.Id, selectedBike } });
|
||||
|
||||
var lockIdList = bikeCollection
|
||||
.GetLockIt()
|
||||
.Cast<BikeInfo>()
|
||||
.Select(x => x.LockInfo)
|
||||
.ToList();
|
||||
|
||||
if (LockService is ILocksServiceFake serviceFake)
|
||||
{
|
||||
serviceFake.UpdateSimulation(bikeCollection);
|
||||
}
|
||||
|
||||
// Check bluetooth and location permission and states
|
||||
ActionText = AppResources.ActivityTextCheckBluetoothState;
|
||||
|
||||
if (bikeCollection.FirstOrDefault(x => x is BikeInfo btBike) != null
|
||||
//&& RuntimePlatform == Device.Android
|
||||
)
|
||||
{
|
||||
// Check location permission
|
||||
var status = await PermissionsService.CheckStatusAsync();
|
||||
if (status != Status.Granted)
|
||||
{
|
||||
if (RuntimePlatform == Device.Android)
|
||||
{
|
||||
var permissionResult = await PermissionsService.RequestAsync();
|
||||
|
||||
if (permissionResult != Status.Granted)
|
||||
{
|
||||
var dialogResult = await ViewService.DisplayAlert(
|
||||
AppResources.MessageHintTitle,
|
||||
AppResources.MessageBikesManagementLocationPermissionOpenDialog,
|
||||
AppResources.MessageAnswerYes,
|
||||
AppResources.MessageAnswerNo);
|
||||
|
||||
if (!dialogResult)
|
||||
{
|
||||
// User decided not to give access to locations permissions.
|
||||
BikeCollection.Update(bikeCollection, Stations);
|
||||
|
||||
await StartUpdateTask(() => UpdateTask());
|
||||
|
||||
ActionText = string.Empty;
|
||||
IsIdle = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// Open permissions dialog.
|
||||
PermissionsService.OpenAppSettings();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var dialogResult = await ViewService.DisplayAlert(
|
||||
AppResources.MessageHintTitle,
|
||||
|
@ -331,102 +372,79 @@ namespace TINK.ViewModel.FindBike
|
|||
PermissionsService.OpenAppSettings();
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
// Location state
|
||||
if (GeolocationService.IsGeolcationEnabled == false)
|
||||
{
|
||||
var dialogResult = await ViewService.DisplayAlert(
|
||||
AppResources.MessageHintTitle,
|
||||
AppResources.MessageBikesManagementLocationPermissionOpenDialog,
|
||||
AppResources.MessageAnswerYes,
|
||||
AppResources.MessageAnswerNo);
|
||||
await ViewService.DisplayAlert(
|
||||
AppResources.MessageHintTitle,
|
||||
AppResources.MessageBikesManagementLocationActivation,
|
||||
AppResources.MessageAnswerOk);
|
||||
|
||||
if (!dialogResult)
|
||||
{
|
||||
// User decided not to give access to locations permissions.
|
||||
BikeCollection.Update(bikeCollection, Stations);
|
||||
BikeCollection.Update(bikeCollection, Stations);
|
||||
|
||||
await StartUpdateTask(() => UpdateTask());
|
||||
await StartUpdateTask(() => UpdateTask());
|
||||
|
||||
ActionText = string.Empty;
|
||||
IsIdle = true;
|
||||
return;
|
||||
}
|
||||
ActionText = string.Empty;
|
||||
IsIdle = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// Open permissions dialog.
|
||||
PermissionsService.OpenAppSettings();
|
||||
// Bluetooth state
|
||||
if (await BluetoothService.GetBluetoothState() != BluetoothState.On)
|
||||
{
|
||||
await ViewService.DisplayAlert(
|
||||
AppResources.MessageHintTitle,
|
||||
AppResources.MessageBikesManagementBluetoothActivation,
|
||||
AppResources.MessageAnswerOk);
|
||||
|
||||
BikeCollection.Update(bikeCollection, Stations);
|
||||
|
||||
await StartUpdateTask(() => UpdateTask());
|
||||
|
||||
ActionText = string.Empty;
|
||||
IsIdle = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Location state
|
||||
if (GeolocationService.IsGeolcationEnabled == false)
|
||||
// Connect to bluetooth devices.
|
||||
ActionText = AppResources.ActivityTextSearchBikes;
|
||||
IEnumerable<LockInfoTdo> locksInfoTdo;
|
||||
try
|
||||
{
|
||||
await ViewService.DisplayAlert(
|
||||
AppResources.MessageHintTitle,
|
||||
AppResources.MessageBikesManagementLocationActivation,
|
||||
AppResources.MessageAnswerOk);
|
||||
|
||||
BikeCollection.Update(bikeCollection, Stations);
|
||||
|
||||
await StartUpdateTask(() => UpdateTask());
|
||||
|
||||
ActionText = string.Empty;
|
||||
IsIdle = true;
|
||||
return;
|
||||
locksInfoTdo = await LockService.GetLocksStateAsync(
|
||||
lockIdList.Select(x => x.ToLockInfoTdo()).ToList(),
|
||||
LockService.TimeOut.MultiConnect);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Log.ForContext<FindBikePageViewModel>().Error("Getting bluetooth state failed. {Exception}", exception);
|
||||
locksInfoTdo = new List<LockInfoTdo>();
|
||||
}
|
||||
|
||||
// Bluetooth state
|
||||
if (await BluetoothService.GetBluetoothState() != BluetoothState.On)
|
||||
{
|
||||
await ViewService.DisplayAlert(
|
||||
AppResources.MessageHintTitle,
|
||||
AppResources.MessageBikesManagementBluetoothActivation,
|
||||
AppResources.MessageAnswerOk);
|
||||
var locksInfo = lockIdList.UpdateById(locksInfoTdo);
|
||||
|
||||
BikeCollection.Update(bikeCollection, Stations);
|
||||
BikeCollection.Update(bikeCollection.UpdateLockInfo(locksInfo), Stations);
|
||||
|
||||
await StartUpdateTask(() => UpdateTask());
|
||||
await StartUpdateTask(() => UpdateTask());
|
||||
|
||||
ActionText = string.Empty;
|
||||
IsIdle = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Connect to bluetooth devices.
|
||||
ActionText = AppResources.ActivityTextSearchBikes;
|
||||
IEnumerable<LockInfoTdo> locksInfoTdo;
|
||||
try
|
||||
{
|
||||
locksInfoTdo = await LockService.GetLocksStateAsync(
|
||||
lockIdList.Select(x => x.ToLockInfoTdo()).ToList(),
|
||||
LockService.TimeOut.MultiConnect);
|
||||
ActionText = string.Empty;
|
||||
IsIdle = true;
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Log.ForContext<FindBikePageViewModel>().Error("Getting bluetooth state failed. {Exception}", exception);
|
||||
locksInfoTdo = new List<LockInfoTdo>();
|
||||
await ViewService.DisplayAlert(
|
||||
AppResources.ErrorSelectBikeTitle,
|
||||
exception.Message,
|
||||
AppResources.MessageAnswerOk);
|
||||
|
||||
Log.ForContext<FindBikePageViewModel>().Error("Running command to select bike failed. {Exception}", exception);
|
||||
|
||||
ActionText = string.Empty;
|
||||
IsIdle = true;
|
||||
return;
|
||||
}
|
||||
|
||||
var locksInfo = lockIdList.UpdateById(locksInfoTdo);
|
||||
|
||||
BikeCollection.Update(bikeCollection.UpdateLockInfo(locksInfo), Stations);
|
||||
|
||||
await StartUpdateTask(() => UpdateTask());
|
||||
|
||||
ActionText = string.Empty;
|
||||
IsIdle = true;
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
await ViewService.DisplayAlert(
|
||||
AppResources.ErrorSelectBikeTitle,
|
||||
exception.Message,
|
||||
AppResources.MessageAnswerOk);
|
||||
|
||||
Log.ForContext<FindBikePageViewModel>().Error("Running command to select bike failed. {Exception}", exception);
|
||||
|
||||
ActionText = string.Empty;
|
||||
IsIdle = true;
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue