21762: added trycatch to observer callback
[arvados.git] / services / workbench2 / src / views-components / side-panel / side-panel.tsx
index 18aed873aa9fc018b36585ea09ea2846122fd28a..80cfe75b27d4bb3dd61c44ca5a1ac98e5460685b 100644 (file)
@@ -2,13 +2,13 @@
 //
 // SPDX-License-Identifier: AGPL-3.0
 
-import React from 'react';
+import React, { useRef, useEffect } from 'react';
 import { StyleRulesCallback, WithStyles, withStyles } from '@material-ui/core/styles';
 import { ArvadosTheme } from 'common/custom-theme';
 import { SidePanelTree, SidePanelTreeProps } from 'views-components/side-panel-tree/side-panel-tree';
 import { Dispatch } from 'redux';
 import { connect } from 'react-redux';
-import { navigateFromSidePanel } from 'store/side-panel/side-panel-action';
+import { navigateFromSidePanel, setCurrentSideWidth } from 'store/side-panel/side-panel-action';
 import { Grid } from '@material-ui/core';
 import { SidePanelButton } from 'views-components/side-panel-button/side-panel-button';
 import { RootState } from 'store/store';
@@ -36,30 +36,70 @@ const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
 const mapDispatchToProps = (dispatch: Dispatch): SidePanelTreeProps => ({
     onItemActivation: id => {
         dispatch<any>(navigateFromSidePanel(id));
+    },
+    setCurrentSideWidth: width => {
+        dispatch<any>(setCurrentSideWidth(width))
     }
 });
 
-const mapStateToProps = ({ router, sidePanel }: RootState) => ({
+const mapStateToProps = ({ router, sidePanel, detailsPanel }: RootState) => ({
     currentRoute: router.location ? router.location.pathname : '',
-    isCollapsed: sidePanel.collapsedState
+    isCollapsed: sidePanel.collapsedState,
+    isDetailsPanelTransitioning: detailsPanel.isTransitioning
 });
 
 export const SidePanel = withStyles(styles)(
     connect(mapStateToProps, mapDispatchToProps)(
-        ({ classes, ...props }: WithStyles<CssRules> & SidePanelTreeProps & { currentRoute: string }) =>
-            <Grid item xs>
-                {props.isCollapsed ? 
-                <>
-                    <SidePanelToggle />
-                    <SidePanelCollapsed />
-                </>
-                :
-                <>
-                    <Grid className={classes.topButtonContainer}>
-                        <SidePanelButton key={props.currentRoute} />
-                        <SidePanelToggle/>
+        ({ classes, ...props }: WithStyles<CssRules> & SidePanelTreeProps & { currentRoute: string, isDetailsPanelTransitioning: boolean }) =>{
+
+        const splitPaneRef = useRef<any>(null)
+
+        useEffect(()=>{
+            const splitPane = splitPaneRef?.current as Element
+
+            if (!splitPane) return;
+
+            const observerCallback: ResizeObserverCallback = (entries: ResizeObserverEntry[]) => {
+                try {
+                    //prevents potential infinite resize triggers
+                    window.requestAnimationFrame((): void | undefined => {
+                    if (!Array.isArray(entries) || !entries.length) {
+                        return;
+                    }
+                        const width = entries[0].contentRect.width
+                        props.setCurrentSideWidth(width)
+                    });
+                } catch (error) {
+                    console.error('Error in resize observer callback', error);
+                }
+              };
+
+            const observer = new ResizeObserver(observerCallback)
+
+            observer.observe(splitPane)
+            return ()=> observer.disconnect()
+        }, [props])
+
+            return (
+                <Grid item xs>
+                        {props.isCollapsed ? 
+                            <div ref={splitPaneRef}>
+                                <>
+                                    <SidePanelToggle />
+                                    <SidePanelCollapsed />
+                                </>
+                            </div>
+                            :
+                            <>
+                                <div ref={splitPaneRef}>
+                                    <Grid className={classes.topButtonContainer}>
+                                        <SidePanelButton key={props.currentRoute} />
+                                        <SidePanelToggle/>
+                                    </Grid>
+                                    <SidePanelTree {...props} />
+                                </div>
+                            </>
+                        }
                     </Grid>
-                    <SidePanelTree {...props} />
-                </>}
-            </Grid>
+        )}
     ));