Media Viewer: Fix document preview slides (#6401)

This commit is contained in:
zubiden 2025-10-16 02:09:01 +02:00 committed by Alexander Zinchuk
parent 96901aec27
commit df263291da
8 changed files with 54 additions and 30 deletions

View File

@ -42,14 +42,16 @@ type OwnProps = {
autoLoadFileMaxSizeMb?: number;
isDownloading?: boolean;
shouldWarnAboutFiles?: boolean;
onCancelUpload?: () => void;
onMediaClick?: () => void;
id?: string;
onCancelUpload?: NoneToVoidFunction;
} & ({
message: ApiMessage;
onDateClick: (arg: ApiMessage) => void;
onMediaClick?: (messageId: number) => void;
} | {
message?: ApiMessage;
onDateClick?: never;
onMediaClick?: NoneToVoidFunction;
});
const BYTES_PER_MB = 1024 * 1024;
@ -69,6 +71,7 @@ const Document = ({
shouldWarnAboutFiles,
isDownloading,
message,
id,
onCancelUpload,
onMediaClick,
onDateClick,
@ -161,7 +164,11 @@ const Document = ({
}
if (withMediaViewer) {
onMediaClick();
if (message) {
onMediaClick?.(message.id);
} else if (onMediaClick) {
(onMediaClick as NoneToVoidFunction)();
}
return;
}
@ -187,6 +194,7 @@ const Document = ({
<>
<File
ref={ref}
id={id}
name={fileName}
extension={extension}
size={size}

View File

@ -27,6 +27,7 @@ import './File.scss';
type OwnProps = {
ref?: ElementRef<HTMLDivElement>;
id?: string;
name: string;
extension?: string;
size: number;
@ -48,6 +49,7 @@ type OwnProps = {
const File: FC<OwnProps> = ({
ref,
id,
name,
size,
extension = '',
@ -101,7 +103,7 @@ const File: FC<OwnProps> = ({
);
return (
<div ref={elementRef} className={fullClassName} dir={lang.isRtl ? 'rtl' : undefined}>
<div id={id} ref={elementRef} className={fullClassName} dir={lang.isRtl ? 'rtl' : undefined}>
{isSelectable && (
<div className="message-select-control no-selection">
{isSelected && <Icon name="select" />}

View File

@ -18,6 +18,7 @@ import { type MediaViewerMedia, MediaViewerOrigin, type ThreadId } from '../../t
import { ANIMATION_END_DELAY } from '../../config';
import { requestMutation } from '../../lib/fasterdom/fasterdom';
import {
getMediaSearchType,
getMessageContentIds,
getMessagePaidMedia, isChatAdmin,
} from '../../global/helpers';
@ -174,7 +175,7 @@ const MediaViewer = ({
const messageMediaIds = useMemo(() => {
return withDynamicLoading
? collectedMessageIds
: getMessageContentIds(chatMessages || {}, collectedMessageIds || [], contentType);
: getMessageContentIds(chatMessages || {}, collectedMessageIds || [], contentType || 'media');
}, [chatMessages, collectedMessageIds, contentType, withDynamicLoading]);
if (isOpen && (!prevSenderId || prevSenderId !== senderId || animationKey.current === undefined)) {
@ -353,7 +354,7 @@ const MediaViewer = ({
}
const index = messageMediaIds?.indexOf(fromMessage.id);
if (index === undefined) return undefined;
if (index === undefined || index === -1) return undefined;
const nextIndex = index + direction;
const nextMessageId = messageMediaIds![nextIndex];
const nextMessage = chatMessages?.[nextMessageId];
@ -595,7 +596,8 @@ export default memo(withGlobal(
} else if (origin === MediaViewerOrigin.SharedMedia) {
const currentSearch = selectCurrentSharedMediaSearch(global);
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;
} else if (isOriginInline || isOriginAlbum) {
const outlyingList = selectOutlyingListByMessageId(global, chatId, threadId, messageId);

View File

@ -2,7 +2,7 @@ import type {
ApiMessage, ApiPeer, ApiPeerPhotos, ApiSponsoredMessage,
} from '../../../api/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 { selectWebPageFromMessage } from '../../../global/selectors';
@ -28,7 +28,6 @@ export type MediaViewerItem = {
export type ViewableMedia = {
media: MediaViewerMedia;
isGif?: boolean;
isSingle?: boolean;
};
@ -87,7 +86,6 @@ export default function selectViewableMedia(
const media = params.media[params.mediaIndex];
return {
media,
isGif: media.mediaType === 'video' && media.isGif,
isSingle: params.media.length === 1,
};
}
@ -139,7 +137,6 @@ export default function selectViewableMedia(
const { photo: extendedPhoto, video: extendedVideo } = extendedMedia;
return {
media: (extendedPhoto || extendedVideo)!,
isGif: extendedVideo?.isGif,
};
}
}
@ -149,8 +146,6 @@ export default function selectViewableMedia(
if (media) {
return {
media,
isGif: video?.isGif,
isSingle: video?.isGif && origin !== MediaViewerOrigin.SharedMedia,
};
}

View File

@ -1,13 +1,14 @@
import { useMemo } from '../../../lib/teact/teact';
import type { MediaViewerMedia } from '../../../types';
import { ApiMediaFormat, type ApiMessageSearchType } from '../../../api/types';
import { ApiMediaFormat } from '../../../api/types';
import { MediaViewerOrigin } from '../../../types';
import {
getMediaFileSize,
getMediaFormat,
getMediaHash,
getMediaSearchType,
getMediaThumbUri,
getPhotoFullDimensions,
getProfilePhotoMediaHash,
@ -46,7 +47,7 @@ export const useMediaProps = ({
const isFromSharedMedia = origin === MediaViewerOrigin.SharedMedia;
const isFromSearch = origin === MediaViewerOrigin.SearchResult;
const contentType: ApiMessageSearchType = isGif ? 'gif' : 'media';
const contentType = media && getMediaSearchType(media);
const getMediaOrAvatarHash = useMemo(() => (isFull?: boolean) => {
if (!media) return undefined;

View File

@ -30,6 +30,7 @@ import {
getIsDownloading,
getIsSavedDialog,
getMessageDocument,
getMessageHtmlId,
isChatChannel,
isChatGroup,
isUserBot,
@ -903,6 +904,7 @@ const Profile = ({
(viewportIds as number[]).map((id) => messagesById[id] && (
<Document
key={id}
id={`shared-media${getMessageHtmlId(id)}`}
document={getMessageDocument(messagesById[id])!}
datetime={messagesById[id].date}
smaller
@ -912,6 +914,7 @@ const Profile = ({
onDateClick={handleMessageFocus}
message={messagesById[id]}
shouldWarnAboutFiles={shouldWarnAboutFiles}
onMediaClick={handleSelectMedia}
/>
))
) : resultType === 'links' ? (

View File

@ -479,7 +479,7 @@ async function searchChatMedia<T extends GlobalState>(
const loadingState = calcLoadingState(direction, limit, newFoundIds.length, currentSegment);
const filteredIds = getMessageContentIds(byId, newFoundIds, 'inlineMedia');
const filteredIds = getMessageContentIds(byId, newFoundIds, 'media');
currentSegment = mergeWithChatMediaSearchSegment(
filteredIds,
loadingState,

View File

@ -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(
messages: Record<number, ApiMessage>, messageIds: number[], contentType: ApiMessageSearchType | 'inlineMedia',
messages: Record<number, ApiMessage>, messageIds: number[], contentType: ApiMessageSearchType,
) {
let validator: (message: ApiMessage) => unknown;
@ -504,19 +530,6 @@ export function getMessageContentIds(
};
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:
return [] as Array<number>;
}