diff --git a/src/api/gramjs/apiBuilders/appConfig.ts b/src/api/gramjs/apiBuilders/appConfig.ts index b2e247e00..5eafc874e 100644 --- a/src/api/gramjs/apiBuilders/appConfig.ts +++ b/src/api/gramjs/apiBuilders/appConfig.ts @@ -94,6 +94,7 @@ export interface GramJsAppConfig extends LimitsConfig { freeze_since_date?: number; freeze_until_date?: number; freeze_appeal_url?: string; + channel_autotranslation_level_min?: number; stars_stargift_resale_amount_max?: number; stars_stargift_resale_amount_min?: number; stars_stargift_resale_commission_permille?: number; @@ -182,6 +183,7 @@ export function buildAppConfig(json: GramJs.TypeJSONValue, hash: number): ApiApp bandwidthPremiumUploadSpeedup: appConfig.upload_premium_speedup_upload, bandwidthPremiumDownloadSpeedup: appConfig.upload_premium_speedup_download, channelRestrictAdsLevelMin: appConfig.channel_restrict_sponsored_level_min, + channelAutoTranslationLevelMin: appConfig.channel_autotranslation_level_min, paidReactionMaxAmount: appConfig.stars_paid_reaction_amount_max, isChannelRevenueWithdrawalEnabled: appConfig.channel_revenue_withdrawal_enabled, isStarsGiftEnabled: appConfig.stars_gifts_enabled, diff --git a/src/api/gramjs/apiBuilders/chats.ts b/src/api/gramjs/apiBuilders/chats.ts index 5c5f66c21..d466f1ced 100644 --- a/src/api/gramjs/apiBuilders/chats.ts +++ b/src/api/gramjs/apiBuilders/chats.ts @@ -119,6 +119,8 @@ function buildApiChatFieldsFromPeerEntity( hasGeo: channel?.hasGeo, subscriptionUntil: channel?.subscriptionUntilDate, paidMessagesStars: paidMessagesStars?.toJSNumber(), + level: channel?.level, + hasAutoTranslation: channel?.autotranslation, ...buildApiChatPermissions(peerEntity), ...buildApiChatRestrictions(peerEntity), diff --git a/src/api/gramjs/methods/chats.ts b/src/api/gramjs/methods/chats.ts index 6ee05d36b..124d00bcb 100644 --- a/src/api/gramjs/methods/chats.ts +++ b/src/api/gramjs/methods/chats.ts @@ -2087,3 +2087,16 @@ export async function fetchSponsoredPeer({ query }: { query: string }) { if (!result || result instanceof GramJs.contacts.SponsoredPeersEmpty) return undefined; return buildApiSponsoredPeer(result.peers[0]); } + +export function toggleAutoTranslation({ + chat, isEnabled, +}: { + chat: ApiChat; isEnabled: boolean; +}) { + return invokeRequest(new GramJs.channels.ToggleAutotranslation({ + channel: buildInputChannel(chat.id, chat.accessHash), + enabled: isEnabled, + }), { + shouldReturnTrue: true, + }); +} diff --git a/src/api/types/chats.ts b/src/api/types/chats.ts index 9f52657ea..d0ab69dac 100644 --- a/src/api/types/chats.ts +++ b/src/api/types/chats.ts @@ -49,6 +49,8 @@ export interface ApiChat { isForumAsMessages?: true; boostLevel?: number; botVerificationIconId?: string; + hasAutoTranslation?: true; + level?: number; // Calls isCallActive?: boolean; diff --git a/src/api/types/misc.ts b/src/api/types/misc.ts index 08d98c0d5..031c8cf45 100644 --- a/src/api/types/misc.ts +++ b/src/api/types/misc.ts @@ -235,6 +235,7 @@ export interface ApiAppConfig { bandwidthPremiumUploadSpeedup?: number; bandwidthPremiumDownloadSpeedup?: number; channelRestrictAdsLevelMin?: number; + channelAutoTranslationLevelMin?: number; paidReactionMaxAmount?: number; isChannelRevenueWithdrawalEnabled?: boolean; isStarsGiftEnabled?: boolean; diff --git a/src/assets/localization/fallback.strings b/src/assets/localization/fallback.strings index 87a987612..1ea96ca99 100644 --- a/src/assets/localization/fallback.strings +++ b/src/assets/localization/fallback.strings @@ -2007,4 +2007,5 @@ "ValueGiftSortByPrice" = "Price"; "ValueGiftSortByNumber" = "Number"; "ResellGiftsNoFound" = "No gifts found"; -"ResellGiftsClearFilters" = "Clear Filters"; \ No newline at end of file +"ResellGiftsClearFilters" = "Clear Filters"; +"AutomaticTranslation" = "Automatic Translation"; diff --git a/src/components/middle/HeaderActions.tsx b/src/components/middle/HeaderActions.tsx index 9d80442e9..500d47ed0 100644 --- a/src/components/middle/HeaderActions.tsx +++ b/src/components/middle/HeaderActions.tsx @@ -1,6 +1,6 @@ import type { FC } from '../../lib/teact/teact'; import { - memo, useMemo, useRef, useState, + memo, useCallback, useMemo, useRef, useState, } from '../../lib/teact/teact'; import { getActions, withGlobal } from '../../global'; @@ -123,8 +123,8 @@ const HeaderActions: FC = ({ language, detectedChatLanguage, doNotTranslate, - onTopicSearch, isAccountFrozen, + onTopicSearch, }) => { const { joinChannel, @@ -239,7 +239,7 @@ const HeaderActions: FC = ({ handleSearchClick(); }); - const getTextWithLanguage = useLastCallback((langKey: string, langCode: string) => { + const getTextWithLanguage = useCallback((langKey: string, langCode: string) => { const simplified = langCode.split('-')[0]; const translationKey = `TranslateLanguage${simplified.toUpperCase()}`; const name = lang(translationKey); @@ -250,7 +250,7 @@ const HeaderActions: FC = ({ const translatedNames = new Intl.DisplayNames([language], { type: 'language' }); const translatedName = translatedNames.of(langCode)!; return lang(`${langKey}Other`, translatedName); - }); + }, [language, lang]); const buttonText = useMemo(() => { if (isTranslating) return lang('ShowOriginalButton'); diff --git a/src/components/middle/MessageList.tsx b/src/components/middle/MessageList.tsx index 7489dc4da..68b99993f 100644 --- a/src/components/middle/MessageList.tsx +++ b/src/components/middle/MessageList.tsx @@ -32,6 +32,7 @@ import { } from '../../global/helpers'; import { selectBot, + selectCanTranslateChat, selectChat, selectChatFullInfo, selectChatLastMessage, @@ -52,6 +53,7 @@ import { selectTabState, selectThreadInfo, selectTopic, + selectTranslationLanguage, selectUserFullInfo, } from '../../global/selectors'; import animateScroll, { isAnimatingScroll, restartCurrentScrollAnimation } from '../../util/animateScroll'; @@ -92,13 +94,13 @@ type OwnProps = { isComments?: boolean; canPost: boolean; isReady: boolean; - onScrollDownToggle: BooleanToVoidFunction; - onNotchToggle: BooleanToVoidFunction; withBottomShift?: boolean; withDefaultBg: boolean; - onIntersectPinnedMessage: OnIntersectPinnedMessage; isContactRequirePremium?: boolean; paidMessagesStars?: number; + onScrollDownToggle: BooleanToVoidFunction; + onNotchToggle: BooleanToVoidFunction; + onIntersectPinnedMessage: OnIntersectPinnedMessage; }; type StateProps = { @@ -137,6 +139,9 @@ type StateProps = { isChatProtected?: boolean; hasCustomGreeting?: boolean; isAppConfigLoaded?: boolean; + canTranslate?: boolean; + translationLanguage?: string; + shouldAutoTranslate?: boolean; }; const MESSAGE_REACTIONS_POLLING_INTERVAL = 20 * 1000; @@ -196,16 +201,19 @@ const MessageList: FC = ({ areAdsEnabled, channelJoinInfo, isChatProtected, - onIntersectPinnedMessage, - onScrollDownToggle, - onNotchToggle, isAccountFrozen, hasCustomGreeting, isAppConfigLoaded, + canTranslate, + translationLanguage, + shouldAutoTranslate, + onIntersectPinnedMessage, + onScrollDownToggle, + onNotchToggle, }) => { const { loadViewportMessages, setScrollOffset, loadSponsoredMessages, loadMessageReactions, copyMessagesByIds, - loadMessageViews, loadPeerStoriesByIds, loadFactChecks, + loadMessageViews, loadPeerStoriesByIds, loadFactChecks, requestChatTranslation, } = getActions(); const containerRef = useRef(); @@ -268,6 +276,12 @@ const MessageList: FC = ({ memoFocusingIdRef.current = focusingId; }, [focusingId]); + // Enable auto translation for the chat if it's available + useEffect(() => { + if (!shouldAutoTranslate || !canTranslate) return; + requestChatTranslation({ chatId, toLanguageCode: translationLanguage }); + }, [shouldAutoTranslate, canTranslate, translationLanguage, chatId]); + useNativeCopySelectedMessages(copyMessagesByIds); const messageGroups = useMemo(() => { @@ -806,6 +820,10 @@ export default memo(withGlobal( const hasCustomGreeting = Boolean(userFullInfo?.businessIntro); const isAppConfigLoaded = global.isAppConfigLoaded; + const canTranslate = selectCanTranslateChat(global, chatId) && !chatFullInfo?.isTranslationDisabled; + const shouldAutoTranslate = chat?.hasAutoTranslation; + const translationLanguage = selectTranslationLanguage(global); + return { areAdsEnabled, isChatLoaded: true, @@ -842,6 +860,9 @@ export default memo(withGlobal( isAccountFrozen, hasCustomGreeting, isAppConfigLoaded, + canTranslate, + translationLanguage, + shouldAutoTranslate, }; }, )(MessageList)); diff --git a/src/components/middle/message/Message.tsx b/src/components/middle/message/Message.tsx index 7a02bcfca..cf11d2d45 100644 --- a/src/components/middle/message/Message.tsx +++ b/src/components/middle/message/Message.tsx @@ -747,7 +747,7 @@ const Message: FC = ({ const detectedLanguage = useTextLanguage( text?.text, - !(areTranslationsEnabled || shouldDetectChatLanguage), + !(areTranslationsEnabled && shouldDetectChatLanguage), getIsMessageListReady, ); useDetectChatLanguage(message, detectedLanguage, !shouldDetectChatLanguage, getIsMessageListReady); diff --git a/src/components/middle/message/hooks/useDetectChatLanguage.ts b/src/components/middle/message/hooks/useDetectChatLanguage.ts index 9a9bd9550..49fd28f61 100644 --- a/src/components/middle/message/hooks/useDetectChatLanguage.ts +++ b/src/components/middle/message/hooks/useDetectChatLanguage.ts @@ -30,13 +30,25 @@ export default function useDetectChatLanguage( if (isDisabled || (getIsReady && !getIsReady())) return; const isTranslatable = Boolean(message.content.text?.text.length); - processMessageMetadata(message.chatId, message.id, isTranslatable, detectedLanguage); + processMessageMetadata({ + chatId: message.chatId, + id: message.id, + isTranslatable, + detectedLanguage, + }); }, [message, detectedLanguage, isDisabled, getIsReady]); } const throttledMakeChatDecision = throttle(makeChatDecision, THROTTLE_DELAY); -function processMessageMetadata(chatId: string, id: number, isTranslatable: boolean, detectedLanguage?: string) { +function processMessageMetadata({ + chatId, id, isTranslatable, detectedLanguage, +}: { + chatId: string; + id: number; + isTranslatable: boolean; + detectedLanguage?: string; +}) { const chatStats = CHAT_STATS.get(chatId) || new LimitedMap(MESSAGES_LIMIT); const previousMetadata = chatStats.get(id); @@ -90,7 +102,7 @@ function makeChatDecision(chatId: string) { } const translatableRatio = translatableCount / messagesChecked; - const detectableRatio = detectableCount / messagesChecked; + const detectableRatio = detectableCount / translatableCount; if (translatableRatio < MIN_TRANSLATABLE_RATIO || detectableRatio < MIN_DETECTABLE_RATIO) { return; diff --git a/src/components/right/management/ManageChannel.tsx b/src/components/right/management/ManageChannel.tsx index f1afea992..20ffdd04e 100644 --- a/src/components/right/management/ManageChannel.tsx +++ b/src/components/right/management/ManageChannel.tsx @@ -1,7 +1,7 @@ import type { ChangeEvent } from 'react'; import type { FC } from '../../../lib/teact/teact'; import { - memo, useCallback, useEffect, useMemo, useState, + memo, useEffect, useMemo, useState, } from '../../../lib/teact/teact'; import { getActions, withGlobal } from '../../../global'; @@ -11,12 +11,13 @@ import type { import { ApiMediaFormat } from '../../../api/types'; import { ManagementProgress, ManagementScreens } from '../../../types'; -import { getChatAvatarHash, getHasAdminRight, isChatPublic } from '../../../global/helpers'; +import { getChatAvatarHash, getHasAdminRight, isChatChannel, isChatPublic } from '../../../global/helpers'; import { selectChat, selectChatFullInfo, selectTabState } from '../../../global/selectors'; import { formatInteger } from '../../../util/textFormat'; import useFlag from '../../../hooks/useFlag'; import useHistoryBack from '../../../hooks/useHistoryBack'; +import useLastCallback from '../../../hooks/useLastCallback'; import useMedia from '../../../hooks/useMedia'; import useOldLang from '../../../hooks/useOldLang'; @@ -27,6 +28,7 @@ import FloatingActionButton from '../../ui/FloatingActionButton'; import InputText from '../../ui/InputText'; import ListItem from '../../ui/ListItem'; import Spinner from '../../ui/Spinner'; +import Switcher from '../../ui/Switcher'; import TextArea from '../../ui/TextArea'; import './Management.scss'; @@ -46,6 +48,8 @@ type StateProps = { canInvite?: boolean; exportedInvites?: ApiExportedInvite[]; availableReactions?: ApiAvailableReaction[]; + hasAutoTranslation?: boolean; + canToggleAutoTranslation?: boolean; }; const CHANNEL_TITLE_EMPTY = 'Channel title can\'t be empty'; @@ -63,6 +67,8 @@ const ManageChannel: FC = ({ availableReactions, onScreenSelect, onClose, + hasAutoTranslation, + canToggleAutoTranslation, }) => { const { updateChat, @@ -72,6 +78,7 @@ const ManageChannel: FC = ({ openChat, loadExportedChatInvites, loadChatJoinRequests, + toggleAutoTranslation, } = getActions(); const currentTitle = chat?.title || ''; @@ -88,6 +95,12 @@ const ManageChannel: FC = ({ const currentAvatarBlobUrl = useMedia(imageHash, false, ApiMediaFormat.BlobUrl); const lang = useOldLang(); + const hasAutoTranslationAvailable = chat && isChatChannel(chat); + + const handleAutoTranslationChange = useLastCallback(() => { + toggleAutoTranslation({ chatId, isEnabled: !hasAutoTranslation }); + }); + useHistoryBack({ isActive, onBack: onClose, @@ -112,46 +125,46 @@ const ManageChannel: FC = ({ }, [chatFullInfo?.adminMembersById]); const removedUsersCount = chatFullInfo?.kickedMembers?.length || 0; - const handleClickEditType = useCallback(() => { + const handleClickEditType = useLastCallback(() => { onScreenSelect(ManagementScreens.ChatPrivacyType); - }, [onScreenSelect]); + }); - const handleClickDiscussion = useCallback(() => { + const handleClickDiscussion = useLastCallback(() => { onScreenSelect(ManagementScreens.Discussion); - }, [onScreenSelect]); + }); - const handleClickReactions = useCallback(() => { + const handleClickReactions = useLastCallback(() => { onScreenSelect(ManagementScreens.Reactions); - }, [onScreenSelect]); + }); - const handleClickAdministrators = useCallback(() => { + const handleClickAdministrators = useLastCallback(() => { onScreenSelect(ManagementScreens.ChatAdministrators); - }, [onScreenSelect]); + }); - const handleClickInvites = useCallback(() => { + const handleClickInvites = useLastCallback(() => { onScreenSelect(ManagementScreens.Invites); - }, [onScreenSelect]); + }); - const handleClickRequests = useCallback(() => { + const handleClickRequests = useLastCallback(() => { onScreenSelect(ManagementScreens.JoinRequests); - }, [onScreenSelect]); + }); - const handleSetPhoto = useCallback((file: File) => { + const handleSetPhoto = useLastCallback((file: File) => { setPhoto(file); setIsProfileFieldsTouched(true); - }, []); + }); - const handleTitleChange = useCallback((e: ChangeEvent) => { + const handleTitleChange = useLastCallback((e: ChangeEvent) => { setTitle(e.target.value); setIsProfileFieldsTouched(true); - }, []); + }); - const handleAboutChange = useCallback((e: ChangeEvent) => { + const handleAboutChange = useLastCallback((e: ChangeEvent) => { setAbout(e.target.value); setIsProfileFieldsTouched(true); - }, []); + }); - const handleUpdateChannel = useCallback(() => { + const handleUpdateChannel = useLastCallback(() => { const trimmedTitle = title.trim(); const trimmedAbout = about.trim(); @@ -166,17 +179,17 @@ const ManageChannel: FC = ({ about: trimmedAbout, photo, }); - }, [about, chatId, photo, title, updateChat]); + }); - const handleClickSubscribers = useCallback(() => { + const handleClickSubscribers = useLastCallback(() => { onScreenSelect(ManagementScreens.ChannelSubscribers); - }, [onScreenSelect]); + }); - const handleRemovedUsersClick = useCallback(() => { + const handleRemovedUsersClick = useLastCallback(() => { onScreenSelect(ManagementScreens.ChannelRemovedUsers); - }, [onScreenSelect]); + }); - const handleDeleteChannel = useCallback(() => { + const handleDeleteChannel = useLastCallback(() => { if (chat.isCreator) { deleteChannel({ chatId: chat.id }); } else { @@ -186,7 +199,7 @@ const ManageChannel: FC = ({ closeDeleteDialog(); closeManagement(); openChat({ id: undefined }); - }, [chat.isCreator, chat.id, closeDeleteDialog, closeManagement, leaveChannel, deleteChannel, openChat]); + }); const chatReactionsDescription = useMemo(() => { if (!chatFullInfo?.enabledReactions) { @@ -290,6 +303,22 @@ const ManageChannel: FC = ({ {chatReactionsDescription} + {hasAutoTranslationAvailable && ( + + {lang('AutomaticTranslation')} + + + )}
( const { management } = selectTabState(global); const { progress } = management; const { invites } = management.byChatId[chatId] || {}; - + const minLevelToToggleAutoTranslation = global.appConfig?.channelAutoTranslationLevelMin; + const hasAutoTranslation = chat?.hasAutoTranslation; + const chatBoostLevel = chat?.level; + const canToggleAutoTranslation = chatBoostLevel && minLevelToToggleAutoTranslation + ? chatBoostLevel >= minLevelToToggleAutoTranslation : false; return { chat, chatFullInfo: selectChatFullInfo(global, chatId), @@ -362,6 +395,8 @@ export default memo(withGlobal( canInvite: getHasAdminRight(chat, 'inviteUsers'), exportedInvites: invites, availableReactions: global.reactions.availableReactions, + hasAutoTranslation, + canToggleAutoTranslation, }; }, (global, { chatId }) => { diff --git a/src/components/right/management/ManageDiscussion.tsx b/src/components/right/management/ManageDiscussion.tsx index 998361177..29f811b0a 100644 --- a/src/components/right/management/ManageDiscussion.tsx +++ b/src/components/right/management/ManageDiscussion.tsx @@ -15,7 +15,7 @@ import renderText from '../../common/helpers/renderText'; import useFlag from '../../../hooks/useFlag'; import useHistoryBack from '../../../hooks/useHistoryBack'; -import useLastCallback from '../../../hooks/useLastCallback.ts'; +import useLastCallback from '../../../hooks/useLastCallback'; import useOldLang from '../../../hooks/useOldLang'; import AnimatedIconWithPreview from '../../common/AnimatedIconWithPreview'; @@ -154,14 +154,14 @@ const ManageDiscussion: FC = ({ if (isChatPublic(linkedGroup)) { return renderText( - `Do you want to make **${linkedGroup.title}** the discussion board for **${chat!.title}**?`, + `Do you want to make **${linkedGroup.title}** the discussion board for **${chat?.title}**?`, ['br', 'simple_markdown'], ); } return renderText( // eslint-disable-next-line @stylistic/max-len - `Do you want to make **${linkedGroup.title}** the discussion board for **${chat!.title}**?\n\nAnyone from the channel will be able to see messages in this group.`, + `Do you want to make **${linkedGroup.title}** the discussion board for **${chat?.title}**?\n\nAnyone from the channel will be able to see messages in this group.`, ['br', 'simple_markdown'], ); } @@ -169,12 +169,14 @@ const ManageDiscussion: FC = ({ function renderLinkedGroup() { return (
- - - + {linkedChat && ( + + + + )} = ({ onClose={closeConfirmUnlinkGroupDialog} header={renderUnlinkGroupHeader()} textParts={renderText( - lang(isChannel ? 'DiscussionUnlinkChannelAlert' : 'DiscussionUnlinkGroupAlert', linkedChat!.title), + lang(isChannel ? 'DiscussionUnlinkChannelAlert' : 'DiscussionUnlinkGroupAlert', linkedChat?.title), ['br', 'simple_markdown'], )} confirmLabel={lang(isChannel ? 'DiscussionUnlinkGroup' : 'DiscussionUnlinkChannel')} diff --git a/src/components/right/statistics/BoostStatistics.module.scss b/src/components/right/statistics/BoostStatistics.module.scss index c334e4857..a7b270ee4 100644 --- a/src/components/right/statistics/BoostStatistics.module.scss +++ b/src/components/right/statistics/BoostStatistics.module.scss @@ -134,3 +134,7 @@ right: 0.5rem; transform: translate(0, -50%); } + +.boostInfo { + margin: 0 -1rem; +} diff --git a/src/components/right/statistics/BoostStatistics.tsx b/src/components/right/statistics/BoostStatistics.tsx index 912f809d2..030988cba 100644 --- a/src/components/right/statistics/BoostStatistics.tsx +++ b/src/components/right/statistics/BoostStatistics.tsx @@ -226,8 +226,7 @@ const BoostStatistics = ({ return ( handleBoosterClick(boost.userId)} > => { + const { chatId, isEnabled } = payload; + const chat = selectChat(global, chatId); + if (!chat) return; + + const result = await callApi('toggleAutoTranslation', { chat, isEnabled }); + if (!result) return; + + global = getGlobal(); + global = updateChat(global, chatId, { hasAutoTranslation: isEnabled || undefined }); + setGlobal(global); +}); + addActionHandler('resolveBusinessChatLink', async (global, actions, payload): Promise => { const { slug, tabId = getCurrentTabId() } = payload; const result = await callApi('resolveBusinessChatLink', { slug }); diff --git a/src/global/selectors/chats.ts b/src/global/selectors/chats.ts index 55bc44de7..7b1fdaf19 100644 --- a/src/global/selectors/chats.ts +++ b/src/global/selectors/chats.ts @@ -283,6 +283,9 @@ export function selectShouldDetectChatLanguage( ) { const chat = selectChat(global, chatId); if (!chat) return false; + + if (chat.hasAutoTranslation) return true; + const { canTranslateChats } = global.settings.byKey; const isPremium = selectIsCurrentUserPremium(global); diff --git a/src/global/types/actions.ts b/src/global/types/actions.ts index 9ba4b6fde..b9e4b585c 100644 --- a/src/global/types/actions.ts +++ b/src/global/types/actions.ts @@ -1081,6 +1081,10 @@ export interface ActionPayloads { chatId: string; paidMessagesStars: number; } & WithTabId; + toggleAutoTranslation: { + chatId: string; + isEnabled: boolean; + } & WithTabId; updateChat: { chatId: string; diff --git a/src/lib/gramjs/tl/api.d.ts b/src/lib/gramjs/tl/api.d.ts index 4dc9d9157..15fca4ee3 100644 --- a/src/lib/gramjs/tl/api.d.ts +++ b/src/lib/gramjs/tl/api.d.ts @@ -421,7 +421,7 @@ namespace Api { export type TypeAccessPointRule = AccessPointRule; export type TypeTlsClientHello = TlsClientHello; export type TypeTlsBlock = TlsBlockString | TlsBlockRandom | TlsBlockZero | TlsBlockDomain | TlsBlockGrease | TlsBlockScope; - + export namespace storage { export type TypeFileType = storage.FileUnknown | storage.FilePartial | storage.FileJpeg | storage.FileGif | storage.FilePng | storage.FilePdf | storage.FileMp3 | storage.FileMov | storage.FileMp4 | storage.FileWebp; @@ -17724,7 +17724,7 @@ namespace Api { static fromReader(reader: Reader): TlsBlockScope; } - + export namespace storage { export class FileUnknown extends VirtualClass { @@ -22053,7 +22053,7 @@ namespace Api { }>, Api.TypeDestroySessionRes> { sessionId: long; } - + export namespace auth { export class SendCode extends Request peer:InputPeer = premium.MyBoosts; premium.getBoostsStatus#42f1f61 peer:InputPeer = premium.BoostsStatus; -fragment.getCollectibleInfo#be1e85ba collectible:InputCollectible = fragment.CollectibleInfo;`; \ No newline at end of file +fragment.getCollectibleInfo#be1e85ba collectible:InputCollectible = fragment.CollectibleInfo;`; diff --git a/src/lib/gramjs/tl/static/api.json b/src/lib/gramjs/tl/static/api.json index 7e6d306de..7a4005102 100644 --- a/src/lib/gramjs/tl/static/api.json +++ b/src/lib/gramjs/tl/static/api.json @@ -280,6 +280,7 @@ "channels.searchPosts", "channels.reportSpam", "channels.updatePaidMessagesPrice", + "channels.toggleAutotranslation", "bots.getBotRecommendations", "bots.canSendMessage", "bots.allowSendMessage", diff --git a/src/types/language.d.ts b/src/types/language.d.ts index 968823715..330032420 100644 --- a/src/types/language.d.ts +++ b/src/types/language.d.ts @@ -1530,6 +1530,7 @@ export interface LangPair { 'ValueGiftSortByNumber': undefined; 'ResellGiftsNoFound': undefined; 'ResellGiftsClearFilters': undefined; + 'AutomaticTranslation': undefined; } export interface LangPairWithVariables { @@ -1773,6 +1774,9 @@ export interface LangPairWithVariables { 'VoipPeerIncompatible': { 'user': V; }; + 'NewDiscussionChatTitle': { + 'name': V; + }; 'LastSeenTodayAt': { 'time': V; }; @@ -2170,6 +2174,9 @@ export interface LangPairWithVariables { 'from': V; 'title': V; }; + 'ActionCreatedChatYou': { + 'title': V; + }; 'ActionPaymentDone': { 'amount': V; 'user': V; @@ -2488,9 +2495,6 @@ export interface LangPairWithVariables { 'ComposerTitleForwardFrom': { 'users': V; }; - 'NewDiscussionChatTitle': { - 'name': V; - } } export interface LangPairPlural {