From 85bc6cb2975e65b20913c921c494132b3dee0fb5 Mon Sep 17 00:00:00 2001 From: Alexander Zinchuk Date: Fri, 3 May 2024 14:38:26 +0200 Subject: [PATCH] Web Page: Display stickerset preview (#4529) --- src/api/gramjs/apiBuilders/messageContent.ts | 17 ++++- src/api/types/messages.ts | 3 +- src/api/types/stories.ts | 8 ++- src/components/middle/message/Message.tsx | 3 +- src/components/middle/message/WebPage.scss | 19 ++++- src/components/middle/message/WebPage.tsx | 70 +++++++++++++------ .../middle/message/helpers/webpageType.ts | 2 + src/hooks/useIntersectionObserver.ts | 50 ++++++++++--- 8 files changed, 136 insertions(+), 36 deletions(-) diff --git a/src/api/gramjs/apiBuilders/messageContent.ts b/src/api/gramjs/apiBuilders/messageContent.ts index 49cbb3e38..b9f487625 100644 --- a/src/api/gramjs/apiBuilders/messageContent.ts +++ b/src/api/gramjs/apiBuilders/messageContent.ts @@ -19,6 +19,7 @@ import type { ApiVoice, ApiWebDocument, ApiWebPage, + ApiWebPageStickerData, ApiWebPageStoryData, MediaContent, } from '../../types'; @@ -35,7 +36,7 @@ import { buildApiThumbnailFromStripped, } from './common'; import { buildApiPeerId, getApiChatIdFromMtpPeer } from './peers'; -import { buildStickerFromDocument } from './symbols'; +import { buildStickerFromDocument, processStickerResult } from './symbols'; export function buildMessageContent( mtpMessage: UniversalMessage | GramJs.UpdateServiceNotification, @@ -694,8 +695,9 @@ export function buildWebPage(media: GramJs.TypeMessageMedia): ApiWebPage | undef audio = buildAudioFromDocument(document); } let story: ApiWebPageStoryData | undefined; + let stickers: ApiWebPageStickerData | undefined; const attributeStory = attributes - ?.find((a: any): a is GramJs.WebPageAttributeStory => a instanceof GramJs.WebPageAttributeStory); + ?.find((a): a is GramJs.WebPageAttributeStory => a instanceof GramJs.WebPageAttributeStory); if (attributeStory) { const peerId = getApiChatIdFromMtpPeer(attributeStory.peer); story = { @@ -707,6 +709,16 @@ export function buildWebPage(media: GramJs.TypeMessageMedia): ApiWebPage | undef addStoryToLocalDb(attributeStory.story, peerId); } } + const attributeStickers = attributes?.find((a): a is GramJs.WebPageAttributeStickerSet => ( + a instanceof GramJs.WebPageAttributeStickerSet + )); + if (attributeStickers) { + stickers = { + documents: processStickerResult(attributeStickers.stickers), + isEmoji: attributeStickers.emojis, + isWithTextColor: attributeStickers.textColor, + }; + } return { id: Number(id), @@ -724,6 +736,7 @@ export function buildWebPage(media: GramJs.TypeMessageMedia): ApiWebPage | undef video, audio, story, + stickers, }; } diff --git a/src/api/types/messages.ts b/src/api/types/messages.ts index 9b9da973a..7a2bb97a2 100644 --- a/src/api/types/messages.ts +++ b/src/api/types/messages.ts @@ -3,7 +3,7 @@ import type { ApiWebDocument } from './bots'; import type { ApiGroupCall, PhoneCallAction } from './calls'; import type { ApiChat, ApiPeerColor } from './chats'; import type { ApiInputStorePaymentPurpose, ApiPremiumGiftCodeOption } from './payments'; -import type { ApiMessageStoryData, ApiWebPageStoryData } from './stories'; +import type { ApiMessageStoryData, ApiWebPageStickerData, ApiWebPageStoryData } from './stories'; export interface ApiDimensions { width: number; @@ -380,6 +380,7 @@ export interface ApiWebPage { document?: ApiDocument; video?: ApiVideo; story?: ApiWebPageStoryData; + stickers?: ApiWebPageStickerData; } export type ApiReplyInfo = ApiMessageReplyInfo | ApiStoryReplyInfo; diff --git a/src/api/types/stories.ts b/src/api/types/stories.ts index 02a1eea06..97d7fc2c4 100644 --- a/src/api/types/stories.ts +++ b/src/api/types/stories.ts @@ -1,6 +1,6 @@ import type { ApiPrivacySettings } from '../../types'; import type { - ApiGeoPoint, ApiMessage, ApiReaction, ApiReactionCount, ApiStoryForwardInfo, MediaContent, + ApiGeoPoint, ApiMessage, ApiReaction, ApiReactionCount, ApiSticker, ApiStoryForwardInfo, MediaContent, } from './messages'; export interface ApiStory { @@ -73,6 +73,12 @@ export type ApiWebPageStoryData = { peerId: string; }; +export type ApiWebPageStickerData = { + documents: ApiSticker[]; + isEmoji?: boolean; + isWithTextColor?: boolean; +}; + export type ApiStoryViewPublicForward = { type: 'forward'; peerId: string; diff --git a/src/components/middle/message/Message.tsx b/src/components/middle/message/Message.tsx index 1dbd6d8e8..bca5a36c5 100644 --- a/src/components/middle/message/Message.tsx +++ b/src/components/middle/message/Message.tsx @@ -1230,7 +1230,8 @@ const Message: FC = ({ {webPage && ( = ({ message, - observeIntersection, + observeIntersectionForLoading, + observeIntersectionForPlaying, noAvatars, canAutoLoad, canAutoPlay, @@ -76,6 +82,10 @@ const WebPage: FC = ({ const { openTelegramLink } = getActions(); const webPage = getMessageWebPage(message); const { isMobile } = useAppLayout(); + // eslint-disable-next-line no-null/no-null + const ref = useRef(null); + // eslint-disable-next-line no-null/no-null + const stickersRef = useRef(null); const lang = useLang(); @@ -90,10 +100,13 @@ const WebPage: FC = ({ }); }); - const { story: storyData } = webPage || {}; + const { story: storyData, stickers } = webPage || {}; useEnsureStory(storyData?.peerId, storyData?.id, story); + const hasCustomColor = stickers?.isWithTextColor || stickers?.documents?.[0]?.shouldUseTextColor; + const customColor = useDynamicColorListener(stickersRef, !hasCustomColor); + if (!webPage) { return undefined; } @@ -115,7 +128,7 @@ const WebPage: FC = ({ const quickButtonLangKey = !inPreview && !isExpiredStory ? getWebpageButtonText(type) : undefined; const truncatedDescription = trimText(description, MAX_TEXT_LENGTH); const isArticle = Boolean(truncatedDescription || title || siteName); - let isSquarePhoto = false; + let isSquarePhoto = Boolean(stickers); if (isArticle && webPage?.photo && !webPage.video) { const { width, height } = calculateMediaDimensions(message, undefined, undefined, isMobile); isSquarePhoto = width === height; @@ -149,18 +162,25 @@ const WebPage: FC = ({ return (
+ {backgroundEmojiId && ( + + )} {isStory && ( )} {photo && !video && ( = ({ )} {isArticle && (
- {backgroundEmojiId && ( - - )} {!inPreview && title && (

{renderText(title)}

@@ -193,7 +207,7 @@ const WebPage: FC = ({ {!inPreview && video && (