Refactor: Remove GlobalVar and replace with IAppSettings; restructure affected infrastructure, services, and view models for dependency injection.
This commit is contained in:
@@ -10,7 +10,6 @@ namespace Jugenddienst_Stunden.ViewModels;
|
||||
/// </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);
|
||||
@@ -59,9 +58,8 @@ public partial class LoginViewModel : ObservableObject {
|
||||
// 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) {
|
||||
public LoginViewModel(IAuthService auth) {
|
||||
_auth = auth;
|
||||
_settings = settings;
|
||||
|
||||
// gespeicherte Präferenz für Logintyp laden
|
||||
var lt = Preferences.Default.Get("logintype", "qr");
|
||||
@@ -81,7 +79,7 @@ public partial class LoginViewModel : ObservableObject {
|
||||
}
|
||||
|
||||
// DI-Konstruktor: AlertService anbinden und Alerts an VM-Event weiterreichen (analog StundeViewModel)
|
||||
internal LoginViewModel(IAuthService auth, IAppSettings settings, IAlertService alertService) : this(auth, settings) {
|
||||
internal LoginViewModel(IAuthService auth, IAlertService alertService) : this(auth) {
|
||||
_alerts = alertService;
|
||||
if (alertService is not null) {
|
||||
alertService.AlertRaised += (s, msg) => AlertEvent?.Invoke(this, msg);
|
||||
@@ -102,7 +100,7 @@ public partial class LoginViewModel : ObservableObject {
|
||||
var user = await _auth.LoginWithCredentials(Username?.Trim() ?? string.Empty,
|
||||
Password ?? string.Empty,
|
||||
(Server ?? string.Empty).Trim());
|
||||
|
||||
|
||||
Title = $"{user.Name} {user.Surname}";
|
||||
// Info zeigen und auf Bestätigung warten
|
||||
var args = new ConfirmationEventArgs("Information:", "Login erfolgreich");
|
||||
|
||||
@@ -19,13 +19,13 @@ namespace Jugenddienst_Stunden.ViewModels;
|
||||
/// </summary>
|
||||
public partial class StundeViewModel : ObservableObject, IQueryAttributable {
|
||||
private readonly IHoursService _hoursService;
|
||||
private readonly IAppSettings _settings;
|
||||
private readonly IAlertService _alertService;
|
||||
|
||||
public int Id { get; set; }
|
||||
public string Title { get; set; } = "Eintrag bearbeiten";
|
||||
public string SubTitle { get; set; } = DateTime.Today.ToString("dddd, d. MMMM yyyy");
|
||||
|
||||
//private HoursBase HoursBase = new HoursBase();
|
||||
internal Settings Settings = new Settings();
|
||||
|
||||
public event EventHandler<string> AlertEvent;
|
||||
public event EventHandler<string> InfoEvent;
|
||||
@@ -77,36 +77,19 @@ public partial class StundeViewModel : ObservableObject, IQueryAttributable {
|
||||
//public ICommand LoadDataCommand { get; private set; }
|
||||
|
||||
|
||||
public StundeViewModel(IHoursService hoursService, IAlertService alertService) {
|
||||
public StundeViewModel(IHoursService hoursService, IAlertService alertService, IAppSettings settings) {
|
||||
_hoursService = hoursService;
|
||||
_settings = settings;
|
||||
_alertService = alertService;
|
||||
SaveCommand = new AsyncRelayCommand(Save);
|
||||
DeleteConfirmCommand = new Command(async () => await DeleteConfirm());
|
||||
|
||||
if (alertService is not null) {
|
||||
alertService.AlertRaised += (s, msg) => AlertEvent?.Invoke(this, msg);
|
||||
}
|
||||
|
||||
//LoadSettingsAsync();
|
||||
_alertService.AlertRaised += (s, msg) => AlertEvent?.Invoke(this, msg);
|
||||
}
|
||||
|
||||
private async void LoadSettingsAsync() {
|
||||
try {
|
||||
Settings = await _hoursService.GetSettingsAsync();
|
||||
GlobalVar.Settings = Settings;
|
||||
|
||||
OptionsGemeinde = Settings.Gemeinden;
|
||||
OptionsProjekt = Settings.Projekte;
|
||||
OptionsFreistellung = Settings.Freistellungen;
|
||||
|
||||
GemeindeAktivSet = Settings.GemeindeAktivSet;
|
||||
ProjektAktivSet = Settings.ProjektAktivSet;
|
||||
} catch (Exception e) {
|
||||
AlertEvent?.Invoke(this, e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private async void UpdateSettingsAsync(Settings settings) {
|
||||
GlobalVar.Settings = settings;
|
||||
private void UpdateSettings(Settings settings) {
|
||||
_settings.Settings = settings;
|
||||
OptionsGemeinde = settings.Gemeinden;
|
||||
OptionsProjekt = settings.Projekte;
|
||||
OptionsFreistellung = settings.Freistellungen;
|
||||
@@ -126,7 +109,7 @@ public partial class StundeViewModel : ObservableObject, IQueryAttributable {
|
||||
}
|
||||
|
||||
//Projekt ist ein Pflichtfeld
|
||||
if (Settings.ProjektAktivSet) {
|
||||
if (_settings.Settings.ProjektAktivSet) {
|
||||
var projektId = DayTime.ProjektAktiv?.Id ?? 0;
|
||||
if (projektId == 0) {
|
||||
proceed = false;
|
||||
@@ -135,7 +118,7 @@ public partial class StundeViewModel : ObservableObject, IQueryAttributable {
|
||||
}
|
||||
|
||||
//Gemeinde ist ein Pflichtfeld
|
||||
if (Settings.GemeindeAktivSet) {
|
||||
if (_settings.Settings.GemeindeAktivSet) {
|
||||
var gemeindeId = DayTime.GemeindeAktiv?.Id ?? 0;
|
||||
if (gemeindeId == 0) {
|
||||
proceed = false;
|
||||
@@ -200,17 +183,18 @@ public partial class StundeViewModel : ObservableObject, IQueryAttributable {
|
||||
//DateTime heute = DateTime.Now;
|
||||
try {
|
||||
//var entry = await _hoursService.GetEntryAsync(Convert.ToInt32(query["load"]));
|
||||
var (entry, settings, daytimes) = await _hoursService.GetEntryWithSettingsAsync(Convert.ToInt32(query["load"]));
|
||||
UpdateSettingsAsync(settings);
|
||||
var (entry, settings, daytimes) =
|
||||
await _hoursService.GetEntryWithSettingsAsync(Convert.ToInt32(query["load"]));
|
||||
UpdateSettings(settings);
|
||||
|
||||
DayTime = entry;
|
||||
DayTime.TimeSpanVon = entry.Begin.ToTimeSpan();
|
||||
DayTime.TimeSpanBis = entry.End.ToTimeSpan();
|
||||
|
||||
DayTime.GemeindeAktiv = OptionsGemeinde.FirstOrDefault(Gemeinde => Gemeinde.Id == DayTime.Gemeinde) ??
|
||||
new Gemeinde();
|
||||
new Gemeinde();
|
||||
DayTime.ProjektAktiv = OptionsProjekt.FirstOrDefault(Projekt => Projekt.Id == DayTime.Projekt) ??
|
||||
new Projekt();
|
||||
new Projekt();
|
||||
DayTime.FreistellungAktiv =
|
||||
OptionsFreistellung.FirstOrDefault(Freistellung => Freistellung.Id == DayTime.Free) ??
|
||||
new Freistellung();
|
||||
@@ -229,11 +213,6 @@ public partial class StundeViewModel : ObservableObject, IQueryAttributable {
|
||||
OnPropertyChanged(nameof(DayTimes));
|
||||
} catch (Exception e) {
|
||||
AlertEvent?.Invoke(this, e.Message);
|
||||
} finally {
|
||||
//Evtl. noch die anderen Zeiten des gleichen Tages holen
|
||||
//var day = await _hoursService.GetDayWithSettingsAsync(DayTime.Day);
|
||||
//DayTimes = day.dayTimes;
|
||||
//OnPropertyChanged(nameof(DayTimes));
|
||||
}
|
||||
|
||||
//OnPropertyChanged(nameof(DayTime));
|
||||
@@ -246,7 +225,7 @@ public partial class StundeViewModel : ObservableObject, IQueryAttributable {
|
||||
//Bei neuem Eintrag die vorhandenen des gleichen Tages anzeigen
|
||||
try {
|
||||
var (list, settings) = await _hoursService.GetDayWithSettingsAsync(_date);
|
||||
UpdateSettingsAsync(settings);
|
||||
UpdateSettings(settings);
|
||||
DayTimes = list;
|
||||
OnPropertyChanged(nameof(DayTimes));
|
||||
} catch (Exception) {
|
||||
@@ -257,7 +236,7 @@ public partial class StundeViewModel : ObservableObject, IQueryAttributable {
|
||||
} finally {
|
||||
DayTime = new DayTime();
|
||||
DayTime.Day = _date;
|
||||
DayTime.EmployeeId = GlobalVar.EmployeeId;
|
||||
DayTime.EmployeeId = _settings.EmployeeId;
|
||||
DayTime.GemeindeAktiv = new Gemeinde();
|
||||
DayTime.ProjektAktiv = new Projekt();
|
||||
DayTime.FreistellungAktiv = new Freistellung();
|
||||
|
||||
@@ -15,6 +15,7 @@ namespace Jugenddienst_Stunden.ViewModels;
|
||||
/// </summary>
|
||||
public partial class StundenViewModel : ObservableObject, IQueryAttributable, INotifyPropertyChanged {
|
||||
private readonly IHoursService _hoursService;
|
||||
private readonly IAppSettings _settings;
|
||||
|
||||
public ICommand NewEntryCommand { get; }
|
||||
public ICommand SelectEntryCommand { get; }
|
||||
@@ -50,7 +51,13 @@ public partial class StundenViewModel : ObservableObject, IQueryAttributable, IN
|
||||
/// </summary>
|
||||
[ObservableProperty] private List<DayTime> dayTimes = new List<DayTime>();
|
||||
|
||||
public string Title { get; set; } = GlobalVar.Name + " " + GlobalVar.Surname;
|
||||
/// <summary>
|
||||
/// Der Titel der Stundenübersicht ist der aktuelle Benutzername
|
||||
/// </summary>
|
||||
public string Title {
|
||||
get => _settings.Name + " " + _settings.Surname;
|
||||
set;
|
||||
}
|
||||
|
||||
[ObservableProperty] private Hours hours;
|
||||
|
||||
@@ -82,14 +89,10 @@ public partial class StundenViewModel : ObservableObject, IQueryAttributable, IN
|
||||
LoadOverview = "Lade Summen für " + dateToday.ToString("MMMM yy");
|
||||
// Task.Run(() => LoadDay(value));
|
||||
// NICHT Task.Run: LoadDay aktualisiert UI-gebundene Properties
|
||||
MainThread.BeginInvokeOnMainThread(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
MainThread.BeginInvokeOnMainThread(async () => {
|
||||
try {
|
||||
await LoadDay(dateToday);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
} catch (Exception ex) {
|
||||
AlertEvent?.Invoke(this, ex.Message);
|
||||
}
|
||||
});
|
||||
@@ -162,8 +165,9 @@ public partial class StundenViewModel : ObservableObject, IQueryAttributable, IN
|
||||
/// <summary>
|
||||
/// CTOR (DI)
|
||||
/// </summary>
|
||||
public StundenViewModel(IHoursService hoursService) {
|
||||
public StundenViewModel(IHoursService hoursService, IAppSettings appSettings) {
|
||||
_hoursService = hoursService;
|
||||
_settings = appSettings;
|
||||
Hours = new Hours();
|
||||
|
||||
LoadOverview = "Lade Summen für " + DateToday.ToString("MMMM");
|
||||
@@ -177,19 +181,15 @@ public partial class StundenViewModel : ObservableObject, IQueryAttributable, IN
|
||||
// Task task = LoadDay(DateTime.Today);
|
||||
// Beim Startup NICHT direkt im CTOR laden (kann Startup/Navigation blockieren)
|
||||
// Stattdessen via Dispatcher "nach" dem Aufbau starten:
|
||||
MainThread.BeginInvokeOnMainThread(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
MainThread.BeginInvokeOnMainThread(async () => {
|
||||
try {
|
||||
await LoadDay(DateTime.Today);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
} catch (Exception ex) {
|
||||
AlertEvent?.Invoke(this, ex.Message);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
@@ -244,16 +244,14 @@ public partial class StundenViewModel : ObservableObject, IQueryAttributable, IN
|
||||
/// </summary>
|
||||
public async Task LoadDay(DateTime date) {
|
||||
// kleine Initialwerte sind ok, aber UI-Thread sicher setzen:
|
||||
await MainThread.InvokeOnMainThreadAsync(() =>
|
||||
{
|
||||
await MainThread.InvokeOnMainThreadAsync(() => {
|
||||
DayTotal = new TimeOnly(0);
|
||||
Sollstunden = new TimeOnly(0);
|
||||
});
|
||||
try {
|
||||
var (dayTimes, settings) = await _hoursService.GetDayWithSettingsAsync(date);
|
||||
|
||||
await MainThread.InvokeOnMainThreadAsync(() =>
|
||||
{
|
||||
await MainThread.InvokeOnMainThreadAsync(() => {
|
||||
DayTimes = dayTimes;
|
||||
Settings = settings;
|
||||
GemeindeAktivSet = Settings.GemeindeAktivSet;
|
||||
@@ -275,8 +273,7 @@ public partial class StundenViewModel : ObservableObject, IQueryAttributable, IN
|
||||
}
|
||||
|
||||
_soll = Settings.Nominal.Where(w => w.Timetable == dt.TimeTable && w.Wochentag == dt.Wday).ToList();
|
||||
if (_soll.Count > 0)
|
||||
{
|
||||
if (_soll.Count > 0) {
|
||||
var soll = TimeOnly.FromTimeSpan(TimeSpan.FromHours(_soll[0].Zeit));
|
||||
await MainThread.InvokeOnMainThreadAsync(() => Sollstunden = soll);
|
||||
}
|
||||
@@ -288,17 +285,15 @@ public partial class StundenViewModel : ObservableObject, IQueryAttributable, IN
|
||||
//Nach der Tagessumme die anderen Tage anhängen
|
||||
if (DayTimes != null) {
|
||||
var more = await _hoursService.GetDayRangeAsync(date.AddDays(1), date.AddDays(3));
|
||||
if (more != null && more.Count > 0)
|
||||
{
|
||||
if (more != null && more.Count > 0) {
|
||||
await MainThread.InvokeOnMainThreadAsync(() =>
|
||||
DayTimes = DayTimes.Concat(more).ToList()
|
||||
);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
||||
await MainThread.InvokeOnMainThreadAsync(() =>
|
||||
{
|
||||
|
||||
await MainThread.InvokeOnMainThreadAsync(() => {
|
||||
DayTimes = new List<DayTime>();
|
||||
//TODO: hier könnte auch ein Fehler kommen, dann wäre InfoEvent falsch.
|
||||
|
||||
@@ -310,12 +305,11 @@ public partial class StundenViewModel : ObservableObject, IQueryAttributable, IN
|
||||
InfoEvent?.Invoke(this, e.Message);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
} finally {
|
||||
await MainThread.InvokeOnMainThreadAsync(() =>
|
||||
{
|
||||
await MainThread.InvokeOnMainThreadAsync(() => {
|
||||
OnPropertyChanged(nameof(DayTotal));
|
||||
OnPropertyChanged(nameof(Sollstunden));
|
||||
OnPropertyChanged(nameof(DateToday));
|
||||
|
||||
Reference in New Issue
Block a user