Introduce WebM stickers; GramJs: Update layer to 138 (#1681)

This commit is contained in:
Alexander Zinchuk 2022-02-02 22:49:44 +01:00
parent 19cb5101da
commit 9456aafc8c
27 changed files with 242 additions and 86 deletions

View File

@ -50,7 +50,7 @@ export function buildApiThumbnailFromCached(photoSize: GramJs.PhotoCachedSize):
export function buildApiThumbnailFromPath(
photoSize: GramJs.PhotoPathSize,
sizeAttribute: GramJs.DocumentAttributeImageSize,
sizeAttribute: GramJs.DocumentAttributeImageSize | GramJs.DocumentAttributeVideo,
): ApiThumbnail | undefined {
const { w, h } = sizeAttribute;
const dataUri = `data:image/svg+xml;utf8,${pathBytesToSvg(photoSize.bytes, w, h)}`;

View File

@ -155,7 +155,7 @@ export function buildApiMessageWithChatId(chatId: string, mtpMessage: UniversalM
const forwardInfo = mtpMessage.fwdFrom && buildApiMessageForwardInfo(mtpMessage.fwdFrom, isChatWithSelf);
const { replies, mediaUnread: isMediaUnread, postAuthor } = mtpMessage;
const groupedId = mtpMessage.groupedId && String(mtpMessage.groupedId);
const isInAlbum = Boolean(groupedId) && !(content.document || content.audio);
const isInAlbum = Boolean(groupedId) && !(content.document || content.audio || content.sticker);
const shouldHideKeyboardButtons = mtpMessage.replyMarkup instanceof GramJs.ReplyKeyboardHide;
return {
@ -192,13 +192,13 @@ export function buildApiMessageWithChatId(chatId: string, mtpMessage: UniversalM
export function buildMessageReactions(reactions: GramJs.MessageReactions): ApiReactions {
const {
recentReactons, results, canSeeList,
recentReactions, results, canSeeList,
} = reactions;
return {
canSeeList,
results: results.map(buildReactionCount),
recentReactions: recentReactons?.map(buildMessageUserReaction),
recentReactions: recentReactions?.map(buildMessagePeerReaction),
};
}
@ -212,11 +212,11 @@ function buildReactionCount(reactionCount: GramJs.ReactionCount): ApiReactionCou
};
}
export function buildMessageUserReaction(userReaction: GramJs.MessageUserReaction): ApiUserReaction {
const { userId, reaction } = userReaction;
export function buildMessagePeerReaction(userReaction: GramJs.MessagePeerReaction): ApiUserReaction {
const { peerId, reaction } = userReaction;
return {
userId: buildApiPeerId(userId, 'user'),
userId: getApiChatIdFromMtpPeer(peerId),
reaction,
};
}

View File

@ -2,12 +2,13 @@ import { Api as GramJs } from '../../../lib/gramjs';
import {
ApiEmojiInteraction, ApiSticker, ApiStickerSet, GramJsEmojiInteraction,
} from '../../types';
import { MEMOJI_STICKER_ID } from '../../../config';
import { NO_STICKER_SET_ID } from '../../../config';
import { buildApiThumbnailFromCached, buildApiThumbnailFromPath } from './common';
import localDb from '../localDb';
const ANIMATED_STICKER_MIME_TYPE = 'application/x-tgsticker';
const LOTTIE_STICKER_MIME_TYPE = 'application/x-tgsticker';
const GIF_STICKER_MIME_TYPE = 'video/webm';
export function buildStickerFromDocument(document: GramJs.TypeDocument): ApiSticker | undefined {
if (document instanceof GramJs.DocumentEmpty) {
@ -19,31 +20,55 @@ export function buildStickerFromDocument(document: GramJs.TypeDocument): ApiStic
attr instanceof GramJs.DocumentAttributeSticker
));
const fileAttribute = document.mimeType === ANIMATED_STICKER_MIME_TYPE && document.attributes
.find((attr: any): attr is GramJs.DocumentAttributeFilename => (
attr instanceof GramJs.DocumentAttributeFilename
));
const fileAttribute = (document.mimeType === LOTTIE_STICKER_MIME_TYPE || document.mimeType === GIF_STICKER_MIME_TYPE)
&& document.attributes
.find((attr: any): attr is GramJs.DocumentAttributeFilename => (
attr instanceof GramJs.DocumentAttributeFilename
));
if (!stickerAttribute && !fileAttribute) {
return undefined;
}
const sizeAttribute = document.attributes
const isLottie = document.mimeType === LOTTIE_STICKER_MIME_TYPE;
const isGif = document.mimeType === GIF_STICKER_MIME_TYPE;
const imageSizeAttribute = document.attributes
.find((attr: any): attr is GramJs.DocumentAttributeImageSize => (
attr instanceof GramJs.DocumentAttributeImageSize
));
const videoSizeAttribute = document.attributes
.find((attr: any): attr is GramJs.DocumentAttributeVideo => (
attr instanceof GramJs.DocumentAttributeVideo
));
const sizeAttribute = imageSizeAttribute || videoSizeAttribute;
const stickerSetInfo = stickerAttribute && stickerAttribute.stickerset instanceof GramJs.InputStickerSetID
? stickerAttribute.stickerset
: undefined;
const emoji = stickerAttribute?.alt;
const isAnimated = document.mimeType === ANIMATED_STICKER_MIME_TYPE;
const cachedThumb = document.thumbs && document.thumbs.find(
(s): s is GramJs.PhotoCachedSize => s instanceof GramJs.PhotoCachedSize,
);
// eslint-disable-next-line no-restricted-globals
if (document.mimeType === GIF_STICKER_MIME_TYPE && !(self as any).isWebmSupported && !cachedThumb) {
const staticThumb = document.thumbs && document.thumbs.find(
(s): s is GramJs.PhotoSize => s instanceof GramJs.PhotoSize,
);
if (!staticThumb) {
return undefined;
}
}
const pathThumb = document.thumbs && document.thumbs.find(
(s): s is GramJs.PhotoPathSize => s instanceof GramJs.PhotoPathSize,
);
const thumbnail = cachedThumb ? (
buildApiThumbnailFromCached(cachedThumb)
) : pathThumb && sizeAttribute ? (
@ -54,10 +79,11 @@ export function buildStickerFromDocument(document: GramJs.TypeDocument): ApiStic
return {
id: String(document.id),
stickerSetId: stickerSetInfo ? String(stickerSetInfo.id) : MEMOJI_STICKER_ID,
stickerSetId: stickerSetInfo ? String(stickerSetInfo.id) : NO_STICKER_SET_ID,
stickerSetAccessHash: stickerSetInfo && String(stickerSetInfo.accessHash),
emoji,
isAnimated,
isLottie,
isGif,
width,
height,
thumbnail,
@ -69,6 +95,7 @@ export function buildStickerSet(set: GramJs.StickerSet): ApiStickerSet {
archived,
animated,
installedDate,
gifs,
id,
accessHash,
title,
@ -79,7 +106,8 @@ export function buildStickerSet(set: GramJs.StickerSet): ApiStickerSet {
return {
archived,
isAnimated: animated,
isLottie: animated,
isGifs: gifs,
installedDate,
id: String(id),
accessHash: String(accessHash),

View File

@ -47,12 +47,14 @@ export async function init(_onUpdate: OnApiUpdate, initialArgs: ApiInitialArgs)
onUpdate = _onUpdate;
const {
userAgent, platform, sessionData, isTest, isMovSupported,
userAgent, platform, sessionData, isTest, isMovSupported, isWebmSupported,
} = initialArgs;
const session = new sessions.CallbackSession(sessionData, onSessionUpdate);
// eslint-disable-next-line no-restricted-globals
(self as any).isMovSupported = isMovSupported;
// eslint-disable-next-line no-restricted-globals
(self as any).isWebmSupported = isWebmSupported;
client = new TelegramClient(
session,

View File

@ -3,7 +3,7 @@ import { invokeRequest } from './client';
import { Api as GramJs } from '../../../lib/gramjs';
import { buildInputPeer } from '../gramjsBuilders';
import localDb from '../localDb';
import { buildApiAvailableReaction, buildMessageUserReaction } from '../apiBuilders/messages';
import { buildApiAvailableReaction, buildMessagePeerReaction } from '../apiBuilders/messages';
import { REACTION_LIST_LIMIT } from '../../../config';
import { addEntitiesWithPhotosToLocalDb } from '../helpers';
import { buildApiUser } from '../apiBuilders/users';
@ -120,7 +120,7 @@ export async function fetchMessageReactionsList({
return {
users: result.users.map(buildApiUser).filter<ApiUser>(Boolean as any),
nextOffset,
reactions: reactions.map(buildMessageUserReaction),
reactions: reactions.map(buildMessagePeerReaction),
count,
};
}

View File

@ -25,7 +25,8 @@ export interface ApiSticker {
stickerSetId: string;
stickerSetAccessHash?: string;
emoji?: string;
isAnimated: boolean;
isLottie: boolean;
isGif: boolean;
width?: number;
height?: number;
thumbnail?: ApiThumbnail;
@ -34,7 +35,8 @@ export interface ApiSticker {
export interface ApiStickerSet {
archived?: true;
isAnimated?: true;
isLottie?: true;
isGifs?: true;
installedDate?: number;
id: string;
accessHash: string;

View File

@ -6,6 +6,7 @@ export interface ApiInitialArgs {
sessionData?: ApiSessionData;
isTest?: boolean;
isMovSupported?: boolean;
isWebmSupported?: boolean;
}
export interface ApiOnProgress {

View File

@ -38,7 +38,7 @@
margin: 0;
}
.AnimatedSticker, img {
.AnimatedSticker, img, video {
position: absolute;
top: 0;
left: 0;
@ -46,7 +46,7 @@
height: 100%;
}
img {
img, video {
object-fit: contain;
}

View File

@ -11,6 +11,8 @@ import useShowTransition from '../../hooks/useShowTransition';
import useFlag from '../../hooks/useFlag';
import buildClassName from '../../util/buildClassName';
import { preventMessageInputBlurWithBubbling } from '../middle/helpers/preventMessageInputBlur';
import safePlay from '../../util/safePlay';
import { IS_WEBM_SUPPORTED } from '../../util/environment';
import AnimatedSticker from './AnimatedSticker';
import Button from '../ui/Button';
@ -44,12 +46,15 @@ const StickerButton: FC<OwnProps> = ({
const previewBlobUrl = useMedia(`${localMediaHash}?size=m`, !isIntersecting, ApiMediaFormat.BlobUrl);
const shouldPlay = isIntersecting && !noAnimate;
const lottieData = useMedia(sticker.isAnimated && localMediaHash, !shouldPlay, ApiMediaFormat.Lottie);
const [isAnimationLoaded, markLoaded, unmarkLoaded] = useFlag(Boolean(lottieData));
const canAnimatedPlay = isAnimationLoaded && shouldPlay;
const lottieData = useMedia(sticker.isLottie && localMediaHash, !shouldPlay, ApiMediaFormat.Lottie);
const [isLottieLoaded, markLoaded, unmarkLoaded] = useFlag(Boolean(lottieData));
const canLottiePlay = isLottieLoaded && shouldPlay;
const isGif = sticker.isGif && IS_WEBM_SUPPORTED;
const gifBlobUrl = useMedia(isGif && localMediaHash, !shouldPlay, ApiMediaFormat.BlobUrl);
const canGifPlay = Boolean(isGif && gifBlobUrl && shouldPlay);
const { transitionClassNames: previewTransitionClassNames } = useShowTransition(
Boolean(previewBlobUrl || canAnimatedPlay),
Boolean(previewBlobUrl || canLottiePlay),
undefined,
undefined,
'slow',
@ -62,6 +67,17 @@ const StickerButton: FC<OwnProps> = ({
}
}, [unmarkLoaded, shouldPlay]);
useEffect(() => {
if (!isGif || !ref.current) return;
const video = ref.current.querySelector('video');
if (!video) return;
if (canGifPlay) {
safePlay(video);
} else {
video.pause();
}
}, [isGif, canGifPlay]);
function handleClick() {
if (onClick) {
onClick(clickArg);
@ -78,12 +94,11 @@ const StickerButton: FC<OwnProps> = ({
const fullClassName = buildClassName(
'StickerButton',
onClick && 'interactive',
sticker.isAnimated && 'animated',
stickerSelector,
className,
);
const style = thumbDataUri && !canAnimatedPlay ? `background-image: url('${thumbDataUri}');` : '';
const style = (thumbDataUri && !canLottiePlay && !canGifPlay) ? `background-image: url('${thumbDataUri}');` : '';
return (
<div
@ -96,10 +111,20 @@ const StickerButton: FC<OwnProps> = ({
onMouseDown={preventMessageInputBlurWithBubbling}
onClick={handleClick}
>
{!canAnimatedPlay && (
{!canLottiePlay && !canGifPlay && (
// eslint-disable-next-line jsx-a11y/alt-text
<img src={previewBlobUrl} className={previewTransitionClassNames} />
)}
{isGif && (
<video
className={previewTransitionClassNames}
src={gifBlobUrl}
autoPlay={canGifPlay}
loop
playsInline
muted
/>
)}
{shouldPlay && lottieData && (
<AnimatedSticker
id={localMediaHash}

View File

@ -47,7 +47,7 @@ const SettingsStickerSet: FC<OwnProps> = ({
color="translucent"
isRtl={lang.isRtl}
>
{stickerSet.isAnimated ? (
{stickerSet.isLottie ? (
<StickerSetCoverAnimated
size={STICKER_SIZE_GENERAL_SETTINGS}
stickerSet={stickerSet}

View File

@ -45,11 +45,13 @@
.sticker-set-button {
display: inline-flex;
vertical-align: middle;
align-items: center;
justify-content: center;
&.StickerButton {
background-size: 2rem;
img, .AnimatedSticker {
video, img, .AnimatedSticker {
top: 0.375rem;
left: 0.375rem;
width: 2rem;
@ -65,7 +67,7 @@
align-items: center;
justify-content: center;
img, .AnimatedSticker {
video, img, .AnimatedSticker {
width: 100%;
height: 100%;
position: absolute;

View File

@ -201,7 +201,7 @@ const StickerPicker: FC<OwnProps & StateProps> = ({
<i className="icon-recent" />
) : stickerSet.id === 'favorite' ? (
<i className="icon-favorite" />
) : stickerSet.isAnimated ? (
) : stickerSet.isLottie ? (
<StickerSetCoverAnimated
stickerSet={stickerSet as ApiStickerSet}
observeIntersection={observeIntersectionForCovers}

View File

@ -4,6 +4,7 @@ import React, {
import { ApiStickerSet } from '../../../api/types';
import { IS_WEBM_SUPPORTED } from '../../../util/environment';
import { getFirstLetters } from '../../../util/textFormat';
import { ObserveFn, useIsIntersecting } from '../../../hooks/useIntersectionObserver';
import useMedia from '../../../hooks/useMedia';
@ -22,17 +23,20 @@ const StickerSetCover: FC<OwnProps> = ({ stickerSet, observeIntersection }) => {
const mediaData = useMedia(stickerSet.hasThumbnail && `stickerSet${stickerSet.id}`, !isIntersecting);
const transitionClassNames = useMediaTransition(mediaData);
const isGif = stickerSet.isGifs;
const firstLetters = useMemo(() => {
if (mediaData) return undefined;
return getFirstLetters(stickerSet.title, 2);
}, [mediaData, stickerSet.title]);
if ((isGif && !IS_WEBM_SUPPORTED) || !mediaData) return getFirstLetters(stickerSet.title, 2);
}, [isGif, mediaData, stickerSet.title]);
return (
<div ref={ref} className="sticker-set-cover">
{firstLetters}
<img src={mediaData} className={transitionClassNames} alt="" />
{isGif ? (
<video src={mediaData} className={transitionClassNames} loop autoPlay />
) : (
<img src={mediaData} className={transitionClassNames} alt="" />
)}
</div>
);
};

View File

@ -1,8 +1,8 @@
import React, { FC, useRef } from '../../../lib/teact/teact';
import React, { FC, useEffect, useRef } from '../../../lib/teact/teact';
import { ApiMessage } from '../../../api/types';
import { MEMOJI_STICKER_ID } from '../../../config';
import { NO_STICKER_SET_ID } from '../../../config';
import { getStickerDimensions } from '../../common/helpers/mediaDimensions';
import { getMessageMediaFormat, getMessageMediaHash } from '../../../modules/helpers';
import buildClassName from '../../../util/buildClassName';
@ -11,6 +11,8 @@ import useMedia from '../../../hooks/useMedia';
import useMediaTransition from '../../../hooks/useMediaTransition';
import useFlag from '../../../hooks/useFlag';
import useWebpThumbnail from '../../../hooks/useWebpThumbnail';
import safePlay from '../../../util/safePlay';
import { IS_WEBM_SUPPORTED } from '../../../util/environment';
import AnimatedSticker from '../../common/AnimatedSticker';
import StickerSetModal from '../../common/StickerSetModal.async';
@ -34,14 +36,20 @@ const Sticker: FC<OwnProps> = ({
const [isModalOpen, openModal, closeModal] = useFlag();
const sticker = message.content.sticker!;
const { isAnimated, stickerSetId } = sticker;
const isMemojiSticker = stickerSetId === MEMOJI_STICKER_ID;
const { isLottie, stickerSetId, isGif } = sticker;
const canDisplayGif = IS_WEBM_SUPPORTED;
const isMemojiSticker = stickerSetId === NO_STICKER_SET_ID;
const shouldLoad = useIsIntersecting(ref, observeIntersection);
const shouldPlay = useIsIntersecting(ref, observeIntersectionForPlaying);
const mediaHash = sticker.isPreloadedGlobally ? `sticker${sticker.id}` : getMessageMediaHash(message, 'inline')!;
const previewMediaHash = isGif && !canDisplayGif && (
sticker.isPreloadedGlobally ? `sticker${sticker.id}?size=m` : getMessageMediaHash(message, 'pictogram'));
const previewBlobUrl = useMedia(previewMediaHash);
const thumbDataUri = useWebpThumbnail(message);
const previewUrl = previewBlobUrl || thumbDataUri;
const mediaData = useMedia(
mediaHash,
!shouldLoad,
@ -50,8 +58,8 @@ const Sticker: FC<OwnProps> = ({
);
const isMediaLoaded = Boolean(mediaData);
const [isAnimationLoaded, markAnimationLoaded] = useFlag(isMediaLoaded);
const isMediaReady = isAnimated ? isAnimationLoaded : isMediaLoaded;
const [isLottieLoaded, markLottieLoaded] = useFlag(isMediaLoaded);
const isMediaReady = isLottie ? isLottieLoaded : isMediaLoaded;
const transitionClassNames = useMediaTransition(isMediaReady);
const { width, height } = getStickerDimensions(sticker);
@ -62,19 +70,30 @@ const Sticker: FC<OwnProps> = ({
isMemojiSticker && 'inactive',
);
useEffect(() => {
if (!isGif || !ref.current) return;
const video = ref.current.querySelector('video');
if (!video) return;
if (shouldPlay) {
safePlay(video);
} else {
video.pause();
}
}, [isGif, shouldPlay]);
return (
<div ref={ref} className={stickerClassName} onClick={!isMemojiSticker ? openModal : undefined}>
{!isMediaReady && (
{(!isMediaReady || (isGif && !canDisplayGif)) && (
<img
id={`sticker-thumb-${message.id}`}
src={thumbDataUri}
src={previewUrl}
width={width}
height={height}
alt=""
className={thumbClassName}
/>
)}
{!isAnimated && (
{!isLottie && !isGif && (
<img
id={`sticker-${message.id}`}
src={mediaData as string}
@ -84,7 +103,19 @@ const Sticker: FC<OwnProps> = ({
className={buildClassName('full-media', transitionClassNames)}
/>
)}
{isAnimated && isMediaLoaded && (
{isGif && canDisplayGif && isMediaReady && (
<video
id={`sticker-${message.id}`}
src={mediaData as string}
width={width}
height={height}
autoPlay={shouldPlay}
playsInline
loop={shouldLoop}
muted
/>
)}
{isLottie && isMediaLoaded && (
<AnimatedSticker
key={mediaHash}
className={buildClassName('full-media', transitionClassNames)}
@ -93,7 +124,7 @@ const Sticker: FC<OwnProps> = ({
size={width}
play={shouldPlay}
noLoop={!shouldLoop}
onLoad={markAnimationLoaded}
onLoad={markLottieLoaded}
/>
)}
<StickerSetModal

View File

@ -126,7 +126,7 @@ export const STICKER_SIZE_INLINE_BOT_RESULT = 100;
export const STICKER_SIZE_JOIN_REQUESTS = 140;
export const STICKER_SIZE_INVITES = 140;
export const RECENT_STICKERS_LIMIT = 20;
export const MEMOJI_STICKER_ID = 'MEMOJI_STICKER';
export const NO_STICKER_SET_ID = 'NO_STICKER_SET';
export const BASE_EMOJI_KEYWORD_LANG = 'en';

View File

@ -1,6 +1,6 @@
const api = require('./api');
const LAYER = 137;
const LAYER = 138;
const tlobjects = {};
for (const tl of Object.values(api)) {

View File

@ -267,8 +267,8 @@ namespace Api {
export type TypeSearchResultsPosition = SearchResultPosition;
export type TypeReactionCount = ReactionCount;
export type TypeMessageReactions = MessageReactions;
export type TypeMessageUserReaction = MessageUserReaction;
export type TypeAvailableReaction = AvailableReaction;
export type TypeMessagePeerReaction = MessagePeerReaction;
export type TypeResPQ = ResPQ;
export type TypeP_Q_inner_data = PQInnerData | PQInnerDataDc | PQInnerDataTemp | PQInnerDataTempDc;
export type TypeServer_DH_Params = ServerDHParamsFail | ServerDHParamsOk;
@ -1655,6 +1655,7 @@ namespace Api {
readOutboxMaxId: int;
unreadCount: int;
unreadMentionsCount: int;
unreadReactionsCount: int;
notifySettings: Api.TypePeerNotifySettings;
pts?: int;
draft?: Api.TypeDraftMessage;
@ -1669,6 +1670,7 @@ namespace Api {
readOutboxMaxId: int;
unreadCount: int;
unreadMentionsCount: int;
unreadReactionsCount: int;
notifySettings: Api.TypePeerNotifySettings;
pts?: int;
draft?: Api.TypeDraftMessage;
@ -3650,6 +3652,7 @@ namespace Api {
official?: true;
masks?: true;
animated?: true;
gifs?: true;
installedDate?: int;
id: long;
accessHash: long;
@ -3666,6 +3669,7 @@ namespace Api {
official?: true;
masks?: true;
animated?: true;
gifs?: true;
installedDate?: int;
id: long;
accessHash: long;
@ -7003,20 +7007,13 @@ namespace Api {
min?: true;
canSeeList?: true;
results: Api.TypeReactionCount[];
recentReactons?: Api.TypeMessageUserReaction[];
recentReactions?: Api.TypeMessagePeerReaction[];
}> {
// flags: undefined;
min?: true;
canSeeList?: true;
results: Api.TypeReactionCount[];
recentReactons?: Api.TypeMessageUserReaction[];
};
export class MessageUserReaction extends VirtualClass<{
userId: long;
reaction: string;
}> {
userId: long;
reaction: string;
recentReactions?: Api.TypeMessagePeerReaction[];
};
export class AvailableReaction extends VirtualClass<{
// flags: undefined;
@ -7043,6 +7040,19 @@ namespace Api {
aroundAnimation?: Api.TypeDocument;
centerIcon?: Api.TypeDocument;
};
export class MessagePeerReaction extends VirtualClass<{
// flags: undefined;
big?: true;
unread?: true;
peerId: Api.TypePeer;
reaction: string;
}> {
// flags: undefined;
big?: true;
unread?: true;
peerId: Api.TypePeer;
reaction: string;
};
export class ResPQ extends VirtualClass<{
nonce: int128;
serverNonce: int128;
@ -8075,13 +8085,15 @@ namespace Api {
export class MessageReactionsList extends VirtualClass<{
// flags: undefined;
count: int;
reactions: Api.TypeMessageUserReaction[];
reactions: Api.TypeMessagePeerReaction[];
chats: Api.TypeChat[];
users: Api.TypeUser[];
nextOffset?: string;
}> {
// flags: undefined;
count: int;
reactions: Api.TypeMessageUserReaction[];
reactions: Api.TypeMessagePeerReaction[];
chats: Api.TypeChat[];
users: Api.TypeUser[];
nextOffset?: string;
};
@ -11224,11 +11236,13 @@ namespace Api {
};
export class SendReaction extends Request<Partial<{
// flags: undefined;
big?: true;
peer: Api.TypeInputPeer;
msgId: int;
reaction?: string;
}>, Api.TypeUpdates> {
// flags: undefined;
big?: true;
peer: Api.TypeInputPeer;
msgId: int;
reaction?: string;
@ -11287,6 +11301,26 @@ namespace Api {
fromLang?: string;
toLang: string;
};
export class GetUnreadReactions extends Request<Partial<{
peer: Api.TypeInputPeer;
offsetId: int;
addOffset: int;
limit: int;
maxId: int;
minId: int;
}>, messages.TypeMessages> {
peer: Api.TypeInputPeer;
offsetId: int;
addOffset: int;
limit: int;
maxId: int;
minId: int;
};
export class ReadReactions extends Request<Partial<{
peer: Api.TypeInputPeer;
}>, messages.TypeAffectedHistory> {
peer: Api.TypeInputPeer;
};
}
export namespace updates {
@ -12359,7 +12393,7 @@ namespace Api {
| account.RegisterDevice | account.UnregisterDevice | account.UpdateNotifySettings | account.GetNotifySettings | account.ResetNotifySettings | account.UpdateProfile | account.UpdateStatus | account.GetWallPapers | account.ReportPeer | account.CheckUsername | account.UpdateUsername | account.GetPrivacy | account.SetPrivacy | account.DeleteAccount | account.GetAccountTTL | account.SetAccountTTL | account.SendChangePhoneCode | account.ChangePhone | account.UpdateDeviceLocked | account.GetAuthorizations | account.ResetAuthorization | account.GetPassword | account.GetPasswordSettings | account.UpdatePasswordSettings | account.SendConfirmPhoneCode | account.ConfirmPhone | account.GetTmpPassword | account.GetWebAuthorizations | account.ResetWebAuthorization | account.ResetWebAuthorizations | account.GetAllSecureValues | account.GetSecureValue | account.SaveSecureValue | account.DeleteSecureValue | account.GetAuthorizationForm | account.AcceptAuthorization | account.SendVerifyPhoneCode | account.VerifyPhone | account.SendVerifyEmailCode | account.VerifyEmail | account.InitTakeoutSession | account.FinishTakeoutSession | account.ConfirmPasswordEmail | account.ResendPasswordEmail | account.CancelPasswordEmail | account.GetContactSignUpNotification | account.SetContactSignUpNotification | account.GetNotifyExceptions | account.GetWallPaper | account.UploadWallPaper | account.SaveWallPaper | account.InstallWallPaper | account.ResetWallPapers | account.GetAutoDownloadSettings | account.SaveAutoDownloadSettings | account.UploadTheme | account.CreateTheme | account.UpdateTheme | account.SaveTheme | account.InstallTheme | account.GetTheme | account.GetThemes | account.SetContentSettings | account.GetContentSettings | account.GetMultiWallPapers | account.GetGlobalPrivacySettings | account.SetGlobalPrivacySettings | account.ReportProfilePhoto | account.ResetPassword | account.DeclinePasswordReset | account.GetChatThemes | account.SetAuthorizationTTL | account.ChangeAuthorizationSettings
| users.GetUsers | users.GetFullUser | users.SetSecureValueErrors
| contacts.GetContactIDs | contacts.GetStatuses | contacts.GetContacts | contacts.ImportContacts | contacts.DeleteContacts | contacts.DeleteByPhones | contacts.Block | contacts.Unblock | contacts.GetBlocked | contacts.Search | contacts.ResolveUsername | contacts.GetTopPeers | contacts.ResetTopPeerRating | contacts.ResetSaved | contacts.GetSaved | contacts.ToggleTopPeers | contacts.AddContact | contacts.AcceptContact | contacts.GetLocated | contacts.BlockFromReplies
| messages.GetMessages | messages.GetDialogs | messages.GetHistory | messages.Search | messages.ReadHistory | messages.DeleteHistory | messages.DeleteMessages | messages.ReceivedMessages | messages.SetTyping | messages.SendMessage | messages.SendMedia | messages.ForwardMessages | messages.ReportSpam | messages.GetPeerSettings | messages.Report | messages.GetChats | messages.GetFullChat | messages.EditChatTitle | messages.EditChatPhoto | messages.AddChatUser | messages.DeleteChatUser | messages.CreateChat | messages.GetDhConfig | messages.RequestEncryption | messages.AcceptEncryption | messages.DiscardEncryption | messages.SetEncryptedTyping | messages.ReadEncryptedHistory | messages.SendEncrypted | messages.SendEncryptedFile | messages.SendEncryptedService | messages.ReceivedQueue | messages.ReportEncryptedSpam | messages.ReadMessageContents | messages.GetStickers | messages.GetAllStickers | messages.GetWebPagePreview | messages.ExportChatInvite | messages.CheckChatInvite | messages.ImportChatInvite | messages.GetStickerSet | messages.InstallStickerSet | messages.UninstallStickerSet | messages.StartBot | messages.GetMessagesViews | messages.EditChatAdmin | messages.MigrateChat | messages.SearchGlobal | messages.ReorderStickerSets | messages.GetDocumentByHash | messages.GetSavedGifs | messages.SaveGif | messages.GetInlineBotResults | messages.SetInlineBotResults | messages.SendInlineBotResult | messages.GetMessageEditData | messages.EditMessage | messages.EditInlineBotMessage | messages.GetBotCallbackAnswer | messages.SetBotCallbackAnswer | messages.GetPeerDialogs | messages.SaveDraft | messages.GetAllDrafts | messages.GetFeaturedStickers | messages.ReadFeaturedStickers | messages.GetRecentStickers | messages.SaveRecentSticker | messages.ClearRecentStickers | messages.GetArchivedStickers | messages.GetMaskStickers | messages.GetAttachedStickers | messages.SetGameScore | messages.SetInlineGameScore | messages.GetGameHighScores | messages.GetInlineGameHighScores | messages.GetCommonChats | messages.GetAllChats | messages.GetWebPage | messages.ToggleDialogPin | messages.ReorderPinnedDialogs | messages.GetPinnedDialogs | messages.SetBotShippingResults | messages.SetBotPrecheckoutResults | messages.UploadMedia | messages.SendScreenshotNotification | messages.GetFavedStickers | messages.FaveSticker | messages.GetUnreadMentions | messages.ReadMentions | messages.GetRecentLocations | messages.SendMultiMedia | messages.UploadEncryptedFile | messages.SearchStickerSets | messages.GetSplitRanges | messages.MarkDialogUnread | messages.GetDialogUnreadMarks | messages.ClearAllDrafts | messages.UpdatePinnedMessage | messages.SendVote | messages.GetPollResults | messages.GetOnlines | messages.EditChatAbout | messages.EditChatDefaultBannedRights | messages.GetEmojiKeywords | messages.GetEmojiKeywordsDifference | messages.GetEmojiKeywordsLanguages | messages.GetEmojiURL | messages.GetSearchCounters | messages.RequestUrlAuth | messages.AcceptUrlAuth | messages.HidePeerSettingsBar | messages.GetScheduledHistory | messages.GetScheduledMessages | messages.SendScheduledMessages | messages.DeleteScheduledMessages | messages.GetPollVotes | messages.ToggleStickerSets | messages.GetDialogFilters | messages.GetSuggestedDialogFilters | messages.UpdateDialogFilter | messages.UpdateDialogFiltersOrder | messages.GetOldFeaturedStickers | messages.GetReplies | messages.GetDiscussionMessage | messages.ReadDiscussion | messages.UnpinAllMessages | messages.DeleteChat | messages.DeletePhoneCallHistory | messages.CheckHistoryImport | messages.InitHistoryImport | messages.UploadImportedMedia | messages.StartHistoryImport | messages.GetExportedChatInvites | messages.GetExportedChatInvite | messages.EditExportedChatInvite | messages.DeleteRevokedExportedChatInvites | messages.DeleteExportedChatInvite | messages.GetAdminsWithInvites | messages.GetChatInviteImporters | messages.SetHistoryTTL | messages.CheckHistoryImportPeer | messages.SetChatTheme | messages.GetMessageReadParticipants | messages.GetSearchResultsCalendar | messages.GetSearchResultsPositions | messages.HideChatJoinRequest | messages.HideAllChatJoinRequests | messages.ToggleNoForwards | messages.SaveDefaultSendAs | messages.SendReaction | messages.GetMessagesReactions | messages.GetMessageReactionsList | messages.SetChatAvailableReactions | messages.GetAvailableReactions | messages.SetDefaultReaction | messages.TranslateText
| messages.GetMessages | messages.GetDialogs | messages.GetHistory | messages.Search | messages.ReadHistory | messages.DeleteHistory | messages.DeleteMessages | messages.ReceivedMessages | messages.SetTyping | messages.SendMessage | messages.SendMedia | messages.ForwardMessages | messages.ReportSpam | messages.GetPeerSettings | messages.Report | messages.GetChats | messages.GetFullChat | messages.EditChatTitle | messages.EditChatPhoto | messages.AddChatUser | messages.DeleteChatUser | messages.CreateChat | messages.GetDhConfig | messages.RequestEncryption | messages.AcceptEncryption | messages.DiscardEncryption | messages.SetEncryptedTyping | messages.ReadEncryptedHistory | messages.SendEncrypted | messages.SendEncryptedFile | messages.SendEncryptedService | messages.ReceivedQueue | messages.ReportEncryptedSpam | messages.ReadMessageContents | messages.GetStickers | messages.GetAllStickers | messages.GetWebPagePreview | messages.ExportChatInvite | messages.CheckChatInvite | messages.ImportChatInvite | messages.GetStickerSet | messages.InstallStickerSet | messages.UninstallStickerSet | messages.StartBot | messages.GetMessagesViews | messages.EditChatAdmin | messages.MigrateChat | messages.SearchGlobal | messages.ReorderStickerSets | messages.GetDocumentByHash | messages.GetSavedGifs | messages.SaveGif | messages.GetInlineBotResults | messages.SetInlineBotResults | messages.SendInlineBotResult | messages.GetMessageEditData | messages.EditMessage | messages.EditInlineBotMessage | messages.GetBotCallbackAnswer | messages.SetBotCallbackAnswer | messages.GetPeerDialogs | messages.SaveDraft | messages.GetAllDrafts | messages.GetFeaturedStickers | messages.ReadFeaturedStickers | messages.GetRecentStickers | messages.SaveRecentSticker | messages.ClearRecentStickers | messages.GetArchivedStickers | messages.GetMaskStickers | messages.GetAttachedStickers | messages.SetGameScore | messages.SetInlineGameScore | messages.GetGameHighScores | messages.GetInlineGameHighScores | messages.GetCommonChats | messages.GetAllChats | messages.GetWebPage | messages.ToggleDialogPin | messages.ReorderPinnedDialogs | messages.GetPinnedDialogs | messages.SetBotShippingResults | messages.SetBotPrecheckoutResults | messages.UploadMedia | messages.SendScreenshotNotification | messages.GetFavedStickers | messages.FaveSticker | messages.GetUnreadMentions | messages.ReadMentions | messages.GetRecentLocations | messages.SendMultiMedia | messages.UploadEncryptedFile | messages.SearchStickerSets | messages.GetSplitRanges | messages.MarkDialogUnread | messages.GetDialogUnreadMarks | messages.ClearAllDrafts | messages.UpdatePinnedMessage | messages.SendVote | messages.GetPollResults | messages.GetOnlines | messages.EditChatAbout | messages.EditChatDefaultBannedRights | messages.GetEmojiKeywords | messages.GetEmojiKeywordsDifference | messages.GetEmojiKeywordsLanguages | messages.GetEmojiURL | messages.GetSearchCounters | messages.RequestUrlAuth | messages.AcceptUrlAuth | messages.HidePeerSettingsBar | messages.GetScheduledHistory | messages.GetScheduledMessages | messages.SendScheduledMessages | messages.DeleteScheduledMessages | messages.GetPollVotes | messages.ToggleStickerSets | messages.GetDialogFilters | messages.GetSuggestedDialogFilters | messages.UpdateDialogFilter | messages.UpdateDialogFiltersOrder | messages.GetOldFeaturedStickers | messages.GetReplies | messages.GetDiscussionMessage | messages.ReadDiscussion | messages.UnpinAllMessages | messages.DeleteChat | messages.DeletePhoneCallHistory | messages.CheckHistoryImport | messages.InitHistoryImport | messages.UploadImportedMedia | messages.StartHistoryImport | messages.GetExportedChatInvites | messages.GetExportedChatInvite | messages.EditExportedChatInvite | messages.DeleteRevokedExportedChatInvites | messages.DeleteExportedChatInvite | messages.GetAdminsWithInvites | messages.GetChatInviteImporters | messages.SetHistoryTTL | messages.CheckHistoryImportPeer | messages.SetChatTheme | messages.GetMessageReadParticipants | messages.GetSearchResultsCalendar | messages.GetSearchResultsPositions | messages.HideChatJoinRequest | messages.HideAllChatJoinRequests | messages.ToggleNoForwards | messages.SaveDefaultSendAs | messages.SendReaction | messages.GetMessagesReactions | messages.GetMessageReactionsList | messages.SetChatAvailableReactions | messages.GetAvailableReactions | messages.SetDefaultReaction | messages.TranslateText | messages.GetUnreadReactions | messages.ReadReactions
| updates.GetState | updates.GetDifference | updates.GetChannelDifference
| photos.UpdateProfilePhoto | photos.UploadProfilePhoto | photos.DeletePhotos | photos.GetUserPhotos
| upload.SaveFilePart | upload.GetFile | upload.SaveBigFilePart | upload.GetWebFile | upload.GetCdnFile | upload.ReuploadCdnFile | upload.GetCdnFileHashes | upload.GetFileHashes

View File

@ -133,7 +133,7 @@ messageActionSetMessagesTTL#aa1afbfd period:int = MessageAction;
messageActionGroupCallScheduled#b3a07661 call:InputGroupCall schedule_date:int = MessageAction;
messageActionSetChatTheme#aa786345 emoticon:string = MessageAction;
messageActionChatJoinedByRequest#ebbca3cb = MessageAction;
dialog#2c171f72 flags:# pinned:flags.2?true unread_mark:flags.3?true peer:Peer top_message:int read_inbox_max_id:int read_outbox_max_id:int unread_count:int unread_mentions_count:int notify_settings:PeerNotifySettings pts:flags.0?int draft:flags.1?DraftMessage folder_id:flags.4?int = Dialog;
dialog#a8edd0f5 flags:# pinned:flags.2?true unread_mark:flags.3?true peer:Peer top_message:int read_inbox_max_id:int read_outbox_max_id:int unread_count:int unread_mentions_count:int unread_reactions_count:int notify_settings:PeerNotifySettings pts:flags.0?int draft:flags.1?DraftMessage folder_id:flags.4?int = Dialog;
dialogFolder#71bd134c flags:# pinned:flags.2?true folder:Folder peer:Peer top_message:int unread_muted_peers_count:int unread_unmuted_peers_count:int unread_muted_messages_count:int unread_unmuted_messages_count:int = Dialog;
photoEmpty#2331b22d id:long = Photo;
photo#fb197a65 flags:# has_stickers:flags.0?true id:long access_hash:long file_reference:bytes date:int sizes:Vector<PhotoSize> video_sizes:flags.1?Vector<VideoSize> dc_id:int = Photo;
@ -436,7 +436,7 @@ inputStickerSetShortName#861cc8a0 short_name:string = InputStickerSet;
inputStickerSetAnimatedEmoji#28703c8 = InputStickerSet;
inputStickerSetDice#e67f520e emoticon:string = InputStickerSet;
inputStickerSetAnimatedEmojiAnimations#cde3739 = InputStickerSet;
stickerSet#d7df217a flags:# archived:flags.1?true official:flags.2?true masks:flags.3?true animated:flags.5?true installed_date:flags.0?int id:long access_hash:long title:string short_name:string thumbs:flags.4?Vector<PhotoSize> thumb_dc_id:flags.4?int thumb_version:flags.4?int count:int hash:int = StickerSet;
stickerSet#d7df217a flags:# archived:flags.1?true official:flags.2?true masks:flags.3?true animated:flags.5?true gifs:flags.6?true installed_date:flags.0?int id:long access_hash:long title:string short_name:string thumbs:flags.4?Vector<PhotoSize> thumb_dc_id:flags.4?int thumb_version:flags.4?int count:int hash:int = StickerSet;
messages.stickerSet#b60a24a6 set:StickerSet packs:Vector<StickerPack> documents:Vector<Document> = messages.StickerSet;
messages.stickerSetNotModified#d3f924eb = messages.StickerSet;
botCommand#c27ac8c7 command:string description:string = BotCommand;
@ -944,14 +944,14 @@ users.userFull#3b6d152e full_user:UserFull chats:Vector<Chat> users:Vector<User>
messages.peerSettings#6880b94d settings:PeerSettings chats:Vector<Chat> users:Vector<User> = messages.PeerSettings;
auth.loggedOut#c3a2835f flags:# future_auth_token:flags.0?bytes = auth.LoggedOut;
reactionCount#6fb250d1 flags:# chosen:flags.0?true reaction:string count:int = ReactionCount;
messageReactions#87b6e36 flags:# min:flags.0?true can_see_list:flags.2?true results:Vector<ReactionCount> recent_reactons:flags.1?Vector<MessageUserReaction> = MessageReactions;
messageUserReaction#932844fa user_id:long reaction:string = MessageUserReaction;
messages.messageReactionsList#a366923c flags:# count:int reactions:Vector<MessageUserReaction> users:Vector<User> next_offset:flags.0?string = messages.MessageReactionsList;
messageReactions#4f2b9479 flags:# min:flags.0?true can_see_list:flags.2?true results:Vector<ReactionCount> recent_reactions:flags.1?Vector<MessagePeerReaction> = MessageReactions;
messages.messageReactionsList#31bd492d flags:# count:int reactions:Vector<MessagePeerReaction> chats:Vector<Chat> users:Vector<User> next_offset:flags.0?string = messages.MessageReactionsList;
availableReaction#c077ec01 flags:# inactive:flags.0?true reaction:string title:string static_icon:Document appear_animation:Document select_animation:Document activate_animation:Document effect_animation:Document around_animation:flags.1?Document center_icon:flags.1?Document = AvailableReaction;
messages.availableReactionsNotModified#9f071957 = messages.AvailableReactions;
messages.availableReactions#768e3aad hash:int reactions:Vector<AvailableReaction> = messages.AvailableReactions;
messages.translateNoResult#67ca4737 = messages.TranslatedText;
messages.translateResultText#a214f7d0 text:string = messages.TranslatedText;
messagePeerReaction#51b67eff flags:# big:flags.0?true unread:flags.1?true peer_id:Peer reaction:string = MessagePeerReaction;
---functions---
initConnection#c1cd5ea9 {X:Type} flags:# api_id:int device_model:string system_version:string app_version:string system_lang_code:string lang_pack:string lang_code:string proxy:flags.0?InputClientProxy params:flags.1?JSONValue query:!X = X;
invokeWithLayer#da9b0d0d {X:Type} layer:int query:!X = X;
@ -1092,7 +1092,7 @@ messages.hideChatJoinRequest#7fe7e815 flags:# approved:flags.0?true peer:InputPe
messages.hideAllChatJoinRequests#e085f4ea flags:# approved:flags.0?true peer:InputPeer link:flags.1?string = Updates;
messages.toggleNoForwards#b11eafa2 peer:InputPeer enabled:Bool = Updates;
messages.saveDefaultSendAs#ccfddf96 peer:InputPeer send_as:InputPeer = Bool;
messages.sendReaction#25690ce4 flags:# peer:InputPeer msg_id:int reaction:flags.0?string = Updates;
messages.sendReaction#25690ce4 flags:# big:flags.1?true peer:InputPeer msg_id:int reaction:flags.0?string = Updates;
messages.getMessagesReactions#8bba90e6 peer:InputPeer id:Vector<int> = Updates;
messages.getMessageReactionsList#e0ee6b77 flags:# peer:InputPeer id:int reaction:flags.0?string offset:flags.1?string limit:int = messages.MessageReactionsList;
messages.setChatAvailableReactions#14050ea6 peer:InputPeer available_reactions:Vector<string> = Updates;

View File

@ -190,7 +190,7 @@ messageActionGroupCallScheduled#b3a07661 call:InputGroupCall schedule_date:int =
messageActionSetChatTheme#aa786345 emoticon:string = MessageAction;
messageActionChatJoinedByRequest#ebbca3cb = MessageAction;
dialog#2c171f72 flags:# pinned:flags.2?true unread_mark:flags.3?true peer:Peer top_message:int read_inbox_max_id:int read_outbox_max_id:int unread_count:int unread_mentions_count:int notify_settings:PeerNotifySettings pts:flags.0?int draft:flags.1?DraftMessage folder_id:flags.4?int = Dialog;
dialog#a8edd0f5 flags:# pinned:flags.2?true unread_mark:flags.3?true peer:Peer top_message:int read_inbox_max_id:int read_outbox_max_id:int unread_count:int unread_mentions_count:int unread_reactions_count:int notify_settings:PeerNotifySettings pts:flags.0?int draft:flags.1?DraftMessage folder_id:flags.4?int = Dialog;
dialogFolder#71bd134c flags:# pinned:flags.2?true folder:Folder peer:Peer top_message:int unread_muted_peers_count:int unread_unmuted_peers_count:int unread_muted_messages_count:int unread_unmuted_messages_count:int = Dialog;
photoEmpty#2331b22d id:long = Photo;
@ -566,7 +566,7 @@ inputStickerSetAnimatedEmoji#28703c8 = InputStickerSet;
inputStickerSetDice#e67f520e emoticon:string = InputStickerSet;
inputStickerSetAnimatedEmojiAnimations#cde3739 = InputStickerSet;
stickerSet#d7df217a flags:# archived:flags.1?true official:flags.2?true masks:flags.3?true animated:flags.5?true installed_date:flags.0?int id:long access_hash:long title:string short_name:string thumbs:flags.4?Vector<PhotoSize> thumb_dc_id:flags.4?int thumb_version:flags.4?int count:int hash:int = StickerSet;
stickerSet#d7df217a flags:# archived:flags.1?true official:flags.2?true masks:flags.3?true animated:flags.5?true gifs:flags.6?true installed_date:flags.0?int id:long access_hash:long title:string short_name:string thumbs:flags.4?Vector<PhotoSize> thumb_dc_id:flags.4?int thumb_version:flags.4?int count:int hash:int = StickerSet;
messages.stickerSet#b60a24a6 set:StickerSet packs:Vector<StickerPack> documents:Vector<Document> = messages.StickerSet;
messages.stickerSetNotModified#d3f924eb = messages.StickerSet;
@ -1307,11 +1307,9 @@ auth.loggedOut#c3a2835f flags:# future_auth_token:flags.0?bytes = auth.LoggedOut
reactionCount#6fb250d1 flags:# chosen:flags.0?true reaction:string count:int = ReactionCount;
messageReactions#87b6e36 flags:# min:flags.0?true can_see_list:flags.2?true results:Vector<ReactionCount> recent_reactons:flags.1?Vector<MessageUserReaction> = MessageReactions;
messageReactions#4f2b9479 flags:# min:flags.0?true can_see_list:flags.2?true results:Vector<ReactionCount> recent_reactions:flags.1?Vector<MessagePeerReaction> = MessageReactions;
messageUserReaction#932844fa user_id:long reaction:string = MessageUserReaction;
messages.messageReactionsList#a366923c flags:# count:int reactions:Vector<MessageUserReaction> users:Vector<User> next_offset:flags.0?string = messages.MessageReactionsList;
messages.messageReactionsList#31bd492d flags:# count:int reactions:Vector<MessagePeerReaction> chats:Vector<Chat> users:Vector<User> next_offset:flags.0?string = messages.MessageReactionsList;
availableReaction#c077ec01 flags:# inactive:flags.0?true reaction:string title:string static_icon:Document appear_animation:Document select_animation:Document activate_animation:Document effect_animation:Document around_animation:flags.1?Document center_icon:flags.1?Document = AvailableReaction;
@ -1321,6 +1319,8 @@ messages.availableReactions#768e3aad hash:int reactions:Vector<AvailableReaction
messages.translateNoResult#67ca4737 = messages.TranslatedText;
messages.translateResultText#a214f7d0 text:string = messages.TranslatedText;
messagePeerReaction#51b67eff flags:# big:flags.0?true unread:flags.1?true peer_id:Peer reaction:string = MessagePeerReaction;
---functions---
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
@ -1599,13 +1599,15 @@ messages.hideChatJoinRequest#7fe7e815 flags:# approved:flags.0?true peer:InputPe
messages.hideAllChatJoinRequests#e085f4ea flags:# approved:flags.0?true peer:InputPeer link:flags.1?string = Updates;
messages.toggleNoForwards#b11eafa2 peer:InputPeer enabled:Bool = Updates;
messages.saveDefaultSendAs#ccfddf96 peer:InputPeer send_as:InputPeer = Bool;
messages.sendReaction#25690ce4 flags:# peer:InputPeer msg_id:int reaction:flags.0?string = Updates;
messages.sendReaction#25690ce4 flags:# big:flags.1?true peer:InputPeer msg_id:int reaction:flags.0?string = Updates;
messages.getMessagesReactions#8bba90e6 peer:InputPeer id:Vector<int> = Updates;
messages.getMessageReactionsList#e0ee6b77 flags:# peer:InputPeer id:int reaction:flags.0?string offset:flags.1?string limit:int = messages.MessageReactionsList;
messages.setChatAvailableReactions#14050ea6 peer:InputPeer available_reactions:Vector<string> = Updates;
messages.getAvailableReactions#18dea0ac hash:int = messages.AvailableReactions;
messages.setDefaultReaction#d960c4d4 reaction:string = Bool;
messages.translateText#24ce6dee flags:# peer:flags.0?InputPeer msg_id:flags.0?int text:flags.1?string from_lang:flags.2?string to_lang:string = messages.TranslatedText;
messages.getUnreadReactions#e85bae1a peer:InputPeer offset_id:int add_offset:int limit:int max_id:int min_id:int = messages.Messages;
messages.readReactions#82e251d7 peer:InputPeer = messages.AffectedHistory;
updates.getState#edd4882a = updates.State;
updates.getDifference#25939651 flags:# pts:int pts_total_limit:flags.0?int date:int qts:int = updates.Difference;
@ -1754,4 +1756,4 @@ stats.getMegagroupStats#dcdf8607 flags:# dark:flags.0?true channel:InputChannel
stats.getMessagePublicForwards#5630281b channel:InputChannel msg_id:int offset_rate:int offset_peer:InputPeer offset_id:int limit:int = messages.Messages;
stats.getMessageStats#b6e0a3f5 flags:# dark:flags.0?true channel:InputChannel msg_id:int = stats.MessageStats;
// LAYER 137
// LAYER 138

View File

@ -13,7 +13,7 @@ import {
MEDIA_PROGRESSIVE_CACHE_NAME,
IS_TEST,
} from '../../../config';
import { IS_MOV_SUPPORTED, PLATFORM_ENV } from '../../../util/environment';
import { IS_MOV_SUPPORTED, IS_WEBM_SUPPORTED, PLATFORM_ENV } from '../../../util/environment';
import { unsubscribe } from '../../../util/notifications';
import * as cacheApi from '../../../util/cacheApi';
import { updateAppBadge } from '../../../util/appBadge';
@ -39,6 +39,7 @@ addReducer('initApi', (global: GlobalState, actions) => {
sessionData: loadStoredSession(),
isTest: window.location.search.includes('test'),
isMovSupported: IS_MOV_SUPPORTED,
isWebmSupported: IS_WEBM_SUPPORTED,
});
})();
});

View File

@ -27,13 +27,18 @@ addReducer('loadStickerSets', (global) => {
addReducer('loadAddedStickers', (global, actions) => {
const { setIds: addedSetIds } = global.stickers.added;
const cached = global.stickers.setsById;
if (!addedSetIds || !addedSetIds.length) {
return;
}
(async () => {
for (let i = 0; i < addedSetIds.length; i++) {
actions.loadStickers({ stickerSetId: addedSetIds[i] });
const id = addedSetIds[i];
if (cached[id].stickers) {
continue; // Already loaded
}
actions.loadStickers({ stickerSetId: id });
if (i % ADDED_SETS_THROTTLE_CHUNK === 0 && i > 0) {
await pause(ADDED_SETS_THROTTLE);

View File

@ -252,7 +252,7 @@ export function getMessageMediaFormat(
const fullVideo = video || getMessageWebPageVideo(message);
if (sticker && target === 'inline' && sticker.isAnimated) {
if (sticker && target === 'inline' && sticker.isLottie) {
return ApiMediaFormat.Lottie;
} else if (fullVideo && IS_PROGRESSIVE_SUPPORTED && (
target === 'viewerFull' || target === 'inline'

View File

@ -190,7 +190,8 @@ export function getMessageContentFilename(message: ApiMessage) {
}
if (content.sticker) {
const extension = content.sticker.isAnimated ? 'tgs' : isWebpSupported() ? 'webp' : 'png';
const extension = content.sticker.isLottie ? 'tgs' : content.sticker.isGif
? 'webm' : isWebpSupported() ? 'webp' : 'png';
return `${content.sticker.id}.${extension}`;
}

View File

@ -47,11 +47,24 @@ export function updateStickerSet(
global: GlobalState, stickerSetId: string, update: Partial<ApiStickerSet>,
): GlobalState {
const currentStickerSet = global.stickers.setsById[stickerSetId] || {};
const addedSets = global.stickers.added.setIds || [];
let setIds: string[] = addedSets;
if (update.installedDate && addedSets && !addedSets.includes(stickerSetId)) {
setIds = [stickerSetId, ...setIds];
}
if (!update.installedDate && addedSets?.includes(stickerSetId)) {
setIds = setIds.filter((id) => id !== stickerSetId);
}
return {
...global,
stickers: {
...global.stickers,
added: {
...global.stickers.added,
setIds,
},
setsById: {
...global.stickers.setsById,
[stickerSetId]: {

View File

@ -208,7 +208,7 @@ export enum SettingsScreens {
}
export type StickerSetOrRecent = Pick<ApiStickerSet, (
'id' | 'title' | 'count' | 'stickers' | 'hasThumbnail' | 'isAnimated'
'id' | 'title' | 'count' | 'stickers' | 'hasThumbnail' | 'isLottie' | 'isGifs'
)>;
export enum LeftColumnContent {

View File

@ -73,11 +73,15 @@ export const IS_REQUEST_FULLSCREEN_SUPPORTED = 'requestFullscreen' in document.c
export const ARE_CALLS_SUPPORTED = !navigator.userAgent.includes('Firefox');
export const LAYERS_ANIMATION_NAME = IS_ANDROID ? 'slide-fade' : IS_IOS ? 'slide-layers' : 'push-slide';
const TEST_VIDEO = document.createElement('video');
// `canPlayType(VIDEO_MOV_TYPE)` returns false negative at least for macOS Chrome and iOS Safari
export const IS_MOV_SUPPORTED = true;
if (IS_MOV_SUPPORTED) SUPPORTED_VIDEO_CONTENT_TYPES.add(VIDEO_MOV_TYPE);
export const IS_WEBM_SUPPORTED = Boolean(TEST_VIDEO.canPlayType('video/webm; codecs="vp9"').replace('no', ''))
&& !(IS_MAC_OS && IS_SAFARI); // Safari on MacOS has some issues with WebM
export const DPR = window.devicePixelRatio || 1;
export const MASK_IMAGE_DISABLED = true;

View File

@ -22,6 +22,7 @@ module.exports = (env = {}, argv = {}) => {
port: 1234,
host: '0.0.0.0',
allowedHosts: "all",
hot: false,
static: [
{
directory: path.resolve(__dirname, 'public'),