diff --git a/SlipItIn.AppHost/AppHost.cs b/SlipItIn.AppHost/AppHost.cs index cdbb743..1e99437 100644 --- a/SlipItIn.AppHost/AppHost.cs +++ b/SlipItIn.AppHost/AppHost.cs @@ -1,8 +1,7 @@ var builder = DistributedApplication.CreateBuilder(args); var db = builder.AddPostgres("pgsql") - .AddDatabase("postgresdb") - ; + .AddDatabase("postgresdb"); var server = builder.AddProject("server") .WithReference(db) diff --git a/SlipItIn/App.xaml.cs b/SlipItIn/App.xaml.cs index 9574392..dcd0776 100644 --- a/SlipItIn/App.xaml.cs +++ b/SlipItIn/App.xaml.cs @@ -8,34 +8,47 @@ public partial class App : Application public App() { InitializeComponent(); - _ = InitializeAsync(); } protected override Window CreateWindow(IActivationState? activationState) { var window = new Window(new AppShell()); + + window.Created += async (_, _) => + { + await InitializeSafeAsync(); + }; + window.Resumed += async (_, _) => { var gameStateService = ServiceHelper.GetRequiredService(); await gameStateService.ResyncAsync(); }; + return window; } - private static async Task InitializeAsync() + private static async Task InitializeSafeAsync() { - var authSession = ServiceHelper.GetRequiredService(); - var signalR = ServiceHelper.GetRequiredService(); - var gameStateService = ServiceHelper.GetRequiredService(); - - await authSession.InitializeAsync(); - await gameStateService.InitializeAsync(); - - if (!string.IsNullOrWhiteSpace(authSession.AccessToken)) + try { - var connected = await signalR.ConnectAsync(authSession.AccessToken); - if (connected) - await gameStateService.ResyncAsync(); + var authSession = ServiceHelper.GetRequiredService(); + var signalR = ServiceHelper.GetRequiredService(); + var gameStateService = ServiceHelper.GetRequiredService(); + + await authSession.InitializeAsync(); + await gameStateService.InitializeAsync(); + + if (!string.IsNullOrWhiteSpace(authSession.AccessToken)) + { + var connected = await signalR.ConnectAsync(authSession.AccessToken); + if (connected) + await gameStateService.ResyncAsync(); + } + } + catch + { + // Start darf nicht abstürzen, wenn Session/Netzwerk fehlschlägt. } } } diff --git a/SlipItIn/AppShell.xaml b/SlipItIn/AppShell.xaml index 2d8af88..edb2911 100644 --- a/SlipItIn/AppShell.xaml +++ b/SlipItIn/AppShell.xaml @@ -3,22 +3,12 @@ x:Class="SlipItIn.AppShell" xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" - xmlns:views="clr-namespace:SlipItIn.Views"> + xmlns:views="clr-namespace:SlipItIn.Views" + FlyoutBehavior="Disabled"> - - - - - - - diff --git a/SlipItIn/AppShell.xaml.cs b/SlipItIn/AppShell.xaml.cs index 5f8c199..edf85c3 100644 --- a/SlipItIn/AppShell.xaml.cs +++ b/SlipItIn/AppShell.xaml.cs @@ -7,5 +7,8 @@ public partial class AppShell : Shell public AppShell() { InitializeComponent(); + Routing.RegisterRoute(nameof(RegisterPage), typeof(RegisterPage)); + Routing.RegisterRoute(nameof(LobbyPage), typeof(LobbyPage)); + Routing.RegisterRoute(nameof(GameBoardPage), typeof(GameBoardPage)); } } diff --git a/SlipItIn/Services/GameStateService.cs b/SlipItIn/Services/GameStateService.cs index 573dd9f..51b08f8 100644 --- a/SlipItIn/Services/GameStateService.cs +++ b/SlipItIn/Services/GameStateService.cs @@ -50,7 +50,21 @@ public class GameStateService : IGameStateService }; _signalR.ErrorReceived += (_, error) => _messenger.Send(new ErrorOccurredMessage(error)); - _signalR.ConnectionStateChanged += (_, connected) => _messenger.Send(new ConnectionStateChangedMessage(connected)); + _signalR.ConnectionStateChanged += async (_, connected) => + { + _messenger.Send(new ConnectionStateChangedMessage(connected)); + if (connected) + { + try + { + await ResyncAsync(); + } + catch (Exception ex) + { + _messenger.Send(new ErrorOccurredMessage($"Resync fehlgeschlagen: {ex.Message}")); + } + } + }; } public async Task InitializeAsync() diff --git a/SlipItIn/Services/SignalRService.cs b/SlipItIn/Services/SignalRService.cs index 55416e1..b07d87b 100644 --- a/SlipItIn/Services/SignalRService.cs +++ b/SlipItIn/Services/SignalRService.cs @@ -108,11 +108,17 @@ public class SignalRService : ISignalRService _hubConnection = new HubConnectionBuilder() .WithUrl(_configuration.HubUrl, options => { - options.AccessTokenProvider = () => Task.FromResult(token); + options.AccessTokenProvider = () => Task.FromResult(_authSession.AccessToken ?? token); }) .WithAutomaticReconnect([TimeSpan.Zero, TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(30)]) .Build(); + _hubConnection.Reconnecting += _ => + { + ConnectionStateChanged?.Invoke(this, false); + return Task.CompletedTask; + }; + _hubConnection.Closed += _ => { ConnectionStateChanged?.Invoke(this, false); diff --git a/SlipItIn/SlipItIn.csproj b/SlipItIn/SlipItIn.csproj index 3146f80..81b956c 100644 --- a/SlipItIn/SlipItIn.csproj +++ b/SlipItIn/SlipItIn.csproj @@ -110,6 +110,9 @@ + + MSBuild:Compile + MSBuild:Compile diff --git a/SlipItIn/ViewModels/GameBoardViewModel.cs b/SlipItIn/ViewModels/GameBoardViewModel.cs index 2e6b94a..78737f1 100644 --- a/SlipItIn/ViewModels/GameBoardViewModel.cs +++ b/SlipItIn/ViewModels/GameBoardViewModel.cs @@ -42,7 +42,6 @@ public partial class GameBoardViewModel : BaseViewModel, _gameStateService = gameStateService; _authSession = authSession; - WeakReferenceMessenger.Default.RegisterAll(this); IsActive = true; } diff --git a/SlipItIn/ViewModels/LobbyViewModel.cs b/SlipItIn/ViewModels/LobbyViewModel.cs index c4cfa13..dc17d24 100644 --- a/SlipItIn/ViewModels/LobbyViewModel.cs +++ b/SlipItIn/ViewModels/LobbyViewModel.cs @@ -42,7 +42,6 @@ public partial class LobbyViewModel : BaseViewModel, _apiService = apiService; IsConnected = _signalR.IsConnected; - //WeakReferenceMessenger.Default.RegisterAll(this); IsActive = true; } @@ -127,7 +126,7 @@ public partial class LobbyViewModel : BaseViewModel, public async void Receive(GameStartedMessage message) { - await MainThread.InvokeOnMainThreadAsync(() => Shell.Current.GoToAsync($"//{nameof(Views.GameBoardPage)}")); + await MainThread.InvokeOnMainThreadAsync(() => Shell.Current.GoToAsync(nameof(Views.GameBoardPage))); } public void Receive(ErrorOccurredMessage message) diff --git a/SlipItIn/ViewModels/LoginViewModel.cs b/SlipItIn/ViewModels/LoginViewModel.cs index c09d7e9..ef8cbdb 100644 --- a/SlipItIn/ViewModels/LoginViewModel.cs +++ b/SlipItIn/ViewModels/LoginViewModel.cs @@ -14,10 +14,10 @@ public partial class LoginViewModel : BaseViewModel private readonly IGameStateService _gameStateService; [ObservableProperty] - public partial string Email { get; set; } + private string email = string.Empty; [ObservableProperty] - public partial string Password { get; set; } + private string password = string.Empty; public LoginViewModel(IApiService apiService, IAuthSessionService authSession, ISignalRService signalR, IGameStateService gameStateService) { @@ -28,7 +28,7 @@ public partial class LoginViewModel : BaseViewModel } [RelayCommand] - private Task GoToRegisterAsync() => Shell.Current.GoToAsync($"//{nameof(RegisterPage)}"); + private Task GoToRegisterAsync() => Shell.Current.GoToAsync(nameof(RegisterPage)); [RelayCommand] private async Task LoginAsync() @@ -44,7 +44,7 @@ public partial class LoginViewModel : BaseViewModel await _authSession.SetSessionAsync(response); await _signalR.ConnectAsync(response.Token); await _gameStateService.InitializeAsync(); - await Shell.Current.GoToAsync($"//{nameof(LobbyPage)}"); + await Shell.Current.GoToAsync(nameof(LobbyPage)); }, "Anmeldung läuft..."); } @@ -53,9 +53,9 @@ public partial class LoginViewModel : BaseViewModel { bool isAuthenticated = _authSession.IsAuthenticated; - if ( isAuthenticated) + if (isAuthenticated) { - await Shell.Current.GoToAsync($"//{nameof(LobbyPage)}"); + await Shell.Current.GoToAsync(nameof(LobbyPage)); } } } diff --git a/SlipItIn/ViewModels/RegisterViewModel.cs b/SlipItIn/ViewModels/RegisterViewModel.cs index 40db412..572807f 100644 --- a/SlipItIn/ViewModels/RegisterViewModel.cs +++ b/SlipItIn/ViewModels/RegisterViewModel.cs @@ -13,13 +13,13 @@ public partial class RegisterViewModel : BaseViewModel private readonly ISignalRService _signalR; [ObservableProperty] - public partial string Username { get; set; } = string.Empty; + private string username = string.Empty; [ObservableProperty] - public partial string Email { get; set; } = string.Empty; + private string email = string.Empty; [ObservableProperty] - public partial string Password { get; set; } = string.Empty; + private string password = string.Empty; public RegisterViewModel(IApiService apiService, IAuthSessionService authSession, ISignalRService signalR) { @@ -45,7 +45,7 @@ public partial class RegisterViewModel : BaseViewModel await _authSession.SetSessionAsync(response); await _signalR.ConnectAsync(response.Token); - await Shell.Current.GoToAsync($"//{nameof(LobbyPage)}"); + await Shell.Current.GoToAsync(nameof(LobbyPage)); }, "Registrierung läuft..."); } }