321 lines
10 KiB
C#

using System.Collections.ObjectModel;
using CommunityToolkit.Maui.Core.Extensions;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using gehGassiApp.Core.Interfaces;
using gehGassiApp.Core.Messaging;
using gehGassiApp.Domain.Advertisements;
using gehGassiApp.Domain.Listings;
using gehGassiApp.Resources;
using gehGassiApp.Views.Advertisements;
using gehGassiApp.Views.Listings;
using gehGassiApp.Views.Partners;
namespace gehGassiApp.ViewModels
{
/// <summary>
/// Viewmodel für die kombnierte Partner und Angebote Sicht
/// </summary>
public partial class OffersViewModel : MenuViewModel
{
private readonly IAdvertisementService _advertisementService;
private readonly IListingService _listingService;
private readonly IDispatcher _dispatcher;
/// <summary>
/// Erstellt eine Instanz
/// </summary>
/// <param name="advertisementService">Instanz eines IAdvertisementService</param>
/// <param name="listingService">Instanz eines IListingService</param>
/// <param name="dispatcher">Instanz eines IDispatcher</param>
public OffersViewModel(IAdvertisementService advertisementService, IListingService listingService, IDispatcher dispatcher)
{
_advertisementService = advertisementService;
_listingService = listingService;
_dispatcher = dispatcher;
Title = Text.View_Title_Offers;
SelectedMenu = MenuSelected.Offers;
Branches = new ObservableCollection<BranchWithListings>();
Advertisements = new ObservableCollection<Advertisement>();
//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_Offers or Core.Messaging.Messages.Refresh_All)
{
_refresh = true;
}
});
}
/// <summary>
/// Liste der Branchen
/// </summary>
[ObservableProperty]
private ObservableCollection<BranchWithListings> _branches;
/// <summary>
/// Liste der top-Werbungen
/// </summary>
[ObservableProperty]
private ObservableCollection<Advertisement> _advertisements;
[ObservableProperty]
private bool _isRefreshing;
#region Commands
/// <summary>
/// Command zum Neuladen der Listen-Inhalte
/// </summary>
/// <returns>Task</returns>
[RelayCommand]
public async Task Refresh()
{
IsRefreshing = true;
IsBusy = true;
Advertisements = null;
Branches = null;
await LoadAdvertisementsAsync();
await LoadBranchesAsync();
IsBusy = false;
IsRefreshing = false;
}
/// <summary>
/// Listungen einer Brnache anzeigen
/// </summary>
/// <param name="parameter">Branche</param>
[RelayCommand]
public async Task ShowListings(object parameter)
{
if (IsBusy)
return;
var branch = (BranchWithListings)parameter;
WeakReferenceMessenger.Default.Send(new RefreshViewModelMessage(Core.Messaging.Messages.Refresh_Listings));
await Shell.Current.GoToAsync($"{nameof(ListingsView)}?bid={branch.Id}&name={branch.Name}", Core.Common.Constants.AnimateNavigation);
}
/// <summary>
/// Werbung anzeigen
/// </summary>
[RelayCommand]
public async Task ShowAdvertisement(object parameter)
{
if (IsBusy)
return;
var advertisement = (Advertisement)parameter;
await Shell.Current.GoToAsync($"{nameof(AdvertisementView)}?aid={advertisement.Id}", Core.Common.Constants.AnimateNavigation);
//await App.Current.MainPage.ShowPopupAsync()
}
/// <summary>
/// Werbung anzeigen - Listung
/// </summary>
[RelayCommand]
public async Task ShowAdvertisements()
{
if (IsBusy)
return;
WeakReferenceMessenger.Default.Send(new RefreshViewModelMessage(Core.Messaging.Messages.Refresh_Advertisements));
await Shell.Current.GoToAsync($"{nameof(AdvertisementsView)}", Core.Common.Constants.AnimateNavigation);
}
/// <summary>
/// Listung anzeigen
/// </summary>
/// <param name="parameter">Branche</param>
[RelayCommand]
public async Task ShowListing(object parameter)
{
if (IsBusy)
return;
var listing = (Listing)parameter;
await Shell.Current.GoToAsync($"{nameof(ListingView)}?lid={listing.Id}", Core.Common.Constants.AnimateNavigation);
}
#endregion
/// <summary>
/// Event wenn der Timer Tickt :)
/// </summary>
public void TimerTick()
{
if (Advertisements != null && Advertisements.Any())
{
if (!IsBusy && !IsRefreshing)
{
foreach (var advertisement in Advertisements)
{
advertisement.SetTimeLeft();
}
var forceReload = Advertisements.Count(c => c.LeftTicks <= 0) > 0;
if (forceReload)
{
_dispatcher.DispatchAsync( async () =>
{
IsBusy = true;
await LoadAdvertisementsAsync();
IsBusy = false;
});
}
}
}
}
/// <summary>
/// Laden der initialen Daten
/// </summary>
/// <returns></returns>
private async Task LoadAsync()
{
IsBusy = true;
await LoadAdvertisementsAsync();
await LoadBranchesAsync();
IsBusy = false;
}
/// <summary>
/// Laden der Branchen
/// </summary>
/// <returns></returns>
private async Task LoadBranchesAsync()
{
try
{
var branches = new List<BranchWithListings>();
using var cts = new CancellationTokenSource(Core.Common.Constants.ListTimeout);
var branchesResult = await _listingService.GetOverviewAsync(CurrentLocation, 5, 0, App.AppMode, App.CurrentUser.AccessToken, SelectedLanguage, cts.Token);
if (branchesResult.Success && branchesResult.Value.Any())
{
branches = branchesResult.Value;
Branches = branches.ToObservableCollection();
}
else
{
Branches = null;
}
}
catch (Exception ex)
{
await TrackErrorAsync(ex, true);
Branches = null;
}
}
/// <summary>
/// Laden der 3 ablaufenden Werbungen
/// </summary>
/// <returns></returns>
private async Task LoadAdvertisementsAsync()
{
try
{
var advertisements = new List<Advertisement>();
using var cts = new CancellationTokenSource(Core.Common.Constants.ListTimeout);
var advertisementResult = await _advertisementService.GetAdvertisementsNearEndAsync(CurrentLocation, 3, 0, App.AppMode, App.CurrentUser.AccessToken, SelectedLanguage, cts.Token);
if (advertisementResult.Success && advertisementResult.Value.Any())
{
advertisements = advertisementResult.Value;
foreach (var advertisement in advertisements)
{
advertisement.SetTimeLeft();
if(!string.IsNullOrWhiteSpace(advertisement.ImageLanguage))
advertisement.Image = advertisement.ImageLanguage;
}
Advertisements = advertisements.OrderBy(c => c.LeftTicks).ToObservableCollection();
}
else
{
Advertisements = null;
}
}
catch (Exception ex)
{
await TrackErrorAsync(ex, true);
Advertisements = null;
}
}
#region Initialisierung
/// <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("Offers");
if (_refresh)
{
IsBusy = true;
Advertisements = null;
Branches = null;
await Task.Delay(Core.Common.Constants.AnimationDelayList);
//await LoadAsync();
#pragma warning disable CS4014
Task.Run(LoadAsync);
#pragma warning restore CS4014
_refresh = false;
}
}
/// <summary>
/// Entladen des Viewmodels.
/// Soll überschrieben werden
/// </summary>
/// <returns>Task</returns>
public override Task DisappearingAsync(object sender)
{
IsBusy = false;
HasError = false;
ErrorMessage = string.Empty;
return base.DisappearingAsync(sender);
}
#endregion
#region Resumed
/// <summary>
/// Eventhandler wenn die App aus dem Sleepmode kommt
/// </summary>
/// <returns></returns>
internal override async Task AppResumed()
{
await _dispatcher.DispatchAsync(async () =>
{
IsBusy = true;
await LoadAsync();
IsBusy = false;
});
}
#endregion
}
}