Commit 35207c31 authored by Imran Salam's avatar Imran Salam
Browse files

refactored browser activation method and fix track panel browser event issues

parent 7cced511
import React, { FunctionComponent, RefObject, useEffect } from 'react';
import { connect } from 'react-redux';
import { updateBrowserNavStates, updateChrLocation } from '../browserActions';
import {
updateBrowserNavStates,
updateChrLocation,
updateBrowserActivated
} from '../browserActions';
import { BrowserNavStates, ChrLocation } from '../browserState';
import { getBrowserNavOpened } from '../browserSelectors';
import { RootState } from 'src/rootReducer';
......@@ -13,6 +17,7 @@ type StateProps = {
};
type DispatchProps = {
updateBrowserActivated: (browserActivated: boolean) => void;
updateBrowserNavStates: (browserNavStates: BrowserNavStates) => void;
updateChrLocation: (chrLocation: ChrLocation) => void;
};
......@@ -48,22 +53,21 @@ export const BrowserImage: FunctionComponent<BrowserImageProps> = (
};
useEffect(() => {
let currentEl: HTMLDivElement | null = null;
if (props.browserRef) {
currentEl = props.browserRef.current as HTMLDivElement;
const currentEl: HTMLDivElement = props.browserRef
.current as HTMLDivElement;
activateIfPossible(currentEl as HTMLDivElement);
activateBrowser(currentEl, props);
currentEl.addEventListener('bpane-out', listenBpaneOut);
}
currentEl.addEventListener('bpane-out', listenBpaneOut);
return function cleanup() {
if (currentEl) {
if (currentEl && currentEl.ownerDocument) {
props.updateBrowserActivated(false);
currentEl.removeEventListener('bpane-out', listenBpaneOut);
}
};
}, []);
}, [props.browserRef]);
return (
<div
......@@ -73,7 +77,45 @@ export const BrowserImage: FunctionComponent<BrowserImageProps> = (
);
};
function activateIfPossible(currentEl: HTMLDivElement) {
function activateBrowser(currentEl: HTMLDivElement, props: BrowserImageProps) {
if (currentEl && currentEl.ownerDocument) {
const bodyEl = currentEl.ownerDocument.body as HTMLBodyElement;
// no need to check for DOM mutations if the browser class is already set in body
if (bodyEl.classList.contains('browser-app-ready')) {
dispatchActivateEvents(currentEl, props);
return;
}
const observerConfig = {
attributeFilter: ['class'],
attributes: true,
subtree: false
};
const observerCallback = (mutationsList: MutationRecord[]) => {
for (const mutation of mutationsList) {
const mutationNode = mutation.target as HTMLElement;
if (mutationNode.classList.contains('browser-app-ready')) {
dispatchActivateEvents(currentEl, props);
observer.disconnect();
break;
}
}
};
const observer = new MutationObserver(observerCallback);
observer.observe(bodyEl, observerConfig);
}
}
function dispatchActivateEvents(
currentEl: HTMLDivElement,
props: BrowserImageProps
) {
const activateEvent = new CustomEvent('bpane-activate', {
bubbles: true,
detail: {
......@@ -81,22 +123,8 @@ function activateIfPossible(currentEl: HTMLDivElement) {
}
});
let done = false;
if (currentEl && currentEl.ownerDocument) {
const bodyEl = currentEl.ownerDocument.querySelector(
'body'
) as HTMLBodyElement;
if (bodyEl.classList.contains('browser-app-ready')) {
currentEl.dispatchEvent(activateEvent);
done = true;
}
}
if (!done) {
setTimeout(() => activateIfPossible(currentEl), 250);
}
currentEl.dispatchEvent(activateEvent);
props.updateBrowserActivated(true);
}
function getBrowserImageClasses(browserNavOpened: boolean): string {
......@@ -114,6 +142,7 @@ const mapStateToProps = (state: RootState): StateProps => ({
});
const mapDispatchToProps: DispatchProps = {
updateBrowserActivated,
updateBrowserNavStates,
updateChrLocation
};
......
import React, { FunctionComponent, RefObject, useEffect } from 'react';
import React, {
FunctionComponent,
RefObject,
useEffect,
Fragment
} from 'react';
import { connect } from 'react-redux';
import TrackPanelBar from './track-panel-bar/TrackPanelBar';
......@@ -15,7 +20,8 @@ import {
import {
getCurrentTrack,
getDrawerOpened,
getTrackPanelOpened
getTrackPanelOpened,
getBrowserActivated
} from '../browserSelectors';
import { getLaunchbarExpanded } from 'src/header/headerSelectors';
......@@ -25,6 +31,7 @@ import { BreakpointWidth } from 'src/globalConfig';
import styles from './TrackPanel.scss';
type StateProps = {
browserActivated: boolean;
currentTrack: string;
drawerOpened: boolean;
breakpointWidth: BreakpointWidth;
......@@ -57,28 +64,33 @@ const TrackPanel: FunctionComponent<TrackPanelProps> = (
return (
<section className={`${styles.trackPanel} reactSlideDrawer`}>
<TrackPanelBar
drawerOpened={props.drawerOpened}
launchbarExpanded={props.launchbarExpanded}
toggleDrawer={props.toggleDrawer}
toggleTrackPanel={props.toggleTrackPanel}
trackPanelOpened={props.trackPanelOpened}
/>
{props.trackPanelOpened ? (
<TrackPanelList
browserRef={props.browserRef}
currentTrack={props.currentTrack}
launchbarExpanded={props.launchbarExpanded}
toggleDrawer={props.toggleDrawer}
updateTrack={props.changeCurrentTrack}
/>
) : null}
{props.browserActivated && (
<Fragment>
<TrackPanelBar
drawerOpened={props.drawerOpened}
launchbarExpanded={props.launchbarExpanded}
toggleDrawer={props.toggleDrawer}
toggleTrackPanel={props.toggleTrackPanel}
trackPanelOpened={props.trackPanelOpened}
/>
{props.trackPanelOpened ? (
<TrackPanelList
browserRef={props.browserRef}
currentTrack={props.currentTrack}
launchbarExpanded={props.launchbarExpanded}
toggleDrawer={props.toggleDrawer}
updateTrack={props.changeCurrentTrack}
/>
) : null}
</Fragment>
)}
</section>
);
};
const mapStateToProps = (state: RootState): StateProps => ({
breakpointWidth: getBreakpointWidth(state),
browserActivated: getBrowserActivated(state),
currentTrack: getCurrentTrack(state),
drawerOpened: getDrawerOpened(state),
launchbarExpanded: getLaunchbarExpanded(state),
......
......@@ -20,8 +20,6 @@ type TrackPanelListProps = {
const TrackPanelList: FunctionComponent<TrackPanelListProps> = (
props: TrackPanelListProps
) => {
const browserImageEl = props.browserRef.current as HTMLDivElement;
const changeTrack = (currentTrack: string) => {
const { toggleDrawer, updateTrack } = props;
......@@ -51,7 +49,7 @@ const TrackPanelList: FunctionComponent<TrackPanelListProps> = (
const getTrackListItem = (track: TrackPanelItem) => (
<TrackPanelListItem
browserImageEl={browserImageEl}
browserRef={props.browserRef}
className={getTrackClass(track.name)}
changeTrack={changeTrack}
key={track.id}
......
import React, { FunctionComponent, Fragment, ReactNode, useState } from 'react';
import React, {
FunctionComponent,
Fragment,
ReactNode,
RefObject,
useState
} from 'react';
import { TrackPanelItem, trackPanelIconConfig } from '../trackPanelConfig';
import chevronDownIcon from 'static/img/shared/chevron-down.svg';
......@@ -7,20 +13,23 @@ import chevronUpIcon from 'static/img/shared/chevron-up.svg';
import styles from './TrackPanelListItem.scss';
type TrackPanelListItemProps = {
browserImageEl: HTMLDivElement | null;
browserRef: RefObject<HTMLDivElement>;
children?: ReactNode[];
className: string;
track: TrackPanelItem;
changeTrack: (name: string) => void;
};
// delete this when there is a better place to put this
const trackPrefix = 'internal:debug';
const TrackPanelListItem: FunctionComponent<TrackPanelListItemProps> = (
props: TrackPanelListItemProps
) => {
const [expanded, setExpanded] = useState(false);
const [trackStatus, setTrackStatus] = useState('on');
const { browserImageEl, className, track } = props;
const { browserRef, className, track } = props;
const { ellipsis, eye } = trackPanelIconConfig;
const listItemClass = styles[className] || '';
......@@ -35,15 +44,15 @@ const TrackPanelListItem: FunctionComponent<TrackPanelListItemProps> = (
const toggleTrack = () => {
const currentTrackStatus = trackStatus === 'on' ? 'off' : 'on';
const navEvent = new CustomEvent('bpane', {
const trackEvent = new CustomEvent('bpane', {
bubbles: true,
detail: {
[currentTrackStatus]: track.name
[currentTrackStatus]: `${trackPrefix}:${track.name}`
}
});
if (browserImageEl) {
browserImageEl.dispatchEvent(navEvent);
if (browserRef.current) {
browserRef.current.dispatchEvent(trackEvent);
}
setTrackStatus(currentTrackStatus);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment