Media Viewer: Fix document preview slides (#6401)
This commit is contained in:
parent
96901aec27
commit
df263291da
@ -42,14 +42,16 @@ type OwnProps = {
|
|||||||
autoLoadFileMaxSizeMb?: number;
|
autoLoadFileMaxSizeMb?: number;
|
||||||
isDownloading?: boolean;
|
isDownloading?: boolean;
|
||||||
shouldWarnAboutFiles?: boolean;
|
shouldWarnAboutFiles?: boolean;
|
||||||
onCancelUpload?: () => void;
|
id?: string;
|
||||||
onMediaClick?: () => void;
|
onCancelUpload?: NoneToVoidFunction;
|
||||||
} & ({
|
} & ({
|
||||||
message: ApiMessage;
|
message: ApiMessage;
|
||||||
onDateClick: (arg: ApiMessage) => void;
|
onDateClick: (arg: ApiMessage) => void;
|
||||||
|
onMediaClick?: (messageId: number) => void;
|
||||||
} | {
|
} | {
|
||||||
message?: ApiMessage;
|
message?: ApiMessage;
|
||||||
onDateClick?: never;
|
onDateClick?: never;
|
||||||
|
onMediaClick?: NoneToVoidFunction;
|
||||||
});
|
});
|
||||||
|
|
||||||
const BYTES_PER_MB = 1024 * 1024;
|
const BYTES_PER_MB = 1024 * 1024;
|
||||||
@ -69,6 +71,7 @@ const Document = ({
|
|||||||
shouldWarnAboutFiles,
|
shouldWarnAboutFiles,
|
||||||
isDownloading,
|
isDownloading,
|
||||||
message,
|
message,
|
||||||
|
id,
|
||||||
onCancelUpload,
|
onCancelUpload,
|
||||||
onMediaClick,
|
onMediaClick,
|
||||||
onDateClick,
|
onDateClick,
|
||||||
@ -161,7 +164,11 @@ const Document = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (withMediaViewer) {
|
if (withMediaViewer) {
|
||||||
onMediaClick();
|
if (message) {
|
||||||
|
onMediaClick?.(message.id);
|
||||||
|
} else if (onMediaClick) {
|
||||||
|
(onMediaClick as NoneToVoidFunction)();
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,6 +194,7 @@ const Document = ({
|
|||||||
<>
|
<>
|
||||||
<File
|
<File
|
||||||
ref={ref}
|
ref={ref}
|
||||||
|
id={id}
|
||||||
name={fileName}
|
name={fileName}
|
||||||
extension={extension}
|
extension={extension}
|
||||||
size={size}
|
size={size}
|
||||||
|
|||||||
@ -27,6 +27,7 @@ import './File.scss';
|
|||||||
|
|
||||||
type OwnProps = {
|
type OwnProps = {
|
||||||
ref?: ElementRef<HTMLDivElement>;
|
ref?: ElementRef<HTMLDivElement>;
|
||||||
|
id?: string;
|
||||||
name: string;
|
name: string;
|
||||||
extension?: string;
|
extension?: string;
|
||||||
size: number;
|
size: number;
|
||||||
@ -48,6 +49,7 @@ type OwnProps = {
|
|||||||
|
|
||||||
const File: FC<OwnProps> = ({
|
const File: FC<OwnProps> = ({
|
||||||
ref,
|
ref,
|
||||||
|
id,
|
||||||
name,
|
name,
|
||||||
size,
|
size,
|
||||||
extension = '',
|
extension = '',
|
||||||
@ -101,7 +103,7 @@ const File: FC<OwnProps> = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={elementRef} className={fullClassName} dir={lang.isRtl ? 'rtl' : undefined}>
|
<div id={id} ref={elementRef} className={fullClassName} dir={lang.isRtl ? 'rtl' : undefined}>
|
||||||
{isSelectable && (
|
{isSelectable && (
|
||||||
<div className="message-select-control no-selection">
|
<div className="message-select-control no-selection">
|
||||||
{isSelected && <Icon name="select" />}
|
{isSelected && <Icon name="select" />}
|
||||||
|
|||||||
@ -18,6 +18,7 @@ import { type MediaViewerMedia, MediaViewerOrigin, type ThreadId } from '../../t
|
|||||||
import { ANIMATION_END_DELAY } from '../../config';
|
import { ANIMATION_END_DELAY } from '../../config';
|
||||||
import { requestMutation } from '../../lib/fasterdom/fasterdom';
|
import { requestMutation } from '../../lib/fasterdom/fasterdom';
|
||||||
import {
|
import {
|
||||||
|
getMediaSearchType,
|
||||||
getMessageContentIds,
|
getMessageContentIds,
|
||||||
getMessagePaidMedia, isChatAdmin,
|
getMessagePaidMedia, isChatAdmin,
|
||||||
} from '../../global/helpers';
|
} from '../../global/helpers';
|
||||||
@ -174,7 +175,7 @@ const MediaViewer = ({
|
|||||||
const messageMediaIds = useMemo(() => {
|
const messageMediaIds = useMemo(() => {
|
||||||
return withDynamicLoading
|
return withDynamicLoading
|
||||||
? collectedMessageIds
|
? collectedMessageIds
|
||||||
: getMessageContentIds(chatMessages || {}, collectedMessageIds || [], contentType);
|
: getMessageContentIds(chatMessages || {}, collectedMessageIds || [], contentType || 'media');
|
||||||
}, [chatMessages, collectedMessageIds, contentType, withDynamicLoading]);
|
}, [chatMessages, collectedMessageIds, contentType, withDynamicLoading]);
|
||||||
|
|
||||||
if (isOpen && (!prevSenderId || prevSenderId !== senderId || animationKey.current === undefined)) {
|
if (isOpen && (!prevSenderId || prevSenderId !== senderId || animationKey.current === undefined)) {
|
||||||
@ -353,7 +354,7 @@ const MediaViewer = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const index = messageMediaIds?.indexOf(fromMessage.id);
|
const index = messageMediaIds?.indexOf(fromMessage.id);
|
||||||
if (index === undefined) return undefined;
|
if (index === undefined || index === -1) return undefined;
|
||||||
const nextIndex = index + direction;
|
const nextIndex = index + direction;
|
||||||
const nextMessageId = messageMediaIds![nextIndex];
|
const nextMessageId = messageMediaIds![nextIndex];
|
||||||
const nextMessage = chatMessages?.[nextMessageId];
|
const nextMessage = chatMessages?.[nextMessageId];
|
||||||
@ -595,7 +596,8 @@ export default memo(withGlobal(
|
|||||||
} else if (origin === MediaViewerOrigin.SharedMedia) {
|
} else if (origin === MediaViewerOrigin.SharedMedia) {
|
||||||
const currentSearch = selectCurrentSharedMediaSearch(global);
|
const currentSearch = selectCurrentSharedMediaSearch(global);
|
||||||
const resultsByType = currentSearch?.resultsByType;
|
const resultsByType = currentSearch?.resultsByType;
|
||||||
const { foundIds } = (viewableMedia?.isGif ? resultsByType?.gif : resultsByType?.media) || {};
|
const contentType = viewableMedia && getMediaSearchType(viewableMedia?.media);
|
||||||
|
const { foundIds } = (contentType && resultsByType?.[contentType]) || {};
|
||||||
collectedMessageIds = foundIds;
|
collectedMessageIds = foundIds;
|
||||||
} else if (isOriginInline || isOriginAlbum) {
|
} else if (isOriginInline || isOriginAlbum) {
|
||||||
const outlyingList = selectOutlyingListByMessageId(global, chatId, threadId, messageId);
|
const outlyingList = selectOutlyingListByMessageId(global, chatId, threadId, messageId);
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import type {
|
|||||||
ApiMessage, ApiPeer, ApiPeerPhotos, ApiSponsoredMessage,
|
ApiMessage, ApiPeer, ApiPeerPhotos, ApiSponsoredMessage,
|
||||||
} from '../../../api/types';
|
} from '../../../api/types';
|
||||||
import type { GlobalState } from '../../../global/types';
|
import type { GlobalState } from '../../../global/types';
|
||||||
import { type MediaViewerMedia, MediaViewerOrigin } from '../../../types';
|
import type { MediaViewerMedia, MediaViewerOrigin } from '../../../types';
|
||||||
|
|
||||||
import { getMessageContent, isDocumentPhoto, isDocumentVideo } from '../../../global/helpers';
|
import { getMessageContent, isDocumentPhoto, isDocumentVideo } from '../../../global/helpers';
|
||||||
import { selectWebPageFromMessage } from '../../../global/selectors';
|
import { selectWebPageFromMessage } from '../../../global/selectors';
|
||||||
@ -28,7 +28,6 @@ export type MediaViewerItem = {
|
|||||||
|
|
||||||
export type ViewableMedia = {
|
export type ViewableMedia = {
|
||||||
media: MediaViewerMedia;
|
media: MediaViewerMedia;
|
||||||
isGif?: boolean;
|
|
||||||
isSingle?: boolean;
|
isSingle?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -87,7 +86,6 @@ export default function selectViewableMedia(
|
|||||||
const media = params.media[params.mediaIndex];
|
const media = params.media[params.mediaIndex];
|
||||||
return {
|
return {
|
||||||
media,
|
media,
|
||||||
isGif: media.mediaType === 'video' && media.isGif,
|
|
||||||
isSingle: params.media.length === 1,
|
isSingle: params.media.length === 1,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -139,7 +137,6 @@ export default function selectViewableMedia(
|
|||||||
const { photo: extendedPhoto, video: extendedVideo } = extendedMedia;
|
const { photo: extendedPhoto, video: extendedVideo } = extendedMedia;
|
||||||
return {
|
return {
|
||||||
media: (extendedPhoto || extendedVideo)!,
|
media: (extendedPhoto || extendedVideo)!,
|
||||||
isGif: extendedVideo?.isGif,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -149,8 +146,6 @@ export default function selectViewableMedia(
|
|||||||
if (media) {
|
if (media) {
|
||||||
return {
|
return {
|
||||||
media,
|
media,
|
||||||
isGif: video?.isGif,
|
|
||||||
isSingle: video?.isGif && origin !== MediaViewerOrigin.SharedMedia,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,13 +1,14 @@
|
|||||||
import { useMemo } from '../../../lib/teact/teact';
|
import { useMemo } from '../../../lib/teact/teact';
|
||||||
|
|
||||||
import type { MediaViewerMedia } from '../../../types';
|
import type { MediaViewerMedia } from '../../../types';
|
||||||
import { ApiMediaFormat, type ApiMessageSearchType } from '../../../api/types';
|
import { ApiMediaFormat } from '../../../api/types';
|
||||||
import { MediaViewerOrigin } from '../../../types';
|
import { MediaViewerOrigin } from '../../../types';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
getMediaFileSize,
|
getMediaFileSize,
|
||||||
getMediaFormat,
|
getMediaFormat,
|
||||||
getMediaHash,
|
getMediaHash,
|
||||||
|
getMediaSearchType,
|
||||||
getMediaThumbUri,
|
getMediaThumbUri,
|
||||||
getPhotoFullDimensions,
|
getPhotoFullDimensions,
|
||||||
getProfilePhotoMediaHash,
|
getProfilePhotoMediaHash,
|
||||||
@ -46,7 +47,7 @@ export const useMediaProps = ({
|
|||||||
const isFromSharedMedia = origin === MediaViewerOrigin.SharedMedia;
|
const isFromSharedMedia = origin === MediaViewerOrigin.SharedMedia;
|
||||||
const isFromSearch = origin === MediaViewerOrigin.SearchResult;
|
const isFromSearch = origin === MediaViewerOrigin.SearchResult;
|
||||||
|
|
||||||
const contentType: ApiMessageSearchType = isGif ? 'gif' : 'media';
|
const contentType = media && getMediaSearchType(media);
|
||||||
|
|
||||||
const getMediaOrAvatarHash = useMemo(() => (isFull?: boolean) => {
|
const getMediaOrAvatarHash = useMemo(() => (isFull?: boolean) => {
|
||||||
if (!media) return undefined;
|
if (!media) return undefined;
|
||||||
|
|||||||
@ -30,6 +30,7 @@ import {
|
|||||||
getIsDownloading,
|
getIsDownloading,
|
||||||
getIsSavedDialog,
|
getIsSavedDialog,
|
||||||
getMessageDocument,
|
getMessageDocument,
|
||||||
|
getMessageHtmlId,
|
||||||
isChatChannel,
|
isChatChannel,
|
||||||
isChatGroup,
|
isChatGroup,
|
||||||
isUserBot,
|
isUserBot,
|
||||||
@ -903,6 +904,7 @@ const Profile = ({
|
|||||||
(viewportIds as number[]).map((id) => messagesById[id] && (
|
(viewportIds as number[]).map((id) => messagesById[id] && (
|
||||||
<Document
|
<Document
|
||||||
key={id}
|
key={id}
|
||||||
|
id={`shared-media${getMessageHtmlId(id)}`}
|
||||||
document={getMessageDocument(messagesById[id])!}
|
document={getMessageDocument(messagesById[id])!}
|
||||||
datetime={messagesById[id].date}
|
datetime={messagesById[id].date}
|
||||||
smaller
|
smaller
|
||||||
@ -912,6 +914,7 @@ const Profile = ({
|
|||||||
onDateClick={handleMessageFocus}
|
onDateClick={handleMessageFocus}
|
||||||
message={messagesById[id]}
|
message={messagesById[id]}
|
||||||
shouldWarnAboutFiles={shouldWarnAboutFiles}
|
shouldWarnAboutFiles={shouldWarnAboutFiles}
|
||||||
|
onMediaClick={handleSelectMedia}
|
||||||
/>
|
/>
|
||||||
))
|
))
|
||||||
) : resultType === 'links' ? (
|
) : resultType === 'links' ? (
|
||||||
|
|||||||
@ -479,7 +479,7 @@ async function searchChatMedia<T extends GlobalState>(
|
|||||||
|
|
||||||
const loadingState = calcLoadingState(direction, limit, newFoundIds.length, currentSegment);
|
const loadingState = calcLoadingState(direction, limit, newFoundIds.length, currentSegment);
|
||||||
|
|
||||||
const filteredIds = getMessageContentIds(byId, newFoundIds, 'inlineMedia');
|
const filteredIds = getMessageContentIds(byId, newFoundIds, 'media');
|
||||||
currentSegment = mergeWithChatMediaSearchSegment(
|
currentSegment = mergeWithChatMediaSearchSegment(
|
||||||
filteredIds,
|
filteredIds,
|
||||||
loadingState,
|
loadingState,
|
||||||
|
|||||||
@ -465,8 +465,34 @@ export function getMediaTransferState(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getMediaSearchType(media: DownloadableMedia):
|
||||||
|
Extract<ApiMessageSearchType, 'gif' | 'media' | 'documents' | 'audio' | 'voice'> | undefined {
|
||||||
|
if (media.mediaType === 'video') {
|
||||||
|
if (media.isRound) return 'voice';
|
||||||
|
return media.isGif ? 'gif' : 'media';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (media.mediaType === 'audio') {
|
||||||
|
return 'audio';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (media.mediaType === 'voice') {
|
||||||
|
return 'voice';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (media.mediaType === 'document') {
|
||||||
|
return 'documents';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (media.mediaType === 'photo') {
|
||||||
|
return 'media';
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
export function getMessageContentIds(
|
export function getMessageContentIds(
|
||||||
messages: Record<number, ApiMessage>, messageIds: number[], contentType: ApiMessageSearchType | 'inlineMedia',
|
messages: Record<number, ApiMessage>, messageIds: number[], contentType: ApiMessageSearchType,
|
||||||
) {
|
) {
|
||||||
let validator: (message: ApiMessage) => unknown;
|
let validator: (message: ApiMessage) => unknown;
|
||||||
|
|
||||||
@ -504,19 +530,6 @@ export function getMessageContentIds(
|
|||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'inlineMedia':
|
|
||||||
validator = (message: ApiMessage) => {
|
|
||||||
const video = getMessageVideo(message);
|
|
||||||
const document = getMessageDocument(message);
|
|
||||||
return (
|
|
||||||
getMessagePhoto(message)
|
|
||||||
|| (video && !video.isRound && !video.isGif)
|
|
||||||
|| (document && isDocumentPhoto(document))
|
|
||||||
|| (document && isDocumentVideo(document))
|
|
||||||
);
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return [] as Array<number>;
|
return [] as Array<number>;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user