net-9 upgrade v1

This commit is contained in:
Max Mannstein 2025-08-14 10:34:58 +02:00
parent 3b4f83e994
commit 806edf7676
29 changed files with 347 additions and 400 deletions

BIN
.DS_Store vendored

Binary file not shown.

BIN
gehGassiApp/.DS_Store vendored

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
gehGassiApp/gehGassiApp.Domain/.DS_Store vendored Normal file

Binary file not shown.

Binary file not shown.

View File

@ -387,6 +387,11 @@ public static class MauiProgram
builder.Services.AddTransient<ReportViewModel>(); builder.Services.AddTransient<ReportViewModel>();
builder.Services.AddTransient<SubscriptionsViewModel>(); builder.Services.AddTransient<SubscriptionsViewModel>();
// Popup ViewModels - NEW PATTERN
builder.Services.AddTransientPopup<AGBUpdatePopup, AGBUpdatePopupViewModel>();
builder.Services.AddTransientPopup<SubscriptionOfferPopup, SubscriptionOfferPopupViewModel>();
builder.Services.AddTransientPopup<SubscriptionSuccessPopup, SubscriptionSuccessPopupViewModel>();
#endregion #endregion
#region Views #region Views

View File

@ -0,0 +1,17 @@
namespace gehGassiApp.Models.PopupResults;
public class AGBUpdateResult
{
public bool IsAccepted { get; set; }
// Factory Methods für bessere Usability
public static AGBUpdateResult Accepted() => new()
{
IsAccepted = true
};
public static AGBUpdateResult Declined() => new()
{
IsAccepted = false
};
}

View File

@ -0,0 +1,17 @@
namespace gehGassiApp.Models.PopupResults;
public class SubscriptionOfferResult
{
public bool IsAccepted { get; set; }
// Factory Methods für bessere Usability
public static SubscriptionOfferResult Accepted() => new()
{
IsAccepted = true
};
public static SubscriptionOfferResult Declined() => new()
{
IsAccepted = false
};
}

View File

@ -0,0 +1,17 @@
namespace gehGassiApp.Models.PopupResults;
public class SubscriptionSuccessResult
{
public bool HasOpenedStrayz { get; set; }
// Factory Methods für bessere Usability
public static SubscriptionSuccessResult StrayzOpened() => new()
{
HasOpenedStrayz = true
};
public static SubscriptionSuccessResult Closed() => new()
{
HasOpenedStrayz = false
};
}

View File

@ -2,6 +2,7 @@
using Android.App; using Android.App;
using Android.Content; using Android.Content;
using Android.Content.PM; using Android.Content.PM;
using Android.Gms.Tasks;
using Android.OS; using Android.OS;
using Android.Views; using Android.Views;
using CommunityToolkit.Mvvm.Messaging; using CommunityToolkit.Mvvm.Messaging;
@ -24,7 +25,7 @@ namespace gehGassiApp;
Android.Content.Intent.CategoryDefault, Android.Content.Intent.CategoryDefault,
Android.Content.Intent.CategoryBrowsable Android.Content.Intent.CategoryBrowsable
})] })]
public class MainActivity : MauiAppCompatActivity, Android.Gms.Tasks.IOnSuccessListener public class MainActivity : MauiAppCompatActivity, IOnSuccessListener
{ {
//Service der die Installation des Gerätes am PNS ermöglicht //Service der die Installation des Gerätes am PNS ermöglicht
IDeviceInstallationService _deviceInstallationService; IDeviceInstallationService _deviceInstallationService;

View File

@ -1,4 +1,5 @@
using CommunityToolkit.Maui.Core; using CommunityToolkit.Maui;
using CommunityToolkit.Maui.Core;
using CommunityToolkit.Maui.Core.Extensions; using CommunityToolkit.Maui.Core.Extensions;
using CommunityToolkit.Maui.Views; using CommunityToolkit.Maui.Views;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
@ -14,6 +15,7 @@ using gehGassiApp.Domain.Common;
using gehGassiApp.Domain.Lookup; using gehGassiApp.Domain.Lookup;
using gehGassiApp.Domain.Walks; using gehGassiApp.Domain.Walks;
using gehGassiApp.Helper; using gehGassiApp.Helper;
using gehGassiApp.Models.PopupResults;
using gehGassiApp.Resources; using gehGassiApp.Resources;
using gehGassiApp.Services; using gehGassiApp.Services;
using gehGassiApp.Views; using gehGassiApp.Views;
@ -40,6 +42,7 @@ namespace gehGassiApp.ViewModels
private readonly IUserService _userService; private readonly IUserService _userService;
private readonly IFavouriteService _favouriteService; private readonly IFavouriteService _favouriteService;
private readonly IConversationService _conversationService; private readonly IConversationService _conversationService;
private readonly IPopupService _popupService;
/// <summary> /// <summary>
/// Hilfsvariable: max. Anzahl verfügbare Walker /// Hilfsvariable: max. Anzahl verfügbare Walker
/// </summary> /// </summary>
@ -64,7 +67,7 @@ namespace gehGassiApp.ViewModels
/// <param name="dispatcher">Instanz eines IDispatcher</param> /// <param name="dispatcher">Instanz eines IDispatcher</param>
/// <param name="userService">Instanz eines IUserService</param> /// <param name="userService">Instanz eines IUserService</param>
/// <param name="favouriteService">Instanz eines IFavouriteService</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) public HomeViewModel(IWalkService walkService, IBannerService bannerService, IDialogService dialogService, IDogWalkerService dogWalkerService, IDispatcher dispatcher, IUserService userService, IFavouriteService favouriteService, IConversationService conversationService, IPopupService popupService)
{ {
_walkService = walkService; _walkService = walkService;
_bannerService = bannerService; _bannerService = bannerService;
@ -74,6 +77,7 @@ namespace gehGassiApp.ViewModels
_userService = userService; _userService = userService;
_favouriteService = favouriteService; _favouriteService = favouriteService;
_conversationService = conversationService; _conversationService = conversationService;
_popupService = popupService;
Title = Text.View_Title_Home; Title = Text.View_Title_Home;
SelectedMenu = MenuSelected.Home; SelectedMenu = MenuSelected.Home;
@ -797,11 +801,13 @@ namespace gehGassiApp.ViewModels
&& registrationDate != null && registrationDate != null
&& registrationDate.Value.Date < cutoffDate) && registrationDate.Value.Date < cutoffDate)
{ {
var popup = new AGBUpdatePopup(); var popupResult = await _popupService.ShowPopupAsync<AGBUpdatePopup, AGBUpdateResult>(
var result = await Shell.Current.CurrentPage.ShowPopupAsync(popup); Shell.Current
);
// Nach dem Schließen des Popups prüfen wir erneut // Nach dem Schließen des Popups prüfen wir erneut
if (result is bool accepted && accepted) var result = popupResult.Result;
if (result != null && result.IsAccepted)
{ {
UserPreferencesService.HasAcceptedAGB = true; UserPreferencesService.HasAcceptedAGB = true;
} }
@ -816,14 +822,22 @@ namespace gehGassiApp.ViewModels
// UND der Count <= 5 ist und noch nicht in dieser Session gezeigt wurde // UND der Count <= 5 ist und noch nicht in dieser Session gezeigt wurde
if (!IsPremiumUser && UserPreferencesService.ShowSubscriptionOffer) if (!IsPremiumUser && UserPreferencesService.ShowSubscriptionOffer)
{ {
var popup = new SubscriptionOfferPopup(); var popupResult = await _popupService.ShowPopupAsync<SubscriptionOfferPopup, SubscriptionOfferResult>(
var result = await Shell.Current.CurrentPage.ShowPopupAsync(popup); Shell.Current
);
// Markiere als in dieser Session gezeigt // Markiere als in dieser Session gezeigt
UserPreferencesService.MarkSubscriptionOfferShownThisSession(); UserPreferencesService.MarkSubscriptionOfferShownThisSession();
// Erhöhe den Counter, unabhängig davon ob das Popup angenommen oder abgelehnt wurde // Erhöhe den Counter, unabhängig davon ob das Popup angenommen oder abgelehnt wurde
UserPreferencesService.IncreaseSubscriptionOfferPopupCount(); 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
}
} }
} }

View File

@ -1,4 +1,5 @@
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using CommunityToolkit.Maui;
using CommunityToolkit.Maui.Core; using CommunityToolkit.Maui.Core;
using CommunityToolkit.Maui.Core.Extensions; using CommunityToolkit.Maui.Core.Extensions;
using CommunityToolkit.Maui.Views; using CommunityToolkit.Maui.Views;
@ -10,6 +11,7 @@ using gehGassiApp.Core.Messaging;
using gehGassiApp.Domain.Banners; using gehGassiApp.Domain.Banners;
using gehGassiApp.Domain.Common; using gehGassiApp.Domain.Common;
using gehGassiApp.Domain.Walks; using gehGassiApp.Domain.Walks;
using gehGassiApp.Models.PopupResults;
using gehGassiApp.Resources; using gehGassiApp.Resources;
using gehGassiApp.Services; using gehGassiApp.Services;
using gehGassiApp.Views.Popups; using gehGassiApp.Views.Popups;
@ -28,6 +30,7 @@ namespace gehGassiApp.ViewModels
private readonly IDispatcher _dispatcher; private readonly IDispatcher _dispatcher;
private readonly IUserService _userService; private readonly IUserService _userService;
private readonly IFavouriteService _favouriteService; private readonly IFavouriteService _favouriteService;
private readonly IPopupService _popupService;
/// <summary> /// <summary>
/// Hilfsvariable: max. Anzahl verfügbare öffentlichen Anfragen /// Hilfsvariable: max. Anzahl verfügbare öffentlichen Anfragen
@ -55,7 +58,7 @@ namespace gehGassiApp.ViewModels
/// <param name="userService">Instanz eines IUserService</param> /// <param name="userService">Instanz eines IUserService</param>
/// <param name="favouriteService">Instanz eines IFavouriteService</param> /// <param name="favouriteService">Instanz eines IFavouriteService</param>
public HomeWalkerViewModel(IWalkService walkService, IBannerService bannerService, public HomeWalkerViewModel(IWalkService walkService, IBannerService bannerService,
IPublicWalkRequestService publicWalkRequestService, IPublicWalkResponseService publicWalkResponseService, IDialogService dialogService, IDispatcher dispatcher, IUserService userService, IFavouriteService favouriteService) IPublicWalkRequestService publicWalkRequestService, IPublicWalkResponseService publicWalkResponseService, IDialogService dialogService, IDispatcher dispatcher, IUserService userService, IFavouriteService favouriteService, IPopupService popupService)
{ {
_walkService = walkService; _walkService = walkService;
_bannerService = bannerService; _bannerService = bannerService;
@ -65,6 +68,7 @@ namespace gehGassiApp.ViewModels
_dispatcher = dispatcher; _dispatcher = dispatcher;
_userService = userService; _userService = userService;
_favouriteService = favouriteService; _favouriteService = favouriteService;
_popupService = popupService;
Title = Text.View_Title_Home; Title = Text.View_Title_Home;
SelectedMenu = MenuSelected.HomeWalker; SelectedMenu = MenuSelected.HomeWalker;
BannerMargin = new Thickness(0, 0, 0, 0); BannerMargin = new Thickness(0, 0, 0, 0);
@ -364,11 +368,13 @@ namespace gehGassiApp.ViewModels
&& registrationDate != null && registrationDate != null
&& registrationDate.Value.Date < cutoffDate) && registrationDate.Value.Date < cutoffDate)
{ {
var popup = new AGBUpdatePopup(); var popupResult = await _popupService.ShowPopupAsync<AGBUpdatePopup, AGBUpdateResult>(
var result = await Shell.Current.CurrentPage.ShowPopupAsync(popup); Shell.Current
);
// Nach dem Schließen des Popups prüfen wir erneut // Nach dem Schließen des Popups prüfen wir erneut
if (result is bool accepted && accepted) var result = popupResult.Result;
if (result != null && result.IsAccepted)
{ {
UserPreferencesService.HasAcceptedAGB = true; UserPreferencesService.HasAcceptedAGB = true;
} }

View File

@ -153,35 +153,6 @@ namespace gehGassiApp.ViewModels.Onboarding
//await ShowSubscriptionSuccessPopup(); //await ShowSubscriptionSuccessPopup();
//await CheckAGBStatus(); //await CheckAGBStatus();
} }
[RelayCommand]
private async Task CheckAGBStatus()
{
// Prüfe, ob AGB-Popup angezeigt werden muss
if (!AGBUpdatePopupViewModel.HasUserAcceptedCurrentAGB())
{
// Popup und ViewModel erstellen
var popup = new AGBUpdatePopup();
var viewModel = new AGBUpdatePopupViewModel(popup);
popup.BindingContext = viewModel;
// Popup anzeigen und auf Ergebnis warten
var result = await Shell.Current.CurrentPage.ShowPopupAsync(popup);
// result ist true wenn akzeptiert, false wenn abgelehnt
if (result is bool accepted)
{
if (accepted)
{
await Shell.Current.DisplayAlert("Info", "Danke für die Zustimmung!", "OK");
}
else
{
// User hat abgelehnt - weitere Aktionen
await Shell.Current.DisplayAlert("Info", "AGB wurden abgelehnt", "OK");
}
}
}
}
} }
public class OnboardingItemViewModel public class OnboardingItemViewModel

View File

@ -1,34 +1,44 @@
using CommunityToolkit.Maui.Core; using CommunityToolkit.Maui;
using CommunityToolkit.Maui.Core;
using CommunityToolkit.Maui.Views; using CommunityToolkit.Maui.Views;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Input;
using gehGassiApp.Models.PopupResults;
using gehGassiApp.Resources; using gehGassiApp.Resources;
using gehGassiApp.Services; using gehGassiApp.Services;
using gehGassiApp.Views; using gehGassiApp.Views;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace gehGassiApp.ViewModels.Popups namespace gehGassiApp.ViewModels.Popups;
{ public partial class AGBUpdatePopupViewModel : ObservableObject
public partial class AGBUpdatePopupViewModel : ObservableObject, IQueryAttributable
{ {
private readonly Popup _popup; #region Properties
private const string AGB_URL = "https://gehgassi.app/agb"; // Ersetze mit eurer tatsächlichen AGB-URL
[ObservableProperty] [ObservableProperty]
[NotifyPropertyChangedFor(nameof(AcceptButtonColor))] [NotifyPropertyChangedFor(nameof(AcceptButtonColor))]
private bool _hasAccepted = false; private bool _hasAccepted = false;
// Computed Property für Button-Farbe // Computed Property für Button-Farbe
readonly IPopupService _popupService;
public Color AcceptButtonColor => HasAccepted ? Color.FromArgb("#2E7D32") : Color.FromArgb("#BDBDBD"); public Color AcceptButtonColor => HasAccepted ? Color.FromArgb("#2E7D32") : Color.FromArgb("#BDBDBD");
#endregion
public AGBUpdatePopupViewModel(Popup popup) #region Constructor
public AGBUpdatePopupViewModel(IPopupService popupService)
{ {
_popup = popup; _popupService = popupService;
// Initialisiere die AGB-Status
HasAccepted = HasUserAcceptedCurrentAGB();
} }
#endregion
#region IQueryAttributable Implementation
public void ApplyQueryAttributes(IDictionary<string, object> query)
{
// Falls Parameter benötigt werden, hier implementieren
}
#endregion
#region Static Methods
/// <summary> /// <summary>
/// Prüft, ob der User bereits den aktuellen AGB zugestimmt hat /// Prüft, ob der User bereits den aktuellen AGB zugestimmt hat
/// </summary> /// </summary>
@ -44,7 +54,9 @@ namespace gehGassiApp.ViewModels.Popups
{ {
UserPreferencesService.HasAcceptedAGB = true; UserPreferencesService.HasAcceptedAGB = true;
} }
#endregion
#region Commands
/// <summary> /// <summary>
/// Öffnet die vollständigen AGB im Browser /// Öffnet die vollständigen AGB im Browser
/// </summary> /// </summary>
@ -53,11 +65,9 @@ namespace gehGassiApp.ViewModels.Popups
{ {
try try
{ {
var menu = MenuSelected.More.ToString(); var menu = MenuSelected.More.ToString();
var title = Text.View_Title_Privacy; var title = Text.View_Title_Privacy;
await Shell.Current.GoToAsync($"{nameof(ShowTextPageView)}?code={Core.Common.Constants.PagePrivacy}&menu={menu}&title={title}", Core.Common.Constants.AnimateNavigation); await Shell.Current.GoToAsync($"{nameof(ShowTextPageView)}?code={Core.Common.Constants.PagePrivacy}&menu={menu}&title={title}", Core.Common.Constants.AnimateNavigation);
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -90,8 +100,10 @@ namespace gehGassiApp.ViewModels.Popups
// AGB als akzeptiert markieren // AGB als akzeptiert markieren
MarkAGBAsAccepted(); MarkAGBAsAccepted();
// Popup schließen var result = AGBUpdateResult.Accepted();
await _popup.CloseAsync(true);
} // ✅ Toolkit übernimmt das Popup-Closing
await _popupService.ClosePopupAsync(Shell.Current, result);
} }
#endregion
} }

View File

@ -1,57 +0,0 @@
using CommunityToolkit.Maui.Views;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
namespace gehGassiApp.ViewModels.Popups
{
/// <summary>
/// ViewModel für das Zahlungshinweis-Popup
///
/// Verwendung:
/// // Prüfen ob bereits angezeigt
/// if (!PaymentInfoPopupViewModel.HasInfoBeenShown())
/// {
/// var popup = new PaymentInfoPopup();
/// await Shell.Current.CurrentPage.ShowPopupAsync(popup);
/// }
/// </summary>
public partial class PaymentInfoPopupViewModel : ObservableObject
{
private readonly Popup _popup;
private const string PAYMENT_INFO_SHOWN_KEY = "payment_info_july_shown_2025";
public PaymentInfoPopupViewModel(Popup popup)
{
_popup = popup;
}
/// <summary>
/// Prüft, ob der Zahlungshinweis bereits angezeigt wurde
/// </summary>
public static bool HasInfoBeenShown()
{
return Preferences.Get(PAYMENT_INFO_SHOWN_KEY, false);
}
/// <summary>
/// Markiert den Hinweis als angezeigt
/// </summary>
private static void MarkInfoAsShown()
{
Preferences.Set(PAYMENT_INFO_SHOWN_KEY, true);
}
/// <summary>
/// User hat den Hinweis zur Kenntnis genommen
/// </summary>
[RelayCommand]
private async Task Acknowledge()
{
// Hinweis als angezeigt markieren
MarkInfoAsShown();
// Popup schließen
await _popup.CloseAsync(true);
}
}
}

View File

@ -1,47 +1,45 @@
using CommunityToolkit.Maui.Views; using CommunityToolkit.Maui;
using CommunityToolkit.Maui.Views;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Input;
using gehGassiApp.Models.PopupResults;
using gehGassiApp.Views.Subscriptions; using gehGassiApp.Views.Subscriptions;
namespace gehGassiApp.ViewModels.Popups namespace gehGassiApp.ViewModels.Popups;
{
public partial class SubscriptionOfferPopupViewModel : ObservableObject
{
private readonly Popup _popup;
private const string SUBSCRIPTION_OFFER_SHOWN_KEY = "subscription_offer_shown_v2025";
public SubscriptionOfferPopupViewModel(Popup popup) public partial class SubscriptionOfferPopupViewModel : ObservableObject, IQueryAttributable
{ {
_popup = popup; #region Dependencies
private readonly IPopupService _popupService;
#endregion
#region Constructor
public SubscriptionOfferPopupViewModel(IPopupService popupService)
{
_popupService = popupService;
} }
#endregion
/// <summary> #region IQueryAttributable Implementation
/// Prüft, ob das Abo-Angebot bereits angezeigt wurde public void ApplyQueryAttributes(IDictionary<string, object> query)
/// </summary>
public static bool HasOfferBeenShown()
{ {
return Preferences.Get(SUBSCRIPTION_OFFER_SHOWN_KEY, false); // Falls Parameter benötigt werden, hier implementieren
}
/// <summary>
/// Markiert das Angebot als angezeigt
/// </summary>
private static void MarkOfferAsShown()
{
//Preferences.Set(SUBSCRIPTION_OFFER_SHOWN_KEY, true);
} }
#endregion
#region Commands
/// <summary> /// <summary>
/// User möchte Abo abschließen /// User möchte Abo abschließen
/// </summary> /// </summary>
[RelayCommand] [RelayCommand]
private async Task Accept() private async Task Accept()
{ {
// Angebot als angezeigt markieren var result = SubscriptionOfferResult.Accepted();
MarkOfferAsShown();
// Popup schließen mit true (User will Abo) // Popup schließen mit Result
await _popup.CloseAsync(true); await _popupService.ClosePopupAsync(Shell.Current, result);
// Navigation zu Subscriptions
await Shell.Current.GoToAsync($"{nameof(SubscriptionsView)}", Core.Common.Constants.AnimateNavigation); await Shell.Current.GoToAsync($"{nameof(SubscriptionsView)}", Core.Common.Constants.AnimateNavigation);
} }
@ -51,11 +49,10 @@ namespace gehGassiApp.ViewModels.Popups
[RelayCommand] [RelayCommand]
private async Task Decline() private async Task Decline()
{ {
// Angebot als angezeigt markieren var result = SubscriptionOfferResult.Declined();
MarkOfferAsShown();
// Popup schließen mit false (User will kein Abo) // Popup schließen mit Result
await _popup.CloseAsync(false); await _popupService.ClosePopupAsync(Shell.Current, result);
}
} }
#endregion
} }

View File

@ -1,20 +1,36 @@
using CommunityToolkit.Maui.Views; using CommunityToolkit.Maui;
using CommunityToolkit.Maui.Views;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Input;
using gehGassiApp.Models.PopupResults;
namespace gehGassiApp.ViewModels.Popups namespace gehGassiApp.ViewModels.Popups;
{
public partial class SubscriptionSuccessPopupViewModel : ObservableObject
{
private readonly Popup _popup;
private const string STRAYZ_URL = "https://www.strayz.de/pages/fuer-hunde"; // Ersetze mit der tatsächlichen STRAYZ-URL
public partial class SubscriptionSuccessPopupViewModel : ObservableObject, IQueryAttributable
public SubscriptionSuccessPopupViewModel(Popup popup)
{ {
_popup = popup; #region Constants
private const string STRAYZ_URL = "https://www.strayz.de/pages/fuer-hunde";
#endregion
#region Dependencies
private readonly IPopupService _popupService;
#endregion
#region Constructor
public SubscriptionSuccessPopupViewModel(IPopupService popupService)
{
_popupService = popupService;
} }
#endregion
#region IQueryAttributable Implementation
public void ApplyQueryAttributes(IDictionary<string, object> query)
{
// Falls Parameter benötigt werden, hier implementieren
}
#endregion
#region Commands
/// <summary> /// <summary>
/// Öffnet die STRAYZ-Partnerseite /// Öffnet die STRAYZ-Partnerseite
/// </summary> /// </summary>
@ -26,8 +42,10 @@ namespace gehGassiApp.ViewModels.Popups
// Öffne STRAYZ-Seite im Browser // Öffne STRAYZ-Seite im Browser
await Browser.OpenAsync(STRAYZ_URL, BrowserLaunchMode.External); await Browser.OpenAsync(STRAYZ_URL, BrowserLaunchMode.External);
// Popup schließen var result = SubscriptionSuccessResult.StrayzOpened();
await _popup.CloseAsync(true);
// Popup schließen mit Result
await _popupService.ClosePopupAsync(Shell.Current, result);
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -47,7 +65,10 @@ namespace gehGassiApp.ViewModels.Popups
[RelayCommand] [RelayCommand]
private async Task Close() private async Task Close()
{ {
await _popup.CloseAsync(false); var result = SubscriptionSuccessResult.Closed();
}
// Popup schließen mit Result
await _popupService.ClosePopupAsync(Shell.Current, result);
} }
#endregion
} }

View File

@ -1,3 +1,4 @@
using CommunityToolkit.Maui;
using CommunityToolkit.Maui.Core.Extensions; using CommunityToolkit.Maui.Core.Extensions;
using CommunityToolkit.Maui.Views; using CommunityToolkit.Maui.Views;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
@ -8,6 +9,7 @@ using gehGassiApp.Core.Messaging;
using gehGassiApp.Domain.Common; using gehGassiApp.Domain.Common;
using gehGassiApp.Domain.Subscriptions; using gehGassiApp.Domain.Subscriptions;
using gehGassiApp.Models; using gehGassiApp.Models;
using gehGassiApp.Models.PopupResults;
using gehGassiApp.Resources; using gehGassiApp.Resources;
using gehGassiApp.Services; using gehGassiApp.Services;
using gehGassiApp.Views; using gehGassiApp.Views;
@ -30,6 +32,7 @@ namespace gehGassiApp.ViewModels.Subscriptions
private readonly ISubscriptionValidationService _subscriptionValidationService; private readonly ISubscriptionValidationService _subscriptionValidationService;
private readonly IDispatcher _dispatcher; private readonly IDispatcher _dispatcher;
private readonly IDialogService _dialogService; private readonly IDialogService _dialogService;
private readonly IPopupService _popupService;
/// <summary> /// <summary>
/// ERstellt eine Instanz /// ERstellt eine Instanz
@ -38,12 +41,13 @@ namespace gehGassiApp.ViewModels.Subscriptions
/// <param name="subscriptionValidationService">Instanz eines ISubscriptionValidationService</param> /// <param name="subscriptionValidationService">Instanz eines ISubscriptionValidationService</param>
/// <param name="dispatcher">Instanz eines IDispatcher</param> /// <param name="dispatcher">Instanz eines IDispatcher</param>
/// <param name="dialogService">Instanz eines IDialogService</param> /// <param name="dialogService">Instanz eines IDialogService</param>
public SubscriptionsViewModel(ISubscriptionService subscriptionService, ISubscriptionValidationService subscriptionValidationService, IDispatcher dispatcher, IDialogService dialogService) public SubscriptionsViewModel(ISubscriptionService subscriptionService, ISubscriptionValidationService subscriptionValidationService, IDispatcher dispatcher, IDialogService dialogService, IPopupService popupService)
{ {
_subscriptionService = subscriptionService; _subscriptionService = subscriptionService;
_subscriptionValidationService = subscriptionValidationService; _subscriptionValidationService = subscriptionValidationService;
_dispatcher = dispatcher; _dispatcher = dispatcher;
_dialogService = dialogService; _dialogService = dialogService;
_popupService = popupService;
Title = Text.View_Title_Subscriptions; Title = Text.View_Title_Subscriptions;
SelectedMenu = MenuSelected.More; SelectedMenu = MenuSelected.More;
@ -205,8 +209,15 @@ namespace gehGassiApp.ViewModels.Subscriptions
await LoadAsync(); await LoadAsync();
if (MySubscriptions != null && MySubscriptions.Any()) if (MySubscriptions != null && MySubscriptions.Any())
{ {
var popup = new SubscriptionSuccessPopup(); var popupResult = await _popupService.ShowPopupAsync<SubscriptionSuccessPopup, SubscriptionSuccessResult>(
await Shell.Current.CurrentPage.ShowPopupAsync(popup); Shell.Current
);
var result = popupResult.Result;
if (result != null && result.HasOpenedStrayz)
{
// User hat STRAYZ geöffnet
}
} }
} }
else else
@ -425,8 +436,15 @@ namespace gehGassiApp.ViewModels.Subscriptions
IsBusy = false; IsBusy = false;
if (MySubscriptions != null && MySubscriptions.Any()) if (MySubscriptions != null && MySubscriptions.Any())
{ {
var popup = new SubscriptionSuccessPopup(); var popupResult = await _popupService.ShowPopupAsync<SubscriptionSuccessPopup, SubscriptionSuccessResult>(
await Shell.Current.CurrentPage.ShowPopupAsync(popup); Shell.Current
);
var result = popupResult.Result;
if (result != null && result.HasOpenedStrayz)
{
// User hat STRAYZ geöffnet
}
} }
} }

View File

@ -5,8 +5,9 @@
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:res="clr-namespace:gehGassiApp.Resources" xmlns:res="clr-namespace:gehGassiApp.Resources"
xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit" xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
CanBeDismissedByTappingOutsideOfPopup="False" xmlns:viewModels="clr-namespace:gehGassiApp.ViewModels.Popups"
Color="Transparent"> x:DataType="viewModels:AGBUpdatePopupViewModel"
CanBeDismissedByTappingOutsideOfPopup="False">
<!-- Popup Content --> <!-- Popup Content -->
<Border <Border
Padding="0" Padding="0"

View File

@ -5,9 +5,9 @@ namespace gehGassiApp.Views.Popups;
public partial class AGBUpdatePopup : Popup public partial class AGBUpdatePopup : Popup
{ {
public AGBUpdatePopup() public AGBUpdatePopup(AGBUpdatePopupViewModel viewModel)
{ {
InitializeComponent(); InitializeComponent();
BindingContext = new AGBUpdatePopupViewModel(this); BindingContext = viewModel;
} }
} }

View File

@ -1,98 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<toolkit:Popup
x:Class="gehGassiApp.Views.Popups.PaymentInfoPopup"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:res="clr-namespace:gehGassiApp.Resources"
xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
CanBeDismissedByTappingOutsideOfPopup="True"
Color="Transparent">
<!-- Popup Content -->
<Border
Padding="0"
BackgroundColor="White"
StrokeShape="RoundRectangle 16"
StrokeThickness="0"
WidthRequest="350">
<!-- Drop Shadow Effect -->
<Border.Shadow>
<Shadow
Brush="{AppThemeBinding Light={StaticResource Grey_Dark},
Dark={StaticResource Grey_Dark_Dark}}"
Opacity="0.3"
Radius="8"
Offset="0,4" />
</Border.Shadow>
<Grid RowDefinitions="Auto,Auto,Auto">
<!-- Header -->
<Border
Grid.Row="0"
Padding="20,16"
BackgroundColor="{AppThemeBinding Light={StaticResource Primary_DarkBlue},
Dark={StaticResource Primary_DarkBlue_Dark}}"
StrokeShape="RoundRectangle 16,16,0,0"
StrokeThickness="0">
<Label
Style="{StaticResource H4}"
Text="Zahlungshinweis"
TextColor="{AppThemeBinding Light={StaticResource Primary_White},
Dark={StaticResource Primary_White_Dark}}"
VerticalOptions="Center" />
</Border>
<!-- Content Bereich -->
<VerticalStackLayout
Grid.Row="1"
Padding="20,20"
Spacing="16">
<!-- Info Icon -->
<Label
FontFamily="MaterialIconsRegular"
FontSize="48"
HorizontalOptions="Center"
Text="info"
TextColor="{AppThemeBinding Light={StaticResource Primary_DarkBlue},
Dark={StaticResource Primary_DarkBlue_Dark}}" />
<!-- Info Text -->
<Label
HorizontalTextAlignment="Center"
LineHeight="1.4"
Style="{StaticResource BodyM}"
Text="Leider sind diese Funktionen im Juli nicht verfügbar. Wir arbeiten aber fleißig an einer Lösung."
TextColor="{AppThemeBinding Light={StaticResource Grey_Dark},
Dark={StaticResource Grey_Dark_Dark}}" />
<!-- Additional Info -->
<Label
HorizontalTextAlignment="Center"
LineHeight="1.4"
Style="{StaticResource BodyM}"
Text="Im Juli sind nur Barzahlungen verfügbar."
TextColor="{AppThemeBinding Light={StaticResource Primary_DarkBlue},
Dark={StaticResource Primary_DarkBlue_Dark}}"
FontAttributes="Bold" />
</VerticalStackLayout>
<!-- Action Button -->
<Button
Grid.Row="2"
Margin="20,0,20,20"
BackgroundColor="{AppThemeBinding Light={StaticResource Primary_DarkBlue},
Dark={StaticResource Primary_DarkBlue_Dark}}"
Command="{Binding AcknowledgeCommand}"
CornerRadius="12"
FontAttributes="Bold"
FontSize="{StaticResource FontLabelM}"
Text="Verstanden"
TextColor="White" />
</Grid>
</Border>
</toolkit:Popup>

View File

@ -1,13 +0,0 @@
using CommunityToolkit.Maui.Views;
using gehGassiApp.ViewModels.Popups;
namespace gehGassiApp.Views.Popups;
public partial class PaymentInfoPopup : Popup
{
public PaymentInfoPopup()
{
InitializeComponent();
BindingContext = new PaymentInfoPopupViewModel(this);
}
}

View File

@ -5,8 +5,9 @@
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:res="clr-namespace:gehGassiApp.Resources" xmlns:res="clr-namespace:gehGassiApp.Resources"
xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit" xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
CanBeDismissedByTappingOutsideOfPopup="True" xmlns:viewModels="clr-namespace:gehGassiApp.ViewModels.Popups"
Color="Transparent"> x:DataType="viewModels:SubscriptionOfferPopupViewModel"
CanBeDismissedByTappingOutsideOfPopup="True">
<!-- Popup Content --> <!-- Popup Content -->
<Border <Border

View File

@ -5,9 +5,9 @@ namespace gehGassiApp.Views.Popups;
public partial class SubscriptionOfferPopup : Popup public partial class SubscriptionOfferPopup : Popup
{ {
public SubscriptionOfferPopup() public SubscriptionOfferPopup(SubscriptionOfferPopupViewModel viewModel)
{ {
InitializeComponent(); InitializeComponent();
BindingContext = new SubscriptionOfferPopupViewModel(this); BindingContext = viewModel;
} }
} }

View File

@ -5,9 +5,10 @@
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:res="clr-namespace:gehGassiApp.Resources" xmlns:res="clr-namespace:gehGassiApp.Resources"
xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit" xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
xmlns:viewModels="clr-namespace:gehGassiApp.ViewModels.Popups"
x:DataType="viewModels:SubscriptionSuccessPopupViewModel"
CanBeDismissedByTappingOutsideOfPopup="True" CanBeDismissedByTappingOutsideOfPopup="True"
VerticalOptions="Center" VerticalOptions="Center">
Color="Transparent">
<!-- Popup Content --> <!-- Popup Content -->
<Border <Border

View File

@ -5,9 +5,9 @@ namespace gehGassiApp.Views.Popups;
public partial class SubscriptionSuccessPopup : Popup public partial class SubscriptionSuccessPopup : Popup
{ {
public SubscriptionSuccessPopup() public SubscriptionSuccessPopup(SubscriptionSuccessPopupViewModel viewModel)
{ {
InitializeComponent(); InitializeComponent();
BindingContext = new SubscriptionSuccessPopupViewModel(this); BindingContext = viewModel;
} }
} }

View File

@ -705,9 +705,28 @@
</ItemGroup> </ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net9.0-android'"> <ItemGroup Condition="'$(TargetFramework)' == 'net9.0-android'">
<PackageReference Include="Xamarin.AndroidX.Lifecycle.Runtime.Ktx" Version="2.9.1" />
<PackageReference Include="Xamarin.AndroidX.Lifecycle.Runtime.Ktx.Android" Version="2.9.1" />
<PackageReference Include="Xamarin.AndroidX.SavedState" Version="1.3.1" />
<PackageReference Include="Xamarin.AndroidX.SavedState.SavedState.Ktx" Version="1.3.1" />
<PackageReference Include="Xamarin.AndroidX.Activity.Ktx"> <PackageReference Include="Xamarin.AndroidX.Activity.Ktx">
<Version>1.10.1.2</Version> <Version>1.10.1.2</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Xamarin.AndroidX.Lifecycle.Common">
<Version>2.9.2</Version>
</PackageReference>
<PackageReference Include="Xamarin.AndroidX.Lifecycle.Runtime">
<Version>2.9.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.AndroidX.Lifecycle.ViewModel">
<Version>2.9.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.AndroidX.Lifecycle.LiveData.Core">
<Version>2.9.2</Version>
</PackageReference>
<PackageReference Include="Xamarin.AndroidX.Fragment">
<Version>1.8.8</Version>
</PackageReference>
<PackageReference Include="Xamarin.AndroidX.Collection.Ktx"> <PackageReference Include="Xamarin.AndroidX.Collection.Ktx">
<Version>1.5.0.2</Version> <Version>1.5.0.2</Version>
</PackageReference> </PackageReference>
@ -717,9 +736,6 @@
<PackageReference Include="Xamarin.AndroidX.Lifecycle.LiveData.Ktx"> <PackageReference Include="Xamarin.AndroidX.Lifecycle.LiveData.Ktx">
<Version>2.9.2</Version> <Version>2.9.2</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Xamarin.AndroidX.SavedState">
<Version>1.3.1</Version>
</PackageReference>
<PackageReference Include="Xamarin.Firebase.Messaging"> <PackageReference Include="Xamarin.Firebase.Messaging">
<Version>125.0.0</Version> <Version>125.0.0</Version>
</PackageReference> </PackageReference>