Version 3.0.371

This commit is contained in:
Anja 2023-08-31 12:31:38 +02:00
parent bdb2dec1c1
commit 6d22dbf40b
145 changed files with 2289 additions and 764 deletions

View file

@ -3,6 +3,7 @@ using System;
using System.ComponentModel;
using System.Text.RegularExpressions;
using TINK.Model.Bikes.BikeInfoNS.BikeNS;
using TINK.Model.Bikes.BikeInfoNS.DriveNS.BatteryNS;
#if !USEFLYOUT
#endif
using TINK.Model.Connector;
@ -136,20 +137,32 @@ namespace TINK.ViewModel.Bikes.Bike
selectedBike.PropertyChanged +=
(sender, eventargs) => OnSelectedBikePropertyChanged(eventargs.PropertyName);
var battery = selectedBike.Drive?.Battery;
if (battery != null)
{
battery.PropertyChanged += (_, args) =>
{
if (args.PropertyName == nameof(BatteryMutable.CurrentChargeBars))
{
RaisePropertyChanged(this, new PropertyChangedEventArgs(nameof(CurrentChargeBars)));
}
};
}
BikesViewModel = bikesViewModel
?? throw new ArgumentException($"Can not construct {GetType().Name}-object. {nameof(bikesViewModel)} must not be null.");
OpenUrlInBrowser = openUrlInBrowser ?? (url => { Log.ForContext<BikeViewModelBase>().Error($"No browse service avialble to upen {url}."); });
OpenUrlInBrowser = openUrlInBrowser ?? (url => { Log.ForContext<BikeViewModelBase>().Error($"No browse service available to open {url}."); });
}
/// <summary>
/// Handles BikeInfoMutable events.
/// Helper member to raise events. Maps model event change notification to view model events.
/// </summary>
/// <param name="p_strNameOfProp"></param>
private void OnSelectedBikePropertyChanged(string p_strNameOfProp)
/// <param name="nameOfProp"></param>
private void OnSelectedBikePropertyChanged(string nameOfProp)
{
if (p_strNameOfProp == nameof(State))
if (nameOfProp == nameof(State))
{
OnSelectedBikeStateChanged(); // Notify derived class about change of state.
}
@ -211,7 +224,7 @@ namespace TINK.ViewModel.Bikes.Bike
Bike.Drive.Type == Model.Bikes.BikeInfoNS.DriveNS.DriveType.Pedelec
&& (!Bike.Drive.Battery.IsHidden.HasValue /* no value means show battery level */ || Bike.Drive.Battery.IsHidden.Value == false);
/// Gets the image path for bike type Citybike, CargoLong, Trike or Pedelec.
/// Gets the image path for bike type City bike, CargoLong, Trike or Pedelec.
public string DisplayedBikeImageSourceString => $"bike_{Bike.TypeOfBike}_{Bike.Drive.Type}_{Bike.WheelType}.png";
/// <summary>
@ -302,7 +315,7 @@ namespace TINK.ViewModel.Bikes.Bike
/// <summary>
/// Gets reserved into display text.
/// </summary>
/// <todo>Log unexpeced states.</todo>
/// <todo>Log unexpected states.</todo>
/// <param name="p_oInUseState"></param>
/// <returns>Display text</returns>
private string GetReservedInfo(
@ -316,7 +329,7 @@ namespace TINK.ViewModel.Bikes.Bike
/// <summary>
/// Gets booked into display text.
/// </summary>
/// <todo>Log unexpeced states.</todo>
/// <todo>Log unexpected states.</todo>
/// <param name="p_oInUseState"></param>
/// <returns>Display text</returns>
private string GetBookedInfo(
@ -366,7 +379,7 @@ namespace TINK.ViewModel.Bikes.Bike
}
}
/// <summary> Holds description about the tarif. </summary>
/// <summary> Holds description about the tariff. </summary>
public TariffDescriptionViewModel TariffDescription => new TariffDescriptionViewModel(Bike.TariffDescription);
/// <summary> Gets the value of property <see cref="StateColor"/> when PropertyChanged was fired. </summary>

View file

@ -23,6 +23,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock
{
public Xamarin.Forms.Command ShowTrackingInfoCommand { get; private set; }
public Xamarin.Forms.Command ShowRideTypeInfoCommand { get; private set; }
public Xamarin.Forms.Command ShowBikeIsBoundToCityInfoCommand { get; private set; }
/// <summary> Notifies GUI about changes. </summary>
public override event PropertyChangedEventHandler PropertyChanged;
@ -123,6 +124,16 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock
});
ShowBikeIsBoundToCityInfoCommand = new Xamarin.Forms.Command(async () => {
// later, if value comes from backend: message = TariffDescription.CityAreaType
await ViewService.DisplayAlert(
AppResources.MessageBikeIsBoundToCityInfoTitle,
String.Format(AppResources.MessageBikeIsBoundToCityInfoText,selectedBike.TypeOfBike),
AppResources.MessageAnswerOk);
});
RequestHandler = user.IsLoggedIn
? RequestHandlerFactory.Create(
selectedBike,
@ -178,6 +189,9 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock
RaisePropertyChangedEvent(lastHandler);
}
public bool IsBikeBoundToCity
=> Bike.AaRideType == TINK.Model.Bikes.BikeInfoNS.BikeNS.AaRideType.NoAaRide ? true : false;
/// <summary> Gets visibility of the copri command button. </summary>
public bool IsButtonVisible
=> RequestHandler.IsButtonVisible;

View file

@ -1,15 +1,10 @@
using System;
using System.Threading.Tasks;
using Serilog;
using TINK.Model.Connector;
using TINK.Model;
using TINK.MultilingualResources;
using TINK.Repository.Exception;
using TINK.Repository.Request;
using TINK.Services.Logging;
using TINK.View;
using static TINK.Model.Bikes.BikeInfoNS.BluetoothLock.Command.CloseCommand;
using TINK.Services.BluetoothLock;
using System.ComponentModel;
namespace TINK.ViewModel.Bikes.Bike.BluetoothLock
@ -33,20 +28,6 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock
/// </summary>
private IViewService ViewService { get; }
/// <summary>
/// Service to control locks.
/// </summary>
private ILocksService LockService { get; }
/// <summary> Provides a connector object.</summary>
protected Func<bool, IConnector> ConnectorFactory { get; }
/// <summary> Delegate to retrieve connected state. </summary>
private Func<bool> IsConnectedDelegate { get; }
/// <summary>Gets the is connected state. </summary>
bool IsConnected;
/// <summary>Object to start or stop update of view model objects from Copri.</summary>
private Func<IPollingUpdateTaskManager> ViewUpdateManager { get; }
@ -83,7 +64,6 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock
switch (step)
{
case Step.StartStopingPolling:
BikesViewModel.ActionText = AppResources.ActivityTextOneMomentPlease;
break;
case Step.StartingQueryingLocation:
@ -188,12 +168,12 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock
// 1. Step
// Parameter for RentalProcess View
BikesViewModel.RentalProcess = new RentalProcess(SelectedBike.Id)
BikesViewModel.StartRentalProcess(new RentalProcessViewModel(SelectedBike.Id)
{
State = CurrentRentalProcess.CloseLock,
StepIndex = 1,
Result = CurrentStepStatus.None
};
});
// Close Lock
BikesViewModel.RentalProcess.StepInfoText = AppResources.MarkingRentalProcessCloseLockStepCloseLock;
@ -215,9 +195,8 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock
await ViewUpdateManager().StartAsync();
BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true;
BikesViewModel.RentalProcess.State = CurrentRentalProcess.None;
BikesViewModel.IsIdle = true;
return;
}
@ -231,90 +210,31 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock
BikesViewModel.RentalProcess.Result = CurrentStepStatus.None;
BikesViewModel.RentalProcess.ImportantStepInfoText = String.Empty;
//// Ask if lock is closed
//var isLockClosed = await ViewService.DisplayAlert(
// AppResources.QuestionRentalProcessCloseLockCheckLockTitle,
// AppResources.QuestionRentalProcessCloseLockCheckLockText,
// AppResources.QuestionRentalProcessCloseLockCheckLockAnswerYes,
// AppResources.QuestionRentalProcessCloseLockCheckLockAnswerNo);
// Question if park bike or end rental
IsEndRentalRequested = await ViewService.DisplayAlert(
AppResources.QuestionRentalProcessCloseLockEndOrContinueTitle,
AppResources.QuestionRentalProcessCloseLockEndOrContinueText,
AppResources.QuestionRentalProcessCloseLockEndRentalAnswer,
AppResources.QuestionRentalProcessCloseLockContinueRentalAnswer);
//// If lock is not closed
//if(isLockClosed == false)
//{
// var retryOrContactresult = await ViewService.DisplayAlert(
// AppResources.MessageRentalProcessCloseLockNotClosedTitle,
// AppResources.MessageRentalProcessCloseLockNotClosedText,
// AppResources.MessageAnswerRetry,
// AppResources.MessageAnswerContactSupport);
BikesViewModel.RentalProcess.Result = CurrentStepStatus.Succeeded;
// BikesViewModel.RentalProcess.Result = CurrentStepStatus.Failed;
// if (retryOrContactresult == true)
// {
// //restart CloseLock()
// }
// else if(retryOrContactresult == false)
// {
// await OpenContactPageAsync();
// }
//}
// If lock is closed
//else if(isLockClosed == true)
//{
IsEndRentalRequested = await ViewService.DisplayAlert(
AppResources.QuestionRentalProcessCloseLockEndOrContinueTitle,
AppResources.QuestionRentalProcessCloseLockEndOrContinueText,
AppResources.QuestionRentalProcessCloseLockEndRentalAnswer,
AppResources.QuestionRentalProcessCloseLockContinueRentalAnswer);
BikesViewModel.RentalProcess.Result = CurrentStepStatus.Succeeded;
// Continue with End rental in RequestHandler
if (IsEndRentalRequested == true)
{
return;
}
// Park bike
else if(IsEndRentalRequested == false)
{
await ViewService.DisplayAlert(
AppResources.MessageRentalProcessCloseLockFinishedTitle,
AppResources.MessageRentalProcessCloseLockFinishedText,
AppResources.MessageAnswerOk);
}
//}
// Message for parking bike
if(IsEndRentalRequested == false)
{
await ViewService.DisplayAlert(
AppResources.MessageRentalProcessCloseLockFinishedTitle,
AppResources.MessageRentalProcessCloseLockFinishedText,
AppResources.MessageAnswerOk);
}
BikesViewModel.RentalProcess.State = CurrentRentalProcess.None;
BikesViewModel.IsIdle = true;
return;
}
/// <summary> Opens support. </summary>
//#if USEFLYOUT
// public void OpenContactPageAsync()
//#else
// public async Task OpenContactPageAsync()
//#endif
// {
// try
// {
// // Open Contact Page with Contact information for operator of SelectedBike
//#if USEFLYOUT
// ViewService.ShowPage(ViewTypes.ContactPage, AppResources.MarkingFeedbackAndContact);
//#else
// await ViewService.ShowPage("//ContactPage");
//#endif
// }
// catch (Exception p_oException)
// {
// Log.Error("Ein unerwarteter Fehler ist auf der Seite Kontakt aufgetreten. Kontext: Klick auf Konakt aufnehmen bei Schloss schließen (Schloss nicht zu!). {@Exception}", p_oException);
// return;
// }
// }
/// <summary>
/// True if user requested End rental.
/// Default value of user request to end rental = false.
/// </summary>
private bool isEndRentalRequested = false;

View file

@ -76,12 +76,12 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock
?? throw new ArgumentException($"Can not construct {typeof(EndRentalActionViewModel<T>)}-object. {nameof(bikesViewModel)} must not be null.");
// Set parameter for RentalProcess View to initial value.
BikesViewModel.RentalProcess = new RentalProcess(SelectedBike.Id)
BikesViewModel.StartRentalProcess(new RentalProcessViewModel(SelectedBike.Id)
{
State = CurrentRentalProcess.None,
StepIndex = 0,
Result = CurrentStepStatus.None
};
});
}
/// <summary>
@ -155,12 +155,12 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock
// 1. Step
// Parameter for RentalProcess View
BikesViewModel.RentalProcess = new RentalProcess(SelectedBike.Id)
BikesViewModel.StartRentalProcess(new RentalProcessViewModel(SelectedBike.Id)
{
State = CurrentRentalProcess.EndRental,
StepIndex = 1,
Result = CurrentStepStatus.None
};
});
// Get Location
BikesViewModel.RentalProcess.StepInfoText = AppResources.MarkingRentalProcessEndRentalStepGPS;
@ -271,7 +271,16 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock
BikesViewModel.RentalProcess.ImportantStepInfoText = String.Empty;
var feedBackUri = SelectedBike?.OperatorUri;
var feedback = await ViewService.DisplayUserFeedbackPopup(SelectedBike.Drive?.Battery);
var battery = SelectedBike.Drive?.Battery;
var feedback = await ViewService.DisplayUserFeedbackPopup(
battery,
bookingFinished?.Co2Saving);
if (battery != null
&& feedback.CurrentChargeBars != null)
{
SelectedBike.Drive.Battery.CurrentChargeBars = feedback.CurrentChargeBars;
}
#endif
BikesViewModel.RentalProcess.Result = CurrentStepStatus.Succeeded;

View file

@ -62,7 +62,16 @@ namespace TINK.ViewModel.Bikes.Bike.CopriLock.RequestHandler
await ViewUpdateManager().StopAsync();
// Do get Feedback
var feedback = await ViewService.DisplayUserFeedbackPopup(SelectedBike.Drive?.Battery, SelectedBike?.BookingFinishedModel?.Co2Saving);
var battery = SelectedBike.Drive?.Battery;
var feedback = await ViewService.DisplayUserFeedbackPopup(
battery,
SelectedBike?.BookingFinishedModel?.Co2Saving);
if (battery != null
&& feedback.CurrentChargeBars != null)
{
SelectedBike.Drive.Battery.CurrentChargeBars = feedback.CurrentChargeBars;
}
BikesViewModel.ActionText = AppResources.ActivityTextSubmittingFeedback;
IsConnected = IsConnectedDelegate();

View file

@ -10,7 +10,6 @@ using TINK.Model.Bikes;
using TINK.Model.Connector;
using TINK.Model.Device;
using TINK.Model.User;
using TINK.MultilingualResources;
using TINK.Services.BluetoothLock;
using TINK.Services.Geolocation;
using TINK.Services.Permissions;
@ -344,24 +343,25 @@ namespace TINK.ViewModel.Bikes
}
/// <summary> Used to display active rental process.</summary>
private IRentalProcess _rentalProcess = new RentalProcess();
private IRentalProcessViewModel _rentalProcess = new RentalProcessViewModel();
/// <summary> Holds the active rental process.</summary>
public IRentalProcess RentalProcess
public IRentalProcessViewModel RentalProcess => _rentalProcess;
/// <summary>
/// Starts the rental process.
/// </summary>
/// <param name="processViewModel">Rental process values to start with.</param>
public void StartRentalProcess(IRentalProcessViewModel processViewModel)
{
get => _rentalProcess;
set
{
if (value == _rentalProcess)
return;
if (processViewModel == _rentalProcess)
return;
_rentalProcess = value;
_rentalProcess.LoadFrom(processViewModel);
BikeInRentalProcess = this.FirstOrDefault(bike => bike.Id == _rentalProcess.BikeId) as Bike.BluetoothLock.BikeViewModel;
BikeInRentalProcess = this.FirstOrDefault(bike => bike.Id == _rentalProcess.BikeId) as Bike.BluetoothLock.BikeViewModel;
base.OnPropertyChanged(new PropertyChangedEventArgs(nameof(RentalProcess)));
base.OnPropertyChanged(new PropertyChangedEventArgs(nameof(BikeInRentalProcess)));
}
base.OnPropertyChanged(new PropertyChangedEventArgs(nameof(RentalProcess)));
base.OnPropertyChanged(new PropertyChangedEventArgs(nameof(BikeInRentalProcess)));
}
public Bike.BluetoothLock.BikeViewModel BikeInRentalProcess { get; private set; }

View file

@ -4,7 +4,13 @@ namespace TINK.ViewModel.Bikes
public interface IBikesViewModel
{
/// <summary> Holds info about active rental process. </summary>
IRentalProcess RentalProcess { get; set; }
IRentalProcessViewModel RentalProcess { get; }
/// <summary>
/// Starts the rental process.
/// </summary>
/// <param name="processViewModel">Rental process values to start with.</param>
void StartRentalProcess(IRentalProcessViewModel process);
/// <summary> Holds info about current action. </summary>
string ActionText { get; set; }

View file

@ -2,8 +2,14 @@ using TINK.Model;
namespace TINK.ViewModel.Bikes
{
public interface IRentalProcess
public interface IRentalProcessViewModel
{
/// <summary>
/// Loads rental process view model from source.
/// </summary>
/// <param name="processViewModel">Source object to load from.</param>
void LoadFrom(IRentalProcessViewModel processViewModel);
/// <summary>
/// Gets the id of the bike which is rental ends.
/// </summary>

View file

@ -21,16 +21,31 @@ namespace TINK.ViewModel.Bikes
Failed = 2,
}
public class RentalProcess : IRentalProcess, INotifyPropertyChanged
public class RentalProcessViewModel : IRentalProcessViewModel, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public RentalProcess(string bikeId = null) => BikeId = bikeId ?? string.Empty;
public RentalProcessViewModel(string bikeId = null) => BikeId = bikeId ?? string.Empty;
/// <summary>
/// Loads rental process view model from source.
/// </summary>
/// <param name="processViewModel">Source object to load from </param>
public void LoadFrom(IRentalProcessViewModel processViewModel)
{
BikeId = processViewModel.BikeId;
_state = processViewModel.State;
_stepIndex = processViewModel.StepIndex;
_stepInfoText = processViewModel.StepInfoText;
_importantStepInfoText = processViewModel.ImportantStepInfoText;
_result = processViewModel.Result;
EndRentalInfo = processViewModel.EndRentalInfo;
}
/// <summary>
/// Gets the id of the bike which is rental ends.
/// </summary>
public string BikeId { get; }
public string BikeId { get; private set; }
/// <summary> Holds info about active rental process. </summary>
private CurrentRentalProcess _state = CurrentRentalProcess.None;
@ -53,9 +68,7 @@ namespace TINK.ViewModel.Bikes
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(State)));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(StepIndex)));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Result)));
}
}
/// <summary> Holds info about current step in rental process. </summary>

View file

@ -5,6 +5,7 @@ using System.Threading.Tasks;
using System.Windows.Input;
using Plugin.Messaging;
using Serilog;
using TINK.Model;
using TINK.Model.Stations;
using TINK.Model.Stations.StationNS;
using TINK.MultilingualResources;
@ -31,6 +32,9 @@ namespace TINK.ViewModel.Info
/// <summary> Holds the name of the app (sharee.bike, Mein konrad, ...)</summary>
string AppFlavorName { get; }
/// <summary> Reference on the tink app instance. </summary>
private ITinkApp TinkApp { get; }
/// <summary> Holds a reference to the external trigger service. </summary>
private Action OpenUrlInExternalBrowser { get; }
@ -45,6 +49,7 @@ namespace TINK.ViewModel.Info
/// <param name="viewService">View service to notify user.</param>
public ContactPageViewModel(
string appFlavorName,
ITinkApp tinkApp,
Func<string> createAttachment,
Action openUrlInExternalBrowser,
IViewService viewService)
@ -53,6 +58,9 @@ namespace TINK.ViewModel.Info
? appFlavorName
: throw new ArgumentException("Can not instantiate contact page view model- object. No app name centered.");
TinkApp = tinkApp
?? throw new ArgumentException("Can not instantiate settings page view model- object. No tink app object available.");
CreateAttachment = createAttachment
?? throw new ArgumentException("Can not instantiate contact page view model- object. No create attachment provider available.");
@ -141,7 +149,8 @@ namespace TINK.ViewModel.Info
Cc = APPSUPPORTMAILADDRESS.ToUpper() != MailAddressText.ToUpper() // do not sent copy if same mail address
&& MailAddressText != "konrad@sharee.bike" // do not sent copy if Mein konrad
? new List<string> { APPSUPPORTMAILADDRESS } : new List<string>(),
Subject = string.Format(AppResources.SupportmailSubjectOperatormail, AppFlavorName, SelectedStation?.Id)
Subject = string.Format(AppResources.SupportmailSubjectOperatormail, AppFlavorName, SelectedStation?.Id),
Body = TinkApp.ActiveUser.Mail != null ? $"{AppResources.SupportmailBodyText}\r\n\r\n\r\n\r\n{string.Format(AppResources.MarkingLoggedInStateInfoLoggedIn, TinkApp.ActiveUser.Mail)}" : $"{AppResources.SupportmailBodyText}\r\n\r\n\r\n\r\n{string.Format(AppResources.SupportmailBodyNotLoggedIn)}"
});
return;
@ -172,7 +181,8 @@ namespace TINK.ViewModel.Info
var message = new EmailMessage
{
To = new List<string> { APPSUPPORTMAILADDRESS },
Subject = SelectedStation?.Id != null ? string.Format(AppResources.SupportmailSubjectAppmailWithStation, AppFlavorName, SelectedStation?.Id) : string.Format(AppResources.SupportmailSubjectAppmail, AppFlavorName)
Subject = SelectedStation?.Id != null ? string.Format(AppResources.SupportmailSubjectAppmailWithStation, AppFlavorName, SelectedStation?.Id) : string.Format(AppResources.SupportmailSubjectAppmail, AppFlavorName),
Body = TinkApp.ActiveUser.Mail != null ? $"{AppResources.SupportmailBodyText}\r\n\r\n\r\n\r\n{string.Format(AppResources.MarkingLoggedInStateInfoLoggedIn, TinkApp.ActiveUser.Mail)}" : $"{AppResources.SupportmailBodyText}\r\n\r\n\r\n\r\n{string.Format(AppResources.SupportmailBodyNotLoggedIn)}"
};
// Send with attachment.

View file

@ -6,7 +6,6 @@ using TINK.Model;
using TINK.Model.Bikes;
using TINK.Model.Connector;
using TINK.Model.Services.CopriApi;
using TINK.ViewModel.Info;
using Xamarin.Forms;
namespace TINK.ViewModel.Contact
@ -15,6 +14,10 @@ namespace TINK.ViewModel.Contact
{
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Holds the current ui two letter ISO language name.
/// </summary>
private string UiIsoLanguageName { get; }
/// <summary> Holds value whether site caching is on or off.</summary>
bool IsSiteCachingOn { get; }
@ -71,6 +74,7 @@ namespace TINK.ViewModel.Contact
string feesResourcePath,
string bikesResourcePath,
bool isSiteCachingOn,
string uiIsoLangugageName,
Func<IQuery> queryProvider,
Action<IResourceUrls> updateUrlsAction)
{
@ -80,6 +84,7 @@ namespace TINK.ViewModel.Contact
IsSiteCachingOn = isSiteCachingOn;
QueryProvider = queryProvider;
UpdateUrlsAction = updateUrlsAction;
UiIsoLanguageName = uiIsoLangugageName;
}
/// <summary> Holds the name of the host.</summary>
@ -130,6 +135,13 @@ namespace TINK.ViewModel.Contact
: await Task.FromResult(ViewModelHelper.FromBody("No bikes instruction resource available. Resource path is null or empty."))
};
FAQ = new HtmlWebViewSource
{
Html = UiIsoLanguageName == "de"
? await ViewModelHelper.GetSource($"https://sharee.bike/faq/fahrrad-nutzung/", IsSiteCachingOn)
: await ViewModelHelper.GetSource($"https://sharee.bike/faq/bike-usage/", IsSiteCachingOn)
};
// Set state to idle.
IsIdle = true;
}
@ -138,6 +150,8 @@ namespace TINK.ViewModel.Contact
private HtmlWebViewSource typesOfBikesText;
private HtmlWebViewSource faq;
public HtmlWebViewSource RentBikeText
{
get => rentBikeText;
@ -157,5 +171,15 @@ namespace TINK.ViewModel.Contact
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(TypesOfBikesText)));
}
}
public HtmlWebViewSource FAQ
{
get => faq;
set
{
faq = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(FAQ)));
}
}
}
}