Skip to content

Commit

Permalink
Merge branch 'master-upstream'
Browse files Browse the repository at this point in the history
# Conflicts:
#	src/components/AnnotationSettings.js
#	src/components/CanvasAnnotations.js
#	src/components/VideoViewer.js
#	src/components/ViewerNavigation.js
#	src/components/WindowSideBarAnnotationsPanel.js
#	src/containers/CompanionWindow.js
  • Loading branch information
geourjoa committed Nov 22, 2024
2 parents 54d2c19 + c1fa0cc commit f78d904
Show file tree
Hide file tree
Showing 87 changed files with 3,483 additions and 4,988 deletions.
7 changes: 4 additions & 3 deletions __tests__/src/extend/withSize.test.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { forwardRef } from 'react';
import { render, screen } from '@testing-library/react';
import PropTypes from 'prop-types';
import { withSize } from '../../../src/extend/withSize';
Expand Down Expand Up @@ -25,12 +26,12 @@ class ResizeObserver {
global.ResizeObserver = ResizeObserver;

/** */
const TestComponent = ({ size }) => (
<div>
const TestComponent = forwardRef(({ size }, ref) => (
<div ref={ref}>
{size.width}
{size.height}
</div>
);
));

TestComponent.propTypes = {
size: PropTypes.shape({
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
"react-dnd-html5-backend": "^16.0.0",
"react-dnd-multi-backend": "^8.0.0",
"react-dnd-touch-backend": "^16.0.0",
"react-error-boundary": "^4.1.2",
"react-full-screen": "^1.1.1",
"react-i18next": "^13.0.0 || ^14.0.0 || ^15.0.0",
"react-image": "^4.0.1",
Expand Down
49 changes: 16 additions & 33 deletions src/components/AccessTokenSender.js
Original file line number Diff line number Diff line change
@@ -1,48 +1,31 @@
import { Component } from 'react';
import { useCallback } from 'react';
import PropTypes from 'prop-types';
import { IIIFIFrameCommunication } from './IIIFIFrameCommunication';

/**
* Opens a new window for click
*/
export class AccessTokenSender extends Component {
/** */
constructor(props) {
super(props);

this.onReceiveAccessTokenMessage = this.onReceiveAccessTokenMessage.bind(this);
}

/** @private */
onReceiveAccessTokenMessage(e) {
const { handleAccessTokenMessage, url } = this.props;
export function AccessTokenSender({ handleAccessTokenMessage, url = undefined }) {
const onReceiveAccessTokenMessage = useCallback((e) => {
if (e.data && e.data.messageId && e.data.messageId === url) handleAccessTokenMessage(e.data);
}
}, [handleAccessTokenMessage, url]);

/** */
render() {
const { url } = this.props;
if (!url) return null;
if (!url) return null;

/**
login, clickthrough/kiosk open @id, wait for close
external, no-op
*/
return (
<IIIFIFrameCommunication
src={`${url}?origin=${window.origin}&messageId=${url}`}
title="AccessTokenSender"
handleReceiveMessage={this.onReceiveAccessTokenMessage}
/>
);
}
/**
login, clickthrough/kiosk open @id, wait for close
external, no-op
*/
return (
<IIIFIFrameCommunication
src={`${url}?origin=${window.origin}&messageId=${url}`}
title="AccessTokenSender"
handleReceiveMessage={onReceiveAccessTokenMessage}
/>
);
}

AccessTokenSender.propTypes = {
handleAccessTokenMessage: PropTypes.func.isRequired,
url: PropTypes.string,
};

AccessTokenSender.defaultProps = {
url: undefined,
};
52 changes: 25 additions & 27 deletions src/components/AnnotationSettings.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { Component } from 'react';
import PropTypes from 'prop-types';
import VisibilityIcon from '@mui/icons-material/VisibilitySharp';
import VisibilityOffIcon from '@mui/icons-material/VisibilityOffSharp';
Expand All @@ -11,29 +10,29 @@ import { VideosReferences } from '../plugins/VideosReferences';
* AnnotationSettings is a component to handle various annotation
* display settings in the Annotation companion window
*/
export class AnnotationSettings extends Component {
/**
* Returns the rendered component
*/
render() {
const {
windowId, autoScroll, autoScrollDisabled,
displayAll, displayAllDisabled, t, toggleAnnotationAutoScroll, toggleAnnotationDisplay,
} = this.props;
export function AnnotationSettings({
autoScroll,
autoScrollDisabled,
displayAll,
displayAllDisabled,
t,
toggleAnnotationDisplay,
toggleAnnotationAutoScroll,
windowId,
}) {
const mediaIsVideo = typeof VideosReferences.get(windowId) !== 'undefined';

const mediaIsVideo = typeof VideosReferences.get(windowId) !== 'undefined';

return (
<>
<MiradorMenuButton
aria-label={t(displayAll ? 'displayNoAnnotations' : 'highlightAllAnnotations')}
onClick={toggleAnnotationDisplay}
disabled={displayAllDisabled}
size="small"
>
{ displayAll ? <VisibilityIcon /> : <VisibilityOffIcon /> }
</MiradorMenuButton>
{ mediaIsVideo && (
return (
<>
<MiradorMenuButton
aria-label={t(displayAll ? 'displayNoAnnotations' : 'highlightAllAnnotations')}
onClick={toggleAnnotationDisplay}
disabled={displayAllDisabled}
size="small"
>
{ displayAll ? <VisibilityIcon /> : <VisibilityOffIcon /> }
</MiradorMenuButton>
{ mediaIsVideo && (
<MiradorMenuButton
aria-label={autoScroll ? 'Disable auto scroll' : 'Enable auto scroll'}
onClick={toggleAnnotationAutoScroll}
Expand All @@ -42,10 +41,9 @@ export class AnnotationSettings extends Component {
>
{ autoScroll ? <SyncIcon /> : <SyncDisabledIcon /> }
</MiradorMenuButton>
)}
</>
);
}
)}
</>
);
}

AnnotationSettings.defaultProps = {
Expand Down
52 changes: 17 additions & 35 deletions src/components/App.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {
createRef, Component, lazy, Suspense,
createRef, lazy, Suspense,
} from 'react';
import PropTypes from 'prop-types';
import PluginProvider from '../extend/PluginProvider';
Expand All @@ -12,45 +12,27 @@ const WorkspaceArea = lazy(() => import('../containers/WorkspaceArea'));
* This is the top level Mirador component.
* @prop {Object} manifests
*/
export class App extends Component {
/** */
constructor(props) {
super(props);

this.areaRef = createRef();
}

/**
* render
* @return {String} - HTML markup for the component
*/
render() {
const { dndManager, plugins } = this.props;

return (
<PluginProvider plugins={plugins}>
<AppProviders dndManager={dndManager}>
<WorkspaceContext.Provider value={this.areaRef}>
<Suspense
fallback={<div />}
>
<WorkspaceArea areaRef={this.areaRef} />
</Suspense>
</WorkspaceContext.Provider>
</AppProviders>
</PluginProvider>
);
}
export function App({ dndManager = undefined, plugins = [] }) {
const areaRef = createRef();

return (
<PluginProvider plugins={plugins}>
<AppProviders dndManager={dndManager}>
<WorkspaceContext.Provider value={areaRef}>
<Suspense
fallback={<div />}
>
<WorkspaceArea areaRef={areaRef} />
</Suspense>
</WorkspaceContext.Provider>
</AppProviders>
</PluginProvider>
);
}

App.propTypes = {
dndManager: PropTypes.object, // eslint-disable-line react/forbid-prop-types
plugins: PropTypes.array, // eslint-disable-line react/forbid-prop-types
};

App.defaultProps = {
dndManager: undefined,
plugins: [],
};

export default App;
123 changes: 58 additions & 65 deletions src/components/AppProviders.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component } from 'react';
import { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import { FullScreen, useFullScreenHandle } from 'react-full-screen';
import { I18nextProvider } from 'react-i18next';
Expand Down Expand Up @@ -68,72 +68,70 @@ FullScreenShim.propTypes = {
};

/**
* This component adds viewer-specific providers.
* @prop {Object} manifests
* Hook up the I18next provider to the configuration in redux to allow
* plugins + config to inject additional translations.
*/
export class AppProviders extends Component {
/** */
constructor(props) {
super(props);

this.i18n = createI18nInstance();
// Set i18n language
this.i18n.changeLanguage(props.language);
}
const StoreAwareI18nextProvider = ({ children, language, translations }) => {
const [i18n] = useState(createI18nInstance());
useEffect(() => {
i18n.changeLanguage(language);
}, [i18n, language]);

/**
* Update the i18n language if it is changed
*/
componentDidUpdate(prevProps) {
const { language } = this.props;
if (prevProps.language !== language) {
this.i18n.changeLanguage(language);
}
}
useEffect(() => {
Object.keys(translations).forEach((lng) => {
i18n.addResourceBundle(lng, 'translation', translations[lng], true, true);
});
}, [i18n, translations]);

/** */
render() {
const {
children,
theme, translations,
dndManager,
} = this.props;
return (<I18nextProvider i18n={i18n}>{children}</I18nextProvider>);
};

/**
* Create rtl emotion cache
*/
const cacheRtl = createCache({
key: 'muirtl',
stylisPlugins: [prefixer, rtlPlugin],
});
StoreAwareI18nextProvider.propTypes = {
children: PropTypes.node.isRequired,
language: PropTypes.string.isRequired,
translations: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
};

/**
* Create default emotion cache
*/
const cacheDefault = createCache({
key: 'mui',
});
/**
* Create rtl emotion cache
*/
const cacheRtl = createCache({
key: 'muirtl',
stylisPlugins: [prefixer, rtlPlugin],
});

Object.keys(translations).forEach((lng) => {
this.i18n.addResourceBundle(lng, 'translation', translations[lng], true, true);
});
/**
* Create default emotion cache
*/
const cacheDefault = createCache({
key: 'mui',
});

return (
<FullScreenShim>
<I18nextProvider i18n={this.i18n}>
<StyledEngineProvider injectFirst>
<CacheProvider value={theme.direction === 'rtl' ? cacheRtl : cacheDefault}>
<ThemeProvider theme={createTheme((theme))}>
<MaybeDndProvider dndManager={dndManager}>
{children}
</MaybeDndProvider>
</ThemeProvider>
</CacheProvider>
</StyledEngineProvider>
</I18nextProvider>
</FullScreenShim>
);
}
/**
* This component adds viewer-specific providers.
* @prop {Object} manifests
*/
export function AppProviders({
children = null,
language,
theme, translations,
dndManager = undefined,
}) {
return (
<FullScreenShim>
<StoreAwareI18nextProvider language={language} translations={translations}>
<StyledEngineProvider injectFirst>
<CacheProvider value={theme.direction === 'rtl' ? cacheRtl : cacheDefault}>
<ThemeProvider theme={createTheme((theme))}>
<MaybeDndProvider dndManager={dndManager}>
{children}
</MaybeDndProvider>
</ThemeProvider>
</CacheProvider>
</StyledEngineProvider>
</StoreAwareI18nextProvider>
</FullScreenShim>
);
}

AppProviders.propTypes = {
Expand All @@ -143,8 +141,3 @@ AppProviders.propTypes = {
theme: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
translations: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
};

AppProviders.defaultProps = {
children: null,
dndManager: undefined,
};
Loading

0 comments on commit f78d904

Please sign in to comment.