Version 3.0.346

This commit is contained in:
Oliver Hauff 2022-10-17 18:45:38 +02:00
parent 1ba809dd59
commit 47c03f43fb
43 changed files with 609 additions and 117 deletions

View file

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Threading;
@ -218,6 +218,12 @@ namespace TINK.ViewModel.Bikes
}
break;
case System.Collections.Specialized.NotifyCollectionChangedAction.Reset:
// Empty collection.
// Occurs in context of find bike page when searching for second, third, ... bike (reopen of page via flyout).
ClearItems();
break;
}
}
@ -442,11 +448,17 @@ namespace TINK.ViewModel.Bikes
}
/// <summary>
/// Invoked when page is shown.
/// Starts update process.
/// Invoked when page is shown and starts update process.
/// </summary>
/// <param name="updateAction"> Update fuction passed as argument by child class.</param>
protected async Task OnAppearing(Action updateAction)
=> await StartUpdateTask(updateAction);
/// <summary>
/// Starts update process.
/// </summary>
/// <param name="updateAction"> Update fuction passed as argument by child class.</param>
public async Task StartUpdateTask(Action updateAction)
{
m_oViewUpdateManager = new PollingUpdateTaskManager(updateAction);
@ -465,10 +477,7 @@ namespace TINK.ViewModel.Bikes
/// Invoked when page is shutdown.
/// Currently invoked by code behind, would be nice if called by XAML in future versions.
/// </summary>
public async Task OnDisappearing()
{
await m_oViewUpdateManager.StopUpdatePeridically();
}
public virtual async Task OnDisappearing()
=> await m_oViewUpdateManager.StopUpdatePeridically();
}
}
}

View file

@ -13,9 +13,11 @@ using TINK.Model.Bikes;
using TINK.Model.Bikes.BikeInfoNS.BluetoothLock;
using TINK.Model.Connector;
using TINK.Model.Device;
using TINK.Model.Services.CopriApi;
using TINK.Model.Station;
using TINK.Model.User;
using TINK.MultilingualResources;
using TINK.Repository.Exception;
using TINK.Services.BluetoothLock;
using TINK.Services.BluetoothLock.Tdo;
using TINK.Services.Geolocation;
@ -43,6 +45,7 @@ namespace TINK.ViewModel.FindBike
}
bikeIdUserInput = value;
base.OnPropertyChanged(new PropertyChangedEventArgs(nameof(BikeIdUserInput)));
base.OnPropertyChanged(new PropertyChangedEventArgs(nameof(IsSelectBikeEnabled)));
}
}
@ -123,14 +126,29 @@ namespace TINK.ViewModel.FindBike
/// </summary>
public async Task OnAppearing()
{
IsIdle = false;
Log.ForContext<FindBikePageViewModel>().Information("User request to show page FindBike- page re-appearing");
ActionText = AppResources.ActivityTextFindBikeLoadingBikes;
if (string.IsNullOrEmpty(BikeIdUserInput) /* Find bike page flyout was taped */
&& BikeCollection.Count > 0 /* Bike was successfully selected */)
{
// Find bike page flyout was taped and page was already opened before and bike has been selected.
// Clear bike collection to allow user to enter bike id and search for bike.
BikeCollection.Clear();
}
var bikes = await ConnectorFactory(IsConnected).Query.GetBikesAsync();
if (BikeCollection.Count > 0)
{
// Page is appearing not because page flyout was taped.
// Bike has already been selected.
// Restart update.
await StartUpdateTask(() => UpdateTask());
Exception = bikes.Exception; // Update communication error from query for bikes occupied.
Bikes = bikes.Response;
ActionText = "";
IsIdle = true;
return;
}
ActionText = "";
IsIdle = true;
@ -142,6 +160,48 @@ namespace TINK.ViewModel.FindBike
/// <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;
Result<BikeCollection> bikes = null;
try
{
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 failed (Copri server not reachable).");
await ViewService.DisplayAdvancedAlert(
AppResources.ErrorReturnBikeNoWebTitle,
string.Format("{0}\r\n{1}", AppResources.ErrorReturnBikeNoWebMessage, WebConnectFailureException.GetHintToPossibleExceptionsReasons),
exception.Message,
AppResources.MessageAnswerOk);
}
else
{
Log.ForContext<FindBikePageViewModel>().Error("Getting bikes failed. {Exception}", exception);
await ViewService.DisplayAlert(
AppResources.MessageTitleHint,
exception.Message,
AppResources.MessageAnswerOk);
}
ActionText = "";
IsIdle = true;
return;
}
finally
{
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));
@ -152,6 +212,9 @@ namespace TINK.ViewModel.FindBike
AppResources.MessageTitleHint,
string.Format(AppResources.MessageErrorSelectBikeNoBikeFound, BikeIdUserInput),
AppResources.MessageAnswerOk);
ActionText = "";
IsIdle = true;
return;
}
@ -193,7 +256,7 @@ namespace TINK.ViewModel.FindBike
// User decided not to give access to locations permissions.
BikeCollection.Update(bikeCollection, Stations);
//await OnAppearing(() => UpdateTask());
await StartUpdateTask(() => UpdateTask());
ActionText = "";
IsIdle = true;
@ -215,7 +278,7 @@ namespace TINK.ViewModel.FindBike
BikeCollection.Update(bikeCollection, Stations);
await OnAppearing(() => UpdateTask());
await StartUpdateTask(() => UpdateTask());
ActionText = "";
IsIdle = true;
@ -232,7 +295,7 @@ namespace TINK.ViewModel.FindBike
BikeCollection.Update(bikeCollection, Stations);
await OnAppearing(() => UpdateTask());
await StartUpdateTask(() => UpdateTask());
ActionText = "";
IsIdle = true;
@ -259,7 +322,7 @@ namespace TINK.ViewModel.FindBike
BikeCollection.Update(bikeCollection.UpdateLockInfo(locksInfo), Stations);
await OnAppearing(() => UpdateTask());
await StartUpdateTask(() => UpdateTask());
ActionText = "";
IsIdle = true;
@ -272,6 +335,9 @@ namespace TINK.ViewModel.FindBike
AppResources.MessageAnswerOk);
Log.ForContext<FindBikePageViewModel>().Error("Running command to select bike failed. {Exception}", exception);
ActionText = "";
IsIdle = true;
return;
}
}

View file

@ -1,4 +1,4 @@
using Xamarin.Forms;
using Xamarin.Forms;
using TINK.View;
using TINK.Model.Station;
using System;
@ -1028,4 +1028,4 @@ namespace TINK.ViewModel.Map
public bool IsToggleVisible => tinkKonradToggleViewModel.IsToggleVisible;
}
}
}

View file

@ -0,0 +1,18 @@
using System.Collections.Generic;
using System.Linq;
namespace TINK.ViewModel.Settings
{
/// <summary> Manages data to be shown by a picker. </summary>
public class PickerViewModel : ServicesViewModel
{
/// <summary>Constructs view model ensuring consistency. </summary>
/// <param name="serviceToText"> Dictionary holding values and display text to mange and display by picker.</param>
/// <param name="active">Value of entry for which the display text has to be shown.</param>
public PickerViewModel(
IDictionary<string, string> serviceToText,
string active) : base(serviceToText.Select(x => x.Key), serviceToText, active)
{
}
}
}

View file

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;

View file

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
@ -8,6 +8,7 @@ using Serilog.Events;
using TINK.Model;
using TINK.Model.Connector;
using TINK.Model.User.Account;
using TINK.MultilingualResources;
using TINK.Repository.Exception;
using TINK.Services;
using TINK.Services.BluetoothLock;
@ -44,6 +45,9 @@ namespace TINK.ViewModel
/// <summary> Manages selection of locks services.</summary>
public LocksServicesViewModel LocksServices { get; }
/// <summary>Settings determining the startup behavior of the app.</summary>
public ServicesViewModel StartupSettings { get; }
/// <summary> Manages selection of geolocation services.</summary>
public ServicesViewModel GeolocationServices { get; }
@ -155,6 +159,13 @@ namespace TINK.ViewModel
{ typeof(GeolocationAccuracyBestService).FullName, "Best Accuracy" },
{ typeof(SimulatedGeolocationService).FullName, "Simulation-AlwaysSamePosition" } },
GeoloctionServicesContainer.Active.GetType().FullName);
StartupSettings = new PickerViewModel(
new Dictionary<string, string> {
{ ViewTypes.MapPage.ToString(), AppResources.MarkingMapPage },
{ ViewTypes.FindBikePage.ToString(), AppResources.MarkingFindBike },
},
tinkApp.StartupSettings.StartupPage.ToString());
}
/// <summary>
@ -259,6 +270,8 @@ namespace TINK.ViewModel
TinkApp.GroupFilterMapPage,
TinkApp.ActiveUser.DoFilter(TinkApp.FilterGroupSetting.DoFilter()));
TinkApp.StartupSettings.StartupPage = Enum.TryParse(StartupSettings.Active, out ViewTypes startupPage) ? startupPage : Model.Settings.StartupSettings.DefaultStartupPage;
TinkApp.CenterMapToCurrentLocation = CenterMapToCurrentLocation;
if (IsLogToExternalFolderVisible)