From 125226127d8eba3f949ba72a8ab7a4cd30c1f74b Mon Sep 17 00:00:00 2001 From: beo3000 Date: Sat, 27 Dec 2025 22:11:30 +0100 Subject: [PATCH] add appsettings, undo/redo without saving --- .../Configuration/AppSettings.cs | 15 +++++ .../DependencyInjection.cs | 5 ++ src/Koogle.Web/Store/GameState/GameActions.cs | 6 +- src/Koogle.Web/Store/GameState/GameEffects.cs | 57 +++++++++++++------ .../Store/GameState/GameReducers.cs | 4 +- src/Koogle.Web/appsettings.json | 5 +- 6 files changed, 69 insertions(+), 23 deletions(-) create mode 100644 src/Koogle.Infrastructure/Configuration/AppSettings.cs diff --git a/src/Koogle.Infrastructure/Configuration/AppSettings.cs b/src/Koogle.Infrastructure/Configuration/AppSettings.cs new file mode 100644 index 0000000..8873544 --- /dev/null +++ b/src/Koogle.Infrastructure/Configuration/AppSettings.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Koogle.Infrastructure.Configuration +{ + public class AppSettings + { + public const string SectionName = "AppSettings"; + + public bool SaveOnUndoRedo { get; set; }= false; + } +} diff --git a/src/Koogle.Infrastructure/DependencyInjection.cs b/src/Koogle.Infrastructure/DependencyInjection.cs index 5f7eae5..38419cb 100644 --- a/src/Koogle.Infrastructure/DependencyInjection.cs +++ b/src/Koogle.Infrastructure/DependencyInjection.cs @@ -1,4 +1,5 @@ using Koogle.Domain.Interfaces; +using Koogle.Infrastructure.Configuration; using Koogle.Infrastructure.Data; using Koogle.Infrastructure.Identity; using Koogle.Infrastructure.Repositories; @@ -86,6 +87,10 @@ public static class DependencyInjection services.AddCascadingAuthenticationState(); + + // Configurations + services.Configure(configuration.GetSection(AppSettings.SectionName)); + return services; } } \ No newline at end of file diff --git a/src/Koogle.Web/Store/GameState/GameActions.cs b/src/Koogle.Web/Store/GameState/GameActions.cs index dda5588..4b1a837 100644 --- a/src/Koogle.Web/Store/GameState/GameActions.cs +++ b/src/Koogle.Web/Store/GameState/GameActions.cs @@ -181,7 +181,8 @@ public record UndoThrowAction; public record UndoThrowSuccessAction( ThrowPanelState ThrowPanel, ParticipantsState Participants, - object? GameModel); + object? GameModel, + bool IsSaving); /// /// Action dispatched when undo fails (e.g., empty stack). @@ -201,7 +202,8 @@ public record RedoThrowAction; public record RedoThrowSuccessAction( ThrowPanelState ThrowPanel, ParticipantsState Participants, - object? GameModel); + object? GameModel, + bool IsSaving); /// /// Action dispatched when redo fails (e.g., empty stack). diff --git a/src/Koogle.Web/Store/GameState/GameEffects.cs b/src/Koogle.Web/Store/GameState/GameEffects.cs index 90dcc7f..f1c0559 100644 --- a/src/Koogle.Web/Store/GameState/GameEffects.cs +++ b/src/Koogle.Web/Store/GameState/GameEffects.cs @@ -4,8 +4,10 @@ using Koogle.Application.DTOs; using Koogle.Application.Games; using Koogle.Application.Interfaces; using Koogle.Domain.Enums; +using Koogle.Infrastructure.Configuration; using Koogle.Web.Hubs; using Koogle.Web.Services; +using Microsoft.Extensions.Options; namespace Koogle.Web.Store.GameState; @@ -21,6 +23,7 @@ public class GameEffects private readonly ICurrentClubContext _clubContext; private readonly GameDefinitionRegistry _gameRegistry; private readonly GameHubService _hubService; + private readonly IOptions _appSettings; // Debounce timer for save operations private Timer? _saveDebounceTimer; @@ -35,7 +38,8 @@ public class GameEffects IGamePersistenceService persistenceService, ICurrentClubContext clubContext, GameDefinitionRegistry gameRegistry, - GameHubService hubService) + GameHubService hubService, + IOptions appSettings) { _logger = logger; _gameState = gameState; @@ -43,6 +47,7 @@ public class GameEffects _clubContext = clubContext; _gameRegistry = gameRegistry; _hubService = hubService; + _appSettings = appSettings; } /// @@ -478,20 +483,23 @@ public class GameEffects public Task HandleUndoThrowSuccess(UndoThrowSuccessAction action, IDispatcher dispatcher) { var stateAfterReducer = _gameState.Value; - _logger.LogInformation( + _logger.LogDebug( "UNDO SUCCESS: State after reducer - pins fallen={Fallen}, total={Total}, UndoStack={UndoCount}, RedoStack={RedoCount}", stateAfterReducer.ThrowPanelAfter.CountFallenPins(), stateAfterReducer.ThrowPanelAfter.TotalThrowCounter, stateAfterReducer.UndoStack.Count, stateAfterReducer.RedoStack.Count); - // Save after undo as well - _saveDebounceTimer?.Dispose(); - _saveDebounceTimer = new Timer( - async _ => await DebouncedSaveAsync(dispatcher), - null, - SaveDebounceMs, - Timeout.Infinite); + if (_appSettings.Value.SaveOnUndoRedo) + { + // Save after undo as well + _saveDebounceTimer?.Dispose(); + _saveDebounceTimer = new Timer( + async _ => await DebouncedSaveAsync(dispatcher), + null, + SaveDebounceMs, + Timeout.Infinite); + } return Task.CompletedTask; } @@ -524,7 +532,8 @@ public class GameEffects dispatcher.Dispatch(new UndoThrowSuccessAction( lastSnapshot.ThrowPanelAfter, lastSnapshot.Participants, - lastSnapshot.GameModel)); + lastSnapshot.GameModel, + _appSettings.Value.SaveOnUndoRedo)); return Task.CompletedTask; } @@ -554,7 +563,8 @@ public class GameEffects dispatcher.Dispatch(new RedoThrowSuccessAction( lastSnapshot.ThrowPanelAfter, lastSnapshot.Participants, - lastSnapshot.GameModel)); + lastSnapshot.GameModel, + _appSettings.Value.SaveOnUndoRedo)); return Task.CompletedTask; } @@ -565,13 +575,24 @@ public class GameEffects [EffectMethod] public Task HandleRedoThrowSuccess(RedoThrowSuccessAction action, IDispatcher dispatcher) { - // Save after redo - _saveDebounceTimer?.Dispose(); - _saveDebounceTimer = new Timer( - async _ => await DebouncedSaveAsync(dispatcher), - null, - SaveDebounceMs, - Timeout.Infinite); + var stateAfterReducer = _gameState.Value; + _logger.LogDebug( + "REDO SUCCESS: State after reducer - pins fallen={Fallen}, total={Total}, UndoStack={UndoCount}, RedoStack={RedoCount}", + stateAfterReducer.ThrowPanelAfter.CountFallenPins(), + stateAfterReducer.ThrowPanelAfter.TotalThrowCounter, + stateAfterReducer.UndoStack.Count, + stateAfterReducer.RedoStack.Count); + + if (_appSettings.Value.SaveOnUndoRedo) + { + // Save after redo + _saveDebounceTimer?.Dispose(); + _saveDebounceTimer = new Timer( + async _ => await DebouncedSaveAsync(dispatcher), + null, + SaveDebounceMs, + Timeout.Infinite); + } return Task.CompletedTask; } diff --git a/src/Koogle.Web/Store/GameState/GameReducers.cs b/src/Koogle.Web/Store/GameState/GameReducers.cs index 5fad56d..f09e843 100644 --- a/src/Koogle.Web/Store/GameState/GameReducers.cs +++ b/src/Koogle.Web/Store/GameState/GameReducers.cs @@ -366,7 +366,7 @@ public static class GameReducers GameModel = action.GameModel, UndoStack = newUndoStack, RedoStack = state.RedoStack.Add(currentSnapshot), - IsSaving = true + IsSaving = action.IsSaving }; } @@ -408,7 +408,7 @@ public static class GameReducers GameModel = action.GameModel, UndoStack = state.UndoStack.Add(currentSnapshot), RedoStack = newRedoStack, - IsSaving = true + IsSaving = action.IsSaving }; } diff --git a/src/Koogle.Web/appsettings.json b/src/Koogle.Web/appsettings.json index 86e6b45..ac4a1c7 100644 --- a/src/Koogle.Web/appsettings.json +++ b/src/Koogle.Web/appsettings.json @@ -8,5 +8,8 @@ "Microsoft.AspNetCore": "Warning" } }, - "AllowedHosts": "*" + "AllowedHosts": "*", + "AppSettings": { + "SaveOnUndoRedo" : false + } }