Align outro animations at slide end
Publish Docker Image / build-and-push-existing-registry (./build/Dockerfile, web, pulse-signage-web) (push) Successful in 1m21s
Publish Docker Image / build-and-push-existing-registry (./build/Dockerfile.player, player, pulse-signage-player) (push) Successful in 33s

This commit is contained in:
lzstealth committed 2026-10-26 23:13:11 +00:00
1 parent 8ee59e97d3
commit 24a566a1a4
7 files changed
+88 -49

No files matched your search

+5 -1
View File
@@ -1256,8 +1256,12 @@ test('player applies animation delays and schedules outro triggers to finish at
assert.equal(values['animation-delay'], '250ms');
sandbox.scheduleSlideOutro(5000);
assert.equal(timers[0].delay, 3200);
assert.equal(timers[0].delay, 3150);
timers[0].callback();
assert.equal(values['--animate-duration'], '700ms');
assert.equal(values['animation-delay'], undefined);
timers.length = 0;
assert.equal(sandbox.scheduleSlideOutro(1000), 1850);
assert.equal(timers[0].delay, 0);
});
+7 -3
View File
@@ -386,8 +386,8 @@ test('slide advanced popup applies changes, cancels drafts and preserves the par
const previewTimers = [];
const context = { window: { innerWidth: 1200,
setTimeout(_callback, delay) { previewTimers.push(delay); return previewTimers.length; }, clearTimeout() {},
getComputedStyle() {
return { animationDuration: '400ms' };
getComputedStyle(element) {
return { animationDuration: element.dataset.regionKey === 'fixed_brand' ? '400ms' : '100ms' };
},
pulseModal: {
show(modal) { this.getOrCreate(modal)._scrollBar.hide(); modal.shown = true; },
@@ -419,7 +419,10 @@ test('slide advanced popup applies changes, cancels drafts and preserves the par
outro: { preset: 'hinge', duration_ms: 200, delay_ms: 500 },
loop: { preset: 'pulse', duration_ms: 200, delay_ms: 240, iterations: 1 }
} },
{ region_key: 'fixed_brand_second', read_only: true, animation_json: { loop: { preset: 'pulse', duration_ms: 200, iterations: 1 } } }
{ region_key: 'fixed_brand_second', read_only: true, animation_json: {
outro: { preset: 'fadeOut', duration_ms: 100 },
loop: { preset: 'pulse', duration_ms: 200, iterations: 1 }
} }
] }; },
getAnimationOverrides() { return {}; }, requestPreviewRender() {}, markEdited() {},
setAnimationOverrides(value) { applied = value; }
@@ -437,6 +440,7 @@ test('slide advanced popup applies changes, cancels drafts and preserves the par
animationPreviewButtons[2].handlers.click();
animationPreviewButtons[1].handlers.click();
assert.equal(readonlyPreviewRegion.style.values['animation-delay'], '0ms');
assert.equal(secondPreviewRegion.style.values['animation-delay'], '300ms');
animationPreviewButtons[1].handlers.click();
assert.equal(previewTimers[previewTimers.length - 1], 580);
const resetRegion = ids['slide-animation-reset-region'];
+13
View File
@@ -609,4 +609,17 @@ test('template animation preview applies configured delays to the CSS animation
assert.equal(values['animation-delay'], '425ms');
context.applyAnimateCssPreview(rect, 'fadeOut', { duration_ms: 1000, delay_ms: 425 }, 'out');
assert.equal(values['animation-delay'], undefined);
});
test('template outro preview aligns regions using computed CSS animation duration', () => {
const script = fs.readFileSync(require.resolve('../src/web/public/js/templates/template-designer.js'), 'utf8');
assert.match(script, /getComputedAnimationDurationMs\(rect, durationMs\) \* iterations/);
assert.match(script, /mode === 'out' \? Math\.max\(0, longestTimingMs - entry\.runtimeMs\) : entry\.delay/);
assert.match(script, /Number\(rect\.getAttribute\('data-index'\)\)/);
const helper = script.match(/ function getComputedAnimationDurationMs\([^]*?\n }/);
assert.ok(helper);
const context = vm.createContext({ window: { getComputedStyle() { return { animationDuration: '1s, 2.5s' }; } } });
vm.runInContext(helper[0] + '\nthis.getComputedAnimationDurationMs = getComputedAnimationDurationMs;', context);
assert.equal(context.getComputedAnimationDurationMs({}, 900), 2500);
});