mirror of
https://dev.azure.com/TeilRad/sharee.bike%20App/_git/Code
synced 2025-06-21 21:46:27 +02:00
3.0.275
This commit is contained in:
parent
f38b516d25
commit
578fcee611
70 changed files with 6828 additions and 9625 deletions
|
@ -90,7 +90,8 @@ namespace TINK.Model.Connector
|
|||
response.merchant_message,
|
||||
response.TryGetCopriVersion(out Version copriVersion)
|
||||
? new Version(0,0)
|
||||
: copriVersion);
|
||||
: copriVersion,
|
||||
new ResourceUrls(response.tariff_info_html, response.bike_info_html, response.agb_html, response.privacy_html, response.impress_html));
|
||||
|
||||
/// <summary> Gets account object from login response.</summary>
|
||||
/// <param name="merchantId">Needed to extract cookie from autorization response.</param>
|
||||
|
|
|
@ -100,6 +100,22 @@ namespace TINK.Model
|
|||
string ExternalFolder { get; }
|
||||
|
||||
/// <summary> Holds the stations availalbe. </summary>
|
||||
IEnumerable<IStation> Stations {get; set;}
|
||||
IEnumerable<IStation> Stations { get; set; }
|
||||
|
||||
|
||||
IResourceUrls ResourceUrls { get; set; }
|
||||
}
|
||||
|
||||
public interface IResourceUrls
|
||||
{
|
||||
string FeesResourcePath { get; }
|
||||
|
||||
string BikesResourcePath { get; }
|
||||
|
||||
string AgbResourcePath { get; }
|
||||
|
||||
string PrivacyResourcePath { get; }
|
||||
|
||||
string ImpressResourcePath { get; }
|
||||
}
|
||||
}
|
||||
|
|
29
TINKLib/Model/ResourceUrls.cs
Normal file
29
TINKLib/Model/ResourceUrls.cs
Normal file
|
@ -0,0 +1,29 @@
|
|||
namespace TINK.Model
|
||||
{
|
||||
public class ResourceUrls : IResourceUrls
|
||||
{
|
||||
public ResourceUrls(
|
||||
string feesResourcePath = null,
|
||||
string bikesResourcePath = null,
|
||||
string agbResourcePath = null,
|
||||
string privacyResourcePath = null,
|
||||
string impressResourcePath = null)
|
||||
{
|
||||
FeesResourcePath = !string.IsNullOrEmpty(feesResourcePath) ? feesResourcePath : "site/tariff_info_1.html";
|
||||
BikesResourcePath = !string.IsNullOrEmpty(bikesResourcePath) ? bikesResourcePath : "site/bike_info.html";
|
||||
AgbResourcePath = !string.IsNullOrEmpty(agbResourcePath) ? agbResourcePath : "site/agb.html";
|
||||
PrivacyResourcePath = !string.IsNullOrEmpty(privacyResourcePath) ? privacyResourcePath : "site/privacy.html";
|
||||
ImpressResourcePath = !string.IsNullOrEmpty(impressResourcePath) ? impressResourcePath : "site/impress.html";
|
||||
}
|
||||
|
||||
public string FeesResourcePath { get; }
|
||||
|
||||
public string BikesResourcePath { get; }
|
||||
|
||||
public string AgbResourcePath { get; }
|
||||
|
||||
public string PrivacyResourcePath { get; }
|
||||
|
||||
public string ImpressResourcePath { get; }
|
||||
}
|
||||
}
|
|
@ -344,6 +344,8 @@ namespace TINK.Model
|
|||
/// <summary> Holds the stations availalbe. </summary>
|
||||
public IEnumerable<IStation> Stations { get; set; } = new List<Station.Station>();
|
||||
|
||||
public IResourceUrls ResourceUrls { get; set; } = new ResourceUrls();
|
||||
|
||||
/// <summary> Action to post to GUI thread.</summary>
|
||||
public Action<SendOrPostCallback, object> PostAction { get; }
|
||||
|
||||
|
|
|
@ -476,7 +476,7 @@ namespace TINK.Model
|
|||
AppResources.ChangeLog3_0_266
|
||||
},
|
||||
{
|
||||
new Version(3, 0, 271),
|
||||
new Version(3, 0, 274),
|
||||
AppResources.ChangeLog3_0_231 // Minor improvements.
|
||||
}
|
||||
};
|
||||
|
|
|
@ -733,18 +733,18 @@ namespace TINK.Repository
|
|||
}
|
||||
|
||||
/// <summary> http- post request.</summary>
|
||||
/// <param name="p_strCommand">Command to send.</param>
|
||||
/// <param name="p_oDisplayCommand">Command to display/ log used for error handling.</param>
|
||||
/// <param name="command">Command to send.</param>
|
||||
/// <param name="displayCommand">Command to display/ log used for error handling.</param>
|
||||
/// <param name="uRL">Address of server to communicate with.</param>
|
||||
/// <returns>Response as text.</returns>
|
||||
/// <changelog> An unused member PostAsyncHttpClient using HttpClient for posting was removed 2020-04-02.</changelog>
|
||||
private static async Task<string> PostAsync(
|
||||
string uRL,
|
||||
string p_strCommand,
|
||||
string command,
|
||||
string userAgent = null,
|
||||
Func<string> p_oDisplayCommand = null)
|
||||
Func<string> displayCommand = null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(p_strCommand))
|
||||
if (string.IsNullOrEmpty(command))
|
||||
{
|
||||
Log.ForContext<CopriCallsHttps>().Fatal("Can not post command. Command must not be null or empty.");
|
||||
|
||||
|
@ -759,7 +759,7 @@ namespace TINK.Repository
|
|||
}
|
||||
|
||||
// Get display version of command to used for display/ logging (password should never be included in output)
|
||||
Func<string> displayCommandFunc = p_oDisplayCommand ?? delegate () { return p_strCommand; };
|
||||
Func<string> displayCommandFunc = displayCommand ?? delegate () { return command; };
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -769,7 +769,6 @@ namespace TINK.Repository
|
|||
// Returns a http request.
|
||||
var request = WebRequest.CreateHttp(l_strHost);
|
||||
|
||||
request.Timeout = 5000; // Default value for HttpWebRequest is 100 secs. According to doc this has no impact on async call but when debugging it has.
|
||||
request.Method = "POST";
|
||||
request.ContentType = "application/x-www-form-urlencoded";
|
||||
request.UserAgent = userAgent;
|
||||
|
@ -778,38 +777,38 @@ namespace TINK.Repository
|
|||
// If not KeepAlive is set to true Stream.Write leads arbitrarily to an object disposed exception.
|
||||
request.KeepAlive = true;
|
||||
|
||||
byte[] l_oPostData = Encoding.UTF8.GetBytes(p_strCommand);
|
||||
byte[] postData = Encoding.UTF8.GetBytes(command);
|
||||
|
||||
request.ContentLength = l_oPostData.Length;
|
||||
request.ContentLength = postData.Length;
|
||||
|
||||
// Get the request stream.
|
||||
using (Stream l_oDataStream = await request.GetRequestStreamAsync())
|
||||
using (Stream dataStream = await request.GetRequestStreamAsync())
|
||||
{
|
||||
// Write the data to the request stream.
|
||||
await l_oDataStream.WriteAsync(l_oPostData, 0, l_oPostData.Length);
|
||||
await dataStream.WriteAsync(postData, 0, postData.Length);
|
||||
}
|
||||
|
||||
// Get the response.
|
||||
var l_oResponse = await request.GetResponseAsync() as HttpWebResponse;
|
||||
var webResponse = await request.GetResponseAsync() as HttpWebResponse;
|
||||
|
||||
if (l_oResponse == null)
|
||||
if (webResponse == null)
|
||||
{
|
||||
throw new System.Exception(string.Format("Reserve request failed. Response form from server was not of expected type."));
|
||||
}
|
||||
|
||||
if (l_oResponse.StatusCode != HttpStatusCode.OK)
|
||||
if (webResponse.StatusCode != HttpStatusCode.OK)
|
||||
{
|
||||
throw new CommunicationException(string.Format(
|
||||
"Posting request {0} failed. Expected status code is {1} but was {2}.",
|
||||
displayCommandFunc(),
|
||||
HttpStatusCode.OK,
|
||||
l_oResponse.StatusCode));
|
||||
webResponse.StatusCode));
|
||||
}
|
||||
|
||||
string response = string.Empty;
|
||||
|
||||
// Get the request stream.
|
||||
using (Stream l_oDataStream = l_oResponse.GetResponseStream())
|
||||
using (Stream l_oDataStream = webResponse.GetResponseStream())
|
||||
using (StreamReader l_oReader = new StreamReader(l_oDataStream))
|
||||
{
|
||||
// Read the content.
|
||||
|
@ -819,7 +818,7 @@ namespace TINK.Repository
|
|||
Console.WriteLine(response);
|
||||
|
||||
// Clean up the streams.
|
||||
l_oResponse.Close();
|
||||
webResponse.Close();
|
||||
}
|
||||
|
||||
Log.ForContext<CopriCallsHttps>().Verbose("Post command {DisplayCommand} to host {URL} received {ResponseText:j}.", displayCommandFunc(), uRL, response);
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
|
||||
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace TINK.Repository.Response
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
@ -25,6 +25,26 @@ namespace TINK.Repository.Response
|
|||
[DataMember]
|
||||
public MapSpan init_map { get; private set; }
|
||||
|
||||
/// <summary> Url of page holding agb info. </summary>
|
||||
[DataMember]
|
||||
public string agb_html { get; private set; }
|
||||
|
||||
/// <summary> Url of page holding instructions how to rent bikes. </summary>
|
||||
[DataMember]
|
||||
public string bike_info_html { get; private set; }
|
||||
|
||||
/// <summary> Url of page holding privacy info. </summary>
|
||||
[DataMember]
|
||||
public string privacy_html { get; private set; }
|
||||
|
||||
/// <summary> Url of page holding impress info. </summary>
|
||||
[DataMember]
|
||||
public string impress_html { get; private set; }
|
||||
|
||||
/// <summary> Url of page holding tariff info. </summary>
|
||||
[DataMember]
|
||||
public string tariff_info_html { get; private set; }
|
||||
|
||||
/// <summary> Textual description of response. </summary>
|
||||
public new string ToString()
|
||||
{
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using TINK.Model;
|
||||
using TINK.Model.Map;
|
||||
|
||||
namespace TINK.Services.CopriApi
|
||||
|
@ -7,16 +8,18 @@ namespace TINK.Services.CopriApi
|
|||
public class GeneralData
|
||||
{
|
||||
/// <summary> Constructs an empty general data object. </summary>
|
||||
public GeneralData() : this(null, null, null) { }
|
||||
public GeneralData() : this(null, null, null, null) { }
|
||||
|
||||
public GeneralData(
|
||||
IMapSpan initialMapSpan,
|
||||
string merachantMessage,
|
||||
Version apiVersion)
|
||||
Version apiVersion,
|
||||
ResourceUrls resourceUrls)
|
||||
{
|
||||
InitialMapSpan = initialMapSpan ?? MapSpanFactory.Create();
|
||||
MerchantMessage = merachantMessage ?? string.Empty;
|
||||
ApiVersion = apiVersion ?? new Version(0, 0);
|
||||
ResourceUrls = resourceUrls ?? new ResourceUrls();
|
||||
}
|
||||
|
||||
/// <summary> Initial map display area.</summary>
|
||||
|
@ -27,5 +30,8 @@ namespace TINK.Services.CopriApi
|
|||
|
||||
/// <summary> Version of COPRI api. 0.0 if version is not set</summary>
|
||||
public Version ApiVersion { get; private set; }
|
||||
|
||||
/// <summary> Resources (html pages) to be displayed provided by COPRI.</summary>
|
||||
public IResourceUrls ResourceUrls { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,24 +22,5 @@ namespace TINK.Services.CopriApi.ServerUris
|
|||
? "tinkapp" /* resource tree is more complex for TINK/ konrad*/
|
||||
: "app";
|
||||
|
||||
/// <summary> Get folder name for a static site depending on host name. </summary>
|
||||
/// <param name="hostName">Host name.</param>
|
||||
/// <returns>Folder name.</returns>
|
||||
public static string GetSiteFolderName(this string hostName)
|
||||
=> hostName.GetIsCopri()
|
||||
? "tinkapp" /* resource tree is more complex for TINK/ konrad*/
|
||||
: SHAREE_SILTEFOLDERNAME;
|
||||
|
||||
/// <summary> Get the agb resource name name depending on host name. </summary>
|
||||
/// <param name="hostName">Host name.</param>
|
||||
/// <returns>AGB resource.</returns>
|
||||
public static string GetAGBResource(this string hostName)
|
||||
=> $"{hostName.GetSiteFolderName()}/{(hostName.GetIsCopri()? "konrad-TINK-AGB" : "agb.html")}";
|
||||
|
||||
/// <summary> Get the privacy resource name name depending on host name. </summary>
|
||||
/// <param name="hostName">Host name.</param>
|
||||
/// <returns>Privacy resource.</returns>
|
||||
public static string GetPrivacyResource(this string hostName)
|
||||
=> $"{hostName.GetSiteFolderName()}/{(hostName.GetIsCopri() ? "Datenschutz" : "privacy.html")}";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,7 +53,6 @@
|
|||
<Folder Include="Services\Permissions\Essentials\" />
|
||||
<Folder Include="Services\Permissions\Plugin\" />
|
||||
<Folder Include="ViewModel\Info\BikeInfo\" />
|
||||
<Folder Include="ViewModel\FeesAndBikes\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\LockItBLE\LockItBLE.csproj" />
|
||||
|
|
|
@ -301,122 +301,12 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
// Close lock
|
||||
Log.ForContext<ReservedOpen>().Information("User selected disposable bike {bike} in order to manage sound/ alarm settings.", SelectedBike);
|
||||
|
||||
// Check current state.
|
||||
BikesViewModel.ActionText = "Schlosseinstellung abfragen...";
|
||||
bool isAlarmOff;
|
||||
try
|
||||
{
|
||||
isAlarmOff = await LockService[SelectedBike.LockInfo.Id].GetIsAlarmOffAsync();
|
||||
}
|
||||
catch (OutOfReachException exception)
|
||||
{
|
||||
Log.ForContext<ReservedOpen>().Debug("Can not get lock alarm settings. {Exception}", exception);
|
||||
|
||||
BikesViewModel.ActionText = string.Empty;
|
||||
await ViewService.DisplayAlert(
|
||||
"Fehler beim Abfragen der Alarmeinstellungen!",
|
||||
"Schloss kann erst geschlossen werden, wenn Rad in der Nähe ist.",
|
||||
"OK");
|
||||
|
||||
return this;
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Log.ForContext<ReservedOpen>().Error("Can not get lock alarm settings. {Exception}", exception);
|
||||
|
||||
BikesViewModel.ActionText = string.Empty;
|
||||
await ViewService.DisplayAlert(
|
||||
"Fehler beim Abfragen der Alarmeinstellungen!",
|
||||
exception.Message,
|
||||
"OK");
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
if (isAlarmOff)
|
||||
{
|
||||
// Switch on sound.
|
||||
BikesViewModel.ActionText = "Anschalten von Sounds...";
|
||||
try
|
||||
{
|
||||
await LockService[SelectedBike.LockInfo.Id].SetSoundAsync(SoundSettings.AllOn);
|
||||
}
|
||||
catch (OutOfReachException exception)
|
||||
{
|
||||
Log.ForContext<ReservedOpen>().Debug("Can not turn on sounds. {Exception}", exception);
|
||||
|
||||
BikesViewModel.ActionText = string.Empty;
|
||||
await ViewService.DisplayAlert(
|
||||
"Fehler beim Anschalten der Sounds!",
|
||||
"Sounds können erst angeschalten werden, wenn Rad in der Nähe ist.",
|
||||
"OK");
|
||||
|
||||
return this;
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Log.ForContext<ReservedOpen>().Error("Can not turn on sounds. {Exception}", exception);
|
||||
|
||||
BikesViewModel.ActionText = string.Empty;
|
||||
await ViewService.DisplayAlert(
|
||||
"Fehler beim Anschalten der Sounds!",
|
||||
exception.Message,
|
||||
"OK");
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
// Switch off alarm.
|
||||
BikesViewModel.ActionText = "Anschalten von Alarm...";
|
||||
try
|
||||
{
|
||||
await LockService[SelectedBike.LockInfo.Id].SetIsAlarmOffAsync(true);
|
||||
}
|
||||
catch (OutOfReachException exception)
|
||||
{
|
||||
Log.ForContext<ReservedOpen>().Debug("Can not turn on alarm settings. {Exception}", exception);
|
||||
|
||||
BikesViewModel.ActionText = string.Empty;
|
||||
await ViewService.DisplayAlert(
|
||||
"Fehler beim Anschalten des Alarms!",
|
||||
"Alarm kann erst angeschalten werden, wenn Rad in der Nähe ist.",
|
||||
"OK");
|
||||
|
||||
return this;
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Log.ForContext<ReservedOpen>().Error("Can not turn on alarm. {Exception}", exception);
|
||||
|
||||
BikesViewModel.ActionText = string.Empty;
|
||||
await ViewService.DisplayAlert(
|
||||
"Fehler beim Anschalten des Alarms!",
|
||||
exception.Message,
|
||||
"OK");
|
||||
|
||||
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
|
||||
}
|
||||
finally
|
||||
{
|
||||
BikesViewModel.ActionText = string.Empty;
|
||||
BikesViewModel.IsIdle = true; // Unlock GUI
|
||||
await ViewUpdateManager().StartUpdateAyncPeridically(); // Restart polling again.
|
||||
}
|
||||
|
||||
await ViewService.DisplayAlert(
|
||||
"Hinweis",
|
||||
"Alarm und Sounds erfolgreich aktiviert",
|
||||
"OK");
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
// Alarm and sounds are on, toggle to off.
|
||||
// Switch off sound.
|
||||
BikesViewModel.ActionText = "Abschalten der Sounds...";
|
||||
try
|
||||
{
|
||||
await LockService[SelectedBike.LockInfo.Id].SetSoundAsync(SoundSettings.AllOff);
|
||||
await LockService[SelectedBike.LockInfo.Id].SetSoundAsync(SoundSettings.Warn);
|
||||
}
|
||||
catch (OutOfReachException exception)
|
||||
{
|
||||
|
@ -443,11 +333,42 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
|
|||
return this;
|
||||
}
|
||||
|
||||
// Lower alarm sensivity.
|
||||
BikesViewModel.ActionText = "Setzen Alarm-Einstellungen...";
|
||||
try
|
||||
{
|
||||
await LockService[SelectedBike.LockInfo.Id].SetAlarmSettingsAsync(AlarmSettings.SmallSensivitySilent);
|
||||
}
|
||||
catch (OutOfReachException exception)
|
||||
{
|
||||
Log.ForContext<ReservedOpen>().Debug("Can not set alarm settings. {Exception}", exception);
|
||||
|
||||
BikesViewModel.ActionText = string.Empty;
|
||||
await ViewService.DisplayAlert(
|
||||
"Fehler beim Setzen der Alarm-Einstellungen!",
|
||||
"Alarm kann erst eingestellt werden, wenn Rad in der Nähe ist.",
|
||||
"OK");
|
||||
|
||||
return this;
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Log.ForContext<ReservedOpen>().Error("Can not set alarm settings. {Exception}", exception);
|
||||
|
||||
BikesViewModel.ActionText = string.Empty;
|
||||
await ViewService.DisplayAlert(
|
||||
"Fehler beim Setzen der Alarms-Einstellungen!",
|
||||
exception.Message,
|
||||
"OK");
|
||||
|
||||
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
|
||||
}
|
||||
|
||||
// Switch off alarm.
|
||||
BikesViewModel.ActionText = "Abschalten von Alarm...";
|
||||
try
|
||||
{
|
||||
await LockService[SelectedBike.LockInfo.Id].SetIsAlarmOffAsync(false);
|
||||
await LockService[SelectedBike.LockInfo.Id].SetIsAlarmOffAsync(true);
|
||||
}
|
||||
catch (OutOfReachException exception)
|
||||
{
|
||||
|
|
|
@ -331,6 +331,7 @@ namespace TINK.ViewModel.Contact
|
|||
var resultStationsAndBikes = await TinkApp.GetConnector(IsConnected).Query.GetBikesAndStationsAsync();
|
||||
|
||||
TinkApp.Stations = resultStationsAndBikes.Response.StationsAll;
|
||||
TinkApp.ResourceUrls = resultStationsAndBikes.GeneralData.ResourceUrls;
|
||||
|
||||
if (Pins.Count > 0 && Pins.Count != resultStationsAndBikes.Response.StationsAll.Count)
|
||||
{
|
||||
|
|
|
@ -1,34 +1,35 @@
|
|||
using System.ComponentModel;
|
||||
using Xamarin.Forms;
|
||||
using TINK.Services.CopriApi.ServerUris;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace TINK.ViewModel.Contact
|
||||
{
|
||||
public class HelpContactViewModel : INotifyPropertyChanged
|
||||
public class FeesAndBikesPageViewModel : INotifyPropertyChanged
|
||||
{
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
/// <summary> Gets the platfrom specific prefix. </summary>
|
||||
private Func<string, string> ResourceProvider { get; set; }
|
||||
|
||||
/// <summary> Holds value wether site caching is on or off.</summary>
|
||||
bool IsSiteCachingOn { get; }
|
||||
|
||||
private string FeesResourcePath { get; }
|
||||
|
||||
private string BikesResourcePath { get; }
|
||||
|
||||
|
||||
/// <summary> Constructs view model.</summary>
|
||||
/// <param name="isSiteCachingOn">Set of user permissions</param>
|
||||
/// <param name="resourceProvider">Delegate to get an an embedded html ressource. Used as fallback if download from web page does not work and cache is empty.</param>
|
||||
public HelpContactViewModel(
|
||||
public FeesAndBikesPageViewModel(
|
||||
string hostName,
|
||||
bool isSiteCachingOn,
|
||||
Func<string, string> resourceProvider)
|
||||
string feesResourcePath,
|
||||
string bikesResourcePath,
|
||||
bool isSiteCachingOn)
|
||||
{
|
||||
HostName = hostName;
|
||||
FeesResourcePath = feesResourcePath;
|
||||
BikesResourcePath = bikesResourcePath;
|
||||
IsSiteCachingOn = isSiteCachingOn;
|
||||
|
||||
ResourceProvider = resourceProvider
|
||||
?? throw new ArgumentException($"Can not instantiate {typeof(HelpContactViewModel)}-object. No ressource provider availalbe.");
|
||||
|
||||
}
|
||||
|
||||
/// <summary> Holds the name of the host.</summary>
|
||||
|
@ -39,16 +40,16 @@ namespace TINK.ViewModel.Contact
|
|||
{
|
||||
RentBikeText = new HtmlWebViewSource
|
||||
{
|
||||
Html = HostName.GetIsCopri()
|
||||
? ResourceProvider("HtmlResouces.V02.InfoRentBike.html")
|
||||
: await ViewModelHelper.GetSource($"https://{HostName}/{CopriHelper.SHAREE_SILTEFOLDERNAME}/tariff_info_1.html", IsSiteCachingOn)
|
||||
Html = !string.IsNullOrEmpty(FeesResourcePath)
|
||||
? await ViewModelHelper.GetSource($"https://{HostName}/{FeesResourcePath}" /* "site/tariff_info_1.html" */, IsSiteCachingOn)
|
||||
: await Task.FromResult(ViewModelHelper.FromBody("No fees resource available. Resource path is null or empty."))
|
||||
};
|
||||
|
||||
TypesOfBikesText = new HtmlWebViewSource
|
||||
{
|
||||
Html = HostName.GetIsCopri()
|
||||
? ResourceProvider("HtmlResouces.V02.InfoTypesOfBikes.html")
|
||||
: await ViewModelHelper.GetSource($"https://{HostName}/{CopriHelper.SHAREE_SILTEFOLDERNAME}/bike_info.html", IsSiteCachingOn)
|
||||
Html = !string.IsNullOrEmpty(BikesResourcePath)
|
||||
? await ViewModelHelper.GetSource($"https://{HostName}/{BikesResourcePath}" /*"site/bike_info.html"*/, IsSiteCachingOn)
|
||||
: await Task.FromResult(ViewModelHelper.FromBody("No bikes instruction resource available. Resource path is null or empty."))
|
||||
};
|
||||
}
|
||||
|
|
@ -9,7 +9,7 @@ using Xamarin.Forms;
|
|||
namespace TINK.ViewModel.Info
|
||||
{
|
||||
/// <summary> Manges the tabbed info page. </summary>
|
||||
public class InfoViewModel : INotifyPropertyChanged
|
||||
public class InfoPageViewModel : INotifyPropertyChanged
|
||||
{
|
||||
/// <summary> Fired whenever a property changed.</summary>
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
@ -20,42 +20,56 @@ namespace TINK.ViewModel.Info
|
|||
/// <summary> Holds value wether site caching is on or off.</summary>
|
||||
bool IsSiteCachingOn { get; }
|
||||
|
||||
private string AgbResourcePath { get; }
|
||||
|
||||
private string PrivacyResourcePath { get; }
|
||||
|
||||
private string ImpressResourcePath { get; }
|
||||
|
||||
/// <summary> Constructs Info view model</summary>
|
||||
/// <param name="isSiteCachingOn">Holds value wether site caching is on or off.</param>
|
||||
/// <param name="resourceProvider">Delegate to get an an embedded html ressource. Used as fallback if download from web page does not work and cache is empty.</param>
|
||||
public InfoViewModel(
|
||||
public InfoPageViewModel(
|
||||
string hostName,
|
||||
bool isSiteCachingOn,
|
||||
string agbResourcePath,
|
||||
string privacyResourcePath,
|
||||
string impressResourcePath,
|
||||
bool isSiteCachingOn,
|
||||
Func<string, string> resourceProvider)
|
||||
{
|
||||
HostName = hostName;
|
||||
|
||||
AgbResourcePath = agbResourcePath;
|
||||
PrivacyResourcePath = privacyResourcePath;
|
||||
ImpressResourcePath = impressResourcePath;
|
||||
IsSiteCachingOn = isSiteCachingOn;
|
||||
|
||||
InfoAgb = new HtmlWebViewSource { Html = "<html>Loading...</html>" };
|
||||
|
||||
ResourceProvider = resourceProvider
|
||||
?? throw new ArgumentException($"Can not instantiate {typeof(InfoViewModel)}-object. No ressource provider availalbe.");
|
||||
?? throw new ArgumentException($"Can not instantiate {typeof(InfoPageViewModel)}-object. No ressource provider availalbe.");
|
||||
}
|
||||
|
||||
/// <summary> Called when page is shown. </summary>
|
||||
public async void OnAppearing()
|
||||
{
|
||||
InfoAgb = await GetAgb(HostName, IsSiteCachingOn, ResourceProvider);
|
||||
|
||||
InfoAgb = await GetAgb(HostName, AgbResourcePath, IsSiteCachingOn);
|
||||
|
||||
InfoPrivacy = new HtmlWebViewSource
|
||||
{
|
||||
Html = await ViewModelHelper.GetSource(
|
||||
$"https://{HostName}/{HostName.GetPrivacyResource()}",
|
||||
IsSiteCachingOn,
|
||||
HostName.GetIsCopri() ? () => ResourceProvider("HtmlResouces.V02.InfoDatenschutz.html") : (Func<string>) null) /* offline resources only available for TINK */,
|
||||
Html = !string.IsNullOrEmpty(PrivacyResourcePath)
|
||||
? await ViewModelHelper.GetSource(
|
||||
$"https://{HostName}/{PrivacyResourcePath}", // "site/privacy.html"
|
||||
IsSiteCachingOn)
|
||||
: await Task.FromResult(ViewModelHelper.FromBody("No privacy resource available. Resource path is null or empty."))
|
||||
};
|
||||
|
||||
InfoImpressum = new HtmlWebViewSource
|
||||
{
|
||||
Html = HostName.GetIsCopri()
|
||||
? ResourceProvider("HtmlResouces.V02.InfoImpressum.html")
|
||||
: await ViewModelHelper.GetSource($"https://{HostName}/{CopriHelper.SHAREE_SILTEFOLDERNAME}/impress.html", IsSiteCachingOn)
|
||||
Html = !string.IsNullOrEmpty(ImpressResourcePath)
|
||||
? await ViewModelHelper.GetSource(
|
||||
$"https://{HostName}/{ImpressResourcePath}", // "site/impress.html"
|
||||
IsSiteCachingOn)
|
||||
: await Task.FromResult(ViewModelHelper.FromBody("No impress resource available. Resource path is null or empty."))
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -64,15 +78,16 @@ namespace TINK.ViewModel.Info
|
|||
/// <returns> AGBs</returns>
|
||||
public static async Task<HtmlWebViewSource> GetAgb(
|
||||
string hostName,
|
||||
bool isSiteCachingOn,
|
||||
Func<string, string> resourceProvider)
|
||||
string agbResourcePath,
|
||||
bool isSiteCachingOn)
|
||||
{
|
||||
return new HtmlWebViewSource
|
||||
{
|
||||
Html = await ViewModelHelper.GetSource(
|
||||
$"https://{hostName}/{hostName.GetAGBResource()}",
|
||||
isSiteCachingOn,
|
||||
hostName.GetIsCopri() ? () => resourceProvider("HtmlResouces.V02.InfoAGB.html") : (Func<string>) null) /* offline resources only available for TINK */,
|
||||
Html = !string.IsNullOrEmpty(agbResourcePath)
|
||||
? await ViewModelHelper.GetSource(
|
||||
$"https://{hostName}/{agbResourcePath}", // "agb.html"
|
||||
isSiteCachingOn)
|
||||
: await Task.FromResult(ViewModelHelper.FromBody("No terms resource available. Resource path is null or empty."))
|
||||
};
|
||||
}
|
||||
|
|
@ -325,6 +325,7 @@ namespace TINK.ViewModel.Map
|
|||
var resultStationsAndBikes = await TinkApp.GetConnector(IsConnected).Query.GetBikesAndStationsAsync();
|
||||
|
||||
TinkApp.Stations = resultStationsAndBikes.Response.StationsAll;
|
||||
TinkApp.ResourceUrls = resultStationsAndBikes.GeneralData.ResourceUrls;
|
||||
|
||||
if (!string.IsNullOrEmpty(resultStationsAndBikes?.GeneralData?.MerchantMessage)
|
||||
&& !WasMerchantMessageAlreadyShown)
|
||||
|
|
|
@ -286,8 +286,9 @@ namespace TINK.ViewModel
|
|||
break;
|
||||
}
|
||||
|
||||
return htmlContent ?? string.Format("<!DOCTYPE html><html lang=\"de\"><body>An error occurred loading html- ressource.</body>");
|
||||
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>";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,7 +61,7 @@ namespace TINK.ViewModel.WhatsNew.Agb
|
|||
/// <summary> Called when page is shown. </summary>
|
||||
public async Task OnAppearing()
|
||||
{
|
||||
InfoAgb = await InfoViewModel.GetAgb(HostName, IsSiteCachingOn, ResourceProvider);
|
||||
InfoAgb = await InfoPageViewModel.GetAgb(HostName, "agbResourcePath", IsSiteCachingOn);
|
||||
}
|
||||
|
||||
/// <summary> User clicks OK button.</summary>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue