Message / Video, Web Page: Fix media overflow

This commit is contained in:
Alexander Zinchuk 2022-11-27 19:17:05 +01:00
parent 2d77f5ecf1
commit 73f112ced9
8 changed files with 65 additions and 64 deletions

View File

@ -60,11 +60,11 @@ function getMaxMessageWidthRem(fromOwnMessage: boolean, noAvatars?: boolean) {
export function getAvailableWidth( export function getAvailableWidth(
fromOwnMessage: boolean, fromOwnMessage: boolean,
isForwarded?: boolean, asForwarded?: boolean,
isWebPagePhoto?: boolean, isWebPageMedia?: boolean,
noAvatars?: boolean, noAvatars?: boolean,
) { ) {
const extraPaddingRem = isForwarded || isWebPagePhoto ? 1.625 : 0; const extraPaddingRem = asForwarded && isWebPageMedia ? 2.25 : (asForwarded || isWebPageMedia ? 1.625 : 0);
const availableWidthRem = getMaxMessageWidthRem(fromOwnMessage, noAvatars) - extraPaddingRem; const availableWidthRem = getMaxMessageWidthRem(fromOwnMessage, noAvatars) - extraPaddingRem;
return availableWidthRem * REM; return availableWidthRem * REM;
@ -85,21 +85,21 @@ export function calculateDimensionsForMessageMedia({
width, width,
height, height,
fromOwnMessage, fromOwnMessage,
isForwarded, asForwarded,
isWebPagePhoto, isWebPageMedia,
isGif, isGif,
noAvatars, noAvatars,
}: { }: {
width: number; width: number;
height: number; height: number;
fromOwnMessage: boolean; fromOwnMessage: boolean;
isForwarded?: boolean; asForwarded?: boolean;
isWebPagePhoto?: boolean; isWebPageMedia?: boolean;
isGif?: boolean; isGif?: boolean;
noAvatars?: boolean; noAvatars?: boolean;
}): ApiDimensions { }): ApiDimensions {
const aspectRatio = height / width; const aspectRatio = height / width;
const availableWidth = getAvailableWidth(fromOwnMessage, isForwarded, isWebPagePhoto, noAvatars); const availableWidth = getAvailableWidth(fromOwnMessage, asForwarded, isWebPageMedia, noAvatars);
const availableHeight = getAvailableHeight(isGif, aspectRatio); const availableHeight = getAvailableHeight(isGif, aspectRatio);
const mediaWidth = isGif ? Math.max(GIF_MIN_WIDTH, width) : width; const mediaWidth = isGif ? Math.max(GIF_MIN_WIDTH, width) : width;
const mediaHeight = isGif ? height * (mediaWidth / width) : height; const mediaHeight = isGif ? height * (mediaWidth / width) : height;
@ -123,8 +123,8 @@ export function getMediaViewerAvailableDimensions(withFooter: boolean, isVideo:
export function calculateInlineImageDimensions( export function calculateInlineImageDimensions(
photo: ApiPhoto, photo: ApiPhoto,
fromOwnMessage: boolean, fromOwnMessage: boolean,
isForwarded?: boolean, asForwarded?: boolean,
isWebPagePhoto?: boolean, isWebPageMedia?: boolean,
noAvatars?: boolean, noAvatars?: boolean,
) { ) {
const { width, height } = getPhotoInlineDimensions(photo) || DEFAULT_MEDIA_DIMENSIONS; const { width, height } = getPhotoInlineDimensions(photo) || DEFAULT_MEDIA_DIMENSIONS;
@ -133,8 +133,8 @@ export function calculateInlineImageDimensions(
width, width,
height, height,
fromOwnMessage, fromOwnMessage,
isForwarded, asForwarded,
isWebPagePhoto, isWebPageMedia,
noAvatars, noAvatars,
}); });
} }
@ -142,7 +142,8 @@ export function calculateInlineImageDimensions(
export function calculateVideoDimensions( export function calculateVideoDimensions(
video: ApiVideo, video: ApiVideo,
fromOwnMessage: boolean, fromOwnMessage: boolean,
isForwarded?: boolean, asForwarded?: boolean,
isWebPageMedia?: boolean,
noAvatars?: boolean, noAvatars?: boolean,
) { ) {
const { width, height } = getVideoDimensions(video) || DEFAULT_MEDIA_DIMENSIONS; const { width, height } = getVideoDimensions(video) || DEFAULT_MEDIA_DIMENSIONS;
@ -151,7 +152,8 @@ export function calculateVideoDimensions(
width, width,
height, height,
fromOwnMessage, fromOwnMessage,
isForwarded, asForwarded,
isWebPageMedia,
isGif: video.isGif, isGif: video.isGif,
noAvatars, noAvatars,
}); });

View File

@ -585,12 +585,12 @@ const Message: FC<OwnProps & StateProps> = ({
if (!isAlbum && (photo || video || invoice?.extendedMedia)) { if (!isAlbum && (photo || video || invoice?.extendedMedia)) {
let width: number | undefined; let width: number | undefined;
if (photo) { if (photo) {
width = calculateMediaDimensions(message, noAvatars).width; width = calculateMediaDimensions(message, asForwarded, noAvatars).width;
} else if (video) { } else if (video) {
if (video.isRound) { if (video.isRound) {
width = ROUND_VIDEO_DIMENSIONS_PX; width = ROUND_VIDEO_DIMENSIONS_PX;
} else { } else {
width = calculateMediaDimensions(message, noAvatars).width; width = calculateMediaDimensions(message, asForwarded, noAvatars).width;
} }
} else if (invoice?.extendedMedia && ( } else if (invoice?.extendedMedia && (
invoice.extendedMedia.width && invoice.extendedMedia.height invoice.extendedMedia.width && invoice.extendedMedia.height
@ -600,7 +600,7 @@ const Message: FC<OwnProps & StateProps> = ({
width: previewWidth, width: previewWidth,
height: previewHeight, height: previewHeight,
fromOwnMessage: isOwn, fromOwnMessage: isOwn,
isForwarded: isForwarding, asForwarded,
noAvatars, noAvatars,
}).width; }).width;
} }
@ -776,11 +776,12 @@ const Message: FC<OwnProps & StateProps> = ({
canAutoLoad={canAutoLoadMedia} canAutoLoad={canAutoLoadMedia}
uploadProgress={uploadProgress} uploadProgress={uploadProgress}
shouldAffectAppendix={hasCustomAppendix} shouldAffectAppendix={hasCustomAppendix}
onClick={handleMediaClick}
onCancelUpload={handleCancelUpload}
isDownloading={isDownloading} isDownloading={isDownloading}
isProtected={isProtected} isProtected={isProtected}
asForwarded={asForwarded}
theme={theme} theme={theme}
onClick={handleMediaClick}
onCancelUpload={handleCancelUpload}
/> />
)} )}
{!isAlbum && video && video.isRound && ( {!isAlbum && video && video.isRound && (
@ -802,10 +803,11 @@ const Message: FC<OwnProps & StateProps> = ({
canAutoPlay={canAutoPlayMedia} canAutoPlay={canAutoPlayMedia}
uploadProgress={uploadProgress} uploadProgress={uploadProgress}
lastSyncTime={lastSyncTime} lastSyncTime={lastSyncTime}
onClick={handleMediaClick}
onCancelUpload={handleCancelUpload}
isDownloading={isDownloading} isDownloading={isDownloading}
isProtected={isProtected} isProtected={isProtected}
asForwarded={asForwarded}
onClick={handleMediaClick}
onCancelUpload={handleCancelUpload}
/> />
)} )}
{(audio || voice) && ( {(audio || voice) && (
@ -901,12 +903,13 @@ const Message: FC<OwnProps & StateProps> = ({
noAvatars={noAvatars} noAvatars={noAvatars}
canAutoLoad={canAutoLoadMedia} canAutoLoad={canAutoLoadMedia}
canAutoPlay={canAutoPlayMedia} canAutoPlay={canAutoPlayMedia}
asForwarded={asForwarded}
lastSyncTime={lastSyncTime} lastSyncTime={lastSyncTime}
onMediaClick={handleMediaClick}
onCancelMediaTransfer={handleCancelUpload}
isDownloading={isDownloading} isDownloading={isDownloading}
isProtected={isProtected} isProtected={isProtected}
theme={theme} theme={theme}
onMediaClick={handleMediaClick}
onCancelMediaTransfer={handleCancelUpload}
/> />
)} )}
{invoice && !invoice.extendedMedia && ( {invoice && !invoice.extendedMedia && (

View File

@ -43,10 +43,10 @@ export type OwnProps = {
size?: 'inline' | 'pictogram'; size?: 'inline' | 'pictogram';
shouldAffectAppendix?: boolean; shouldAffectAppendix?: boolean;
dimensions?: IMediaDimensions & { isSmall?: boolean }; dimensions?: IMediaDimensions & { isSmall?: boolean };
asForwarded?: boolean;
nonInteractive?: boolean; nonInteractive?: boolean;
isDownloading: boolean; isDownloading: boolean;
isProtected?: boolean; isProtected?: boolean;
withAspectRatio?: boolean;
theme: ISettings['theme']; theme: ISettings['theme'];
onClick?: (id: number) => void; onClick?: (id: number) => void;
onCancelUpload?: (message: ApiMessage) => void; onCancelUpload?: (message: ApiMessage) => void;
@ -63,11 +63,11 @@ const Photo: FC<OwnProps> = ({
uploadProgress, uploadProgress,
size = 'inline', size = 'inline',
dimensions, dimensions,
asForwarded,
nonInteractive, nonInteractive,
shouldAffectAppendix, shouldAffectAppendix,
isDownloading, isDownloading,
isProtected, isProtected,
withAspectRatio,
theme, theme,
onClick, onClick,
onCancelUpload, onCancelUpload,
@ -148,7 +148,7 @@ const Photo: FC<OwnProps> = ({
} }
}, [shouldAffectAppendix, fullMediaData, isOwn, isInSelectMode, isSelected, theme] as const); }, [shouldAffectAppendix, fullMediaData, isOwn, isInSelectMode, isSelected, theme] as const);
const { width, height, isSmall } = dimensions || calculateMediaDimensions(message, noAvatars); const { width, height, isSmall } = dimensions || calculateMediaDimensions(message, asForwarded, noAvatars);
const className = buildClassName( const className = buildClassName(
'media-inner', 'media-inner',
@ -157,10 +157,8 @@ const Photo: FC<OwnProps> = ({
width === height && 'square-image', width === height && 'square-image',
); );
const aspectRatio = withAspectRatio ? `aspect-ratio: ${(width / height).toFixed(3)}/ 1` : ''; const dimensionsStyle = dimensions ? ` width: ${width}px; left: ${dimensions.x}px; top: ${dimensions.y}px;` : '';
const style = dimensions const style = size === 'inline' ? `height: ${height}px;${dimensionsStyle}` : undefined;
? `width: ${width}px; height: ${height}px; left: ${dimensions.x}px; top: ${dimensions.y}px;${aspectRatio}`
: '';
return ( return (
<div <div
@ -173,17 +171,11 @@ const Photo: FC<OwnProps> = ({
<img <img
src={fullMediaData} src={fullMediaData}
className="full-media" className="full-media"
width={width}
height={height}
alt="" alt=""
draggable={!isProtected} draggable={!isProtected}
/> />
{withThumb && ( {withThumb && (
<canvas <canvas ref={thumbRef} className={buildClassName('thumbnail', thumbClassNames)} />
ref={thumbRef}
className={buildClassName('thumbnail', thumbClassNames)}
style={`width: ${width}px; height: ${height}px;${aspectRatio}`}
/>
)} )}
{isProtected && <span className="protector" />} {isProtected && <span className="protector" />}
{shouldRenderSpinner && !shouldRenderDownloadButton && ( {shouldRenderSpinner && !shouldRenderDownloadButton && (

View File

@ -11,10 +11,10 @@ import { calculateVideoDimensions } from '../../common/helpers/mediaDimensions';
import { import {
getMediaTransferState, getMediaTransferState,
getMessageMediaFormat, getMessageMediaFormat,
getMessageMediaHash, getMessageMediaThumbDataUri, getMessageMediaHash,
getMessageMediaThumbDataUri,
getMessageVideo, getMessageVideo,
getMessageWebPageVideo, getMessageWebPageVideo,
isForwardedMessage,
isOwnMessage, isOwnMessage,
} from '../../../global/helpers'; } from '../../../global/helpers';
import type { ObserveFn } from '../../../hooks/useIntersectionObserver'; import type { ObserveFn } from '../../../hooks/useIntersectionObserver';
@ -41,10 +41,10 @@ export type OwnProps = {
canAutoPlay?: boolean; canAutoPlay?: boolean;
uploadProgress?: number; uploadProgress?: number;
dimensions?: IMediaDimensions; dimensions?: IMediaDimensions;
asForwarded?: boolean;
lastSyncTime?: number; lastSyncTime?: number;
isDownloading: boolean; isDownloading: boolean;
isProtected?: boolean; isProtected?: boolean;
withAspectRatio?: boolean;
onClick?: (id: number) => void; onClick?: (id: number) => void;
onCancelUpload?: (message: ApiMessage) => void; onCancelUpload?: (message: ApiMessage) => void;
}; };
@ -60,11 +60,11 @@ const Video: FC<OwnProps> = ({
uploadProgress, uploadProgress,
lastSyncTime, lastSyncTime,
dimensions, dimensions,
onClick, asForwarded,
onCancelUpload,
isDownloading, isDownloading,
isProtected, isProtected,
withAspectRatio, onClick,
onCancelUpload,
}) => { }) => {
// eslint-disable-next-line no-null/no-null // eslint-disable-next-line no-null/no-null
const ref = useRef<HTMLDivElement>(null); const ref = useRef<HTMLDivElement>(null);
@ -140,8 +140,10 @@ const Video: FC<OwnProps> = ({
const duration = videoRef.current?.duration || video.duration || 0; const duration = videoRef.current?.duration || video.duration || 0;
const isOwn = isOwnMessage(message); const isOwn = isOwnMessage(message);
const isForwarded = isForwardedMessage(message); const isWebPageVideo = Boolean(getMessageWebPageVideo(message));
const { width, height } = dimensions || calculateVideoDimensions(video, isOwn, isForwarded, noAvatars); const {
width, height,
} = dimensions || calculateVideoDimensions(video, isOwn, asForwarded, isWebPageVideo, noAvatars);
const handleClick = useCallback(() => { const handleClick = useCallback(() => {
if (isUploading) { if (isUploading) {
@ -161,9 +163,8 @@ const Video: FC<OwnProps> = ({
const className = buildClassName('media-inner dark', !isUploading && 'interactive'); const className = buildClassName('media-inner dark', !isUploading && 'interactive');
const dimensionsStyle = dimensions ? ` left: ${dimensions.x}px; top: ${dimensions.y}px;` : ''; const dimensionsStyle = dimensions ? ` width: ${width}px; left: ${dimensions.x}px; top: ${dimensions.y}px;` : '';
const aspectRatioStyle = withAspectRatio ? ` aspect-ratio: ${(width / height).toFixed(3)}/ 1;` : ''; const style = `height: ${height}px;${dimensionsStyle}`;
const style = `width: ${width}px; height: ${height}px;${dimensionsStyle}${aspectRatioStyle}`;
return ( return (
<div <div
@ -179,8 +180,6 @@ const Video: FC<OwnProps> = ({
src={fullMediaData} src={fullMediaData}
className="full-media" className="full-media"
canPlay={isPlayAllowed && isIntersectingForPlaying} canPlay={isPlayAllowed && isIntersectingForPlaying}
width={width}
height={height}
muted muted
loop loop
playsInline playsInline

View File

@ -26,6 +26,7 @@ type OwnProps = {
canAutoLoad?: boolean; canAutoLoad?: boolean;
canAutoPlay?: boolean; canAutoPlay?: boolean;
inPreview?: boolean; inPreview?: boolean;
asForwarded?: boolean;
lastSyncTime?: number; lastSyncTime?: number;
isDownloading?: boolean; isDownloading?: boolean;
isProtected?: boolean; isProtected?: boolean;
@ -41,6 +42,7 @@ const WebPage: FC<OwnProps> = ({
canAutoLoad, canAutoLoad,
canAutoPlay, canAutoPlay,
inPreview, inPreview,
asForwarded,
lastSyncTime, lastSyncTime,
isDownloading = false, isDownloading = false,
isProtected, isProtected,
@ -98,13 +100,13 @@ const WebPage: FC<OwnProps> = ({
noAvatars={noAvatars} noAvatars={noAvatars}
canAutoLoad={canAutoLoad} canAutoLoad={canAutoLoad}
size={isSquarePhoto ? 'pictogram' : 'inline'} size={isSquarePhoto ? 'pictogram' : 'inline'}
asForwarded={asForwarded}
nonInteractive={!isMediaInteractive} nonInteractive={!isMediaInteractive}
onClick={isMediaInteractive ? handleMediaClick : undefined}
onCancelUpload={onCancelMediaTransfer}
isDownloading={isDownloading} isDownloading={isDownloading}
isProtected={isProtected} isProtected={isProtected}
withAspectRatio
theme={theme} theme={theme}
onClick={isMediaInteractive ? handleMediaClick : undefined}
onCancelUpload={onCancelMediaTransfer}
/> />
)} )}
{isArticle && ( {isArticle && (
@ -126,11 +128,11 @@ const WebPage: FC<OwnProps> = ({
canAutoLoad={canAutoLoad} canAutoLoad={canAutoLoad}
canAutoPlay={canAutoPlay} canAutoPlay={canAutoPlay}
lastSyncTime={lastSyncTime} lastSyncTime={lastSyncTime}
onClick={isMediaInteractive ? handleMediaClick : undefined} asForwarded={asForwarded}
onCancelUpload={onCancelMediaTransfer}
isDownloading={isDownloading} isDownloading={isDownloading}
isProtected={isProtected} isProtected={isProtected}
withAspectRatio onClick={isMediaInteractive ? handleMediaClick : undefined}
onCancelUpload={onCancelMediaTransfer}
/> />
)} )}
</div> </div>

View File

@ -93,7 +93,7 @@ function calculateContainerSize(layout: IMediaLayout[]) {
export function calculateAlbumLayout( export function calculateAlbumLayout(
isOwn: boolean, isOwn: boolean,
isForwarded: boolean, asForwarded: boolean,
noAvatars: boolean, noAvatars: boolean,
album: IAlbum, album: IAlbum,
): IAlbumLayout { ): IAlbumLayout {
@ -103,7 +103,7 @@ export function calculateAlbumLayout(
const averageRatio = getAverageRatio(ratios); const averageRatio = getAverageRatio(ratios);
const albumCount = ratios.length; const albumCount = ratios.length;
const forceCalc = ratios.some((ratio) => ratio > 2); const forceCalc = ratios.some((ratio) => ratio > 2);
const maxWidth = getAvailableWidth(isOwn, isForwarded, false, noAvatars) - (isForwarded ? 2.5 : 0) * REM; const maxWidth = getAvailableWidth(isOwn, asForwarded, false, noAvatars) - (asForwarded ? 2.5 : 0) * REM;
const maxHeight = maxWidth; const maxHeight = maxWidth;
let layout; let layout;

View File

@ -4,9 +4,9 @@ import {
getMessageText, getMessageText,
getMessagePhoto, getMessagePhoto,
getMessageWebPagePhoto, getMessageWebPagePhoto,
isForwardedMessage,
isOwnMessage, isOwnMessage,
getMessageVideo, getMessageVideo,
getMessageWebPageVideo,
} from '../../../../global/helpers'; } from '../../../../global/helpers';
const MIN_MEDIA_WIDTH = 100; const MIN_MEDIA_WIDTH = 100;
@ -22,16 +22,16 @@ export function getMinMediaWidth(hasText?: boolean, hasCommentButton?: boolean)
: (hasCommentButton ? MIN_MEDIA_WIDTH_WITH_COMMENTS : MIN_MEDIA_WIDTH); : (hasCommentButton ? MIN_MEDIA_WIDTH_WITH_COMMENTS : MIN_MEDIA_WIDTH);
} }
export function calculateMediaDimensions(message: ApiMessage, noAvatars?: boolean) { export function calculateMediaDimensions(message: ApiMessage, asForwarded?: boolean, noAvatars?: boolean) {
const isOwn = isOwnMessage(message); const isOwn = isOwnMessage(message);
const isForwarded = isForwardedMessage(message);
const photo = getMessagePhoto(message) || getMessageWebPagePhoto(message); const photo = getMessagePhoto(message) || getMessageWebPagePhoto(message);
const video = getMessageVideo(message); const video = getMessageVideo(message);
const isWebPagePhoto = Boolean(getMessageWebPagePhoto(message)); const isWebPagePhoto = Boolean(getMessageWebPagePhoto(message));
const isWebPageVideo = Boolean(getMessageWebPageVideo(message));
const { width, height } = photo const { width, height } = photo
? calculateInlineImageDimensions(photo, isOwn, isForwarded, isWebPagePhoto, noAvatars) ? calculateInlineImageDimensions(photo, isOwn, asForwarded, isWebPagePhoto, noAvatars)
: calculateVideoDimensions(video!, isOwn, isForwarded, noAvatars); : calculateVideoDimensions(video!, isOwn, asForwarded, isWebPageVideo, noAvatars);
const hasText = Boolean(getMessageText(message)); const hasText = Boolean(getMessageText(message));
const minMediaWidth = getMinMediaWidth(hasText); const minMediaWidth = getMinMediaWidth(hasText);

View File

@ -5,7 +5,10 @@
position: relative; position: relative;
video, video,
img { img,
canvas {
width: 100%;
height: 100%;
display: block; display: block;
object-fit: cover; object-fit: cover;
} }