Skip to content

Commit 835dfd5

Browse files
fix(CodeModal): Fix ResizeObserver loop completed with undelivered notifications issue (#688)
This moves resize handling/detection to where we have control over it. We are able to put more control over it so it doesn't loop infinitely the way putting a code editor in a modal seems to do.
1 parent bb47c8e commit 835dfd5

File tree

1 file changed

+54
-7
lines changed

1 file changed

+54
-7
lines changed

packages/module/src/CodeModal/CodeModal.tsx

Lines changed: 54 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,23 @@
11
// ============================================================================
22
// Code Modal - Chatbot Modal with Code Editor
33
// ============================================================================
4+
45
import type { FunctionComponent, MouseEvent } from 'react';
5-
import { useState } from 'react';
6+
import { useState, useEffect, useRef } from 'react';
67
import path from 'path-browserify';
8+
import type monaco from 'monaco-editor';
79

810
// Import PatternFly components
911
import { CodeEditor } from '@patternfly/react-code-editor';
10-
import { Button, ModalBody, ModalFooter, ModalHeader, Stack, StackItem } from '@patternfly/react-core';
12+
import {
13+
Button,
14+
getResizeObserver,
15+
ModalBody,
16+
ModalFooter,
17+
ModalHeader,
18+
Stack,
19+
StackItem
20+
} from '@patternfly/react-core';
1121
import FileDetails, { extensionToLanguage } from '../FileDetails';
1222
import { ChatbotDisplayMode } from '../Chatbot';
1323
import ChatbotModal from '../ChatbotModal/ChatbotModal';
@@ -73,6 +83,34 @@ export const CodeModal: FunctionComponent<CodeModalProps> = ({
7383
...props
7484
}: CodeModalProps) => {
7585
const [newCode, setNewCode] = useState(code);
86+
const [editorInstance, setEditorInstance] = useState<monaco.editor.IStandaloneCodeEditor | null>(null);
87+
const [isEditorReady, setIsEditorReady] = useState(false);
88+
const containerRef = useRef<HTMLDivElement>(null);
89+
90+
useEffect(() => {
91+
if (!isModalOpen || !isEditorReady || !editorInstance || !containerRef.current) {
92+
return;
93+
}
94+
95+
const handleResize = () => {
96+
if (editorInstance && isEditorReady && isModalOpen) {
97+
try {
98+
window.requestAnimationFrame(() => {
99+
editorInstance.layout();
100+
});
101+
} catch (error) {
102+
// eslint-disable-next-line no-console
103+
console.error('ChatBot code modal layout error:', error);
104+
}
105+
}
106+
};
107+
108+
const observer = getResizeObserver(containerRef.current, handleResize);
109+
110+
return () => {
111+
observer();
112+
};
113+
}, [editorInstance, isEditorReady, isModalOpen]);
76114

77115
const handlePrimaryAction = (_event: MouseEvent | MouseEvent | KeyboardEvent) => {
78116
handleModalToggle(_event);
@@ -89,9 +127,15 @@ export const CodeModal: FunctionComponent<CodeModalProps> = ({
89127
};
90128

91129
const onEditorDidMount = (editor, monaco) => {
92-
editor.layout();
93-
editor.focus();
130+
setEditorInstance(editor);
131+
94132
monaco.editor.getModels()[0].updateOptions({ tabSize: 5 });
133+
134+
if (containerRef.current) {
135+
setIsEditorReady(true);
136+
editor.layout();
137+
editor.focus();
138+
}
95139
};
96140

97141
const onCodeChange = (value: string) => {
@@ -117,7 +161,7 @@ export const CodeModal: FunctionComponent<CodeModalProps> = ({
117161
<StackItem className="pf-chatbot__code-modal-file-details">
118162
<FileDetails fileName={fileName} />
119163
</StackItem>
120-
<StackItem className="pf-chatbot__code-modal-editor">
164+
<div className="pf-v6-l-stack__item pf-chatbot__code-modal-editor" ref={containerRef}>
121165
<CodeEditor
122166
isDarkTheme
123167
isLineNumbersVisible={isLineNumbersVisible}
@@ -132,11 +176,14 @@ export const CodeModal: FunctionComponent<CodeModalProps> = ({
132176
isFullHeight
133177
options={{
134178
glyphMargin: false,
135-
folding: false
179+
folding: false,
180+
// prevents Monaco from handling resizing itself
181+
// was causing ResizeObserver issues
182+
automaticLayout: false
136183
}}
137184
{...props}
138185
/>
139-
</StackItem>
186+
</div>
140187
</Stack>
141188
</ModalBody>
142189
<ModalFooter className={modalFooterClassName}>

0 commit comments

Comments
 (0)