mirror of
https://dev.azure.com/TeilRad/sharee.bike%20App/_git/Code
synced 2024-11-12 13:36:26 +01:00
303 lines
12 KiB
C#
303 lines
12 KiB
C#
using MonkeyCache.FileStore;
|
|
using Serilog;
|
|
using System;
|
|
using System.Threading.Tasks;
|
|
using TINK.Repository.Exception;
|
|
using TINK.Model.Device;
|
|
using TINK.Model.State;
|
|
using TINK.Model.Station;
|
|
using TINK.Model.User;
|
|
using Xamarin.Forms;
|
|
|
|
using TINK.Model.Bikes.Bike.BC;
|
|
using TINK.Repository;
|
|
using System.Net;
|
|
using TINK.MultilingualResources;
|
|
using System.Linq;
|
|
|
|
namespace TINK.ViewModel
|
|
{
|
|
public static class ViewModelHelper
|
|
{
|
|
/// <summary> First part of text making up a station name.</summary>
|
|
private const string USER_FIENDLY_STATIONNUMBER_PREFIX = "Station";
|
|
|
|
/// <summary>Holds the color which marks link to TINK- app pages, web sites, ...</summary>
|
|
public static Color LINK_COLOR = Color.Blue;
|
|
|
|
/// <summary>
|
|
/// Gets station name from station object.
|
|
/// </summary>
|
|
/// <param name="station">Station to get id from</param>
|
|
/// <returns></returns>
|
|
public static string GetStationName(this IStation station)
|
|
{
|
|
if (station == null)
|
|
{
|
|
return string.Empty;
|
|
}
|
|
|
|
if (!string.IsNullOrEmpty(station.StationName))
|
|
{
|
|
return $"{station.StationName}, Nr. {station.Id}.";
|
|
}
|
|
|
|
return GetStationName(station.Id);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets station name from station object.
|
|
/// </summary>
|
|
/// <param name="p_oStation">Station to get id from</param>
|
|
/// <returns></returns>
|
|
public static string GetStationName(string station)
|
|
{
|
|
return string.Format("{0} {1}", USER_FIENDLY_STATIONNUMBER_PREFIX, station);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets station id from station name.
|
|
/// </summary>
|
|
/// <param name="p_oStation">Station to get id from</param>
|
|
/// <returns></returns>
|
|
public static int GetStationId(string stationName)
|
|
{
|
|
return int.Parse(stationName.Replace(USER_FIENDLY_STATIONNUMBER_PREFIX, "").Trim());
|
|
}
|
|
|
|
/// <summary> Get full display name of a bike which includes id. </summary>
|
|
/// <remarks>
|
|
/// If name is empty return Id as name.
|
|
/// </remarks>
|
|
/// <param name="bike">bike to get name for.</param>
|
|
/// <returns>Display name of bike.</returns>
|
|
public static string GetFullDisplayName(this IBikeInfoMutable bike)
|
|
=> $"{(!string.IsNullOrEmpty(bike.Description) ? $"{bike.Description}, " : string.Empty)}Nr. {bike.Id}";
|
|
|
|
/// <summary> Get the display name of a bike. </summary>
|
|
/// <param name="bike">bike to get name for.</param>
|
|
/// <returns>Display name of bike.</returns>
|
|
public static string GetDisplayName(this IBikeInfoMutable bike)
|
|
=> $"{(!string.IsNullOrEmpty(bike.Description) ? $"{bike.Description}" : $"{bike.Id}")}";
|
|
|
|
/// <summary> Get the display id of a bike.</summary>
|
|
/// <remarks>
|
|
/// If name is empty id is used as name. For this reason return nothing in this case to avoid duplicate output of id.
|
|
/// </remarks>
|
|
/// <param name="bike">bike to get name for.</param>
|
|
/// <returns>Display name of bike.</returns>
|
|
public static string GetDisplayId(this IBikeInfoMutable bike)
|
|
=> $"{(!string.IsNullOrEmpty(bike.Description) ? $"{bike.Id}" : string.Empty)}";
|
|
|
|
/// <summary>
|
|
/// Maps state to color.
|
|
/// </summary>
|
|
/// <param name="state"></param>
|
|
/// <returns></returns>
|
|
public static Color GetColor(this InUseStateEnum state)
|
|
{
|
|
switch (state)
|
|
{
|
|
case InUseStateEnum.Disposable:
|
|
return Color.Default;
|
|
|
|
case InUseStateEnum.Reserved:
|
|
return Color.Orange;
|
|
|
|
case InUseStateEnum.Booked:
|
|
return Color.Green;
|
|
default:
|
|
return Color.Default;
|
|
}
|
|
}
|
|
|
|
/// <summary> Gets message that logged in user has not booked any bikes. </summary>
|
|
/// <param name="isReportLevelVerbose">Holds whether report level is verbose or not.</param>
|
|
public static string GetShortErrorInfoText(this Exception exception, bool isReportLevelVerbose)
|
|
{
|
|
if (exception == null)
|
|
{
|
|
return string.Empty;
|
|
}
|
|
|
|
if (exception is AuthcookieNotDefinedException)
|
|
return AppResources.ActivityTextAuthcookieNotDefinedException;
|
|
|
|
if (!isReportLevelVerbose)
|
|
{
|
|
return AppResources.ActivityTextException;
|
|
}
|
|
|
|
// An error occurred getting bikes information.
|
|
#if USCSHARP9
|
|
switch (exception)
|
|
{
|
|
case WebConnectFailureException:
|
|
return AppResources.ActivityTextErrorWebConnectFailureException;
|
|
case InvalidResponseException:
|
|
return AppResources.ActivityTextErrorInvalidResponseException;
|
|
case WebForbiddenException:
|
|
return AppResources.ActivityTextErrorWebForbiddenException;
|
|
case DeserializationException:
|
|
return AppResources.ActivityTextErrorDeserializationException;
|
|
case WebException webException:
|
|
return webException.Status == WebExceptionStatus.ProtocolError && webException.Response is HttpWebResponse webResponse
|
|
? string.Format(AppResources.ActivityTextErrorWebExceptionProtocolError, webResponse.StatusDescription)
|
|
: string.Format(AppResources.ActivityTextErrorWebExceptionGeneralError, webException.Status.ToString());
|
|
default:
|
|
return AppResources.ActivityTextErrorException;
|
|
}
|
|
#else
|
|
if (exception is WebConnectFailureException)
|
|
return AppResources.ActivityTextErrorWebConnectFailureException;
|
|
if (exception is InvalidResponseException)
|
|
return AppResources.ActivityTextErrorInvalidResponseException;
|
|
if (exception is WebForbiddenException)
|
|
return AppResources.ActivityTextErrorWebForbiddenException;
|
|
if (exception is DeserializationException)
|
|
return AppResources.ActivityTextErrorDeserializationException;
|
|
if (exception is WebException webException)
|
|
{
|
|
return webException.Status == WebExceptionStatus.ProtocolError && webException.Response is HttpWebResponse webResponse
|
|
? string.Format(AppResources.ActivityTextErrorWebExceptionProtocolError, webResponse.StatusDescription)
|
|
: string.Format(AppResources.ActivityTextErrorWebExceptionGeneralError, webException.Status.ToString());
|
|
}
|
|
|
|
return AppResources.ActivityTextErrorException;
|
|
#endif
|
|
|
|
}
|
|
|
|
/// <summary> Gets error message and handles aggegate exceptions. </summary>
|
|
public static string GetErrorMessage(this Exception exception)
|
|
{
|
|
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 (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 = $"{exception.Message}\r\n{WebConnectFailureException.GetHintToPossibleExceptionsReasons}" });
|
|
return l_oError;
|
|
|
|
}
|
|
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 = $"{exception.Message}" });
|
|
return l_oError;
|
|
}
|
|
else if (exception is WebForbiddenException)
|
|
{
|
|
l_oError = new FormattedString();
|
|
l_oError.Spans.Add(new Span { Text = "Beschäftigt... Einen Moment bitte!" });
|
|
return l_oError;
|
|
}
|
|
|
|
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 = $"{exception}" });
|
|
return l_oError;
|
|
}
|
|
|
|
|
|
/// <summary> User tabbed a URI. </summary>
|
|
/// <param name="sender">Sender of the event.</param>
|
|
/// <param name="eventArgs">Event arguments</param>
|
|
public static void OnNavigating(object sender, WebNavigatingEventArgs eventArgs)
|
|
{
|
|
|
|
if (!eventArgs.Url.ToUpper().StartsWith("HTTP"))
|
|
{
|
|
// An internal link was detected.
|
|
// Stay inside WebView
|
|
eventArgs.Cancel = false;
|
|
return;
|
|
}
|
|
|
|
// Do not navigate outside the document.
|
|
eventArgs.Cancel = true;
|
|
|
|
DependencyService.Get<IExternalBrowserService>().OpenUrl(eventArgs.Url);
|
|
}
|
|
|
|
/// <summary> Gets the user group if a user friendly name.</summary>
|
|
/// <param name="user"></param>
|
|
/// <returns></returns>
|
|
public static string GetUserGroupDisplayName(this User user)
|
|
{
|
|
return string.Join(" & ", user.Group);
|
|
}
|
|
|
|
|
|
/// <summary> Called when page is shown. </summary>
|
|
/// <param name="resourceUrl">Url to load data from.</param>
|
|
/// <param name="isSiteCachingOn">Holds value wether site caching is on or off.</param>
|
|
/// <param name="resourceProvider"> Provides resource from embedded ressources.</param>
|
|
public static async Task<string> GetSource(
|
|
string resourceUrl,
|
|
bool isSiteCachingOn,
|
|
Func<string> resourceProvider = null)
|
|
{
|
|
if (!Barrel.Current.IsExpired(resourceUrl) && isSiteCachingOn)
|
|
{
|
|
// Cached html is still valid and caching is on.
|
|
return Barrel.Current.Get<string>(resourceUrl);
|
|
}
|
|
|
|
string htmlContent = string.Empty;
|
|
|
|
try
|
|
{
|
|
// Get info from web server.
|
|
htmlContent = await CopriCallsHttps.Get(resourceUrl);
|
|
}
|
|
catch (Exception l_oException)
|
|
{
|
|
// Getting html failed.
|
|
Log.Error($"Requesting {resourceUrl} failed. {l_oException.Message}");
|
|
}
|
|
|
|
switch (string.IsNullOrEmpty(htmlContent))
|
|
{
|
|
case true:
|
|
// An error occurred getting resource from web
|
|
htmlContent = Barrel.Current.Exists(resourceUrl)
|
|
? Barrel.Current.Get<string>(key: resourceUrl) // Get from MonkeyCache
|
|
: resourceProvider != null ? resourceProvider() : $"<DOCTYPE html>Error loading {resourceUrl}."; // Get build in ressource.
|
|
break;
|
|
|
|
default:
|
|
// Add resource to cache.
|
|
Barrel.Current.Add(key: resourceUrl, data: htmlContent, expireIn: isSiteCachingOn ? TimeSpan.FromDays(1) : TimeSpan.FromMilliseconds(1) );
|
|
break;
|
|
}
|
|
|
|
return htmlContent ?? FromBody("An error occurred loading html- ressource.");
|
|
}
|
|
|
|
public static string FromBody(string message) => $"<!DOCTYPE html><html lang=\"de\"><head><title>Error Information</title></head><body>{message}</body></html>";
|
|
}
|
|
}
|