Skip to content

Commit

Permalink
better error handling (#18)
Browse files Browse the repository at this point in the history
  • Loading branch information
martrapp authored Aug 18, 2024
1 parent 4ea68cd commit 62c7102
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 54 deletions.
5 changes: 5 additions & 0 deletions .changeset/slow-clouds-love.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@vtbag/inspection-chamber': patch
---

Improves robustness against broken animations and outputs better error messages.
76 changes: 23 additions & 53 deletions src/animations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,10 @@ export function listAnimations(name: string) {
anim.innerHTML = !vtActive()
? ''
: `<h4 data-vtbag-name=${name}>Animations of ${name}:</h4>` +
animationPanel2('group') +
animationPanel2('image-pair') +
animationPanel2('old') +
animationPanel2('new');
animationPanel('group') +
animationPanel('image-pair') +
animationPanel('old') +
animationPanel('new');

anim.querySelectorAll<HTMLInputElement>('input[type="checkbox"]').forEach((box) => {
const context = JSON.parse(box.dataset.vtbagContext!);
Expand All @@ -141,21 +141,28 @@ export function listAnimations(name: string) {
});
plugInPanel(anim);

function animationPanel2(pseudo: string) {
function animationPanel(pseudo: string) {
const res: string[] = [];
const style = styleMap.get(`${pseudo}-${name}`) as CSSStyleDeclaration;
const cssAnimation = style?.animation;
const animationName = style?.animationName;
if (animationName && animationName !== 'vtbag-twin-noop' && animationName !== 'none') {
const animationNames = style.animationName.split(', ');
const animationNames = animationName.split(', ');
let skipped = 0;
cssAnimation.split(/,(?![^(]*\))/).forEach((animation, idx) => {
res.push(
`<details><summary><input type="checkbox" data-vtbag-context='{"pseudo":"${pseudo}","idx":${idx}}'/> ${pseudo}: <tt>${animationNames[idx]}</tt></summary>${details(animationNames[idx], animation.endsWith(animationName) ? animation.slice(0, -animationName.length) : animation)}</details>`
);
if (inspectionChamber.keyframesMap?.get(animationNames[idx])) {
res.push(
`<details><summary><input type="checkbox" data-vtbag-context='{"pseudo":"${pseudo}","idx":${idx - skipped}}'/> ${pseudo}: <tt>${animationNames[idx]}</tt></summary>${details(animationNames[idx], animation.endsWith(animationName) ? animation.slice(0, -animationName.length) : animation)}</details>`
);
} else {
res.push(
`<span style="padding-right: 0.25ex; width: 4.75ex; display: inline-block; text-align:right">🔴</span> ${pseudo}: <tt>${animationNames[idx]}</tt><br>`
);
++skipped;
console.error(`[inspection chamber] did not find keyframes named "${animationNames[idx]}" for ::view-transition-${pseudo}(${name})`)
}
});
}
//const cssTtransition = style?.transition;

return res.length > 0 ? res.join('') + '<hr>' : '';

function details(keyframeName: string, animation: string) {
Expand All @@ -168,48 +175,11 @@ export function listAnimations(name: string) {
}
}

function animationPanel(pseudo: string) {
const style = styleMap.get(`${pseudo}-${name}`) as CSSStyleDeclaration;
const animationName = style?.animationName;
if (!style || !animationName || animationName === 'vtbag-twin-noop' || animationName === 'none')
return '';
const animationNames = animationName.split(', ');
const delays = style.animationDelay.split(', ');
const durations = style.animationDuration.split(', ');
const directions = style.animationDirection.split(', ');
const fillModes = style.animationFillMode.split(', ');
const iterationCounts = style.animationIterationCount.split(', ');
const timingFunctions = style.animationTimingFunction.split(/,(?![^(]*\))/);
const timelines =
'animationTimeline' in style ? (style['animationTimeline'] as string).split(', ') : [];

const res: string[] = [];
animationNames.forEach((animationName, idx) => {
res.push(
`<details><summary><input type="checkbox" data-vtbag-context='{"pseudo":"${pseudo}","idx":${idx}}'/> ${pseudo}: <tt>${animationName}(${durations[idx % durations.length]}, ${delays[idx % delays.length]})</tt></summary>${details(idx, animationName)}</details>`
);
});
return res.join('') + '<hr>';

function details(idx: number, keyframeName: string) {
return `
<table>
${row('direction:', directions[idx % directions.length])}
${row('fill-mode:', fillModes[idx % fillModes.length])}
${row('iteration-count:', iterationCounts[idx % iterationCounts.length])}
${row('timing-function:', timingFunctions[idx % timingFunctions.length])}
${row('timeline:', timelines[idx % timelines.length])}
${row('animates:', keyframeProperties(keyframeName))}
${keyframes(keyframeName)}
</table>`;
}
}
function keyframeProperties(name: string) {
const keys = new Set<string>();
inspectionChamber.keyframesMap
?.get(name)
?.forEach((k) => Object.keys(k).forEach((key) => keys.add(key)));
const meta = ['offset', 'computedOffset', 'easing', 'composite'];
return [...keys]
.filter((k) => !meta.includes(k))
.sort()
Expand All @@ -219,7 +189,7 @@ export function listAnimations(name: string) {
function keyframes(name: string) {
return inspectionChamber.keyframesMap
?.get(name)
?.map((key, idx) =>
?.map((key) =>
row(
+(key.computedOffset ?? 0) * 100 + '% :',
Object.keys(key)
Expand Down Expand Up @@ -269,15 +239,15 @@ export function selectAnimation(name: string, pseudo: string, idx: number) {
const pseudoElement = `::view-transition-${pseudo}(${name})`;
const selected = animations.filter((anim) => anim.effect?.pseudoElement === pseudoElement);
if (idx >= selected.length) {
console.error('[injection chamber] no animation found with idx', idx);
console.error(
`[injection chamber] found ${selected.length} animations for ${pseudoElement} when looking for animation with index ${idx} called ${name}`
);
return;
}
const result = selected[idx];
if (result instanceof CSSAnimation && result.animationName !== animationName) {
console.error(
'[injection chamber] animation name mismatch',
animationName,
result.animationName
`[injection chamber] found an animation called ${result.animationName} for ${pseudoElement} when looking for animation at index ${idx} with expected name ${name}`
);
return;
}
Expand Down
1 change: 1 addition & 0 deletions src/bench.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<meta name="astro-view-transitions-enabled" content="true" />
</head>
<body>
<div style="display:none" id="vtbot-loading-indicator"></div>
<iframe id="vtbag-main-frame" src="/"></iframe>
<div id="divider" class="divider"></div>

Expand Down
2 changes: 1 addition & 1 deletion src/panel/full-control.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ export function controlledPlay() {
controller2.max = '' + animationEndTime;
controller2.value = '0';
controller2.disabled = false;
showSomeAnimations();
control();
updateNameVisibility();
//showSomeAnimations();
}

export function control() {
Expand Down

0 comments on commit 62c7102

Please sign in to comment.