Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#7670: Simplify injection of widgets onto the page (renderWidget) #8150

Merged
merged 15 commits into from
Apr 8, 2024

Conversation

fregante
Copy link
Contributor

@fregante fregante commented Apr 4, 2024

What does this PR do?

This helper:

  • simplifies the injection of widgets onto the page
  • automatically removes the widget on context invalidated, and via supplied AbortSignal
  • avoids the additional wrapper created outside React that cause regularly causes conflicts
    • unfortunately React 17 doesn't properly support this, so I left a TODO for React 18

I expect most isolated components to use both the IsolatedWidget component (#7670) and renderWidget:

renderWidget({
  name: "SelectionMenu", // Identification in the dev tools
  widget: 
    <IsolatedComponent name="SelectionMenu">
      etc
    </IsolatedComponent>
});

Future work

  • Migrate the rest of the ReactDOM.render() usage here, particularly the popover utils will have the most benefit complexity-wise

Checklist

  • Add tests and/or storybook stories
  • Designate a primary reviewer: @grahamlangford

Copy link

codecov bot commented Apr 4, 2024

Codecov Report

Attention: Patch coverage is 82.53968% with 11 lines in your changes are missing coverage. Please review.

Project coverage is 73.44%. Comparing base (1995795) to head (c82c591).

❗ Current head c82c591 differs from pull request most recent head 88e004b. Consider uploading reports for the commit 88e004b to get more accurate results

Files Patch % Lines
src/contentScript/modalDom.tsx 45.45% 6 Missing ⚠️
src/utils/reactUtils.tsx 80.00% 4 Missing ⚠️
src/hooks/useContextInvalidated.ts 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #8150      +/-   ##
==========================================
+ Coverage   73.37%   73.44%   +0.06%     
==========================================
  Files        1314     1316       +2     
  Lines       40722    40735      +13     
  Branches     7571     7575       +4     
==========================================
+ Hits        29879    29916      +37     
+ Misses      10843    10819      -24     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

const style = document.createElement("style");
}> = ({ url, controller, onOutsideClick }) => {
const aborted = useAbortSignal(controller.signal);
useScrollLock(!aborted);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this file:

  • replace explicit attachShadow() call with renderWidget()'s own
  • replace inline solution with existing useScrollLock()

};
},
() => signal.aborted,
);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Likewise, we can use useSyncExternalStore to deal with promises too. I think the whole useAsyncState can be replaced with two useSyncExternalStore calls in 15 lines of code.

const containerStyle = {
zIndex: NOTIFICATIONS_Z_INDEX,
fontFamily: "sans-serif",
} satisfies React.CSSProperties;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just moved this out of the init.

signal.addEventListener("abort", () => {
root.remove();
unmountComponentAtNode(root);
});
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code is what we have repeated several times in the codebase, with various level of support and conflict prevention. renderWidget makes this more transparent and in React 18 we'll be able to skip the wrapper element too.

@fregante fregante changed the title #7670: Simplify injection of widgets onto the page #7670: Simplify injection of widgets onto the page (renderWidget) Apr 4, 2024
Copy link

github-actions bot commented Apr 8, 2024

No loom links were found in the first post. Please add one there if you'd like to it to appear on Slack.

Do not edit this comment manually.

@fregante
Copy link
Contributor Author

fregante commented Apr 8, 2024

Tested again, it works.

However I realized that we want notifications to survive context invalidation since we use them to inform the user:

/**
* Display a notification when the background page unloads/reloads because at this point
* all communication becomes impossible.
*/
export async function notifyContextInvalidated(): Promise<void> {

So I added a keepAfterInvalidation option specifically for this case.

@fregante fregante enabled auto-merge (squash) April 8, 2024 15:14
@fregante fregante merged commit 4e94c28 into main Apr 8, 2024
19 of 20 checks passed
@fregante fregante deleted the F/feature/renderWidget branch April 8, 2024 15:20
@grahamlangford grahamlangford added this to the 1.8.13 milestone Apr 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

2 participants