Message: Fix narrow media in messages (#2868)
This commit is contained in:
parent
6176ef1a98
commit
4390800a46
@ -335,7 +335,7 @@ function getNodes(origin: MediaViewerOrigin, message?: ApiMessage) {
|
|||||||
case MediaViewerOrigin.Inline:
|
case MediaViewerOrigin.Inline:
|
||||||
default:
|
default:
|
||||||
containerSelector = `.Transition__slide--active > .MessageList #${getMessageHtmlId(message!.id)}`;
|
containerSelector = `.Transition__slide--active > .MessageList #${getMessageHtmlId(message!.id)}`;
|
||||||
mediaSelector = `${MESSAGE_CONTENT_SELECTOR} .full-media, ${MESSAGE_CONTENT_SELECTOR} .thumbnail`;
|
mediaSelector = `${MESSAGE_CONTENT_SELECTOR} .full-media,${MESSAGE_CONTENT_SELECTOR} .thumbnail:not(.blurred-bg)`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const container = document.querySelector<HTMLElement>(containerSelector)!;
|
const container = document.querySelector<HTMLElement>(containerSelector)!;
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
.Album {
|
.Album {
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
margin: auto;
|
||||||
|
|
||||||
.message-content.media.text & {
|
.message-content.media.text & {
|
||||||
margin: -0.3125rem -0.5rem 0.3125rem;
|
margin: -0.3125rem -0.5rem 0.3125rem;
|
||||||
|
|||||||
@ -14,6 +14,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.invoice-image {
|
.invoice-image {
|
||||||
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-height: 30rem;
|
max-height: 30rem;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
@ -42,4 +43,20 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.invoice-image-container {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thumbnail {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,6 +13,7 @@ import getCustomAppendixBg from './helpers/getCustomAppendixBg';
|
|||||||
import useLayoutEffectWithPrevDeps from '../../../hooks/useLayoutEffectWithPrevDeps';
|
import useLayoutEffectWithPrevDeps from '../../../hooks/useLayoutEffectWithPrevDeps';
|
||||||
import useLang from '../../../hooks/useLang';
|
import useLang from '../../../hooks/useLang';
|
||||||
import useMedia from '../../../hooks/useMedia';
|
import useMedia from '../../../hooks/useMedia';
|
||||||
|
import useBlurredMediaThumbRef from './hooks/useBlurredMediaThumbRef';
|
||||||
|
|
||||||
import Skeleton from '../../ui/Skeleton';
|
import Skeleton from '../../ui/Skeleton';
|
||||||
|
|
||||||
@ -24,6 +25,7 @@ type OwnProps = {
|
|||||||
isInSelectMode?: boolean;
|
isInSelectMode?: boolean;
|
||||||
isSelected?: boolean;
|
isSelected?: boolean;
|
||||||
theme: ISettings['theme'];
|
theme: ISettings['theme'];
|
||||||
|
forcedWidth?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
const Invoice: FC<OwnProps> = ({
|
const Invoice: FC<OwnProps> = ({
|
||||||
@ -32,6 +34,7 @@ const Invoice: FC<OwnProps> = ({
|
|||||||
isInSelectMode,
|
isInSelectMode,
|
||||||
isSelected,
|
isSelected,
|
||||||
theme,
|
theme,
|
||||||
|
forcedWidth,
|
||||||
}) => {
|
}) => {
|
||||||
// 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);
|
||||||
@ -49,6 +52,8 @@ const Invoice: FC<OwnProps> = ({
|
|||||||
} = invoice!;
|
} = invoice!;
|
||||||
|
|
||||||
const photoUrl = useMedia(getWebDocumentHash(photo));
|
const photoUrl = useMedia(getWebDocumentHash(photo));
|
||||||
|
const withBlurredBackground = Boolean(forcedWidth);
|
||||||
|
const blurredBackgroundRef = useBlurredMediaThumbRef(message, !withBlurredBackground, photoUrl);
|
||||||
|
|
||||||
useLayoutEffectWithPrevDeps(([prevShouldAffectAppendix]) => {
|
useLayoutEffectWithPrevDeps(([prevShouldAffectAppendix]) => {
|
||||||
if (!shouldAffectAppendix) {
|
if (!shouldAffectAppendix) {
|
||||||
@ -79,16 +84,26 @@ const Invoice: FC<OwnProps> = ({
|
|||||||
<div>{renderText(text, ['emoji', 'br'])}</div>
|
<div>{renderText(text, ['emoji', 'br'])}</div>
|
||||||
)}
|
)}
|
||||||
<div className={`description ${photo ? 'has-image' : ''}`}>
|
<div className={`description ${photo ? 'has-image' : ''}`}>
|
||||||
{photoUrl && (
|
{Boolean(photo) && (
|
||||||
<img
|
<div className="invoice-image-container">
|
||||||
className="invoice-image"
|
{withBlurredBackground && <canvas ref={blurredBackgroundRef} className="thumbnail blurred-bg" />}
|
||||||
src={photoUrl}
|
{photoUrl && (
|
||||||
alt=""
|
<img
|
||||||
crossOrigin="anonymous"
|
className="invoice-image"
|
||||||
/>
|
src={photoUrl}
|
||||||
)}
|
alt=""
|
||||||
{!photoUrl && photo && (
|
style={forcedWidth ? `width: ${forcedWidth}px` : undefined}
|
||||||
<Skeleton width={photo.dimensions?.width} height={photo.dimensions?.height} forceAspectRatio />
|
crossOrigin="anonymous"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{!photoUrl && photo && (
|
||||||
|
<Skeleton
|
||||||
|
width={forcedWidth || photo.dimensions?.width}
|
||||||
|
height={photo.dimensions?.height}
|
||||||
|
forceAspectRatio
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
<p className="description-text">
|
<p className="description-text">
|
||||||
{formatCurrency(amount, currency, lang.code)}
|
{formatCurrency(amount, currency, lang.code)}
|
||||||
|
|||||||
@ -96,7 +96,12 @@ import {
|
|||||||
ROUND_VIDEO_DIMENSIONS_PX,
|
ROUND_VIDEO_DIMENSIONS_PX,
|
||||||
} from '../../common/helpers/mediaDimensions';
|
} from '../../common/helpers/mediaDimensions';
|
||||||
import { buildContentClassName } from './helpers/buildContentClassName';
|
import { buildContentClassName } from './helpers/buildContentClassName';
|
||||||
import { getMinMediaWidth, calculateMediaDimensions } from './helpers/mediaDimensions';
|
import {
|
||||||
|
getMinMediaWidth,
|
||||||
|
calculateMediaDimensions,
|
||||||
|
MIN_MEDIA_WIDTH_WITH_COMMENTS,
|
||||||
|
MIN_MEDIA_WIDTH_WITH_TEXT,
|
||||||
|
} from './helpers/mediaDimensions';
|
||||||
import { calculateAlbumLayout } from './helpers/calculateAlbumLayout';
|
import { calculateAlbumLayout } from './helpers/calculateAlbumLayout';
|
||||||
import renderText from '../../common/helpers/renderText';
|
import renderText from '../../common/helpers/renderText';
|
||||||
import calculateAuthorWidth from './helpers/calculateAuthorWidth';
|
import calculateAuthorWidth from './helpers/calculateAuthorWidth';
|
||||||
@ -223,6 +228,7 @@ type StateProps = {
|
|||||||
isPinnedList?: boolean;
|
isPinnedList?: boolean;
|
||||||
canAutoLoadMedia?: boolean;
|
canAutoLoadMedia?: boolean;
|
||||||
canAutoPlayMedia?: boolean;
|
canAutoPlayMedia?: boolean;
|
||||||
|
hasLinkedChat?: boolean;
|
||||||
shouldLoopStickers?: boolean;
|
shouldLoopStickers?: boolean;
|
||||||
autoLoadFileMaxSizeMb: number;
|
autoLoadFileMaxSizeMb: number;
|
||||||
repliesThreadInfo?: ApiThreadInfo;
|
repliesThreadInfo?: ApiThreadInfo;
|
||||||
@ -317,6 +323,7 @@ const Message: FC<OwnProps & StateProps> = ({
|
|||||||
animatedEmoji,
|
animatedEmoji,
|
||||||
animatedCustomEmoji,
|
animatedCustomEmoji,
|
||||||
genericEffects,
|
genericEffects,
|
||||||
|
hasLinkedChat,
|
||||||
isInSelectMode,
|
isInSelectMode,
|
||||||
isSelected,
|
isSelected,
|
||||||
isGroupSelected,
|
isGroupSelected,
|
||||||
@ -565,6 +572,10 @@ const Message: FC<OwnProps & StateProps> = ({
|
|||||||
|
|
||||||
const { phoneCall } = action || {};
|
const { phoneCall } = action || {};
|
||||||
|
|
||||||
|
const isMediaWidthWithCommentButton = (repliesThreadInfo || (hasLinkedChat && isChannel && isLocal))
|
||||||
|
&& !isInDocumentGroupNotLast
|
||||||
|
&& messageListType === 'thread'
|
||||||
|
&& !noComments;
|
||||||
const withCommentButton = repliesThreadInfo && !isInDocumentGroupNotLast && messageListType === 'thread'
|
const withCommentButton = repliesThreadInfo && !isInDocumentGroupNotLast && messageListType === 'thread'
|
||||||
&& !noComments;
|
&& !noComments;
|
||||||
const withQuickReactionButton = !IS_TOUCH_ENV && !phoneCall && !isInSelectMode && defaultReaction
|
const withQuickReactionButton = !IS_TOUCH_ENV && !phoneCall && !isInSelectMode && defaultReaction
|
||||||
@ -657,6 +668,7 @@ const Message: FC<OwnProps & StateProps> = ({
|
|||||||
let style = '';
|
let style = '';
|
||||||
let calculatedWidth;
|
let calculatedWidth;
|
||||||
let reactionsMaxWidth;
|
let reactionsMaxWidth;
|
||||||
|
let contentWidth: number | undefined;
|
||||||
let noMediaCorners = false;
|
let noMediaCorners = false;
|
||||||
const albumLayout = useMemo(() => {
|
const albumLayout = useMemo(() => {
|
||||||
return isAlbum
|
return isAlbum
|
||||||
@ -690,14 +702,17 @@ const Message: FC<OwnProps & StateProps> = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (width) {
|
if (width) {
|
||||||
calculatedWidth = Math.max(getMinMediaWidth(Boolean(currentText), withCommentButton), width);
|
if (width < (isMediaWidthWithCommentButton ? MIN_MEDIA_WIDTH_WITH_COMMENTS : MIN_MEDIA_WIDTH_WITH_TEXT)) {
|
||||||
|
contentWidth = width;
|
||||||
|
}
|
||||||
|
calculatedWidth = Math.max(getMinMediaWidth(Boolean(currentText), isMediaWidthWithCommentButton), width);
|
||||||
if (invoice?.extendedMedia && calculatedWidth - width > NO_MEDIA_CORNERS_THRESHOLD) {
|
if (invoice?.extendedMedia && calculatedWidth - width > NO_MEDIA_CORNERS_THRESHOLD) {
|
||||||
noMediaCorners = true;
|
noMediaCorners = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (albumLayout) {
|
} else if (albumLayout) {
|
||||||
calculatedWidth = Math.max(
|
calculatedWidth = Math.max(
|
||||||
getMinMediaWidth(Boolean(currentText), withCommentButton), albumLayout.containerStyle.width,
|
getMinMediaWidth(Boolean(currentText), isMediaWidthWithCommentButton), albumLayout.containerStyle.width,
|
||||||
);
|
);
|
||||||
if (calculatedWidth - albumLayout.containerStyle.width > NO_MEDIA_CORNERS_THRESHOLD) {
|
if (calculatedWidth - albumLayout.containerStyle.width > NO_MEDIA_CORNERS_THRESHOLD) {
|
||||||
noMediaCorners = true;
|
noMediaCorners = true;
|
||||||
@ -900,6 +915,7 @@ const Message: FC<OwnProps & StateProps> = ({
|
|||||||
isProtected={isProtected}
|
isProtected={isProtected}
|
||||||
asForwarded={asForwarded}
|
asForwarded={asForwarded}
|
||||||
theme={theme}
|
theme={theme}
|
||||||
|
forcedWidth={contentWidth}
|
||||||
onClick={handleMediaClick}
|
onClick={handleMediaClick}
|
||||||
onCancelUpload={handleCancelUpload}
|
onCancelUpload={handleCancelUpload}
|
||||||
/>
|
/>
|
||||||
@ -918,6 +934,7 @@ const Message: FC<OwnProps & StateProps> = ({
|
|||||||
message={message}
|
message={message}
|
||||||
observeIntersectionForLoading={observeIntersectionForLoading}
|
observeIntersectionForLoading={observeIntersectionForLoading}
|
||||||
observeIntersectionForPlaying={observeIntersectionForPlaying}
|
observeIntersectionForPlaying={observeIntersectionForPlaying}
|
||||||
|
forcedWidth={contentWidth}
|
||||||
noAvatars={noAvatars}
|
noAvatars={noAvatars}
|
||||||
canAutoLoad={canAutoLoadMedia}
|
canAutoLoad={canAutoLoadMedia}
|
||||||
canAutoPlay={canAutoPlayMedia}
|
canAutoPlay={canAutoPlayMedia}
|
||||||
@ -1038,6 +1055,7 @@ const Message: FC<OwnProps & StateProps> = ({
|
|||||||
isInSelectMode={isInSelectMode}
|
isInSelectMode={isInSelectMode}
|
||||||
isSelected={isSelected}
|
isSelected={isSelected}
|
||||||
theme={theme}
|
theme={theme}
|
||||||
|
forcedWidth={contentWidth}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{location && (
|
{location && (
|
||||||
@ -1410,6 +1428,7 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
chatTranslations,
|
chatTranslations,
|
||||||
areTranslationsEnabled: global.settings.byKey.canTranslate,
|
areTranslationsEnabled: global.settings.byKey.canTranslate,
|
||||||
requestedTranslationLanguage,
|
requestedTranslationLanguage,
|
||||||
|
hasLinkedChat: Boolean(chat?.fullInfo?.linkedChatId),
|
||||||
...((canShowSender || isLocation) && { sender }),
|
...((canShowSender || isLocation) && { sender }),
|
||||||
...(isOutgoing && { outgoingStatus: selectOutgoingStatus(global, message, messageListType === 'scheduled') }),
|
...(isOutgoing && { outgoingStatus: selectOutgoingStatus(global, message, messageListType === 'scheduled') }),
|
||||||
...(typeof uploadProgress === 'number' && { uploadProgress }),
|
...(typeof uploadProgress === 'number' && { uploadProgress }),
|
||||||
|
|||||||
@ -20,7 +20,7 @@ import {
|
|||||||
} from '../../../global/helpers';
|
} from '../../../global/helpers';
|
||||||
import buildClassName from '../../../util/buildClassName';
|
import buildClassName from '../../../util/buildClassName';
|
||||||
import getCustomAppendixBg from './helpers/getCustomAppendixBg';
|
import getCustomAppendixBg from './helpers/getCustomAppendixBg';
|
||||||
import { calculateMediaDimensions } from './helpers/mediaDimensions';
|
import { calculateMediaDimensions, MIN_MEDIA_HEIGHT } from './helpers/mediaDimensions';
|
||||||
|
|
||||||
import { useIsIntersecting } from '../../../hooks/useIntersectionObserver';
|
import { useIsIntersecting } from '../../../hooks/useIntersectionObserver';
|
||||||
import useMediaWithLoadProgress from '../../../hooks/useMediaWithLoadProgress';
|
import useMediaWithLoadProgress from '../../../hooks/useMediaWithLoadProgress';
|
||||||
@ -44,6 +44,7 @@ export type OwnProps = {
|
|||||||
isInSelectMode?: boolean;
|
isInSelectMode?: boolean;
|
||||||
isSelected?: boolean;
|
isSelected?: boolean;
|
||||||
uploadProgress?: number;
|
uploadProgress?: number;
|
||||||
|
forcedWidth?: number;
|
||||||
size?: 'inline' | 'pictogram';
|
size?: 'inline' | 'pictogram';
|
||||||
shouldAffectAppendix?: boolean;
|
shouldAffectAppendix?: boolean;
|
||||||
dimensions?: IMediaDimensions & { isSmall?: boolean };
|
dimensions?: IMediaDimensions & { isSmall?: boolean };
|
||||||
@ -65,6 +66,7 @@ const Photo: FC<OwnProps> = ({
|
|||||||
isInSelectMode,
|
isInSelectMode,
|
||||||
isSelected,
|
isSelected,
|
||||||
uploadProgress,
|
uploadProgress,
|
||||||
|
forcedWidth,
|
||||||
size = 'inline',
|
size = 'inline',
|
||||||
dimensions,
|
dimensions,
|
||||||
asForwarded,
|
asForwarded,
|
||||||
@ -92,9 +94,11 @@ const Photo: FC<OwnProps> = ({
|
|||||||
} = useMediaWithLoadProgress(getMessageMediaHash(message, size), !shouldLoad);
|
} = useMediaWithLoadProgress(getMessageMediaHash(message, size), !shouldLoad);
|
||||||
const fullMediaData = localBlobUrl || mediaData;
|
const fullMediaData = localBlobUrl || mediaData;
|
||||||
|
|
||||||
|
const withBlurredBackground = Boolean(forcedWidth);
|
||||||
const [withThumb] = useState(!fullMediaData);
|
const [withThumb] = useState(!fullMediaData);
|
||||||
const noThumb = Boolean(fullMediaData);
|
const noThumb = Boolean(fullMediaData);
|
||||||
const thumbRef = useBlurredMediaThumbRef(message, noThumb);
|
const thumbRef = useBlurredMediaThumbRef(message, noThumb);
|
||||||
|
const blurredBackgroundRef = useBlurredMediaThumbRef(message, !withBlurredBackground);
|
||||||
const thumbClassNames = useMediaTransition(!noThumb);
|
const thumbClassNames = useMediaTransition(!noThumb);
|
||||||
const thumbDataUri = getMessageMediaThumbDataUri(message);
|
const thumbDataUri = getMessageMediaThumbDataUri(message);
|
||||||
|
|
||||||
@ -170,6 +174,7 @@ const Photo: FC<OwnProps> = ({
|
|||||||
!isUploading && !nonInteractive && 'interactive',
|
!isUploading && !nonInteractive && 'interactive',
|
||||||
isSmall && 'small-image',
|
isSmall && 'small-image',
|
||||||
width === height && 'square-image',
|
width === height && 'square-image',
|
||||||
|
height < MIN_MEDIA_HEIGHT && 'fix-min-height',
|
||||||
);
|
);
|
||||||
|
|
||||||
const dimensionsStyle = dimensions ? ` width: ${width}px; left: ${dimensions.x}px; top: ${dimensions.y}px;` : '';
|
const dimensionsStyle = dimensions ? ` width: ${width}px; left: ${dimensions.x}px; top: ${dimensions.y}px;` : '';
|
||||||
@ -183,10 +188,12 @@ const Photo: FC<OwnProps> = ({
|
|||||||
style={style}
|
style={style}
|
||||||
onClick={isUploading ? undefined : handleClick}
|
onClick={isUploading ? undefined : handleClick}
|
||||||
>
|
>
|
||||||
|
{withBlurredBackground && <canvas ref={blurredBackgroundRef} className="thumbnail blurred-bg" />}
|
||||||
<img
|
<img
|
||||||
src={fullMediaData}
|
src={fullMediaData}
|
||||||
className="full-media"
|
className={buildClassName('full-media', withBlurredBackground && 'with-blurred-bg')}
|
||||||
alt=""
|
alt=""
|
||||||
|
style={forcedWidth ? `width: ${forcedWidth}px` : undefined}
|
||||||
draggable={!isProtected}
|
draggable={!isProtected}
|
||||||
/>
|
/>
|
||||||
{withThumb && (
|
{withThumb && (
|
||||||
|
|||||||
@ -1,11 +1,12 @@
|
|||||||
import type { FC } from '../../../lib/teact/teact';
|
|
||||||
import React, { useCallback, useRef, useState } from '../../../lib/teact/teact';
|
import React, { useCallback, useRef, useState } from '../../../lib/teact/teact';
|
||||||
import { getActions } from '../../../global';
|
import { getActions } from '../../../global';
|
||||||
|
|
||||||
|
import type { FC } from '../../../lib/teact/teact';
|
||||||
import type { ApiMessage } from '../../../api/types';
|
import type { ApiMessage } from '../../../api/types';
|
||||||
import type { IMediaDimensions } from './helpers/calculateAlbumLayout';
|
import type { IMediaDimensions } from './helpers/calculateAlbumLayout';
|
||||||
import type { ObserveFn } from '../../../hooks/useIntersectionObserver';
|
import type { ObserveFn } from '../../../hooks/useIntersectionObserver';
|
||||||
|
|
||||||
|
import { MIN_MEDIA_HEIGHT } from './helpers/mediaDimensions';
|
||||||
import { formatMediaDuration } from '../../../util/dateFormat';
|
import { formatMediaDuration } from '../../../util/dateFormat';
|
||||||
import buildClassName from '../../../util/buildClassName';
|
import buildClassName from '../../../util/buildClassName';
|
||||||
import { calculateVideoDimensions } from '../../common/helpers/mediaDimensions';
|
import { calculateVideoDimensions } from '../../common/helpers/mediaDimensions';
|
||||||
@ -42,6 +43,7 @@ export type OwnProps = {
|
|||||||
canAutoLoad?: boolean;
|
canAutoLoad?: boolean;
|
||||||
canAutoPlay?: boolean;
|
canAutoPlay?: boolean;
|
||||||
uploadProgress?: number;
|
uploadProgress?: number;
|
||||||
|
forcedWidth?: number;
|
||||||
dimensions?: IMediaDimensions;
|
dimensions?: IMediaDimensions;
|
||||||
asForwarded?: boolean;
|
asForwarded?: boolean;
|
||||||
lastSyncTime?: number;
|
lastSyncTime?: number;
|
||||||
@ -60,6 +62,7 @@ const Video: FC<OwnProps> = ({
|
|||||||
canAutoLoad,
|
canAutoLoad,
|
||||||
canAutoPlay,
|
canAutoPlay,
|
||||||
uploadProgress,
|
uploadProgress,
|
||||||
|
forcedWidth,
|
||||||
lastSyncTime,
|
lastSyncTime,
|
||||||
dimensions,
|
dimensions,
|
||||||
asForwarded,
|
asForwarded,
|
||||||
@ -103,6 +106,7 @@ const Video: FC<OwnProps> = ({
|
|||||||
|
|
||||||
const thumbDataUri = getMessageMediaThumbDataUri(message);
|
const thumbDataUri = getMessageMediaThumbDataUri(message);
|
||||||
const hasThumb = Boolean(thumbDataUri);
|
const hasThumb = Boolean(thumbDataUri);
|
||||||
|
const withBlurredBackground = Boolean(forcedWidth);
|
||||||
|
|
||||||
const previewMediaHash = getMessageMediaHash(message, 'preview');
|
const previewMediaHash = getMessageMediaHash(message, 'preview');
|
||||||
const [isPreviewPreloaded] = useState(Boolean(previewMediaHash && mediaLoader.getFromMemory(previewMediaHash)));
|
const [isPreviewPreloaded] = useState(Boolean(previewMediaHash && mediaLoader.getFromMemory(previewMediaHash)));
|
||||||
@ -112,6 +116,7 @@ const Video: FC<OwnProps> = ({
|
|||||||
|
|
||||||
const noThumb = !hasThumb || previewBlobUrl || isPlayerReady;
|
const noThumb = !hasThumb || previewBlobUrl || isPlayerReady;
|
||||||
const thumbRef = useBlurredMediaThumbRef(message, noThumb);
|
const thumbRef = useBlurredMediaThumbRef(message, noThumb);
|
||||||
|
const blurredBackgroundRef = useBlurredMediaThumbRef(message, !withBlurredBackground);
|
||||||
const thumbClassNames = useMediaTransition(!noThumb);
|
const thumbClassNames = useMediaTransition(!noThumb);
|
||||||
|
|
||||||
const isInline = fullMediaData && wasIntersectedRef.current;
|
const isInline = fullMediaData && wasIntersectedRef.current;
|
||||||
@ -182,7 +187,11 @@ const Video: FC<OwnProps> = ({
|
|||||||
hideSpoiler,
|
hideSpoiler,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const className = buildClassName('media-inner dark', !isUploading && 'interactive');
|
const className = buildClassName(
|
||||||
|
'media-inner dark',
|
||||||
|
!isUploading && 'interactive',
|
||||||
|
height < MIN_MEDIA_HEIGHT && 'fix-min-height',
|
||||||
|
);
|
||||||
|
|
||||||
const dimensionsStyle = dimensions ? ` width: ${width}px; left: ${dimensions.x}px; top: ${dimensions.y}px;` : '';
|
const dimensionsStyle = dimensions ? ` width: ${width}px; left: ${dimensions.x}px; top: ${dimensions.y}px;` : '';
|
||||||
const style = `height: ${height}px;${dimensionsStyle}`;
|
const style = `height: ${height}px;${dimensionsStyle}`;
|
||||||
@ -195,11 +204,12 @@ const Video: FC<OwnProps> = ({
|
|||||||
style={style}
|
style={style}
|
||||||
onClick={isUploading ? undefined : handleClick}
|
onClick={isUploading ? undefined : handleClick}
|
||||||
>
|
>
|
||||||
|
{withBlurredBackground && <canvas ref={blurredBackgroundRef} className="thumbnail blurred-bg" />}
|
||||||
{isInline && (
|
{isInline && (
|
||||||
<OptimizedVideo
|
<OptimizedVideo
|
||||||
ref={videoRef}
|
ref={videoRef}
|
||||||
src={fullMediaData}
|
src={fullMediaData}
|
||||||
className="full-media"
|
className={buildClassName('full-media', withBlurredBackground && 'with-blurred-bg')}
|
||||||
canPlay={isPlayAllowed && isIntersectingForPlaying}
|
canPlay={isPlayAllowed && isIntersectingForPlaying}
|
||||||
muted
|
muted
|
||||||
loop
|
loop
|
||||||
@ -207,12 +217,14 @@ const Video: FC<OwnProps> = ({
|
|||||||
draggable={!isProtected}
|
draggable={!isProtected}
|
||||||
onTimeUpdate={handleTimeUpdate}
|
onTimeUpdate={handleTimeUpdate}
|
||||||
onReady={markPlayerReady}
|
onReady={markPlayerReady}
|
||||||
|
style={forcedWidth ? `width: ${forcedWidth}px` : undefined}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<img
|
<img
|
||||||
src={previewBlobUrl}
|
src={previewBlobUrl}
|
||||||
className={buildClassName('thumbnail', previewClassNames)}
|
className={buildClassName('thumbnail', previewClassNames, withBlurredBackground && 'with-blurred-bg')}
|
||||||
alt=""
|
alt=""
|
||||||
|
style={forcedWidth ? `width: ${forcedWidth}px;` : undefined}
|
||||||
draggable={!isProtected}
|
draggable={!isProtected}
|
||||||
/>
|
/>
|
||||||
{hasThumb && !isPreviewPreloaded && (
|
{hasThumb && !isPreviewPreloaded && (
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import type { ApiMessage } from '../../../../api/types';
|
import type { ApiMessage } from '../../../../api/types';
|
||||||
import { calculateInlineImageDimensions, calculateVideoDimensions } from '../../../common/helpers/mediaDimensions';
|
import { calculateInlineImageDimensions, calculateVideoDimensions, REM } from '../../../common/helpers/mediaDimensions';
|
||||||
import {
|
import {
|
||||||
getMessageText,
|
getMessageText,
|
||||||
getMessagePhoto,
|
getMessagePhoto,
|
||||||
@ -9,11 +9,11 @@ import {
|
|||||||
getMessageWebPageVideo,
|
getMessageWebPageVideo,
|
||||||
} from '../../../../global/helpers';
|
} from '../../../../global/helpers';
|
||||||
|
|
||||||
const MIN_MEDIA_WIDTH = 100;
|
export const MIN_MEDIA_WIDTH_WITH_COMMENTS = 20 * REM;
|
||||||
const MIN_MEDIA_WIDTH_WITH_COMMENTS = 238;
|
export const MIN_MEDIA_WIDTH_WITH_TEXT = 15 * REM;
|
||||||
const MIN_MEDIA_WIDTH_WITH_TEXT = 175;
|
const MIN_MEDIA_WIDTH_WITH_TEXT_AND_COMMENTS = 20 * REM;
|
||||||
const MIN_MEDIA_WIDTH_WITH_TEXT_AND_COMMENTS = 238;
|
const MIN_MEDIA_WIDTH = 7 * REM;
|
||||||
const MIN_MEDIA_HEIGHT = 90;
|
export const MIN_MEDIA_HEIGHT = 5 * REM;
|
||||||
const SMALL_IMAGE_THRESHOLD = 12;
|
const SMALL_IMAGE_THRESHOLD = 12;
|
||||||
|
|
||||||
export function getMinMediaWidth(hasText?: boolean, hasCommentButton?: boolean) {
|
export function getMinMediaWidth(hasText?: boolean, hasCommentButton?: boolean) {
|
||||||
|
|||||||
@ -5,11 +5,17 @@ import { getMessageMediaThumbDataUri } from '../../../../global/helpers';
|
|||||||
import useCanvasBlur from '../../../../hooks/useCanvasBlur';
|
import useCanvasBlur from '../../../../hooks/useCanvasBlur';
|
||||||
import useAppLayout from '../../../../hooks/useAppLayout';
|
import useAppLayout from '../../../../hooks/useAppLayout';
|
||||||
|
|
||||||
export default function useBlurredMediaThumbRef(message: ApiMessage, isDisabled?: boolean | string) {
|
export default function useBlurredMediaThumbRef(
|
||||||
|
message: ApiMessage,
|
||||||
|
isDisabled?: boolean | string,
|
||||||
|
forcedUri?: string,
|
||||||
|
) {
|
||||||
const { isMobile } = useAppLayout();
|
const { isMobile } = useAppLayout();
|
||||||
|
|
||||||
|
const dataUri = forcedUri || getMessageMediaThumbDataUri(message);
|
||||||
|
|
||||||
return useCanvasBlur(
|
return useCanvasBlur(
|
||||||
getMessageMediaThumbDataUri(message),
|
dataUri,
|
||||||
Boolean(isDisabled),
|
Boolean(isDisabled),
|
||||||
isMobile && !IS_CANVAS_FILTER_SUPPORTED,
|
isMobile && !IS_CANVAS_FILTER_SUPPORTED,
|
||||||
);
|
);
|
||||||
|
|||||||
@ -14,6 +14,11 @@
|
|||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.full-media.with-blurred-bg {
|
||||||
|
position: relative;
|
||||||
|
border-radius: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
video {
|
video {
|
||||||
background: no-repeat 50% 50%;
|
background: no-repeat 50% 50%;
|
||||||
background-size: contain;
|
background-size: contain;
|
||||||
@ -23,11 +28,21 @@
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
|
|
||||||
|
&.with-blurred-bg {
|
||||||
|
border-radius: 0 !important;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.media-loading {
|
.media-loading {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.fix-min-height {
|
||||||
|
min-height: 5rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.animated-close-icon {
|
.animated-close-icon {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user