H-6327: Integrate Sentry feedback button into ViewportControls#8537
H-6327: Integrate Sentry feedback button into ViewportControls#8537
Conversation
Move the demo-site from libs/@hashintel/petrinaut into its own private package at apps/petrinaut-website, consuming petrinaut as a workspace dependency instead of importing source directly. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… for website - Bundle Monaco Editor into petrinaut (removed from externals), using selective imports (editor.api.js + typescript.contribution.js) to avoid bundling unnecessary language workers - Add define for process.versions in petrinaut vite config for TypeScript internals - Fix Monaco provider to use new Worker() directly instead of returning a promise - Update Monaco type imports to use editor.api.js path across all sync files - Remove stale demo-site references from petrinaut eslint config - Add eslint.config.js for @apps/petrinaut-website - Fix import/export sorting Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Vite library mode emits worker assets as separate files that consumers can't resolve. Using ?worker&inline inlines the compiled worker code as a string and creates a Blob URL at runtime, making workers self-contained in the library bundle. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The canvas npm package is a Node.js native addon that crashes during SSR
in Next.js. Since refractive is a client-side component library, use the
browser-native equivalents instead:
- createImageData(w, h) → new ImageData(w, h)
- createCanvas(w, h) → document.createElement("canvas")
- Remove type-only ImageData imports (it's a browser global)
- Remove canvas from dependencies and vite externals
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…config - Add message queue in useLanguageClient so messages sent before async worker init are drained once the worker is ready - Add terminated flag to both worker hooks to prevent leaking workers if the component unmounts before the dynamic import resolves - Reject pending init promise on teardown in useSimulationWorker - Switch worker.onmessage/onerror to addEventListener for eslint compliance - Extract createSimulationWorker into its own module for clean test mocking - Update test suite to use async mocks via vi.mock instead of vi.stubGlobal - Set sideEffects: ["*.css"] instead of false to prevent CSS tree-shaking - Remove stale build:site task from turbo.json Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add a `viewportActions` prop to Petrinaut that allows consumers to inject custom action buttons into the viewport controls panel. Use this to move the Sentry feedback trigger from a floating overlay into the controls, with a purple button style and bug report icon. - Add `ViewportAction` type with key, icon, label, tooltip, onClick, style, className, and ref fields - Thread `viewportActions` through Petrinaut → EditorView → SDCPNView → ViewportControls - Set `autoInject: false` on Sentry feedbackIntegration - Use React 19 ref cleanup to attach/detach Sentry feedback listener Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
2 Skipped Deployments
|
PR SummaryMedium Risk Overview Updates Written by Cursor Bugbot for commit 70d198a. This will update automatically on new commits. Configure here. |
🤖 Augment PR SummarySummary: This PR adds an extension point for extra viewport control buttons and uses it to expose a Sentry “Give feedback” button in Petrinaut. Changes:
🤖 Was this summary useful? React with 👍 or 👎 |
| const icon = <MdBugReport size={14} />; | ||
|
|
||
| export function useSentryFeedbackAction(): ViewportAction { | ||
| return { |
There was a problem hiding this comment.
useSentryFeedbackAction() returns a new ViewportAction object (and callback ref) on every render, which can cause React to detach/reattach the ref and repeatedly run feedback.attachTo. That can lead to duplicate handlers or a subtle flicker if the host component re-renders frequently.
Severity: medium
🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.
| setTitle={setTitle} | ||
| title={currentNet.title} | ||
| undoRedo={undoRedo} | ||
| viewportActions={[sentryFeedbackAction]} |
There was a problem hiding this comment.
viewportActions={[sentryFeedbackAction]} creates a new array each render, so downstream components will always see this prop change. If the action/ref isn’t stable, this can amplify unnecessary ref detach/attach work for the Sentry feedback button.
Severity: low
🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
| }; | ||
| }, | ||
| }; | ||
| } |
There was a problem hiding this comment.
Unstable ref callback causes repeated Sentry attach/detach cycles
Medium Severity
useSentryFeedbackAction returns a new object (with a new ref callback) on every render without any memoization. Since DevApp re-renders on every net edit or state change, React 19 will invoke the old ref's cleanup (calling unsubscribe) and then call the new ref (calling attachTo again) on each render. This causes the Sentry feedback integration to be repeatedly detached and re-attached, which could cause brief unresponsiveness of the feedback button and unnecessary overhead. The return value — or at minimum the ref callback — needs to be memoized (e.g. via useMemo/useCallback).



🌟 What is the purpose of this PR?
The Sentry "Give feedback" button was floating on top of the UI and hiding elements underneath it. This PR moves it into the
ViewportControlspanel by introducing aviewportActionsprop on thePetrinautcomponent, allowing consumers to inject custom action buttons.🔗 Related links
🔍 What does this change?
ViewportActiontype (key,icon,label,tooltip,onClick,style,className,ref) exported from@hashintel/petrinautviewportActions?: ViewportAction[]prop toPetrinautProps, threaded through toViewportControlsViewportControlsrenders each action as anIconButtonafter the built-in buttonsautoInject: falseon Sentry'sfeedbackIntegrationto remove the floating buttonuseSentryFeedbackAction()hook in the website that returns aViewportActionusing Sentry'sgetFeedback().attachTo()API with a React 19 ref cleanup patternMdBugReporticonPre-Merge Checklist 🚀
🚢 Has this modified a publishable library?
This PR:
📜 Does this require a change to the docs?
The changes in this PR:
🕸️ Does this require a change to the Turbo Graph?
The changes in this PR:
❓ How to test this?
yarn devinapps/petrinaut-website