Skip to content

Commit 596ac03

Browse files
committed
refactor(sonar): clear another low-risk UI and runtime batch
- simplify small update-check, tv-board-zoom, winner-fireworks, snapshot-cache, and path helper smells - keep x01-2player and shell select-value helpers behaviorally identical while reducing local control-flow noise - update changelog and verify with lint, test, and Sonar scan (87 -> 75 open issues)
1 parent 1116a51 commit 596ac03

8 files changed

Lines changed: 82 additions & 48 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ direkt zu einer versionierten Release-Sektion.
2121

2222
### Fixed
2323

24+
- Nutzerwirkung: Keine beabsichtigte sichtbare Verhaltensänderung; eine weitere kleine Sonar-Welle hält Update-Status, Winner-Animation, TV-Zoom, Cricket-Snapshot-Cache sowie ausgewählte xConfig-Helfer auf denselben fachlichen Pfaden, drückt einige Status- und Auswahlzweige intern aber direkter aus.
25+
Technik: `update-check`, `winner-fireworks`, `tv-board-zoom`, `cricket-surface/snapshot-cache`, `x01-2player/policy`, `xconfig-ui/path-utils` und `shell-view` bereinigen nur lokale `S3358`-, `S1788`- und `S7766`-Treffer durch kleine Helper und unveränderte Fallback-Pfade; Observer-, Snapshot-, Select- und Update-Semantik bleiben dabei gleich, und die bestehenden Runtime-, Domain- und Changelog-Regressionen bleiben der fachliche Schutz gegen Drift.
26+
2427
- Nutzerwirkung: Keine beabsichtigte sichtbare Verhaltensänderung; Theme-Mounting, Checkout-Board-Ziele sowie die Cricket-Wrapper für Highlighting und Grid-FX laufen auf denselben fachlichen Pfaden weiter, sind intern aber in dieser Sonar-Welle klarer in Status- und Aktivierungsblöcke getrennt.
2528
Technik: `mount-theme-feature`, `checkout-board-targets`, `cricket-highlighter` und `cricket-grid-fx` ziehen kleine Aktivierungs-, Renderstatus- und Nicht-Ready-Statuspfade jetzt in lokale Helper; `mount-theme-feature` kapselt zusätzlich Theme-Evaluator und Mutation-Callback in eigene lokale Fabriken, ohne öffentliche Signaturen oder die beobachtbare Overlay-/Lifecycle-Semantik zu ändern. Die bestehenden Theme-, Lifecycle-, Runtime-Performance- und Degraded-Host-Regressionen sichern diese Wrapper-Refactors gegen Drift ab.
2629

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import { findBoardSvgGroup, isReusableBoardSnapshot } from "../../shared/dartboard-svg.js";
22

3-
export function resolveGridSnapshot(documentRef, cricketRules, targetOrder, cache = null, findGrid) {
4-
if (cache?.grid?.root && cache.grid.root.isConnected !== false) {
5-
return cache.grid;
3+
export function resolveGridSnapshot(documentRef, cricketRules, targetOrder, cache, findGrid) {
4+
const resolvedCache = cache && typeof cache === "object" ? cache : null;
5+
if (resolvedCache?.grid?.root && resolvedCache.grid.root.isConnected !== false) {
6+
return resolvedCache.grid;
67
}
78

89
const nextGrid =
@@ -13,20 +14,21 @@ export function resolveGridSnapshot(documentRef, cricketRules, targetOrder, cach
1314
targetOrder,
1415
})
1516
: null;
16-
if (cache && typeof cache === "object") {
17-
cache.grid = nextGrid;
17+
if (resolvedCache) {
18+
resolvedCache.grid = nextGrid;
1819
}
1920
return nextGrid;
2021
}
2122

22-
export function resolveBoardSnapshot(documentRef, cache = null) {
23-
if (isReusableBoardSnapshot(cache?.board, documentRef)) {
24-
return cache.board;
23+
export function resolveBoardSnapshot(documentRef, cache) {
24+
const resolvedCache = cache && typeof cache === "object" ? cache : null;
25+
if (isReusableBoardSnapshot(resolvedCache?.board, documentRef)) {
26+
return resolvedCache.board;
2527
}
2628

2729
const nextBoard = findBoardSvgGroup(documentRef);
28-
if (cache && typeof cache === "object") {
29-
cache.board = nextBoard;
30+
if (resolvedCache) {
31+
resolvedCache.board = nextBoard;
3032
}
3133
return nextBoard;
3234
}

src/features/themes/x01-2player/policy.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ function findTableSlot(cardNode, stackNode) {
324324

325325
function resolveFallbackActiveIndex(playerCards) {
326326
const classIndex = playerCards.findIndex((node) => node?.classList?.contains?.("ad-ext-player-active"));
327-
return classIndex >= 0 ? classIndex : 0;
327+
return Math.max(0, classIndex);
328328
}
329329

330330
function resolveActivePlayerIndex(playerCards, gameState) {

src/features/tv-board-zoom/index.js

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -162,14 +162,7 @@ export function shouldScheduleTvBoardZoomMutation(mutations = [], context = {})
162162
return false;
163163
}
164164

165-
const mutationType = String(
166-
mutation.type ||
167-
(mutation.attributeName
168-
? "attributes"
169-
: mutation.addedNodes || mutation.removedNodes
170-
? "childList"
171-
: "")
172-
);
165+
const mutationType = resolveMutationType(mutation);
173166

174167
if (mutationType === "attributes") {
175168
return (
@@ -198,6 +191,19 @@ export function shouldScheduleTvBoardZoomMutation(mutations = [], context = {})
198191
});
199192
}
200193

194+
function resolveMutationType(mutation) {
195+
if (mutation?.type) {
196+
return String(mutation.type);
197+
}
198+
if (mutation?.attributeName) {
199+
return "attributes";
200+
}
201+
if (mutation?.addedNodes || mutation?.removedNodes) {
202+
return "childList";
203+
}
204+
return "";
205+
}
206+
201207
function getNodeClassName(node) {
202208
if (!node || typeof node.getAttribute !== "function") {
203209
return "";
@@ -252,6 +258,16 @@ function buildDebugSummary(payload = {}) {
252258
}" ty="${payload.ty ?? "-"}" anchor="${payload.anchorX ?? "-"},${payload.anchorY ?? "-"}"`;
253259
}
254260

261+
function resolveFeatureDebugLogger(featureDebug, level) {
262+
if (level === "warn" && typeof featureDebug?.warn === "function") {
263+
return featureDebug.warn.bind(featureDebug);
264+
}
265+
if (typeof featureDebug?.log === "function") {
266+
return featureDebug.log.bind(featureDebug);
267+
}
268+
return null;
269+
}
270+
255271
function emitDebugEvent(debugState, level, payload = {}) {
256272
if (!debugState?.featureDebug?.enabled) {
257273
return;
@@ -263,12 +279,7 @@ function emitDebugEvent(debugState, level, payload = {}) {
263279
}
264280
debugState.lastSignature = signature;
265281

266-
const logger =
267-
level === "warn" && typeof debugState.featureDebug.warn === "function"
268-
? debugState.featureDebug.warn.bind(debugState.featureDebug)
269-
: typeof debugState.featureDebug.log === "function"
270-
? debugState.featureDebug.log.bind(debugState.featureDebug)
271-
: null;
282+
const logger = resolveFeatureDebugLogger(debugState.featureDebug, level);
272283
if (!logger) {
273284
return;
274285
}

src/features/winner-fireworks/logic.js

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@ const TERMINAL_STATUS_TOKENS = new Set([
1616
"match-over",
1717
"won",
1818
]);
19+
const STYLE_INTERVAL_MS = Object.freeze({
20+
sides: 16,
21+
fireworks: 250,
22+
victorystorm: 620,
23+
stars: 980,
24+
default: 920,
25+
});
1926

2027
function randomInRange(min, max) {
2128
return Math.random() * (max - min) + min;
@@ -293,15 +300,7 @@ function runStyleBurst(state) {
293300
}
294301

295302
function getStyleIntervalMs(style, intensityPreset) {
296-
const base = style === "sides"
297-
? 16
298-
: style === "fireworks"
299-
? 250
300-
: style === "victorystorm"
301-
? 620
302-
: style === "stars"
303-
? 980
304-
: 920;
303+
const base = STYLE_INTERVAL_MS[style] ?? STYLE_INTERVAL_MS.default;
305304
return scaledInterval(base, intensityPreset);
306305
}
307306

src/features/xconfig-ui/path-utils.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ export function splitFeaturePath(featureKey) {
88
return splitSharedFeaturePath(featureKey);
99
}
1010

11-
export function setNestedValue(rootValue, pathParts = [], value) {
12-
return setSharedNestedValue(rootValue, pathParts, value);
11+
export function setNestedValue(rootValue, pathParts, value) {
12+
const normalizedPathParts = Array.isArray(pathParts) ? pathParts : [];
13+
return setSharedNestedValue(rootValue, normalizedPathParts, value);
1314
}
1415

1516
export function buildFeatureSettingPatch(configKey, settingKey, value) {

src/features/xconfig-ui/shell-view.js

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1073,16 +1073,22 @@ function getFieldNoteText(field) {
10731073
return String(field?.description || "").trim();
10741074
}
10751075

1076+
function resolveConfiguredFieldValues(feature, field) {
1077+
const configuredValue = feature?.config?.[field.key];
1078+
if (isMultiSelectField(field)) {
1079+
return Array.isArray(configuredValue) ? configuredValue : [configuredValue];
1080+
}
1081+
return [configuredValue];
1082+
}
1083+
10761084
function resolveSelectFieldValues(feature, field) {
10771085
const options = Array.isArray(field?.options) ? field.options : [];
10781086
if (!options.length) {
10791087
return [];
10801088
}
10811089

10821090
const allowedValues = new Set(options.map((option) => String(option?.value ?? "")));
1083-
const rawValues = isMultiSelectField(field)
1084-
? (Array.isArray(feature?.config?.[field.key]) ? feature.config[field.key] : [feature?.config?.[field.key]])
1085-
: [feature?.config?.[field.key]];
1091+
const rawValues = resolveConfiguredFieldValues(feature, field);
10861092
const configuredValues = Array.from(
10871093
new Set(
10881094
rawValues

src/features/xconfig-ui/update-check.js

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,24 @@ function createBaseUpdateStatus(installedVersion, capable) {
117117
};
118118
}
119119

120+
function normalizeCheckedAt(value) {
121+
const numericValue = Number(value);
122+
if (!Number.isFinite(numericValue)) {
123+
return 0;
124+
}
125+
return Math.max(0, numericValue);
126+
}
127+
128+
function resolveUpdateStatus(normalizedRemoteVersion, comparison, error) {
129+
if (normalizedRemoteVersion) {
130+
return comparison > 0 ? "available" : "current";
131+
}
132+
if (error) {
133+
return "error";
134+
}
135+
return "idle";
136+
}
137+
120138
function safeParseJson(value) {
121139
if (typeof value !== "string" || !value.trim()) {
122140
return null;
@@ -224,16 +242,10 @@ function createResolvedUpdateStatus({
224242

225243
return {
226244
...baseStatus,
227-
status: normalizedRemoteVersion
228-
? comparison > 0
229-
? "available"
230-
: "current"
231-
: error
232-
? "error"
233-
: "idle",
245+
status: resolveUpdateStatus(normalizedRemoteVersion, comparison, error),
234246
remoteVersion: normalizedRemoteVersion,
235247
available: normalizedRemoteVersion ? comparison > 0 : false,
236-
checkedAt: Number(checkedAt) > 0 ? Number(checkedAt) : 0,
248+
checkedAt: normalizeCheckedAt(checkedAt),
237249
sourceUrl: String(sourceUrl || "").trim(),
238250
error: String(error || "").trim(),
239251
stale: Boolean(stale),
@@ -263,7 +275,7 @@ function writeStoredPayload(storageRef, payload) {
263275
UPDATE_STATUS_STORAGE_KEY,
264276
JSON.stringify({
265277
remoteVersion: normalizeVersion(payload?.remoteVersion),
266-
checkedAt: Number(payload?.checkedAt) > 0 ? Number(payload.checkedAt) : 0,
278+
checkedAt: normalizeCheckedAt(payload?.checkedAt),
267279
sourceUrl: String(payload?.sourceUrl || "").trim(),
268280
validators: normalizeValidatorsMap(payload?.validators),
269281
})

0 commit comments

Comments
 (0)