From b32c0e45607667c4944c51b9f78d3c6d03e8a20a Mon Sep 17 00:00:00 2001 From: Pandipipas Date: Sat, 30 May 2026 21:22:48 +0200 Subject: [PATCH] feat: implement replicant state synchronization for commentary, players, scoreboard, and graphics settings - Added a new service for synchronizing state with replicants in `replicant-state-service.ts`. - Refactored commentary store to utilize the new synchronization service. - Created a new graphics settings store that syncs with replicants. - Introduced a packs store for managing installed packs and their states. - Updated players and scoreboard stores to use the new synchronization service. - Created shared services for managing replicated state in graphics components. - Refactored existing components to use the new shared services for replicant state. - Added normalization and default values for commentary, graphics settings, players, and scoreboard. - Improved type safety and organization in shared domain files for better maintainability. --- docs/refactor/PHASE_2_SUMMARY.md | 85 ++++++ .../scoreko-dev/components/BracketPanel.vue | 4 +- .../components/CommentaryPanel.vue | 14 +- .../components/PlayerSidePanel.vue | 3 +- .../components/ScoreCenterPanel.vue | 14 +- .../composables/useCharacterGame.ts | 42 ++- .../scoreko-dev/composables/useIntegration.ts | 24 +- .../composables/usePackRegistry.ts | 241 +++--------------- .../scoreko-dev/composables/usePlayerSide.ts | 45 +--- src/dashboard/scoreko-dev/views/Graphics.vue | 14 +- .../services/integration-message-service.ts | 8 + src/dashboard/services/pack-service.ts | 79 ++++++ .../replicant-state-service.ts} | 39 ++- src/dashboard/stores/commentary.ts | 51 ++-- src/dashboard/stores/graphics-settings.ts | 31 +++ src/dashboard/stores/packs.ts | 218 ++++++++++++++++ src/dashboard/stores/players.ts | 47 +--- src/dashboard/stores/scoreboard.ts | 142 ++++++----- src/graphics/commentary/main.vue | 12 +- src/graphics/scoreboard-2xko/main.vue | 12 +- src/graphics/scoreboard/main.vue | 24 +- .../shared/services/replicated-state.ts | 25 ++ src/nodecg/browser/packReplicants.ts | 2 +- src/shared/domain/commentary/index.ts | 1 + src/shared/domain/commentary/state.ts | 32 +++ src/shared/domain/graphics/index.ts | 1 + src/shared/domain/graphics/state.ts | 16 ++ src/shared/domain/packs/characters.ts | 48 ++++ src/shared/domain/packs/index.ts | 1 + src/shared/domain/players/state.ts | 51 ++++ src/shared/domain/scoreboard/index.ts | 1 + src/shared/domain/scoreboard/state.ts | 88 +++++++ src/shared/fighting-characters.ts | 122 +-------- 33 files changed, 929 insertions(+), 608 deletions(-) create mode 100644 docs/refactor/PHASE_2_SUMMARY.md create mode 100644 src/dashboard/services/integration-message-service.ts create mode 100644 src/dashboard/services/pack-service.ts rename src/dashboard/{stores/store-sync.ts => services/replicant-state-service.ts} (51%) create mode 100644 src/dashboard/stores/graphics-settings.ts create mode 100644 src/dashboard/stores/packs.ts create mode 100644 src/graphics/shared/services/replicated-state.ts create mode 100644 src/shared/domain/commentary/index.ts create mode 100644 src/shared/domain/commentary/state.ts create mode 100644 src/shared/domain/graphics/index.ts create mode 100644 src/shared/domain/graphics/state.ts create mode 100644 src/shared/domain/packs/characters.ts create mode 100644 src/shared/domain/players/state.ts create mode 100644 src/shared/domain/scoreboard/index.ts create mode 100644 src/shared/domain/scoreboard/state.ts diff --git a/docs/refactor/PHASE_2_SUMMARY.md b/docs/refactor/PHASE_2_SUMMARY.md new file mode 100644 index 0000000..08c82f0 --- /dev/null +++ b/docs/refactor/PHASE_2_SUMMARY.md @@ -0,0 +1,85 @@ +# Phase 2 Summary + +## Scope + +Executed the state and replicants phase only. + +This phase focused on isolating state logic, normalizing Pinia stores, encapsulating browser-side replicant access, and moving side effects behind services without changing UX, visual design, overlay CSS, or public NodeCG contracts. + +## Completed + +- Added pure state/domain modules: + - `src/shared/domain/scoreboard` + - `src/shared/domain/commentary` + - `src/shared/domain/graphics` + - `src/shared/domain/players/state.ts` + - `src/shared/domain/packs/characters.ts` +- Moved normalization and pure state transitions out of dashboard stores. +- Replaced direct dashboard replicant imports with `src/dashboard/services/replicant-state-service.ts`. +- Added `useGraphicsSettingsStore` and moved dashboard graphics skin writes through the store. +- Reworked scoreboard, players and commentary stores to use shared domain normalizers and service-based replicant sync. +- Replaced the pack registry singleton composable with a normalized `usePacksStore`. +- Moved pack replicant listeners and NodeCG pack messages into `src/dashboard/services/pack-service.ts`. +- Removed Vue reactivity and mutable pack registration from `src/shared/fighting-characters.ts`. +- Modeled installed pack manifests as explicit store state instead of hidden module state. +- Centralized registry auto-refresh timer in the packs store. +- Routed integration NodeCG messages through `src/dashboard/services/integration-message-service.ts`. +- Added `src/graphics/shared/services/replicated-state.ts` so graphics read replicants through a service layer. +- Removed the redundant `src/dashboard/stores/store-sync.ts`. + +## Preserved + +- Public replicant names were unchanged. +- Public message names were unchanged. +- Existing dashboard UX was preserved. +- Overlay markup, CSS, positioning and animation logic were not intentionally changed. +- The existing `usePackRegistry` import path remains as a compatibility wrapper over the packs store. +- The legacy `src/shared/fighting-characters.ts` path remains as a compatibility export, but no longer owns mutable runtime state. + +## Realtime Flow After This Phase + +```text +schemas + -> nodecg/browser + -> dashboard services / graphics services + -> Pinia stores or overlay computed state + -> components +``` + +Pack runtime flow: + +```text +pack replicants + -> pack service + -> packs store + -> pack registry compatibility composable + -> game / character UI +``` + +## Verification + +- `pnpm.cmd exec vue-tsc -p tsconfig.browser.json --noEmit`: passed. +- `pnpm.cmd exec tsc -b tsconfig.extension.json --pretty false`: passed. +- `pnpm.cmd exec eslint`: passed with 0 errors and existing Vue formatting warnings. +- `pnpm.cmd run build`: passed. +- Searched dashboard, graphics and shared for direct NodeCG/message/replicant imports: + - remaining browser NodeCG access is contained in services and `nodecg/browser`. + - direct component/view replicant imports were removed. +- Searched for `any` in touched runtime areas: + - no new TypeScript `any` usage was added. + +## Notes and Limits + +- This phase did not split large views like `Players.vue` or `Settings.vue`. +- This phase did not refactor overlay internals beyond replacing direct replicant imports with a read service. +- This phase did not rewrite extension-side `pack-manager.ts`. +- This phase did not rename public messages to the future canonical names; compatibility was preserved. +- Existing Vue lint warnings remain formatting-only and were not addressed because they are outside this phase. + +## Remaining For Later Phases + +- Controlled rewrite of `pack-manager.ts`. +- Full split of `useIntegration` into provider clients, OAuth client, temporary players and import modules. +- Divide `Players.vue` and `Settings.vue`. +- Extract overlay view models and visual helpers after visual baseline. +- Add tests for pure normalizers and pack state derivations. diff --git a/src/dashboard/scoreko-dev/components/BracketPanel.vue b/src/dashboard/scoreko-dev/components/BracketPanel.vue index cec2943..c176692 100644 --- a/src/dashboard/scoreko-dev/components/BracketPanel.vue +++ b/src/dashboard/scoreko-dev/components/BracketPanel.vue @@ -83,12 +83,12 @@ const updateRound = () => { return; } if (customActive.value) { - scoreboardStore.scoreboard.round = customText.value.trim(); + scoreboardStore.setRound(customText.value.trim()); return; } const prefix = bracketSide.value ? `${bracketSide.value} ` : ''; - scoreboardStore.scoreboard.round = `${prefix}${stage.value}`.trim(); + scoreboardStore.setRound(`${prefix}${stage.value}`.trim()); }; watch([stage, bracketSide, customText, customActive], updateRound); diff --git a/src/dashboard/scoreko-dev/components/CommentaryPanel.vue b/src/dashboard/scoreko-dev/components/CommentaryPanel.vue index 3c454c7..a1f2d03 100644 --- a/src/dashboard/scoreko-dev/components/CommentaryPanel.vue +++ b/src/dashboard/scoreko-dev/components/CommentaryPanel.vue @@ -1,5 +1,6 @@