diff --git a/TransactionMobile.Maui.BusinessLogic/TransactionMobile.Maui.BusinessLogic.csproj b/TransactionMobile.Maui.BusinessLogic/TransactionMobile.Maui.BusinessLogic.csproj
index 22430ca4..524cd17e 100644
--- a/TransactionMobile.Maui.BusinessLogic/TransactionMobile.Maui.BusinessLogic.csproj
+++ b/TransactionMobile.Maui.BusinessLogic/TransactionMobile.Maui.BusinessLogic.csproj
@@ -28,6 +28,8 @@
+
+
diff --git a/TransactionMobile.Maui.BusinessLogic/UIServices/IDialogService.cs b/TransactionMobile.Maui.BusinessLogic/UIServices/IDialogService.cs
new file mode 100644
index 00000000..bf68ee55
--- /dev/null
+++ b/TransactionMobile.Maui.BusinessLogic/UIServices/IDialogService.cs
@@ -0,0 +1,44 @@
+namespace TransactionMobile.Maui.BusinessLogic.UIServices;
+
+public interface IDialogService
+{
+ #region Methods
+
+ Task ShowDialog(String title,
+ String message,
+ String acceptString);
+
+ Task ShowDialog(String title,
+ String message,
+ String acceptString,
+ String cancelString);
+
+ Task ShowErrorToast(String message,
+ Action? action,
+ String? actionButtonText,
+ TimeSpan? duration,
+ CancellationToken cancellationToken);
+
+ Task ShowInformationToast(String message,
+ Action? action,
+ String? actionButtonText,
+ TimeSpan? duration,
+ CancellationToken cancellationToken);
+
+ Task ShowPrompt(String title,
+ String message,
+ String acceptString,
+ String cancelString,
+ String placeHolder = "",
+ Int32 maxLength = -1,
+ Keyboard keyboard = null,
+ String initialValue = "");
+
+ Task ShowWarningToast(String message,
+ Action? action,
+ String? actionButtonText,
+ TimeSpan? duration,
+ CancellationToken cancellationToken);
+
+ #endregion
+}
\ No newline at end of file
diff --git a/TransactionMobile.Maui.BusinessLogic/ViewModels/HomePageViewModel.cs b/TransactionMobile.Maui.BusinessLogic/ViewModels/HomePageViewModel.cs
new file mode 100644
index 00000000..cd354890
--- /dev/null
+++ b/TransactionMobile.Maui.BusinessLogic/ViewModels/HomePageViewModel.cs
@@ -0,0 +1,92 @@
+namespace TransactionMobile.Maui.BusinessLogic.ViewModels;
+
+using Microsoft.AppCenter;
+using Microsoft.AppCenter.Distribute;
+using Models;
+using MvvmHelpers;
+using Services;
+using UIServices;
+
+public class HomePageViewModel : BaseViewModel
+{
+ #region Fields
+
+ private readonly IDialogService DialogService;
+
+ private readonly IMemoryCacheService MemoryCacheService;
+
+ #endregion
+
+ #region Constructors
+
+ public HomePageViewModel(IMemoryCacheService memoryCacheService,
+ IDialogService dialogService) {
+ this.MemoryCacheService = memoryCacheService;
+ this.DialogService = dialogService;
+ }
+
+ #endregion
+
+ #region Methods
+
+ public async Task Initialise(CancellationToken cancellationToken) {
+ this.MemoryCacheService.TryGetValue("Configuration", out Configuration configuration);
+
+ if (configuration.EnableAutoUpdates) {
+ await Distribute.SetEnabledAsync(true);
+ Distribute.CheckForUpdate();
+ Distribute.ReleaseAvailable = this.OnReleaseAvailable;
+ Distribute.UpdateTrack = UpdateTrack.Public;
+ }
+ else {
+ Distribute.DisableAutomaticCheckForUpdate();
+ }
+
+ if (this.IsIOS() == false) {
+ // TODO: Move the keys to config service
+ AppCenter.Configure("android=f920cc96-de56-42fe-87d4-b49105761205;" + "ios=dd940171-ca8c-4219-9851-f83769464f37;" +
+ "uwp=3ad27ea3-3f24-4579-a88a-530025bd00d4;" + "macos=244fdee2-f897-431a-8bab-5081fc90b329;");
+ AppCenter.Start(typeof(Distribute));
+ }
+ }
+
+ private Boolean IsIOS() => DeviceInfo.Current.Platform == DevicePlatform.iOS;
+
+ private Boolean OnReleaseAvailable(ReleaseDetails releaseDetails) {
+ // Look at releaseDetails public properties to get version information, release notes text or release notes URL
+ String versionName = releaseDetails.ShortVersion;
+ String versionCodeOrBuildNumber = releaseDetails.Version;
+ String releaseNotes = releaseDetails.ReleaseNotes;
+ Uri releaseNotesUrl = releaseDetails.ReleaseNotesUrl;
+
+ // custom dialog
+ String title = "Version " + versionName + " available!";
+ Task answer;
+
+ // On mandatory update, user can't postpone
+ if (releaseDetails.MandatoryUpdate) {
+ answer = this.DialogService.ShowDialog(title, releaseNotes, "Download and Install");
+ }
+ else {
+ answer = this.DialogService.ShowDialog(title, releaseNotes, "Download and Install", "Later");
+ }
+
+ answer.ContinueWith(task => {
+ // If mandatory or if answer was positive
+ if (releaseDetails.MandatoryUpdate || (task as Task).Result) {
+ // Notify SDK that user selected update
+ Distribute.NotifyUpdateAction(UpdateAction.Update);
+ }
+ else {
+ // Notify SDK that user selected postpone (for 1 day)
+ // This method call is ignored by the SDK if the update is mandatory
+ Distribute.NotifyUpdateAction(UpdateAction.Postpone);
+ }
+ });
+
+ // Return true if you're using your own dialog, false otherwise
+ return true;
+ }
+
+ #endregion
+}
\ No newline at end of file
diff --git a/TransactionMobile.Maui.BusinessLogic/ViewModels/LoginPageViewModel.cs b/TransactionMobile.Maui.BusinessLogic/ViewModels/LoginPageViewModel.cs
index 39f9430c..b2a20f3d 100644
--- a/TransactionMobile.Maui.BusinessLogic/ViewModels/LoginPageViewModel.cs
+++ b/TransactionMobile.Maui.BusinessLogic/ViewModels/LoginPageViewModel.cs
@@ -125,6 +125,7 @@ private async Task LoginCommandExecute()
this.MemoryCacheService.Set("IsLoggedIn", true);
await this.NavigationService.GoToHome();
+
}
private async void AccessTokenExpired(Object key,
diff --git a/TransactionMobile.Maui.UiTests/Features/Login.feature.cs b/TransactionMobile.Maui.UiTests/Features/Login.feature.cs
index 40b52487..33446da6 100644
--- a/TransactionMobile.Maui.UiTests/Features/Login.feature.cs
+++ b/TransactionMobile.Maui.UiTests/Features/Login.feature.cs
@@ -85,14 +85,12 @@ public virtual void FeatureBackground()
[NUnit.Framework.TestAttribute()]
[NUnit.Framework.DescriptionAttribute("Login as Merchant")]
- [NUnit.Framework.CategoryAttribute("PRTest")]
public void LoginAsMerchant()
{
- string[] tagsOfScenario = new string[] {
- "PRTest"};
+ string[] tagsOfScenario = ((string[])(null));
System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new System.Collections.Specialized.OrderedDictionary();
TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Login as Merchant", null, tagsOfScenario, argumentsOfScenario, featureTags);
-#line 7
+#line 6
this.ScenarioInitialize(scenarioInfo);
#line hidden
if ((TagHelper.ContainsIgnoreTag(tagsOfScenario) || TagHelper.ContainsIgnoreTag(featureTags)))
@@ -105,22 +103,22 @@ public void LoginAsMerchant()
#line 4
this.FeatureBackground();
#line hidden
-#line 8
+#line 7
testRunner.Given("I am on the Login Screen", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given ");
#line hidden
-#line 9
+#line 8
testRunner.And("the application is in training mode", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And ");
#line hidden
-#line 10
+#line 9
testRunner.When("I enter \'merchantuser@testmerchant1.co.uk\' as the Email Address", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When ");
#line hidden
-#line 11
+#line 10
testRunner.And("I enter \'123456\' as the Password", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And ");
#line hidden
-#line 12
+#line 11
testRunner.And("I tap on Login", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And ");
#line hidden
-#line 13
+#line 12
testRunner.Then("the Merchant Home Page is displayed", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then ");
#line hidden
}
@@ -129,9 +127,11 @@ public void LoginAsMerchant()
[NUnit.Framework.TestAttribute()]
[NUnit.Framework.DescriptionAttribute("Logout")]
+ [NUnit.Framework.CategoryAttribute("PRTest")]
public void Logout()
{
- string[] tagsOfScenario = ((string[])(null));
+ string[] tagsOfScenario = new string[] {
+ "PRTest"};
System.Collections.Specialized.OrderedDictionary argumentsOfScenario = new System.Collections.Specialized.OrderedDictionary();
TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Logout", null, tagsOfScenario, argumentsOfScenario, featureTags);
#line 15
diff --git a/TransactionMobile.Maui/Extensions/MauiAppBuilderExtensions.cs b/TransactionMobile.Maui/Extensions/MauiAppBuilderExtensions.cs
index 3640565e..407352e4 100644
--- a/TransactionMobile.Maui/Extensions/MauiAppBuilderExtensions.cs
+++ b/TransactionMobile.Maui/Extensions/MauiAppBuilderExtensions.cs
@@ -26,6 +26,7 @@
using TransactionMobile.Maui.Pages.Support;
using System;
using BusinessLogic.ViewModels.MyAccount;
+ using Pages.AppHome;
using Pages.MyAccount;
public static class MauiAppBuilderExtensions
@@ -182,7 +183,7 @@ public static MauiAppBuilder ConfigureTrainingServices(this MauiAppBuilder build
public static MauiAppBuilder ConfigureUIServices(this MauiAppBuilder builder)
{
- // builder.Services.AddSingleton();
+ builder.Services.AddSingleton();
builder.Services.AddSingleton();
builder.Services.AddSingleton();
return builder;
@@ -232,6 +233,8 @@ public static MauiAppBuilder ConfigureViewModels(this MauiAppBuilder builder)
builder.Services.AddTransient();
+ builder.Services.AddTransient();
+
return builder;
}
@@ -258,6 +261,8 @@ public static MauiAppBuilder ConfigurePages(this MauiAppBuilder builder)
builder.Services.AddTransient();
+ builder.Services.AddTransient();
+
return builder;
}
diff --git a/TransactionMobile.Maui/Pages/AppHome/HomePage.xaml.cs b/TransactionMobile.Maui/Pages/AppHome/HomePage.xaml.cs
index eb959471..8ca53558 100644
--- a/TransactionMobile.Maui/Pages/AppHome/HomePage.xaml.cs
+++ b/TransactionMobile.Maui/Pages/AppHome/HomePage.xaml.cs
@@ -1,13 +1,30 @@
namespace TransactionMobile.Maui.Pages.AppHome;
+using BusinessLogic.ViewModels;
+
public partial class HomePage : ContentPage
{
- public HomePage()
- {
- InitializeComponent();
- }
+ #region Constructors
+
+ public HomePage(HomePageViewModel vm) {
+ this.InitializeComponent();
+ this.BindingContext = vm;
+ }
+
+ #endregion
+
+ #region Properties
- protected override void OnAppearing() {
+ private HomePageViewModel viewModel => this.BindingContext as HomePageViewModel;
+
+ #endregion
+
+ #region Methods
+
+ protected override async void OnAppearing() {
base.OnAppearing();
+ await this.viewModel.Initialise(CancellationToken.None);
}
+
+ #endregion
}
\ No newline at end of file
diff --git a/TransactionMobile.Maui/Pages/Transactions/MobileTopup/MobileTopupSelectProductPage.xaml.cs b/TransactionMobile.Maui/Pages/Transactions/MobileTopup/MobileTopupSelectProductPage.xaml.cs
index 0ff595db..256366ea 100644
--- a/TransactionMobile.Maui/Pages/Transactions/MobileTopup/MobileTopupSelectProductPage.xaml.cs
+++ b/TransactionMobile.Maui/Pages/Transactions/MobileTopup/MobileTopupSelectProductPage.xaml.cs
@@ -6,49 +6,51 @@ namespace TransactionMobile.Maui.Pages.Transactions.MobileTopup;
public partial class MobileTopupSelectProductPage : ContentPage
{
- private MobileTopupSelectProductPageViewModel viewModel => BindingContext as MobileTopupSelectProductPageViewModel;
+ #region Constructors
- public MobileTopupSelectProductPage(MobileTopupSelectProductPageViewModel vm)
- {
- InitializeComponent();
- BindingContext = vm;
+ public MobileTopupSelectProductPage(MobileTopupSelectProductPageViewModel vm) {
+ this.InitializeComponent();
+ this.BindingContext = vm;
}
- protected override async void OnAppearing()
- {
+ #endregion
+
+ #region Properties
+
+ private MobileTopupSelectProductPageViewModel viewModel => this.BindingContext as MobileTopupSelectProductPageViewModel;
+
+ #endregion
+
+ #region Methods
+
+ protected override async void OnAppearing() {
base.OnAppearing();
- await viewModel.Initialise(CancellationToken.None);
- this.LoadProducts(viewModel);
+ await this.viewModel.Initialise(CancellationToken.None);
+ this.LoadProducts(this.viewModel);
}
- private void LoadProducts(MobileTopupSelectProductPageViewModel viewModel)
- {
+ private void LoadProducts(MobileTopupSelectProductPageViewModel viewModel) {
this.ProductsList.Clear();
-
+
Int32 rowCount = 0;
- foreach (ContractProductModel modelProduct in viewModel.Products)
- {
- Button button = new Button
- {
- Text = modelProduct.ProductDisplayText,
- HorizontalOptions = LayoutOptions.FillAndExpand,
- AutomationId = modelProduct.ProductDisplayText,
- };
+ foreach (ContractProductModel modelProduct in viewModel.Products) {
+ Button button = new Button {
+ Text = modelProduct.ProductDisplayText,
+ HorizontalOptions = LayoutOptions.FillAndExpand,
+ AutomationId = modelProduct.ProductDisplayText,
+ };
button.SetDynamicResource(VisualElement.StyleProperty, "MobileTopupButtonStyle");
- Binding commandParameter = new Binding()
- {
- Source = new ItemSelected
- {
- SelectedItem = modelProduct,
- SelectedItemIndex = rowCount
- }
- };
+ Binding commandParameter = new Binding {
+ Source = new ItemSelected {
+ SelectedItem = modelProduct,
+ SelectedItemIndex = rowCount
+ }
+ };
- Binding command = new Binding
- {
- Source = viewModel.ProductSelectedCommand
- };
+ Binding command = new Binding {
+ Source = viewModel.ProductSelectedCommand
+ };
button.SetBinding(Button.CommandProperty, command);
button.SetBinding(Button.CommandParameterProperty, commandParameter);
@@ -58,4 +60,6 @@ private void LoadProducts(MobileTopupSelectProductPageViewModel viewModel)
rowCount++;
}
}
+
+ #endregion
}
\ No newline at end of file
diff --git a/TransactionMobile.Maui/Platforms/Android/AndroidManifest.xml b/TransactionMobile.Maui/Platforms/Android/AndroidManifest.xml
index 5a333cd1..654ff35c 100644
--- a/TransactionMobile.Maui/Platforms/Android/AndroidManifest.xml
+++ b/TransactionMobile.Maui/Platforms/Android/AndroidManifest.xml
@@ -1,6 +1,16 @@
-
-
-
-
-
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TransactionMobile.Maui/TransactionMobile.Maui.csproj b/TransactionMobile.Maui/TransactionMobile.Maui.csproj
index e14274ac..62f07bcd 100644
--- a/TransactionMobile.Maui/TransactionMobile.Maui.csproj
+++ b/TransactionMobile.Maui/TransactionMobile.Maui.csproj
@@ -55,6 +55,8 @@
+
+
@@ -200,27 +202,35 @@
apk
- None
+ SdkOnly
+ link
- None
+ SdkOnly
+ link
- None
+ SdkOnly
+ link
- None
+ SdkOnly
+ link
- None
+ SdkOnly
+ link
- None
+ SdkOnly
+ link
- None
+ SdkOnly
+ link
- None
+ SdkOnly
+ link
diff --git a/TransactionMobile.Maui/UIServices/DialogService.cs b/TransactionMobile.Maui/UIServices/DialogService.cs
index 022f159b..2868f5e9 100644
--- a/TransactionMobile.Maui/UIServices/DialogService.cs
+++ b/TransactionMobile.Maui/UIServices/DialogService.cs
@@ -1,63 +1,75 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace TransactionMobile.Maui.UIServices
+namespace TransactionMobile.Maui.UIServices
{
- //using CommunityToolkit.Maui.Alerts;
- //using CommunityToolkit.Maui.Core;
-
- //public interface IDialogService
- //{
- // Task ShowInfoToast(String message,
- // Action? action,
- // String? actionButtonText,
- // TimeSpan? duration,
- // CancellationToken cancellationToken);
- //}
-
- //public class DialogService : IDialogService
- //{
- // public async Task ShowInfoToast(String message, Action? action, String? actionButtonText, TimeSpan? duration, CancellationToken cancellationToken)
- // {
- // await Application.Current.MainPage.DisplaySnackbar(message,
- // action,
- // actionButtonText,
- // duration,
- // SnackBarOptionsHelper.GetInfoSnackbarOptions());
- // }
- //}
-
- //public static class SnackBarOptionsHelper
- //{
- // public static SnackbarOptions GetInfoSnackbarOptions()
- // {
- // return new SnackbarOptions
- // {
- // BackgroundColor = Colors.Blue,
- // TextColor = Colors.White
- // };
- // }
-
- // public static SnackbarOptions GetWarningSnackbarOptions()
- // {
- // return new SnackbarOptions
- // {
- // BackgroundColor = Colors.Orange,
- // TextColor = Colors.White
- // };
- // }
-
- // public static SnackbarOptions GetErrorSnackbarOptions()
- // {
- // return new SnackbarOptions
- // {
- // BackgroundColor = Colors.Red,
- // TextColor = Colors.White
- // };
- // }
- //}
-
-}
+ using BusinessLogic.UIServices;
+ using CommunityToolkit.Maui.Alerts;
+
+ public class DialogService : IDialogService
+ {
+ #region Methods
+
+ public async Task ShowDialog(String title,
+ String message,
+ String cancelString) {
+ await Application.Current.MainPage.DisplayAlert(title, message, cancelString);
+ }
+
+ public async Task ShowDialog(String title,
+ String message,
+ String acceptString,
+ String cancelString) {
+ return await Application.Current.MainPage.DisplayAlert(title, message, acceptString, cancelString);
+ }
+
+ public async Task ShowErrorToast(String message,
+ Action action,
+ String actionButtonText,
+ TimeSpan? duration,
+ CancellationToken cancellationToken) {
+ await Application.Current.MainPage.DisplaySnackbar(message,
+ action,
+ actionButtonText,
+ duration,
+ SnackBarOptionsHelper.GetInfoSnackbarOptions,
+ cancellationToken);
+ }
+
+ public async Task ShowInformationToast(String message,
+ Action action,
+ String actionButtonText,
+ TimeSpan? duration,
+ CancellationToken cancellationToken) {
+ await Application.Current.MainPage.DisplaySnackbar(message,
+ action,
+ actionButtonText,
+ duration,
+ SnackBarOptionsHelper.GetInfoSnackbarOptions,
+ cancellationToken);
+ }
+
+ public async Task ShowPrompt(String title,
+ String message,
+ String acceptString,
+ String cancelString,
+ String placeHolder = "",
+ Int32 maxLength = -1,
+ Keyboard keyboard = null,
+ String initialValue = "") {
+ return await Application.Current.MainPage.DisplayPromptAsync(title, message, acceptString, cancelString, placeHolder, maxLength, keyboard, initialValue);
+ }
+
+ public async Task ShowWarningToast(String message,
+ Action action,
+ String actionButtonText,
+ TimeSpan? duration,
+ CancellationToken cancellationToken) {
+ await Application.Current.MainPage.DisplaySnackbar(message,
+ action,
+ actionButtonText,
+ duration,
+ SnackBarOptionsHelper.GetInfoSnackbarOptions,
+ cancellationToken);
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/TransactionMobile.Maui/UIServices/SnackBarOptionsHelper.cs b/TransactionMobile.Maui/UIServices/SnackBarOptionsHelper.cs
new file mode 100644
index 00000000..6c7cd866
--- /dev/null
+++ b/TransactionMobile.Maui/UIServices/SnackBarOptionsHelper.cs
@@ -0,0 +1,28 @@
+namespace TransactionMobile.Maui.UIServices;
+
+using CommunityToolkit.Maui.Core;
+
+public static class SnackBarOptionsHelper
+{
+ #region Properties
+
+ public static SnackbarOptions GetErrorSnackbarOptions =>
+ new SnackbarOptions {
+ BackgroundColor = Colors.Red,
+ TextColor = Colors.White,
+ };
+
+ public static SnackbarOptions GetInfoSnackbarOptions =>
+ new SnackbarOptions {
+ BackgroundColor = Colors.Blue,
+ TextColor = Colors.White
+ };
+
+ public static SnackbarOptions GetWarningSnackbarOptions =>
+ new SnackbarOptions {
+ BackgroundColor = Colors.Orange,
+ TextColor = Colors.White
+ };
+
+ #endregion
+}
\ No newline at end of file