diff --git a/web/media/multimedia-modal.react.js b/web/media/multimedia-modal.react.js
index 90526241f..336389fd3 100644
--- a/web/media/multimedia-modal.react.js
+++ b/web/media/multimedia-modal.react.js
@@ -1,145 +1,145 @@
// @flow
import invariant from 'invariant';
import * as React from 'react';
import { fetchableMediaURI } from 'lib/media/media-utils.js';
import type {
EncryptedMediaType,
MediaType,
Dimensions,
} from 'lib/types/media-types.js';
import EncryptedMultimedia from './encrypted-multimedia.react.js';
import LoadableVideo from './loadable-video.react.js';
import { usePlaceholder } from './media-utils.js';
import FullScreenViewModal from '../modals/full-screen-view-modal.react.js';
type MediaInfo =
| {
+type: MediaType,
+uri: string,
+dimensions: ?Dimensions,
+thumbHash: ?string,
+thumbnailURI: ?string,
}
| {
+type: EncryptedMediaType,
+blobURI: string,
+encryptionKey: string,
+dimensions: ?Dimensions,
+thumbHash: ?string,
+thumbnailBlobURI: ?string,
+thumbnailEncryptionKey: ?string,
};
type Props = {
+media: MediaInfo,
};
function MultimediaModal(props: Props): React.Node {
const { media } = props;
const thumbHashEncryptionKey =
media.thumbnailEncryptionKey ?? media.encryptionKey;
const placeholderImage = usePlaceholder(
media.thumbHash,
thumbHashEncryptionKey,
);
const [dimensions, setDimensions] = React.useState(null);
const photo = React.useMemo(() => {
if (media.type !== 'photo') {
return null;
}
const uri = fetchableMediaURI(media.uri);
const style = {
backgroundImage: placeholderImage
? `url(${placeholderImage})`
: undefined,
};
return
;
}, [media.type, media.uri, placeholderImage]);
const video = React.useMemo(() => {
if (media.type !== 'video') {
return null;
}
const uri = fetchableMediaURI(media.uri);
const { thumbnailURI } = media;
invariant(thumbnailURI, 'video missing thumbnail');
return (
);
}, [media, placeholderImage]);
const encryptedMultimedia = React.useMemo(() => {
if (media.type !== 'encrypted_photo' && media.type !== 'encrypted_video') {
return null;
}
const {
type,
blobURI,
encryptionKey,
thumbnailBlobURI,
thumbnailEncryptionKey,
} = media;
const contentDimensions = dimensions ?? media.dimensions;
const elementStyle = contentDimensions
? {
width: `${contentDimensions.width}px`,
height: `${contentDimensions.height}px`,
}
: undefined;
return (
);
}, [dimensions, media, placeholderImage]);
const mediaModalItem = React.useMemo(() => {
if (media.type === 'photo') {
return photo;
} else if (media.type === 'video') {
return video;
} else {
return encryptedMultimedia;
}
}, [encryptedMultimedia, media.type, photo, video]);
const multimediaModal = React.useMemo(
() => (
{mediaModalItem}
),
[dimensions, mediaModalItem],
);
return multimediaModal;
}
export default MultimediaModal;
diff --git a/web/modals/full-screen-view-modal.react.js b/web/modals/full-screen-view-modal.react.js
index 0cf361dcf..024596f8a 100644
--- a/web/modals/full-screen-view-modal.react.js
+++ b/web/modals/full-screen-view-modal.react.js
@@ -1,116 +1,128 @@
// @flow
import invariant from 'invariant';
import * as React from 'react';
import { XCircle as XCircleIcon } from 'react-feather';
import { useModalContext } from 'lib/components/modal-provider.react.js';
import type { SetState } from 'lib/types/hook-types.js';
import type { Dimensions } from 'lib/types/media-types.js';
import css from './full-screen-view-modal.css';
type BaseProps = {
+children: React.Node,
- +contentDimensions: ?Dimensions,
- +setContentDimensions: SetState,
+ +dynamicContentDimensions?: ?Dimensions,
+ +setDynamicContentDimensions?: SetState,
};
type Props = {
...BaseProps,
+popModal: (modal: ?React.Node) => void,
};
class FullScreenViewModal extends React.PureComponent {
overlay: ?HTMLDivElement;
componentDidMount() {
invariant(this.overlay, 'overlay ref unset');
this.overlay.focus();
- this.calculateMediaDimensions();
- window.addEventListener('resize', this.calculateMediaDimensions);
+ this.calculateDynamicContentDimensions();
+ window.addEventListener('resize', this.calculateDynamicContentDimensions);
}
componentWillUnmount() {
- window.removeEventListener('resize', this.calculateMediaDimensions);
+ window.removeEventListener(
+ 'resize',
+ this.calculateDynamicContentDimensions,
+ );
}
render(): React.Node {
return (
);
}
overlayRef: (overlay: ?HTMLDivElement) => void = overlay => {
this.overlay = overlay;
};
onBackgroundClick: (event: SyntheticEvent) => void =
event => {
if (event.target === this.overlay) {
this.props.popModal();
}
};
onKeyDown: (event: SyntheticKeyboardEvent) => void =
event => {
if (event.key === 'Escape') {
this.props.popModal();
}
};
- calculateMediaDimensions: () => void = () => {
- if (!this.overlay || !this.props.contentDimensions) {
+ calculateDynamicContentDimensions: () => mixed = () => {
+ const { dynamicContentDimensions, setDynamicContentDimensions } =
+ this.props;
+
+ if (
+ !this.overlay ||
+ !dynamicContentDimensions ||
+ !setDynamicContentDimensions
+ ) {
return;
}
+
const containerWidth = this.overlay.clientWidth;
const containerHeight = this.overlay.clientHeight;
const containerAspectRatio = containerWidth / containerHeight;
- const { width: mediaWidth, height: mediaHeight } =
- this.props.contentDimensions;
- const mediaAspectRatio = mediaWidth / mediaHeight;
+ const { width: contentWidth, height: contentHeight } =
+ dynamicContentDimensions;
+ const contentAspectRatio = contentWidth / contentHeight;
let newWidth, newHeight;
- if (containerAspectRatio > mediaAspectRatio) {
- newWidth = Math.min(mediaWidth, containerHeight * mediaAspectRatio);
- newHeight = newWidth / mediaAspectRatio;
+ if (containerAspectRatio > contentAspectRatio) {
+ newWidth = Math.min(contentWidth, containerHeight * contentAspectRatio);
+ newHeight = newWidth / contentAspectRatio;
} else {
- newHeight = Math.min(mediaHeight, containerWidth / mediaAspectRatio);
- newWidth = newHeight * mediaAspectRatio;
+ newHeight = Math.min(contentHeight, containerWidth / contentAspectRatio);
+ newWidth = newHeight * contentAspectRatio;
}
- this.props.setContentDimensions({
+
+ setDynamicContentDimensions({
width: newWidth,
height: newHeight,
});
};
}
function ConnectedFullScreenViewModal(props: BaseProps): React.Node {
const modalContext = useModalContext();
const fullScreenViewModal = React.useMemo(
() => ,
[modalContext.popModal, props],
);
return fullScreenViewModal;
}
export default ConnectedFullScreenViewModal;