BrowserImage.tsx 2.91 KB
Newer Older
1
import React, { FunctionComponent, RefObject, useEffect } from 'react';
2
import { connect } from 'react-redux';
3

4 5
import { updateBrowserNavStates, updateChrLocation } from '../browserActions';
import { BrowserNavStates, ChrLocation } from '../browserState';
6 7
import { getBrowserNavOpened } from '../browserSelectors';
import { RootState } from 'src/rootReducer';
8

9 10
import styles from './BrowserImage.scss';

11 12 13 14 15 16
type StateProps = {
  browserNavOpened: boolean;
};

type DispatchProps = {
  updateBrowserNavStates: (browserNavStates: BrowserNavStates) => void;
17
  updateChrLocation: (chrLocation: ChrLocation) => void;
18 19
};

20 21 22
type OwnProps = {
  browserRef: RefObject<HTMLDivElement>;
};
23 24

type BrowserImageProps = StateProps & DispatchProps & OwnProps;
25

26 27 28
type BpaneOutEvent = Event & {
  detail: {
    bumper?: BrowserNavStates;
29
    location?: ChrLocation;
30 31 32 33 34 35 36 37 38
  };
};

export const BrowserImage: FunctionComponent<BrowserImageProps> = (
  props: BrowserImageProps
) => {
  const listenBpaneOut = (event: Event) => {
    const bpaneOutEvent = event as BpaneOutEvent;
    const navIconStates = bpaneOutEvent.detail.bumper as BrowserNavStates;
39
    const chrLocation = bpaneOutEvent.detail.location as ChrLocation;
40 41 42 43

    if (navIconStates) {
      props.updateBrowserNavStates(navIconStates);
    }
44 45 46 47

    if (chrLocation) {
      props.updateChrLocation(chrLocation);
    }
48 49
  };

50
  useEffect(() => {
51 52
    let currentEl: HTMLDivElement | null = null;

53 54
    if (props.browserRef) {
      currentEl = props.browserRef.current as HTMLDivElement;
55 56 57 58

      activateIfPossible(currentEl as HTMLDivElement);

      currentEl.addEventListener('bpane-out', listenBpaneOut);
59
    }
60

61 62 63 64 65
    return function cleanup() {
      if (currentEl) {
        currentEl.removeEventListener('bpane-out', listenBpaneOut);
      }
    };
66
  }, []);
67

68 69 70
  return (
    <div
      className={getBrowserImageClasses(props.browserNavOpened)}
71
      ref={props.browserRef}
72 73
    />
  );
74
};
75

76 77 78 79 80
function activateIfPossible(currentEl: HTMLDivElement) {
  const activateEvent = new CustomEvent('bpane-activate', {
    bubbles: true,
    detail: {
      key: 'main'
81
    }
82
  });
83

84 85 86 87 88 89 90 91 92 93
  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;
Dan Sheppard's avatar
Dan Sheppard committed
94 95
    }
  }
96 97 98 99

  if (!done) {
    setTimeout(() => activateIfPossible(currentEl), 250);
  }
100 101
}

102 103 104 105 106 107 108 109 110 111
function getBrowserImageClasses(browserNavOpened: boolean): string {
  let classes = styles.browserStage;

  if (browserNavOpened === true) {
    classes += ` ${styles.shorter}`;
  }

  return classes;
}

112
const mapStateToProps = (state: RootState): StateProps => ({
113 114 115
  browserNavOpened: getBrowserNavOpened(state)
});

116 117 118
const mapDispatchToProps: DispatchProps = {
  updateBrowserNavStates,
  updateChrLocation
119 120 121 122 123 124
};

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(BrowserImage);