Web Page: Support media size (#5083)

This commit is contained in:
Alexander Zinchuk 2024-11-02 21:10:53 +04:00
parent 0eb0784165
commit 63ce255f4c
12 changed files with 56 additions and 5 deletions

View File

@ -761,6 +761,8 @@ export function buildWebPage(media: GramJs.TypeMessageMedia): ApiWebPage | undef
}; };
} }
const mediaSize = media.forceSmallMedia ? 'small' : media.forceLargeMedia ? 'large' : undefined;
return { return {
mediaType: 'webpage', mediaType: 'webpage',
id: Number(id), id: Number(id),
@ -772,6 +774,7 @@ export function buildWebPage(media: GramJs.TypeMessageMedia): ApiWebPage | undef
'title', 'title',
'description', 'description',
'duration', 'duration',
'hasLargeMedia',
]), ]),
photo: photo instanceof GramJs.Photo ? buildApiPhoto(photo) : undefined, photo: photo instanceof GramJs.Photo ? buildApiPhoto(photo) : undefined,
document: !video && !audio && document ? buildApiDocument(document) : undefined, document: !video && !audio && document ? buildApiDocument(document) : undefined,
@ -779,6 +782,7 @@ export function buildWebPage(media: GramJs.TypeMessageMedia): ApiWebPage | undef
audio, audio,
story, story,
stickers, stickers,
mediaSize,
}; };
} }

View File

@ -1,6 +1,7 @@
import BigInt from 'big-integer'; import BigInt from 'big-integer';
import { Api as GramJs } from '../../../lib/gramjs'; import { Api as GramJs } from '../../../lib/gramjs';
import type { WebPageMediaSize } from '../../../global/types';
import type { ThreadId } from '../../../types'; import type { ThreadId } from '../../../types';
import type { import type {
ApiAttachment, ApiAttachment,
@ -264,6 +265,8 @@ export function sendMessage(
wasDrafted, wasDrafted,
isInvertedMedia, isInvertedMedia,
effectId, effectId,
webPageMediaSize,
webPageUrl,
}: { }: {
chat: ApiChat; chat: ApiChat;
lastMessageId?: number; lastMessageId?: number;
@ -285,6 +288,8 @@ export function sendMessage(
wasDrafted?: boolean; wasDrafted?: boolean;
isInvertedMedia?: true; isInvertedMedia?: true;
effectId?: string; effectId?: string;
webPageMediaSize?: WebPageMediaSize;
webPageUrl?: string;
}, },
onProgress?: ApiOnProgress, onProgress?: ApiOnProgress,
) { ) {
@ -366,6 +371,12 @@ export function sendMessage(
media = buildInputPoll(poll, randomId); media = buildInputPoll(poll, randomId);
} else if (story) { } else if (story) {
media = buildInputStory(story); media = buildInputStory(story);
} else if (webPageUrl && webPageMediaSize) {
media = new GramJs.InputMediaWebPage({
url: webPageUrl,
forceLargeMedia: webPageMediaSize === 'large' ? true : undefined,
forceSmallMedia: webPageMediaSize === 'small' ? true : undefined,
});
} else if (contact) { } else if (contact) {
media = new GramJs.InputMediaContact({ media = new GramJs.InputMediaContact({
phoneNumber: contact.phoneNumber, phoneNumber: contact.phoneNumber,

View File

@ -1,3 +1,4 @@
import type { WebPageMediaSize } from '../../global/types';
import type { ThreadId } from '../../types'; import type { ThreadId } from '../../types';
import type { ApiWebDocument } from './bots'; import type { ApiWebDocument } from './bots';
import type { ApiGroupCall, PhoneCallAction } from './calls'; import type { ApiGroupCall, PhoneCallAction } from './calls';
@ -476,6 +477,8 @@ export interface ApiWebPage {
video?: ApiVideo; video?: ApiVideo;
story?: ApiWebPageStoryData; story?: ApiWebPageStoryData;
stickers?: ApiWebPageStickerData; stickers?: ApiWebPageStickerData;
mediaSize?: WebPageMediaSize;
hasLargeMedia?: boolean;
} }
export type ApiReplyInfo = ApiMessageReplyInfo | ApiStoryReplyInfo; export type ApiReplyInfo = ApiMessageReplyInfo | ApiStoryReplyInfo;

View File

@ -1063,6 +1063,8 @@ const Composer: FC<OwnProps & StateProps> = ({
shouldUpdateStickerSetOrder, shouldUpdateStickerSetOrder,
isInvertedMedia, isInvertedMedia,
effectId, effectId,
webPageMediaSize: attachmentSettings.webPageMediaSize,
webPageUrl: hasWebPagePreview ? webPagePreview!.url : undefined,
}); });
} }

View File

@ -5,7 +5,7 @@ import { getActions, withGlobal } from '../../../global';
import type { import type {
ApiFormattedText, ApiMessage, ApiMessageEntityTextUrl, ApiWebPage, ApiFormattedText, ApiMessage, ApiMessageEntityTextUrl, ApiWebPage,
} from '../../../api/types'; } from '../../../api/types';
import type { GlobalState } from '../../../global/types'; import type { GlobalState, WebPageMediaSize } from '../../../global/types';
import type { ISettings, ThreadId } from '../../../types'; import type { ISettings, ThreadId } from '../../../types';
import type { Signal } from '../../../util/signals'; import type { Signal } from '../../../util/signals';
import { ApiMessageEntityTypes } from '../../../api/types'; import { ApiMessageEntityTypes } from '../../../api/types';
@ -76,6 +76,7 @@ const WebPagePreview: FC<OwnProps & StateProps> = ({
const ref = useRef<HTMLDivElement>(null); const ref = useRef<HTMLDivElement>(null);
const isInvertedMedia = attachmentSettings.isInvertedMedia; const isInvertedMedia = attachmentSettings.isInvertedMedia;
const isSmallerMedia = attachmentSettings.webPageMediaSize === 'small';
const detectLinkDebounced = useDebouncedResolver(() => { const detectLinkDebounced = useDebouncedResolver(() => {
const formattedText = parseHtmlAsFormattedText(getHtml()); const formattedText = parseHtmlAsFormattedText(getHtml());
@ -112,6 +113,8 @@ const WebPagePreview: FC<OwnProps & StateProps> = ({
}, [isDisabled, getHtml, noWebPage, webPagePreview]); }, [isDisabled, getHtml, noWebPage, webPagePreview]);
const { shouldRender, transitionClassNames } = useShowTransitionDeprecated(isShown); const { shouldRender, transitionClassNames } = useShowTransitionDeprecated(isShown);
const hasMediaSizeOptions = webPagePreview?.hasLargeMedia;
const renderingWebPage = useCurrentOrPrev(webPagePreview, true); const renderingWebPage = useCurrentOrPrev(webPagePreview, true);
const handleClearWebpagePreview = useLastCallback(() => { const handleClearWebpagePreview = useLastCallback(() => {
@ -144,6 +147,10 @@ const WebPagePreview: FC<OwnProps & StateProps> = ({
updateAttachmentSettings({ isInvertedMedia: value }); updateAttachmentSettings({ isInvertedMedia: value });
} }
function updateIsLargerMedia(value?: WebPageMediaSize) {
updateAttachmentSettings({ webPageMediaSize: value });
}
if (!shouldRender || !renderingWebPage) { if (!shouldRender || !renderingWebPage) {
return undefined; return undefined;
} }
@ -183,6 +190,19 @@ const WebPagePreview: FC<OwnProps & StateProps> = ({
</MenuItem> </MenuItem>
) )
} }
{hasMediaSizeOptions && (
isSmallerMedia ? (
// eslint-disable-next-line react/jsx-no-bind
<MenuItem icon="expand" onClick={() => updateIsLargerMedia('large')}>
{lang('ChatInput.EditLink.LargerMedia')}
</MenuItem>
) : (
// eslint-disable-next-line react/jsx-no-bind
<MenuItem icon="collapse" onClick={() => updateIsLargerMedia('small')}>
{lang(('ChatInput.EditLink.SmallerMedia'))}
</MenuItem>
)
)}
<MenuItem <MenuItem
icon="delete" icon="delete"
// eslint-disable-next-line react/jsx-no-bind // eslint-disable-next-line react/jsx-no-bind

View File

@ -205,7 +205,7 @@ const Photo = <T,>({
'media-inner', 'media-inner',
!isUploading && !nonInteractive && 'interactive', !isUploading && !nonInteractive && 'interactive',
isSmall && 'small-image', isSmall && 'small-image',
width === height && 'square-image', (width === height || size === 'pictogram') && 'square-image',
height < MIN_MEDIA_HEIGHT && 'fix-min-height', height < MIN_MEDIA_HEIGHT && 'fix-min-height',
className, className,
); );

View File

@ -157,6 +157,7 @@
margin-bottom: 0 !important; margin-bottom: 0 !important;
img { img {
object-fit: cover;
width: 100%; width: 100%;
height: 100%; height: 100%;
} }

View File

@ -129,6 +129,7 @@ const WebPage: FC<OwnProps> = ({
audio, audio,
type, type,
document, document,
mediaSize,
} = webPage; } = webPage;
const isStory = type === WEBPAGE_STORY_TYPE; const isStory = type === WEBPAGE_STORY_TYPE;
const isExpiredStory = story && 'isDeleted' in story; const isExpiredStory = story && 'isDeleted' in story;
@ -145,7 +146,7 @@ const WebPage: FC<OwnProps> = ({
noAvatars, noAvatars,
isMobile, isMobile,
}); });
isSquarePhoto = width === height; isSquarePhoto = (width === height || mediaSize === 'small') && mediaSize !== 'large';
} }
const isMediaInteractive = (photo || video) && onMediaClick && !isSquarePhoto; const isMediaInteractive = (photo || video) && onMediaClick && !isSquarePhoto;

View File

@ -19,7 +19,7 @@ import type {
import type { MessageKey } from '../../../util/keys/messageKey'; import type { MessageKey } from '../../../util/keys/messageKey';
import type { RequiredGlobalActions } from '../../index'; import type { RequiredGlobalActions } from '../../index';
import type { import type {
ActionReturnType, ApiDraft, GlobalState, TabArgs, ActionReturnType, ApiDraft, GlobalState, TabArgs, WebPageMediaSize,
} from '../../types'; } from '../../types';
import { MAIN_THREAD_ID, MESSAGE_DELETED } from '../../../api/types'; import { MAIN_THREAD_ID, MESSAGE_DELETED } from '../../../api/types';
import { LoadMoreDirection, type ThreadId } from '../../../types'; import { LoadMoreDirection, type ThreadId } from '../../../types';
@ -1455,6 +1455,7 @@ async function sendMessage<T extends GlobalState>(global: T, params: {
lastMessageId?: number; lastMessageId?: number;
isInvertedMedia?: true; isInvertedMedia?: true;
effectId?: string; effectId?: string;
webPageMediaSize?: WebPageMediaSize;
}) { }) {
let currentMessageKey: MessageKey | undefined; let currentMessageKey: MessageKey | undefined;
const progressCallback = params.attachment ? (progress: number, messageKey: MessageKey) => { const progressCallback = params.attachment ? (progress: number, messageKey: MessageKey) => {

View File

@ -491,7 +491,7 @@ addActionHandler('requestConfetti', (global, actions, payload): ActionReturnType
addActionHandler('updateAttachmentSettings', (global, actions, payload): ActionReturnType => { addActionHandler('updateAttachmentSettings', (global, actions, payload): ActionReturnType => {
const { const {
shouldCompress, shouldSendGrouped, isInvertedMedia, shouldCompress, shouldSendGrouped, isInvertedMedia, webPageMediaSize,
} = payload; } = payload;
return { return {
@ -500,6 +500,7 @@ addActionHandler('updateAttachmentSettings', (global, actions, payload): ActionR
shouldCompress: shouldCompress ?? global.attachmentSettings.shouldCompress, shouldCompress: shouldCompress ?? global.attachmentSettings.shouldCompress,
shouldSendGrouped: shouldSendGrouped ?? global.attachmentSettings.shouldSendGrouped, shouldSendGrouped: shouldSendGrouped ?? global.attachmentSettings.shouldSendGrouped,
isInvertedMedia, isInvertedMedia,
webPageMediaSize,
}, },
}; };
}); });

View File

@ -142,6 +142,7 @@ export const INITIAL_GLOBAL_STATE: GlobalState = {
shouldCompress: true, shouldCompress: true,
shouldSendGrouped: true, shouldSendGrouped: true,
isInvertedMedia: undefined, isInvertedMedia: undefined,
webPageMediaSize: undefined,
}, },
scheduledMessages: { scheduledMessages: {

View File

@ -280,6 +280,8 @@ type ConfettiParams = OptionalCombine<{
height?: number; height?: number;
}>; }>;
export type WebPageMediaSize = 'large' | 'small';
export type TabState = { export type TabState = {
id: number; id: number;
isBlurred?: boolean; isBlurred?: boolean;
@ -920,6 +922,7 @@ export type GlobalState = {
shouldCompress: boolean; shouldCompress: boolean;
shouldSendGrouped: boolean; shouldSendGrouped: boolean;
isInvertedMedia?: true; isInvertedMedia?: true;
webPageMediaSize?: WebPageMediaSize;
}; };
attachMenu: { attachMenu: {
@ -1632,6 +1635,8 @@ export interface ActionPayloads {
isReaction?: true; // Reaction to the story are sent in the form of a message isReaction?: true; // Reaction to the story are sent in the form of a message
isInvertedMedia?: true; isInvertedMedia?: true;
effectId?: string; effectId?: string;
webPageMediaSize?: WebPageMediaSize;
webPageUrl?: string;
} & WithTabId; } & WithTabId;
sendInviteMessages: { sendInviteMessages: {
chatId: string; chatId: string;
@ -3189,6 +3194,7 @@ export interface ActionPayloads {
shouldCompress?: boolean; shouldCompress?: boolean;
shouldSendGrouped?: boolean; shouldSendGrouped?: boolean;
isInvertedMedia?: true; isInvertedMedia?: true;
webPageMediaSize?: WebPageMediaSize;
}; };
saveEffectInDraft: { saveEffectInDraft: {