Merge pull request #469 from dotnet-architecture/xamarin-settings

Replaced Plugin.Settings with unit testable SettingsService (mobile app)
This commit is contained in:
David Britch 2018-01-17 13:33:02 +00:00 committed by GitHub
commit aa27758607
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
81 changed files with 1036 additions and 770 deletions

View File

@ -1,11 +1,11 @@
using System.Globalization; using eShopOnContainers.Core.Models.Location;
using eShopOnContainers.Core.Helpers;
using eShopOnContainers.Services;
using eShopOnContainers.Core.ViewModels.Base;
using System.Threading.Tasks;
using eShopOnContainers.Core.Models.Location;
using eShopOnContainers.Core.Services.Location; using eShopOnContainers.Core.Services.Location;
using eShopOnContainers.Core.Services.Settings;
using eShopOnContainers.Core.ViewModels.Base;
using eShopOnContainers.Services;
using Plugin.Geolocator; using Plugin.Geolocator;
using System.Globalization;
using System.Threading.Tasks;
using Xamarin.Forms; using Xamarin.Forms;
using Xamarin.Forms.Xaml; using Xamarin.Forms.Xaml;
@ -14,6 +14,8 @@ namespace eShopOnContainers
{ {
public partial class App : Application public partial class App : Application
{ {
ISettingsService _settingsService;
public App() public App()
{ {
InitializeComponent(); InitializeComponent();
@ -27,9 +29,9 @@ namespace eShopOnContainers
private void InitApp() private void InitApp()
{ {
bool useMockServices = Settings.UseMocks; _settingsService = ViewModelLocator.Resolve<ISettingsService>();
if (!useMockServices) if (!_settingsService.UseMocks)
ViewModelLocator.UpdateDependencies(useMockServices); ViewModelLocator.UpdateDependencies(_settingsService.UseMocks);
} }
private Task InitNavigation() private Task InitNavigation()
@ -47,12 +49,12 @@ namespace eShopOnContainers
await InitNavigation(); await InitNavigation();
} }
if (Settings.AllowGpsLocation && !Settings.UseFakeLocation) if (_settingsService.AllowGpsLocation && !_settingsService.UseFakeLocation)
{ {
await GetGpsLocation(); await GetGpsLocation();
} }
if (!Settings.UseMocks && !string.IsNullOrEmpty(Settings.AuthAccessToken)) if (!_settingsService.UseMocks && !string.IsNullOrEmpty(_settingsService.AuthAccessToken))
{ {
await SendCurrentLocation(); await SendCurrentLocation();
} }
@ -76,12 +78,12 @@ namespace eShopOnContainers
var position = await locator.GetPositionAsync(); var position = await locator.GetPositionAsync();
Settings.Latitude = position.Latitude.ToString(); _settingsService.Latitude = position.Latitude.ToString();
Settings.Longitude = position.Longitude.ToString(); _settingsService.Longitude = position.Longitude.ToString();
} }
else else
{ {
Settings.AllowGpsLocation = false; _settingsService.AllowGpsLocation = false;
} }
} }
@ -89,13 +91,12 @@ namespace eShopOnContainers
{ {
var location = new Location var location = new Location
{ {
Latitude = double.Parse(Settings.Latitude, CultureInfo.InvariantCulture), Latitude = double.Parse(_settingsService.Latitude, CultureInfo.InvariantCulture),
Longitude = double.Parse(Settings.Longitude, CultureInfo.InvariantCulture) Longitude = double.Parse(_settingsService.Longitude, CultureInfo.InvariantCulture)
}; };
var locationService = ViewModelLocator.Resolve<ILocationService>(); var locationService = ViewModelLocator.Resolve<ILocationService>();
await locationService.UpdateUserLocation(location, await locationService.UpdateUserLocation(location, _settingsService.AuthAccessToken);
Settings.AuthAccessToken);
} }
} }
} }

View File

@ -1,6 +1,6 @@
using System.Linq; using eShopOnContainers.Core.Effects;
using System.Linq;
using Xamarin.Forms; using Xamarin.Forms;
using eShopOnContainers.Core.Effects;
namespace eShopOnContainers.Core.Behaviors namespace eShopOnContainers.Core.Behaviors
{ {

View File

@ -1,8 +1,4 @@
using System; using System.Threading.Tasks;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input; using System.Windows.Input;
using Xamarin.Forms; using Xamarin.Forms;

View File

@ -1,7 +1,7 @@
namespace eShopOnContainers.Core.Models.Marketing using System;
{
using System;
namespace eShopOnContainers.Core.Models.Marketing
{
public class Campaign public class Campaign
{ {
public int Id { get; set; } public int Id { get; set; }

View File

@ -1,7 +1,7 @@
namespace eShopOnContainers.Core.Models.Marketing using System;
{
using System;
namespace eShopOnContainers.Core.Models.Marketing
{
public class CampaignItem public class CampaignItem
{ {
public int Id { get; set; } public int Id { get; set; }

View File

@ -1,7 +1,7 @@
namespace eShopOnContainers.Core.Models.Marketing using System.Collections.Generic;
{
using System.Collections.Generic;
namespace eShopOnContainers.Core.Models.Marketing
{
public class CampaignRoot public class CampaignRoot
{ {
public int PageIndex { get; set; } public int PageIndex { get; set; }

View File

@ -1,6 +1,6 @@
using System; using Newtonsoft.Json;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using Newtonsoft.Json;
namespace eShopOnContainers.Core.Models.Orders namespace eShopOnContainers.Core.Models.Orders
{ {

View File

@ -2,18 +2,21 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using eShopOnContainers.Core.Services.RequestProvider; using eShopOnContainers.Core.Services.RequestProvider;
using eShopOnContainers.Core.Models.Basket; using eShopOnContainers.Core.Models.Basket;
using eShopOnContainers.Core.Helpers; using eShopOnContainers.Core.Services.FixUri;
namespace eShopOnContainers.Core.Services.Basket namespace eShopOnContainers.Core.Services.Basket
{ {
public class BasketService : IBasketService public class BasketService : IBasketService
{ {
private readonly IRequestProvider _requestProvider; private readonly IRequestProvider _requestProvider;
private readonly IFixUriService _fixUriService;
private const string ApiUrlBase = "api/v1/basket"; private const string ApiUrlBase = "api/v1/basket";
public BasketService(IRequestProvider requestProvider) public BasketService(IRequestProvider requestProvider, IFixUriService fixUriService)
{ {
_requestProvider = requestProvider; _requestProvider = requestProvider;
_fixUriService = fixUriService;
} }
public async Task<CustomerBasket> GetBasketAsync(string guidUser, string token) public async Task<CustomerBasket> GetBasketAsync(string guidUser, string token)
@ -28,8 +31,7 @@ namespace eShopOnContainers.Core.Services.Basket
CustomerBasket basket = CustomerBasket basket =
await _requestProvider.GetAsync<CustomerBasket>(uri, token); await _requestProvider.GetAsync<CustomerBasket>(uri, token);
ServicesHelper.FixBasketItemPictureUri(basket?.Items); _fixUriService.FixBasketItemPictureUri(basket?.Items);
return basket; return basket;
} }
@ -41,9 +43,7 @@ namespace eShopOnContainers.Core.Services.Basket
}; };
var uri = builder.ToString(); var uri = builder.ToString();
var result = await _requestProvider.PostAsync(uri, customerBasket, token); var result = await _requestProvider.PostAsync(uri, customerBasket, token);
return result; return result;
} }
@ -55,7 +55,6 @@ namespace eShopOnContainers.Core.Services.Basket
}; };
var uri = builder.ToString(); var uri = builder.ToString();
await _requestProvider.PostAsync(uri, basketCheckout, token); await _requestProvider.PostAsync(uri, basketCheckout, token);
} }
@ -67,7 +66,6 @@ namespace eShopOnContainers.Core.Services.Basket
}; };
var uri = builder.ToString(); var uri = builder.ToString();
await _requestProvider.DeleteAsync(uri, token); await _requestProvider.DeleteAsync(uri, token);
} }
} }

View File

@ -5,29 +5,28 @@ using eShopOnContainers.Core.Models.Catalog;
using eShopOnContainers.Core.Services.RequestProvider; using eShopOnContainers.Core.Services.RequestProvider;
using eShopOnContainers.Core.Extensions; using eShopOnContainers.Core.Extensions;
using System.Collections.Generic; using System.Collections.Generic;
using eShopOnContainers.Core.Helpers; using eShopOnContainers.Core.Services.FixUri;
namespace eShopOnContainers.Core.Services.Catalog namespace eShopOnContainers.Core.Services.Catalog
{ {
public class CatalogService : ICatalogService public class CatalogService : ICatalogService
{ {
private readonly IRequestProvider _requestProvider; private readonly IRequestProvider _requestProvider;
private readonly IFixUriService _fixUriService;
public CatalogService(IRequestProvider requestProvider) public CatalogService(IRequestProvider requestProvider, IFixUriService fixUriService)
{ {
_requestProvider = requestProvider; _requestProvider = requestProvider;
_fixUriService = fixUriService;
} }
public async Task<ObservableCollection<CatalogItem>> FilterAsync(int catalogBrandId, int catalogTypeId) public async Task<ObservableCollection<CatalogItem>> FilterAsync(int catalogBrandId, int catalogTypeId)
{ {
UriBuilder builder = new UriBuilder(GlobalSetting.Instance.CatalogEndpoint); UriBuilder builder = new UriBuilder(GlobalSetting.Instance.CatalogEndpoint);
builder.Path = string.Format("api/v1/catalog/items/type/{0}/brand/{1}", catalogTypeId, catalogBrandId); builder.Path = string.Format("api/v1/catalog/items/type/{0}/brand/{1}", catalogTypeId, catalogBrandId);
string uri = builder.ToString(); string uri = builder.ToString();
CatalogRoot catalog = CatalogRoot catalog = await _requestProvider.GetAsync<CatalogRoot>(uri);
await _requestProvider.GetAsync<CatalogRoot>(uri);
if (catalog?.Data != null) if (catalog?.Data != null)
return catalog?.Data.ToObservableCollection(); return catalog?.Data.ToObservableCollection();
@ -38,34 +37,27 @@ namespace eShopOnContainers.Core.Services.Catalog
public async Task<ObservableCollection<CatalogItem>> GetCatalogAsync() public async Task<ObservableCollection<CatalogItem>> GetCatalogAsync()
{ {
UriBuilder builder = new UriBuilder(GlobalSetting.Instance.CatalogEndpoint); UriBuilder builder = new UriBuilder(GlobalSetting.Instance.CatalogEndpoint);
builder.Path = "api/v1/catalog/items"; builder.Path = "api/v1/catalog/items";
string uri = builder.ToString(); string uri = builder.ToString();
CatalogRoot catalog = CatalogRoot catalog = await _requestProvider.GetAsync<CatalogRoot>(uri);
await _requestProvider.GetAsync<CatalogRoot>(uri);
if (catalog?.Data != null) if (catalog?.Data != null)
{ {
ServicesHelper.FixCatalogItemPictureUri(catalog?.Data); _fixUriService.FixCatalogItemPictureUri(catalog?.Data);
return catalog?.Data.ToObservableCollection(); return catalog?.Data.ToObservableCollection();
} }
else else
return new ObservableCollection<CatalogItem>(); return new ObservableCollection<CatalogItem>();
} }
public async Task<ObservableCollection<CatalogBrand>> GetCatalogBrandAsync() public async Task<ObservableCollection<CatalogBrand>> GetCatalogBrandAsync()
{ {
UriBuilder builder = new UriBuilder(GlobalSetting.Instance.CatalogEndpoint); UriBuilder builder = new UriBuilder(GlobalSetting.Instance.CatalogEndpoint);
builder.Path = "api/v1/catalog/catalogbrands"; builder.Path = "api/v1/catalog/catalogbrands";
string uri = builder.ToString(); string uri = builder.ToString();
IEnumerable<CatalogBrand> brands = IEnumerable<CatalogBrand> brands = await _requestProvider.GetAsync<IEnumerable<CatalogBrand>>(uri);
await _requestProvider.GetAsync<IEnumerable<CatalogBrand>>(uri);
if (brands != null) if (brands != null)
return brands?.ToObservableCollection(); return brands?.ToObservableCollection();
@ -76,18 +68,15 @@ namespace eShopOnContainers.Core.Services.Catalog
public async Task<ObservableCollection<CatalogType>> GetCatalogTypeAsync() public async Task<ObservableCollection<CatalogType>> GetCatalogTypeAsync()
{ {
UriBuilder builder = new UriBuilder(GlobalSetting.Instance.CatalogEndpoint); UriBuilder builder = new UriBuilder(GlobalSetting.Instance.CatalogEndpoint);
builder.Path = "api/v1/catalog/catalogtypes"; builder.Path = "api/v1/catalog/catalogtypes";
string uri = builder.ToString(); string uri = builder.ToString();
IEnumerable<CatalogType> types = IEnumerable<CatalogType> types = await _requestProvider.GetAsync<IEnumerable<CatalogType>>(uri);
await _requestProvider.GetAsync<IEnumerable<CatalogType>>(uri);
if (types != null) if (types != null)
return types.ToObservableCollection(); return types.ToObservableCollection();
else else
return new ObservableCollection<CatalogType>(); return new ObservableCollection<CatalogType>();
} }
} }
} }

View File

@ -0,0 +1,10 @@
namespace eShopOnContainers.Core.Services.Dependency
{
public class DependencyService : IDependencyService
{
public T Get<T>() where T : class
{
return Xamarin.Forms.DependencyService.Get<T>();
}
}
}

View File

@ -0,0 +1,7 @@
namespace eShopOnContainers.Core.Services.Dependency
{
public interface IDependencyService
{
T Get<T>() where T : class;
}
}

View File

@ -6,14 +6,22 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using eShopOnContainers.Core.Services.Settings;
namespace eShopOnContainers.Core.Helpers namespace eShopOnContainers.Core.Services.FixUri
{ {
public static class ServicesHelper public class FixUriService : IFixUriService
{ {
private static Regex IpRegex = new Regex(@"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b"); private readonly ISettingsService _settingsService;
public static void FixCatalogItemPictureUri(IEnumerable<CatalogItem> catalogItems) private Regex IpRegex = new Regex(@"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b");
public FixUriService(ISettingsService settingsService)
{
_settingsService = settingsService;
}
public void FixCatalogItemPictureUri(IEnumerable<CatalogItem> catalogItems)
{ {
if (catalogItems == null) if (catalogItems == null)
{ {
@ -23,12 +31,12 @@ namespace eShopOnContainers.Core.Helpers
try try
{ {
if (!ViewModelLocator.UseMockService if (!ViewModelLocator.UseMockService
&& Settings.UrlBase != GlobalSetting.DefaultEndpoint) && _settingsService.UrlBase != GlobalSetting.DefaultEndpoint)
{ {
foreach (var catalogItem in catalogItems) foreach (var catalogItem in catalogItems)
{ {
MatchCollection serverResult = IpRegex.Matches(catalogItem.PictureUri); MatchCollection serverResult = IpRegex.Matches(catalogItem.PictureUri);
MatchCollection localResult = IpRegex.Matches(Settings.UrlBase); MatchCollection localResult = IpRegex.Matches(_settingsService.UrlBase);
if (serverResult.Count != -1 && localResult.Count != -1) if (serverResult.Count != -1 && localResult.Count != -1)
{ {
@ -46,7 +54,7 @@ namespace eShopOnContainers.Core.Helpers
} }
} }
public static void FixBasketItemPictureUri(IEnumerable<BasketItem> basketItems) public void FixBasketItemPictureUri(IEnumerable<BasketItem> basketItems)
{ {
if (basketItems == null) if (basketItems == null)
{ {
@ -56,12 +64,12 @@ namespace eShopOnContainers.Core.Helpers
try try
{ {
if (!ViewModelLocator.UseMockService if (!ViewModelLocator.UseMockService
&& Settings.UrlBase != GlobalSetting.DefaultEndpoint) && _settingsService.UrlBase != GlobalSetting.DefaultEndpoint)
{ {
foreach (var basketItem in basketItems) foreach (var basketItem in basketItems)
{ {
MatchCollection serverResult = IpRegex.Matches(basketItem.PictureUrl); MatchCollection serverResult = IpRegex.Matches(basketItem.PictureUrl);
MatchCollection localResult = IpRegex.Matches(Settings.UrlBase); MatchCollection localResult = IpRegex.Matches(_settingsService.UrlBase);
if (serverResult.Count != -1 && localResult.Count != -1) if (serverResult.Count != -1 && localResult.Count != -1)
{ {
@ -78,7 +86,7 @@ namespace eShopOnContainers.Core.Helpers
} }
} }
public static void FixCampaignItemPictureUri(IEnumerable<CampaignItem> campaignItems) public void FixCampaignItemPictureUri(IEnumerable<CampaignItem> campaignItems)
{ {
if (campaignItems == null) if (campaignItems == null)
{ {
@ -88,12 +96,12 @@ namespace eShopOnContainers.Core.Helpers
try try
{ {
if (!ViewModelLocator.UseMockService if (!ViewModelLocator.UseMockService
&& Settings.UrlBase != GlobalSetting.DefaultEndpoint) && _settingsService.UrlBase != GlobalSetting.DefaultEndpoint)
{ {
foreach (var campaignItem in campaignItems) foreach (var campaignItem in campaignItems)
{ {
MatchCollection serverResult = IpRegex.Matches(campaignItem.PictureUri); MatchCollection serverResult = IpRegex.Matches(campaignItem.PictureUri);
MatchCollection localResult = IpRegex.Matches(Settings.UrlBase); MatchCollection localResult = IpRegex.Matches(_settingsService.UrlBase);
if (serverResult.Count != -1 && localResult.Count != -1) if (serverResult.Count != -1 && localResult.Count != -1)
{ {

View File

@ -0,0 +1,14 @@
using System.Collections.Generic;
using eShopOnContainers.Core.Models.Basket;
using eShopOnContainers.Core.Models.Catalog;
using eShopOnContainers.Core.Models.Marketing;
namespace eShopOnContainers.Core.Services.FixUri
{
public interface IFixUriService
{
void FixCatalogItemPictureUri(IEnumerable<CatalogItem> catalogItems);
void FixBasketItemPictureUri(IEnumerable<BasketItem> basketItems);
void FixCampaignItemPictureUri(IEnumerable<CampaignItem> campaignItems);
}
}

View File

@ -1,10 +1,9 @@
namespace eShopOnContainers.Core.Services.Location using System.Threading.Tasks;
{
using System.Threading.Tasks; namespace eShopOnContainers.Core.Services.Location
using Models.Location; {
public interface ILocationService public interface ILocationService
{ {
Task UpdateUserLocation(Location newLocReq, string token); Task UpdateUserLocation(eShopOnContainers.Core.Models.Location.Location newLocReq, string token);
} }
} }

View File

@ -1,10 +1,9 @@
namespace eShopOnContainers.Core.Services.Location using System;
{ using System.Threading.Tasks;
using System; using eShopOnContainers.Core.Services.RequestProvider;
using System.Threading.Tasks;
using Models.Location;
using RequestProvider;
namespace eShopOnContainers.Core.Services.Location
{
public class LocationService : ILocationService public class LocationService : ILocationService
{ {
private readonly IRequestProvider _requestProvider; private readonly IRequestProvider _requestProvider;
@ -14,7 +13,7 @@
_requestProvider = requestProvider; _requestProvider = requestProvider;
} }
public async Task UpdateUserLocation(Location newLocReq, string token) public async Task UpdateUserLocation(eShopOnContainers.Core.Models.Location.Location newLocReq, string token)
{ {
UriBuilder builder = new UriBuilder(GlobalSetting.Instance.LocationEndpoint); UriBuilder builder = new UriBuilder(GlobalSetting.Instance.LocationEndpoint);

View File

@ -1,9 +1,9 @@
using System; using eShopOnContainers.Core.Models.Marketing;
using System;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Threading.Tasks;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
using Xamarin.Forms; using Xamarin.Forms;
using eShopOnContainers.Core.Models.Marketing;
namespace eShopOnContainers.Core.Services.Marketing namespace eShopOnContainers.Core.Services.Marketing
{ {

View File

@ -1,37 +1,35 @@
using System; using eShopOnContainers.Core.Extensions;
using eShopOnContainers.Core.Models.Marketing;
using eShopOnContainers.Core.Services.FixUri;
using eShopOnContainers.Core.Services.RequestProvider;
using System;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Threading.Tasks; using System.Threading.Tasks;
using eShopOnContainers.Core.Models.Marketing;
using eShopOnContainers.Core.Services.RequestProvider;
using eShopOnContainers.Core.Extensions;
using eShopOnContainers.Core.Helpers;
namespace eShopOnContainers.Core.Services.Marketing namespace eShopOnContainers.Core.Services.Marketing
{ {
public class CampaignService : ICampaignService public class CampaignService : ICampaignService
{ {
private readonly IRequestProvider _requestProvider; private readonly IRequestProvider _requestProvider;
private readonly IFixUriService _fixUriService;
public CampaignService(IRequestProvider requestProvider) public CampaignService(IRequestProvider requestProvider, IFixUriService fixUriService)
{ {
_requestProvider = requestProvider; _requestProvider = requestProvider;
_fixUriService = fixUriService;
} }
public async Task<ObservableCollection<CampaignItem>> GetAllCampaignsAsync(string token) public async Task<ObservableCollection<CampaignItem>> GetAllCampaignsAsync(string token)
{ {
UriBuilder builder = new UriBuilder(GlobalSetting.Instance.MarketingEndpoint); UriBuilder builder = new UriBuilder(GlobalSetting.Instance.MarketingEndpoint);
builder.Path = "api/v1/campaigns/user"; builder.Path = "api/v1/campaigns/user";
string uri = builder.ToString(); string uri = builder.ToString();
CampaignRoot campaign = CampaignRoot campaign = await _requestProvider.GetAsync<CampaignRoot>(uri, token);
await _requestProvider.GetAsync<CampaignRoot>(uri, token);
if (campaign?.Data != null) if (campaign?.Data != null)
{ {
ServicesHelper.FixCampaignItemPictureUri(campaign?.Data); _fixUriService.FixCampaignItemPictureUri(campaign?.Data);
return campaign?.Data.ToObservableCollection(); return campaign?.Data.ToObservableCollection();
} }
@ -41,11 +39,8 @@ namespace eShopOnContainers.Core.Services.Marketing
public async Task<CampaignItem> GetCampaignByIdAsync(int campaignId, string token) public async Task<CampaignItem> GetCampaignByIdAsync(int campaignId, string token)
{ {
UriBuilder builder = new UriBuilder(GlobalSetting.Instance.MarketingEndpoint); UriBuilder builder = new UriBuilder(GlobalSetting.Instance.MarketingEndpoint);
builder.Path = $"api/v1/campaigns/{campaignId}"; builder.Path = $"api/v1/campaigns/{campaignId}";
string uri = builder.ToString(); string uri = builder.ToString();
return await _requestProvider.GetAsync<CampaignItem>(uri, token); return await _requestProvider.GetAsync<CampaignItem>(uri, token);
} }
} }

View File

@ -1,6 +1,6 @@
using System.Collections.ObjectModel; using eShopOnContainers.Core.Models.Marketing;
using System.Collections.ObjectModel;
using System.Threading.Tasks; using System.Threading.Tasks;
using eShopOnContainers.Core.Models.Marketing;
namespace eShopOnContainers.Core.Services.Marketing namespace eShopOnContainers.Core.Services.Marketing
{ {

View File

@ -1,7 +1,7 @@
using eShopOnContainers.Core.Helpers; using eShopOnContainers.Core.Services.Settings;
using eShopOnContainers.Core.ViewModels; using eShopOnContainers.Core.ViewModels;
using eShopOnContainers.Core.Views;
using eShopOnContainers.Core.ViewModels.Base; using eShopOnContainers.Core.ViewModels.Base;
using eShopOnContainers.Core.Views;
using System; using System;
using System.Globalization; using System.Globalization;
using System.Reflection; using System.Reflection;
@ -12,19 +12,26 @@ namespace eShopOnContainers.Services
{ {
public class NavigationService : INavigationService public class NavigationService : INavigationService
{ {
public ViewModelBase PreviousPageViewModel private readonly ISettingsService _settingsService;
{
get public ViewModelBase PreviousPageViewModel
{ {
var mainPage = Application.Current.MainPage as CustomNavigationView; get
var viewModel = mainPage.Navigation.NavigationStack[mainPage.Navigation.NavigationStack.Count - 2].BindingContext; {
return viewModel as ViewModelBase; var mainPage = Application.Current.MainPage as CustomNavigationView;
} var viewModel = mainPage.Navigation.NavigationStack[mainPage.Navigation.NavigationStack.Count - 2].BindingContext;
} return viewModel as ViewModelBase;
}
}
public NavigationService(ISettingsService settingsService)
{
_settingsService = settingsService;
}
public Task InitializeAsync() public Task InitializeAsync()
{ {
if(string.IsNullOrEmpty(Settings.AuthAccessToken)) if (string.IsNullOrEmpty(_settingsService.AuthAccessToken))
return NavigateToAsync<LoginViewModel>(); return NavigateToAsync<LoginViewModel>();
else else
return NavigateToAsync<MainViewModel>(); return NavigateToAsync<MainViewModel>();
@ -78,7 +85,7 @@ namespace eShopOnContainers.Services
Application.Current.MainPage = new CustomNavigationView(page); Application.Current.MainPage = new CustomNavigationView(page);
} }
else else
{ {
var navigationPage = Application.Current.MainPage as CustomNavigationView; var navigationPage = Application.Current.MainPage as CustomNavigationView;
if (navigationPage != null) if (navigationPage != null)
{ {
@ -93,25 +100,25 @@ namespace eShopOnContainers.Services
await (page.BindingContext as ViewModelBase).InitializeAsync(parameter); await (page.BindingContext as ViewModelBase).InitializeAsync(parameter);
} }
private Type GetPageTypeForViewModel(Type viewModelType) private Type GetPageTypeForViewModel(Type viewModelType)
{ {
var viewName = viewModelType.FullName.Replace("Model", string.Empty); var viewName = viewModelType.FullName.Replace("Model", string.Empty);
var viewModelAssemblyName = viewModelType.GetTypeInfo().Assembly.FullName; var viewModelAssemblyName = viewModelType.GetTypeInfo().Assembly.FullName;
var viewAssemblyName = string.Format(CultureInfo.InvariantCulture, "{0}, {1}", viewName, viewModelAssemblyName); var viewAssemblyName = string.Format(CultureInfo.InvariantCulture, "{0}, {1}", viewName, viewModelAssemblyName);
var viewType = Type.GetType(viewAssemblyName); var viewType = Type.GetType(viewAssemblyName);
return viewType; return viewType;
} }
private Page CreatePage(Type viewModelType, object parameter) private Page CreatePage(Type viewModelType, object parameter)
{ {
Type pageType = GetPageTypeForViewModel(viewModelType); Type pageType = GetPageTypeForViewModel(viewModelType);
if (pageType == null) if (pageType == null)
{ {
throw new Exception($"Cannot locate page type for {viewModelType}"); throw new Exception($"Cannot locate page type for {viewModelType}");
} }
Page page = Activator.CreateInstance(pageType) as Page; Page page = Activator.CreateInstance(pageType) as Page;
return page; return page;
} }
} }
} }

View File

@ -2,7 +2,6 @@
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace eShopOnContainers.Core.Services.Order namespace eShopOnContainers.Core.Services.Order
{ {
public interface IOrderService public interface IOrderService

View File

@ -1,10 +1,9 @@
using eShopOnContainers.Core.Models.Basket; using eShopOnContainers.Core.Models.Basket;
using eShopOnContainers.Core.Models.Orders;
using eShopOnContainers.Core.Services.RequestProvider; using eShopOnContainers.Core.Services.RequestProvider;
using System; using System;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
using eShopOnContainers.Core.Models.Orders;
namespace eShopOnContainers.Core.Services.Order namespace eShopOnContainers.Core.Services.Order
{ {

View File

@ -1,9 +1,5 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http; using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace eShopOnContainers.Core.Services.RequestProvider namespace eShopOnContainers.Core.Services.RequestProvider
{ {

View File

@ -2,11 +2,11 @@
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Converters; using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization; using Newtonsoft.Json.Serialization;
using System;
using System.Net; using System.Net;
using System.Net.Http; using System.Net.Http;
using System.Net.Http.Headers; using System.Net.Http.Headers;
using System.Threading.Tasks; using System.Threading.Tasks;
using System;
namespace eShopOnContainers.Core.Services.RequestProvider namespace eShopOnContainers.Core.Services.RequestProvider
{ {

View File

@ -0,0 +1,14 @@
namespace eShopOnContainers.Core.Services.Settings
{
public interface ISettingsService
{
string AuthAccessToken { get; set; }
string AuthIdToken { get; set; }
bool UseMocks { get; set; }
string UrlBase { get; set; }
bool UseFakeLocation { get; set; }
string Latitude { get; set; }
string Longitude { get; set; }
bool AllowGpsLocation { get; set; }
}
}

View File

@ -0,0 +1,13 @@
namespace eShopOnContainers.Core.Services.Settings
{
public interface ISettingsServiceImplementation
{
bool GetValueOrDefault(string key, bool defaultValue);
string GetValueOrDefault(string key, string defaultValue);
bool AddOrUpdateValue(string key, bool value);
bool AddOrUpdateValue(string key, string value);
void Remove(string key);
}
}

View File

@ -1,21 +1,19 @@
using Plugin.Settings; using eShopOnContainers.Core.Services.Dependency;
using Plugin.Settings.Abstractions;
namespace eShopOnContainers.Core.Helpers namespace eShopOnContainers.Core.Services.Settings
{ {
/// <summary> public class SettingsService : ISettingsService
/// This is the Settings static class that can be used in your Core solution or in any
/// of your client applications. All settings are laid out the same exact way with getters
/// and setters.
/// </summary>
public static class Settings
{ {
private static ISettings AppSettings private readonly ISettingsServiceImplementation _settingsService;
ISettingsServiceImplementation AppSettings
{ {
get get { return _settingsService; }
{ }
return CrossSettings.Current;
} public SettingsService(IDependencyService dependencyService)
{
_settingsService = dependencyService.Get<ISettingsServiceImplementation>();
} }
#region Setting Constants #region Setting Constants
@ -28,60 +26,60 @@ namespace eShopOnContainers.Core.Helpers
private const string IdLatitude = "latitude"; private const string IdLatitude = "latitude";
private const string IdLongitude = "longitude"; private const string IdLongitude = "longitude";
private const string IdAllowGpsLocation = "allow_gps_location"; private const string IdAllowGpsLocation = "allow_gps_location";
private static readonly string AccessTokenDefault = string.Empty; private readonly string AccessTokenDefault = string.Empty;
private static readonly string IdTokenDefault = string.Empty; private readonly string IdTokenDefault = string.Empty;
private static readonly bool UseMocksDefault = true; private readonly bool UseMocksDefault = true;
private static readonly bool UseFakeLocationDefault = false; private readonly bool UseFakeLocationDefault = false;
private static readonly bool AllowGpsLocationDefault = false; private readonly bool AllowGpsLocationDefault = false;
private static readonly double FakeLatitudeDefault = 47.604610d; private readonly double FakeLatitudeDefault = 47.604610d;
private static readonly double FakeLongitudeDefault = -122.315752d; private readonly double FakeLongitudeDefault = -122.315752d;
private static readonly string UrlBaseDefault = GlobalSetting.Instance.BaseEndpoint; private readonly string UrlBaseDefault = GlobalSetting.Instance.BaseEndpoint;
#endregion #endregion
public static string AuthAccessToken public string AuthAccessToken
{ {
get => AppSettings.GetValueOrDefault(AccessToken, AccessTokenDefault); get => AppSettings.GetValueOrDefault(AccessToken, AccessTokenDefault);
set => AppSettings.AddOrUpdateValue(AccessToken, value); set => AppSettings.AddOrUpdateValue(AccessToken, value);
} }
public static string AuthIdToken public string AuthIdToken
{ {
get => AppSettings.GetValueOrDefault(IdToken, IdTokenDefault); get => AppSettings.GetValueOrDefault(IdToken, IdTokenDefault);
set => AppSettings.AddOrUpdateValue(IdToken, value); set => AppSettings.AddOrUpdateValue(IdToken, value);
} }
public static bool UseMocks public bool UseMocks
{ {
get => AppSettings.GetValueOrDefault(IdUseMocks, UseMocksDefault); get => AppSettings.GetValueOrDefault(IdUseMocks, UseMocksDefault);
set => AppSettings.AddOrUpdateValue(IdUseMocks, value); set => AppSettings.AddOrUpdateValue(IdUseMocks, value);
} }
public static string UrlBase public string UrlBase
{ {
get => AppSettings.GetValueOrDefault(IdUrlBase, UrlBaseDefault); get => AppSettings.GetValueOrDefault(IdUrlBase, UrlBaseDefault);
set => AppSettings.AddOrUpdateValue(IdUrlBase, value); set => AppSettings.AddOrUpdateValue(IdUrlBase, value);
} }
public static bool UseFakeLocation public bool UseFakeLocation
{ {
get => AppSettings.GetValueOrDefault(IdUseFakeLocation, UseFakeLocationDefault); get => AppSettings.GetValueOrDefault(IdUseFakeLocation, UseFakeLocationDefault);
set => AppSettings.AddOrUpdateValue(IdUseFakeLocation, value); set => AppSettings.AddOrUpdateValue(IdUseFakeLocation, value);
} }
public static string Latitude public string Latitude
{ {
get => AppSettings.GetValueOrDefault(IdLatitude, FakeLatitudeDefault.ToString()); get => AppSettings.GetValueOrDefault(IdLatitude, FakeLatitudeDefault.ToString());
set => AppSettings.AddOrUpdateValue(IdLatitude, value); set => AppSettings.AddOrUpdateValue(IdLatitude, value);
} }
public static string Longitude public string Longitude
{ {
get => AppSettings.GetValueOrDefault(IdLongitude, FakeLongitudeDefault.ToString()); get => AppSettings.GetValueOrDefault(IdLongitude, FakeLongitudeDefault.ToString());
set => AppSettings.AddOrUpdateValue(IdLongitude, value); set => AppSettings.AddOrUpdateValue(IdLongitude, value);
} }
public static bool AllowGpsLocation public bool AllowGpsLocation
{ {
get => AppSettings.GetValueOrDefault(IdAllowGpsLocation, AllowGpsLocationDefault); get => AppSettings.GetValueOrDefault(IdAllowGpsLocation, AllowGpsLocationDefault);
set => AppSettings.AddOrUpdateValue(IdAllowGpsLocation, value); set => AppSettings.AddOrUpdateValue(IdAllowGpsLocation, value);

View File

@ -1,5 +1,5 @@
using System; using eShopOnContainers.Core.Models.User;
using eShopOnContainers.Core.Models.User; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace eShopOnContainers.Core.Services.User namespace eShopOnContainers.Core.Services.User
@ -29,7 +29,6 @@ namespace eShopOnContainers.Core.Services.User
public async Task<UserInfo> GetUserInfoAsync(string authToken) public async Task<UserInfo> GetUserInfoAsync(string authToken)
{ {
await Task.Delay(500); await Task.Delay(500);
return MockUserInfo; return MockUserInfo;
} }
} }

View File

@ -1,7 +1,7 @@
using eShopOnContainers.Core.Services.RequestProvider; using eShopOnContainers.Core.Models.User;
using eShopOnContainers.Core.Services.RequestProvider;
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using eShopOnContainers.Core.Models.User;
namespace eShopOnContainers.Core.Services.User namespace eShopOnContainers.Core.Services.User
{ {
@ -17,12 +17,8 @@ namespace eShopOnContainers.Core.Services.User
public async Task<UserInfo> GetUserInfoAsync(string authToken) public async Task<UserInfo> GetUserInfoAsync(string authToken)
{ {
UriBuilder builder = new UriBuilder(GlobalSetting.Instance.UserInfoEndpoint); UriBuilder builder = new UriBuilder(GlobalSetting.Instance.UserInfoEndpoint);
string uri = builder.ToString(); string uri = builder.ToString();
var userInfo = await _requestProvider.GetAsync<UserInfo>(uri, authToken);
var userInfo =
await _requestProvider.GetAsync<UserInfo>(uri, authToken);
return userInfo; return userInfo;
} }
} }

View File

@ -1,4 +1,4 @@
using eShopOnContainers.Core.Helpers; using eShopOnContainers.Core.Services.Settings;
using eShopOnContainers.Services; using eShopOnContainers.Services;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -29,7 +29,7 @@ namespace eShopOnContainers.Core.ViewModels.Base
{ {
DialogService = ViewModelLocator.Resolve<IDialogService>(); DialogService = ViewModelLocator.Resolve<IDialogService>();
NavigationService = ViewModelLocator.Resolve<INavigationService>(); NavigationService = ViewModelLocator.Resolve<INavigationService>();
GlobalSetting.Instance.BaseEndpoint = Settings.UrlBase; GlobalSetting.Instance.BaseEndpoint = ViewModelLocator.Resolve<ISettingsService>().UrlBase;
} }
public virtual Task InitializeAsync(object navigationData) public virtual Task InitializeAsync(object navigationData)

View File

@ -1,18 +1,21 @@
using eShopOnContainers.Services; using eShopOnContainers.Core.Services.Basket;
using eShopOnContainers.Core.Services.Catalog;
using eShopOnContainers.Core.Services.Dependency;
using eShopOnContainers.Core.Services.FixUri;
using eShopOnContainers.Core.Services.Identity;
using eShopOnContainers.Core.Services.Location;
using eShopOnContainers.Core.Services.Marketing;
using eShopOnContainers.Core.Services.OpenUrl;
using eShopOnContainers.Core.Services.Order;
using eShopOnContainers.Core.Services.RequestProvider;
using eShopOnContainers.Core.Services.Settings;
using eShopOnContainers.Core.Services.User;
using eShopOnContainers.Services;
using System; using System;
using System.Globalization; using System.Globalization;
using System.Reflection; using System.Reflection;
using eShopOnContainers.Core.Services.Catalog;
using eShopOnContainers.Core.Services.OpenUrl;
using eShopOnContainers.Core.Services.RequestProvider;
using eShopOnContainers.Core.Services.Basket;
using eShopOnContainers.Core.Services.Identity;
using eShopOnContainers.Core.Services.Order;
using eShopOnContainers.Core.Services.User;
using Xamarin.Forms;
using eShopOnContainers.Core.Services.Location;
using eShopOnContainers.Core.Services.Marketing;
using TinyIoC; using TinyIoC;
using Xamarin.Forms;
namespace eShopOnContainers.Core.ViewModels.Base namespace eShopOnContainers.Core.ViewModels.Base
{ {
@ -57,6 +60,9 @@ namespace eShopOnContainers.Core.ViewModels.Base
_container.Register<IOpenUrlService, OpenUrlService>(); _container.Register<IOpenUrlService, OpenUrlService>();
_container.Register<IIdentityService, IdentityService>(); _container.Register<IIdentityService, IdentityService>();
_container.Register<IRequestProvider, RequestProvider>(); _container.Register<IRequestProvider, RequestProvider>();
_container.Register<IDependencyService, Services.Dependency.DependencyService>();
_container.Register<ISettingsService, SettingsService>().AsSingleton();
_container.Register<IFixUriService, FixUriService>().AsSingleton();
_container.Register<ILocationService, LocationService>().AsSingleton(); _container.Register<ILocationService, LocationService>().AsSingleton();
_container.Register<ICatalogService, CatalogMockService>().AsSingleton(); _container.Register<ICatalogService, CatalogMockService>().AsSingleton();
_container.Register<IBasketService, BasketMockService>().AsSingleton(); _container.Register<IBasketService, BasketMockService>().AsSingleton();
@ -90,6 +96,11 @@ namespace eShopOnContainers.Core.ViewModels.Base
} }
} }
public static void RegisterSingleton<TInterface, T>() where TInterface : class where T : class, TInterface
{
_container.Register<TInterface, T>().AsSingleton();
}
public static T Resolve<T>() where T : class public static T Resolve<T>() where T : class
{ {
return _container.Resolve<T>(); return _container.Resolve<T>();

View File

@ -1,7 +1,7 @@
using eShopOnContainers.Core.Helpers; using eShopOnContainers.Core.Models.Basket;
using eShopOnContainers.Core.Models.Basket;
using eShopOnContainers.Core.Models.Catalog; using eShopOnContainers.Core.Models.Catalog;
using eShopOnContainers.Core.Services.Basket; using eShopOnContainers.Core.Services.Basket;
using eShopOnContainers.Core.Services.Settings;
using eShopOnContainers.Core.Services.User; using eShopOnContainers.Core.Services.User;
using eShopOnContainers.Core.ViewModels.Base; using eShopOnContainers.Core.ViewModels.Base;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
@ -18,13 +18,16 @@ namespace eShopOnContainers.Core.ViewModels
private ObservableCollection<BasketItem> _basketItems; private ObservableCollection<BasketItem> _basketItems;
private decimal _total; private decimal _total;
private ISettingsService _settingsService;
private IBasketService _basketService; private IBasketService _basketService;
private IUserService _userService; private IUserService _userService;
public BasketViewModel( public BasketViewModel(
ISettingsService settingsService,
IBasketService basketService, IBasketService basketService,
IUserService userService) IUserService userService)
{ {
_settingsService = settingsService;
_basketService = basketService; _basketService = basketService;
_userService = userService; _userService = userService;
} }
@ -48,7 +51,7 @@ namespace eShopOnContainers.Core.ViewModels
RaisePropertyChanged(() => BasketItems); RaisePropertyChanged(() => BasketItems);
} }
} }
public decimal Total public decimal Total
{ {
get { return _total; } get { return _total; }
@ -68,7 +71,7 @@ namespace eShopOnContainers.Core.ViewModels
if (BasketItems == null) if (BasketItems == null)
BasketItems = new ObservableCollection<BasketItem>(); BasketItems = new ObservableCollection<BasketItem>();
var authToken = Settings.AuthAccessToken; var authToken = _settingsService.AuthAccessToken;
var userInfo = await _userService.GetUserInfoAsync(authToken); var userInfo = await _userService.GetUserInfoAsync(authToken);
// Update Basket // Update Basket
@ -93,7 +96,7 @@ namespace eShopOnContainers.Core.ViewModels
await AddCatalogItemAsync(arg); await AddCatalogItemAsync(arg);
}); });
await base.InitializeAsync(navigationData); await base.InitializeAsync(navigationData);
} }
@ -114,16 +117,13 @@ namespace eShopOnContainers.Core.ViewModels
private async Task AddItemAsync(BasketItem item) private async Task AddItemAsync(BasketItem item)
{ {
BadgeCount++; BadgeCount++;
await AddBasketItemAsync(item); await AddBasketItemAsync(item);
RaisePropertyChanged(() => BasketItems); RaisePropertyChanged(() => BasketItems);
} }
private async Task AddBasketItemAsync(BasketItem item) private async Task AddBasketItemAsync(BasketItem item)
{ {
BasketItems.Add(item); BasketItems.Add(item);
await ReCalculateTotalAsync(); await ReCalculateTotalAsync();
} }
@ -141,12 +141,12 @@ namespace eShopOnContainers.Core.ViewModels
Total += (orderItem.Quantity * orderItem.UnitPrice); Total += (orderItem.Quantity * orderItem.UnitPrice);
} }
var authToken = Settings.AuthAccessToken; var authToken = _settingsService.AuthAccessToken;
var userInfo = await _userService.GetUserInfoAsync(authToken); var userInfo = await _userService.GetUserInfoAsync(authToken);
await _basketService.UpdateBasketAsync(new CustomerBasket await _basketService.UpdateBasketAsync(new CustomerBasket
{ {
BuyerId = userInfo.UserId, BuyerId = userInfo.UserId,
Items = BasketItems.ToList() Items = BasketItems.ToList()
}, authToken); }, authToken);
} }

View File

@ -1,21 +1,26 @@
using System.Threading.Tasks; using eShopOnContainers.Core.Models.Marketing;
using eShopOnContainers.Core.Services.Marketing;
using eShopOnContainers.Core.Services.Settings;
using eShopOnContainers.Core.ViewModels.Base;
using System.Threading.Tasks;
using System.Windows.Input; using System.Windows.Input;
using Xamarin.Forms; using Xamarin.Forms;
using eShopOnContainers.Core.ViewModels.Base;
using eShopOnContainers.Core.Helpers;
using eShopOnContainers.Core.Models.Marketing;
using eShopOnContainers.Core.Services.Marketing;
namespace eShopOnContainers.Core.ViewModels namespace eShopOnContainers.Core.ViewModels
{ {
public class CampaignDetailsViewModel : ViewModelBase public class CampaignDetailsViewModel : ViewModelBase
{ {
private CampaignItem _campaign; private readonly ISettingsService _settingsService;
private bool _isDetailsSite;
private readonly ICampaignService _campaignService; private readonly ICampaignService _campaignService;
public CampaignDetailsViewModel(ICampaignService campaignService) private CampaignItem _campaign;
private bool _isDetailsSite;
public ICommand EnableDetailsSiteCommand => new Command(EnableDetailsSite);
public CampaignDetailsViewModel(ISettingsService settingsService, ICampaignService campaignService)
{ {
_settingsService = settingsService;
_campaignService = campaignService; _campaignService = campaignService;
} }
@ -44,16 +49,12 @@ namespace eShopOnContainers.Core.ViewModels
if (navigationData is int) if (navigationData is int)
{ {
IsBusy = true; IsBusy = true;
// Get campaign by id // Get campaign by id
Campaign = await _campaignService.GetCampaignByIdAsync((int)navigationData, Settings.AuthAccessToken); Campaign = await _campaignService.GetCampaignByIdAsync((int)navigationData, _settingsService.AuthAccessToken);
IsBusy = false; IsBusy = false;
} }
} }
public ICommand EnableDetailsSiteCommand => new Command(EnableDetailsSite);
private void EnableDetailsSite() private void EnableDetailsSite()
{ {
IsDetailsSite = true; IsDetailsSite = true;

View File

@ -1,21 +1,24 @@
using System.Threading.Tasks; using eShopOnContainers.Core.Models.Marketing;
using eShopOnContainers.Core.Services.Marketing;
using eShopOnContainers.Core.Services.Settings;
using eShopOnContainers.Core.ViewModels.Base;
using System.Collections.ObjectModel;
using System.Threading.Tasks;
using System.Windows.Input; using System.Windows.Input;
using Xamarin.Forms; using Xamarin.Forms;
using System.Collections.ObjectModel;
using eShopOnContainers.Core.Models.Marketing;
using eShopOnContainers.Core.Services.Marketing;
using eShopOnContainers.Core.ViewModels.Base;
using eShopOnContainers.Core.Helpers;
namespace eShopOnContainers.Core.ViewModels namespace eShopOnContainers.Core.ViewModels
{ {
public class CampaignViewModel : ViewModelBase public class CampaignViewModel : ViewModelBase
{ {
private ObservableCollection<CampaignItem> _campaigns; private readonly ISettingsService _settingsService;
private readonly ICampaignService _campaignService; private readonly ICampaignService _campaignService;
public CampaignViewModel(ICampaignService campaignService) private ObservableCollection<CampaignItem> _campaigns;
public CampaignViewModel(ISettingsService settingsService, ICampaignService campaignService)
{ {
_settingsService = settingsService;
_campaignService = campaignService; _campaignService = campaignService;
} }
@ -34,10 +37,8 @@ namespace eShopOnContainers.Core.ViewModels
public override async Task InitializeAsync(object navigationData) public override async Task InitializeAsync(object navigationData)
{ {
IsBusy = true; IsBusy = true;
// Get campaigns by user // Get campaigns by user
Campaigns = await _campaignService.GetAllCampaignsAsync(Settings.AuthAccessToken); Campaigns = await _campaignService.GetAllCampaignsAsync(_settingsService.AuthAccessToken);
IsBusy = false; IsBusy = false;
} }

View File

@ -1,10 +1,10 @@
using System.Threading.Tasks; using eShopOnContainers.Core.Models.Catalog;
using eShopOnContainers.Core.Services.Catalog;
using eShopOnContainers.Core.ViewModels.Base; using eShopOnContainers.Core.ViewModels.Base;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using Xamarin.Forms; using System.Threading.Tasks;
using eShopOnContainers.Core.Models.Catalog;
using eShopOnContainers.Core.Services.Catalog;
using System.Windows.Input; using System.Windows.Input;
using Xamarin.Forms;
namespace eShopOnContainers.Core.ViewModels namespace eShopOnContainers.Core.ViewModels
{ {

View File

@ -1,18 +1,18 @@
using eShopOnContainers.Core.Models.Navigation; using eShopOnContainers.Core.Models.Basket;
using eShopOnContainers.Core.ViewModels.Base; using eShopOnContainers.Core.Models.Navigation;
using System.Windows.Input;
using Xamarin.Forms;
using System.Threading.Tasks;
using eShopOnContainers.Core.Models.Orders; using eShopOnContainers.Core.Models.Orders;
using System; using eShopOnContainers.Core.Models.User;
using System.Collections.ObjectModel;
using eShopOnContainers.Core.Models.Basket;
using System.Collections.Generic;
using eShopOnContainers.Core.Services.Basket; using eShopOnContainers.Core.Services.Basket;
using eShopOnContainers.Core.Services.Order; using eShopOnContainers.Core.Services.Order;
using eShopOnContainers.Core.Helpers; using eShopOnContainers.Core.Services.Settings;
using eShopOnContainers.Core.Services.User; using eShopOnContainers.Core.Services.User;
using eShopOnContainers.Core.Models.User; using eShopOnContainers.Core.ViewModels.Base;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Threading.Tasks;
using System.Windows.Input;
using Xamarin.Forms;
namespace eShopOnContainers.Core.ViewModels namespace eShopOnContainers.Core.ViewModels
{ {
@ -20,17 +20,20 @@ namespace eShopOnContainers.Core.ViewModels
{ {
private ObservableCollection<BasketItem> _orderItems; private ObservableCollection<BasketItem> _orderItems;
private Order _order; private Order _order;
private Address _shippingAddress; private Address _shippingAddress;
private ISettingsService _settingsService;
private IBasketService _basketService; private IBasketService _basketService;
private IOrderService _orderService; private IOrderService _orderService;
private IUserService _userService; private IUserService _userService;
public CheckoutViewModel( public CheckoutViewModel(
ISettingsService settingsService,
IBasketService basketService, IBasketService basketService,
IOrderService orderService, IOrderService orderService,
IUserService userService) IUserService userService)
{ {
_settingsService = settingsService;
_basketService = basketService; _basketService = basketService;
_orderService = orderService; _orderService = orderService;
_userService = userService; _userService = userService;
@ -79,7 +82,7 @@ namespace eShopOnContainers.Core.ViewModels
OrderItems = orderItems; OrderItems = orderItems;
var authToken = Settings.AuthAccessToken; var authToken = _settingsService.AuthAccessToken;
var userInfo = await _userService.GetUserInfoAsync(authToken); var userInfo = await _userService.GetUserInfoAsync(authToken);
// Create Shipping Address // Create Shipping Address
@ -98,7 +101,7 @@ namespace eShopOnContainers.Core.ViewModels
{ {
CardNumber = userInfo?.CardNumber, CardNumber = userInfo?.CardNumber,
CardHolderName = userInfo?.CardHolder, CardHolderName = userInfo?.CardHolder,
CardType = new CardType { Id = 3, Name = "MasterCard" }, CardType = new CardType { Id = 3, Name = "MasterCard" },
SecurityNumber = userInfo?.CardSecurityNumber SecurityNumber = userInfo?.CardSecurityNumber
}; };
@ -117,12 +120,12 @@ namespace eShopOnContainers.Core.ViewModels
ShippingState = _shippingAddress.State, ShippingState = _shippingAddress.State,
ShippingCountry = _shippingAddress.Country, ShippingCountry = _shippingAddress.Country,
ShippingStreet = _shippingAddress.Street, ShippingStreet = _shippingAddress.Street,
ShippingCity = _shippingAddress.City, ShippingCity = _shippingAddress.City,
ShippingZipCode = _shippingAddress.ZipCode, ShippingZipCode = _shippingAddress.ZipCode,
Total = CalculateTotal(CreateOrderItems(orderItems)) Total = CalculateTotal(CreateOrderItems(orderItems))
}; };
if (Settings.UseMocks) if (_settingsService.UseMocks)
{ {
// Get number of orders // Get number of orders
var orders = await _orderService.GetOrdersAsync(authToken); var orders = await _orderService.GetOrdersAsync(authToken);
@ -140,7 +143,7 @@ namespace eShopOnContainers.Core.ViewModels
{ {
try try
{ {
var authToken = Settings.AuthAccessToken; var authToken = _settingsService.AuthAccessToken;
var basket = _orderService.MapOrderToBasket(Order); var basket = _orderService.MapOrderToBasket(Order);
basket.RequestId = Guid.NewGuid(); basket.RequestId = Guid.NewGuid();
@ -148,7 +151,7 @@ namespace eShopOnContainers.Core.ViewModels
// Create basket checkout // Create basket checkout
await _basketService.CheckoutAsync(basket, authToken); await _basketService.CheckoutAsync(basket, authToken);
if (Settings.UseMocks) if (_settingsService.UseMocks)
{ {
await _orderService.CreateOrderAsync(Order, authToken); await _orderService.CreateOrderAsync(Order, authToken);
} }
@ -195,13 +198,13 @@ namespace eShopOnContainers.Core.ViewModels
} }
return orderItems; return orderItems;
} }
private decimal CalculateTotal(List<OrderItem> orderItems) private decimal CalculateTotal(List<OrderItem> orderItems)
{ {
decimal total = 0; decimal total = 0;
foreach(var orderItem in orderItems) foreach (var orderItem in orderItems)
{ {
total += (orderItem.Quantity * orderItem.UnitPrice); total += (orderItem.Quantity * orderItem.UnitPrice);
} }

View File

@ -1,7 +1,7 @@
using eShopOnContainers.Core.Helpers; using eShopOnContainers.Core.Models.User;
using eShopOnContainers.Core.Models.User;
using eShopOnContainers.Core.Services.Identity; using eShopOnContainers.Core.Services.Identity;
using eShopOnContainers.Core.Services.OpenUrl; using eShopOnContainers.Core.Services.OpenUrl;
using eShopOnContainers.Core.Services.Settings;
using eShopOnContainers.Core.Validations; using eShopOnContainers.Core.Validations;
using eShopOnContainers.Core.ViewModels.Base; using eShopOnContainers.Core.ViewModels.Base;
using IdentityModel.Client; using IdentityModel.Client;
@ -22,13 +22,16 @@ namespace eShopOnContainers.Core.ViewModels
private bool _isLogin; private bool _isLogin;
private string _authUrl; private string _authUrl;
private ISettingsService _settingsService;
private IOpenUrlService _openUrlService; private IOpenUrlService _openUrlService;
private IIdentityService _identityService; private IIdentityService _identityService;
public LoginViewModel( public LoginViewModel(
ISettingsService settingsService,
IOpenUrlService openUrlService, IOpenUrlService openUrlService,
IIdentityService identityService) IIdentityService identityService)
{ {
_settingsService = settingsService;
_openUrlService = openUrlService; _openUrlService = openUrlService;
_identityService = identityService; _identityService = identityService;
@ -127,13 +130,13 @@ namespace eShopOnContainers.Core.ViewModels
public ICommand SettingsCommand => new Command(async () => await SettingsAsync()); public ICommand SettingsCommand => new Command(async () => await SettingsAsync());
public ICommand ValidateUserNameCommand => new Command(() => ValidateUserName()); public ICommand ValidateUserNameCommand => new Command(() => ValidateUserName());
public ICommand ValidatePasswordCommand => new Command(() => ValidatePassword()); public ICommand ValidatePasswordCommand => new Command(() => ValidatePassword());
public override Task InitializeAsync(object navigationData) public override Task InitializeAsync(object navigationData)
{ {
if(navigationData is LogoutParameter) if (navigationData is LogoutParameter)
{ {
var logoutParameter = (LogoutParameter)navigationData; var logoutParameter = (LogoutParameter)navigationData;
@ -173,7 +176,7 @@ namespace eShopOnContainers.Core.ViewModels
if (isAuthenticated) if (isAuthenticated)
{ {
Settings.AuthAccessToken = GlobalSetting.Instance.AuthToken; _settingsService.AuthAccessToken = GlobalSetting.Instance.AuthToken;
await NavigationService.NavigateToAsync<MainViewModel>(); await NavigationService.NavigateToAsync<MainViewModel>();
await NavigationService.RemoveLastFromBackStackAsync(); await NavigationService.RemoveLastFromBackStackAsync();
@ -202,7 +205,7 @@ namespace eShopOnContainers.Core.ViewModels
private void Logout() private void Logout()
{ {
var authIdToken = Settings.AuthIdToken; var authIdToken = _settingsService.AuthIdToken;
var logoutRequest = _identityService.CreateLogoutRequest(authIdToken); var logoutRequest = _identityService.CreateLogoutRequest(authIdToken);
if (!string.IsNullOrEmpty(logoutRequest)) if (!string.IsNullOrEmpty(logoutRequest))
@ -211,13 +214,13 @@ namespace eShopOnContainers.Core.ViewModels
LoginUrl = logoutRequest; LoginUrl = logoutRequest;
} }
if (Settings.UseMocks) if (_settingsService.UseMocks)
{ {
Settings.AuthAccessToken = string.Empty; _settingsService.AuthAccessToken = string.Empty;
Settings.AuthIdToken = string.Empty; _settingsService.AuthIdToken = string.Empty;
} }
Settings.UseFakeLocation = false; _settingsService.UseFakeLocation = false;
} }
private async Task NavigateAsync(string url) private async Task NavigateAsync(string url)
@ -226,8 +229,8 @@ namespace eShopOnContainers.Core.ViewModels
if (unescapedUrl.Equals(GlobalSetting.Instance.LogoutCallback)) if (unescapedUrl.Equals(GlobalSetting.Instance.LogoutCallback))
{ {
Settings.AuthAccessToken = string.Empty; _settingsService.AuthAccessToken = string.Empty;
Settings.AuthIdToken = string.Empty; _settingsService.AuthIdToken = string.Empty;
IsLogin = false; IsLogin = false;
LoginUrl = _identityService.CreateAuthorizationRequest(); LoginUrl = _identityService.CreateAuthorizationRequest();
} }
@ -241,8 +244,8 @@ namespace eShopOnContainers.Core.ViewModels
if (!string.IsNullOrWhiteSpace(accessToken)) if (!string.IsNullOrWhiteSpace(accessToken))
{ {
Settings.AuthAccessToken = accessToken; _settingsService.AuthAccessToken = accessToken;
Settings.AuthIdToken = authResponse.IdentityToken; _settingsService.AuthIdToken = authResponse.IdentityToken;
await NavigationService.NavigateToAsync<MainViewModel>(); await NavigationService.NavigateToAsync<MainViewModel>();
await NavigationService.RemoveLastFromBackStackAsync(); await NavigationService.RemoveLastFromBackStackAsync();
} }
@ -257,21 +260,21 @@ namespace eShopOnContainers.Core.ViewModels
private bool Validate() private bool Validate()
{ {
bool isValidUser = ValidateUserName(); bool isValidUser = ValidateUserName();
bool isValidPassword = ValidatePassword(); bool isValidPassword = ValidatePassword();
return isValidUser && isValidPassword; return isValidUser && isValidPassword;
} }
private bool ValidateUserName() private bool ValidateUserName()
{ {
return _userName.Validate(); return _userName.Validate();
} }
private bool ValidatePassword() private bool ValidatePassword()
{ {
return _password.Validate(); return _password.Validate();
} }
private void AddValidations() private void AddValidations()
{ {
@ -281,7 +284,7 @@ namespace eShopOnContainers.Core.ViewModels
public void InvalidateMock() public void InvalidateMock()
{ {
IsMock = Settings.UseMocks; IsMock = _settingsService.UseMocks;
} }
} }
} }

View File

@ -1,8 +1,8 @@
using System.Threading.Tasks; using eShopOnContainers.Core.Models.Navigation;
using eShopOnContainers.Core.ViewModels.Base; using eShopOnContainers.Core.ViewModels.Base;
using eShopOnContainers.Core.Models.Navigation; using System.Threading.Tasks;
using Xamarin.Forms;
using System.Windows.Input; using System.Windows.Input;
using Xamarin.Forms;
namespace eShopOnContainers.Core.ViewModels namespace eShopOnContainers.Core.ViewModels
{ {

View File

@ -1,23 +1,25 @@
using System.Threading.Tasks; using eShopOnContainers.Core.Models.Orders;
using eShopOnContainers.Core.Models.Orders;
using eShopOnContainers.Core.ViewModels.Base;
using eShopOnContainers.Core.Services.Order; using eShopOnContainers.Core.Services.Order;
using System; using eShopOnContainers.Core.Services.Settings;
using eShopOnContainers.Core.ViewModels.Base;
using System.Threading.Tasks;
using System.Windows.Input; using System.Windows.Input;
using eShopOnContainers.Core.Helpers;
using Xamarin.Forms; using Xamarin.Forms;
namespace eShopOnContainers.Core.ViewModels namespace eShopOnContainers.Core.ViewModels
{ {
public class OrderDetailViewModel : ViewModelBase public class OrderDetailViewModel : ViewModelBase
{ {
private readonly ISettingsService _settingsService;
private readonly IOrderService _ordersService; private readonly IOrderService _ordersService;
private Order _order;
private Order _order;
private bool _isSubmittedOrder; private bool _isSubmittedOrder;
private string _orderStatusText; private string _orderStatusText;
public OrderDetailViewModel(IOrderService ordersService) public OrderDetailViewModel(ISettingsService settingsService, IOrderService ordersService)
{ {
_settingsService = settingsService;
_ordersService = ordersService; _ordersService = ordersService;
} }
@ -63,7 +65,7 @@ namespace eShopOnContainers.Core.ViewModels
var order = navigationData as Order; var order = navigationData as Order;
// Get order detail info // Get order detail info
var authToken = Settings.AuthAccessToken; var authToken = _settingsService.AuthAccessToken;
Order = await _ordersService.GetOrderAsync(order.OrderNumber, authToken); Order = await _ordersService.GetOrderAsync(order.OrderNumber, authToken);
IsSubmittedOrder = Order.OrderStatus == OrderStatus.Submitted; IsSubmittedOrder = Order.OrderStatus == OrderStatus.Submitted;
OrderStatusText = Order.OrderStatus.ToString().ToUpper(); OrderStatusText = Order.OrderStatus.ToString().ToUpper();
@ -74,13 +76,13 @@ namespace eShopOnContainers.Core.ViewModels
private async Task ToggleCancelOrderAsync() private async Task ToggleCancelOrderAsync()
{ {
var authToken = Settings.AuthAccessToken; var authToken = _settingsService.AuthAccessToken;
var result = await _ordersService.CancelOrderAsync(_order.OrderNumber, authToken); var result = await _ordersService.CancelOrderAsync(_order.OrderNumber, authToken);
if (result) if (result)
{ {
OrderStatusText = OrderStatus.Cancelled.ToString().ToUpper(); OrderStatusText = OrderStatus.Cancelled.ToString().ToUpper();
} }
else else
{ {

View File

@ -1,8 +1,8 @@
using eShopOnContainers.Core.Extensions; using eShopOnContainers.Core.Extensions;
using eShopOnContainers.Core.Helpers;
using eShopOnContainers.Core.Models.Orders; using eShopOnContainers.Core.Models.Orders;
using eShopOnContainers.Core.Models.User; using eShopOnContainers.Core.Models.User;
using eShopOnContainers.Core.Services.Order; using eShopOnContainers.Core.Services.Order;
using eShopOnContainers.Core.Services.Settings;
using eShopOnContainers.Core.ViewModels.Base; using eShopOnContainers.Core.ViewModels.Base;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -13,12 +13,13 @@ namespace eShopOnContainers.Core.ViewModels
{ {
public class ProfileViewModel : ViewModelBase public class ProfileViewModel : ViewModelBase
{ {
private readonly ISettingsService _settingsService;
private readonly IOrderService _orderService;
private ObservableCollection<Order> _orders; private ObservableCollection<Order> _orders;
private IOrderService _orderService; public ProfileViewModel(ISettingsService settingsService, IOrderService orderService)
public ProfileViewModel(IOrderService orderService)
{ {
_settingsService = settingsService;
_orderService = orderService; _orderService = orderService;
} }
@ -41,7 +42,7 @@ namespace eShopOnContainers.Core.ViewModels
IsBusy = true; IsBusy = true;
// Get orders // Get orders
var authToken = Settings.AuthAccessToken; var authToken = _settingsService.AuthAccessToken;
var orders = await _orderService.GetOrdersAsync(authToken); var orders = await _orderService.GetOrdersAsync(authToken);
Orders = orders.ToObservableCollection(); Orders = orders.ToObservableCollection();

View File

@ -1,17 +1,16 @@
using System.Globalization; using eShopOnContainers.Core.Models.Location;
using eShopOnContainers.Core.Models.User;
using eShopOnContainers.Core.Services.Location;
using eShopOnContainers.Core.Services.Settings;
using eShopOnContainers.Core.ViewModels.Base;
using Plugin.Geolocator;
using System.Globalization;
using System.Threading.Tasks;
using System.Windows.Input;
using Xamarin.Forms;
namespace eShopOnContainers.Core.ViewModels namespace eShopOnContainers.Core.ViewModels
{ {
using System.Windows.Input;
using Xamarin.Forms;
using System.Threading.Tasks;
using Helpers;
using Models.User;
using Base;
using Models.Location;
using Services.Location;
using Plugin.Geolocator;
public class SettingsViewModel : ViewModelBase public class SettingsViewModel : ViewModelBase
{ {
private string _titleUseAzureServices; private string _titleUseAzureServices;
@ -28,18 +27,20 @@ namespace eShopOnContainers.Core.ViewModels
private double _longitude; private double _longitude;
private string _gpsWarningMessage; private string _gpsWarningMessage;
private readonly ISettingsService _settingsService;
private readonly ILocationService _locationService; private readonly ILocationService _locationService;
public SettingsViewModel(ILocationService locationService) public SettingsViewModel(ISettingsService settingsService, ILocationService locationService)
{ {
_settingsService = settingsService;
_locationService = locationService; _locationService = locationService;
_useAzureServices = !Settings.UseMocks; _useAzureServices = !_settingsService.UseMocks;
_endpoint = Settings.UrlBase; _endpoint = _settingsService.UrlBase;
_latitude = double.Parse(Settings.Latitude, CultureInfo.CurrentCulture); _latitude = double.Parse(_settingsService.Latitude, CultureInfo.CurrentCulture);
_longitude = double.Parse(Settings.Longitude, CultureInfo.CurrentCulture); _longitude = double.Parse(_settingsService.Longitude, CultureInfo.CurrentCulture);
_useFakeLocation = Settings.UseFakeLocation; _useFakeLocation = _settingsService.UseFakeLocation;
_allowGpsLocation = Settings.AllowGpsLocation; _allowGpsLocation = _settingsService.AllowGpsLocation;
_gpsWarningMessage = string.Empty; _gpsWarningMessage = string.Empty;
} }
@ -194,7 +195,7 @@ namespace eShopOnContainers.Core.ViewModels
} }
} }
public bool UserIsLogged => !string.IsNullOrEmpty(Settings.AuthAccessToken); public bool UserIsLogged => !string.IsNullOrEmpty(_settingsService.AuthAccessToken);
public ICommand ToggleMockServicesCommand => new Command(async () => await ToggleMockServicesAsync()); public ICommand ToggleMockServicesCommand => new Command(async () => await ToggleMockServicesAsync());
@ -227,8 +228,9 @@ namespace eShopOnContainers.Core.ViewModels
await Task.Delay(1000); await Task.Delay(1000);
if (UseAzureServices) if (UseAzureServices)
{ {
Settings.AuthAccessToken = string.Empty; _settingsService.AuthAccessToken = string.Empty;
Settings.AuthIdToken = string.Empty; _settingsService.AuthIdToken = string.Empty;
await NavigationService.NavigateToAsync<LoginViewModel>(new LogoutParameter { Logout = true }); await NavigationService.NavigateToAsync<LoginViewModel>(new LogoutParameter { Logout = true });
await NavigationService.RemoveBackStackAsync(); await NavigationService.RemoveBackStackAsync();
} }
@ -244,14 +246,14 @@ namespace eShopOnContainers.Core.ViewModels
private async Task ToggleSendLocationAsync() private async Task ToggleSendLocationAsync()
{ {
if (!Settings.UseMocks) if (!_settingsService.UseMocks)
{ {
var locationRequest = new Location var locationRequest = new Location
{ {
Latitude = _latitude, Latitude = _latitude,
Longitude = _longitude Longitude = _longitude
}; };
var authToken = Settings.AuthAccessToken; var authToken = _settingsService.AuthAccessToken;
await _locationService.UpdateUserLocation(locationRequest, authToken); await _locationService.UpdateUserLocation(locationRequest, authToken);
} }
@ -310,30 +312,30 @@ namespace eShopOnContainers.Core.ViewModels
private void UpdateUseAzureServices() private void UpdateUseAzureServices()
{ {
// Save use mocks services to local storage // Save use mocks services to local storage
Settings.UseMocks = !_useAzureServices; _settingsService.UseMocks = !_useAzureServices;
} }
private void UpdateEndpoint() private void UpdateEndpoint()
{ {
// Update remote endpoint (save to local storage) // Update remote endpoint (save to local storage)
GlobalSetting.Instance.BaseEndpoint = Settings.UrlBase = _endpoint; GlobalSetting.Instance.BaseEndpoint = _settingsService.UrlBase = _endpoint;
} }
private void UpdateFakeLocation() private void UpdateFakeLocation()
{ {
Settings.UseFakeLocation = _useFakeLocation; _settingsService.UseFakeLocation = _useFakeLocation;
} }
private void UpdateLatitude() private void UpdateLatitude()
{ {
// Update fake latitude (save to local storage) // Update fake latitude (save to local storage)
Settings.Latitude = _latitude.ToString(); _settingsService.Latitude = _latitude.ToString();
} }
private void UpdateLongitude() private void UpdateLongitude()
{ {
// Update fake longitude (save to local storage) // Update fake longitude (save to local storage)
Settings.Longitude = _longitude.ToString(); _settingsService.Longitude = _longitude.ToString();
} }
private void UpdateAllowGpsLocation() private void UpdateAllowGpsLocation()
@ -348,13 +350,13 @@ namespace eShopOnContainers.Core.ViewModels
} }
else else
{ {
Settings.AllowGpsLocation = _allowGpsLocation; _settingsService.AllowGpsLocation = _allowGpsLocation;
GpsWarningMessage = string.Empty; GpsWarningMessage = string.Empty;
} }
} }
else else
{ {
Settings.AllowGpsLocation = _allowGpsLocation; _settingsService.AllowGpsLocation = _allowGpsLocation;
} }
} }
} }

View File

@ -1,8 +1,8 @@
using System; using eShopOnContainers.Core.ViewModels;
using SlideOverKit;
using Xamarin.Forms;
using eShopOnContainers.Core.ViewModels.Base; using eShopOnContainers.Core.ViewModels.Base;
using eShopOnContainers.Core.ViewModels; using SlideOverKit;
using System;
using Xamarin.Forms;
namespace eShopOnContainers.Core.Views namespace eShopOnContainers.Core.Views
{ {

View File

@ -5,7 +5,6 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Xam.Plugins.Settings" Version="3.1.1" />
<PackageReference Include="System.ComponentModel.Annotations" Version="4.4.1" /> <PackageReference Include="System.ComponentModel.Annotations" Version="4.4.1" />
<PackageReference Include="Acr.UserDialogs" Version="6.5.1" /> <PackageReference Include="Acr.UserDialogs" Version="6.5.1" />
<PackageReference Include="SlideOverKit" Version="2.1.5" /> <PackageReference Include="SlideOverKit" Version="2.1.5" />
@ -16,7 +15,4 @@
<PackageReference Include="Xamarin.Forms" Version="2.5.0.122203" /> <PackageReference Include="Xamarin.Forms" Version="2.5.0.122203" />
<PackageReference Include="IdentityModel" Version="3.0.0" /> <PackageReference Include="IdentityModel" Version="3.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Folder Include="TinyIoC\" />
</ItemGroup>
</Project> </Project>

View File

@ -1,15 +1,15 @@
using Android.App;
using Android.OS;
using Android.Content.PM;
using Android.Views;
using Xamarin.Forms.Platform.Android;
using FFImageLoading.Forms.Droid;
using Acr.UserDialogs; using Acr.UserDialogs;
using Android.App;
using Android.Content; using Android.Content;
using Android.Content.PM;
using Android.OS;
using Android.Runtime; using Android.Runtime;
using Android.Views;
using FFImageLoading; using FFImageLoading;
using System; using FFImageLoading.Forms.Droid;
using Plugin.Permissions; using Plugin.Permissions;
using System;
using Xamarin.Forms.Platform.Android;
namespace eShopOnContainers.Droid.Activities namespace eShopOnContainers.Droid.Activities
{ {

View File

@ -1,8 +1,8 @@
using System; using Android.Graphics;
using Xamarin.Forms;
using eShopOnContainers.Droid.Effects;
using Android.Views; using Android.Views;
using Android.Graphics; using eShopOnContainers.Droid.Effects;
using System;
using Xamarin.Forms;
[assembly: ExportEffect(typeof(CircleEffect), "CircleEffect")] [assembly: ExportEffect(typeof(CircleEffect), "CircleEffect")]
namespace eShopOnContainers.Droid.Effects namespace eShopOnContainers.Droid.Effects

View File

@ -1,11 +1,10 @@
using Xamarin.Forms;
using eShopOnContainers.Droid.Effects;
using Xamarin.Forms.Platform.Android;
using System;
using Android.Widget; using Android.Widget;
using eShopOnContainers.Core.Behaviors; using eShopOnContainers.Core.Behaviors;
using eShopOnContainers.Droid.Effects;
using System;
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics; using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ResolutionGroupName("eShopOnContainers")] [assembly: ResolutionGroupName("eShopOnContainers")]
[assembly: ExportEffect(typeof(EntryLineColorEffect), "EntryLineColorEffect")] [assembly: ExportEffect(typeof(EntryLineColorEffect), "EntryLineColorEffect")]
@ -52,7 +51,7 @@ namespace eShopOnContainers.Droid.Effects
} }
catch (Exception ex) catch (Exception ex)
{ {
Debug.WriteLine(ex.Message); Console.WriteLine(ex.Message);
} }
} }
} }

View File

@ -1,44 +0,0 @@
/*
// Helpers/Settings.cs This file was automatically added when you installed the Settings Plugin. If you are not using a PCL then comment this file back in to use it.
using Plugin.Settings;
using Plugin.Settings.Abstractions;
namespace eShopOnContainers.Droid.Helpers
{
/// <summary>
/// This is the Settings static class that can be used in your Core solution or in any
/// of your client applications. All settings are laid out the same exact way with getters
/// and setters.
/// </summary>
public static class Settings
{
private static ISettings AppSettings
{
get
{
return CrossSettings.Current;
}
}
#region Setting Constants
private const string SettingsKey = "settings_key";
private static readonly string SettingsDefault = string.Empty;
#endregion
public static string GeneralSettings
{
get
{
return AppSettings.GetValueOrDefault(SettingsKey, SettingsDefault);
}
set
{
AppSettings.AddOrUpdateValue(SettingsKey, value);
}
}
}
}*/

View File

@ -1,8 +1,8 @@
using System;
using Android.App; using Android.App;
using Android.OS; using Android.OS;
using Android.Runtime; using Android.Runtime;
using Plugin.CurrentActivity; using Plugin.CurrentActivity;
using System;
namespace eShopOnContainers.Droid namespace eShopOnContainers.Droid
{ {

View File

@ -1,12 +1,12 @@
using System;
using Android.Content; using Android.Content;
using Android.Views; using Android.Graphics;
using Android.Widget;
using Android.Graphics.Drawables; using Android.Graphics.Drawables;
using Android.Views.Animations;
using Android.Graphics.Drawables.Shapes; using Android.Graphics.Drawables.Shapes;
using Android.Util; using Android.Util;
using Android.Graphics; using Android.Views;
using Android.Views.Animations;
using Android.Widget;
using System;
namespace eShopOnContainers.Droid.Renderers namespace eShopOnContainers.Droid.Renderers
{ {

View File

@ -1,18 +1,18 @@
using Android.Content;
using Android.Graphics;
using Android.Support.Design.Widget;
using Android.Support.V4.View;
using Android.Views;
using Android.Widget;
using eShopOnContainers.Core.Controls;
using eShopOnContainers.Droid.Extensions;
using eShopOnContainers.Droid.Renderers;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Xamarin.Forms.Platform.Android.AppCompat;
using Xamarin.Forms; using Xamarin.Forms;
using Android.Content;
using Android.Support.Design.Widget;
using Android.Views;
using Android.Widget;
using Xamarin.Forms.Platform.Android; using Xamarin.Forms.Platform.Android;
using eShopOnContainers.Droid.Extensions; using Xamarin.Forms.Platform.Android.AppCompat;
using eShopOnContainers.Core.Controls;
using eShopOnContainers.Droid.Renderers;
using Android.Support.V4.View;
using Android.Graphics;
[assembly: ExportRenderer(typeof(TabbedPage), typeof(CustomTabbedPageRenderer))] [assembly: ExportRenderer(typeof(TabbedPage), typeof(CustomTabbedPageRenderer))]
namespace eShopOnContainers.Droid.Renderers namespace eShopOnContainers.Droid.Renderers

View File

@ -1,7 +1,7 @@
using Android.Content; using Android.Content;
using SlideOverKit.Droid;
using eShopOnContainers.Core.Views; using eShopOnContainers.Core.Views;
using eShopOnContainers.Droid.Renderers; using eShopOnContainers.Droid.Renderers;
using SlideOverKit.Droid;
using System; using System;
using Xamarin.Forms; using Xamarin.Forms;
using Xamarin.Forms.Platform.Android; using Xamarin.Forms.Platform.Android;

View File

@ -0,0 +1,149 @@
using Android.App;
using Android.Content;
using Android.Preferences;
using eShopOnContainers.Core.Services.Settings;
using eShopOnContainers.Droid.Services;
using System;
[assembly: Xamarin.Forms.Dependency(typeof(SettingsServiceImplementation))]
namespace eShopOnContainers.Droid.Services
{
public class SettingsServiceImplementation : ISettingsServiceImplementation
{
#region Internal Implementation
readonly object _locker = new object();
ISharedPreferences GetSharedPreference()
{
return PreferenceManager.GetDefaultSharedPreferences(Application.Context);
}
bool AddOrUpdateValueInternal<T>(string key, T value)
{
if (Application.Context == null)
return false;
if (value == null)
{
Remove(key);
return true;
}
var type = typeof(T);
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
{
type = Nullable.GetUnderlyingType(type);
}
var typeCode = Type.GetTypeCode(type);
lock (_locker)
{
using (var sharedPrefs = GetSharedPreference())
{
using (var editor = sharedPrefs.Edit())
{
switch (typeCode)
{
case TypeCode.Boolean:
editor.PutBoolean(key, Convert.ToBoolean(value));
break;
case TypeCode.String:
editor.PutString(key, Convert.ToString(value));
break;
default:
throw new ArgumentException($"Value of type {typeCode} is not supported.");
}
editor.Commit();
}
}
}
return true;
}
T GetValueOrDefaultInternal<T>(string key, T defaultValue = default(T))
{
if (Application.Context == null)
return defaultValue;
if (!Contains(key))
return defaultValue;
lock (_locker)
{
using (var sharedPrefs = GetSharedPreference())
{
var type = typeof(T);
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
{
type = Nullable.GetUnderlyingType(type);
}
object value = null;
var typeCode = Type.GetTypeCode(type);
switch (typeCode)
{
case TypeCode.Boolean:
value = sharedPrefs.GetBoolean(key, Convert.ToBoolean(defaultValue));
break;
case TypeCode.String:
value = sharedPrefs.GetString(key, Convert.ToString(defaultValue));
break;
default:
throw new ArgumentException($"Value of type {typeCode} is not supported.");
}
return null != value ? (T)value : defaultValue;
}
}
}
bool Contains(string key)
{
if (Application.Context == null)
return false;
lock (_locker)
{
using (var sharedPrefs = GetSharedPreference())
{
if (sharedPrefs == null)
return false;
return sharedPrefs.Contains(key);
}
}
}
#endregion
#region ISettingsServiceImplementation
public bool AddOrUpdateValue(string key, bool value) => AddOrUpdateValueInternal(key, value);
public bool AddOrUpdateValue(string key, string value) => AddOrUpdateValueInternal(key, value);
public bool GetValueOrDefault(string key, bool defaultValue) => GetValueOrDefaultInternal(key, defaultValue);
public string GetValueOrDefault(string key, string defaultValue) => GetValueOrDefaultInternal(key, defaultValue);
public void Remove(string key)
{
if (Application.Context == null)
return;
lock (_locker)
{
using (var sharedPrefs = GetSharedPreference())
{
using (var editor = sharedPrefs.Edit())
{
editor.Remove(key);
editor.Commit();
}
}
}
}
#endregion
}
}

View File

@ -166,12 +166,6 @@
<Reference Include="Plugin.Geolocator"> <Reference Include="Plugin.Geolocator">
<HintPath>..\..\..\..\packages\Xam.Plugin.Geolocator.3.0.4\lib\MonoAndroid10\Plugin.Geolocator.dll</HintPath> <HintPath>..\..\..\..\packages\Xam.Plugin.Geolocator.3.0.4\lib\MonoAndroid10\Plugin.Geolocator.dll</HintPath>
</Reference> </Reference>
<Reference Include="Plugin.Settings.Abstractions">
<HintPath>..\..\..\..\packages\Xam.Plugins.Settings.3.1.1\lib\MonoAndroid10\Plugin.Settings.Abstractions.dll</HintPath>
</Reference>
<Reference Include="Plugin.Settings">
<HintPath>..\..\..\..\packages\Xam.Plugins.Settings.3.1.1\lib\MonoAndroid10\Plugin.Settings.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http.Extensions"> <Reference Include="System.Net.Http.Extensions">
<HintPath>..\..\..\..\packages\Microsoft.Net.Http.2.2.28\lib\monoandroid\System.Net.Http.Extensions.dll</HintPath> <HintPath>..\..\..\..\packages\Microsoft.Net.Http.2.2.28\lib\monoandroid\System.Net.Http.Extensions.dll</HintPath>
</Reference> </Reference>
@ -232,7 +226,7 @@
<Compile Include="Effects\CircleEffect.cs" /> <Compile Include="Effects\CircleEffect.cs" />
<Compile Include="Effects\BaseContainerEffect.cs" /> <Compile Include="Effects\BaseContainerEffect.cs" />
<Compile Include="Activities\SplashActivity.cs" /> <Compile Include="Activities\SplashActivity.cs" />
<Compile Include="Helpers\Settings.cs" /> <Compile Include="Services\SettingsServiceImplementation.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<AndroidAsset Include="..\CommonResources\Fonts\Montserrat-Bold.ttf"> <AndroidAsset Include="..\CommonResources\Fonts\Montserrat-Bold.ttf">
@ -386,6 +380,9 @@
<Name>eShopOnContainers.Core</Name> <Name>eShopOnContainers.Core</Name>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup>
<Folder Include="Services\" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" /> <Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
<Import Project="..\..\..\..\packages\Xamarin.Android.Support.Compat.25.4.0.2\build\MonoAndroid70\Xamarin.Android.Support.Compat.targets" Condition="Exists('..\..\..\..\packages\Xamarin.Android.Support.Compat.25.4.0.2\build\MonoAndroid70\Xamarin.Android.Support.Compat.targets')" /> <Import Project="..\..\..\..\packages\Xamarin.Android.Support.Compat.25.4.0.2\build\MonoAndroid70\Xamarin.Android.Support.Compat.targets" Condition="Exists('..\..\..\..\packages\Xamarin.Android.Support.Compat.25.4.0.2\build\MonoAndroid70\Xamarin.Android.Support.Compat.targets')" />
<Import Project="..\..\..\..\packages\Xamarin.Android.Support.Core.UI.25.4.0.2\build\MonoAndroid70\Xamarin.Android.Support.Core.UI.targets" Condition="Exists('..\..\..\..\packages\Xamarin.Android.Support.Core.UI.25.4.0.2\build\MonoAndroid70\Xamarin.Android.Support.Core.UI.targets')" /> <Import Project="..\..\..\..\packages\Xamarin.Android.Support.Core.UI.25.4.0.2\build\MonoAndroid70\Xamarin.Android.Support.Core.UI.targets" Condition="Exists('..\..\..\..\packages\Xamarin.Android.Support.Core.UI.25.4.0.2\build\MonoAndroid70\Xamarin.Android.Support.Core.UI.targets')" />

View File

@ -70,7 +70,6 @@
<package id="System.Xml.XmlDocument" version="4.3.0" targetFramework="monoandroid80" /> <package id="System.Xml.XmlDocument" version="4.3.0" targetFramework="monoandroid80" />
<package id="Validation" version="2.2.8" targetFramework="monoandroid80" /> <package id="Validation" version="2.2.8" targetFramework="monoandroid80" />
<package id="Xam.Plugin.Geolocator" version="3.0.4" targetFramework="monoandroid80" /> <package id="Xam.Plugin.Geolocator" version="3.0.4" targetFramework="monoandroid80" />
<package id="Xam.Plugins.Settings" version="3.1.1" targetFramework="monoandroid80" />
<package id="Xamarin.Android.Support.Animated.Vector.Drawable" version="25.4.0.2" targetFramework="monoandroid80" /> <package id="Xamarin.Android.Support.Animated.Vector.Drawable" version="25.4.0.2" targetFramework="monoandroid80" />
<package id="Xamarin.Android.Support.Annotations" version="25.4.0.2" targetFramework="monoandroid80" /> <package id="Xamarin.Android.Support.Annotations" version="25.4.0.2" targetFramework="monoandroid80" />
<package id="Xamarin.Android.Support.Compat" version="25.4.0.2" targetFramework="monoandroid80" /> <package id="Xamarin.Android.Support.Compat" version="25.4.0.2" targetFramework="monoandroid80" />

View File

@ -1,44 +0,0 @@
/*
// Helpers/Settings.cs This file was automatically added when you installed the Settings Plugin. If you are not using a PCL then comment this file back in to use it.
using Plugin.Settings;
using Plugin.Settings.Abstractions;
namespace eShopOnContainers.TestRunner.Droid.Helpers
{
/// <summary>
/// This is the Settings static class that can be used in your Core solution or in any
/// of your client applications. All settings are laid out the same exact way with getters
/// and setters.
/// </summary>
public static class Settings
{
private static ISettings AppSettings
{
get
{
return CrossSettings.Current;
}
}
#region Setting Constants
private const string SettingsKey = "settings_key";
private static readonly string SettingsDefault = string.Empty;
#endregion
public static string GeneralSettings
{
get
{
return AppSettings.GetValueOrDefault(SettingsKey, SettingsDefault);
}
set
{
AppSettings.AddOrUpdateValue(SettingsKey, value);
}
}
}
}*/

View File

@ -1,13 +1,12 @@
using System;
using Android.App; using Android.App;
using Android.OS; using Android.OS;
using Android.Runtime; using Android.Runtime;
using Plugin.CurrentActivity; using Plugin.CurrentActivity;
using System;
namespace eShopOnContainers.TestRunner.Droid namespace eShopOnContainers.TestRunner.Droid
{ {
//You can specify additional application information in this attribute //You can specify additional application information in this attribute
[Application] [Application]
public class MainApplication : Application, Application.IActivityLifecycleCallbacks public class MainApplication : Application, Application.IActivityLifecycleCallbacks
{ {

View File

@ -231,7 +231,6 @@
<Compile Include="MainActivity.cs" /> <Compile Include="MainActivity.cs" />
<Compile Include="Resources\Resource.Designer.cs" /> <Compile Include="Resources\Resource.Designer.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Helpers\Settings.cs" />
<Compile Include="MainApplication.cs" /> <Compile Include="MainApplication.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@ -289,4 +288,4 @@
</Target> </Target>
<Import Project="..\..\..\..\packages\Xamarin.Forms.2.5.0.122203\build\netstandard1.0\Xamarin.Forms.targets" Condition="Exists('..\..\..\..\packages\Xamarin.Forms.2.5.0.122203\build\netstandard1.0\Xamarin.Forms.targets')" /> <Import Project="..\..\..\..\packages\Xamarin.Forms.2.5.0.122203\build\netstandard1.0\Xamarin.Forms.targets" Condition="Exists('..\..\..\..\packages\Xamarin.Forms.2.5.0.122203\build\netstandard1.0\Xamarin.Forms.targets')" />
<Import Project="..\..\..\..\packages\NETStandard.Library.2.0.0\build\netstandard2.0\NETStandard.Library.targets" Condition="Exists('..\..\..\..\packages\NETStandard.Library.2.0.0\build\netstandard2.0\NETStandard.Library.targets')" /> <Import Project="..\..\..\..\packages\NETStandard.Library.2.0.0\build\netstandard2.0\NETStandard.Library.targets" Condition="Exists('..\..\..\..\packages\NETStandard.Library.2.0.0\build\netstandard2.0\NETStandard.Library.targets')" />
</Project> </Project>

View File

@ -67,7 +67,6 @@
<package id="System.Xml.XmlDocument" version="4.3.0" targetFramework="monoandroid80" /> <package id="System.Xml.XmlDocument" version="4.3.0" targetFramework="monoandroid80" />
<package id="Validation" version="2.2.8" targetFramework="monoandroid80" /> <package id="Validation" version="2.2.8" targetFramework="monoandroid80" />
<package id="Xam.Plugin.Geolocator" version="3.0.4" targetFramework="monoandroid80" /> <package id="Xam.Plugin.Geolocator" version="3.0.4" targetFramework="monoandroid80" />
<package id="Xam.Plugins.Settings" version="3.1.1" targetFramework="monoandroid80" />
<package id="Xamarin.Android.Support.Animated.Vector.Drawable" version="25.4.0.2" targetFramework="monoandroid80" /> <package id="Xamarin.Android.Support.Animated.Vector.Drawable" version="25.4.0.2" targetFramework="monoandroid80" />
<package id="Xamarin.Android.Support.Annotations" version="25.4.0.2" targetFramework="monoandroid80" /> <package id="Xamarin.Android.Support.Annotations" version="25.4.0.2" targetFramework="monoandroid80" />
<package id="Xamarin.Android.Support.Compat" version="25.4.0.2" targetFramework="monoandroid80" /> <package id="Xamarin.Android.Support.Compat" version="25.4.0.2" targetFramework="monoandroid80" />

View File

@ -1,5 +1,4 @@
using System; using System.Reflection;
using System.Reflection;
using Windows.ApplicationModel.Activation; using Windows.ApplicationModel.Activation;
using Xunit.Runners.UI; using Xunit.Runners.UI;

View File

@ -1,44 +0,0 @@
/*
// Helpers/Settings.cs This file was automatically added when you installed the Settings Plugin. If you are not using a PCL then comment this file back in to use it.
using Plugin.Settings;
using Plugin.Settings.Abstractions;
namespace eShopOnContainers.TestRunner.iOS.Helpers
{
/// <summary>
/// This is the Settings static class that can be used in your Core solution or in any
/// of your client applications. All settings are laid out the same exact way with getters
/// and setters.
/// </summary>
public static class Settings
{
private static ISettings AppSettings
{
get
{
return CrossSettings.Current;
}
}
#region Setting Constants
private const string SettingsKey = "settings_key";
private static readonly string SettingsDefault = string.Empty;
#endregion
public static string GeneralSettings
{
get
{
return AppSettings.GetValueOrDefault(SettingsKey, SettingsDefault);
}
set
{
AppSettings.AddOrUpdateValue(SettingsKey, value);
}
}
}
}*/

View File

@ -105,7 +105,6 @@
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<InterfaceDefinition Include="Resources\LaunchScreen.xib" /> <InterfaceDefinition Include="Resources\LaunchScreen.xib" />
<None Include="packages.config" /> <None Include="packages.config" />
<Compile Include="Helpers\Settings.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Reference Include="System" /> <Reference Include="System" />
@ -148,12 +147,6 @@
<Reference Include="Newtonsoft.Json"> <Reference Include="Newtonsoft.Json">
<HintPath>..\..\..\..\packages\Newtonsoft.Json.10.0.3\lib\netstandard1.3\Newtonsoft.Json.dll</HintPath> <HintPath>..\..\..\..\packages\Newtonsoft.Json.10.0.3\lib\netstandard1.3\Newtonsoft.Json.dll</HintPath>
</Reference> </Reference>
<Reference Include="Plugin.Settings.Abstractions">
<HintPath>..\..\..\..\packages\Xam.Plugins.Settings.3.1.1\lib\Xamarin.iOS10\Plugin.Settings.Abstractions.dll</HintPath>
</Reference>
<Reference Include="Plugin.Settings">
<HintPath>..\..\..\..\packages\Xam.Plugins.Settings.3.1.1\lib\Xamarin.iOS10\Plugin.Settings.dll</HintPath>
</Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Content Include="Entitlements.plist" /> <Content Include="Entitlements.plist" />

View File

@ -52,7 +52,6 @@
<package id="System.Xml.ReaderWriter" version="4.3.0" targetFramework="xamarinios10" /> <package id="System.Xml.ReaderWriter" version="4.3.0" targetFramework="xamarinios10" />
<package id="System.Xml.XDocument" version="4.3.0" targetFramework="xamarinios10" /> <package id="System.Xml.XDocument" version="4.3.0" targetFramework="xamarinios10" />
<package id="System.Xml.XmlDocument" version="4.3.0" targetFramework="xamarinios10" /> <package id="System.Xml.XmlDocument" version="4.3.0" targetFramework="xamarinios10" />
<package id="Xam.Plugins.Settings" version="3.1.1" targetFramework="xamarinios10" />
<package id="Xamarin.Forms" version="2.5.0.122203" targetFramework="xamarinios10" /> <package id="Xamarin.Forms" version="2.5.0.122203" targetFramework="xamarinios10" />
<package id="xunit" version="2.3.1" targetFramework="xamarinios10" /> <package id="xunit" version="2.3.1" targetFramework="xamarinios10" />
<package id="xunit.abstractions" version="2.0.1" targetFramework="xamarinios10" /> <package id="xunit.abstractions" version="2.0.1" targetFramework="xamarinios10" />

View File

@ -1,11 +1,11 @@
using Xunit; using System;
using Xamarin.Forms;
using System;
using System.Globalization; using System.Globalization;
using Xamarin.Forms;
using Xunit;
namespace eShopOnContainers.UnitTests namespace eShopOnContainers.UnitTests
{ {
public class EventToCommandBehaviorTests public class EventToCommandBehaviorTests
{ {
[Fact] [Fact]
public void InvalidEventNameShouldThrowArgumentExceptionText() public void InvalidEventNameShouldThrowArgumentExceptionText()

View File

@ -1,50 +0,0 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
namespace eShopOnContainers.UnitTests.Helpers
{
public class PropertyChangeTracker
{
List<string> _notifications = new List<string>();
public PropertyChangeTracker(INotifyPropertyChanged changer)
{
changer.PropertyChanged += (sender, e) => _notifications.Add(e.PropertyName + ".Value");
}
//public string[] ChangedProperties
//{
// get { return _notifications.ToArray(); }
//}
public bool WaitForChange(string propertyName, int maxWaitMilliSeconds)
{
var startTime = DateTime.UtcNow;
while (!_notifications.Contains(propertyName))
{
if (startTime.AddMilliseconds(maxWaitMilliSeconds) < DateTime.UtcNow)
return false;
}
return true;
}
public bool WaitForChange(string propertyName, TimeSpan maxWait)
{
var startTime = DateTime.UtcNow;
while (!_notifications.Contains(propertyName))
{
if (startTime + maxWait < DateTime.UtcNow)
return false;
}
return true;
}
public void Reset()
{
_notifications.Clear();
}
}
}

View File

@ -0,0 +1,65 @@
using eShopOnContainers.Core.Services.Settings;
using System;
namespace eShopOnContainers.UnitTests.Mocks
{
public class MockSettingsService : ISettingsService
{
string _accessTokenDefault = string.Empty;
string _idTokenDefault = string.Empty;
bool _useMocksDefault = true;
string _urlBaseDefault = "https://13.88.8.119";
bool _useFakeLocationDefault = false;
bool _allowGpsLocationDefault = false;
double _fakeLatitudeDefault = 47.604610d;
double _fakeLongitudeDefault = -122.315752d;
public string AuthAccessToken
{
get { return _accessTokenDefault; }
set { _accessTokenDefault = value; }
}
public string AuthIdToken
{
get { return _idTokenDefault; }
set { _idTokenDefault = value; }
}
public bool UseMocks
{
get { return _useMocksDefault; }
set { _useMocksDefault = value; }
}
public string UrlBase
{
get { return _urlBaseDefault; }
set { _urlBaseDefault = value; }
}
public bool UseFakeLocation
{
get { return _useFakeLocationDefault; }
set { _useFakeLocationDefault = value; }
}
public string Latitude
{
get { return _fakeLatitudeDefault.ToString(); }
set { _fakeLatitudeDefault = Convert.ToDouble(value); }
}
public string Longitude
{
get { return _fakeLongitudeDefault.ToString(); }
set { _fakeLongitudeDefault = Convert.ToDouble(value); }
}
public bool AllowGpsLocation
{
get { return _allowGpsLocationDefault; }
set { _allowGpsLocationDefault = value; }
}
}
}

View File

@ -1,9 +1,9 @@
using eShopOnContainers.Core.ViewModels.Base; using eShopOnContainers.Core.Validations;
using eShopOnContainers.Core.Validations; using eShopOnContainers.Core.ViewModels.Base;
namespace eShopOnContainers.UnitTests namespace eShopOnContainers.UnitTests
{ {
public class MockViewModel : ViewModelBase public class MockViewModel : ViewModelBase
{ {
private ValidatableObject<string> _forename; private ValidatableObject<string> _forename;
private ValidatableObject<string> _surname; private ValidatableObject<string> _surname;

View File

@ -1,11 +1,10 @@
namespace eShopOnContainers.UnitTests.Services using eShopOnContainers.Core;
{ using eShopOnContainers.Core.Services.Marketing;
using System.Threading.Tasks; using System.Threading.Tasks;
using Core; using Xunit;
using Core.Helpers;
using Core.Services.Marketing;
using Xunit;
namespace eShopOnContainers.UnitTests.Services
{
public class MarketingServiceTests public class MarketingServiceTests
{ {
[Fact] [Fact]

View File

@ -1,10 +1,12 @@
using Xunit; using eShopOnContainers.Core.Models.Catalog;
using eShopOnContainers.Core.Services.Catalog;
using eShopOnContainers.Core.Services.Settings;
using eShopOnContainers.Core.ViewModels; using eShopOnContainers.Core.ViewModels;
using eShopOnContainers.Core.ViewModels.Base; using eShopOnContainers.Core.ViewModels.Base;
using eShopOnContainers.Core.Services.Catalog; using eShopOnContainers.UnitTests.Mocks;
using eShopOnContainers.Core.Models.Catalog;
using System.Threading.Tasks;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
using Xunit;
namespace eShopOnContainers.UnitTests namespace eShopOnContainers.UnitTests
{ {
@ -13,6 +15,7 @@ namespace eShopOnContainers.UnitTests
public CatalogViewModelTests() public CatalogViewModelTests()
{ {
ViewModelLocator.UpdateDependencies(true); ViewModelLocator.UpdateDependencies(true);
ViewModelLocator.RegisterSingleton<ISettingsService, MockSettingsService>();
} }
[Fact] [Fact]

View File

@ -1,54 +1,57 @@
using Xunit; using eShopOnContainers.Core.Models.Navigation;
using eShopOnContainers.Core.Services.Settings;
using eShopOnContainers.Core.ViewModels; using eShopOnContainers.Core.ViewModels;
using eShopOnContainers.Core.ViewModels.Base; using eShopOnContainers.Core.ViewModels.Base;
using eShopOnContainers.Core.Models.Navigation; using eShopOnContainers.UnitTests.Mocks;
using System.Threading.Tasks; using System.Threading.Tasks;
using Xunit;
namespace eShopOnContainers.UnitTests namespace eShopOnContainers.UnitTests
{ {
public class MainViewModelTests public class MainViewModelTests
{ {
public MainViewModelTests() public MainViewModelTests()
{ {
ViewModelLocator.UpdateDependencies(true); ViewModelLocator.UpdateDependencies(true);
} ViewModelLocator.RegisterSingleton<ISettingsService, MockSettingsService>();
}
[Fact] [Fact]
public void SettingsCommandIsNotNullWhenViewModelInstantiatedTest() public void SettingsCommandIsNotNullWhenViewModelInstantiatedTest()
{ {
var mainViewModel = new MainViewModel(); var mainViewModel = new MainViewModel();
Assert.NotNull(mainViewModel.SettingsCommand); Assert.NotNull(mainViewModel.SettingsCommand);
} }
[Fact] [Fact]
public async Task ViewModelInitializationSendsChangeTabMessageTest() public async Task ViewModelInitializationSendsChangeTabMessageTest()
{ {
bool messageReceived = false; bool messageReceived = false;
var mainViewModel = new MainViewModel(); var mainViewModel = new MainViewModel();
var tabParam = new TabParameter { TabIndex = 2 }; var tabParam = new TabParameter { TabIndex = 2 };
Xamarin.Forms.MessagingCenter.Subscribe<MainViewModel, int>(this, MessageKeys.ChangeTab, (sender, arg) => Xamarin.Forms.MessagingCenter.Subscribe<MainViewModel, int>(this, MessageKeys.ChangeTab, (sender, arg) =>
{ {
messageReceived = true; messageReceived = true;
}); });
await mainViewModel.InitializeAsync(tabParam); await mainViewModel.InitializeAsync(tabParam);
Assert.True(messageReceived); Assert.True(messageReceived);
} }
[Fact] [Fact]
public void IsBusyPropertyIsFalseWhenViewModelInstantiatedTest() public void IsBusyPropertyIsFalseWhenViewModelInstantiatedTest()
{ {
var mainViewModel = new MainViewModel(); var mainViewModel = new MainViewModel();
Assert.False(mainViewModel.IsBusy); Assert.False(mainViewModel.IsBusy);
} }
[Fact] [Fact]
public async Task IsBusyPropertyIsTrueAfterViewModelInitializationTest() public async Task IsBusyPropertyIsTrueAfterViewModelInitializationTest()
{ {
var mainViewModel = new MainViewModel(); var mainViewModel = new MainViewModel();
await mainViewModel.InitializeAsync(null); await mainViewModel.InitializeAsync(null);
Assert.True(mainViewModel.IsBusy); Assert.True(mainViewModel.IsBusy);
} }
} }
} }

View File

@ -1,31 +1,36 @@
namespace eShopOnContainers.UnitTests.ViewModels using eShopOnContainers.Core.Services.Marketing;
{ using eShopOnContainers.Core.Services.Settings;
using System.Threading.Tasks; using eShopOnContainers.Core.ViewModels;
using Xunit; using eShopOnContainers.Core.ViewModels.Base;
using Core.ViewModels.Base; using eShopOnContainers.UnitTests.Mocks;
using Core.Services.Marketing; using System.Threading.Tasks;
using Core.ViewModels; using Xunit;
namespace eShopOnContainers.UnitTests.ViewModels
{
public class MarketingViewModelTests public class MarketingViewModelTests
{ {
public MarketingViewModelTests() public MarketingViewModelTests()
{ {
ViewModelLocator.UpdateDependencies(true); ViewModelLocator.UpdateDependencies(true);
ViewModelLocator.RegisterSingleton<ISettingsService, MockSettingsService>();
} }
[Fact] [Fact]
public void GetCampaignsIsNullTest() public void GetCampaignsIsNullTest()
{ {
var settingsService = new MockSettingsService();
var campaignService = new CampaignMockService(); var campaignService = new CampaignMockService();
var campaignViewModel = new CampaignViewModel(campaignService); var campaignViewModel = new CampaignViewModel(settingsService, campaignService);
Assert.Null(campaignViewModel.Campaigns); Assert.Null(campaignViewModel.Campaigns);
} }
[Fact] [Fact]
public async Task GetCampaignsIsNotNullTest() public async Task GetCampaignsIsNotNullTest()
{ {
var settingsService = new MockSettingsService();
var campaignService = new CampaignMockService(); var campaignService = new CampaignMockService();
var campaignViewModel = new CampaignViewModel(campaignService); var campaignViewModel = new CampaignViewModel(settingsService, campaignService);
await campaignViewModel.InitializeAsync(null); await campaignViewModel.InitializeAsync(null);
@ -35,24 +40,27 @@
[Fact] [Fact]
public void GetCampaignDetailsCommandIsNotNullTest() public void GetCampaignDetailsCommandIsNotNullTest()
{ {
var settingsService = new MockSettingsService();
var campaignService = new CampaignMockService(); var campaignService = new CampaignMockService();
var campaignViewModel = new CampaignViewModel(campaignService); var campaignViewModel = new CampaignViewModel(settingsService, campaignService);
Assert.NotNull(campaignViewModel.GetCampaignDetailsCommand); Assert.NotNull(campaignViewModel.GetCampaignDetailsCommand);
} }
[Fact] [Fact]
public void GetCampaignDetailsByIdIsNullTest() public void GetCampaignDetailsByIdIsNullTest()
{ {
var settingsService = new MockSettingsService();
var campaignService = new CampaignMockService(); var campaignService = new CampaignMockService();
var campaignViewModel = new CampaignDetailsViewModel(campaignService); var campaignViewModel = new CampaignDetailsViewModel(settingsService, campaignService);
Assert.Null(campaignViewModel.Campaign); Assert.Null(campaignViewModel.Campaign);
} }
[Fact] [Fact]
public async Task GetCampaignDetailsByIdIsNotNullTest() public async Task GetCampaignDetailsByIdIsNotNullTest()
{ {
var settingsService = new MockSettingsService();
var campaignService = new CampaignMockService(); var campaignService = new CampaignMockService();
var campaignDetailsViewModel = new CampaignDetailsViewModel(campaignService); var campaignDetailsViewModel = new CampaignDetailsViewModel(settingsService, campaignService);
await campaignDetailsViewModel.InitializeAsync(1); await campaignDetailsViewModel.InitializeAsync(1);

View File

@ -1,7 +1,5 @@
using Xunit; using eShopOnContainers.Core.ViewModels.Base;
using eShopOnContainers.Core.ViewModels.Base; using Xunit;
using eShopOnContainers.UnitTests.Helpers;
using System.ComponentModel;
namespace eShopOnContainers.UnitTests namespace eShopOnContainers.UnitTests
{ {
@ -86,15 +84,12 @@ namespace eShopOnContainers.UnitTests
bool invoked = false; bool invoked = false;
var mockViewModel = new MockViewModel(); var mockViewModel = new MockViewModel();
PropertyChangedEventHandler handler = (sender, e) => mockViewModel.Forename.PropertyChanged += (sender, e) =>
{ {
if (e.PropertyName.Equals("Value")) if (e.PropertyName.Equals("Value"))
invoked = true; invoked = true;
}; };
mockViewModel.Forename.PropertyChanged += handler;
mockViewModel.Forename.Value = "John"; mockViewModel.Forename.Value = "John";
mockViewModel.Forename.PropertyChanged -= handler;
Assert.True(invoked); Assert.True(invoked);
} }
@ -105,15 +100,12 @@ namespace eShopOnContainers.UnitTests
bool invoked = false; bool invoked = false;
var mockViewModel = new MockViewModel(); var mockViewModel = new MockViewModel();
PropertyChangedEventHandler handler = (sender, e) => mockViewModel.Surname.PropertyChanged += (sender, e) =>
{ {
if (e.PropertyName.Equals("Value")) if (e.PropertyName.Equals("Value"))
invoked = true; invoked = true;
}; };
mockViewModel.Surname.PropertyChanged += handler;
mockViewModel.Surname.Value = "Smith"; mockViewModel.Surname.Value = "Smith";
mockViewModel.Surname.PropertyChanged -= handler;
Assert.True(invoked); Assert.True(invoked);
} }

View File

@ -1,55 +1,61 @@
using Xunit; using eShopOnContainers.Core;
using eShopOnContainers.Core; using eShopOnContainers.Core.Services.Order;
using eShopOnContainers.Core.Services.Settings;
using eShopOnContainers.Core.ViewModels; using eShopOnContainers.Core.ViewModels;
using eShopOnContainers.Core.ViewModels.Base; using eShopOnContainers.Core.ViewModels.Base;
using eShopOnContainers.Core.Services.Order; using eShopOnContainers.UnitTests.Mocks;
using System.Threading.Tasks; using System.Threading.Tasks;
using Xunit;
namespace eShopOnContainers.UnitTests namespace eShopOnContainers.UnitTests
{ {
public class OrderViewModelTests public class OrderViewModelTests
{ {
public OrderViewModelTests() public OrderViewModelTests()
{ {
ViewModelLocator.UpdateDependencies(true); ViewModelLocator.UpdateDependencies(true);
} ViewModelLocator.RegisterSingleton<ISettingsService, MockSettingsService>();
}
[Fact] [Fact]
public void OrderPropertyIsNullWhenViewModelInstantiatedTest() public void OrderPropertyIsNullWhenViewModelInstantiatedTest()
{ {
var orderService = new OrderMockService(); var settingsService = new MockSettingsService();
var orderViewModel = new OrderDetailViewModel(orderService); var orderService = new OrderMockService();
Assert.Null(orderViewModel.Order); var orderViewModel = new OrderDetailViewModel(settingsService, orderService);
} Assert.Null(orderViewModel.Order);
}
[Fact] [Fact]
public async Task OrderPropertyIsNotNullAfterViewModelInitializationTest() public async Task OrderPropertyIsNotNullAfterViewModelInitializationTest()
{ {
var orderService = new OrderMockService(); var settingsService = new MockSettingsService();
var orderViewModel = new OrderDetailViewModel(orderService); var orderService = new OrderMockService();
var orderViewModel = new OrderDetailViewModel(settingsService, orderService);
var order = await orderService.GetOrderAsync(1, GlobalSetting.Instance.AuthToken); var order = await orderService.GetOrderAsync(1, GlobalSetting.Instance.AuthToken);
await orderViewModel.InitializeAsync(order); await orderViewModel.InitializeAsync(order);
Assert.NotNull(orderViewModel.Order); Assert.NotNull(orderViewModel.Order);
} }
[Fact] [Fact]
public async Task SettingOrderPropertyShouldRaisePropertyChanged() public async Task SettingOrderPropertyShouldRaisePropertyChanged()
{ {
bool invoked = false; bool invoked = false;
var orderService = new OrderMockService(); var settingsService = new MockSettingsService();
var orderViewModel = new OrderDetailViewModel(orderService); var orderService = new OrderMockService();
var orderViewModel = new OrderDetailViewModel(settingsService, orderService);
orderViewModel.PropertyChanged += (sender, e) => orderViewModel.PropertyChanged += (sender, e) =>
{ {
if (e.PropertyName.Equals("Order")) if (e.PropertyName.Equals("Order"))
invoked = true; invoked = true;
}; };
var order = await orderService.GetOrderAsync(1, GlobalSetting.Instance.AuthToken); var order = await orderService.GetOrderAsync(1, GlobalSetting.Instance.AuthToken);
await orderViewModel.InitializeAsync(order); await orderViewModel.InitializeAsync(order);
Assert.True(invoked); Assert.True(invoked);
} }
} }
} }

View File

@ -9,9 +9,6 @@
<PackageReference Include="xunit" Version="2.3.1" /> <PackageReference Include="xunit" Version="2.3.1" />
<PackageReference Include="xunit.runner.console" Version="2.3.1" /> <PackageReference Include="xunit.runner.console" Version="2.3.1" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Folder Include="Helpers\" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\eShopOnContainers.Core\eShopOnContainers.Core.csproj" /> <ProjectReference Include="..\eShopOnContainers.Core\eShopOnContainers.Core.csproj" />
</ItemGroup> </ItemGroup>

View File

@ -1,14 +1,14 @@
using System; using eShopOnContainers.Core.Behaviors;
using eShopOnContainers.Windows.Effects;
using System;
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using UI = Windows.UI; using Windows.UI.Xaml.Controls;
using Xaml = Windows.UI.Xaml;
using Media = Windows.UI.Xaml.Media;
using Xamarin.Forms; using Xamarin.Forms;
using Xamarin.Forms.Platform.UWP; using Xamarin.Forms.Platform.UWP;
using Windows.UI.Xaml.Controls; using Media = Windows.UI.Xaml.Media;
using eShopOnContainers.Windows.Effects; using UI = Windows.UI;
using eShopOnContainers.Core.Behaviors; using Xaml = Windows.UI.Xaml;
[assembly: ResolutionGroupName("eShopOnContainers")] [assembly: ResolutionGroupName("eShopOnContainers")]
[assembly: ExportEffect(typeof(EntryLineColorEffect), "EntryLineColorEffect")] [assembly: ExportEffect(typeof(EntryLineColorEffect), "EntryLineColorEffect")]

View File

@ -0,0 +1,99 @@
using eShopOnContainers.Core.Services.Settings;
using eShopOnContainers.Windows.Services;
using Windows.Storage;
[assembly: Xamarin.Forms.Dependency(typeof(SettingsServiceImplementation))]
namespace eShopOnContainers.Windows.Services
{
public class SettingsServiceImplementation : ISettingsServiceImplementation
{
#region Internal Implementation
readonly object _locker = new object();
ApplicationDataContainer GetAppSettings()
{
return ApplicationData.Current.LocalSettings;
}
bool AddOrUpdateValueInternal<T>(string key, T value)
{
bool valueChanged = false;
if (value == null)
{
Remove(key);
return true;
}
lock (_locker)
{
var settings = GetAppSettings();
if (settings.Values.ContainsKey(key))
{
if (settings.Values[key] != (object)value)
{
settings.Values[key] = value;
valueChanged = true;
}
}
else
{
settings.Values[key] = value;
valueChanged = true;
}
}
return valueChanged;
}
T GetValueOrDefaultInternal<T>(string key, T defaultValue = default(T))
{
object value;
lock (_locker)
{
var settings = GetAppSettings();
if (settings.Values.ContainsKey(key))
{
var tempValue = settings.Values[key];
if (tempValue != null)
value = (T)tempValue;
else
value = defaultValue;
}
else
{
value = defaultValue;
}
}
return null != value ? (T)value : defaultValue;
}
#endregion
#region ISettingsServiceImplementation
public bool AddOrUpdateValue(string key, bool value) => AddOrUpdateValueInternal(key, value);
public bool AddOrUpdateValue(string key, string value) => AddOrUpdateValueInternal(key, value);
public bool GetValueOrDefault(string key, bool defaultValue) => GetValueOrDefaultInternal(key, defaultValue);
public string GetValueOrDefault(string key, string defaultValue) => GetValueOrDefaultInternal(key, defaultValue);
public void Remove(string key)
{
lock (_locker)
{
var settings = GetAppSettings();
if (settings.Values.ContainsKey(key))
{
settings.Values.Remove(key);
}
}
}
#endregion
}
}

View File

@ -121,6 +121,7 @@
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Renderers\CustomTabbedPageRenderer.cs" /> <Compile Include="Renderers\CustomTabbedPageRenderer.cs" />
<Compile Include="Renderers\SlideDownMenuPageRenderer.cs" /> <Compile Include="Renderers\SlideDownMenuPageRenderer.cs" />
<Compile Include="Services\SettingsServiceImplementation.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<AppxManifest Include="Package.appxmanifest"> <AppxManifest Include="Package.appxmanifest">

View File

@ -1,9 +1,9 @@
using System; using CoreAnimation;
using CoreGraphics;
using eShopOnContainers.iOS.Effects;
using System;
using Xamarin.Forms; using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS; using Xamarin.Forms.Platform.iOS;
using eShopOnContainers.iOS.Effects;
using CoreGraphics;
using CoreAnimation;
[assembly: ExportEffect(typeof(CircleEffect), "CircleEffect")] [assembly: ExportEffect(typeof(CircleEffect), "CircleEffect")]
namespace eShopOnContainers.iOS.Effects namespace eShopOnContainers.iOS.Effects

View File

@ -1,44 +0,0 @@
/*
// Helpers/Settings.cs This file was automatically added when you installed the Settings Plugin. If you are not using a PCL then comment this file back in to use it.
using Plugin.Settings;
using Plugin.Settings.Abstractions;
namespace eShopOnContainers.iOS.Helpers
{
/// <summary>
/// This is the Settings static class that can be used in your Core solution or in any
/// of your client applications. All settings are laid out the same exact way with getters
/// and setters.
/// </summary>
public static class Settings
{
private static ISettings AppSettings
{
get
{
return CrossSettings.Current;
}
}
#region Setting Constants
private const string SettingsKey = "settings_key";
private static readonly string SettingsDefault = string.Empty;
#endregion
public static string GeneralSettings
{
get
{
return AppSettings.GetValueOrDefault(SettingsKey, SettingsDefault);
}
set
{
AppSettings.AddOrUpdateValue(SettingsKey, value);
}
}
}
}*/

View File

@ -1,8 +1,8 @@
using System; using CoreGraphics;
using CoreGraphics;
using eShopOnContainers.Core.Views; using eShopOnContainers.Core.Views;
using eShopOnContainers.iOS; using eShopOnContainers.iOS;
using SlideOverKit.iOS; using SlideOverKit.iOS;
using System;
using UIKit; using UIKit;
using Xamarin.Forms; using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS; using Xamarin.Forms.Platform.iOS;
@ -10,7 +10,7 @@ using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(CatalogView), typeof(SlideDownMenuPageRenderer))] [assembly: ExportRenderer(typeof(CatalogView), typeof(SlideDownMenuPageRenderer))]
namespace eShopOnContainers.iOS namespace eShopOnContainers.iOS
{ {
public class SlideDownMenuPageRenderer : PageRenderer, ISlideOverKitPageRendereriOS public class SlideDownMenuPageRenderer : PageRenderer, ISlideOverKitPageRendereriOS
{ {
public Action<bool> ViewDidAppearEvent { get; set; } public Action<bool> ViewDidAppearEvent { get; set; }

View File

@ -0,0 +1,128 @@
using eShopOnContainers.Core.Services.Settings;
using eShopOnContainers.iOS.Services;
using Foundation;
using System;
[assembly: Xamarin.Forms.Dependency(typeof(SettingsServiceImplementation))]
namespace eShopOnContainers.iOS.Services
{
public class SettingsServiceImplementation : ISettingsServiceImplementation
{
#region Internal Implementation
readonly object _locker = new object();
NSUserDefaults GetUserDefaults() => NSUserDefaults.StandardUserDefaults;
bool AddOrUpdateValueInternal<T>(string key, T value)
{
if (value == null)
{
Remove(key);
return true;
}
var type = typeof(T);
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
{
type = Nullable.GetUnderlyingType(type);
}
var typeCode = Type.GetTypeCode(type);
lock (_locker)
{
var defaults = GetUserDefaults();
switch (typeCode)
{
case TypeCode.Boolean:
defaults.SetBool(Convert.ToBoolean(value), key);
break;
case TypeCode.String:
defaults.SetString(Convert.ToString(value), key);
break;
default:
throw new ArgumentException($"Value of type {typeCode} is unsupported.");
}
try
{
defaults.Synchronize();
}
catch (Exception ex)
{
Console.WriteLine("Unable to save: " + key, " Message: " + ex.Message);
}
}
return true;
}
T GetValueOrDefaultInternal<T>(string key, T defaultValue = default(T))
{
lock (_locker)
{
var defaults = GetUserDefaults();
if (defaults[key] == null)
{
return defaultValue;
}
var type = typeof(T);
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
{
type = Nullable.GetUnderlyingType(type);
}
object value = null;
var typeCode = Type.GetTypeCode(type);
switch (typeCode)
{
case TypeCode.Boolean:
value = defaults.BoolForKey(key);
break;
case TypeCode.String:
value = defaults.StringForKey(key);
break;
default:
throw new ArgumentException($"Value of type {typeCode} is unsupported.");
}
return null != value ? (T)value : defaultValue;
}
}
#endregion
#region ISettingsServiceImplementation
public bool AddOrUpdateValue(string key, bool value) => AddOrUpdateValueInternal(key, value);
public bool AddOrUpdateValue(string key, string value) => AddOrUpdateValueInternal(key, value);
public bool GetValueOrDefault(string key, bool defaultValue) => GetValueOrDefaultInternal(key, defaultValue);
public string GetValueOrDefault(string key, string defaultValue) => GetValueOrDefaultInternal(key, defaultValue);
public void Remove(string key)
{
lock (_locker)
{
var defaults = GetUserDefaults();
try
{
if (defaults[key] != null)
{
defaults.RemoveObject(key);
defaults.Synchronize();
}
}
catch (Exception ex)
{
Console.WriteLine("Unable to remove: " + key, " Message: " + ex.Message);
}
}
}
#endregion
}
}

View File

@ -125,7 +125,7 @@
<BundleResource Include="Resources\menu_campaigns%402x.png" /> <BundleResource Include="Resources\menu_campaigns%402x.png" />
<BundleResource Include="Resources\menu_campaigns%403x.png" /> <BundleResource Include="Resources\menu_campaigns%403x.png" />
<None Include="packages.config" /> <None Include="packages.config" />
<Compile Include="Helpers\Settings.cs" /> <Compile Include="Services\SettingsServiceImplementation.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<BundleResource Include="Resources\Icon-60%403x.png" /> <BundleResource Include="Resources\Icon-60%403x.png" />
@ -417,6 +417,9 @@
<Name>eShopOnContainers.Core</Name> <Name>eShopOnContainers.Core</Name>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup>
<Folder Include="Services\" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" /> <Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" />
<Import Project="..\..\..\..\packages\Xamarin.Forms.2.5.0.122203\build\netstandard1.0\Xamarin.Forms.targets" Condition="Exists('..\..\..\..\packages\Xamarin.Forms.2.5.0.122203\build\netstandard1.0\Xamarin.Forms.targets')" /> <Import Project="..\..\..\..\packages\Xamarin.Forms.2.5.0.122203\build\netstandard1.0\Xamarin.Forms.targets" Condition="Exists('..\..\..\..\packages\Xamarin.Forms.2.5.0.122203\build\netstandard1.0\Xamarin.Forms.targets')" />
<Import Project="..\..\..\..\packages\NETStandard.Library.2.0.0\build\netstandard2.0\NETStandard.Library.targets" Condition="Exists('..\..\..\..\packages\NETStandard.Library.2.0.0\build\netstandard2.0\NETStandard.Library.targets')" /> <Import Project="..\..\..\..\packages\NETStandard.Library.2.0.0\build\netstandard2.0\NETStandard.Library.targets" Condition="Exists('..\..\..\..\packages\NETStandard.Library.2.0.0\build\netstandard2.0\NETStandard.Library.targets')" />
@ -426,4 +429,4 @@
</PropertyGroup> </PropertyGroup>
<Error Condition="!Exists('..\..\..\..\packages\NETStandard.Library.2.0.0\build\netstandard2.0\NETStandard.Library.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\NETStandard.Library.2.0.0\build\netstandard2.0\NETStandard.Library.targets'))" /> <Error Condition="!Exists('..\..\..\..\packages\NETStandard.Library.2.0.0\build\netstandard2.0\NETStandard.Library.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\NETStandard.Library.2.0.0\build\netstandard2.0\NETStandard.Library.targets'))" />
</Target> </Target>
</Project> </Project>

View File

@ -66,7 +66,6 @@
<package id="Validation" version="2.2.8" targetFramework="xamarinios10" /> <package id="Validation" version="2.2.8" targetFramework="xamarinios10" />
<package id="WebP.Touch" version="1.0.7" targetFramework="xamarinios10" /> <package id="WebP.Touch" version="1.0.7" targetFramework="xamarinios10" />
<package id="Xam.Plugin.Geolocator" version="3.0.4" targetFramework="xamarinios10" /> <package id="Xam.Plugin.Geolocator" version="3.0.4" targetFramework="xamarinios10" />
<package id="Xam.Plugins.Settings" version="3.1.1" targetFramework="xamarinios10" />
<package id="Xamarin.FFImageLoading" version="2.3.4" targetFramework="xamarinios10" /> <package id="Xamarin.FFImageLoading" version="2.3.4" targetFramework="xamarinios10" />
<package id="Xamarin.FFImageLoading.Forms" version="2.3.4" targetFramework="xamarinios10" /> <package id="Xamarin.FFImageLoading.Forms" version="2.3.4" targetFramework="xamarinios10" />
<package id="Xamarin.Forms" version="2.5.0.122203" targetFramework="xamarinios10" /> <package id="Xamarin.Forms" version="2.5.0.122203" targetFramework="xamarinios10" />