Skip to content

Commit d86349d

Browse files
committed
chore: bump version to 2.3.20 and update dependencies
feat: enhance x01 score progress animations and effects - Improved animation definitions for pulse-core and glass-charge effects. - Adjusted timing and easing functions for smoother transitions. - Updated CSS styles for score progress elements to enhance visual feedback. fix: ensure ghost trail animations handle stale callbacks correctly - Added logic to ignore stale animation cancel callbacks after score changes. test: add comprehensive tests for x01 score progress features - Implemented tests for new animation behaviors and visual effects. - Verified correct rendering of score progress previews and dynamic updates.
1 parent 221dba4 commit d86349d

16 files changed

Lines changed: 784 additions & 97 deletions

AGENTS.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ Priority: truthfulness, correctness, proportional validation.
1616
- use `$maintain-changelog` only when changelog, release-note, or compare-link work is explicitly in scope
1717
- do not run `git commit`, push, create PRs, or create releases without an explicit user request
1818
- final output must state what changed, what was validated, what remains unverified, and include a draft commit message when there are meaningful file changes
19-
- when SonarQube is relevant, run `npm test`; it includes `npm run sonar`, which must use `SONARQUBE_URL`/`SONARQUBE_TOKEN` from the environment or fall back to `~/.codex/config.toml` `[mcp_servers.sonarqube].env`
19+
- when SonarQube is relevant on new builds, run `npm test`; it includes `npm run sonar`, which must use `SONARQUBE_URL`/`SONARQUBE_TOKEN` from the environment or fall back to `~/.codex/config.toml` `[mcp_servers.sonarqube].env`
2020
- never claim SonarQube is unavailable before checking `npm run sonar`; never print or commit the SonarQube token
21+
- For minor changes, such as changing variable values, skip all tests. In general, keep in mind the proportionality of tests.
2122

2223
Done means the change is in the right layer, scoped validation ran or is clearly blocked, and any skipped release, changelog, browser, or SonarQube verification is reported truthfully.

CHANGELOG.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,15 @@ zum nächsten Release-Commit vorübergehend auf `HEAD` zeigen.
1212
Dieses Repository führt keine `Unreleased`-Sektion. Jeder dokumentierte Eintrag gehört
1313
direkt zu einer versionierten Release-Sektion.
1414

15+
## [2.3.20] - 2026-06-16
16+
17+
### Changed
18+
19+
- Nutzerwirkung: `X01 Score Progress`-Effekte sind in der Konfiguration leichter vergleichbar: Die Effekt-Buttons zeigen längere Balken, `Ghost Trail` demonstriert eine echte Abnahme von `80 %` auf `15 %`, und die Hauptvorschau läuft als Prozentsequenz.
20+
Technik: Die xConfig-Shell nutzt einen eigenen X01-Score-Progress-Preview-Controller mit loopbaren Runtime-Hosts, hält Render-Hooks stabil und deckt Button- sowie Hauptvorschau mit Shell-Regressionen ab.
21+
- Nutzerwirkung: `Pulse Core`, `Glass Charge` und `Ghost Trail` wirken klarer und stärker unterscheidbar; besonders Trails, Ladeglanz und Pulse-Peak sind besser wahrnehmbar.
22+
Technik: Runtime-Keyframes, CSS-Animationen, Glow-/Sweep-Layer und Effekt-Dauern wurden gezielt nachgeschärft; Runtime-Regressionen sichern die neuen Effektverträge und den stabilen Ghost-Trail-Cleanup ab.
23+
1524
## [2.3.19] - 2026-06-05
1625

1726
### Added
@@ -1661,7 +1670,8 @@ direkt zu einer versionierten Release-Sektion.
16611670
und Regressionstests eingeführt und die generierten README-/FEATURES-Texte wurden
16621671
entsprechend synchronisiert.
16631672

1664-
[2.3.19]: https://github.com/thomasasen/autodarts-xconfig/compare/d48730f...HEAD
1673+
[2.3.20]: https://github.com/thomasasen/autodarts-xconfig/compare/09ae6b2...HEAD
1674+
[2.3.19]: https://github.com/thomasasen/autodarts-xconfig/compare/d48730f...09ae6b2
16651675
[2.3.18]: https://github.com/thomasasen/autodarts-xconfig/compare/0c88218...d48730f
16661676
[2.3.17]: https://github.com/thomasasen/autodarts-xconfig/compare/3cbf7b3...0c88218
16671677
[2.3.16]: https://github.com/thomasasen/autodarts-xconfig/compare/53e5d17...3cbf7b3

dist/autodarts-xconfig.meta.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// ==UserScript==
22
// @name autodarts-xconfig
33
// @namespace https://github.com/thomasasen/autodarts-xconfig
4-
// @version 2.3.19
4+
// @version 2.3.20
55
// @description Modular, side-effect resistant Tampermonkey runtime for Autodarts enhancements.
66
// @author Thomas Asen
77
// @license MIT

dist/autodarts-xconfig.user.js

Lines changed: 228 additions & 44 deletions
Large diffs are not rendered by default.

loader/autodarts-xconfig.user.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// ==UserScript==
22
// @name autodarts-xconfig
33
// @namespace https://github.com/thomasasen/autodarts-xconfig
4-
// @version 2.3.19
4+
// @version 2.3.20
55
// @description Modular, side-effect resistant Tampermonkey runtime for Autodarts enhancements.
66
// @author Thomas Asen
77
// @license MIT

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "autodarts-xconfig",
3-
"version": "2.3.19",
3+
"version": "2.3.20",
44
"description": "Clean successor architecture for autodarts xConfig userscript modules",
55
"type": "module",
66
"imports": {

src/core/bootstrap.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { createListenerRegistry } from "./listener-registry.js";
1313
import { createObserverRegistry } from "./observer-registry.js";
1414

1515
const GLOBAL_NAMESPACE_KEY = "__adXConfig";
16-
const API_VERSION = "2.3.19";
16+
const API_VERSION = "2.3.20";
1717
const STARTUP_DEFER_INTERVAL_MS = 16;
1818

1919
function getWindowTimerApi(windowRef) {

src/features/x01-score-progress/logic.js

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1023,14 +1023,20 @@ function cancelEffectAnimation(fillNode) {
10231023
}
10241024
}
10251025

1026-
function clearTrailState(trailNode) {
1026+
function clearTrailState(trailNode, expectedAnimation = null) {
10271027
if (!trailNode) {
10281028
return;
10291029
}
10301030

10311031
const runningAnimation = trailNode[TRAIL_ANIMATION_SLOT];
1032-
if (runningAnimation && typeof runningAnimation.cancel === "function") {
1032+
if (expectedAnimation && runningAnimation !== expectedAnimation) {
1033+
return;
1034+
}
1035+
1036+
if (!expectedAnimation && runningAnimation && typeof runningAnimation.cancel === "function") {
10331037
try {
1038+
runningAnimation.onfinish = null;
1039+
runningAnimation.oncancel = null;
10341040
runningAnimation.cancel();
10351041
} catch (_) {
10361042
// Ignore stale animation handles.
@@ -1058,22 +1064,23 @@ function createEffectAnimationDefinition(effect) {
10581064
if (normalizedEffect === "pulse-core") {
10591065
return {
10601066
keyframes: [
1061-
{ transform: "scaleY(1)", filter: "brightness(1.06) saturate(1.02)" },
1062-
{ transform: "scaleY(1.24)", filter: "brightness(1.28) saturate(1.18)" },
1063-
{ transform: "scaleY(1)", filter: "brightness(1.02) saturate(1.02)" },
1067+
{ transform: "scaleY(1)", filter: "brightness(1.08) saturate(1.06)" },
1068+
{ transform: "scaleY(1.38)", filter: "brightness(1.46) saturate(1.3)" },
1069+
{ transform: "scaleY(1)", filter: "brightness(1.04) saturate(1.04)" },
10641070
],
1065-
options: { duration: 360, easing: "ease-out" },
1071+
options: { duration: 440, easing: "cubic-bezier(0.16, 0.9, 0.2, 1)" },
10661072
};
10671073
}
10681074

10691075
if (normalizedEffect === "glass-charge") {
10701076
return {
10711077
keyframes: [
1072-
{ filter: "brightness(1.04) saturate(1.04)", opacity: 0.94 },
1073-
{ filter: "brightness(1.26) saturate(1.16)", opacity: 1 },
1074-
{ filter: "brightness(1.02) saturate(1.02)", opacity: 0.96 },
1078+
{ filter: "brightness(1.03) saturate(1.06)", opacity: 0.94, transform: "scaleY(1)" },
1079+
{ filter: "brightness(1.18) saturate(1.16)", opacity: 0.98, transform: "scaleY(1.04)" },
1080+
{ filter: "brightness(1.38) saturate(1.28)", opacity: 1, transform: "scaleY(1.1)" },
1081+
{ filter: "brightness(1.05) saturate(1.08)", opacity: 0.96, transform: "scaleY(1)" },
10751082
],
1076-
options: { duration: 420, easing: "ease-in-out" },
1083+
options: { duration: 560, easing: "cubic-bezier(0.18, 0.82, 0.18, 1)" },
10771084
};
10781085
}
10791086

@@ -1111,23 +1118,39 @@ function triggerGhostTrail(trailNode, shouldTrigger, previousRatio, currentRatio
11111118
const fromWidth = formatProgressWidth(isFiniteNumber(previousRatio) ? previousRatio : currentRatio);
11121119
const toWidth = formatProgressWidth(currentRatio);
11131120
trailNode.style?.setProperty?.(TRAIL_WIDTH_PROPERTY, fromWidth);
1114-
trailNode.style?.setProperty?.("opacity", "0.76");
1121+
trailNode.style?.setProperty?.("opacity", "0.92");
11151122

11161123
const animation = trailNode.animate(
11171124
[
1118-
{ width: fromWidth, opacity: 0.76, filter: "blur(8px) brightness(1.28)" },
1119-
{ width: toWidth, opacity: 0, filter: "blur(2px) brightness(1.02)" },
1125+
{
1126+
width: fromWidth,
1127+
opacity: 0.92,
1128+
filter: "blur(7px) brightness(1.38) saturate(1.18)",
1129+
offset: 0,
1130+
},
1131+
{
1132+
width: fromWidth,
1133+
opacity: 0.78,
1134+
filter: "blur(6px) brightness(1.32) saturate(1.14)",
1135+
offset: 0.32,
1136+
},
1137+
{
1138+
width: toWidth,
1139+
opacity: 0,
1140+
filter: "blur(2px) brightness(1.04) saturate(1.04)",
1141+
offset: 1,
1142+
},
11201143
],
11211144
{
1122-
duration: 620,
1145+
duration: 1860,
11231146
easing: "cubic-bezier(0.22, 1, 0.36, 1)",
11241147
fill: "none",
11251148
iterations: 1,
11261149
}
11271150
);
11281151

11291152
trailNode[TRAIL_ANIMATION_SLOT] = animation;
1130-
const finish = () => clearTrailState(trailNode);
1153+
const finish = () => clearTrailState(trailNode, animation);
11311154
animation.onfinish = finish;
11321155
animation.oncancel = finish;
11331156
}

src/features/x01-score-progress/style.js

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -240,9 +240,14 @@ ${HOST_SELECTOR} .${TRAIL_CLASS}{
240240
width:var(--ad-ext-x01-score-progress-trail-width);
241241
opacity:0;
242242
border-radius:inherit;
243-
background:var(--ad-ext-x01-score-progress-fill-bg);
244-
filter:blur(7px) brightness(1.18);
245-
box-shadow:var(--ad-ext-x01-score-progress-fill-shadow);
243+
background:
244+
linear-gradient(90deg,rgba(255,255,255,.38) 0%,rgba(255,255,255,.18) 42%,rgba(255,255,255,0) 100%),
245+
var(--ad-ext-x01-score-progress-fill-bg);
246+
filter:blur(7px) brightness(1.24) saturate(1.12);
247+
box-shadow:
248+
var(--ad-ext-x01-score-progress-fill-shadow),
249+
0 0 16px var(--ad-ext-x01-score-progress-fill-outline-active),
250+
0 0 26px var(--ad-ext-x01-score-progress-fill-ambient-active);
246251
pointer-events:none;
247252
}
248253
@@ -299,18 +304,25 @@ ${HOST_SELECTOR}.${ACTIVE_CLASS}.ad-ext-x01-score-progress--size-extrabreit{
299304
}
300305
301306
${HOST_SELECTOR}.${ACTIVE_CLASS} .${FILL_CLASS}.ad-ext-x01-score-progress__fill--effect-pulse-core{
302-
animation:ad-ext-x01-score-progress-pulse-core 1.32s ease-in-out infinite;
307+
transform-origin:center;
308+
animation:ad-ext-x01-score-progress-pulse-core 1.22s cubic-bezier(.16,.9,.2,1) infinite;
303309
}
304310
305311
${HOST_SELECTOR}.${ACTIVE_CLASS} .${FILL_CLASS}.ad-ext-x01-score-progress__fill--effect-glass-charge{
306-
animation:ad-ext-x01-score-progress-glass-charge-core 1.74s ease-in-out infinite;
312+
animation:ad-ext-x01-score-progress-glass-charge-core 2.2s cubic-bezier(.18,.82,.18,1) infinite;
313+
box-shadow:
314+
var(--ad-ext-x01-score-progress-fill-shadow),
315+
inset 0 1px 2px rgba(255,255,255,.34),
316+
inset 0 -1px 4px rgba(255,255,255,.12);
307317
}
308318
309319
${HOST_SELECTOR}.${ACTIVE_CLASS} .${FILL_CLASS}.ad-ext-x01-score-progress__fill--effect-glass-charge::after{
310320
opacity:1;
311-
background:linear-gradient(115deg,rgba(255,255,255,0) 18%,rgba(255,255,255,.12) 36%,rgba(255,255,255,.66) 50%,rgba(255,255,255,.12) 64%,rgba(255,255,255,0) 82%);
312-
transform:translateX(-150%);
313-
animation:ad-ext-x01-score-progress-glass-charge-sweep 1.74s cubic-bezier(.22,.9,.18,1) infinite;
321+
background:
322+
linear-gradient(115deg,rgba(255,255,255,0) 8%,rgba(255,255,255,.16) 27%,rgba(255,255,255,.76) 48%,rgba(255,255,255,.2) 68%,rgba(255,255,255,0) 92%),
323+
linear-gradient(180deg,rgba(255,255,255,.28) 0%,rgba(255,255,255,0) 46%);
324+
transform:translateX(-175%);
325+
animation:ad-ext-x01-score-progress-glass-charge-sweep 2.2s cubic-bezier(.18,.82,.18,1) infinite;
314326
}
315327
316328
${HOST_SELECTOR}.${ACTIVE_CLASS} .${FILL_CLASS}.ad-ext-x01-score-progress__fill--effect-segment-drain{
@@ -342,18 +354,20 @@ ${HOST_SELECTOR}.${ACTIVE_CLASS} .${FILL_CLASS}.ad-ext-x01-score-progress__fill-
342354
}
343355
344356
@keyframes ad-ext-x01-score-progress-pulse-core{
345-
0%,100%{transform:scaleY(1);filter:brightness(1) saturate(1.02)}
346-
50%{transform:scaleY(1.18);filter:brightness(1.2) saturate(1.18)}
357+
0%,100%{transform:scaleY(1);filter:brightness(1.02) saturate(1.05);box-shadow:var(--ad-ext-x01-score-progress-fill-shadow)}
358+
48%{transform:scaleY(1.34);filter:brightness(1.36) saturate(1.28);box-shadow:var(--ad-ext-x01-score-progress-fill-shadow),0 0 16px var(--ad-ext-x01-score-progress-fill-outline-active),0 0 26px var(--ad-ext-x01-score-progress-fill-ambient-active)}
347359
}
348360
349361
@keyframes ad-ext-x01-score-progress-glass-charge-core{
350-
0%,100%{filter:brightness(1.02) saturate(1.03)}
351-
45%{filter:brightness(1.18) saturate(1.12)}
362+
0%,100%{filter:brightness(1.02) saturate(1.05);box-shadow:var(--ad-ext-x01-score-progress-fill-shadow),inset 0 1px 2px rgba(255,255,255,.26),inset 0 -1px 3px rgba(255,255,255,.1)}
363+
42%{filter:brightness(1.16) saturate(1.14);box-shadow:var(--ad-ext-x01-score-progress-fill-shadow),0 0 10px var(--ad-ext-x01-score-progress-fill-outline-active),inset 0 1px 4px rgba(255,255,255,.34),inset 0 -1px 5px rgba(255,255,255,.14)}
364+
62%{filter:brightness(1.34) saturate(1.26);box-shadow:var(--ad-ext-x01-score-progress-fill-shadow),0 0 18px var(--ad-ext-x01-score-progress-fill-outline-active),0 0 30px var(--ad-ext-x01-score-progress-fill-ambient-active),inset 0 1px 6px rgba(255,255,255,.46),inset 0 -1px 8px rgba(255,255,255,.18)}
352365
}
353366
354367
@keyframes ad-ext-x01-score-progress-glass-charge-sweep{
355-
0%{transform:translateX(-150%)}
356-
68%,100%{transform:translateX(155%)}
368+
0%,16%{transform:translateX(-175%);opacity:.18}
369+
56%{transform:translateX(-8%);opacity:1}
370+
78%,100%{transform:translateX(175%);opacity:.16}
357371
}
358372
359373
@keyframes ad-ext-x01-score-progress-segment-drain{

0 commit comments

Comments
 (0)