Unverified 提交 0c122e3b authored 作者: Will Chen's avatar Will Chen 提交者: GitHub

Add MutationObserver retry for component selector initialization (#2408)

## Summary - Fixes the component selector being permanently disabled when apps have delayed first render (e.g., async auth/Supabase initialization) - Uses MutationObserver to retry detecting `[data-dyad-id]` elements for up to 5 seconds - Properly cleans up observer and timeout when elements are found to avoid resource leaks ## Test plan 1. All existing `select component` e2e tests pass (4 tests) 2. Annotator e2e test passes 3. For manual testing: - Create an app that has delayed initialization (e.g., async auth check before rendering) - Previously: component selector button would be disabled - Now: component selector button should enable once components render Fixes #2231 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- devin-review-badge-begin --> --- <a href="https://app.devin.ai/review/dyad-sh/dyad/pull/2408"> <picture> <source media="(prefers-color-scheme: dark)" srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1"> <img src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1" alt="Open with Devin"> </picture> </a> <!-- devin-review-badge-end --> <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Adds a long-lived `MutationObserver`/timeout loop to initialization, which could affect iframe performance or leave the selector disabled if the observer logic misfires, though cleanup and a hard timeout mitigate this. > > **Overview** > Makes the component selector initialization resilient to delayed renders by no longer giving up immediately when no `[data-dyad-id]` elements exist. > > The client now retries by observing DOM/attribute mutations for newly tagged elements, posts `dyad-component-selector-initialized` once found, and cleans up the observer/timeout; it only logs the “no tagged elements” warning after a 60s timeout. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 56474bce646c9f41c87c869a4310964efcb62a99. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Fixes the component selector staying disabled when apps render late by retrying initialization until tagged elements appear. Adds a MutationObserver with a 60s timeout and proper cleanup. - **Bug Fixes** - Watch for [data-dyad-id] with a MutationObserver and retry init for up to 60s. - Disconnect observer and clear timeout once found; warn only if timeout expires. - Addresses Linear issue #2231 by enabling the selector after delayed renders. <sup>Written for commit 56474bce646c9f41c87c869a4310964efcb62a99. Summary will update on new commits.</sup> <!-- End of auto-generated description by cubic. --> --------- Co-authored-by: 's avatarClaude Opus 4.5 <noreply@anthropic.com>
上级 f0431145
......@@ -575,8 +575,28 @@
);
return;
}
setTimeout(() => {
// Usually the tagged elements are added right away, but in some cases (e.g.
// supabase auth loading), it can take a while and thus we use a timeout/observer
// to wait for tagged elements to appear.
//
// see: https://github.com/dyad-sh/dyad/issues/2231
const INIT_TIMEOUT_MS = 60_000; // Wait up to 60 seconds for tagged elements
let observer = null;
let timeoutId = null;
function checkForTaggedElements() {
if (document.body.querySelector("[data-dyad-id]")) {
// Clean up observer and timeout
if (observer) {
observer.disconnect();
observer = null;
}
if (timeoutId) {
clearTimeout(timeoutId);
timeoutId = null;
}
window.parent.postMessage(
{
type: "dyad-component-selector-initialized",
......@@ -584,11 +604,70 @@
"*",
);
console.debug("Dyad component selector initialized");
} else {
return true;
}
return false;
}
// First, try immediately
setTimeout(() => {
if (checkForTaggedElements()) {
return;
}
// If not found, set up MutationObserver to watch for tagged elements
console.debug(
"Dyad component selector waiting for tagged elements to appear...",
);
observer = new MutationObserver((mutations) => {
// Filter mutations to only process relevant changes
const hasRelevantMutation = mutations.some((mutation) => {
// Attribute mutation on data-dyad-id (already filtered by attributeFilter)
if (mutation.type === "attributes") {
return true;
}
// Check if any added nodes have data-dyad-id
if (mutation.type === "childList") {
for (const node of mutation.addedNodes) {
if (node.nodeType === Node.ELEMENT_NODE) {
if (
node.hasAttribute("data-dyad-id") ||
node.querySelector("[data-dyad-id]")
) {
return true;
}
}
}
}
return false;
});
if (hasRelevantMutation) {
checkForTaggedElements();
}
});
observer.observe(document.body, {
childList: true,
subtree: true,
attributes: true,
attributeFilter: ["data-dyad-id"],
});
// Set a timeout to give up after INIT_TIMEOUT_MS
timeoutId = setTimeout(() => {
if (observer) {
observer.disconnect();
observer = null;
}
// Only warn if we never found tagged elements
if (!document.body.querySelector("[data-dyad-id]")) {
console.warn(
"Dyad component selector not initialized because no DOM elements were tagged",
);
}
}, INIT_TIMEOUT_MS);
}, 0);
}
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论