singal undoredo state to other clients

This commit is contained in:
beo3000 2025-11-11 20:26:46 +01:00
parent 0df393812a
commit b9758b0497
9 changed files with 148 additions and 95 deletions

View File

@ -17,6 +17,8 @@ namespace KoogleApp.Hub
{ {
private readonly IGameStatusDataService _dataService; private readonly IGameStatusDataService _dataService;
private readonly AuthenticationStateProvider _authenticationStateProvider; private readonly AuthenticationStateProvider _authenticationStateProvider;
private readonly ILogger<SharedModelHub> _logger;
//private HubConnection _hubConnection; //private HubConnection _hubConnection;
//public async Task UpdateText(string newText) //public async Task UpdateText(string newText)
@ -25,89 +27,91 @@ namespace KoogleApp.Hub
//} //}
public SharedModelHub(IGameStatusDataService dataService, NavigationManager navigationManager, public SharedModelHub(IGameStatusDataService dataService, NavigationManager navigationManager,
AuthenticationStateProvider authenticationStateProvider) AuthenticationStateProvider authenticationStateProvider,
ILogger<SharedModelHub> logger)
{ {
_dataService = dataService; _dataService = dataService;
_authenticationStateProvider = authenticationStateProvider; _authenticationStateProvider = authenticationStateProvider;
_logger = logger;
} }
public async Task UpdateThrowPanelState(ThrowPanelState panelState, string username) //public async Task UpdateThrowPanelState(ThrowPanelState panelState, string username)
{ //{
await Clients.All.SendAsync("UpdateThrowPanelState", panelState); // await Clients.All.SendAsync("UpdateThrowPanelState", panelState);
} //}
public async Task SendDataUpdate(GameStatus content, string username) //public async Task SendDataUpdate(GameStatus content, string username)
{ //{
_dataService.UpdateData(content, username); // _dataService.UpdateData(content, username);
var currentData = _dataService.GetCurrentData(); // var currentData = _dataService.GetCurrentData();
var changeEvent = new DataChangeEvent // var changeEvent = new DataChangeEvent
{ // {
Content = content, // Content = content,
Username = currentData.LastModifiedBy, // Username = currentData.LastModifiedBy,
Timestamp = currentData.LastModified, // Timestamp = currentData.LastModified,
Version = currentData.Version // Version = currentData.Version
}; // };
await Clients.All.SendAsync("ReceiveDataUpdate", changeEvent); // await Clients.All.SendAsync("ReceiveDataUpdate", changeEvent);
await BroadcastUndoRedoState(); // await BroadcastUndoRedoState();
} //}
public async Task RequestUndo(string username) //public async Task RequestUndo(string username)
{ //{
var success = _dataService.Undo(); // var success = _dataService.Undo();
if (success) // if (success)
{ // {
var currentData = _dataService.GetCurrentData(); // var currentData = _dataService.GetCurrentData();
var changeEvent = new DataChangeEvent // var changeEvent = new DataChangeEvent
{ // {
Content = currentData.Status, // Content = currentData.Status,
Username = $"{username} (Undo)", // Username = $"{username} (Undo)",
Timestamp = currentData.LastModified, // Timestamp = currentData.LastModified,
Version = currentData.Version // Version = currentData.Version
}; // };
await Clients.All.SendAsync("ReceiveDataUpdate", changeEvent); // await Clients.All.SendAsync("ReceiveDataUpdate", changeEvent);
await BroadcastUndoRedoState(); // await BroadcastUndoRedoState();
} // }
} //}
public async Task RequestRedo(string username) //public async Task RequestRedo(string username)
{ //{
var success = _dataService.Redo(); // var success = _dataService.Redo();
if (success) // if (success)
{ // {
var currentData = _dataService.GetCurrentData(); // var currentData = _dataService.GetCurrentData();
var changeEvent = new DataChangeEvent // var changeEvent = new DataChangeEvent
{ // {
Content = currentData.Status, // Content = currentData.Status,
Username = $"{username} (Redo)", // Username = $"{username} (Redo)",
Timestamp = currentData.LastModified, // Timestamp = currentData.LastModified,
Version = currentData.Version // Version = currentData.Version
}; // };
await Clients.All.SendAsync("ReceiveDataUpdate", changeEvent); // await Clients.All.SendAsync("ReceiveDataUpdate", changeEvent);
await BroadcastUndoRedoState(); // await BroadcastUndoRedoState();
} // }
} //}
public async Task GetUndoRedoState() //public async Task GetUndoRedoState()
{ //{
await BroadcastUndoRedoState(); // await BroadcastUndoRedoState();
} //}
private async Task BroadcastUndoRedoState() //private async Task BroadcastUndoRedoState()
{ //{
var state = new UndoRedoState // var state = new UndoRedoState
{ // {
CanUndo = _dataService.CanUndo(), // CanUndo = _dataService.CanUndo(),
CanRedo = _dataService.CanRedo() // CanRedo = _dataService.CanRedo()
}; // };
await Clients.All.SendAsync("UpdateUndoRedoState", state); // await Clients.All.SendAsync("UpdateUndoRedoState", state);
} //}
public override async Task OnConnectedAsync() public override async Task OnConnectedAsync()
{ {
@ -120,12 +124,6 @@ namespace KoogleApp.Hub
public async Task BroadcastThrowPanelState(ThrowPanelState state, IDispatcher dispatcher) public async Task BroadcastThrowPanelState(ThrowPanelState state, IDispatcher dispatcher)
{ {
//if (_hubConnection?.State != HubConnectionState.Connected)
//{
// //_logger.LogWarning("Cannot add activity: not connected");
// return;
//}
try try
{ {
await Clients.Others.SendAsync("ReceiveThrowPanelState", state); await Clients.Others.SendAsync("ReceiveThrowPanelState", state);
@ -137,7 +135,20 @@ namespace KoogleApp.Hub
} }
catch (Exception ex) 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 // Optional: Error-Handling Action dispatchen
} }
} }

View File

@ -1,5 +1,6 @@
using Fluxor; using Fluxor;
using KoogleApp.Store.Game.ThrowPanel; using KoogleApp.Store.Game.ThrowPanel;
using KoogleApp.Store.Game.UndoRedo;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Authorization; using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.SignalR.Client; using Microsoft.AspNetCore.SignalR.Client;
@ -12,12 +13,15 @@ namespace KoogleApp.Services
private readonly AuthenticationStateProvider _authenticationStateProvider; private readonly AuthenticationStateProvider _authenticationStateProvider;
private HubConnection? _hubConnection; private HubConnection? _hubConnection;
private string? _userName; private string? _userName;
private readonly ILogger<HubConnectionService> _logger;
public HubConnectionService(NavigationManager navigationManager, public HubConnectionService(NavigationManager navigationManager,
AuthenticationStateProvider authenticationStateProvider) AuthenticationStateProvider authenticationStateProvider,
ILogger<HubConnectionService> logger)
{ {
_navigationManager = navigationManager; _navigationManager = navigationManager;
_authenticationStateProvider = authenticationStateProvider; _authenticationStateProvider = authenticationStateProvider;
_logger = logger;
} }
public HubConnection Connection => _hubConnection public HubConnection Connection => _hubConnection
@ -43,26 +47,24 @@ namespace KoogleApp.Services
.Build(); .Build();
_hubConnection.On<ThrowPanelState>("ReceiveThrowPanelState", state => _hubConnection.On<ThrowPanelState>("ReceiveThrowPanelState", state =>
{ {
dispatcher.Dispatch(new ReceiveStateFromServerAction(state)); dispatcher.Dispatch(new ReceiveThrowPanelStateFromServerAction(state));
}); });
// _hubConnection.On<string>("ReceiveTextUpdate", (newText) => _hubConnection.On<UndoRedoState>("ReceiveUndoRedoState", (state) =>
// { {
// _sharedText = newText; dispatcher.Dispatch(new ReceiveUndoRedoStateFromServerAction(state));
// InvokeAsync(StateHasChanged); });
// });
await _hubConnection.StartAsync(); await _hubConnection.StartAsync();
} }
public async Task HandelBroadcastThrowPanelStateAction(BroadcastThrowPanelStateAction action, IDispatcher dispatcher) public async Task BroadcastThrowPanelState(ThrowPanelState state, IDispatcher dispatcher)
{ {
if (_hubConnection?.State != HubConnectionState.Connected) if (_hubConnection?.State != HubConnectionState.Connected)
{ {
//_logger.LogWarning("Cannot add activity: not connected"); _logger.LogWarning("Cannot BroadcastThrowPanelState: not connected");
return; return;
} }
@ -70,7 +72,7 @@ namespace KoogleApp.Services
{ {
if (_hubConnection is not null) if (_hubConnection is not null)
{ {
await _hubConnection.SendAsync("BroadcastThrowPanelState", action.State); await _hubConnection.SendAsync("BroadcastThrowPanelState", state);
} }
//await Clients.Others.SendAsync("ReceiveThrowPanelState", new ThrowPanelState()); //await Clients.Others.SendAsync("ReceiveThrowPanelState", new ThrowPanelState());
@ -82,7 +84,29 @@ namespace KoogleApp.Services
} }
catch (Exception ex) 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 // Optional: Error-Handling Action dispatchen
} }
} }

View File

@ -14,7 +14,7 @@ namespace KoogleApp.Store.Game.ThrowPanel
public record UpdatePinStateByNumberAction(int Number); public record UpdatePinStateByNumberAction(int Number);
public record ReceiveStateFromServerAction(ThrowPanelState State); public record ReceiveThrowPanelStateFromServerAction(ThrowPanelState State);
public record LoadStateFromSessionAction(); public record LoadStateFromSessionAction();

View File

@ -227,7 +227,7 @@ namespace KoogleApp.Store.Game.ThrowPanel
[EffectMethod] [EffectMethod]
public async Task HandelBroadcastThrowPanelStateAction(BroadcastThrowPanelStateAction action, IDispatcher dispatcher) public async Task HandelBroadcastThrowPanelStateAction(BroadcastThrowPanelStateAction action, IDispatcher dispatcher)
{ {
await _sharedHubService.HandelBroadcastThrowPanelStateAction(action, dispatcher); await _sharedHubService.BroadcastThrowPanelState(action.State, dispatcher);
} }

View File

@ -5,7 +5,7 @@ namespace KoogleApp.Store.Game.ThrowPanel
public static class ThrowPanelStateReducer public static class ThrowPanelStateReducer
{ {
[ReducerMethod] [ReducerMethod]
public static ThrowPanelState OnReceiveStateFromServer(ThrowPanelState state, ReceiveStateFromServerAction action) public static ThrowPanelState OnReceiveStateFromServer(ThrowPanelState state, ReceiveThrowPanelStateFromServerAction action)
{ {
return action.State; return action.State;
} }

View File

@ -13,7 +13,7 @@ namespace KoogleApp.Store.Game.ThrowPanel
public enum ThrowPanelStateStatus public enum ThrowPanelStateStatus
{ {
undefined, Undefined,
GameStart, GameStart,
BeforeThrow, BeforeThrow,
AfterThrow, AfterThrow,
@ -30,14 +30,9 @@ namespace KoogleApp.Store.Game.ThrowPanel
public ThrowPanelState() : this(BellValue:false, IsStated:false, 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, 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, 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
} }

View File

@ -7,4 +7,8 @@
public record CanUndoRedoAction(bool CanUndo, bool CanRedo, int Version, DateTime ModifiedAt, string ModifiedBy); public record CanUndoRedoAction(bool CanUndo, bool CanRedo, int Version, DateTime ModifiedAt, string ModifiedBy);
public record UpdateUndoRedoStateAction(); public record UpdateUndoRedoStateAction();
public record BroadcastUndoRedoStateAction(UndoRedoState State);
public record ReceiveUndoRedoStateFromServerAction(UndoRedoState State);
} }

View File

@ -65,6 +65,19 @@ namespace KoogleApp.Store.Game.UndoRedo
dispatcher.Dispatch(new CanUndoRedoAction(canUndo,canRedo, currentData.Version, currentData.LastModified, currentData.LastModifiedBy)); dispatcher.Dispatch(new CanUndoRedoAction(canUndo,canRedo, currentData.Version, currentData.LastModified, currentData.LastModifiedBy));
return Task.CompletedTask; 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);
}
} }
} }

View File

@ -16,5 +16,11 @@ namespace KoogleApp.Store.Game.UndoRedo
IsInitialized = true IsInitialized = true
}; };
} }
[ReducerMethod]
public static UndoRedoState OnReceiveStateFromServer(UndoRedoState state, ReceiveUndoRedoStateFromServerAction action)
{
return action.State;
}
} }
} }