mirror of
https://dev.azure.com/TeilRad/sharee.bike%20App/_git/Code
synced 2025-04-19 03:27:29 +02:00
Closing lock and returning bike speeded up.
This commit is contained in:
parent
e4adeb908c
commit
db9c288584
70 changed files with 933 additions and 902 deletions
|
@ -425,6 +425,10 @@ namespace TINK.Model
|
|||
{
|
||||
new Version(3, 0, 243),
|
||||
AppResources.ChangeLog3_0_243
|
||||
},
|
||||
{
|
||||
new Version(3, 0, 244),
|
||||
AppResources.ChangeLog3_0_231 // Minor improvements.
|
||||
}
|
||||
};
|
||||
|
||||
|
|
153
TINKLib/MultilingualResources/AppResources.Designer.cs
generated
153
TINKLib/MultilingualResources/AppResources.Designer.cs
generated
|
@ -312,6 +312,24 @@ namespace TINK.MultilingualResources {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Can not query location info..
|
||||
/// </summary>
|
||||
public static string ActivityTextErrorQueryLocationQuery {
|
||||
get {
|
||||
return ResourceManager.GetString("ActivityTextErrorQueryLocationQuery", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to No location info available..
|
||||
/// </summary>
|
||||
public static string ActivityTextErrorQueryLocationWhenAny {
|
||||
get {
|
||||
return ResourceManager.GetString("ActivityTextErrorQueryLocationWhenAny", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Battery status cannot be read..
|
||||
/// </summary>
|
||||
|
@ -438,6 +456,33 @@ namespace TINK.MultilingualResources {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Query location....
|
||||
/// </summary>
|
||||
public static string ActivityTextQueryLocation {
|
||||
get {
|
||||
return ResourceManager.GetString("ActivityTextQueryLocation", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Cancel query location....
|
||||
/// </summary>
|
||||
public static string ActivityTextQueryLocationCancelWait {
|
||||
get {
|
||||
return ResourceManager.GetString("ActivityTextQueryLocationCancelWait", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Start query location....
|
||||
/// </summary>
|
||||
public static string ActivityTextQueryLocationStart {
|
||||
get {
|
||||
return ResourceManager.GetString("ActivityTextQueryLocationStart", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Reading charging level....
|
||||
/// </summary>
|
||||
|
@ -456,6 +501,15 @@ namespace TINK.MultilingualResources {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Asking for permissions....
|
||||
/// </summary>
|
||||
public static string ActivityTextRequestingLocationPermissions {
|
||||
get {
|
||||
return ResourceManager.GetString("ActivityTextRequestingLocationPermissions", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Reserving bike....
|
||||
/// </summary>
|
||||
|
@ -465,6 +519,15 @@ namespace TINK.MultilingualResources {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Returning bike....
|
||||
/// </summary>
|
||||
public static string ActivityTextReturningBike {
|
||||
get {
|
||||
return ResourceManager.GetString("ActivityTextReturningBike", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Searching locks....
|
||||
/// </summary>
|
||||
|
@ -779,6 +842,15 @@ namespace TINK.MultilingualResources {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Closing lock and returning bike speeded up..
|
||||
/// </summary>
|
||||
public static string ChangeLog3_0_244 {
|
||||
get {
|
||||
return ResourceManager.GetString("ChangeLog3_0_244", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Lock of rented bike can not be found..
|
||||
/// </summary>
|
||||
|
@ -965,6 +1037,24 @@ namespace TINK.MultilingualResources {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Internet must be available when returning the bike..
|
||||
/// </summary>
|
||||
public static string ErrorReturnBikeNoWebMessage {
|
||||
get {
|
||||
return ResourceManager.GetString("ErrorReturnBikeNoWebMessage", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Connection error when returning the bike!.
|
||||
/// </summary>
|
||||
public static string ErrorReturnBikeNoWebTitle {
|
||||
get {
|
||||
return ResourceManager.GetString("ErrorReturnBikeNoWebTitle", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Your feedback could not be send to server successfully..
|
||||
/// </summary>
|
||||
|
@ -1514,6 +1604,33 @@ namespace TINK.MultilingualResources {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Closing the lock and ending the rental is not possible..
|
||||
/// </summary>
|
||||
public static string MessageErrorQueryLocationMessage {
|
||||
get {
|
||||
return ResourceManager.GetString("MessageErrorQueryLocationMessage", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Error Start Query Location!.
|
||||
/// </summary>
|
||||
public static string MessageErrorQueryLocationStartTitle {
|
||||
get {
|
||||
return ResourceManager.GetString("MessageErrorQueryLocationStartTitle", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Error Query Location!.
|
||||
/// </summary>
|
||||
public static string MessageErrorQueryLocationTitle {
|
||||
get {
|
||||
return ResourceManager.GetString("MessageErrorQueryLocationTitle", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Login cookie must not be empty. {0}.
|
||||
/// </summary>
|
||||
|
@ -1607,15 +1724,6 @@ namespace TINK.MultilingualResources {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Rent bike {0} and open lock?.
|
||||
/// </summary>
|
||||
public static string MessageOpenLockAndBookeBike {
|
||||
get {
|
||||
return ResourceManager.GetString("MessageOpenLockAndBookeBike", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Urgent questions?.
|
||||
/// </summary>
|
||||
|
@ -1733,6 +1841,24 @@ namespace TINK.MultilingualResources {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Close lock and return bike {0}?.
|
||||
/// </summary>
|
||||
public static string QuestionCloseLockAndReturnBike {
|
||||
get {
|
||||
return ResourceManager.GetString("QuestionCloseLockAndReturnBike", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Rent bike {0} and open lock?.
|
||||
/// </summary>
|
||||
public static string QuestionOpenLockAndBookBike {
|
||||
get {
|
||||
return ResourceManager.GetString("QuestionOpenLockAndBookBike", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Reserve bike {0} free of charge for {1} min?.
|
||||
/// </summary>
|
||||
|
@ -1742,6 +1868,15 @@ namespace TINK.MultilingualResources {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Return bike {0}?.
|
||||
/// </summary>
|
||||
public static string QuestionReturnBike {
|
||||
get {
|
||||
return ResourceManager.GetString("QuestionReturnBike", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to {0} app request.
|
||||
/// </summary>
|
||||
|
|
|
@ -374,9 +374,6 @@ Freigabedialog öffen?</value>
|
|||
Software Pakete aktualisiert.
|
||||
Zielplatform Android 11.</value>
|
||||
</data>
|
||||
<data name="MessageOpenLockAndBookeBike" xml:space="preserve">
|
||||
<value>Fahrrad {0} mieten und Schloss öffnen?</value>
|
||||
</data>
|
||||
<data name="ActivityTextReservingBike" xml:space="preserve">
|
||||
<value>Reserviere Rad...</value>
|
||||
</data>
|
||||
|
@ -653,4 +650,53 @@ Layout Anzeige Radnamen und nummern verbessert.</value>
|
|||
<value>Miniumfrage implementiert.
|
||||
Kleinere Verbesserungen.</value>
|
||||
</data>
|
||||
<data name="ActivityTextRequestingLocationPermissions" xml:space="preserve">
|
||||
<value>Anfrage nach Berechtigungen...</value>
|
||||
</data>
|
||||
<data name="ActivityTextQueryLocation" xml:space="preserve">
|
||||
<value>Abfrage Standort...</value>
|
||||
</data>
|
||||
<data name="MessageErrorQueryLocationTitle" xml:space="preserve">
|
||||
<value>Fehler bei Standortabfrage!</value>
|
||||
</data>
|
||||
<data name="MessageErrorQueryLocationMessage" xml:space="preserve">
|
||||
<value>Schloss schließen und Miete beenden ist nicht möglich.</value>
|
||||
</data>
|
||||
<data name="MessageErrorQueryLocationStartTitle" xml:space="preserve">
|
||||
<value>Fehler beim Start der Standortabfrage!</value>
|
||||
</data>
|
||||
<data name="ActivityTextErrorQueryLocationWhenAny" xml:space="preserve">
|
||||
<value>Keine Standortinfo verfügbar.</value>
|
||||
</data>
|
||||
<data name="ActivityTextErrorQueryLocationQuery" xml:space="preserve">
|
||||
<value>Standortabfrage nicht möglich.</value>
|
||||
</data>
|
||||
<data name="ActivityTextQueryLocationCancelWait" xml:space="preserve">
|
||||
<value>Abbruch Standortabfrage...</value>
|
||||
</data>
|
||||
<data name="ActivityTextQueryLocationStart" xml:space="preserve">
|
||||
<value>Start Standortabfrage...</value>
|
||||
</data>
|
||||
<data name="QuestionCloseLockAndReturnBike" xml:space="preserve">
|
||||
<value>Fahrrad {0} abschließen und zurückgeben?</value>
|
||||
</data>
|
||||
<data name="QuestionReturnBike" xml:space="preserve">
|
||||
<value>Fahrrad {0} zurückgeben?
|
||||
</value>
|
||||
</data>
|
||||
<data name="ActivityTextReturningBike" xml:space="preserve">
|
||||
<value>Gebe Rad zurück...</value>
|
||||
</data>
|
||||
<data name="QuestionOpenLockAndBookBike" xml:space="preserve">
|
||||
<value>Fahrrad {0} mieten und Schloss öffnen?</value>
|
||||
</data>
|
||||
<data name="ErrorReturnBikeNoWebMessage" xml:space="preserve">
|
||||
<value>Internet muss erreichbar sein beim Zurückgeben des Rads.</value>
|
||||
</data>
|
||||
<data name="ErrorReturnBikeNoWebTitle" xml:space="preserve">
|
||||
<value>Verbingungsfehler beim Zurückgeben des Rads!</value>
|
||||
</data>
|
||||
<data name="ChangeLog3_0_244" xml:space="preserve">
|
||||
<value>Abschließen von Rad und Radrückgabe beschleunigt.</value>
|
||||
</data>
|
||||
</root>
|
|
@ -482,7 +482,7 @@ Targets Android 11.</value>
|
|||
<data name="ActivityTextReservingBike" xml:space="preserve">
|
||||
<value>Reserving bike...</value>
|
||||
</data>
|
||||
<data name="MessageOpenLockAndBookeBike" xml:space="preserve">
|
||||
<data name="QuestionOpenLockAndBookBike" xml:space="preserve">
|
||||
<value>Rent bike {0} and open lock?</value>
|
||||
</data>
|
||||
<data name="ActivityTextErrorReadingChargingLevelGeneral" xml:space="preserve">
|
||||
|
@ -749,4 +749,49 @@ Layout of bike names and id display improved.</value>
|
|||
<value>Mini survey implemented.
|
||||
Minor fixes.</value>
|
||||
</data>
|
||||
<data name="ActivityTextRequestingLocationPermissions" xml:space="preserve">
|
||||
<value>Asking for permissions...</value>
|
||||
</data>
|
||||
<data name="ActivityTextErrorQueryLocationQuery" xml:space="preserve">
|
||||
<value>Can not query location info.</value>
|
||||
</data>
|
||||
<data name="ActivityTextErrorQueryLocationWhenAny" xml:space="preserve">
|
||||
<value>No location info available.</value>
|
||||
</data>
|
||||
<data name="ActivityTextQueryLocation" xml:space="preserve">
|
||||
<value>Query location...</value>
|
||||
</data>
|
||||
<data name="ActivityTextQueryLocationCancelWait" xml:space="preserve">
|
||||
<value>Cancel query location...</value>
|
||||
</data>
|
||||
<data name="ActivityTextQueryLocationStart" xml:space="preserve">
|
||||
<value>Start query location...</value>
|
||||
</data>
|
||||
<data name="MessageErrorQueryLocationMessage" xml:space="preserve">
|
||||
<value>Closing the lock and ending the rental is not possible.</value>
|
||||
</data>
|
||||
<data name="MessageErrorQueryLocationStartTitle" xml:space="preserve">
|
||||
<value>Error Start Query Location!</value>
|
||||
</data>
|
||||
<data name="MessageErrorQueryLocationTitle" xml:space="preserve">
|
||||
<value>Error Query Location!</value>
|
||||
</data>
|
||||
<data name="QuestionCloseLockAndReturnBike" xml:space="preserve">
|
||||
<value>Close lock and return bike {0}?</value>
|
||||
</data>
|
||||
<data name="ActivityTextReturningBike" xml:space="preserve">
|
||||
<value>Returning bike...</value>
|
||||
</data>
|
||||
<data name="QuestionReturnBike" xml:space="preserve">
|
||||
<value>Return bike {0}?</value>
|
||||
</data>
|
||||
<data name="ChangeLog3_0_244" xml:space="preserve">
|
||||
<value>Closing lock and returning bike speeded up.</value>
|
||||
</data>
|
||||
<data name="ErrorReturnBikeNoWebMessage" xml:space="preserve">
|
||||
<value>Internet must be available when returning the bike.</value>
|
||||
</data>
|
||||
<data name="ErrorReturnBikeNoWebTitle" xml:space="preserve">
|
||||
<value>Connection error when returning the bike!</value>
|
||||
</data>
|
||||
</root>
|
|
@ -496,10 +496,6 @@ Targets Android 11.</source>
|
|||
Software Pakete aktualisiert.
|
||||
Zielplatform Android 11.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="MessageOpenLockAndBookeBike" translate="yes" xml:space="preserve">
|
||||
<source>Rent bike {0} and open lock?</source>
|
||||
<target state="translated">Fahrrad {0} mieten und Schloss öffnen?</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ActivityTextReservingBike" translate="yes" xml:space="preserve">
|
||||
<source>Reserving bike...</source>
|
||||
<target state="translated">Reserviere Rad...</target>
|
||||
|
@ -875,6 +871,71 @@ Minor fixes.</source>
|
|||
<target state="translated">Miniumfrage implementiert.
|
||||
Kleinere Verbesserungen.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ActivityTextRequestingLocationPermissions" translate="yes" xml:space="preserve">
|
||||
<source>Asking for permissions...</source>
|
||||
<target state="translated">Anfrage nach Berechtigungen...</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ActivityTextQueryLocation" translate="yes" xml:space="preserve">
|
||||
<source>Query location...</source>
|
||||
<target state="translated">Abfrage Standort...</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="MessageErrorQueryLocationTitle" translate="yes" xml:space="preserve">
|
||||
<source>Error Query Location!</source>
|
||||
<target state="translated">Fehler bei Standortabfrage!</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="MessageErrorQueryLocationMessage" translate="yes" xml:space="preserve">
|
||||
<source>Closing the lock and ending the rental is not possible.</source>
|
||||
<target state="translated">Schloss schließen und Miete beenden ist nicht möglich.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="MessageErrorQueryLocationStartTitle" translate="yes" xml:space="preserve">
|
||||
<source>Error Start Query Location!</source>
|
||||
<target state="translated">Fehler beim Start der Standortabfrage!</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ActivityTextErrorQueryLocationWhenAny" translate="yes" xml:space="preserve">
|
||||
<source>No location info available.</source>
|
||||
<target state="translated">Keine Standortinfo verfügbar.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ActivityTextErrorQueryLocationQuery" translate="yes" xml:space="preserve">
|
||||
<source>Can not query location info.</source>
|
||||
<target state="translated">Standortabfrage nicht möglich.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ActivityTextQueryLocationCancelWait" translate="yes" xml:space="preserve">
|
||||
<source>Cancel query location...</source>
|
||||
<target state="translated">Abbruch Standortabfrage...</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ActivityTextQueryLocationStart" translate="yes" xml:space="preserve">
|
||||
<source>Start query location...</source>
|
||||
<target state="translated">Start Standortabfrage...</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="QuestionCloseLockAndReturnBike" translate="yes" xml:space="preserve">
|
||||
<source>Close lock and return bike {0}?</source>
|
||||
<target state="translated">Fahrrad {0} abschließen und zurückgeben?</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="QuestionReturnBike" translate="yes" xml:space="preserve">
|
||||
<source>Return bike {0}?</source>
|
||||
<target state="translated">Fahrrad {0} zurückgeben?
|
||||
</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ActivityTextReturningBike" translate="yes" xml:space="preserve">
|
||||
<source>Returning bike...</source>
|
||||
<target state="translated">Gebe Rad zurück...</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="QuestionOpenLockAndBookBike" translate="yes" xml:space="preserve">
|
||||
<source>Rent bike {0} and open lock?</source>
|
||||
<target state="translated">Fahrrad {0} mieten und Schloss öffnen?</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ErrorReturnBikeNoWebMessage" translate="yes" xml:space="preserve">
|
||||
<source>Internet must be available when returning the bike.</source>
|
||||
<target state="translated">Internet muss erreichbar sein beim Zurückgeben des Rads.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ErrorReturnBikeNoWebTitle" translate="yes" xml:space="preserve">
|
||||
<source>Connection error when returning the bike!</source>
|
||||
<target state="translated">Verbingungsfehler beim Zurückgeben des Rads!</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="ChangeLog3_0_244" translate="yes" xml:space="preserve">
|
||||
<source>Closing lock and returning bike speeded up.</source>
|
||||
<target state="translated">Abschließen von Rad und Radrückgabe beschleunigt.</target>
|
||||
</trans-unit>
|
||||
</group>
|
||||
</body>
|
||||
</file>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using Serilog;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.Model.Device;
|
||||
using Xamarin.Essentials;
|
||||
|
@ -22,13 +23,17 @@ namespace TINK.Model.Services.Geolocation
|
|||
|
||||
public bool IsGeolcationEnabled => Dependent.IsGeolcationEnabled;
|
||||
|
||||
/// <summary> Gets the current location.</summary>
|
||||
/// <param name="cancellationToken">Token to cancel request for geolocation.</param>
|
||||
/// <param name="timeStamp">Time when geolocation is of interest. Is used to determine whether cached geoloation can be used or not.</param>
|
||||
public async Task<Location> GetAsync(DateTime? timeStamp = null)
|
||||
public async Task<Location> GetAsync(CancellationToken? cancellationToken = null, DateTime? timeStamp = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var request = new GeolocationRequest(GeolocationAccuracy.Medium, TimeSpan.FromMilliseconds(GEOLOCATIONREQUEST_TIMEOUT_MS));
|
||||
return await Xamarin.Essentials.Geolocation.GetLocationAsync(request);
|
||||
return cancellationToken.HasValue
|
||||
? await Xamarin.Essentials.Geolocation.GetLocationAsync(request, cancellationToken.Value)
|
||||
: await Xamarin.Essentials.Geolocation.GetLocationAsync(request);
|
||||
}
|
||||
catch (FeatureNotSupportedException fnsEx)
|
||||
{
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.Model.Device;
|
||||
using Xamarin.Essentials;
|
||||
|
@ -9,9 +10,10 @@ namespace TINK.Model.Services.Geolocation
|
|||
public interface IGeolocation : IGeolodationDependent
|
||||
{
|
||||
/// <summary> Gets the current location.</summary>
|
||||
/// <param name="cancellationToken">Token to cancel request for geolocation. If null request can not be cancels and times out after GeolocationService.GEOLOCATIONREQUEST_TIMEOUT_MS if geolocation is not available.</param>
|
||||
/// <param name="timeStamp">Time when geolocation is of interest. Is used to determine for some implementations whether cached geoloation can be used or not.</param>
|
||||
/// <returns></returns>
|
||||
Task<Location> GetAsync(DateTime? timeStamp = null);
|
||||
Task<Location> GetAsync(CancellationToken? cancellationToken = null, DateTime? timeStamp = null);
|
||||
|
||||
/// <summary> If true location data returned is simulated.</summary>
|
||||
bool IsSimulation { get; }
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using Serilog;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.Model.Device;
|
||||
using Xamarin.Essentials;
|
||||
|
@ -8,24 +9,22 @@ namespace TINK.Model.Services.Geolocation
|
|||
{
|
||||
public class LastKnownGeolocationService : IGeolocation
|
||||
{
|
||||
/// <summary> Timeout for geolocation request operations.</summary>
|
||||
private const int GEOLOCATIONREQUEST_TIMEOUT_MS = 5000;
|
||||
|
||||
private IGeolodationDependent Dependent { get; }
|
||||
|
||||
public LastKnownGeolocationService(IGeolodationDependent dependent)
|
||||
{
|
||||
Dependent = dependent;
|
||||
}
|
||||
|
||||
|
||||
/// <summary> Gets the current location.</summary>
|
||||
/// <param name="cancelationToken">Token to cancel request for geolocation.</param>
|
||||
/// <param name="timeStamp">Time when geolocation is of interest. Is used to determine whether cached geoloation can be used or not.</param>
|
||||
public async Task<Location> GetAsync(DateTime? timeStamp = null)
|
||||
public async Task<Location> GetAsync(CancellationToken? cancelationToken = null, DateTime? timeStamp = null)
|
||||
{
|
||||
Location location;
|
||||
try
|
||||
{
|
||||
var request = new GeolocationRequest(GeolocationAccuracy.Medium, TimeSpan.FromMilliseconds(GEOLOCATIONREQUEST_TIMEOUT_MS));
|
||||
location = await Xamarin.Essentials.Geolocation.GetLocationAsync(request);
|
||||
location = await Xamarin.Essentials.Geolocation.GetLastKnownLocationAsync();
|
||||
}
|
||||
catch (FeatureNotSupportedException fnsEx)
|
||||
{
|
||||
|
@ -59,13 +58,14 @@ namespace TINK.Model.Services.Geolocation
|
|||
return location;
|
||||
}
|
||||
|
||||
return await Xamarin.Essentials.Geolocation.GetLocationAsync();
|
||||
return await new GeolocationService(Dependent).GetAsync(cancelationToken, timeStamp);
|
||||
}
|
||||
|
||||
/// <summary> If true location data returned is simulated.</summary>
|
||||
public bool IsSimulation { get => false; }
|
||||
|
||||
public TimeSpan MaxAge => new TimeSpan(0, 3, 0);
|
||||
/// <summary> Maximum age allowed for location info. </summary>
|
||||
public TimeSpan MaxAge => new TimeSpan(0, 3 /*minutes*/, 0);
|
||||
|
||||
public bool IsGeolcationEnabled => Dependent.IsGeolcationEnabled;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.Model.Device;
|
||||
using Xamarin.Essentials;
|
||||
|
@ -14,7 +15,10 @@ namespace TINK.Model.Services.Geolocation
|
|||
Dependent = dependent;
|
||||
}
|
||||
|
||||
public async Task<Location> GetAsync(DateTime? timeStamp = null)
|
||||
/// <summary> Gets the current location.</summary>
|
||||
/// <param name="cancelToken">Token to cancel request for geolocation.</param>
|
||||
/// <param name="timeStamp">Time when geolocation is of interest. Is used to determine whether cached geoloation can be used or not.</param>
|
||||
public async Task<Location> GetAsync(CancellationToken? cancelToken = null, DateTime? timeStamp = null)
|
||||
{
|
||||
return await Task.FromResult(new Location(47.976634, 7.825490) { Accuracy = 0, Timestamp = timeStamp ?? DateTime.Now }); ;
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ namespace TINK.View
|
|||
/// <returns>T</returns>
|
||||
Task<string> DisplayActionSheet(string title, string cancel, string destruction, params string[] buttons);
|
||||
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
#if USEFLYOUT
|
||||
/// <summary> Shows a page.</summary>
|
||||
/// <param name="type">Type of page to show.</param>
|
||||
/// <param name="title">Title of page to show.</param>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
#if USEFLYOUT
|
||||
using Serilog;
|
||||
using System;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
#if USEFLYOUT
|
||||
using TINK.View.MasterDetail;
|
||||
|
||||
namespace TINK.View
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
#if USEFLYOUT
|
||||
using System;
|
||||
|
||||
namespace TINK.View.MasterDetail
|
||||
|
|
|
@ -325,7 +325,7 @@ namespace TINK.ViewModel.Account
|
|||
try
|
||||
{
|
||||
// Switch to map view after log out.
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
#if USEFLYOUT
|
||||
m_oViewService.ShowPage(ViewTypes.MapPage);
|
||||
#else
|
||||
await m_oViewService.ShowPage("//MapPage");
|
||||
|
|
|
@ -67,7 +67,7 @@ namespace TINK.ViewModel.Bikes.Bike.BC.RequestHandler
|
|||
try
|
||||
{
|
||||
// Switch to login page
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
#if USEFLYOUT
|
||||
ViewService.ShowPage(ViewTypes.LoginPage);
|
||||
#else
|
||||
await ViewService.ShowPage("//LoginPage");
|
||||
|
|
|
@ -16,6 +16,8 @@ using Xamarin.Essentials;
|
|||
using TINK.Repository.Request;
|
||||
using TINK.Model.Device;
|
||||
using TINK.Model.MiniSurvey;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
|
||||
namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
||||
{
|
||||
|
@ -64,18 +66,54 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
/// <summary> Return bike. </summary>
|
||||
public async Task<IRequestHandler> ReturnBike()
|
||||
{
|
||||
BikesViewModel.IsIdle = false;
|
||||
BikesViewModel.IsIdle = false;
|
||||
var ctsLocation = new CancellationTokenSource();
|
||||
Task<Location> currentLocationTask = null;
|
||||
var timeStamp = DateTime.Now;
|
||||
|
||||
// Check if bike is around.
|
||||
var deviceState = LockService[SelectedBike.LockInfo.Id].GetDeviceState();
|
||||
if (deviceState == DeviceState.Connected)
|
||||
{
|
||||
BikesViewModel.ActionText = AppResources.ActivityTextQueryLocationStart; // Bluetooth is in reach
|
||||
|
||||
// Start getting geolocation.
|
||||
try
|
||||
{
|
||||
currentLocationTask = Geolocation.GetAsync(ctsLocation.Token, timeStamp);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// No location information available.
|
||||
Log.ForContext<BookedClosed>().Information("Getting geolocation when returning bike {Bike} failed. {Exception}", SelectedBike, ex);
|
||||
}
|
||||
}
|
||||
|
||||
// Ask whether to really return bike?
|
||||
var l_oResult = await ViewService.DisplayAlert(
|
||||
string.Empty,
|
||||
$"Fahrrad {SelectedBike.GetFullDisplayName()} zurückgeben?",
|
||||
"Ja",
|
||||
"Nein");
|
||||
string.Format(AppResources.QuestionReturnBike, SelectedBike.GetFullDisplayName()),
|
||||
AppResources.MessageAnswerYes,
|
||||
AppResources.MessageAnswerNo);
|
||||
|
||||
if (l_oResult == false)
|
||||
{
|
||||
// User aborted returning bike process
|
||||
Log.ForContext<BookedClosed>().Information("User selected booked bike {l_oId} in order to return but action was canceled.", SelectedBike.Id);
|
||||
|
||||
// Cancel getting geolocation.
|
||||
ctsLocation.Cancel();
|
||||
BikesViewModel.ActionText = AppResources.ActivityTextQueryLocationCancelWait;
|
||||
try
|
||||
{
|
||||
await Task.WhenAny(new List<Task> { currentLocationTask ?? Task.CompletedTask });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// No location information available.
|
||||
Log.ForContext<BookedClosed>().Information("Canceling query location failed on abort returning closed bike failed. {Exception}", SelectedBike, ex);
|
||||
}
|
||||
|
||||
BikesViewModel.IsIdle = true;
|
||||
return this;
|
||||
}
|
||||
|
@ -88,23 +126,20 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
await ViewUpdateManager().StopUpdatePeridically();
|
||||
|
||||
// Check if bike is around.
|
||||
Location currentLocation = null;
|
||||
LocationDto currentLocationDto = null;
|
||||
var deviceState = LockService[SelectedBike.LockInfo.Id].GetDeviceState();
|
||||
if (deviceState == DeviceState.Connected)
|
||||
{
|
||||
// Bluetooth is in reach
|
||||
// Get geoposition to pass when returning.
|
||||
var timeStamp = DateTime.Now;
|
||||
BikesViewModel.ActionText = "Abfrage Standort...";
|
||||
Location currentLocation = null;
|
||||
BikesViewModel.ActionText = AppResources.ActivityTextQueryLocation;
|
||||
try
|
||||
{
|
||||
currentLocation = await Geolocation.GetAsync(timeStamp);
|
||||
await Task.WhenAny(new List<Task> { currentLocationTask ?? Task.CompletedTask });
|
||||
currentLocation = currentLocationTask?.Result ?? null;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// No location information available.
|
||||
Log.ForContext<BookedClosed>().Information("Returning bike {Bike} is not possible. {Exception}", SelectedBike, ex);
|
||||
Log.ForContext<BookedClosed>().Information("Returning closed bike {Bike} is not possible. Cancel geolocation query failed. {Exception}", SelectedBike, ex);
|
||||
}
|
||||
|
||||
currentLocationDto = currentLocation != null
|
||||
|
@ -123,7 +158,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
SelectedBike.LockInfo.State = LockingState.Disconnected;
|
||||
}
|
||||
|
||||
BikesViewModel.ActionText = "Gebe Rad zurück...";
|
||||
BikesViewModel.ActionText = "Returning bike...";
|
||||
IsConnected = IsConnectedDelegate();
|
||||
|
||||
var feedBackUri = SelectedBike?.OperatorUri;
|
||||
|
@ -146,10 +181,11 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
// Copri server is not reachable.
|
||||
Log.ForContext<BookedClosed>().Information("User selected booked bike {bike} but returing failed (Copri server not reachable).", SelectedBike);
|
||||
|
||||
await ViewService.DisplayAlert(
|
||||
"Verbingungsfehler beim Zurückgeben des Rads!",
|
||||
string.Format("{0}\r\n{1}\r\n{2}", "Internet muss erreichbar sein zum Zurückgeben des Rads.", exception.Message, WebConnectFailureException.GetHintToPossibleExceptionsReasons),
|
||||
"OK");
|
||||
await ViewService.DisplayAdvancedAlert(
|
||||
AppResources.ErrorReturnBikeNoWebTitle,
|
||||
string.Format("{0}\r\n{1}", AppResources.ErrorReturnBikeNoWebMessage, WebConnectFailureException.GetHintToPossibleExceptionsReasons),
|
||||
exception.Message,
|
||||
AppResources.MessageAnswerOk);
|
||||
}
|
||||
else if (exception is NotAtStationException notAtStationException)
|
||||
{
|
||||
|
@ -159,7 +195,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
await ViewService.DisplayAlert(
|
||||
AppResources.ErrorReturnBikeNotAtStationTitle,
|
||||
string.Format(AppResources.ErrorReturnBikeNotAtStationMessage, notAtStationException.StationNr, notAtStationException.Distance),
|
||||
"OK");
|
||||
AppResources.MessageAnswerOk);
|
||||
}
|
||||
else if (exception is NoGPSDataException)
|
||||
{
|
||||
|
@ -169,7 +205,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
await ViewService.DisplayAlert(
|
||||
AppResources.ErrorReturnBikeNotAtStationTitle,
|
||||
string.Format(AppResources.ErrorReturnBikeLockClosedNoGPSMessage),
|
||||
"OK");
|
||||
AppResources.MessageAnswerOk);
|
||||
}
|
||||
else if (exception is ResponseException copriException)
|
||||
{
|
||||
|
@ -188,7 +224,8 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
|
||||
await ViewService.DisplayAlert(
|
||||
"Fehler beim Zurückgeben des Rads!",
|
||||
exception.Message, "OK");
|
||||
exception.Message,
|
||||
"OK");
|
||||
}
|
||||
|
||||
BikesViewModel.ActionText = AppResources.ActivityTextStartingUpdater;
|
||||
|
@ -208,7 +245,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Log.ForContext<ReservedClosed>().Error("Lock can not be disconnected. {Exception}", exception);
|
||||
Log.ForContext<BookedClosed>().Error("Lock can not be disconnected. {Exception}", exception);
|
||||
|
||||
BikesViewModel.ActionText = AppResources.ActivityTextErrorDisconnect;
|
||||
}
|
||||
|
@ -230,11 +267,11 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
if (exception is ResponseException copriException)
|
||||
{
|
||||
// Copri server is not reachable.
|
||||
Log.ForContext<BookedOpen>().Information("Submitting feedback for bike {bike} failed. COPRI returned an error.", SelectedBike);
|
||||
Log.ForContext<BookedClosed>().Information("Submitting feedback for bike {bike} failed. COPRI returned an error.", SelectedBike);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.ForContext<BookedOpen>().Error("Submitting feedback for bike {bike} failed. {@l_oException}", SelectedBike.Id, exception);
|
||||
Log.ForContext<BookedClosed>().Error("Submitting feedback for bike {bike} failed. {@l_oException}", SelectedBike.Id, exception);
|
||||
}
|
||||
|
||||
await ViewService.DisplayAlert(
|
||||
|
@ -314,7 +351,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
else if (exception is CouldntOpenInconsistentStateExecption inconsistentState
|
||||
&& inconsistentState.State == LockingState.Closed)
|
||||
{
|
||||
Log.ForContext<BookedOpen>().Debug("Lock can not be opened. lock reports state closed. {Exception}", exception);
|
||||
Log.ForContext<BookedClosed>().Debug("Lock can not be opened. lock reports state closed. {Exception}", exception);
|
||||
|
||||
await ViewService.DisplayAlert(
|
||||
AppResources.ErrorOpenLockTitle,
|
||||
|
|
|
@ -93,7 +93,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
if (l_oException is WebConnectFailureException)
|
||||
{
|
||||
// Copri server is not reachable.
|
||||
Log.ForContext<DisposableDisconnected>().Information("User selected booked bike {l_oId} to connect to lock. (Copri server not reachable).", SelectedBike.Id);
|
||||
Log.ForContext<BookedDisconnected>().Information("User selected booked bike {l_oId} to connect to lock. (Copri server not reachable).", SelectedBike.Id);
|
||||
|
||||
await ViewService.DisplayAlert(
|
||||
"Fehler bei Verbinden mit Schloss!",
|
||||
|
@ -102,7 +102,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
}
|
||||
else
|
||||
{
|
||||
Log.ForContext<DisposableDisconnected>().Error("User selected booked bike {l_oId} to connect to lock. {@l_oException}", SelectedBike.Id, l_oException);
|
||||
Log.ForContext<BookedDisconnected>().Error("User selected booked bike {l_oId} to connect to lock. {@l_oException}", SelectedBike.Id, l_oException);
|
||||
|
||||
await ViewService.DisplayAlert(
|
||||
"Fehler bei Verbinden mit Schloss!",
|
||||
|
|
|
@ -16,6 +16,8 @@ using TINK.Model.User;
|
|||
using TINK.Repository.Request;
|
||||
using TINK.Model.Device;
|
||||
using TINK.Model.MiniSurvey;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
|
||||
namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
||||
{
|
||||
|
@ -62,18 +64,62 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
/// <summary> Close lock and return bike.</summary>
|
||||
public async Task<IRequestHandler> CloseLockAndReturnBike()
|
||||
{
|
||||
// Ask whether to really return bike?
|
||||
// Prevent concurrent interaction
|
||||
BikesViewModel.IsIdle = false;
|
||||
|
||||
// Start getting geolocation.
|
||||
BikesViewModel.ActionText = AppResources.ActivityTextQueryLocationStart;
|
||||
var ctsLocation = new CancellationTokenSource();
|
||||
Task<Location> currentLocationTask = null;
|
||||
var timeStamp = DateTime.Now;
|
||||
try
|
||||
{
|
||||
currentLocationTask = Geolocation.GetAsync(ctsLocation.Token, timeStamp);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// No location information available.
|
||||
Log.ForContext<BookedOpen>().Information("Returning bike {Bike} is not possible. Start query location failed. {Exception}", SelectedBike, ex);
|
||||
|
||||
BikesViewModel.ActionText = string.Empty;
|
||||
await ViewService.DisplayAlert(
|
||||
AppResources.MessageErrorQueryLocationStartTitle,
|
||||
$"{AppResources.MessageErrorQueryLocationMessage}\r\n{ex.Message}",
|
||||
AppResources.MessageAnswerOk);
|
||||
|
||||
BikesViewModel.ActionText = AppResources.ActivityTextStartingUpdater;
|
||||
await ViewUpdateManager().StartUpdateAyncPeridically(); // Restart polling again.
|
||||
|
||||
BikesViewModel.ActionText = string.Empty;
|
||||
BikesViewModel.IsIdle = true; // Unlock GUI
|
||||
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
|
||||
}
|
||||
|
||||
// Ask whether to really return bike?
|
||||
var l_oResult = await ViewService.DisplayAlert(
|
||||
string.Empty,
|
||||
$"Fahrrad {SelectedBike.GetFullDisplayName()} abschließen und zurückgeben?",
|
||||
"Ja",
|
||||
"Nein");
|
||||
string.Format(AppResources.QuestionCloseLockAndReturnBike, SelectedBike.GetFullDisplayName()),
|
||||
AppResources.MessageAnswerYes,
|
||||
AppResources.MessageAnswerNo);
|
||||
|
||||
if (l_oResult == false)
|
||||
{
|
||||
// User aborted closing and returning bike process
|
||||
Log.ForContext<BookedOpen>().Information("User selected booked bike {l_oId} in order to close and return but action was canceled.", SelectedBike.Id);
|
||||
|
||||
// Cancel getting geolocation.
|
||||
ctsLocation.Cancel();
|
||||
BikesViewModel.ActionText = AppResources.ActivityTextQueryLocationCancelWait;
|
||||
try
|
||||
{
|
||||
await Task.WhenAny(new List<Task> { currentLocationTask ?? Task.CompletedTask });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// No location information available.
|
||||
Log.ForContext<BookedOpen>().Information("Canceling query location failed on abort returning opened bike failed. {Exception}", SelectedBike, ex);
|
||||
}
|
||||
|
||||
BikesViewModel.IsIdle = true;
|
||||
return this;
|
||||
}
|
||||
|
@ -85,6 +131,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
BikesViewModel.ActionText = AppResources.ActivityTextOneMomentPlease;
|
||||
await ViewUpdateManager().StopUpdatePeridically();
|
||||
|
||||
// Close lock
|
||||
BikesViewModel.ActionText = AppResources.ActivityTextClosingLock;
|
||||
try
|
||||
{
|
||||
|
@ -94,6 +141,9 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
{
|
||||
BikesViewModel.ActionText = string.Empty;
|
||||
|
||||
// Signal cts to cancel getting geolocation.
|
||||
ctsLocation.Cancel();
|
||||
|
||||
if (exception is OutOfReachException)
|
||||
{
|
||||
Log.ForContext<BookedOpen>().Debug("Lock can not be closed. Lock is out of reach. {Exception}", exception);
|
||||
|
@ -101,7 +151,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
await ViewService.DisplayAlert(
|
||||
AppResources.ErrorCloseLockTitle,
|
||||
AppResources.ErrorCloseLockOutOfReachMessage,
|
||||
"OK");
|
||||
AppResources.MessageAnswerOk);
|
||||
}
|
||||
else if (exception is CounldntCloseMovingException)
|
||||
{
|
||||
|
@ -110,7 +160,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
await ViewService.DisplayAlert(
|
||||
AppResources.ErrorCloseLockTitle,
|
||||
AppResources.ErrorCloseLockMovingMessage,
|
||||
"OK");
|
||||
AppResources.MessageAnswerOk);
|
||||
}
|
||||
else if (exception is CouldntCloseBoldBlockedException)
|
||||
{
|
||||
|
@ -119,7 +169,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
await ViewService.DisplayAlert(
|
||||
AppResources.ErrorCloseLockTitle,
|
||||
AppResources.ErrorCloseLockBoldBlockedMessage,
|
||||
"OK");
|
||||
AppResources.MessageAnswerOk);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -128,13 +178,25 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
await ViewService.DisplayAlert(
|
||||
AppResources.ErrorCloseLockTitle,
|
||||
exception.Message,
|
||||
"OK");
|
||||
AppResources.MessageAnswerOk);
|
||||
}
|
||||
|
||||
SelectedBike.LockInfo.State = exception is StateAwareException stateAwareException
|
||||
? stateAwareException.State
|
||||
: LockingState.Disconnected;
|
||||
|
||||
// Wait until cancel getting geolocation has completed.
|
||||
BikesViewModel.ActionText = AppResources.ActivityTextQueryLocationCancelWait;
|
||||
try
|
||||
{
|
||||
await Task.WhenAny(new List<Task> { currentLocationTask ?? Task.CompletedTask });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// No location information available.
|
||||
Log.ForContext<BookedOpen>().Information("Canceling query location failed on closing lock error. {Exception}", SelectedBike, ex);
|
||||
}
|
||||
|
||||
BikesViewModel.ActionText = AppResources.ActivityTextStartingUpdater;
|
||||
await ViewUpdateManager().StartUpdateAyncPeridically(); // Restart polling again.
|
||||
|
||||
|
@ -146,14 +208,29 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
if (SelectedBike.LockInfo.State != LockingState.Closed)
|
||||
{
|
||||
Log.ForContext<BookedOpen>().Error($"Lock can not be closed. Invalid locking state state {SelectedBike.LockInfo.State} detected.");
|
||||
|
||||
// Signal cts to cancel getting geolocation.
|
||||
ctsLocation.Cancel();
|
||||
|
||||
BikesViewModel.ActionText = string.Empty;
|
||||
await ViewService.DisplayAlert(
|
||||
AppResources.ErrorCloseLockTitle,
|
||||
SelectedBike.LockInfo.State == LockingState.Open
|
||||
? AppResources.ErrorCloseLockStillOpenMessage
|
||||
: string.Format(AppResources.ErrorCloseLockUnexpectedStateMessage, SelectedBike.LockInfo.State),
|
||||
"OK");
|
||||
: string.Format(AppResources.ErrorCloseLockUnexpectedStateMessage, SelectedBike.LockInfo.State),
|
||||
AppResources.MessageAnswerOk);
|
||||
|
||||
// Wait until cancel getting geolocation has completed.
|
||||
BikesViewModel.ActionText = AppResources.ActivityTextQueryLocationCancelWait;
|
||||
try
|
||||
{
|
||||
await Task.WhenAny(new List<Task> { currentLocationTask ?? Task.CompletedTask });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// No location information available.
|
||||
Log.ForContext<BookedOpen>().Information("Canceling query location failed on unexpected lock state failed. {Exception}", SelectedBike, ex);
|
||||
}
|
||||
|
||||
BikesViewModel.ActionText = AppResources.ActivityTextStartingUpdater;
|
||||
await ViewUpdateManager().StartUpdateAyncPeridically(); // Restart polling again.
|
||||
|
@ -163,24 +240,24 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
|
||||
}
|
||||
|
||||
// Get geoposition.
|
||||
var timeStamp = DateTime.Now;
|
||||
BikesViewModel.ActionText = "Abfrage Standort...";
|
||||
Location currentLocation;
|
||||
BikesViewModel.ActionText = AppResources.ActivityTextQueryLocation;
|
||||
Location currentLocation = null;
|
||||
try
|
||||
{
|
||||
currentLocation = await Geolocation.GetAsync(timeStamp);
|
||||
var task = await Task.WhenAny(new List<Task> { currentLocationTask });
|
||||
currentLocation = currentLocationTask.Result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// No location information available.
|
||||
Log.ForContext<BookedOpen>().Information("Returning bike {Bike} is not possible. {Exception}", SelectedBike, ex);
|
||||
Log.ForContext<BookedOpen>().Information("Returning bike {Bike} is not possible. Query location failed. {Exception}", SelectedBike, ex);
|
||||
|
||||
BikesViewModel.ActionText = string.Empty;
|
||||
await ViewService.DisplayAlert(
|
||||
"Fehler bei Standortabfrage!",
|
||||
string.Format($"Schloss schließen und Miete beenden ist nicht möglich.\r\n{ex.Message}"),
|
||||
"OK");
|
||||
await ViewService.DisplayAdvancedAlert(
|
||||
AppResources.MessageErrorQueryLocationTitle,
|
||||
AppResources.MessageErrorQueryLocationMessage,
|
||||
ex.GetErrorMessage(),
|
||||
AppResources.MessageAnswerOk);
|
||||
|
||||
BikesViewModel.ActionText = AppResources.ActivityTextStartingUpdater;
|
||||
await ViewUpdateManager().StartUpdateAyncPeridically(); // Restart polling again.
|
||||
|
@ -191,7 +268,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
}
|
||||
|
||||
// Lock list to avoid multiple taps while copri action is pending.
|
||||
BikesViewModel.ActionText = "Gebe Rad zurück...";
|
||||
BikesViewModel.ActionText = AppResources.ActivityTextReturningBike;
|
||||
|
||||
IsConnected = IsConnectedDelegate();
|
||||
|
||||
|
@ -222,10 +299,11 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
// Copri server is not reachable.
|
||||
Log.ForContext<BookedOpen>().Information("User selected booked bike {bike} but returing failed (Copri server not reachable).", SelectedBike);
|
||||
|
||||
await ViewService.DisplayAlert(
|
||||
"Verbingungsfehler beim Zurückgeben des Rads!",
|
||||
string.Format("{0}\r\n{1}\r\n{2}", "Internet muss erreichbar sein beim Zurückgeben des Rads.", exception.Message, WebConnectFailureException.GetHintToPossibleExceptionsReasons),
|
||||
"OK");
|
||||
await ViewService.DisplayAdvancedAlert(
|
||||
AppResources.ErrorReturnBikeNoWebTitle,
|
||||
string.Format("{0}\r\n{1}", AppResources.ErrorReturnBikeNoWebMessage, WebConnectFailureException.GetHintToPossibleExceptionsReasons),
|
||||
exception.Message,
|
||||
AppResources.MessageAnswerOk);
|
||||
}
|
||||
else if (exception is NotAtStationException notAtStationException)
|
||||
{
|
||||
|
@ -235,7 +313,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
await ViewService.DisplayAlert(
|
||||
AppResources.ErrorReturnBikeNotAtStationTitle,
|
||||
string.Format(AppResources.ErrorReturnBikeNotAtStationMessage, notAtStationException.StationNr, notAtStationException.Distance),
|
||||
"OK");
|
||||
AppResources.MessageAnswerOk);
|
||||
}
|
||||
else if (exception is NoGPSDataException)
|
||||
{
|
||||
|
@ -245,7 +323,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
await ViewService.DisplayAlert(
|
||||
AppResources.ErrorReturnBikeNotAtStationTitle,
|
||||
string.Format(AppResources.ErrorReturnBikeLockOpenNoGPSMessage),
|
||||
"OK");
|
||||
AppResources.MessageAnswerOk);
|
||||
}
|
||||
else if (exception is ResponseException copriException)
|
||||
{
|
||||
|
@ -256,7 +334,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
"Statusfehler beim Zurückgeben des Rads!",
|
||||
copriException.Message,
|
||||
copriException.Response,
|
||||
"OK");
|
||||
AppResources.MessageAnswerOk);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -283,7 +361,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Log.ForContext<ReservedClosed>().Error("Lock can not be disconnected. {Exception}", exception);
|
||||
Log.ForContext<BookedOpen>().Error("Lock can not be disconnected. {Exception}", exception);
|
||||
|
||||
BikesViewModel.ActionText = AppResources.ActivityTextErrorDisconnect;
|
||||
}
|
||||
|
@ -345,12 +423,29 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
BikesViewModel.IsIdle = false;
|
||||
Log.ForContext<BookedOpen>().Information("User request to lock bike {bike} in order to pause ride.", SelectedBike);
|
||||
|
||||
// Start getting geolocation.
|
||||
BikesViewModel.ActionText = AppResources.ActivityTextQueryLocationStart;
|
||||
var ctsLocation = new CancellationTokenSource();
|
||||
Task<Location> currentLocationTask = null;
|
||||
var timeStamp = DateTime.Now;
|
||||
try
|
||||
{
|
||||
currentLocationTask = Geolocation.GetAsync(ctsLocation.Token, timeStamp);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// No location information available.
|
||||
Log.ForContext<BookedOpen>().Information("Closing lock of bike {Bike} is not possible. Starting query location failed. {Exception}", SelectedBike, ex);
|
||||
|
||||
BikesViewModel.ActionText = AppResources.ActivityTextErrorQueryLocationQuery;
|
||||
}
|
||||
|
||||
// Stop polling before returning bike.
|
||||
BikesViewModel.ActionText = AppResources.ActivityTextOneMomentPlease;
|
||||
await ViewUpdateManager().StopUpdatePeridically();
|
||||
|
||||
// Close lock
|
||||
BikesViewModel.ActionText = AppResources.ActivityTextClosingLock;
|
||||
|
||||
try
|
||||
{
|
||||
SelectedBike.LockInfo.State = (await LockService[SelectedBike.LockInfo.Id].CloseAsync())?.GetLockingState() ?? LockingState.Disconnected;
|
||||
|
@ -359,13 +454,16 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
{
|
||||
BikesViewModel.ActionText = string.Empty;
|
||||
|
||||
// Signal cts to cancel getting geolocation.
|
||||
ctsLocation.Cancel();
|
||||
|
||||
if (exception is OutOfReachException)
|
||||
{
|
||||
Log.ForContext<BookedOpen>().Debug("Lock can not be closed. {Exception}", exception);
|
||||
await ViewService.DisplayAlert(
|
||||
AppResources.ErrorCloseLockTitle,
|
||||
AppResources.ErrorCloseLockOutOfReachMessage,
|
||||
"OK");
|
||||
AppResources.MessageAnswerOk);
|
||||
}
|
||||
else if (exception is CounldntCloseMovingException)
|
||||
{
|
||||
|
@ -374,7 +472,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
await ViewService.DisplayAlert(
|
||||
AppResources.ErrorCloseLockTitle,
|
||||
AppResources.ErrorCloseLockMovingMessage,
|
||||
"OK");
|
||||
AppResources.MessageAnswerOk);
|
||||
}
|
||||
else if (exception is CouldntCloseBoldBlockedException)
|
||||
{
|
||||
|
@ -383,7 +481,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
await ViewService.DisplayAlert(
|
||||
AppResources.ErrorCloseLockTitle,
|
||||
AppResources.ErrorCloseLockBoldBlockedMessage,
|
||||
"OK");
|
||||
AppResources.MessageAnswerOk);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -391,34 +489,47 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
await ViewService.DisplayAlert(
|
||||
AppResources.ErrorCloseLockTitle,
|
||||
exception.Message,
|
||||
"OK");
|
||||
AppResources.MessageAnswerOk);
|
||||
}
|
||||
|
||||
SelectedBike.LockInfo.State = exception is StateAwareException stateAwareException
|
||||
? stateAwareException.State
|
||||
: LockingState.Disconnected;
|
||||
|
||||
// Wait until cancel getting geolocation has completed.
|
||||
BikesViewModel.ActionText = AppResources.ActivityTextQueryLocationCancelWait;
|
||||
try
|
||||
{
|
||||
await Task.WhenAny(new List<Task> { currentLocationTask ?? Task.CompletedTask });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// No location information available.
|
||||
Log.ForContext<BookedOpen>().Information("Canceling query location failed on closing lock error. {Exception}", SelectedBike, ex);
|
||||
}
|
||||
|
||||
BikesViewModel.ActionText = AppResources.ActivityTextStartingUpdater;
|
||||
await ViewUpdateManager().StartUpdateAyncPeridically();
|
||||
|
||||
BikesViewModel.ActionText = string.Empty;
|
||||
BikesViewModel.IsIdle = true;
|
||||
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
|
||||
}
|
||||
|
||||
// Get geoposition.
|
||||
var timeStamp = DateTime.Now;
|
||||
BikesViewModel.ActionText = "Abfrage Standort...";
|
||||
BikesViewModel.ActionText = AppResources.ActivityTextQueryLocation;
|
||||
Location currentLocation = null;
|
||||
try
|
||||
{
|
||||
currentLocation = await Geolocation.GetAsync(timeStamp);
|
||||
await Task.WhenAny(new List<Task> { currentLocationTask });
|
||||
currentLocation = currentLocationTask.Result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// No location information available.
|
||||
Log.ForContext<BookedOpen>().Information("Returning bike {Bike} is not possible. {Exception}", SelectedBike, ex);
|
||||
Log.ForContext<BookedOpen>().Information("Getting geolocation when closing lock of bike {Bike} failed. {Exception}", SelectedBike, ex);
|
||||
|
||||
BikesViewModel.ActionText = "Keine Standortinformationen verfügbar.";
|
||||
BikesViewModel.ActionText = AppResources.ActivityTextErrorQueryLocationWhenAny;
|
||||
}
|
||||
|
||||
// Lock list to avoid multiple taps while copri action is pending.
|
||||
|
|
|
@ -15,6 +15,8 @@ using TINK.Model.User;
|
|||
using Xamarin.Essentials;
|
||||
using TINK.Repository.Request;
|
||||
using TINK.Model.Device;
|
||||
using System.Threading;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
||||
{
|
||||
|
@ -100,7 +102,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
}
|
||||
else if (exception is CouldntOpenBoldWasBlockedException)
|
||||
{
|
||||
Log.ForContext<BookedClosed>().Debug("Lock can not be opened. Bold was or is blocked. {Exception}", exception);
|
||||
Log.ForContext<BookedUnknown>().Debug("Lock can not be opened. Bold was or is blocked. {Exception}", exception);
|
||||
|
||||
await ViewService.DisplayAlert(
|
||||
AppResources.ErrorOpenLockStillOpenTitle,
|
||||
|
@ -206,14 +208,32 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
{
|
||||
// Unlock bike.
|
||||
BikesViewModel.IsIdle = false;
|
||||
|
||||
Log.ForContext<BookedUnknown>().Information("User request to lock bike {bike} in order to pause ride.", SelectedBike);
|
||||
|
||||
// Start getting geolocation.
|
||||
BikesViewModel.ActionText = AppResources.ActivityTextQueryLocationStart;
|
||||
var ctsLocation = new CancellationTokenSource();
|
||||
Task<Location> currentLocationTask = null;
|
||||
var timeStamp = DateTime.Now;
|
||||
try
|
||||
{
|
||||
currentLocationTask = Geolocation.GetAsync(ctsLocation.Token, timeStamp);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// No location information available.
|
||||
Log.ForContext<BookedUnknown>().Information("Returning bike {Bike} is not possible. Start query location failed. {Exception}", SelectedBike, ex);
|
||||
|
||||
BikesViewModel.ActionText = AppResources.ActivityTextErrorQueryLocationQuery;
|
||||
}
|
||||
|
||||
// Stop polling before returning bike.
|
||||
BikesViewModel.ActionText = AppResources.ActivityTextOneMomentPlease;
|
||||
await ViewUpdateManager().StopUpdatePeridically();
|
||||
|
||||
// Close lock
|
||||
BikesViewModel.ActionText = AppResources.ActivityTextClosingLock;
|
||||
|
||||
try
|
||||
{
|
||||
SelectedBike.LockInfo.State = (await LockService[SelectedBike.LockInfo.Id].CloseAsync())?.GetLockingState() ?? LockingState.Disconnected;
|
||||
|
@ -222,6 +242,9 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
{
|
||||
BikesViewModel.ActionText = string.Empty;
|
||||
|
||||
// Signal cts to cancel getting geolocation.
|
||||
ctsLocation.Cancel();
|
||||
|
||||
if (exception is OutOfReachException)
|
||||
{
|
||||
Log.ForContext<BookedUnknown>().Debug("Lock can not be closed. {Exception}", exception);
|
||||
|
@ -261,27 +284,40 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
? stateAwareException.State
|
||||
: LockingState.Disconnected;
|
||||
|
||||
// Wait until cancel getting geolocation has completed.
|
||||
BikesViewModel.ActionText = AppResources.ActivityTextQueryLocationCancelWait;
|
||||
try
|
||||
{
|
||||
await Task.WhenAny(new List<Task> { currentLocationTask ?? Task.CompletedTask });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// No location information available.
|
||||
Log.ForContext<BookedUnknown>().Information("Canceling query location failed on unexpected lock state failed. {Exception}", SelectedBike, ex);
|
||||
}
|
||||
|
||||
BikesViewModel.ActionText = AppResources.ActivityTextStartingUpdater;
|
||||
await ViewUpdateManager().StartUpdateAyncPeridically();
|
||||
|
||||
BikesViewModel.ActionText = string.Empty;
|
||||
BikesViewModel.IsIdle = true;
|
||||
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
|
||||
}
|
||||
|
||||
// Get geoposition.
|
||||
var timeStamp = DateTime.Now;
|
||||
BikesViewModel.ActionText = "Abfrage Standort...";
|
||||
BikesViewModel.ActionText = AppResources.ActivityTextQueryLocation;
|
||||
Location currentLocation = null;
|
||||
try
|
||||
{
|
||||
currentLocation = await Geolocation.GetAsync(timeStamp);
|
||||
await Task.WhenAny(new List<Task> { currentLocationTask ?? Task.CompletedTask });
|
||||
currentLocation = currentLocationTask?.Result ?? null;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// No location information available.
|
||||
Log.ForContext<BookedUnknown>().Information("Returning bike {Bike} is not possible. {Exception}", SelectedBike, ex);
|
||||
Log.ForContext<BookedUnknown>().Information("Get geolocation failed when closing lock of bike {Bike} with unknown state. {Exception}", SelectedBike, ex);
|
||||
|
||||
BikesViewModel.ActionText = "Keine Standortinformationen verfügbar.";
|
||||
BikesViewModel.ActionText = AppResources.ActivityTextErrorQueryLocationWhenAny;
|
||||
}
|
||||
|
||||
// Lock list to avoid multiple taps while copri action is pending.
|
||||
|
|
|
@ -187,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.GetFullDisplayName()),
|
||||
string.Format(AppResources.QuestionOpenLockAndBookBike, SelectedBike.GetFullDisplayName()),
|
||||
AppResources.MessageAnswerYes,
|
||||
AppResources.MessageAnswerNo);
|
||||
|
||||
|
@ -287,7 +287,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
}
|
||||
else if (exception is CouldntOpenBoldWasBlockedException)
|
||||
{
|
||||
Log.ForContext<BookedClosed>().Debug("Lock can not be opened. Bold was or is blocked. {Exception}", exception);
|
||||
Log.ForContext<DisposableDisconnected>().Debug("Lock can not be opened. Bold was or is blocked. {Exception}", exception);
|
||||
|
||||
await ViewService.DisplayAlert(
|
||||
AppResources.ErrorOpenLockStillOpenTitle,
|
||||
|
|
|
@ -94,8 +94,6 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
{
|
||||
// Close lock
|
||||
Log.ForContext<DisposableOpen>().Information("User selected disposable bike {bike} in order to close lock.", SelectedBike);
|
||||
|
||||
// Unlock bike.
|
||||
BikesViewModel.ActionText = AppResources.ActivityTextClosingLock;
|
||||
try
|
||||
{
|
||||
|
@ -115,7 +113,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
}
|
||||
else if (exception is CounldntCloseMovingException)
|
||||
{
|
||||
Log.ForContext<BookedOpen>().Debug("Lock can not be closed. Lock is out of reach. {Exception}", exception);
|
||||
Log.ForContext<DisposableOpen>().Debug("Lock can not be closed. Lock is out of reach. {Exception}", exception);
|
||||
|
||||
await ViewService.DisplayAlert(
|
||||
AppResources.ErrorCloseLockTitle,
|
||||
|
@ -124,7 +122,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
}
|
||||
else if (exception is CouldntCloseBoldBlockedException)
|
||||
{
|
||||
Log.ForContext<BookedOpen>().Debug("Lock can not be closed. Lock is out of reach. {Exception}", exception);
|
||||
Log.ForContext<DisposableOpen>().Debug("Lock can not be closed. Lock is out of reach. {Exception}", exception);
|
||||
|
||||
await ViewService.DisplayAlert(
|
||||
AppResources.ErrorCloseLockTitle,
|
||||
|
@ -160,7 +158,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Log.ForContext<ReservedClosed>().Error("Lock can not be disconnected. {Exception}", exception);
|
||||
Log.ForContext<DisposableOpen>().Error("Lock can not be disconnected. {Exception}", exception);
|
||||
|
||||
BikesViewModel.ActionText = AppResources.ActivityTextErrorDisconnect;
|
||||
}
|
||||
|
@ -249,7 +247,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Log.ForContext<ReservedClosed>().Error("Lock can not be disconnected. {Exception}", exception);
|
||||
Log.ForContext<DisposableOpen>().Error("Lock can not be disconnected. {Exception}", exception);
|
||||
|
||||
BikesViewModel.ActionText = AppResources.ActivityTextErrorDisconnect;
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock
|
|||
try
|
||||
{
|
||||
// Switch to map page
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
#if USEFLYOUT
|
||||
ViewService.ShowPage(ViewTypes.LoginPage);
|
||||
#else
|
||||
await ViewService.ShowPage("//LoginPage");
|
||||
|
|
|
@ -167,7 +167,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
// Ask whether to really book bike?
|
||||
var l_oResult = await ViewService.DisplayAlert(
|
||||
string.Empty,
|
||||
string.Format(AppResources.MessageOpenLockAndBookeBike, SelectedBike.GetFullDisplayName()),
|
||||
string.Format(AppResources.QuestionOpenLockAndBookBike, SelectedBike.GetFullDisplayName()),
|
||||
AppResources.MessageAnswerYes,
|
||||
AppResources.MessageAnswerNo);
|
||||
|
||||
|
@ -244,7 +244,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
}
|
||||
else if (exception is CouldntOpenBoldIsBlockedException)
|
||||
{
|
||||
Log.ForContext<BookedOpen>().Debug("Lock can not be opened. Bold is blocked. {Exception}", exception);
|
||||
Log.ForContext<ReservedClosed>().Debug("Lock can not be opened. Bold is blocked. {Exception}", exception);
|
||||
|
||||
await ViewService.DisplayAlert(
|
||||
AppResources.ErrorOpenLockTitle,
|
||||
|
@ -253,7 +253,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
}
|
||||
else if (exception is CouldntOpenBoldWasBlockedException)
|
||||
{
|
||||
Log.ForContext<BookedClosed>().Debug("Lock can not be opened. Bold was or is blocked. {Exception}", exception);
|
||||
Log.ForContext<ReservedClosed>().Debug("Lock can not be opened. Bold was or is blocked. {Exception}", exception);
|
||||
|
||||
await ViewService.DisplayAlert(
|
||||
AppResources.ErrorOpenLockStillOpenTitle,
|
||||
|
@ -263,7 +263,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
else if (exception is CouldntOpenInconsistentStateExecption inconsistentState
|
||||
&& inconsistentState.State == LockingState.Closed)
|
||||
{
|
||||
Log.ForContext<BookedOpen>().Debug("Lock can not be opened. lock reports state closed. {Exception}", exception);
|
||||
Log.ForContext<ReservedClosed>().Debug("Lock can not be opened. lock reports state closed. {Exception}", exception);
|
||||
|
||||
await ViewService.DisplayAlert(
|
||||
AppResources.ErrorOpenLockTitle,
|
||||
|
@ -337,20 +337,20 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
if (exception is WebConnectFailureException)
|
||||
{
|
||||
// Copri server is not reachable.
|
||||
Log.ForContext<BookedClosed>().Information("User locked bike {bike} in order to pause ride but updating failed (Copri server not reachable).", SelectedBike);
|
||||
Log.ForContext<ReservedClosed>().Information("User locked bike {bike} in order to pause ride but updating failed (Copri server not reachable).", SelectedBike);
|
||||
|
||||
BikesViewModel.ActionText = AppResources.ActivityTextErrorNoWebUpdateingLockstate;
|
||||
}
|
||||
else if (exception is ResponseException copriException)
|
||||
{
|
||||
// Copri server is not reachable.
|
||||
Log.ForContext<BookedClosed>().Information("User locked bike {bike} in order to pause ride but updating failed. {response}.", SelectedBike, copriException.Response);
|
||||
Log.ForContext<ReservedClosed>().Information("User locked bike {bike} in order to pause ride but updating failed. {response}.", SelectedBike, copriException.Response);
|
||||
|
||||
BikesViewModel.ActionText = AppResources.ActivityTextErrorStatusUpdateingLockstate;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.ForContext<BookedClosed>().Error("User locked bike {bike} in order to pause ride but updating failed . {@l_oException}", SelectedBike.Id, exception);
|
||||
Log.ForContext<ReservedClosed>().Error("User locked bike {bike} in order to pause ride but updating failed . {@l_oException}", SelectedBike.Id, exception);
|
||||
BikesViewModel.ActionText = AppResources.ActivityTextErrorConnectionUpdateingLockstate;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -270,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.GetFullDisplayName()),
|
||||
string.Format(AppResources.QuestionOpenLockAndBookBike, SelectedBike.GetFullDisplayName()),
|
||||
AppResources.MessageAnswerYes,
|
||||
AppResources.MessageAnswerNo);
|
||||
|
||||
|
@ -370,7 +370,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
}
|
||||
else if (exception is CouldntOpenBoldWasBlockedException)
|
||||
{
|
||||
Log.ForContext<BookedClosed>().Debug("Lock can not be opened. Bold was or is blocked. {Exception}", exception);
|
||||
Log.ForContext<ReservedDisconnected>().Debug("Lock can not be opened. Bold was or is blocked. {Exception}", exception);
|
||||
|
||||
await ViewService.DisplayAlert(
|
||||
AppResources.ErrorOpenLockStillOpenTitle,
|
||||
|
|
|
@ -171,7 +171,6 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
|
||||
// Close lock and cancel reservation.
|
||||
Log.ForContext<ReservedClosed>().Information("User selected reserved bike {l_oId} in order to cancel reservation.", SelectedBike.Id);
|
||||
|
||||
BikesViewModel.ActionText = AppResources.ActivityTextClosingLock;
|
||||
try
|
||||
{
|
||||
|
@ -182,7 +181,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
BikesViewModel.ActionText = string.Empty;
|
||||
if (exception is OutOfReachException)
|
||||
{
|
||||
Log.ForContext<BookedOpen>().Debug("Lock can not be closed. {Exception}", exception);
|
||||
Log.ForContext<ReservedOpen>().Debug("Lock can not be closed. {Exception}", exception);
|
||||
|
||||
await ViewService.DisplayAlert(
|
||||
AppResources.ErrorCloseLockTitle,
|
||||
|
@ -191,7 +190,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
}
|
||||
else if (exception is CounldntCloseMovingException)
|
||||
{
|
||||
Log.ForContext<BookedOpen>().Debug("Lock can not be closed. Lock bike is moving. {Exception}", exception);
|
||||
Log.ForContext<ReservedOpen>().Debug("Lock can not be closed. Lock bike is moving. {Exception}", exception);
|
||||
|
||||
await ViewService.DisplayAlert(
|
||||
AppResources.ErrorCloseLockTitle,
|
||||
|
@ -200,7 +199,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
}
|
||||
else if (exception is CouldntCloseBoldBlockedException)
|
||||
{
|
||||
Log.ForContext<BookedOpen>().Debug("Lock can not be closed. Lock is out of reach. {Exception}", exception);
|
||||
Log.ForContext<ReservedOpen>().Debug("Lock can not be closed. Lock is out of reach. {Exception}", exception);
|
||||
|
||||
await ViewService.DisplayAlert(
|
||||
AppResources.ErrorCloseLockTitle,
|
||||
|
@ -209,7 +208,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
}
|
||||
else
|
||||
{
|
||||
Log.ForContext<BookedOpen>().Error("Lock can not be closed. {Exception}", exception);
|
||||
Log.ForContext<ReservedOpen>().Error("Lock can not be closed. {Exception}", exception);
|
||||
|
||||
await ViewService.DisplayAlert(
|
||||
AppResources.ErrorCloseLockTitle,
|
||||
|
|
|
@ -15,6 +15,8 @@ using TINK.Model.User;
|
|||
using Xamarin.Essentials;
|
||||
using TINK.Repository.Request;
|
||||
using TINK.Model.Device;
|
||||
using System.Threading;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
||||
{
|
||||
|
@ -54,7 +56,10 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
public override InUseStateEnum State => InUseStateEnum.Reserved;
|
||||
|
||||
/// <summary> Open bike and update COPRI lock state. </summary>
|
||||
public async Task<IRequestHandler> HandleRequestOption1()
|
||||
public async Task<IRequestHandler> HandleRequestOption1() => await OpenLock();
|
||||
|
||||
/// <summary> Open bike and update COPRI lock state. </summary>
|
||||
public async Task<IRequestHandler> OpenLock()
|
||||
{
|
||||
// Unlock bike.
|
||||
Log.ForContext<ReservedUnknown>().Information("User request to unlock bike {bike}.", SelectedBike);
|
||||
|
@ -93,7 +98,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
}
|
||||
else if (exception is CouldntOpenBoldWasBlockedException)
|
||||
{
|
||||
Log.ForContext<BookedClosed>().Debug("Lock can not be opened. Bold was or is blocked. {Exception}", exception);
|
||||
Log.ForContext<ReservedUnknown>().Debug("Lock can not be opened. Bold was or is blocked. {Exception}", exception);
|
||||
|
||||
await ViewService.DisplayAlert(
|
||||
AppResources.ErrorOpenLockStillOpenTitle,
|
||||
|
@ -195,18 +200,40 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
}
|
||||
|
||||
/// <summary> Close lock in order to pause ride and update COPRI lock state.</summary>
|
||||
public async Task<IRequestHandler> HandleRequestOption2()
|
||||
public async Task<IRequestHandler> HandleRequestOption2() => await CloseLock();
|
||||
|
||||
|
||||
/// <summary> Close lock in order to pause ride and update COPRI lock state.</summary>
|
||||
public async Task<IRequestHandler> CloseLock()
|
||||
{
|
||||
// Unlock bike.
|
||||
BikesViewModel.IsIdle = false;
|
||||
|
||||
Log.ForContext<ReservedUnknown>().Information("User request to lock bike {bike} in order to pause ride.", SelectedBike);
|
||||
|
||||
// Start getting geolocation.
|
||||
BikesViewModel.ActionText = AppResources.ActivityTextQueryLocationStart;
|
||||
var ctsLocation = new CancellationTokenSource();
|
||||
Task<Location> currentLocationTask = null;
|
||||
var timeStamp = DateTime.Now;
|
||||
try
|
||||
{
|
||||
currentLocationTask = Geolocation.GetAsync(ctsLocation.Token, timeStamp);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// No location information available.
|
||||
Log.ForContext<ReservedUnknown>().Information("Returning bike {Bike} is not possible. Start query location failed. {Exception}", SelectedBike, ex);
|
||||
|
||||
BikesViewModel.ActionText = AppResources.ActivityTextErrorQueryLocationQuery;
|
||||
}
|
||||
|
||||
// Stop polling before returning bike.
|
||||
BikesViewModel.ActionText = AppResources.ActivityTextOneMomentPlease;
|
||||
await ViewUpdateManager().StopUpdatePeridically();
|
||||
|
||||
// Close lock
|
||||
BikesViewModel.ActionText = AppResources.ActivityTextClosingLock;
|
||||
|
||||
try
|
||||
{
|
||||
SelectedBike.LockInfo.State = (await LockService[SelectedBike.LockInfo.Id].CloseAsync())?.GetLockingState() ?? LockingState.Disconnected;
|
||||
|
@ -215,6 +242,9 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
{
|
||||
BikesViewModel.ActionText = string.Empty;
|
||||
|
||||
// Signal cts to cancel getting geolocation.
|
||||
ctsLocation.Cancel();
|
||||
|
||||
if (exception is OutOfReachException)
|
||||
{
|
||||
Log.ForContext<ReservedUnknown>().Debug("Lock can not be closed. {Exception}", exception);
|
||||
|
@ -254,27 +284,40 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
? stateAwareException.State
|
||||
: LockingState.Disconnected;
|
||||
|
||||
// Wait until cancel getting geolocation has completed.
|
||||
BikesViewModel.ActionText = AppResources.ActivityTextQueryLocationCancelWait;
|
||||
try
|
||||
{
|
||||
await Task.WhenAny(new List<Task> { currentLocationTask ?? Task.CompletedTask });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// No location information available.
|
||||
Log.ForContext<ReservedUnknown>().Information("Canceling query location failed on closing lock error. {Exception}", SelectedBike, ex);
|
||||
}
|
||||
|
||||
BikesViewModel.ActionText = AppResources.ActivityTextStartingUpdater;
|
||||
await ViewUpdateManager().StartUpdateAyncPeridically();
|
||||
|
||||
BikesViewModel.ActionText = string.Empty;
|
||||
BikesViewModel.IsIdle = true;
|
||||
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
|
||||
}
|
||||
|
||||
// Get geoposition.
|
||||
var timeStamp = DateTime.Now;
|
||||
BikesViewModel.ActionText = "Abfrage Standort...";
|
||||
BikesViewModel.ActionText = AppResources.ActivityTextQueryLocation;
|
||||
Location currentLocation = null;
|
||||
try
|
||||
{
|
||||
currentLocation = await Geolocation.GetAsync(timeStamp);
|
||||
await Task.WhenAny(new List<Task> { currentLocationTask ?? Task.CompletedTask });
|
||||
currentLocation = currentLocationTask?.Result ?? null;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// No location information available.
|
||||
Log.ForContext<ReservedUnknown>().Information("Returning bike {Bike} is not possible. {Exception}", SelectedBike, ex);
|
||||
|
||||
BikesViewModel.ActionText = "Keine Standortinformationen verfügbar.";
|
||||
BikesViewModel.ActionText = AppResources.ActivityTextErrorQueryLocationWhenAny;
|
||||
}
|
||||
|
||||
// Lock list to avoid multiple taps while copri action is pending.
|
||||
|
|
|
@ -145,7 +145,7 @@ namespace TINK.ViewModel.BikesAtStation
|
|||
|
||||
/// <summary> Command object to bind login page redirect link to view model.</summary>
|
||||
public System.Windows.Input.ICommand ContactSupportClickedCommand
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
#if USEFLYOUT
|
||||
=> new Xamarin.Forms.Command(() => OpenSupportPageAsync());
|
||||
#else
|
||||
=> new Xamarin.Forms.Command(async () => await OpenLoginPageAsync());
|
||||
|
@ -153,14 +153,14 @@ namespace TINK.ViewModel.BikesAtStation
|
|||
|
||||
/// <summary> Command object to bind login page redirect link to view model.</summary>
|
||||
public System.Windows.Input.ICommand LoginRequiredHintClickedCommand
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
#if USEFLYOUT
|
||||
=> new Xamarin.Forms.Command(() => OpenLoginPageAsync());
|
||||
#else
|
||||
=> new Xamarin.Forms.Command(async () => await OpenLoginPageAsync());
|
||||
#endif
|
||||
|
||||
/// <summary> Opens login page. </summary>
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
#if USEFLYOUT
|
||||
public void OpenLoginPageAsync()
|
||||
#else
|
||||
public async Task OpenLoginPageAsync()
|
||||
|
@ -170,7 +170,7 @@ namespace TINK.ViewModel.BikesAtStation
|
|||
{
|
||||
// Switch to map page
|
||||
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
#if USEFLYOUT
|
||||
ViewService.ShowPage(ViewTypes.LoginPage);
|
||||
#else
|
||||
await ViewService.ShowPage("//LoginPage");
|
||||
|
@ -184,7 +184,7 @@ namespace TINK.ViewModel.BikesAtStation
|
|||
}
|
||||
|
||||
/// <summary> Opens support. </summary>
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
#if USEFLYOUT
|
||||
public void OpenSupportPageAsync()
|
||||
#else
|
||||
public async Task OpenSupportPageAsync()
|
||||
|
@ -194,7 +194,7 @@ namespace TINK.ViewModel.BikesAtStation
|
|||
{
|
||||
// Switch to map page
|
||||
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
#if USEFLYOUT
|
||||
ViewService.ShowPage(ViewTypes.ContactPage, AppResources.MarkingFeedbackAndContact);
|
||||
#else
|
||||
await ViewService.ShowPage("//LoginPage");
|
||||
|
|
|
@ -166,14 +166,14 @@ namespace TINK.ViewModel.Info
|
|||
|
||||
/// <summary> Command object to bind login button to view model. </summary>
|
||||
public ICommand OnSelectStationRequest
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
#if USEFLYOUT
|
||||
=> new Xamarin.Forms.Command(() => OpenSelectStationPage());
|
||||
#else
|
||||
=> new Xamarin.Forms.Command(async () => await OpenSelectStationPageAsync());
|
||||
#endif
|
||||
|
||||
/// <summary> Opens login page. </summary>
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
#if USEFLYOUT
|
||||
public void OpenSelectStationPage()
|
||||
#else
|
||||
public async Task OpenSelectStationPageAsync()
|
||||
|
@ -183,7 +183,7 @@ namespace TINK.ViewModel.Info
|
|||
{
|
||||
// Switch to map page
|
||||
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
#if USEFLYOUT
|
||||
ViewService.PushAsync(ViewTypes.SelectStationPage);
|
||||
#else
|
||||
await ViewService.ShowPage("//SelectStationPage");
|
||||
|
|
|
@ -12,7 +12,7 @@ using System.Threading.Tasks;
|
|||
using System.ComponentModel;
|
||||
using Xamarin.Forms.GoogleMaps;
|
||||
using System.Collections.ObjectModel;
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
#if USEFLYOUT
|
||||
using TINK.View.MasterDetail;
|
||||
#endif
|
||||
using TINK.Settings;
|
||||
|
@ -66,7 +66,7 @@ namespace TINK.ViewModel.Contact
|
|||
/// <summary>Delegate to perform navigation.</summary>
|
||||
private INavigation m_oNavigation;
|
||||
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
#if USEFLYOUT
|
||||
/// <summary>Delegate to perform navigation.</summary>
|
||||
private INavigationMasterDetail m_oNavigationMasterDetail;
|
||||
#endif
|
||||
|
@ -142,14 +142,14 @@ namespace TINK.ViewModel.Contact
|
|||
m_oNavigation = navigation
|
||||
?? throw new ArgumentException("Can not instantiate map page view model- object. No navigation service available.");
|
||||
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
#if USEFLYOUT
|
||||
m_oNavigationMasterDetail = new EmptyNavigationMasterDetail();
|
||||
#endif
|
||||
|
||||
IsConnected = TinkApp.GetIsConnected();
|
||||
}
|
||||
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
#if USEFLYOUT
|
||||
/// <summary> Delegate to perform navigation.</summary>
|
||||
public INavigationMasterDetail NavigationMasterDetail
|
||||
{
|
||||
|
@ -285,7 +285,7 @@ namespace TINK.ViewModel.Contact
|
|||
|
||||
if (Pins.Count <= 0)
|
||||
{
|
||||
ActionText = AppResources.ActivityTextMyBikesLoadingBikes;
|
||||
ActionText = AppResources.ActivityTextRequestingLocationPermissions;
|
||||
|
||||
// Check location permission
|
||||
var status = await PermissionsService.CheckPermissionStatusAsync<LocationPermission>();
|
||||
|
|
|
@ -99,7 +99,7 @@ namespace TINK.ViewModel.FindBike
|
|||
{
|
||||
Log.ForContext<FindBikePageViewModel>().Information("User request to show page FindBike- page re-appearing");
|
||||
|
||||
ActionText = AppResources.ActivityTextMyBikesLoadingBikes;
|
||||
ActionText = AppResources.ActivityTextFindBikeLoadingBikes;
|
||||
|
||||
var bikes = await ConnectorFactory(IsConnected).Query.GetBikesAsync();
|
||||
|
||||
|
|
|
@ -142,7 +142,7 @@ namespace TINK.ViewModel.Info.BikeInfo
|
|||
public IList<CourouselPageItemViewModel> CarouselItems { get; }
|
||||
|
||||
/// <summary> Command object to bind close button to view model. </summary>
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
#if USEFLYOUT
|
||||
private Action CloseAction
|
||||
=> () => m_oViewService.ShowPage(ViewTypes.MapPage);
|
||||
#else
|
||||
|
|
|
@ -317,7 +317,7 @@ 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
|
||||
#if USEFLYOUT
|
||||
m_oViewService.ShowPage(ViewTypes.MapPage);
|
||||
#else
|
||||
await m_oViewService.ShowPage("//MapPage");
|
||||
|
@ -326,7 +326,7 @@ namespace TINK.ViewModel
|
|||
}
|
||||
|
||||
// Swich to map page
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
#if USEFLYOUT
|
||||
m_oViewService.ShowPage(ViewTypes.BikeInfoCarouselPage, AppResources.MarkingLoginInstructions);
|
||||
#else
|
||||
await m_oViewService.ShowPage("//MapPage");
|
||||
|
|
|
@ -12,7 +12,7 @@ using System.Threading.Tasks;
|
|||
using System.ComponentModel;
|
||||
using Xamarin.Forms.GoogleMaps;
|
||||
using System.Collections.ObjectModel;
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
#if USEFLYOUT
|
||||
using TINK.View.MasterDetail;
|
||||
#endif
|
||||
using TINK.Settings;
|
||||
|
@ -74,7 +74,7 @@ namespace TINK.ViewModel.Map
|
|||
/// <summary>Delegate to perform navigation.</summary>
|
||||
private INavigation m_oNavigation;
|
||||
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
#if USEFLYOUT
|
||||
/// <summary>Delegate to perform navigation.</summary>
|
||||
private INavigationMasterDetail m_oNavigationMasterDetail;
|
||||
#endif
|
||||
|
@ -151,7 +151,7 @@ namespace TINK.ViewModel.Map
|
|||
|
||||
m_oViewUpdateManager = new IdlePollingUpdateTaskManager();
|
||||
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
#if USEFLYOUT
|
||||
m_oNavigationMasterDetail = new EmptyNavigationMasterDetail();
|
||||
#endif
|
||||
|
||||
|
@ -176,7 +176,7 @@ namespace TINK.ViewModel.Map
|
|||
}
|
||||
}
|
||||
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
#if USEFLYOUT
|
||||
/// <summary> Delegate to perform navigation.</summary>
|
||||
public INavigationMasterDetail NavigationMasterDetail
|
||||
{
|
||||
|
@ -315,7 +315,7 @@ namespace TINK.ViewModel.Map
|
|||
// Update map page filter
|
||||
ActiveFilterMap = TinkApp.GroupFilterMapPage;
|
||||
|
||||
ActionText = AppResources.ActivityTextMyBikesLoadingBikes;
|
||||
ActionText = AppResources.ActivityTextRequestingLocationPermissions;
|
||||
|
||||
// Check location permission
|
||||
var status = await PermissionsService.CheckPermissionStatusAsync<LocationPermission>();
|
||||
|
@ -325,13 +325,13 @@ namespace TINK.ViewModel.Map
|
|||
{
|
||||
var permissionResult = await PermissionsService.RequestPermissionAsync<LocationPermission>();
|
||||
|
||||
if (permissionResult != Plugin.Permissions.Abstractions.PermissionStatus.Granted)
|
||||
{
|
||||
var dialogResult = await ViewService.DisplayAlert(
|
||||
AppResources.MessageTitleHint,
|
||||
AppResources.MessageCenterMapLocationPermissionOpenDialog,
|
||||
AppResources.MessageAnswerYes,
|
||||
AppResources.MessageAnswerNo);
|
||||
if (permissionResult != Plugin.Permissions.Abstractions.PermissionStatus.Granted)
|
||||
{
|
||||
var dialogResult = await ViewService.DisplayAlert(
|
||||
AppResources.MessageTitleHint,
|
||||
AppResources.MessageCenterMapLocationPermissionOpenDialog,
|
||||
AppResources.MessageAnswerYes,
|
||||
AppResources.MessageAnswerNo);
|
||||
|
||||
if (dialogResult)
|
||||
{
|
||||
|
|
|
@ -13,6 +13,7 @@ using TINK.Model.Bikes.Bike.BC;
|
|||
using TINK.Repository;
|
||||
using System.Net;
|
||||
using TINK.MultilingualResources;
|
||||
using System.Linq;
|
||||
|
||||
namespace TINK.ViewModel
|
||||
{
|
||||
|
@ -59,9 +60,9 @@ namespace TINK.ViewModel
|
|||
/// </summary>
|
||||
/// <param name="p_oStation">Station to get id from</param>
|
||||
/// <returns></returns>
|
||||
public static int GetStationId(string p_strStationName)
|
||||
public static int GetStationId(string stationName)
|
||||
{
|
||||
return int.Parse(p_strStationName.Replace(USER_FIENDLY_STATIONNUMBER_PREFIX, "").Trim());
|
||||
return int.Parse(stationName.Replace(USER_FIENDLY_STATIONNUMBER_PREFIX, "").Trim());
|
||||
}
|
||||
|
||||
/// <summary> Get full display name of a bike which includes id. </summary>
|
||||
|
@ -91,11 +92,11 @@ namespace TINK.ViewModel
|
|||
/// <summary>
|
||||
/// Maps state to color.
|
||||
/// </summary>
|
||||
/// <param name="p_eState"></param>
|
||||
/// <param name="state"></param>
|
||||
/// <returns></returns>
|
||||
public static Color GetColor(this InUseStateEnum p_eState)
|
||||
public static Color GetColor(this InUseStateEnum state)
|
||||
{
|
||||
switch (p_eState)
|
||||
switch (state)
|
||||
{
|
||||
case InUseStateEnum.Disposable:
|
||||
return Color.Default;
|
||||
|
@ -158,33 +159,48 @@ namespace TINK.ViewModel
|
|||
|
||||
}
|
||||
|
||||
/// <summary> Gets message that logged in user has not booked any bikes. </summary>
|
||||
public static FormattedString GetErrorInfoText(this Exception p_oException)
|
||||
/// <summary> Gets error message and handles aggegate exceptions. </summary>
|
||||
public static string GetErrorMessage(this Exception exception)
|
||||
{
|
||||
if (p_oException == null)
|
||||
if (exception == null)
|
||||
return string.Empty;
|
||||
|
||||
if (!(exception is AggregateException aggregateException))
|
||||
return exception.Message;
|
||||
|
||||
if (aggregateException.InnerExceptions.Count == 1)
|
||||
return aggregateException.InnerExceptions[0].Message;
|
||||
|
||||
return new AggregateException().Message + "\r\n"+ string.Join("\r\n", aggregateException.InnerExceptions.Select(x => x.Message));
|
||||
}
|
||||
|
||||
/// <summary> Gets message that logged in user has not booked any bikes. </summary>
|
||||
public static FormattedString GetErrorInfoText(this Exception exception)
|
||||
{
|
||||
if (exception == null)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
FormattedString l_oError;
|
||||
// An error occurred getting bikes information.
|
||||
if (p_oException is WebConnectFailureException)
|
||||
if (exception is WebConnectFailureException)
|
||||
{
|
||||
|
||||
l_oError = new FormattedString();
|
||||
l_oError.Spans.Add(new Span { Text = "Information!\r\n", FontAttributes = FontAttributes.Bold });
|
||||
l_oError.Spans.Add(new Span { Text = $"{p_oException.Message}\r\n{WebConnectFailureException.GetHintToPossibleExceptionsReasons}" });
|
||||
l_oError.Spans.Add(new Span { Text = $"{exception.Message}\r\n{WebConnectFailureException.GetHintToPossibleExceptionsReasons}" });
|
||||
return l_oError;
|
||||
|
||||
}
|
||||
else if (p_oException is InvalidResponseException)
|
||||
else if (exception is InvalidResponseException)
|
||||
{
|
||||
l_oError = new FormattedString();
|
||||
l_oError.Spans.Add(new Span { Text = "Fehler, ungültige Serverantwort!\r\n", FontAttributes = FontAttributes.Bold });
|
||||
l_oError.Spans.Add(new Span { Text = $"{p_oException.Message}" });
|
||||
l_oError.Spans.Add(new Span { Text = $"{exception.Message}" });
|
||||
return l_oError;
|
||||
}
|
||||
else if (p_oException is WebForbiddenException)
|
||||
else if (exception is WebForbiddenException)
|
||||
{
|
||||
l_oError = new FormattedString();
|
||||
l_oError.Spans.Add(new Span { Text = "Beschäftigt... Einen Moment bitte!" });
|
||||
|
@ -193,37 +209,37 @@ namespace TINK.ViewModel
|
|||
|
||||
l_oError = new FormattedString();
|
||||
l_oError.Spans.Add(new Span { Text = "Allgemeiner Fehler!\r\n", FontAttributes = FontAttributes.Bold });
|
||||
l_oError.Spans.Add(new Span { Text = $"{p_oException}" });
|
||||
l_oError.Spans.Add(new Span { Text = $"{exception}" });
|
||||
return l_oError;
|
||||
}
|
||||
|
||||
|
||||
/// <summary> User tabbed a URI. </summary>
|
||||
/// <param name="p_oSender">Sender of the event.</param>
|
||||
/// <param name="p_eEventArgs">Event arguments</param>
|
||||
public static void OnNavigating(object p_oSender, WebNavigatingEventArgs p_eEventArgs)
|
||||
/// <param name="sender">Sender of the event.</param>
|
||||
/// <param name="eventArgs">Event arguments</param>
|
||||
public static void OnNavigating(object sender, WebNavigatingEventArgs eventArgs)
|
||||
{
|
||||
|
||||
if (!p_eEventArgs.Url.ToUpper().StartsWith("HTTP"))
|
||||
if (!eventArgs.Url.ToUpper().StartsWith("HTTP"))
|
||||
{
|
||||
// An internal link was detected.
|
||||
// Stay inside WebView
|
||||
p_eEventArgs.Cancel = false;
|
||||
eventArgs.Cancel = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Do not navigate outside the document.
|
||||
p_eEventArgs.Cancel = true;
|
||||
eventArgs.Cancel = true;
|
||||
|
||||
DependencyService.Get<IExternalBrowserService>().OpenUrl(p_eEventArgs.Url);
|
||||
DependencyService.Get<IExternalBrowserService>().OpenUrl(eventArgs.Url);
|
||||
}
|
||||
|
||||
/// <summary> Gets the user group if a user friendly name.</summary>
|
||||
/// <param name="p_oUser"></param>
|
||||
/// <param name="user"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetUserGroupDisplayName(this User p_oUser)
|
||||
public static string GetUserGroupDisplayName(this User user)
|
||||
{
|
||||
return string.Join(" & ", p_oUser.Group);
|
||||
return string.Join(" & ", user.Group);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue