2022-10-03 17:55:10 +02:00
using System ;
2021-05-13 20:03:07 +02:00
using System.ComponentModel ;
using System.Threading.Tasks ;
2022-08-30 15:42:25 +02:00
using Serilog ;
2022-10-03 17:55:10 +02:00
using TINK.Model.Bikes ;
using TINK.Model ;
2021-05-13 20:03:07 +02:00
using TINK.Model.Device ;
2022-10-03 17:55:10 +02:00
using TINK.Model.Services.CopriApi ;
2021-05-13 20:03:07 +02:00
using Xamarin.Essentials ;
using Xamarin.Forms ;
2022-10-03 17:55:10 +02:00
using TINK.Model.Connector ;
2021-05-13 20:03:07 +02:00
namespace TINK.ViewModel.Info
{
2022-09-06 16:08:19 +02:00
/// <summary> Manges the tabbed info page. </summary>
public class InfoPageViewModel : INotifyPropertyChanged
{
/// <summary> Fired whenever a property changed.</summary>
public event PropertyChangedEventHandler PropertyChanged ;
/// <summary> Holds the name of the host.</summary>
private string HostName { get ; }
/// <summary> Holds value wether site caching is on or off.</summary>
bool IsSiteCachingOn { get ; }
2022-10-03 17:55:10 +02:00
/// <summary>
/// Relative path to agb resources of empty if value was not yet querried from backend.
/// </summary>
private string AgbResourcePath { get ; set ; }
/// <summary>
/// Relative path to privacy resources of empty if value was not yet querried from backend.
/// </summary>
private string PrivacyResourcePath { get ; set ; }
/// <summary>
/// Relative path to impress resources of empty if value was not yet querried from backend.
/// </summary>
private string ImpressResourcePath { get ; set ; }
private bool _IsIdle = false ;
2022-09-06 16:08:19 +02:00
2022-10-03 17:55:10 +02:00
/// <summary>
/// Is true if no action is pending, false otherwise.
/// </summary>
public bool IsIdle
{
get = > _IsIdle ;
private set
{
if ( _IsIdle = = value )
{
// Nothing to do.
return ;
}
_IsIdle = value ;
PropertyChanged ? . Invoke ( this , new PropertyChangedEventArgs ( nameof ( IsIdle ) ) ) ;
return ;
}
}
2022-09-06 16:08:19 +02:00
2022-10-03 17:55:10 +02:00
/// <summary>
/// Object to querry resources urls object from backend if required.
/// This object is used to update resources path values <see cref="AgbResourcePath"/>, <see cref="PrivacyResourcePath"/> and <see cref="ImpressResourcePath"/> from.
/// </summary>
private Func < IQuery > QueryProvider { get ; }
2022-09-06 16:08:19 +02:00
/// <summary>
2022-10-03 17:55:10 +02:00
/// Action to update shared resources urls object exposed by main model.
2022-09-06 16:08:19 +02:00
/// </summary>
2022-10-03 17:55:10 +02:00
private Action < IResourceUrls > UpdateUrlsAction { get ; }
2022-09-06 16:08:19 +02:00
/// <summary> Constructs Info view model</summary>
2022-10-03 17:55:10 +02:00
/// <param name="hostName">Name of the host to get html resources from.</param>
2022-09-06 16:08:19 +02:00
/// <param name="isSiteCachingOn">Holds value wether site caching is on or off.</param>
/// <param name="agbResourcePath"> Agb resouce path received from backend.</param>
/// <param name="privacyResourcePath"> Privacy resouce path received from backend.</param>
/// <param name="impressResourcePath"> Impress resouce path received from backend.</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>
2022-10-03 17:55:10 +02:00
/// <param name="queryProvider">Object to querry resources urls object from backend if required.</param>
/// <param name="updateUrlsAction">Action to update shared resources urls object</param>
2022-09-06 16:08:19 +02:00
public InfoPageViewModel (
string hostName ,
string agbResourcePath ,
string privacyResourcePath ,
string impressResourcePath ,
bool isSiteCachingOn ,
2022-10-03 17:55:10 +02:00
Func < string , string > resourceProvider ,
Func < IQuery > queryProvider ,
Action < IResourceUrls > updateUrlsAction )
2022-09-06 16:08:19 +02:00
{
HostName = hostName ;
AgbResourcePath = agbResourcePath ;
PrivacyResourcePath = privacyResourcePath ;
ImpressResourcePath = impressResourcePath ;
IsSiteCachingOn = isSiteCachingOn ;
2022-10-03 17:55:10 +02:00
QueryProvider = queryProvider ;
UpdateUrlsAction = updateUrlsAction ;
2022-09-06 16:08:19 +02:00
InfoAgb = new HtmlWebViewSource { Html = "<html>Loading...</html>" } ;
ResourceProvider = resourceProvider
? ? throw new ArgumentException ( $"Can not instantiate {typeof(InfoPageViewModel)}-object. No ressource provider availalbe." ) ;
}
/// <summary> Called when page is shown. </summary>
public async void OnAppearing ( )
{
2022-10-03 17:55:10 +02:00
// Get resource urls object from backend.
async Task < IResourceUrls > GetUrls ( )
{
Result < BikeCollection > bikes ;
try
{
bikes = await QueryProvider ( ) . GetBikesAsync ( ) ;
}
catch ( Exception ex )
{
Log . ForContext < InfoPageViewModel > ( ) . Error ( $"Getting resource urls from COPRI failed. {ex.Message}" ) ;
return new ResourceUrls ( ) ;
}
IResourceUrls resourceUrls = bikes ? . GeneralData ? . ResourceUrls ? ? new ResourceUrls ( ) ;
return resourceUrls ;
}
// Set state to busy.
IsIdle = false ;
// Check if urls to show info from are already known.
if ( string . IsNullOrEmpty ( PrivacyResourcePath ) )
{
var urls = await GetUrls ( ) ;
PrivacyResourcePath = urls . PrivacyResourcePath ;
ImpressResourcePath = urls . ImpressResourcePath ;
AgbResourcePath = urls . AgbResourcePath ;
UpdateUrlsAction ( urls ) ; // Update main model to prevent duplicate queries.
}
2022-09-06 16:08:19 +02:00
// Gets privacy info from server.
async Task < HtmlWebViewSource > GetInfoPrivacy ( )
{
string GetUriText ( )
= > $"https://{HostName}/{PrivacyResourcePath}" ;
if ( string . IsNullOrEmpty ( PrivacyResourcePath ) )
{
// Information to access ressource is missing
return new HtmlWebViewSource
{
Html = await Task . FromResult ( ViewModelHelper . FromBody ( "No privacy resource available. Resource path is null or empty." ) )
} ;
}
Log . Debug ( $"Request to open url {GetUriText()} to get privacy info." ) ;
return new HtmlWebViewSource
{
Html = await ViewModelHelper . GetSource (
GetUriText ( ) , // "site/privacy.html"
IsSiteCachingOn )
} ;
}
// Gets impress info from server.
async Task < HtmlWebViewSource > GetImpressum ( )
{
string GetUriText ( )
= > $"https://{HostName}/{ImpressResourcePath}" ;
if ( string . IsNullOrEmpty ( ImpressResourcePath ) )
{
// Information to access ressource is missing
return new HtmlWebViewSource
{
Html = await Task . FromResult ( ViewModelHelper . FromBody ( "No impress resource available. Resource path is null or empty." ) )
} ;
}
Log . Debug ( $"Request to open url {GetUriText()} to get impress info." ) ;
return new HtmlWebViewSource
{
Html = await ViewModelHelper . GetSource (
GetUriText ( ) , // "site/privacy.html"
IsSiteCachingOn )
} ;
}
2022-10-03 17:55:10 +02:00
InfoAgb = await GetAgb ( HostName , AgbResourcePath , IsSiteCachingOn ) ;
2022-09-06 16:08:19 +02:00
InfoPrivacy = await GetInfoPrivacy ( ) ;
InfoImpressum = await GetImpressum ( ) ;
2022-10-03 17:55:10 +02:00
// Set state to idle.
IsIdle = true ;
2022-09-06 16:08:19 +02:00
}
/// <summary> Gets the AGBs</summary>
/// <param name="resourceProvider"></param>
/// <returns> AGBs</returns>
public static async Task < HtmlWebViewSource > GetAgb (
string hostName ,
string agbResourcePath ,
2022-10-03 17:55:10 +02:00
bool isSiteCachingOn )
2022-09-06 16:08:19 +02:00
{
string GetUriText ( )
= > $"https://{hostName}/{agbResourcePath}" ;
if ( string . IsNullOrEmpty ( agbResourcePath ) )
{
return new HtmlWebViewSource
{
Html = await Task . FromResult ( ViewModelHelper . FromBody ( "No terms resource available. Resource path is null or empty." ) )
} ;
}
Log . Debug ( $"Request to open url {GetUriText()} to get AGB infos." ) ;
return new HtmlWebViewSource
{
Html = await ViewModelHelper . GetSource (
GetUriText ( ) , // "agb.html"
isSiteCachingOn )
} ;
}
/// <summary> Gets the platfrom specific prefix. </summary>
private Func < string , string > ResourceProvider { get ; set ; }
/// <summary> Gets the app related information (app version and licenses). </summary>
public HtmlWebViewSource InfoLicenses = > new HtmlWebViewSource
{
Html = ResourceProvider ( "HtmlResouces.V02.InfoLicenses.html" )
. Replace ( "CURRENT_VERSION_TINKAPP" , DependencyService . Get < IAppInfo > ( ) . Version . ToString ( ) )
. Replace ( "ACTIVE_APPNAME" , AppInfo . Name )
. Replace ( "APPSUPPORTMAILADDRESS" , ContactPageViewModel . APPSUPPORTMAILADDRESS )
} ;
/// <summary> Privacy text.</summary>
private HtmlWebViewSource infoImpress ;
/// <summary> Gets the privacy related information. </summary>
public HtmlWebViewSource InfoImpressum
{
get = > infoImpress ;
set
{
infoImpress = value ;
PropertyChanged ? . Invoke ( this , new PropertyChangedEventArgs ( nameof ( InfoImpressum ) ) ) ;
}
}
/// <summary> Agb information text.</summary>
private HtmlWebViewSource infoAgb ;
/// <summary> Privacy text.</summary>
private HtmlWebViewSource infoPrivacy ;
/// <summary> Agb information text.</summary>
public HtmlWebViewSource InfoAgb
{
get = > infoAgb ;
set
{
infoAgb = value ;
PropertyChanged ? . Invoke ( this , new PropertyChangedEventArgs ( nameof ( InfoAgb ) ) ) ;
}
}
/// <summary> Agb information text.</summary>
public HtmlWebViewSource InfoPrivacy
{
get = > infoPrivacy ;
set
{
infoPrivacy = value ;
PropertyChanged ? . Invoke ( this , new PropertyChangedEventArgs ( nameof ( InfoPrivacy ) ) ) ;
}
}
}
2021-05-13 20:03:07 +02:00
}