From b9758b04975a2782dd9a218eac96cddc1330aa45 Mon Sep 17 00:00:00 2001 From: beo3000 Date: Tue, 11 Nov 2025 20:26:46 +0100 Subject: [PATCH] singal undoredo state to other clients --- KoogleApp/Hub/SharedModelHub.cs | 157 +++++++++++--------- KoogleApp/Services/HubConnectionService.cs | 48 ++++-- KoogleApp/Store/Game/ThrowPanel/Actions.cs | 2 +- KoogleApp/Store/Game/ThrowPanel/Effects.cs | 2 +- KoogleApp/Store/Game/ThrowPanel/Reducers.cs | 2 +- KoogleApp/Store/Game/ThrowPanel/State.cs | 9 +- KoogleApp/Store/Game/UndoRedo/Actions.cs | 4 + KoogleApp/Store/Game/UndoRedo/Effects.cs | 13 ++ KoogleApp/Store/Game/UndoRedo/Reducers.cs | 6 + 9 files changed, 148 insertions(+), 95 deletions(-) diff --git a/KoogleApp/Hub/SharedModelHub.cs b/KoogleApp/Hub/SharedModelHub.cs index 33422bf..0a15908 100644 --- a/KoogleApp/Hub/SharedModelHub.cs +++ b/KoogleApp/Hub/SharedModelHub.cs @@ -17,6 +17,8 @@ namespace KoogleApp.Hub { private readonly IGameStatusDataService _dataService; private readonly AuthenticationStateProvider _authenticationStateProvider; + + private readonly ILogger _logger; //private HubConnection _hubConnection; //public async Task UpdateText(string newText) @@ -25,89 +27,91 @@ namespace KoogleApp.Hub //} public SharedModelHub(IGameStatusDataService dataService, NavigationManager navigationManager, - AuthenticationStateProvider authenticationStateProvider) + AuthenticationStateProvider authenticationStateProvider, + ILogger logger) { _dataService = dataService; _authenticationStateProvider = authenticationStateProvider; + _logger = logger; } - public async Task UpdateThrowPanelState(ThrowPanelState panelState, string username) - { - await Clients.All.SendAsync("UpdateThrowPanelState", panelState); - } + //public async Task UpdateThrowPanelState(ThrowPanelState panelState, string username) + //{ + // await Clients.All.SendAsync("UpdateThrowPanelState", panelState); + //} - public async Task SendDataUpdate(GameStatus content, string username) - { - _dataService.UpdateData(content, username); - var currentData = _dataService.GetCurrentData(); + //public async Task SendDataUpdate(GameStatus content, string username) + //{ + // _dataService.UpdateData(content, username); + // var currentData = _dataService.GetCurrentData(); - var changeEvent = new DataChangeEvent - { - Content = content, - Username = currentData.LastModifiedBy, - Timestamp = currentData.LastModified, - Version = currentData.Version - }; + // var changeEvent = new DataChangeEvent + // { + // Content = content, + // Username = currentData.LastModifiedBy, + // Timestamp = currentData.LastModified, + // Version = currentData.Version + // }; - await Clients.All.SendAsync("ReceiveDataUpdate", changeEvent); - await BroadcastUndoRedoState(); - } + // await Clients.All.SendAsync("ReceiveDataUpdate", changeEvent); + // await BroadcastUndoRedoState(); + //} - public async Task RequestUndo(string username) - { - var success = _dataService.Undo(); + //public async Task RequestUndo(string username) + //{ + // var success = _dataService.Undo(); - if (success) - { - var currentData = _dataService.GetCurrentData(); - var changeEvent = new DataChangeEvent - { - Content = currentData.Status, - Username = $"{username} (Undo)", - Timestamp = currentData.LastModified, - Version = currentData.Version - }; + // if (success) + // { + // var currentData = _dataService.GetCurrentData(); + // var changeEvent = new DataChangeEvent + // { + // Content = currentData.Status, + // Username = $"{username} (Undo)", + // Timestamp = currentData.LastModified, + // Version = currentData.Version + // }; - await Clients.All.SendAsync("ReceiveDataUpdate", changeEvent); - await BroadcastUndoRedoState(); - } - } + // await Clients.All.SendAsync("ReceiveDataUpdate", changeEvent); + // await BroadcastUndoRedoState(); + // } + //} - public async Task RequestRedo(string username) - { - var success = _dataService.Redo(); + //public async Task RequestRedo(string username) + //{ + // var success = _dataService.Redo(); - if (success) - { - var currentData = _dataService.GetCurrentData(); - var changeEvent = new DataChangeEvent - { - Content = currentData.Status, - Username = $"{username} (Redo)", - Timestamp = currentData.LastModified, - Version = currentData.Version - }; + // if (success) + // { + // var currentData = _dataService.GetCurrentData(); + // var changeEvent = new DataChangeEvent + // { + // Content = currentData.Status, + // Username = $"{username} (Redo)", + // Timestamp = currentData.LastModified, + // Version = currentData.Version + // }; - await Clients.All.SendAsync("ReceiveDataUpdate", changeEvent); - await BroadcastUndoRedoState(); - } - } + // await Clients.All.SendAsync("ReceiveDataUpdate", changeEvent); + // await BroadcastUndoRedoState(); + // } + //} - public async Task GetUndoRedoState() - { - await BroadcastUndoRedoState(); - } + //public async Task GetUndoRedoState() + //{ + // await BroadcastUndoRedoState(); + //} - private async Task BroadcastUndoRedoState() - { - var state = new UndoRedoState - { - CanUndo = _dataService.CanUndo(), - CanRedo = _dataService.CanRedo() - }; + //private async Task BroadcastUndoRedoState() + //{ + // var state = new UndoRedoState + // { + // CanUndo = _dataService.CanUndo(), + // CanRedo = _dataService.CanRedo() + // }; - await Clients.All.SendAsync("UpdateUndoRedoState", state); - } + // await Clients.All.SendAsync("UpdateUndoRedoState", state); + //} public override async Task OnConnectedAsync() { @@ -120,12 +124,6 @@ namespace KoogleApp.Hub public async Task BroadcastThrowPanelState(ThrowPanelState state, IDispatcher dispatcher) { - //if (_hubConnection?.State != HubConnectionState.Connected) - //{ - // //_logger.LogWarning("Cannot add activity: not connected"); - // return; - //} - try { await Clients.Others.SendAsync("ReceiveThrowPanelState", state); @@ -137,7 +135,20 @@ namespace KoogleApp.Hub } catch (Exception ex) { - //_logger.LogError(ex, "Failed to add activity"); + _logger.LogError(ex, "Failed to BroadcastThrowPanelState"); + // Optional: Error-Handling Action dispatchen + } + } + + public async Task BroadcastUndoRedoState(UndoRedoState state, IDispatcher dispatcher) + { + try + { + await Clients.Others.SendAsync("ReceiveUndoRedoState", state); + } + catch (Exception ex) + { + _logger.LogError(ex, "Failed to BroadcastThrowPanelState"); // Optional: Error-Handling Action dispatchen } } diff --git a/KoogleApp/Services/HubConnectionService.cs b/KoogleApp/Services/HubConnectionService.cs index af8f3bb..fd2a0a5 100644 --- a/KoogleApp/Services/HubConnectionService.cs +++ b/KoogleApp/Services/HubConnectionService.cs @@ -1,5 +1,6 @@ using Fluxor; using KoogleApp.Store.Game.ThrowPanel; +using KoogleApp.Store.Game.UndoRedo; using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Authorization; using Microsoft.AspNetCore.SignalR.Client; @@ -12,12 +13,15 @@ namespace KoogleApp.Services private readonly AuthenticationStateProvider _authenticationStateProvider; private HubConnection? _hubConnection; private string? _userName; + private readonly ILogger _logger; public HubConnectionService(NavigationManager navigationManager, - AuthenticationStateProvider authenticationStateProvider) + AuthenticationStateProvider authenticationStateProvider, + ILogger logger) { _navigationManager = navigationManager; _authenticationStateProvider = authenticationStateProvider; + _logger = logger; } public HubConnection Connection => _hubConnection @@ -43,26 +47,24 @@ namespace KoogleApp.Services .Build(); - _hubConnection.On("ReceiveThrowPanelState", state => { - dispatcher.Dispatch(new ReceiveStateFromServerAction(state)); + dispatcher.Dispatch(new ReceiveThrowPanelStateFromServerAction(state)); }); - // _hubConnection.On("ReceiveTextUpdate", (newText) => - // { - // _sharedText = newText; - // InvokeAsync(StateHasChanged); - // }); + _hubConnection.On("ReceiveUndoRedoState", (state) => + { + dispatcher.Dispatch(new ReceiveUndoRedoStateFromServerAction(state)); + }); await _hubConnection.StartAsync(); } - public async Task HandelBroadcastThrowPanelStateAction(BroadcastThrowPanelStateAction action, IDispatcher dispatcher) + public async Task BroadcastThrowPanelState(ThrowPanelState state, IDispatcher dispatcher) { if (_hubConnection?.State != HubConnectionState.Connected) { - //_logger.LogWarning("Cannot add activity: not connected"); + _logger.LogWarning("Cannot BroadcastThrowPanelState: not connected"); return; } @@ -70,7 +72,7 @@ namespace KoogleApp.Services { if (_hubConnection is not null) { - await _hubConnection.SendAsync("BroadcastThrowPanelState", action.State); + await _hubConnection.SendAsync("BroadcastThrowPanelState", state); } //await Clients.Others.SendAsync("ReceiveThrowPanelState", new ThrowPanelState()); @@ -82,7 +84,29 @@ namespace KoogleApp.Services } catch (Exception ex) { - //_logger.LogError(ex, "Failed to add activity"); + _logger.LogError(ex, "Failed to BroadcastThrowPanelState"); + // Optional: Error-Handling Action dispatchen + } + } + + public async Task BroadcastUndoRedoState(UndoRedoState state, IDispatcher dispatcher) + { + if (_hubConnection?.State != HubConnectionState.Connected) + { + _logger.LogWarning("Cannot BroadcastUndoRedoState: not connected"); + return; + } + + try + { + if (_hubConnection is not null) + { + await _hubConnection.SendAsync("BroadcastUndoRedoState", state); + } + } + catch (Exception ex) + { + _logger.LogError(ex, "Failed to BroadcastUndoRedoState"); // Optional: Error-Handling Action dispatchen } } diff --git a/KoogleApp/Store/Game/ThrowPanel/Actions.cs b/KoogleApp/Store/Game/ThrowPanel/Actions.cs index a24ea5e..a62cb35 100644 --- a/KoogleApp/Store/Game/ThrowPanel/Actions.cs +++ b/KoogleApp/Store/Game/ThrowPanel/Actions.cs @@ -14,7 +14,7 @@ namespace KoogleApp.Store.Game.ThrowPanel public record UpdatePinStateByNumberAction(int Number); - public record ReceiveStateFromServerAction(ThrowPanelState State); + public record ReceiveThrowPanelStateFromServerAction(ThrowPanelState State); public record LoadStateFromSessionAction(); diff --git a/KoogleApp/Store/Game/ThrowPanel/Effects.cs b/KoogleApp/Store/Game/ThrowPanel/Effects.cs index 0cb8155..250831c 100644 --- a/KoogleApp/Store/Game/ThrowPanel/Effects.cs +++ b/KoogleApp/Store/Game/ThrowPanel/Effects.cs @@ -227,7 +227,7 @@ namespace KoogleApp.Store.Game.ThrowPanel [EffectMethod] public async Task HandelBroadcastThrowPanelStateAction(BroadcastThrowPanelStateAction action, IDispatcher dispatcher) { - await _sharedHubService.HandelBroadcastThrowPanelStateAction(action, dispatcher); + await _sharedHubService.BroadcastThrowPanelState(action.State, dispatcher); } diff --git a/KoogleApp/Store/Game/ThrowPanel/Reducers.cs b/KoogleApp/Store/Game/ThrowPanel/Reducers.cs index cf58334..cbfae86 100644 --- a/KoogleApp/Store/Game/ThrowPanel/Reducers.cs +++ b/KoogleApp/Store/Game/ThrowPanel/Reducers.cs @@ -5,7 +5,7 @@ namespace KoogleApp.Store.Game.ThrowPanel public static class ThrowPanelStateReducer { [ReducerMethod] - public static ThrowPanelState OnReceiveStateFromServer(ThrowPanelState state, ReceiveStateFromServerAction action) + public static ThrowPanelState OnReceiveStateFromServer(ThrowPanelState state, ReceiveThrowPanelStateFromServerAction action) { return action.State; } diff --git a/KoogleApp/Store/Game/ThrowPanel/State.cs b/KoogleApp/Store/Game/ThrowPanel/State.cs index 84e94ef..b416f3e 100644 --- a/KoogleApp/Store/Game/ThrowPanel/State.cs +++ b/KoogleApp/Store/Game/ThrowPanel/State.cs @@ -13,7 +13,7 @@ namespace KoogleApp.Store.Game.ThrowPanel public enum ThrowPanelStateStatus { - undefined, + Undefined, GameStart, BeforeThrow, AfterThrow, @@ -30,14 +30,9 @@ namespace KoogleApp.Store.Game.ThrowPanel public ThrowPanelState() : this(BellValue:false, IsStated:false, Pin1Value:false, Pin2Value:false, Pin3Value: false, Pin4Value: false, Pin5Value: false, Pin6Value: false, Pin7Value: false, Pin8Value: false, Pin9Value: false, Pin1Disabled:false, Pin2Disabled:false, Pin3Disabled: false, Pin4Disabled: false, Pin5Disabled: false, Pin6Disabled: false, Pin7Disabled: false, Pin8Disabled: false, Pin9Disabled: false, - ThrowsPerRound : 3, ThrowCounterPerRound : 1, ThrowMode : ThrowMode.Reposition, ThrowPanelStateStatus: ThrowPanelStateStatus.undefined, ThrowCounter:0 + ThrowsPerRound : 3, ThrowCounterPerRound : 1, ThrowMode : ThrowMode.Reposition, ThrowPanelStateStatus: ThrowPanelStateStatus.Undefined, ThrowCounter:0 ) { } } - - // Actions - - - } \ No newline at end of file diff --git a/KoogleApp/Store/Game/UndoRedo/Actions.cs b/KoogleApp/Store/Game/UndoRedo/Actions.cs index c27b6c1..10e9fbf 100644 --- a/KoogleApp/Store/Game/UndoRedo/Actions.cs +++ b/KoogleApp/Store/Game/UndoRedo/Actions.cs @@ -7,4 +7,8 @@ public record CanUndoRedoAction(bool CanUndo, bool CanRedo, int Version, DateTime ModifiedAt, string ModifiedBy); public record UpdateUndoRedoStateAction(); + + public record BroadcastUndoRedoStateAction(UndoRedoState State); + + public record ReceiveUndoRedoStateFromServerAction(UndoRedoState State); } diff --git a/KoogleApp/Store/Game/UndoRedo/Effects.cs b/KoogleApp/Store/Game/UndoRedo/Effects.cs index 5735d01..cd10047 100644 --- a/KoogleApp/Store/Game/UndoRedo/Effects.cs +++ b/KoogleApp/Store/Game/UndoRedo/Effects.cs @@ -65,6 +65,19 @@ namespace KoogleApp.Store.Game.UndoRedo dispatcher.Dispatch(new CanUndoRedoAction(canUndo,canRedo, currentData.Version, currentData.LastModified, currentData.LastModifiedBy)); return Task.CompletedTask; } + + [EffectMethod] + public Task HandleCanUndoRedoAction(CanUndoRedoAction action, IDispatcher dispatcher) + { + dispatcher.Dispatch(new BroadcastUndoRedoStateAction(_state.Value)); + return Task.CompletedTask; + } + + [EffectMethod] + public async Task HandelBroadcastUndoRedoStateAction(BroadcastUndoRedoStateAction action, IDispatcher dispatcher) + { + await _sharedHubService.BroadcastUndoRedoState(action.State, dispatcher); + } } } diff --git a/KoogleApp/Store/Game/UndoRedo/Reducers.cs b/KoogleApp/Store/Game/UndoRedo/Reducers.cs index 2713db7..0904a92 100644 --- a/KoogleApp/Store/Game/UndoRedo/Reducers.cs +++ b/KoogleApp/Store/Game/UndoRedo/Reducers.cs @@ -16,5 +16,11 @@ namespace KoogleApp.Store.Game.UndoRedo IsInitialized = true }; } + + [ReducerMethod] + public static UndoRedoState OnReceiveStateFromServer(UndoRedoState state, ReceiveUndoRedoStateFromServerAction action) + { + return action.State; + } } }