Skip to content
Snippets Groups Projects
Unverified Commit 2bfd6a18 authored by Justin Coyne's avatar Justin Coyne Committed by GitHub
Browse files

Merge pull request #3605 from ProjectMirador/react-full-screen

Update react-full-screen
parents 704aee69 5d2fda70
No related branches found
No related tags found
No related merge requests found
...@@ -13,24 +13,6 @@ describe('workspace actions', () => { ...@@ -13,24 +13,6 @@ describe('workspace actions', () => {
expect(actions.updateWorkspace(options)).toEqual(expectedAction); expect(actions.updateWorkspace(options)).toEqual(expectedAction);
}); });
}); });
describe('setWorkspaceFullscreen', () => {
it('should return correct action type if set to true', () => {
const receivedAction = actions.setWorkspaceFullscreen(true);
const expectedAction = {
isFullscreenEnabled: true,
type: ActionTypes.SET_WORKSPACE_FULLSCREEN,
};
expect(receivedAction).toEqual(expectedAction);
});
it('should return correct action type if set to false', () => {
const receivedAction = actions.setWorkspaceFullscreen(false);
const expectedAction = {
isFullscreenEnabled: false,
type: ActionTypes.SET_WORKSPACE_FULLSCREEN,
};
expect(receivedAction).toEqual(expectedAction);
});
});
describe('updateWorkspaceMosaicLayout', () => { describe('updateWorkspaceMosaicLayout', () => {
it('should updates mosaic layout', () => { it('should updates mosaic layout', () => {
const options = { foo: 'bar' }; const options = { foo: 'bar' };
......
import React from 'react'; import React from 'react';
import { shallow } from 'enzyme'; import { shallow } from 'enzyme';
import { ThemeProvider, StylesProvider } from '@material-ui/core/styles'; import { ThemeProvider, StylesProvider } from '@material-ui/core/styles';
import Fullscreen from 'react-full-screen';
import { DndContext, DndProvider } from 'react-dnd'; import { DndContext, DndProvider } from 'react-dnd';
import { AppProviders } from '../../../src/components/AppProviders'; import { AppProviders } from '../../../src/components/AppProviders';
import settings from '../../../src/config/settings'; import settings from '../../../src/config/settings';
...@@ -14,7 +13,6 @@ function createWrapper(props) { ...@@ -14,7 +13,6 @@ function createWrapper(props) {
<AppProviders <AppProviders
language="en" language="en"
isFullscreenEnabled={false} isFullscreenEnabled={false}
setWorkspaceFullscreen={() => {}}
theme={settings.theme} theme={settings.theme}
translations={{}} translations={{}}
t={k => k} t={k => k}
...@@ -28,7 +26,6 @@ describe('AppProviders', () => { ...@@ -28,7 +26,6 @@ describe('AppProviders', () => {
const wrapper = createWrapper(); const wrapper = createWrapper();
expect(wrapper.find(ThemeProvider).length).toBe(1); expect(wrapper.find(ThemeProvider).length).toBe(1);
expect(wrapper.find(StylesProvider).length).toBe(1); expect(wrapper.find(StylesProvider).length).toBe(1);
expect(wrapper.find(Fullscreen).length).toBe(1);
}); });
it('sets up a theme based on the config passed in merged w/ MaterialUI', () => { it('sets up a theme based on the config passed in merged w/ MaterialUI', () => {
...@@ -44,23 +41,6 @@ describe('AppProviders', () => { ...@@ -44,23 +41,6 @@ describe('AppProviders', () => {
expect(wrapper.instance().i18n.t('off')).toEqual('on'); expect(wrapper.instance().i18n.t('off')).toEqual('on');
}); });
it('should pass setWorkspaceFullscreen to Fullscreen.onChange', () => {
const mockFn = jest.fn();
const wrapper = createWrapper({ setWorkspaceFullscreen: mockFn });
expect(wrapper.find(Fullscreen).first().prop('onChange'))
.toBe(mockFn);
});
it('should pass isFullscreenEnabled to Fullscreen.enabled', () => {
let wrapper = createWrapper({ isFullscreenEnabled: false });
expect(wrapper.find(Fullscreen).first().prop('enabled'))
.toEqual(false);
wrapper = createWrapper({ isFullscreenEnabled: true });
expect(wrapper.find(Fullscreen).first().prop('enabled'))
.toEqual(true);
});
describe('componentDidUpdate()', () => { describe('componentDidUpdate()', () => {
it('changes the i18n language if the language prop has been updated', () => { it('changes the i18n language if the language prop has been updated', () => {
const wrapper = createWrapper(); const wrapper = createWrapper();
......
...@@ -4,18 +4,21 @@ import FullscreenIcon from '@material-ui/icons/FullscreenSharp'; ...@@ -4,18 +4,21 @@ import FullscreenIcon from '@material-ui/icons/FullscreenSharp';
import FullscreenExitIcon from '@material-ui/icons/FullscreenExitSharp'; import FullscreenExitIcon from '@material-ui/icons/FullscreenExitSharp';
import MiradorMenuButton from '../../../src/containers/MiradorMenuButton'; import MiradorMenuButton from '../../../src/containers/MiradorMenuButton';
import { FullScreenButton } from '../../../src/components/FullScreenButton'; import { FullScreenButton } from '../../../src/components/FullScreenButton';
import FullScreenContext from '../../../src/contexts/FullScreenContext';
/** */ /** */
function createWrapper(props) { function createWrapper(props, contextProps = { active: false }) {
return shallow( return shallow(
<FullScreenButton <FullScreenButton
classes={{}} classes={{}}
className="xyz" className="xyz"
setWorkspaceFullscreen={() => {}}
isFullscreenEnabled={false}
{...props} {...props}
/>, />,
); {
wrappingComponent: FullScreenContext.Provider,
wrappingComponentProps: { value: { enter: () => { }, exit: () => { }, ...contextProps } },
},
).dive();
} }
describe('FullScreenButton', () => { describe('FullScreenButton', () => {
...@@ -30,10 +33,10 @@ describe('FullScreenButton', () => { ...@@ -30,10 +33,10 @@ describe('FullScreenButton', () => {
}); });
describe('when not in fullscreen', () => { describe('when not in fullscreen', () => {
let setWorkspaceFullscreen; let enter;
beforeAll(() => { beforeAll(() => {
setWorkspaceFullscreen = jest.fn(); enter = jest.fn();
wrapper = createWrapper({ setWorkspaceFullscreen }); wrapper = createWrapper({}, { enter });
menuButton = wrapper.find(MiradorMenuButton); menuButton = wrapper.find(MiradorMenuButton);
}); });
...@@ -45,17 +48,17 @@ describe('FullScreenButton', () => { ...@@ -45,17 +48,17 @@ describe('FullScreenButton', () => {
expect(menuButton.props()['aria-label']).toEqual('workspaceFullScreen'); expect(menuButton.props()['aria-label']).toEqual('workspaceFullScreen');
}); });
it('triggers the setWorkspaceFullscreen prop with the appropriate boolean', () => { it('triggers the handle enter with the appropriate boolean', () => {
menuButton.props().onClick(); // Trigger the onClick prop menuButton.props().onClick(); // Trigger the onClick prop
expect(setWorkspaceFullscreen).toHaveBeenCalledWith(true); expect(enter).toHaveBeenCalled();
}); });
}); });
describe('when in fullscreen', () => { describe('when in fullscreen', () => {
let setWorkspaceFullscreen; let exit;
beforeAll(() => { beforeAll(() => {
setWorkspaceFullscreen = jest.fn(); exit = jest.fn();
wrapper = createWrapper({ isFullscreenEnabled: true, setWorkspaceFullscreen }); wrapper = createWrapper({}, { active: true, exit });
menuButton = wrapper.find(MiradorMenuButton); menuButton = wrapper.find(MiradorMenuButton);
}); });
...@@ -67,9 +70,9 @@ describe('FullScreenButton', () => { ...@@ -67,9 +70,9 @@ describe('FullScreenButton', () => {
expect(menuButton.props()['aria-label']).toEqual('exitFullScreen'); expect(menuButton.props()['aria-label']).toEqual('exitFullScreen');
}); });
it('triggers the setWorkspaceFullscreen prop with the appropriate boolean', () => { it('triggers the handle exit with the appropriate boolean', () => {
menuButton.props().onClick(); // Trigger the onClick prop menuButton.props().onClick(); // Trigger the onClick prop
expect(setWorkspaceFullscreen).toHaveBeenCalledWith(false); expect(exit).toHaveBeenCalled();
}); });
}); });
}); });
import React, { Component } from 'react'; import React, { Component } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import Fullscreen from 'react-full-screen'; import { FullScreen, useFullScreenHandle } from 'react-full-screen';
import { I18nextProvider } from 'react-i18next'; import { I18nextProvider } from 'react-i18next';
import { LiveAnnouncer } from 'react-aria-live'; import { LiveAnnouncer } from 'react-aria-live';
import { import {
...@@ -12,6 +12,7 @@ import HTML5toTouch from 'react-dnd-multi-backend/dist/cjs/HTML5toTouch'; ...@@ -12,6 +12,7 @@ import HTML5toTouch from 'react-dnd-multi-backend/dist/cjs/HTML5toTouch';
import { create } from 'jss'; import { create } from 'jss';
import rtl from 'jss-rtl'; import rtl from 'jss-rtl';
import createI18nInstance from '../i18n'; import createI18nInstance from '../i18n';
import FullScreenContext from '../contexts/FullScreenContext';
/** /**
* Allow applications to opt-out of (or provide their own) drag and drop context * Allow applications to opt-out of (or provide their own) drag and drop context
...@@ -46,6 +47,25 @@ MaybeDndProvider.propTypes = { ...@@ -46,6 +47,25 @@ MaybeDndProvider.propTypes = {
]).isRequired, ]).isRequired,
}; };
/**
* Shim to inject the full screen handle into a context
*/
const FullScreenShim = ({ children }) => {
const handle = useFullScreenHandle();
return (
<FullScreen handle={handle}>
<FullScreenContext.Provider value={handle}>
{children}
</FullScreenContext.Provider>
</FullScreen>
);
};
FullScreenShim.propTypes = {
children: PropTypes.node.isRequired,
};
/** /**
* This component adds viewer-specific providers. * This component adds viewer-specific providers.
* @prop {Object} manifests * @prop {Object} manifests
...@@ -81,8 +101,8 @@ export class AppProviders extends Component { ...@@ -81,8 +101,8 @@ export class AppProviders extends Component {
/** */ /** */
render() { render() {
const { const {
children, createGenerateClassNameOptions, isFullscreenEnabled, children, createGenerateClassNameOptions,
setWorkspaceFullscreen, theme, translations, theme, translations,
dndManager, dndManager,
} = this.props; } = this.props;
...@@ -93,10 +113,7 @@ export class AppProviders extends Component { ...@@ -93,10 +113,7 @@ export class AppProviders extends Component {
}); });
return ( return (
<Fullscreen <FullScreenShim>
enabled={isFullscreenEnabled}
onChange={setWorkspaceFullscreen}
>
<I18nextProvider i18n={this.i18n}> <I18nextProvider i18n={this.i18n}>
<LiveAnnouncer> <LiveAnnouncer>
<ThemeProvider <ThemeProvider
...@@ -113,7 +130,7 @@ export class AppProviders extends Component { ...@@ -113,7 +130,7 @@ export class AppProviders extends Component {
</ThemeProvider> </ThemeProvider>
</LiveAnnouncer> </LiveAnnouncer>
</I18nextProvider> </I18nextProvider>
</Fullscreen> </FullScreenShim>
); );
} }
} }
...@@ -122,9 +139,7 @@ AppProviders.propTypes = { ...@@ -122,9 +139,7 @@ AppProviders.propTypes = {
children: PropTypes.node, children: PropTypes.node,
createGenerateClassNameOptions: PropTypes.object, // eslint-disable-line react/forbid-prop-types createGenerateClassNameOptions: PropTypes.object, // eslint-disable-line react/forbid-prop-types
dndManager: PropTypes.object, // eslint-disable-line react/forbid-prop-types dndManager: PropTypes.object, // eslint-disable-line react/forbid-prop-types
isFullscreenEnabled: PropTypes.bool,
language: PropTypes.string.isRequired, language: PropTypes.string.isRequired,
setWorkspaceFullscreen: PropTypes.func.isRequired,
theme: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types theme: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
translations: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types translations: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
}; };
...@@ -133,5 +148,4 @@ AppProviders.defaultProps = { ...@@ -133,5 +148,4 @@ AppProviders.defaultProps = {
children: null, children: null,
createGenerateClassNameOptions: {}, createGenerateClassNameOptions: {},
dndManager: undefined, dndManager: undefined,
isFullscreenEnabled: false,
}; };
...@@ -3,6 +3,8 @@ import FullscreenIcon from '@material-ui/icons/FullscreenSharp'; ...@@ -3,6 +3,8 @@ import FullscreenIcon from '@material-ui/icons/FullscreenSharp';
import FullscreenExitIcon from '@material-ui/icons/FullscreenExitSharp'; import FullscreenExitIcon from '@material-ui/icons/FullscreenExitSharp';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import MiradorMenuButton from '../containers/MiradorMenuButton'; import MiradorMenuButton from '../containers/MiradorMenuButton';
import FullScreenContext from '../contexts/FullScreenContext';
/** /**
*/ */
export class FullScreenButton extends Component { export class FullScreenButton extends Component {
...@@ -12,29 +14,30 @@ export class FullScreenButton extends Component { ...@@ -12,29 +14,30 @@ export class FullScreenButton extends Component {
*/ */
render() { render() {
const { const {
className, isFullscreenEnabled, setWorkspaceFullscreen, t, className, t,
} = this.props; } = this.props;
return ( return (
<FullScreenContext.Consumer>
{ handle => (
<MiradorMenuButton <MiradorMenuButton
className={className} className={className}
aria-label={isFullscreenEnabled ? t('exitFullScreen') : t('workspaceFullScreen')} aria-label={handle.active ? t('exitFullScreen') : t('workspaceFullScreen')}
onClick={() => setWorkspaceFullscreen(!isFullscreenEnabled)} onClick={handle.active ? handle.exit : handle.enter}
> >
{isFullscreenEnabled ? <FullscreenExitIcon /> : <FullscreenIcon />} {handle.active ? <FullscreenExitIcon /> : <FullscreenIcon />}
</MiradorMenuButton> </MiradorMenuButton>
)}
</FullScreenContext.Consumer>
); );
} }
} }
FullScreenButton.propTypes = { FullScreenButton.propTypes = {
className: PropTypes.string, className: PropTypes.string,
isFullscreenEnabled: PropTypes.bool,
setWorkspaceFullscreen: PropTypes.func.isRequired,
t: PropTypes.func, t: PropTypes.func,
}; };
FullScreenButton.defaultProps = { FullScreenButton.defaultProps = {
className: undefined, className: undefined,
isFullscreenEnabled: false,
t: key => key, t: key => key,
}; };
import { compose } from 'redux'; import { compose } from 'redux';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { withPlugins } from '../extend/withPlugins'; import { withPlugins } from '../extend/withPlugins';
import * as actions from '../state/actions'; import { getConfig, getTheme } from '../state/selectors';
import { getConfig, getTheme, getFullScreenEnabled } from '../state/selectors';
import { AppProviders } from '../components/AppProviders'; import { AppProviders } from '../components/AppProviders';
/** /**
...@@ -13,24 +12,14 @@ import { AppProviders } from '../components/AppProviders'; ...@@ -13,24 +12,14 @@ import { AppProviders } from '../components/AppProviders';
const mapStateToProps = state => ( const mapStateToProps = state => (
{ {
createGenerateClassNameOptions: getConfig(state).createGenerateClassNameOptions, createGenerateClassNameOptions: getConfig(state).createGenerateClassNameOptions,
isFullscreenEnabled: getFullScreenEnabled(state),
language: getConfig(state).language, language: getConfig(state).language,
theme: getTheme(state), theme: getTheme(state),
translations: getConfig(state).translations, translations: getConfig(state).translations,
} }
); );
/**
* mapDispatchToProps - used to hook up connect to action creators
* @memberof App
* @private
*/
const mapDispatchToProps = {
setWorkspaceFullscreen: actions.setWorkspaceFullscreen,
};
const enhance = compose( const enhance = compose(
connect(mapStateToProps, mapDispatchToProps), connect(mapStateToProps),
withPlugins('AppProviders'), withPlugins('AppProviders'),
); );
......
...@@ -2,8 +2,6 @@ import { connect } from 'react-redux'; ...@@ -2,8 +2,6 @@ import { connect } from 'react-redux';
import { compose } from 'redux'; import { compose } from 'redux';
import { withTranslation } from 'react-i18next'; import { withTranslation } from 'react-i18next';
import { withPlugins } from '../extend/withPlugins'; import { withPlugins } from '../extend/withPlugins';
import * as actions from '../state/actions';
import { getFullScreenEnabled } from '../state/selectors';
import { FullScreenButton } from '../components/FullScreenButton'; import { FullScreenButton } from '../components/FullScreenButton';
/** /**
...@@ -11,16 +9,14 @@ import { FullScreenButton } from '../components/FullScreenButton'; ...@@ -11,16 +9,14 @@ import { FullScreenButton } from '../components/FullScreenButton';
* @memberof FullScreenButton * @memberof FullScreenButton
* @private * @private
*/ */
const mapStateToProps = state => ({ const mapStateToProps = _state => ({});
isFullscreenEnabled: getFullScreenEnabled(state),
});
/** /**
* mapDispatchToProps - used to hook up connect to action creators * mapDispatchToProps - used to hook up connect to action creators
* @memberof ManifestListItem * @memberof ManifestListItem
* @private * @private
*/ */
const mapDispatchToProps = { setWorkspaceFullscreen: actions.setWorkspaceFullscreen }; const mapDispatchToProps = {};
const enhance = compose( const enhance = compose(
withTranslation(), withTranslation(),
......
import { createContext } from 'react';
const FullScreenContext = createContext();
export default FullScreenContext;
...@@ -9,16 +9,6 @@ export function updateWorkspace(config) { ...@@ -9,16 +9,6 @@ export function updateWorkspace(config) {
return { config, type: ActionTypes.UPDATE_WORKSPACE }; return { config, type: ActionTypes.UPDATE_WORKSPACE };
} }
/**
* setWorkspaceFullscreen - action creator
*
* @param {Boolean} isFullscreenEnabled
* @memberof ActionCreators
*/
export function setWorkspaceFullscreen(isFullscreenEnabled) {
return { isFullscreenEnabled, type: ActionTypes.SET_WORKSPACE_FULLSCREEN };
}
/** /**
* toggleZoomControls - action creator * toggleZoomControls - action creator
* @param {Boolean} showZoomControls * @param {Boolean} showZoomControls
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment