149 lines
4.2 KiB
C#
149 lines
4.2 KiB
C#
using CommunityToolkit.Mvvm.ComponentModel;
|
|
using CommunityToolkit.Mvvm.Input;
|
|
using Jugenddienst_Stunden.Interfaces;
|
|
|
|
namespace Jugenddienst_Stunden.ViewModels;
|
|
|
|
/// <summary>
|
|
/// ViewModel für die Loginseite (MVVM)
|
|
/// </summary>
|
|
public partial class LoginViewModel : ObservableObject {
|
|
private readonly IAuthService _auth;
|
|
private readonly IAppSettings _settings;
|
|
private readonly IAlertService? _alerts;
|
|
private DateTime _lastDetectionTime = DateTime.MinValue;
|
|
private readonly TimeSpan _detectionInterval = TimeSpan.FromSeconds(5);
|
|
|
|
public event EventHandler<string>? AlertEvent;
|
|
public event EventHandler<string>? InfoEvent;
|
|
|
|
/// <summary>
|
|
/// Name der Anwendung
|
|
/// </summary>
|
|
public string AppTitle => AppInfo.Name;
|
|
|
|
/// <summary>
|
|
/// Programmversion
|
|
/// </summary>
|
|
public string Version => AppInfo.VersionString;
|
|
|
|
[ObservableProperty]
|
|
private string message = "Scanne den QR-Code von deinem Benutzerprofil auf der Stundenseite.";
|
|
|
|
[ObservableProperty]
|
|
private string? server;
|
|
|
|
[ObservableProperty]
|
|
private string? serverLabel;
|
|
|
|
[ObservableProperty]
|
|
private string title = Preferences.Default.Get("name", "Nicht") + " " + Preferences.Default.Get("surname", "eingeloggt");
|
|
|
|
[ObservableProperty]
|
|
private string? username;
|
|
|
|
[ObservableProperty]
|
|
private string? password;
|
|
|
|
[ObservableProperty]
|
|
private bool isManualMode;
|
|
|
|
[ObservableProperty]
|
|
private bool isBusy;
|
|
|
|
[ObservableProperty]
|
|
private bool isDetecting;
|
|
|
|
// Explizite Command-Property für den QR-Scanner-Event, damit das Binding in XAML zuverlässig greift
|
|
public IAsyncRelayCommand<object?> QrDetectedCommand { get; }
|
|
|
|
public LoginViewModel(IAuthService auth, IAppSettings settings) {
|
|
_auth = auth;
|
|
_settings = settings;
|
|
|
|
// gespeicherte Präferenz für Logintyp laden
|
|
var lt = Preferences.Default.Get("logintype", "qr");
|
|
isManualMode = string.Equals(lt, "manual", StringComparison.OrdinalIgnoreCase);
|
|
// Scanner standardmäßig nur im QR-Modus aktivieren
|
|
IsDetecting = !isManualMode;
|
|
|
|
// Serveranzeige vorbereiten
|
|
var apiUrl = Preferences.Default.Get("apiUrl", string.Empty);
|
|
if (!string.IsNullOrWhiteSpace(apiUrl)) {
|
|
Server = apiUrl.Replace("/appapi", "").Replace("https://", "").Replace("http://", "");
|
|
ServerLabel = "Server: " + Server;
|
|
}
|
|
|
|
// Command initialisieren
|
|
QrDetectedCommand = new AsyncRelayCommand<object?>(QrDetectedAsync);
|
|
}
|
|
|
|
// DI-Konstruktor: AlertService anbinden und Alerts an VM-Event weiterreichen (analog StundeViewModel)
|
|
internal LoginViewModel(IAuthService auth, IAppSettings settings, IAlertService alertService) : this(auth, settings) {
|
|
_alerts = alertService;
|
|
if (alertService is not null) {
|
|
alertService.AlertRaised += (s, msg) => AlertEvent?.Invoke(this, msg);
|
|
}
|
|
}
|
|
|
|
partial void OnIsManualModeChanged(bool value) {
|
|
Preferences.Default.Set("logintype", value ? "manual" : "qr");
|
|
// Scanner nur aktiv, wenn QR-Modus aktiv ist
|
|
IsDetecting = !value;
|
|
}
|
|
|
|
[RelayCommand]
|
|
private async Task LoginAsync() {
|
|
if (IsBusy) return;
|
|
try {
|
|
IsBusy = true;
|
|
var user = await _auth.LoginWithCredentials(Username?.Trim() ?? string.Empty,
|
|
Password ?? string.Empty,
|
|
(Server ?? string.Empty).Trim());
|
|
|
|
Title = $"{user.Name} {user.Surname}";
|
|
InfoEvent?.Invoke(this, "Login erfolgreich");
|
|
|
|
await Shell.Current.GoToAsync("//StundenPage");
|
|
} catch (Exception ex) {
|
|
if (_alerts is not null) {
|
|
_alerts.Raise(ex.Message);
|
|
} else {
|
|
AlertEvent?.Invoke(this, ex.Message);
|
|
}
|
|
} finally {
|
|
IsBusy = false;
|
|
}
|
|
}
|
|
|
|
private async Task QrDetectedAsync(object? args) {
|
|
var now = DateTime.Now;
|
|
if ((now - _lastDetectionTime) <= _detectionInterval) return;
|
|
_lastDetectionTime = now;
|
|
|
|
try {
|
|
var token = ExtractFirstBarcodeValue(args);
|
|
if (string.IsNullOrWhiteSpace(token)) return;
|
|
|
|
var user = await _auth.LoginWithToken(token);
|
|
Title = $"{user.Name} {user.Surname}";
|
|
|
|
await Shell.Current.GoToAsync("//StundenPage");
|
|
} catch (Exception ex) {
|
|
if (_alerts is not null) {
|
|
_alerts.Raise(ex.Message);
|
|
} else {
|
|
AlertEvent?.Invoke(this, ex.Message);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static string? ExtractFirstBarcodeValue(object? args) {
|
|
try {
|
|
if (args is ZXing.Net.Maui.BarcodeDetectionEventArgs e && e.Results is not null) {
|
|
return e.Results.FirstOrDefault()?.Value;
|
|
}
|
|
} catch { }
|
|
return null;
|
|
}
|
|
} |