867 lines
32 KiB
C#
867 lines
32 KiB
C#
using CommunityToolkit.Maui;
|
|
using CommunityToolkit.Maui.Core;
|
|
using CommunityToolkit.Maui.Core.Extensions;
|
|
using CommunityToolkit.Maui.Views;
|
|
using CommunityToolkit.Mvvm.ComponentModel;
|
|
using CommunityToolkit.Mvvm.Input;
|
|
using CommunityToolkit.Mvvm.Messaging;
|
|
using gehGassi.Dto;
|
|
using gehGassi.Dto.Common;
|
|
using gehGassi.Dto.DogWalkers;
|
|
using gehGassiApp.Core.Interfaces;
|
|
using gehGassiApp.Core.Messaging;
|
|
using gehGassiApp.Domain.Banners;
|
|
using gehGassiApp.Domain.Common;
|
|
using gehGassiApp.Domain.Lookup;
|
|
using gehGassiApp.Domain.Walks;
|
|
using gehGassiApp.Helper;
|
|
using gehGassiApp.Models.PopupResults;
|
|
using gehGassiApp.Resources;
|
|
using gehGassiApp.Services;
|
|
using gehGassiApp.Views;
|
|
using gehGassiApp.Views.Messages;
|
|
using gehGassiApp.Views.Popups;
|
|
using gehGassiApp.Views.Report;
|
|
using gehGassiApp.Views.Walkers;
|
|
using gehGassiApp.Views.Walks;
|
|
using System.Collections.ObjectModel;
|
|
|
|
|
|
namespace gehGassiApp.ViewModels
|
|
{
|
|
/// <summary>
|
|
/// Viewmodel für den Home-Screen
|
|
/// </summary>
|
|
public partial class HomeViewModel : MenuViewModel
|
|
{
|
|
private readonly IWalkService _walkService;
|
|
private readonly IBannerService _bannerService;
|
|
private readonly IDialogService _dialogService;
|
|
private readonly IDogWalkerService _dogWalkerService;
|
|
private readonly IDispatcher _dispatcher;
|
|
private readonly IUserService _userService;
|
|
private readonly IFavouriteService _favouriteService;
|
|
private readonly IConversationService _conversationService;
|
|
private readonly IPopupService _popupService;
|
|
/// <summary>
|
|
/// Hilfsvariable: max. Anzahl verfügbare Walker
|
|
/// </summary>
|
|
private int _total;
|
|
/// <summary>
|
|
/// Hilfsvariable: wie viele schon geladen?
|
|
/// </summary>
|
|
private int _skip;
|
|
|
|
/// <summary>
|
|
/// Hilfsvariable: wie viele auf einmal laden?
|
|
/// </summary>
|
|
private const int _take = Core.Common.Constants.ListPageSizeDefault;
|
|
|
|
/// <summary>
|
|
/// Erstellt eine Instanz
|
|
/// </summary>
|
|
/// <param name="walkService">Instanz eines IWalkService</param>
|
|
/// <param name="bannerService">Instanz eines IBannerService</param>
|
|
/// <param name="dialogService">Instanz eines IDialogService</param>
|
|
/// <param name="dogWalkerService">Instanz eines IDogWalkerService</param>
|
|
/// <param name="dispatcher">Instanz eines IDispatcher</param>
|
|
/// <param name="userService">Instanz eines IUserService</param>
|
|
/// <param name="favouriteService">Instanz eines IFavouriteService</param>
|
|
public HomeViewModel(IWalkService walkService, IBannerService bannerService, IDialogService dialogService, IDogWalkerService dogWalkerService, IDispatcher dispatcher, IUserService userService, IFavouriteService favouriteService, IConversationService conversationService, IPopupService popupService)
|
|
{
|
|
_walkService = walkService;
|
|
_bannerService = bannerService;
|
|
_dialogService = dialogService;
|
|
_dogWalkerService = dogWalkerService;
|
|
_dispatcher = dispatcher;
|
|
_userService = userService;
|
|
_favouriteService = favouriteService;
|
|
_conversationService = conversationService;
|
|
_popupService = popupService;
|
|
Title = Text.View_Title_Home;
|
|
SelectedMenu = MenuSelected.Home;
|
|
|
|
NextWalk = null;
|
|
HasNextWalk = false;
|
|
HasNotNextWalk = false;
|
|
Walkers = new ObservableCollection<DogWalkerLookup>();
|
|
BannerMargin = new Thickness(0, 0, 0, 0);
|
|
ListMargin = new Thickness(0, 0, 0, 12);
|
|
|
|
_showAppModeNext = null;
|
|
|
|
//Event wenn Refresh für diesen View gesetzt werden soll
|
|
if (WeakReferenceMessenger.Default.IsRegistered<RefreshViewModelMessage>(this) == false)
|
|
WeakReferenceMessenger.Default.Register<RefreshViewModelMessage>(this, (recipient, message) =>
|
|
{
|
|
if (message.Value is Core.Messaging.Messages.Refresh_Home or Core.Messaging.Messages.Refresh_All)
|
|
{
|
|
_refresh = true;
|
|
}
|
|
});
|
|
|
|
}
|
|
|
|
private DateTimeOffset? _showAppModeNext;
|
|
|
|
[ObservableProperty]
|
|
private WalkWithNames _nextWalk;
|
|
|
|
[ObservableProperty]
|
|
private bool _hasNextWalk;
|
|
|
|
[ObservableProperty]
|
|
private bool _hasNotNextWalk;
|
|
|
|
[ObservableProperty]
|
|
private ObservableCollection<DogWalkerLookup> _walkers;
|
|
|
|
/// <summary>
|
|
/// First 10 walkers for the home screen display
|
|
/// </summary>
|
|
[ObservableProperty]
|
|
private ObservableCollection<DogWalkerLookup> _first10Walkers;
|
|
|
|
[ObservableProperty]
|
|
private DogWalkerLookup _selectedWalker;
|
|
|
|
[ObservableProperty]
|
|
private bool _walkersRefreshing;
|
|
|
|
[ObservableProperty]
|
|
private Banner _banner;
|
|
|
|
[ObservableProperty]
|
|
private bool _hasBanner;
|
|
|
|
[ObservableProperty]
|
|
private ObservableCollection<WalkWithNames> _nextWalks;
|
|
|
|
[ObservableProperty]
|
|
private double _nextWalkWidth;
|
|
|
|
[ObservableProperty]
|
|
private double _refreshGridHeight;
|
|
|
|
[ObservableProperty]
|
|
private Thickness _bannerMargin;
|
|
|
|
[ObservableProperty]
|
|
private Thickness _listMargin;
|
|
|
|
#region Commands
|
|
|
|
/// <summary>
|
|
/// Command zum Neuladen der Walkers
|
|
/// </summary>
|
|
/// <returns>Task</returns>
|
|
[RelayCommand]
|
|
public async Task RefreshWalkers()
|
|
{
|
|
WalkersRefreshing = true;
|
|
IsBusy = true;
|
|
_total = 0;
|
|
_skip = 0;
|
|
SelectedWalker = null;
|
|
Walkers = null;
|
|
await LoadWalkersAsync();
|
|
IsBusy = false;
|
|
WalkersRefreshing = false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Command für das Anzeigen eines Banner-Links
|
|
/// </summary>
|
|
[RelayCommand]
|
|
public async Task ShowBanner()
|
|
{
|
|
if (IsBusy)
|
|
return;
|
|
|
|
try
|
|
{
|
|
if (Banner != null && !string.IsNullOrWhiteSpace(Banner.Url))
|
|
{
|
|
using var cts = new CancellationTokenSource(Core.Common.Constants.BannerTimeout);
|
|
await _bannerService.AddClicksAsync(Banner.Id, 1, App.AppMode, CurrentLocation, SelectedLanguage, App.CurrentUser.AccessToken, cts.Token);
|
|
IsBusy = true;
|
|
var uri = new Uri(Banner.Url);
|
|
await Browser.Default.OpenAsync(uri, BrowserLaunchMode.SystemPreferred);
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
// An unexpected error occured. No browser may be installed on the device.
|
|
}
|
|
finally
|
|
{
|
|
IsBusy = false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Command für das erstellen einer öffentlichen Anfrage
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
[RelayCommand]
|
|
public async Task CreatePublicWalkRequest()
|
|
{
|
|
if (IsBusy)
|
|
return;
|
|
|
|
WeakReferenceMessenger.Default.Send(new RefreshViewModelMessage(Core.Messaging.Messages.Refresh_PublicWalkRequest));
|
|
await Shell.Current.GoToAsync($"{nameof(PublicWalkRequestCreateView)}", Core.Common.Constants.AnimateNavigation);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Command für die Auswahl eines Walks
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
[RelayCommand]
|
|
public async Task WalkSelected()
|
|
{
|
|
if (IsBusy)
|
|
return;
|
|
|
|
if (NextWalk != null)
|
|
{
|
|
var menu = MenuSelected.HomeWalker.ToString();
|
|
WeakReferenceMessenger.Default.Send(new RefreshViewModelMessage(Core.Messaging.Messages.Refresh_Walk));
|
|
await Shell.Current.GoToAsync($"{nameof(WalkView)}?id={NextWalk.Id}&menu={menu}", Core.Common.Constants.AnimateNavigation);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Command für die Auswahl eines Walks
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
[RelayCommand]
|
|
public async Task NextWalkSelected(string id)
|
|
{
|
|
if (IsBusy)
|
|
return;
|
|
|
|
var menu = MenuSelected.HomeWalker.ToString();
|
|
WeakReferenceMessenger.Default.Send(new RefreshViewModelMessage(Core.Messaging.Messages.Refresh_Walk));
|
|
await Shell.Current.GoToAsync($"{nameof(WalkView)}?id={id}&menu={menu}", Core.Common.Constants.AnimateNavigation);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Command für die Auswahl eines Walkers
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
[RelayCommand]
|
|
public async Task WalkerSelected(DogWalkerLookup value)
|
|
{
|
|
if (IsBusy || value == null)
|
|
return;
|
|
|
|
SelectedWalker = value;
|
|
|
|
var id = SelectedWalker.Id;
|
|
var menu = MenuSelected.Home.ToString();
|
|
await Shell.Current.GoToAsync($"{nameof(WalkerView)}?id={id}&menu={menu}", Core.Common.Constants.AnimateNavigation);
|
|
SelectedWalker = null;
|
|
}
|
|
/// <summary>
|
|
/// Command für das Anlegen einer Konversation.
|
|
/// Sollte bereits eine existieren, dann nur das Wechseln zu den Nachrichten
|
|
/// </summary>
|
|
/// <returns>Task</returns>
|
|
[RelayCommand]
|
|
public async Task CreateConversation(DogWalkerLookup SelectedAppUser)
|
|
{
|
|
IsBusy = true;
|
|
|
|
using var cts = new CancellationTokenSource(Core.Common.Constants.ListTimeout);
|
|
var existingConversation = await _conversationService.GetByReceipientAsync(App.CurrentAppUser.Id, SelectedAppUser.Id, App.CurrentUser.AccessToken, cts.Token);
|
|
if (existingConversation == null)
|
|
{
|
|
//Konversation anlegen
|
|
var result = await _conversationService.CreateAsync(App.CurrentAppUser.Id, SelectedAppUser.Id, App.CurrentUser.AccessToken, cts.Token);
|
|
if (result.Success)
|
|
existingConversation = result.Value;
|
|
else
|
|
{
|
|
if (result.ErrorCode == CommunicationErrors.ServerNoConnection)
|
|
{
|
|
var options = ResourceHelper.GetSnackbarAlertOptions();
|
|
await _dialogService.SnackBarAsync(Text.Err_Conversation_NotOnline, null, Text.Button_Ok, TimeSpan.FromSeconds(10), options, SnackbarAnchor);
|
|
//SelectedAppUser = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
IsBusy = false;
|
|
|
|
if (existingConversation != null)
|
|
{
|
|
var stackCount = Shell.Current.Navigation.NavigationStack.Count;
|
|
if (stackCount > 1)
|
|
{
|
|
if (DeviceInfo.Platform == DevicePlatform.Android)
|
|
await Shell.Current.Navigation.PopToRootAsync();
|
|
}
|
|
#if IOS
|
|
await Shell.Current.GoToAsync($"//{nameof(ConversationsView)}/{nameof(MessagesIosView)}?cid={existingConversation.Id}&name={existingConversation.RecipientName}", Core.Common.Constants.AnimateNavigation);
|
|
#else
|
|
await Shell.Current.GoToAsync($"//{nameof(ConversationsView)}/{nameof(MessagesView)}?cid={existingConversation.Id}&name={existingConversation.RecipientName}", Core.Common.Constants.AnimateNavigation);
|
|
#endif
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Command für das Laden weiterer Listungen
|
|
/// </summary>
|
|
[RelayCommand]
|
|
public async Task LoadMore()
|
|
{
|
|
if (Walkers != null && Walkers.Count < _total && !IsBusy)
|
|
{
|
|
try
|
|
{
|
|
IsBusy = true;
|
|
|
|
//var sortOrders = new List<DynamicSortOrder>() { new() { Property = "UpdatedAt", SortDirection = SortDirection.Descending } };
|
|
|
|
var query = CreateQuery();
|
|
|
|
using var cts = new CancellationTokenSource(Core.Common.Constants.ListTimeout);
|
|
var requestsResult = await _dogWalkerService.GetDogWalkersLookupAsync(query, CurrentLocation, App.CurrentUser.AccessToken, cts.Token);
|
|
if (requestsResult.Success)
|
|
{
|
|
foreach (var request in requestsResult.Value)
|
|
{
|
|
if (CurrentLocation.Lat != null && CurrentLocation.Lng != null)
|
|
request.Distance = Location.CalculateDistance(CurrentLocation.Lat.Value, CurrentLocation.Lng.Value, request.Lat, request.Lng, DistanceUnits.Kilometers);
|
|
Walkers.Add(request);
|
|
}
|
|
}
|
|
|
|
_total = requestsResult.Total;
|
|
_skip = requestsResult.Skip + requestsResult.Take;
|
|
|
|
IsBusy = false;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
await TrackErrorAsync(ex, true);
|
|
}
|
|
finally
|
|
{
|
|
IsBusy = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Command für das Blockieren eines Walkers
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
[RelayCommand]
|
|
public async Task Block(DogWalkerLookup value)
|
|
{
|
|
if (IsBusy || value == null)
|
|
return;
|
|
|
|
var doBlock = await _dialogService.ShowAlertAsync(Text.Block_User_Title, Text.Block_User_Desc, Text.Common_Yes, Text.Common_No);
|
|
if (doBlock)
|
|
{
|
|
IsBusy = true;
|
|
try
|
|
{
|
|
using var cts = new CancellationTokenSource(Core.Common.Constants.CreateTimeout);
|
|
var result = await _userService.BlockAppUserAsync(App.CurrentAppUser.Id, value.Id, App.CurrentUser.AccessToken, cts.Token);
|
|
if (result.Success && result.Value)
|
|
{
|
|
var isFavourite = await _favouriteService.IsFavouriteLocalAsync(value.Id, Core.Common.Constants.FavouriteCategory_Walker);
|
|
if (isFavourite)
|
|
await _favouriteService.ToggleAsync(value.Id, Core.Common.Constants.FavouriteCategory_Walker, App.CurrentAppUser.Id, App.CurrentUser.AccessToken, cts.Token);
|
|
|
|
_total = 0;
|
|
_skip = 0;
|
|
SelectedWalker = null;
|
|
Walkers = null;
|
|
HasNextWalk = false;
|
|
HasNotNextWalk = false;
|
|
NextWalks = null;
|
|
NextWalk = null;
|
|
|
|
await LoadNextWalksAsync();
|
|
await LoadWalkersAsync();
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
await TrackErrorAsync(ex, true);
|
|
}
|
|
finally
|
|
{
|
|
IsBusy = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Command für das Melden eines Benutzers
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
[RelayCommand]
|
|
public async Task Report(DogWalkerLookup value)
|
|
{
|
|
if (IsBusy || value == null)
|
|
return;
|
|
|
|
var reportedAppUserId = value.Id;
|
|
var section = AppUserReportSection.HomeDogOwner;
|
|
var sectionId = value.Id;
|
|
var sectionId2 = string.Empty;
|
|
var backToHome = false;
|
|
|
|
var menu = MenuSelected.Home.ToString();
|
|
await Shell.Current.GoToAsync($"{nameof(ReportView)}?reportedAppUserId={reportedAppUserId}§ion={section}§ionId={sectionId}§ionId2={sectionId2}&backToHome={backToHome}&menu={menu}", Core.Common.Constants.AnimateNavigation);
|
|
}
|
|
|
|
#endregion
|
|
|
|
/// <summary>
|
|
/// Laden der initialen Daten
|
|
/// </summary>
|
|
/// <returns>Task</returns>
|
|
private async Task LoadAsync()
|
|
{
|
|
IsBusy = true;
|
|
CheckIsPremiumUser();
|
|
//await LoadNextWalkAsync();
|
|
await LoadNextWalksAsync();
|
|
await LoadWalkersAsync();
|
|
await LoadBannerAsync();
|
|
|
|
|
|
if (_showAppModeNext == null || _showAppModeNext < DateTimeOffset.UtcNow)
|
|
{
|
|
if (CurrentAppUser.Type == AppUserType.Both && App.AppMode == AppMode.DogOwner)
|
|
await _dialogService.ToastAsync(Resources.Text.AppMode_Note + " " + Resources.Text.Enum_AppMode_DogOwner, ToastDuration.Short, 14);
|
|
else if (CurrentAppUser.Type == AppUserType.Both && App.AppMode == AppMode.DogWalker)
|
|
await _dialogService.ToastAsync(Resources.Text.AppMode_Note + " " + Resources.Text.Enum_AppMode_DogWalker, ToastDuration.Short, 14);
|
|
_showAppModeNext = DateTimeOffset.UtcNow.AddHours(1);
|
|
}
|
|
|
|
if (ProfileNotFinished == false && NextWalk == null && (NextWalks == null || NextWalks.Count == 0))
|
|
BannerMargin = new Thickness(0, 0, 0, 0);
|
|
else
|
|
BannerMargin = new Thickness(0, 24, 0, 0);
|
|
|
|
if (ProfileNotFinished == false && Banner == null && NextWalk == null && (NextWalks == null || NextWalks.Count == 0))
|
|
ListMargin = new Thickness(0, 0, 0, 12);
|
|
else
|
|
ListMargin = new Thickness(0, 40, 0, 12);
|
|
|
|
IsBusy = false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Laden des nächsten Walks
|
|
/// </summary>
|
|
/// <returns>Task</returns>
|
|
private async Task LoadNextWalkAsync()
|
|
{
|
|
try
|
|
{
|
|
using var cts = new CancellationTokenSource(Core.Common.Constants.ListTimeout);
|
|
var nextWalkResult = await _walkService.GetNextWalkForOwnerAsync(App.CurrentAppUser.Id, DateTimeOffset.UtcNow, SelectedLanguage, App.AppMode, CurrentLocation, App.CurrentUser.AccessToken, cts.Token);
|
|
NextWalk = nextWalkResult.Value;
|
|
HasNextWalk = NextWalk != null;
|
|
HasNotNextWalk = !HasNextWalk;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
await TrackErrorAsync(ex, true);
|
|
HasNextWalk = false;
|
|
HasNotNextWalk = true;
|
|
NextWalk = null;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Laden eines Banners wenn verfügbar
|
|
/// </summary>
|
|
/// <returns>Task</returns>
|
|
private async Task LoadBannerAsync()
|
|
{
|
|
try
|
|
{
|
|
var currentBannerId = string.Empty;
|
|
if (Banner != null)
|
|
currentBannerId = Banner.Id;
|
|
|
|
//Banner = null;
|
|
HasBanner = false;
|
|
|
|
using var cts = new CancellationTokenSource(Core.Common.Constants.BannerTimeout);
|
|
var bannerResult = await _bannerService.GetForLocationAsync(BannerLocation.Home, currentBannerId, CurrentLocation, App.CurrentUser.AccessToken, App.AppMode, SelectedLanguage, cts.Token);
|
|
if (bannerResult.Success)
|
|
{
|
|
if (Banner != null && !string.IsNullOrWhiteSpace(Banner.Image))
|
|
{
|
|
if (Banner.Image != bannerResult.Value.Image)
|
|
{
|
|
Banner = bannerResult.Value;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Banner = bannerResult.Value;
|
|
}
|
|
|
|
HasBanner = true;
|
|
}
|
|
else
|
|
{
|
|
HasBanner = false;
|
|
//Banner = null;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
await TrackErrorAsync(ex, true);
|
|
HasBanner = false;
|
|
//Banner = null;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Laden der Walker in der Nähre
|
|
/// </summary>
|
|
/// <returns>Task</returns>
|
|
private async Task LoadWalkersAsync()
|
|
{
|
|
try
|
|
{
|
|
var query = CreateQuery();
|
|
|
|
using var cts = new CancellationTokenSource(Core.Common.Constants.ListTimeout);
|
|
var requests = await _dogWalkerService.GetDogWalkersLookupAsync(query, CurrentLocation, App.CurrentUser.AccessToken, cts.Token);
|
|
if (requests.Success && requests.Value.Any())
|
|
{
|
|
foreach (var request in requests.Value)
|
|
{
|
|
if (CurrentLocation.Lat != null && CurrentLocation.Lng != null)
|
|
request.Distance = Location.CalculateDistance(CurrentLocation.Lat.Value, CurrentLocation.Lng.Value, request.Lat, request.Lng, DistanceUnits.Kilometers);
|
|
}
|
|
|
|
// Maximale Entfernung in Kilometern
|
|
const double maxDistanceKm = 2.0;
|
|
const int minWalkersCount = 10;
|
|
|
|
// Filtern nach Entfernung (max 2km), dann Sortierung: Bewertung, dann mit Foto, dann Entfernung
|
|
var filteredWalkers = requests.Value
|
|
.Where(x => x.Distance <= maxDistanceKm)
|
|
.OrderByDescending(x => x.AverageRating)
|
|
.ThenByDescending(x => !string.IsNullOrWhiteSpace(x.Photo))
|
|
.ThenBy(x => x.Distance)
|
|
.ToList();
|
|
|
|
// Falls weniger als 10 Walker in der 1km-Zone, weitere nach Entfernung hinzufügen
|
|
if (filteredWalkers.Count < minWalkersCount)
|
|
{
|
|
var additionalWalkers = requests.Value
|
|
.Where(x => x.Distance > maxDistanceKm)
|
|
.OrderBy(x => x.Distance)
|
|
.Take(minWalkersCount - filteredWalkers.Count);
|
|
|
|
filteredWalkers.AddRange(additionalWalkers);
|
|
}
|
|
|
|
Walkers = filteredWalkers.ToObservableCollection();
|
|
|
|
// Set First10Walkers for the home screen display
|
|
First10Walkers = filteredWalkers.Take(10).ToObservableCollection();
|
|
|
|
_total = requests.Total;
|
|
_skip = requests.Skip + requests.Take;
|
|
}
|
|
else
|
|
{
|
|
_total = 0;
|
|
_skip = 0;
|
|
Walkers = null;
|
|
First10Walkers = null;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
await TrackErrorAsync(ex, true);
|
|
_total = 0;
|
|
_skip = 0;
|
|
Walkers = null;
|
|
First10Walkers = null;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Laden der nächsten Walks
|
|
/// </summary>
|
|
/// <returns>Task</returns>
|
|
private async Task LoadNextWalksAsync()
|
|
{
|
|
try
|
|
{
|
|
using var cts = new CancellationTokenSource(Core.Common.Constants.ListTimeout);
|
|
var requests = await _walkService.GetNextWalksOwnerAsync(App.CurrentAppUser.Id, DateTimeOffset.UtcNow, SelectedLanguage, 100, 0, App.CurrentUser.AccessToken, cts.Token);
|
|
if (requests.Success && requests.Value.Any())
|
|
{
|
|
foreach (var request in requests.Value)
|
|
{
|
|
if (CurrentLocation.Lat != null && CurrentLocation.Lng != null)
|
|
{
|
|
request.DistancePickup = Location.CalculateDistance(CurrentLocation.Lat.Value, CurrentLocation.Lng.Value, request.PickupAddressLat, request.PickupAddressLng, DistanceUnits.Kilometers);
|
|
request.DistanceReturn = Location.CalculateDistance(CurrentLocation.Lat.Value, CurrentLocation.Lng.Value, request.ReturnAddressLat, request.ReturnAddressLng, DistanceUnits.Kilometers);
|
|
}
|
|
|
|
if (request.BlockedOrLocked)
|
|
{
|
|
|
|
}
|
|
}
|
|
|
|
NextWalks = requests.Value.ToObservableCollection();
|
|
if (NextWalks.Count == 1)
|
|
{
|
|
HasNextWalk = true;
|
|
NextWalk = NextWalks.FirstOrDefault();
|
|
}
|
|
else
|
|
{
|
|
HasNextWalk = false;
|
|
NextWalk = null;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
HasNextWalk = false;
|
|
NextWalks = null;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
await TrackErrorAsync(ex, true);
|
|
HasNextWalk = false;
|
|
NextWalks = null;
|
|
}
|
|
}
|
|
|
|
#region Initialize
|
|
|
|
/// <summary>
|
|
/// Initialisieren des Viewmodels.
|
|
/// Soll überschrieben werden um lazy loading in Viewmodels ermöglicht wird
|
|
/// </summary>
|
|
/// <returns>Task</returns>
|
|
public override async Task InitializeAsync(object sender)
|
|
{
|
|
await base.InitializeAsync(sender);
|
|
|
|
IsBusy = false;
|
|
HasError = false;
|
|
ErrorMessage = string.Empty;
|
|
|
|
await TrackPageViewAsync("HomeDogOwner");
|
|
|
|
if (_refresh)
|
|
{
|
|
IsBusy = true;
|
|
_total = 0;
|
|
_skip = 0;
|
|
|
|
try
|
|
{
|
|
HasBanner = false;
|
|
//Banner = null;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
await TrackErrorAsync(ex, true);
|
|
HasBanner = false;
|
|
//Banner = null;
|
|
}
|
|
|
|
HasNextWalk = false;
|
|
HasNotNextWalk = false;
|
|
|
|
if (LocationPermissionStatus == PermissionStatus.Unknown || LocationPermissionStatus == PermissionStatus.Denied || LocationPermissionStatus == PermissionStatus.Disabled)
|
|
{
|
|
var status = await Permissions.RequestAsync<Permissions.LocationWhenInUse>();
|
|
LocationPermissionStatus = status;
|
|
}
|
|
|
|
NextWalks = null;
|
|
NextWalk = null;
|
|
SelectedWalker = null;
|
|
Walkers = null;
|
|
|
|
await Task.Delay(Core.Common.Constants.AnimationDelayList);
|
|
//await LoadAsync();
|
|
//IsBusy = false;
|
|
#pragma warning disable CS4014
|
|
Task.Run(LoadAsync);
|
|
#pragma warning restore CS4014
|
|
_refresh = false;
|
|
// AGB-Prüfung nach dem Laden der Daten
|
|
await CheckAGBAcceptanceAsync();
|
|
CheckIsPremiumUser();
|
|
// Subscription Offer Popup-Prüfung nach dem Laden der Daten
|
|
await CheckSubscriptionOfferAsync();
|
|
|
|
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Entladen des Viewmodels.
|
|
/// Soll überschrieben werden
|
|
/// </summary>
|
|
/// <returns>Task</returns>
|
|
public override Task DisappearingAsync(object sender)
|
|
{
|
|
IsBusy = false;
|
|
HasError = false;
|
|
ErrorMessage = string.Empty;
|
|
|
|
//if(Banner != null)
|
|
// Banner.Image = string.Empty;
|
|
//Banner = null;
|
|
if (Banner == null || string.IsNullOrWhiteSpace(Banner.Image))
|
|
HasBanner = false;
|
|
//HasBanner = false;
|
|
|
|
return base.DisappearingAsync(sender);
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
#region Resumed
|
|
|
|
/// <summary>
|
|
/// Eventhandler wenn die App aus dem Sleepmode kommt
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
internal override async Task AppResumed()
|
|
{
|
|
System.Diagnostics.Debug.WriteLine($"{DateTime.Now}: AppResumedMessage received");
|
|
System.Diagnostics.Debug.WriteLine($"IsMainThread: {MainThread.IsMainThread}");
|
|
|
|
await _dispatcher.DispatchAsync(async () =>
|
|
{
|
|
_total = 0;
|
|
_skip = 0;
|
|
|
|
_showAppModeNext = null;
|
|
try
|
|
{
|
|
HasBanner = false;
|
|
//Banner = null;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
await TrackErrorAsync(ex, true);
|
|
HasBanner = false;
|
|
//Banner = null;
|
|
}
|
|
HasNextWalk = false;
|
|
HasNotNextWalk = false;
|
|
IsBusy = true;
|
|
NextWalks = null;
|
|
NextWalk = null;
|
|
SelectedWalker = null;
|
|
Walkers = null;
|
|
|
|
await LoadAsync();
|
|
IsBusy = false;
|
|
});
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region private
|
|
|
|
/// <summary>
|
|
/// Erstellt ein Query-Objekt für die Anfrage der Walker
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
private DogWalkerQueryDto CreateQuery()
|
|
{
|
|
var query = new DogWalkerQueryDto()
|
|
{
|
|
Skip = _skip,
|
|
Take = _take,
|
|
Language = SelectedLanguage,
|
|
AppMode = (AppModeDto)App.AppMode,
|
|
IgnoreId = App.CurrentAppUser.Id,
|
|
Name = string.Empty,
|
|
City = string.Empty,
|
|
Country = string.Empty,
|
|
MinRating = 0
|
|
};
|
|
return query;
|
|
} /// <summary>
|
|
/// Prüft, ob der Benutzer die AGB akzeptiert hat und zeigt das Popup bei Bedarf an
|
|
/// </summary>
|
|
/// <returns>Task</returns>
|
|
private async Task CheckAGBAcceptanceAsync()
|
|
{
|
|
// Zeige das Popup nur, wenn der User die AGB noch nicht akzeptiert hat
|
|
// UND das Registrierungsdatum vor dem 16.06.2024 liegt
|
|
var registrationDate = App.CurrentUser?.RegistrationDate;
|
|
var cutoffDate = new DateTime(2024, 6, 16);
|
|
|
|
if (!UserPreferencesService.HasAcceptedAGB
|
|
&& registrationDate != null
|
|
&& registrationDate.Value.Date < cutoffDate)
|
|
{
|
|
var popupResult = await _popupService.ShowPopupAsync<AGBUpdatePopup, AGBUpdateResult>(
|
|
Shell.Current
|
|
);
|
|
|
|
// Nach dem Schließen des Popups prüfen wir erneut
|
|
var result = popupResult.Result;
|
|
if (result != null && result.IsAccepted)
|
|
{
|
|
UserPreferencesService.HasAcceptedAGB = true;
|
|
}
|
|
}
|
|
} /// <summary>
|
|
/// Prüft, ob das Subscription Offer Popup angezeigt werden soll und zeigt es bei Bedarf an
|
|
/// </summary>
|
|
/// <returns>Task</returns>
|
|
private async Task CheckSubscriptionOfferAsync()
|
|
{
|
|
// Zeige das Popup nur, wenn der User kein Premium-User ist
|
|
// UND der Count <= 5 ist und noch nicht in dieser Session gezeigt wurde
|
|
if (!IsPremiumUser && UserPreferencesService.ShowSubscriptionOffer)
|
|
{
|
|
var popupResult = await _popupService.ShowPopupAsync<SubscriptionOfferPopup, SubscriptionOfferResult>(
|
|
Shell.Current
|
|
);
|
|
|
|
// Markiere als in dieser Session gezeigt
|
|
UserPreferencesService.MarkSubscriptionOfferShownThisSession();
|
|
|
|
// Erhöhe den Counter, unabhängig davon ob das Popup angenommen oder abgelehnt wurde
|
|
UserPreferencesService.IncreaseSubscriptionOfferPopupCount();
|
|
|
|
// Falls der User das Abo akzeptiert hat, ist Navigation bereits im ViewModel behandelt
|
|
var result = popupResult.Result;
|
|
if (result != null && result.IsAccepted)
|
|
{
|
|
// Navigation erfolgt bereits im SubscriptionOfferPopupViewModel
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
|
|
|
|
}
|