Skip to content
This repository was archived by the owner on Feb 19, 2025. It is now read-only.

Commit ff011d0

Browse files
committed
Added workaround for memory leak when unmounting WV in Mendix
1 parent 227519d commit ff011d0

File tree

7 files changed

+45
-3
lines changed

7 files changed

+45
-3
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "webviewer",
33
"widgetName": "WebViewer",
4-
"version": "1.1.0",
4+
"version": "1.1.1",
55
"description": "My widget description",
66
"copyright": "2022 PDFTron",
77
"author": "Andrey Safonov",

src/WebViewer.editorPreview.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export class preview extends Component<WebViewerPreviewProps> {
2222
enabledElements: this.props.enabledElements,
2323
disabledElements: this.props.disabledElements,
2424
selectAnnotationOnCreation: this.props.selectAnnotationOnCreation,
25+
isVisible: this.props.isVisible === "true",
2526
enableDarkMode: this.props.enableDarkMode,
2627
enableFullAPI: this.props.enableFullAPI,
2728
customCss: this.props.customCss,

src/WebViewer.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export default class WebViewer extends Component<WebViewerContainerProps> {
2323
enabledElements: this.props.enabledElements,
2424
disabledElements: this.props.disabledElements,
2525
selectAnnotationOnCreation: this.props.selectAnnotationOnCreation,
26+
isVisible: this.props.isVisible?.value,
2627
enableDarkMode: this.props.enableDarkMode,
2728
enableFullAPI: this.props.enableFullAPI,
2829
customCss: this.props.customCss,

src/WebViewer.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,13 @@
7373
</propertyGroup>
7474
</propertyGroup>
7575
<propertyGroup caption="UI">
76+
<property key="isVisible" type="attribute">
77+
<caption>Is visible</caption>
78+
<description>A flag to toggle the visibility of WebViewer. Please use this option to hide WebViewer over the one in Common.</description>
79+
<attributeTypes>
80+
<attributeType name="Boolean"/>
81+
</attributeTypes>
82+
</property>
7683
<property key="containerHeight" type="string" required="true" defaultValue="100vh">
7784
<caption>Container height</caption>
7885
<description>The height of the container, in CSS, that WebViewer mounts to. Ultimately, the height of WebViewer as well.</description>

src/components/PDFViewer.tsx

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { createElement, useRef, useEffect, useState } from "react";
2+
import { unmountComponentAtNode } from "react-dom";
23
import viewer, { WebViewerInstance } from "@pdftron/webviewer";
34
import WebViewerModuleClient from "../clients/WebViewerModuleClient";
45

@@ -18,6 +19,7 @@ export interface InputProps {
1819
enabledElements: string;
1920
disabledElements: string;
2021
selectAnnotationOnCreation?: boolean;
22+
isVisible?: boolean;
2123
enableDarkMode?: boolean;
2224
enableFullAPI?: boolean;
2325
customCss?: string;
@@ -30,6 +32,25 @@ const PDFViewer: React.FC<InputProps> = props => {
3032
const viewerRef = useRef<HTMLDivElement>(null);
3133
const [wvInstance, setInstance] = useState<null | WebViewerInstance>(null);
3234

35+
// Perform clean-up of WV when unmounted forcibly.
36+
useEffect(() => {
37+
const topWindow = window.top;
38+
return () => {
39+
if (wvInstance) {
40+
// Disposing WV events
41+
wvInstance.UI.dispose();
42+
const element = wvInstance.UI.iframeWindow.document.getElementById("app") as Element;
43+
// Further remove React component
44+
unmountComponentAtNode(element);
45+
// This part is necessary as a page refresh is the only way everything gets cleared.
46+
// However, the page will show a reload post navigation.
47+
if (topWindow) {
48+
topWindow.location.reload();
49+
}
50+
}
51+
};
52+
}, [wvInstance]);
53+
3354
useEffect(() => {
3455
viewer(
3556
{
@@ -118,7 +139,17 @@ const PDFViewer: React.FC<InputProps> = props => {
118139
}
119140
}, [wvInstance, props.file]);
120141

121-
return <div className="webviewer" style={{ height: props.containerHeight }} ref={viewerRef}></div>;
142+
return (
143+
<div
144+
className="webviewer"
145+
style={{
146+
height: props.containerHeight,
147+
visibility:
148+
props.isVisible || props.isVisible === undefined || props.isVisible === null ? "visible" : "hidden"
149+
}}
150+
ref={viewerRef}
151+
></div>
152+
);
122153
};
123154

124155
export default PDFViewer;

src/package.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0" encoding="utf-8" ?>
22
<package xmlns="http://www.mendix.com/package/1.0/">
3-
<clientModule name="WebViewer" version="1.1.0" xmlns="http://www.mendix.com/clientModule/1.0/">
3+
<clientModule name="WebViewer" version="1.1.1" xmlns="http://www.mendix.com/clientModule/1.0/">
44
<widgetFiles>
55
<widgetFile path="WebViewer.xml"/>
66
</widgetFiles>

typings/WebViewerProps.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ export interface WebViewerContainerProps {
4444
enableMeasurement: boolean;
4545
enableRedaction: boolean;
4646
selectAnnotationOnCreation: boolean;
47+
isVisible: EditableValue<boolean>;
4748
containerHeight: string;
4849
enableDarkMode: boolean;
4950
defaultLanguage: DefaultLanguageEnum;
@@ -73,6 +74,7 @@ export interface WebViewerPreviewProps {
7374
enableMeasurement: boolean;
7475
enableRedaction: boolean;
7576
selectAnnotationOnCreation: boolean;
77+
isVisible: string;
7678
containerHeight: string;
7779
enableDarkMode: boolean;
7880
defaultLanguage: DefaultLanguageEnum;

0 commit comments

Comments
 (0)