Introduce Mini-Apps (#3868)

This commit is contained in:
Alexander Zinchuk 2023-09-25 13:00:13 +02:00
parent 548430bd2e
commit acc962bcf5
25 changed files with 560 additions and 337 deletions

View File

@ -118,6 +118,11 @@ interface Navigator {
setAppBadge?(count: number): Promise<void>;
}
type Undefined<T> = {
[K in keyof T]: undefined;
};
type OptionalCombine<A, B> = (A & B) | (A & Undefined<B>);
// Fix to make Boolean() work as !!
// https://github.com/microsoft/TypeScript/issues/16655
type Falsy = false | 0 | '' | null | undefined;

View File

@ -75,8 +75,12 @@ export function buildApiAttachBot(bot: GramJs.AttachMenuBot): ApiAttachBot {
hasSettings: bot.hasSettings,
shouldRequestWriteAccess: bot.requestWriteAccess,
shortName: bot.shortName,
peerTypes: bot.peerTypes.map(buildApiAttachMenuPeerType),
isForAttachMenu: bot.showInAttachMenu!,
isForSideMenu: bot.showInSideMenu,
attachMenuPeerTypes: bot.peerTypes?.map(buildApiAttachMenuPeerType)!,
icons: bot.icons.map(buildApiAttachMenuIcon).filter(Boolean),
isInactive: bot.inactive,
isDisclaimerNeeded: bot.sideMenuDisclaimerNeeded,
};
}

View File

@ -214,17 +214,28 @@ export async function requestWebView({
}
export async function requestSimpleWebView({
bot, url, theme,
bot,
url,
theme,
startParam,
isFromSwitchWebView,
isFromSideMenu,
}: {
bot: ApiUser;
url: string;
url?: string;
theme?: ApiThemeParameters;
startParam?: string;
isFromSwitchWebView?: boolean;
isFromSideMenu?: boolean;
}) {
const result = await invokeRequest(new GramJs.messages.RequestSimpleWebView({
url,
bot: buildInputPeer(bot.id, bot.accessHash),
themeParams: theme ? buildInputThemeParams(theme) : undefined,
platform: WEB_APP_PLATFORM,
startParam,
fromSwitchWebview: isFromSwitchWebView || undefined,
fromSideMenu: isFromSideMenu || undefined,
}));
return result?.url;

View File

@ -1104,6 +1104,10 @@ export function updater(update: Update) {
'@type': 'updateStealthMode',
stealthMode: buildApiStealthMode(update.stealthMode),
});
} else if (update instanceof GramJs.UpdateAttachMenuBots) {
onUpdate({
'@type': 'updateAttachMenuBots',
});
} else if (DEBUG) {
const params = typeof update === 'object' && 'className' in update ? update.className : update;
log('UNEXPECTED UPDATE', params);

View File

@ -661,6 +661,10 @@ export type ApiRequestSync = {
'@type': 'requestSync';
};
export type ApiUpdateAttachMenuBots = {
'@type': 'updateAttachMenuBots';
};
export type ApiUpdate = (
ApiUpdateReady | ApiUpdateSession | ApiUpdateWebAuthTokenFailed | ApiUpdateRequestUserUpdate |
ApiUpdateAuthorizationState | ApiUpdateAuthorizationError | ApiUpdateConnectionState | ApiUpdateCurrentUser |
@ -689,7 +693,7 @@ export type ApiUpdate = (
ApiUpdatePinnedTopicsOrder | ApiUpdateTopic | ApiUpdateTopics | ApiUpdateRecentEmojiStatuses |
ApiUpdateRecentReactions | ApiUpdateStory | ApiUpdateReadStories | ApiUpdateDeleteStory | ApiUpdateSentStoryReaction |
ApiRequestReconnectApi | ApiRequestSync | ApiUpdateFetchingDifference | ApiUpdateChannelMessages |
ApiUpdateStealthMode
ApiUpdateStealthMode | ApiUpdateAttachMenuBots
);
export type OnApiUpdate = (update: ApiUpdate) => void;

View File

@ -74,14 +74,23 @@ export interface ApiUsername {
export type ApiChatType = typeof API_CHAT_TYPES[number];
export type ApiAttachMenuPeerType = 'self' | ApiChatType;
export interface ApiAttachBot {
type ApiAttachBotForMenu = {
isForAttachMenu: true;
attachMenuPeerTypes: ApiAttachMenuPeerType[];
};
type ApiAttachBotBase = {
id: string;
hasSettings?: boolean;
shouldRequestWriteAccess?: boolean;
shortName: string;
peerTypes: ApiAttachMenuPeerType[];
isForSideMenu?: true;
isDisclaimerNeeded?: boolean;
icons: ApiAttachBotIcon[];
}
isInactive?: boolean;
};
export type ApiAttachBot = OptionalCombine<ApiAttachBotBase, ApiAttachBotForMenu>;
export interface ApiAttachBotIcon {
name: string;

View File

@ -4,28 +4,15 @@ import React, {
} from '../../../lib/teact/teact';
import { getActions, withGlobal } from '../../../global';
import type { GlobalState, TabState } from '../../../global/types';
import type { AnimationLevel, ISettings } from '../../../types';
import type { GlobalState } from '../../../global/types';
import type { ISettings } from '../../../types';
import { LeftColumnContent, SettingsScreens } from '../../../types';
import {
ANIMATION_LEVEL_MAX,
ANIMATION_LEVEL_MIN,
APP_NAME,
ARCHIVED_FOLDER_ID,
BETA_CHANGELOG_URL,
DEBUG,
FEEDBACK_URL,
IS_BETA,
IS_TEST,
PRODUCTION_HOSTNAME,
WEB_VERSION_BASE,
} from '../../../config';
import {
INITIAL_PERFORMANCE_STATE_MAX,
INITIAL_PERFORMANCE_STATE_MID,
INITIAL_PERFORMANCE_STATE_MIN,
} from '../../../global/initialState';
import {
selectCanSetPasscode,
selectCurrentMessageList,
@ -36,14 +23,12 @@ import {
import buildClassName from '../../../util/buildClassName';
import captureEscKeyListener from '../../../util/captureEscKeyListener';
import { formatDateToString } from '../../../util/dateFormat';
import { getPromptInstall } from '../../../util/installPrompt';
import { switchPermanentWebVersion } from '../../../util/permanentWebVersion';
import { IS_APP, IS_ELECTRON, IS_MAC_OS } from '../../../util/windowEnvironment';
import useAppLayout from '../../../hooks/useAppLayout';
import useConnectionStatus from '../../../hooks/useConnectionStatus';
import useElectronDrag from '../../../hooks/useElectronDrag';
import { useFolderManagerForUnreadCounters } from '../../../hooks/useFolderManager';
import useFlag from '../../../hooks/useFlag';
import { useFullscreenStatus } from '../../../hooks/useFullscreen';
import { useHotkeys } from '../../../hooks/useHotkeys';
import useLang from '../../../hooks/useLang';
@ -54,12 +39,10 @@ import PickerSelectedItem from '../../common/PickerSelectedItem';
import StoryToggler from '../../story/StoryToggler';
import Button from '../../ui/Button';
import DropdownMenu from '../../ui/DropdownMenu';
import MenuItem from '../../ui/MenuItem';
import SearchInput from '../../ui/SearchInput';
import ShowTransition from '../../ui/ShowTransition';
import Switcher from '../../ui/Switcher';
import Toggle from '../../ui/Toggle';
import ConnectionStatusOverlay from '../ConnectionStatusOverlay';
import LeftSideMenuItems from './LeftSideMenuItems';
import StatusButton from './StatusButton';
import './LeftMainHeader.scss';
@ -71,21 +54,19 @@ type OwnProps = {
isClosingSearch?: boolean;
shouldSkipTransition?: boolean;
onSearchQuery: (query: string) => void;
onSelectSettings: () => void;
onSelectContacts: () => void;
onSelectArchived: () => void;
onReset: () => void;
onSelectSettings: NoneToVoidFunction;
onSelectContacts: NoneToVoidFunction;
onSelectArchived: NoneToVoidFunction;
onReset: NoneToVoidFunction;
};
type StateProps =
{
searchQuery?: string;
isLoading: boolean;
currentUserId?: string;
globalSearchChatId?: string;
searchDate?: number;
theme: ISettings['theme'];
animationLevel: AnimationLevel;
isMessageListOpen: boolean;
isCurrentUserPremium?: boolean;
isConnectionStatusMinimized: ISettings['isConnectionStatusMinimized'];
@ -93,8 +74,7 @@ type StateProps =
hasPasscode?: boolean;
canSetPasscode?: boolean;
}
& Pick<GlobalState, 'connectionState' | 'isSyncing' | 'isFetchingDifference' | 'archiveSettings'>
& Pick<TabState, 'canInstall'>;
& Pick<GlobalState, 'connectionState' | 'isSyncing' | 'isFetchingDifference'>;
const CLEAR_DATE_SEARCH_PARAM = { date: undefined };
const CLEAR_CHAT_SEARCH_PARAM = { id: undefined };
@ -103,21 +83,14 @@ const LeftMainHeader: FC<OwnProps & StateProps> = ({
shouldHideSearch,
content,
contactsFilter,
onSearchQuery,
isClosingSearch,
onSelectSettings,
onSelectContacts,
onSelectArchived,
onReset,
searchQuery,
isLoading,
isCurrentUserPremium,
shouldSkipTransition,
currentUserId,
globalSearchChatId,
searchDate,
theme,
animationLevel,
connectionState,
isSyncing,
isFetchingDifference,
@ -126,24 +99,25 @@ const LeftMainHeader: FC<OwnProps & StateProps> = ({
areChatsLoaded,
hasPasscode,
canSetPasscode,
canInstall,
archiveSettings,
onSearchQuery,
onSelectSettings,
onSelectContacts,
onSelectArchived,
onReset,
}) => {
const {
openChat,
openChatWithInfo,
setGlobalSearchDate,
setSettingOption,
setGlobalSearchChatId,
openChatByUsername,
lockScreen,
requestNextSettingsScreen,
openUrl,
updatePerformanceSettings,
} = getActions();
const lang = useLang();
const { isMobile } = useAppLayout();
const [isBotMenuOpen, markBotMenuOpen, unmarkBotMenuOpen] = useFlag();
const hasMenu = content === LeftColumnContent.ChatList;
const selectedSearchDate = useMemo(() => {
return searchDate
@ -151,8 +125,6 @@ const LeftMainHeader: FC<OwnProps & StateProps> = ({
: undefined;
}, [searchDate]);
const archivedUnreadChatsCount = useFolderManagerForUnreadCounters()[ARCHIVED_FOLDER_ID]?.chatsCount || 0;
const { connectionStatus, connectionStatusText, connectionStatusPosition } = useConnectionStatus(
lang,
connectionState,
@ -172,10 +144,6 @@ const LeftMainHeader: FC<OwnProps & StateProps> = ({
}
});
const handleOpenMyStories = useLastCallback(() => {
openChatWithInfo({ id: currentUserId, shouldReplaceHistory: true, profileTab: 'stories' });
});
useHotkeys(canSetPasscode ? {
'Ctrl+Shift+L': handleLockScreenHotkey,
'Alt+Shift+L': handleLockScreenHotkey,
@ -183,8 +151,6 @@ const LeftMainHeader: FC<OwnProps & StateProps> = ({
...(IS_APP && { 'Mod+L': handleLockScreenHotkey }),
} : undefined);
const withOtherVersions = window.location.hostname === PRODUCTION_HOSTNAME || IS_TEST;
const MainButton: FC<{ onTrigger: () => void; isOpen?: boolean }> = useMemo(() => {
return ({ onTrigger, isOpen }) => (
<Button
@ -217,49 +183,6 @@ const LeftMainHeader: FC<OwnProps & StateProps> = ({
setSettingOption({ isConnectionStatusMinimized: !isConnectionStatusMinimized });
});
const handleSelectSaved = useLastCallback(() => {
openChat({ id: currentUserId, shouldReplaceHistory: true });
});
const handleDarkModeToggle = useLastCallback((e: React.SyntheticEvent<HTMLElement>) => {
e.stopPropagation();
const newTheme = theme === 'light' ? 'dark' : 'light';
setSettingOption({ theme: newTheme });
setSettingOption({ shouldUseSystemTheme: false });
});
const handleAnimationLevelChange = useLastCallback((e: React.SyntheticEvent<HTMLElement>) => {
e.stopPropagation();
let newLevel = animationLevel + 1;
if (newLevel > ANIMATION_LEVEL_MAX) {
newLevel = ANIMATION_LEVEL_MIN;
}
const performanceSettings = newLevel === ANIMATION_LEVEL_MIN
? INITIAL_PERFORMANCE_STATE_MIN
: (newLevel === ANIMATION_LEVEL_MAX ? INITIAL_PERFORMANCE_STATE_MAX : INITIAL_PERFORMANCE_STATE_MID);
setSettingOption({ animationLevel: newLevel as AnimationLevel });
updatePerformanceSettings(performanceSettings);
});
const handleChangelogClick = useLastCallback(() => {
window.open(BETA_CHANGELOG_URL, '_blank', 'noopener');
});
const handleSwitchToWebK = useLastCallback(() => {
switchPermanentWebVersion('K');
});
const handleOpenTipsChat = useLastCallback(() => {
openChatByUsername({ username: lang('Settings.TipsUsername') });
});
const handleBugReportClick = useLastCallback(() => {
openUrl({ url: FEEDBACK_URL });
});
const handleLockScreen = useLastCallback(() => {
lockScreen();
});
@ -277,9 +200,6 @@ const LeftMainHeader: FC<OwnProps & StateProps> = ({
: lang('Search');
const versionString = IS_BETA ? `${APP_VERSION} Beta (${APP_REVISION})` : (DEBUG ? APP_REVISION : APP_VERSION);
const animationLevelValue = animationLevel !== ANIMATION_LEVEL_MIN
? (animationLevel === ANIMATION_LEVEL_MAX ? 'max' : 'mid')
: 'min';
const isFullscreen = useFullscreenStatus();
@ -293,106 +213,6 @@ const LeftMainHeader: FC<OwnProps & StateProps> = ({
const headerRef = useRef<HTMLDivElement>(null);
useElectronDrag(headerRef);
const menuItems = useMemo(() => (
<>
<MenuItem
icon="saved-messages"
onClick={handleSelectSaved}
>
{lang('SavedMessages')}
</MenuItem>
{archiveSettings.isHidden && (
<MenuItem
icon="archive"
onClick={onSelectArchived}
>
<span className="menu-item-name">{lang('ArchivedChats')}</span>
{archivedUnreadChatsCount > 0 && (
<div className="right-badge">{archivedUnreadChatsCount}</div>
)}
</MenuItem>
)}
<MenuItem
icon="user"
onClick={onSelectContacts}
>
{lang('Contacts')}
</MenuItem>
<MenuItem
icon="play-story"
onClick={handleOpenMyStories}
>
{lang('Settings.MyStories')}
</MenuItem>
<MenuItem
icon="settings"
onClick={onSelectSettings}
>
{lang('Settings')}
</MenuItem>
<MenuItem
icon="darkmode"
onClick={handleDarkModeToggle}
>
<span className="menu-item-name">{lang('lng_menu_night_mode')}</span>
<Switcher
id="darkmode"
label={lang(theme === 'dark' ? 'lng_settings_disable_night_theme' : 'lng_settings_enable_night_theme')}
checked={theme === 'dark'}
noAnimation
/>
</MenuItem>
<MenuItem
icon="animations"
onClick={handleAnimationLevelChange}
>
<span className="menu-item-name capitalize">{lang('Appearance.Animations').toLowerCase()}</span>
<Toggle value={animationLevelValue} />
</MenuItem>
<MenuItem
icon="help"
onClick={handleOpenTipsChat}
>
{lang('TelegramFeatures')}
</MenuItem>
<MenuItem
icon="bug"
onClick={handleBugReportClick}
>
Report Bug
</MenuItem>
{IS_BETA && (
<MenuItem
icon="permissions"
onClick={handleChangelogClick}
>
Beta Changelog
</MenuItem>
)}
{withOtherVersions && (
<MenuItem
icon="K"
isCharIcon
href={`${WEB_VERSION_BASE}k`}
onClick={handleSwitchToWebK}
>
Switch to K Version
</MenuItem>
)}
{canInstall && (
<MenuItem
icon="install"
onClick={getPromptInstall()}
>
Install App
</MenuItem>
)}
</>
), [
animationLevelValue, archiveSettings.isHidden, archivedUnreadChatsCount, canInstall, lang, onSelectArchived,
onSelectContacts, onSelectSettings, theme, withOtherVersions,
]);
const searchContent = useMemo(() => {
return (
<>
@ -432,11 +252,18 @@ const LeftMainHeader: FC<OwnProps & StateProps> = ({
shouldHideSearch && lang.isRtl && 'right-aligned',
shouldDisableDropdownMenuTransitionRef.current && lang.isRtl && 'disable-transition',
)}
forceOpen={isBotMenuOpen}
positionX={shouldHideSearch && lang.isRtl ? 'right' : 'left'}
transformOriginX={IS_ELECTRON && IS_MAC_OS && !isFullscreen ? 90 : undefined}
onTransitionEnd={lang.isRtl ? handleDropdownMenuTransitionEnd : undefined}
>
{menuItems}
<LeftSideMenuItems
onSelectArchived={onSelectArchived}
onSelectContacts={onSelectContacts}
onSelectSettings={onSelectSettings}
onBotMenuOpened={markBotMenuOpen}
onBotMenuClosed={unmarkBotMenuOpen}
/>
</DropdownMenu>
<SearchInput
inputId="telegram-search-input"
@ -498,18 +325,16 @@ export default memo(withGlobal<OwnProps>(
query: searchQuery, fetchingStatus, chatId, date,
} = tabState.globalSearch;
const {
currentUserId, connectionState, isSyncing, archiveSettings, isFetchingDifference,
connectionState, isSyncing, isFetchingDifference,
} = global;
const { isConnectionStatusMinimized, animationLevel } = global.settings.byKey;
const { isConnectionStatusMinimized } = global.settings.byKey;
return {
searchQuery,
isLoading: fetchingStatus ? Boolean(fetchingStatus.chats || fetchingStatus.messages) : false,
currentUserId,
globalSearchChatId: chatId,
searchDate: date,
theme: selectTheme(global),
animationLevel,
connectionState,
isSyncing,
isFetchingDifference,
@ -518,8 +343,6 @@ export default memo(withGlobal<OwnProps>(
isCurrentUserPremium: selectIsCurrentUserPremium(global),
areChatsLoaded: Boolean(global.chats.listIds.active),
hasPasscode: Boolean(global.passcode.hasPasscode),
canInstall: Boolean(tabState.canInstall),
archiveSettings,
canSetPasscode: selectCanSetPasscode(global),
};
},

View File

@ -0,0 +1,255 @@
import React, { memo, useMemo } from '../../../lib/teact/teact';
import { getActions, withGlobal } from '../../../global';
import type { GlobalState } from '../../../global/types';
import type { AnimationLevel, ThemeKey } from '../../../types';
import {
ANIMATION_LEVEL_MAX,
ANIMATION_LEVEL_MIN,
ARCHIVED_FOLDER_ID,
BETA_CHANGELOG_URL,
FEEDBACK_URL,
IS_BETA,
IS_TEST,
PRODUCTION_HOSTNAME,
WEB_VERSION_BASE,
} from '../../../config';
import {
INITIAL_PERFORMANCE_STATE_MAX,
INITIAL_PERFORMANCE_STATE_MID,
INITIAL_PERFORMANCE_STATE_MIN,
} from '../../../global/initialState';
import { selectTabState, selectTheme } from '../../../global/selectors';
import { getPromptInstall } from '../../../util/installPrompt';
import { switchPermanentWebVersion } from '../../../util/permanentWebVersion';
import { useFolderManagerForUnreadCounters } from '../../../hooks/useFolderManager';
import useLang from '../../../hooks/useLang';
import useLastCallback from '../../../hooks/useLastCallback';
import AttachBotItem from '../../middle/composer/AttachBotItem';
import MenuItem from '../../ui/MenuItem';
import Switcher from '../../ui/Switcher';
import Toggle from '../../ui/Toggle';
type OwnProps = {
onSelectSettings: NoneToVoidFunction;
onSelectContacts: NoneToVoidFunction;
onSelectArchived: NoneToVoidFunction;
onBotMenuOpened: NoneToVoidFunction;
onBotMenuClosed: NoneToVoidFunction;
};
type StateProps = {
animationLevel: AnimationLevel;
theme: ThemeKey;
canInstall?: boolean;
attachBots: GlobalState['attachMenu']['bots'];
} & Pick<GlobalState, 'currentUserId' | 'archiveSettings'>;
const LeftSideMenuItems = ({
currentUserId,
archiveSettings,
animationLevel,
theme,
canInstall,
attachBots,
onSelectArchived,
onSelectContacts,
onSelectSettings,
onBotMenuOpened,
onBotMenuClosed,
}: OwnProps & StateProps) => {
const {
openChat,
setSettingOption,
updatePerformanceSettings,
openChatByUsername,
openUrl,
openChatWithInfo,
} = getActions();
const lang = useLang();
const animationLevelValue = animationLevel !== ANIMATION_LEVEL_MIN
? (animationLevel === ANIMATION_LEVEL_MAX ? 'max' : 'mid') : 'min';
const withOtherVersions = window.location.hostname === PRODUCTION_HOSTNAME || IS_TEST;
const archivedUnreadChatsCount = useFolderManagerForUnreadCounters()[ARCHIVED_FOLDER_ID]?.chatsCount || 0;
const bots = useMemo(() => Object.values(attachBots).filter((bot) => bot.isForSideMenu), [attachBots]);
const handleSelectSaved = useLastCallback(() => {
openChat({ id: currentUserId, shouldReplaceHistory: true });
});
const handleDarkModeToggle = useLastCallback((e: React.SyntheticEvent<HTMLElement>) => {
e.stopPropagation();
const newTheme = theme === 'light' ? 'dark' : 'light';
setSettingOption({ theme: newTheme });
setSettingOption({ shouldUseSystemTheme: false });
});
const handleAnimationLevelChange = useLastCallback((e: React.SyntheticEvent<HTMLElement>) => {
e.stopPropagation();
let newLevel = animationLevel + 1;
if (newLevel > ANIMATION_LEVEL_MAX) {
newLevel = ANIMATION_LEVEL_MIN;
}
const performanceSettings = newLevel === ANIMATION_LEVEL_MIN
? INITIAL_PERFORMANCE_STATE_MIN
: (newLevel === ANIMATION_LEVEL_MAX ? INITIAL_PERFORMANCE_STATE_MAX : INITIAL_PERFORMANCE_STATE_MID);
setSettingOption({ animationLevel: newLevel as AnimationLevel });
updatePerformanceSettings(performanceSettings);
});
const handleChangelogClick = useLastCallback(() => {
window.open(BETA_CHANGELOG_URL, '_blank', 'noopener');
});
const handleSwitchToWebK = useLastCallback(() => {
switchPermanentWebVersion('K');
});
const handleOpenTipsChat = useLastCallback(() => {
openChatByUsername({ username: lang('Settings.TipsUsername') });
});
const handleBugReportClick = useLastCallback(() => {
openUrl({ url: FEEDBACK_URL });
});
const handleOpenMyStories = useLastCallback(() => {
openChatWithInfo({ id: currentUserId, shouldReplaceHistory: true, profileTab: 'stories' });
});
return (
<>
<MenuItem
icon="saved-messages"
onClick={handleSelectSaved}
>
{lang('SavedMessages')}
</MenuItem>
{archiveSettings.isHidden && (
<MenuItem
icon="archive"
onClick={onSelectArchived}
>
<span className="menu-item-name">{lang('ArchivedChats')}</span>
{archivedUnreadChatsCount > 0 && (
<div className="right-badge">{archivedUnreadChatsCount}</div>
)}
</MenuItem>
)}
<MenuItem
icon="user"
onClick={onSelectContacts}
>
{lang('Contacts')}
</MenuItem>
{bots.map((bot) => (
<AttachBotItem
bot={bot}
theme={theme}
isInSideMenu
onMenuOpened={onBotMenuOpened}
onMenuClosed={onBotMenuClosed}
/>
))}
<MenuItem
icon="play-story"
onClick={handleOpenMyStories}
>
{lang('Settings.MyStories')}
</MenuItem>
<MenuItem
icon="settings"
onClick={onSelectSettings}
>
{lang('Settings')}
</MenuItem>
<MenuItem
icon="darkmode"
onClick={handleDarkModeToggle}
>
<span className="menu-item-name">{lang('lng_menu_night_mode')}</span>
<Switcher
id="darkmode"
label={lang(theme === 'dark' ? 'lng_settings_disable_night_theme' : 'lng_settings_enable_night_theme')}
checked={theme === 'dark'}
noAnimation
/>
</MenuItem>
<MenuItem
icon="animations"
onClick={handleAnimationLevelChange}
>
<span className="menu-item-name capitalize">{lang('Appearance.Animations').toLowerCase()}</span>
<Toggle value={animationLevelValue} />
</MenuItem>
<MenuItem
icon="help"
onClick={handleOpenTipsChat}
>
{lang('TelegramFeatures')}
</MenuItem>
<MenuItem
icon="bug"
onClick={handleBugReportClick}
>
Report Bug
</MenuItem>
{IS_BETA && (
<MenuItem
icon="permissions"
onClick={handleChangelogClick}
>
Beta Changelog
</MenuItem>
)}
{withOtherVersions && (
<MenuItem
icon="K"
isCharIcon
href={`${WEB_VERSION_BASE}k`}
onClick={handleSwitchToWebK}
>
Switch to K Version
</MenuItem>
)}
{canInstall && (
<MenuItem
icon="install"
onClick={getPromptInstall()}
>
Install App
</MenuItem>
)}
</>
);
};
export default memo(withGlobal<OwnProps>(
(global): StateProps => {
const tabState = selectTabState(global);
const {
currentUserId, archiveSettings,
} = global;
const { animationLevel } = global.settings.byKey;
const attachBots = global.attachMenu.bots;
return {
currentUserId,
theme: selectTheme(global),
animationLevel,
canInstall: Boolean(tabState.canInstall),
archiveSettings,
attachBots,
};
},
)(LeftSideMenuItems));

View File

@ -10,7 +10,6 @@ import { getUserFullName } from '../../global/helpers';
import renderText from '../common/helpers/renderText';
import useLang from '../../hooks/useLang';
import usePrevious from '../../hooks/usePrevious';
import Checkbox from '../ui/Checkbox';
import ConfirmDialog from '../ui/ConfirmDialog';
@ -27,11 +26,6 @@ const BotTrustModal: FC<OwnProps> = ({ bot, type, shouldRequestWriteAccess }) =>
const [isWriteAllowed, setIsWriteAllowed] = useState(shouldRequestWriteAccess || false);
const lang = useLang();
// Keep props a little bit longer, to show correct text on closing animation
const previousBot = usePrevious(bot, false);
const previousType = usePrevious(type, false);
const currentBot = bot || previousBot;
const currentType = type || previousType;
const handleBotTrustAccept = useCallback(() => {
markBotTrusted({ botId: bot!.id, isWriteAllowed });
@ -41,18 +35,18 @@ const BotTrustModal: FC<OwnProps> = ({ bot, type, shouldRequestWriteAccess }) =>
cancelBotTrustRequest();
}, []);
const title = currentType === 'game' ? lang('AppName') : lang('BotOpenPageTitle');
const title = type === 'game' ? lang('AppName') : lang('BotOpenPageTitle');
const text = useMemo(() => {
switch (currentType) {
switch (type) {
case 'game':
return lang('BotPermissionGameAlert', getUserFullName(currentBot));
return lang('BotPermissionGameAlert', getUserFullName(bot));
case 'webApp':
return lang('BotOpenPageMessage', getUserFullName(currentBot));
return lang('BotOpenPageMessage', getUserFullName(bot));
case 'botApp':
default:
return lang('BotWebViewStartPermission');
}
}, [currentBot, currentType, lang]);
}, [bot, type, lang]);
return (
<ConfirmDialog
@ -67,7 +61,7 @@ const BotTrustModal: FC<OwnProps> = ({ bot, type, shouldRequestWriteAccess }) =>
className="dialog-checkbox"
checked={isWriteAllowed}
label={renderText(
lang('WebApp.AddToAttachmentAllowMessages', currentBot?.firstName),
lang('WebApp.AddToAttachmentAllowMessages', bot?.firstName),
['simple_markdown'],
)}
onCheck={setIsWriteAllowed}

View File

@ -13,13 +13,13 @@ import useLastCallback from '../../../hooks/useLastCallback';
import Menu from '../../ui/Menu';
import MenuItem from '../../ui/MenuItem';
import Portal from '../../ui/Portal';
import AttachBotIcon from './AttachBotIcon';
type OwnProps = {
bot: ApiAttachBot;
theme: ISettings['theme'];
chatId: string;
isInSideMenu?: true;
chatId?: string;
threadId?: number;
onMenuOpened: VoidFunction;
onMenuClosed: VoidFunction;
@ -30,6 +30,7 @@ const AttachBotItem: FC<OwnProps> = ({
theme,
chatId,
threadId,
isInSideMenu,
onMenuOpened,
onMenuClosed,
}) => {
@ -52,6 +53,15 @@ const AttachBotItem: FC<OwnProps> = ({
openMenu();
});
const handleClick = useLastCallback(() => {
callAttachBot({
bot,
chatId: chatId!,
threadId,
isFromSideMenu: isInSideMenu,
});
});
const handleCloseMenu = useLastCallback(() => {
closeMenu();
onMenuClosed();
@ -73,29 +83,23 @@ const AttachBotItem: FC<OwnProps> = ({
key={bot.id}
customIcon={icon && <AttachBotIcon icon={icon} theme={theme} />}
icon={!icon ? 'bots' : undefined}
// eslint-disable-next-line react/jsx-no-bind
onClick={() => callAttachBot({
bot,
chatId,
threadId,
})}
onClick={handleClick}
onContextMenu={handleContextMenu}
>
{bot.shortName}
{menuPosition && (
<Portal>
<Menu
isOpen={isMenuOpen}
positionX="right"
style={`left: ${menuPosition.x}px;top: ${menuPosition.y}px;`}
className="bot-attach-context-menu"
autoClose
onClose={handleCloseMenu}
onCloseAnimationEnd={handleCloseAnimationEnd}
>
<MenuItem icon="stop" destructive onClick={handleRemoveBot}>{lang('WebApp.RemoveBot')}</MenuItem>
</Menu>
</Portal>
<Menu
isOpen={isMenuOpen}
positionX="right"
style={`left: ${menuPosition.x}px;top: ${menuPosition.y}px;`}
className="bot-attach-context-menu"
autoClose
withPortal
onClose={handleCloseMenu}
onCloseAnimationEnd={handleCloseAnimationEnd}
>
<MenuItem icon="stop" destructive onClick={handleRemoveBot}>{lang('WebApp.RemoveBot')}</MenuItem>
</Menu>
)}
</MenuItem>

View File

@ -44,11 +44,11 @@ export type OwnProps = {
attachBots?: GlobalState['attachMenu']['bots'];
peerType?: ApiAttachMenuPeerType;
shouldCollectDebugLogs?: boolean;
theme: ISettings['theme'];
onFileSelect: (files: File[], shouldSuggestCompression?: boolean) => void;
onPollCreate: NoneToVoidFunction;
onMenuOpen: NoneToVoidFunction;
onMenuClose: NoneToVoidFunction;
theme: ISettings['theme'];
};
const AttachMenu: FC<OwnProps> = ({
@ -64,12 +64,12 @@ const AttachMenu: FC<OwnProps> = ({
attachBots,
peerType,
isScheduled,
theme,
shouldCollectDebugLogs,
onFileSelect,
onMenuOpen,
onMenuClose,
onPollCreate,
theme,
shouldCollectDebugLogs,
}) => {
const [isAttachMenuOpen, openAttachMenu, closeAttachMenu] = useFlag();
const [handleMouseEnter, handleMouseLeave, markMouseInside] = useMouseInside(isAttachMenuOpen, closeAttachMenu);
@ -135,11 +135,11 @@ const AttachMenu: FC<OwnProps> = ({
const bots = useMemo(() => {
return attachBots
? Object.values(attachBots).filter((bot) => {
if (!peerType) return false;
if (peerType === 'bots' && bot.id === chatId && bot.peerTypes.includes('self')) {
if (!peerType || !bot.isForAttachMenu) return false;
if (peerType === 'bots' && bot.id === chatId && bot.attachMenuPeerTypes.includes('self')) {
return true;
}
return bot.peerTypes.includes(peerType);
return bot.attachMenuPeerTypes!.includes(peerType);
})
: undefined;
}, [attachBots, chatId, peerType]);

View File

@ -113,6 +113,7 @@ const InlineBotTooltip: FC<OwnProps> = ({
url: switchWebview!.url,
buttonText: switchWebview!.text,
theme,
isFromSwitchWebView: true,
});
});

View File

@ -1,15 +1,15 @@
import type { FC } from '../../../lib/teact/teact';
import React, {
memo, useCallback, useEffect, useState,
memo, useCallback, useEffect, useMemo, useState,
} from '../../../lib/teact/teact';
import { getActions } from '../../../global';
import type { ApiAttachBot } from '../../../api/types';
import { MINI_APP_TOS_URL } from '../../../config';
import renderText from '../../common/helpers/renderText';
import useLang from '../../../hooks/useLang';
import usePrevious from '../../../hooks/usePrevious';
import Checkbox from '../../ui/Checkbox';
import ConfirmDialog from '../../ui/ConfirmDialog';
@ -22,44 +22,51 @@ const AttachBotInstallModal: FC<OwnProps> = ({
bot,
}) => {
const { confirmAttachBotInstall, cancelAttachBotInstall } = getActions();
const [isWriteAllowed, setIsWriteAllowed] = useState(bot?.shouldRequestWriteAccess || false);
const [isTosAccepted, setIsTosAccepted] = useState(false);
const lang = useLang();
const prevBot = usePrevious(bot);
const renderingBot = bot || prevBot;
const handleConfirm = useCallback(() => {
confirmAttachBotInstall({
isWriteAllowed,
isWriteAllowed: Boolean(bot?.shouldRequestWriteAccess),
});
}, [confirmAttachBotInstall, isWriteAllowed]);
}, [confirmAttachBotInstall, bot]);
// Reset on re-open
useEffect(() => {
if (bot) {
setIsWriteAllowed(bot.shouldRequestWriteAccess ?? false);
setIsTosAccepted(false);
}
}, [bot]);
const tosLabel = useMemo(() => {
const base = lang('lng_mini_apps_disclaimer_button');
const split = base.split('{link}');
const linkText = lang('lng_mini_apps_disclaimer_link');
return [
split[0],
<a href={MINI_APP_TOS_URL} target="_blank" rel="noopener noreferrer">{linkText}</a>,
split[1],
];
}, [lang]);
return (
<ConfirmDialog
isOpen={Boolean(bot)}
onClose={cancelAttachBotInstall}
title={renderingBot?.shortName}
title={lang('lng_mini_apps_disclaimer_title')}
confirmHandler={handleConfirm}
isConfirmDisabled={!isTosAccepted}
>
{lang('WebApp.AddToAttachmentText', renderingBot?.shortName)}
{renderingBot?.shouldRequestWriteAccess && (
<Checkbox
className="dialog-checkbox"
checked={isWriteAllowed}
label={renderText(
lang('WebApp.AddToAttachmentAllowMessages', renderingBot?.shortName),
['simple_markdown'],
)}
onCheck={setIsWriteAllowed}
/>
{renderText(lang('lng_mini_apps_disclaimer_text', bot?.shortName), ['simple_markdown'])}
<Checkbox
className="dialog-checkbox"
checked={isTosAccepted}
label={tosLabel}
onCheck={setIsTosAccepted}
/>
{bot?.isInactive && bot.isForSideMenu && (
renderText(lang('WebBot.Account.Desclaimer.Desc', bot?.shortName), ['simple_markdown'])
)}
</ConfirmDialog>
);

View File

@ -1,10 +1,12 @@
.root {
--color-transition: 0.25s ease-in-out;
:global {
.modal-header {
color: var(--color-header-text);
border-bottom: 1px solid var(--color-dividers);
padding: 0.5rem;
transition: 0.25s ease-in-out background-color;
transition: var(--color-transition) background-color, var(--color-transition) color;
}
.modal-dialog {
@ -43,7 +45,14 @@
}
}
.more-button {
opacity: 0.75;
color: var(--color-header-text) !important;
transition: var(--color-transition) color;
}
.close-icon {
opacity: 0.75;
position: absolute;
transform: rotate(-45deg);
@ -53,8 +62,8 @@
width: 1.125rem;
height: 0.125rem;
border-radius: 0.125rem;
background-color: var(--color-text-secondary);
transition: transform var(--slide-transition);
background-color: var(--color-header-text);
transition: var(--slide-transition) transform, var(--color-transition) background-color;
}
&::before,

View File

@ -15,6 +15,9 @@ import {
selectCurrentChat, selectTabState, selectTheme, selectUser,
} from '../../../global/selectors';
import buildClassName from '../../../util/buildClassName';
import buildStyle from '../../../util/buildStyle';
import { getColorLuma } from '../../../util/colors';
import { hexToRgb } from '../../../util/switchTheme';
import { extractCurrentThemeParams, validateHexColor } from '../../../util/themeStyle';
import { callApi } from '../../../api/gramjs';
@ -65,6 +68,7 @@ const MAIN_BUTTON_ANIMATION_TIME = 250;
const PROLONG_INTERVAL = 45000; // 45s
const ANIMATION_WAIT = 400;
const POPUP_SEQUENTIAL_LIMIT = 3;
const LUMA_THRESHOLD = 128;
const POPUP_RESET_DELAY = 2000; // 2s
const SANDBOX_ATTRIBUTES = [
'allow-scripts',
@ -366,11 +370,18 @@ const WebAppModal: FC<OwnProps & StateProps> = ({
}
if (eventType === 'web_app_set_header_color') {
const themeParams = extractCurrentThemeParams();
const key = eventData.color_key;
const newColor = themeParams[key];
const color = validateHexColor(newColor) ? newColor : themeParams.bg_color;
setHeaderColor(color);
if (eventData.color_key) {
const themeParams = extractCurrentThemeParams();
const key = eventData.color_key;
const newColor = themeParams[key];
const color = validateHexColor(newColor) ? newColor : headerColor;
setHeaderColor(color);
}
if (eventData.color) {
const color = validateHexColor(eventData.color) ? eventData.color : headerColor;
setHeaderColor(color);
}
}
if (eventType === 'web_app_data_send') {
@ -459,7 +470,7 @@ const WebAppModal: FC<OwnProps & StateProps> = ({
ripple={!isMobile}
size="smaller"
color="translucent"
className={isMenuOpen ? 'active' : ''}
className={buildClassName(styles.moreButton, isMenuOpen && 'active')}
onClick={onTrigger}
ariaLabel="More actions"
>
@ -473,9 +484,23 @@ const WebAppModal: FC<OwnProps & StateProps> = ({
isBackButtonVisible && styles.stateBack,
);
const headerTextVar = useMemo(() => {
if (!headerColor) return undefined;
const { r, g, b } = hexToRgb(headerColor);
const luma = getColorLuma([r, g, b]);
const adaptedLuma = theme === 'dark' ? 255 - luma : luma;
return adaptedLuma > LUMA_THRESHOLD ? 'color-text' : 'color-background';
}, [headerColor, theme]);
function renderHeader() {
return (
<div className="modal-header" style={`background-color: ${headerColor}`}>
<div
className="modal-header"
style={buildStyle(
headerColor && `background-color: ${headerColor}`,
headerTextVar && `--color-header-text: var(--${headerTextVar})`,
)}
>
<Button
round
color="translucent"

View File

@ -13,34 +13,36 @@ import Modal from './Modal';
type OwnProps = {
isOpen: boolean;
onClose: () => void;
onCloseAnimationEnd?: () => void;
title?: string;
header?: TeactNode;
textParts?: TextPart;
text?: string;
confirmLabel?: string;
confirmHandler: () => void;
confirmIsDestructive?: boolean;
isConfirmDisabled?: boolean;
areButtonsInColumn?: boolean;
className?: string;
children?: React.ReactNode;
confirmHandler: NoneToVoidFunction;
onClose: NoneToVoidFunction;
onCloseAnimationEnd?: NoneToVoidFunction;
};
const ConfirmDialog: FC<OwnProps> = ({
isOpen,
onClose,
onCloseAnimationEnd,
title,
header,
text,
textParts,
confirmLabel = 'Confirm',
confirmHandler,
confirmIsDestructive,
isConfirmDisabled,
areButtonsInColumn,
className,
children,
confirmHandler,
onClose,
onCloseAnimationEnd,
}) => {
const lang = useLang();
@ -76,6 +78,7 @@ const ConfirmDialog: FC<OwnProps> = ({
isText
onClick={confirmHandler}
color={confirmIsDestructive ? 'danger' : 'primary'}
disabled={isConfirmDisabled}
>
{confirmLabel}
</Button>

View File

@ -51,7 +51,7 @@ export const CUSTOM_EMOJI_PREVIEW_CACHE_DISABLED = false;
export const CUSTOM_EMOJI_PREVIEW_CACHE_NAME = 'tt-custom-emoji-preview';
export const MEDIA_CACHE_MAX_BYTES = 512 * 1024; // 512 KB
export const CUSTOM_BG_CACHE_NAME = 'tt-custom-bg';
export const LANG_CACHE_NAME = 'tt-lang-packs-v22';
export const LANG_CACHE_NAME = 'tt-lang-packs-v23';
export const ASSET_CACHE_NAME = 'tt-assets';
export const AUTODOWNLOAD_FILESIZE_MB_LIMITS = [1, 5, 10, 50, 100, 500];
export const DATA_BROADCAST_CHANNEL_NAME = 'tt-global';
@ -293,6 +293,7 @@ export const DEFAULT_LANG_CODE = 'en';
export const DEFAULT_LANG_PACK = 'android';
export const LANG_PACKS = ['android', 'ios', 'tdesktop', 'macos'] as const;
export const FEEDBACK_URL = 'https://bugs.telegram.org/?tag_ids=41&sort=time';
export const MINI_APP_TOS_URL = 'https://telegram.org/tos/mini-apps';
export const GENERAL_TOPIC_ID = 1;
export const STORY_EXPIRE_PERIOD = 86400; // 1 day
export const STORY_VIEWERS_EXPIRE_PERIOD = 86400; // 1 day

View File

@ -452,7 +452,7 @@ addActionHandler('sharePhoneWithBot', async (global, actions, payload): Promise<
addActionHandler('requestSimpleWebView', async (global, actions, payload): Promise<void> => {
const {
url, botId, theme, buttonText,
url, botId, theme, buttonText, isFromSideMenu, isFromSwitchWebView, startParam,
tabId = getCurrentTabId(),
} = payload;
@ -474,7 +474,14 @@ addActionHandler('requestSimpleWebView', async (global, actions, payload): Promi
return;
}
const webViewUrl = await callApi('requestSimpleWebView', { url, bot, theme });
const webViewUrl = await callApi('requestSimpleWebView', {
url,
bot,
theme,
startParam,
isFromSideMenu,
isFromSwitchWebView,
});
if (!webViewUrl) {
return;
}
@ -724,16 +731,8 @@ addActionHandler('toggleAttachBot', async (global, actions, payload): Promise<vo
if (!bot) return;
await toggleAttachBot(global, bot, isEnabled, isWriteAllowed);
});
async function toggleAttachBot<T extends GlobalState>(
global: T, bot: ApiUser, isEnabled: boolean, isWriteAllowed?: boolean,
) {
await callApi('toggleAttachBot', { bot, isWriteAllowed, isEnabled });
global = getGlobal();
await loadAttachBots(global);
}
});
async function loadAttachBots<T extends GlobalState>(global: T, hash?: string) {
const result = await callApi('loadAttachBots', { hash });
@ -755,33 +754,52 @@ async function loadAttachBots<T extends GlobalState>(global: T, hash?: string) {
addActionHandler('callAttachBot', (global, actions, payload): ActionReturnType => {
const {
chatId, bot, url, startParam, threadId,
chatId, bot, url, startParam, threadId, isFromSideMenu,
tabId = getCurrentTabId(),
} = payload;
const isFromBotMenu = !bot;
if (!isFromBotMenu && !global.attachMenu.bots[bot.id]) {
if ((!isFromBotMenu && !global.attachMenu.bots[bot.id])
|| (isFromSideMenu && (bot?.isInactive || bot?.isDisclaimerNeeded))) {
return updateTabState(global, {
requestedAttachBotInstall: {
bot,
onConfirm: {
action: 'callAttachBot',
payload,
payload: {
...payload,
bot: {
...bot,
isInactive: false,
isDisclaimerNeeded: false,
},
},
},
},
}, tabId);
}
const theme = extractCurrentThemeParams();
actions.openChat({ id: chatId, threadId, tabId });
actions.requestWebView({
url,
peerId: chatId,
botId: isFromBotMenu ? chatId : bot.id,
theme,
buttonText: '',
isFromBotMenu,
startParam,
tabId,
});
if (isFromSideMenu) {
actions.requestSimpleWebView({
botId: bot!.id,
buttonText: '',
isFromSideMenu: true,
theme,
tabId,
});
} else {
actions.openChat({ id: chatId, threadId, tabId });
actions.requestWebView({
url,
peerId: chatId,
botId: isFromBotMenu ? chatId : bot.id,
theme,
buttonText: '',
isFromBotMenu,
startParam,
tabId,
});
}
return undefined;
});
@ -800,7 +818,7 @@ addActionHandler('confirmAttachBotInstall', async (global, actions, payload): Pr
const botUser = selectUser(global, bot.id);
if (!botUser) return;
await toggleAttachBot(global, botUser, true, isWriteAllowed);
await callApi('toggleAttachBot', { bot: botUser, isWriteAllowed, isEnabled: true });
if (onConfirm) {
const { action, payload: actionPayload } = onConfirm;
// @ts-ignore
@ -821,11 +839,11 @@ addActionHandler('requestAttachBotInChat', (global, actions, payload): ActionRet
} = payload;
const currentChatId = selectCurrentMessageList(global, tabId)?.chatId;
const supportedFilters = bot.peerTypes.filter((type): type is ApiChatType => (
const supportedFilters = bot.attachMenuPeerTypes?.filter((type): type is ApiChatType => (
type !== 'self' && filter.includes(type)
));
if (!supportedFilters.length) {
if (!supportedFilters?.length) {
actions.callAttachBot({
chatId: currentChatId || bot.id,
bot,

View File

@ -141,6 +141,10 @@ addActionHandler('apiUpdate', (global, actions, update): ActionReturnType => {
global = updateStealthMode(global, update.stealthMode);
setGlobal(global);
break;
case 'updateAttachMenuBots':
actions.loadAttachBots({ hash: global.attachMenu.hash });
break;
}
return undefined;

View File

@ -2346,10 +2346,13 @@ export interface ActionPayloads {
threadId?: number;
} & WithTabId;
requestSimpleWebView: {
url: string;
url?: string;
botId: string;
buttonText: string;
theme?: ApiThemeParameters;
startParam?: string;
isFromSwitchWebView?: boolean;
isFromSideMenu?: boolean;
} & WithTabId;
requestAppWebView: {
botId: string;
@ -2407,6 +2410,7 @@ export interface ActionPayloads {
bot?: ApiAttachBot;
url?: string;
startParam?: string;
isFromSideMenu?: boolean;
} & WithTabId;
requestBotUrlAuth: {

View File

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

View File

@ -86,7 +86,7 @@ namespace Api {
export type TypeImportedContact = ImportedContact;
export type TypeContactStatus = ContactStatus;
export type TypeMessagesFilter = InputMessagesFilterEmpty | InputMessagesFilterPhotos | InputMessagesFilterVideo | InputMessagesFilterPhotoVideo | InputMessagesFilterDocument | InputMessagesFilterUrl | InputMessagesFilterGif | InputMessagesFilterVoice | InputMessagesFilterMusic | InputMessagesFilterChatPhotos | InputMessagesFilterPhoneCalls | InputMessagesFilterRoundVoice | InputMessagesFilterRoundVideo | InputMessagesFilterMyMentions | InputMessagesFilterGeo | InputMessagesFilterContacts | InputMessagesFilterPinned;
export type TypeUpdate = UpdateNewMessage | UpdateMessageID | UpdateDeleteMessages | UpdateUserTyping | UpdateChatUserTyping | UpdateChatParticipants | UpdateUserStatus | UpdateUserName | UpdateNewEncryptedMessage | UpdateEncryptedChatTyping | UpdateEncryption | UpdateEncryptedMessagesRead | UpdateChatParticipantAdd | UpdateChatParticipantDelete | UpdateDcOptions | UpdateNotifySettings | UpdateServiceNotification | UpdatePrivacy | UpdateUserPhone | UpdateReadHistoryInbox | UpdateReadHistoryOutbox | UpdateWebPage | UpdateReadMessagesContents | UpdateChannelTooLong | UpdateChannel | UpdateNewChannelMessage | UpdateReadChannelInbox | UpdateDeleteChannelMessages | UpdateChannelMessageViews | UpdateChatParticipantAdmin | UpdateNewStickerSet | UpdateStickerSetsOrder | UpdateStickerSets | UpdateSavedGifs | UpdateBotInlineQuery | UpdateBotInlineSend | UpdateEditChannelMessage | UpdateBotCallbackQuery | UpdateEditMessage | UpdateInlineBotCallbackQuery | UpdateReadChannelOutbox | UpdateDraftMessage | UpdateReadFeaturedStickers | UpdateRecentStickers | UpdateConfig | UpdatePtsChanged | UpdateChannelWebPage | UpdateDialogPinned | UpdatePinnedDialogs | UpdateBotWebhookJSON | UpdateBotWebhookJSONQuery | UpdateBotShippingQuery | UpdateBotPrecheckoutQuery | UpdatePhoneCall | UpdateLangPackTooLong | UpdateLangPack | UpdateFavedStickers | UpdateChannelReadMessagesContents | UpdateContactsReset | UpdateChannelAvailableMessages | UpdateDialogUnreadMark | UpdateMessagePoll | UpdateChatDefaultBannedRights | UpdateFolderPeers | UpdatePeerSettings | UpdatePeerLocated | UpdateNewScheduledMessage | UpdateDeleteScheduledMessages | UpdateTheme | UpdateGeoLiveViewed | UpdateLoginToken | UpdateMessagePollVote | UpdateDialogFilter | UpdateDialogFilterOrder | UpdateDialogFilters | UpdatePhoneCallSignalingData | UpdateChannelMessageForwards | UpdateReadChannelDiscussionInbox | UpdateReadChannelDiscussionOutbox | UpdatePeerBlocked | UpdateChannelUserTyping | UpdatePinnedMessages | UpdatePinnedChannelMessages | UpdateChat | UpdateGroupCallParticipants | UpdateGroupCall | UpdatePeerHistoryTTL | UpdateChatParticipant | UpdateChannelParticipant | UpdateBotStopped | UpdateGroupCallConnection | UpdateBotCommands | UpdatePendingJoinRequests | UpdateBotChatInviteRequester | UpdateMessageReactions | UpdateAttachMenuBots | UpdateWebViewResultSent | UpdateBotMenuButton | UpdateSavedRingtones | UpdateTranscribedAudio | UpdateReadFeaturedEmojiStickers | UpdateUserEmojiStatus | UpdateRecentEmojiStatuses | UpdateRecentReactions | UpdateMoveStickerSetToTop | UpdateMessageExtendedMedia | UpdateChannelPinnedTopic | UpdateChannelPinnedTopics | UpdateUser | UpdateAutoSaveSettings | UpdateGroupInvitePrivacyForbidden | UpdateStory | UpdateReadStories | UpdateStoryID | UpdateStoriesStealthMode | UpdateSentStoryReaction;
export type TypeUpdate = UpdateNewMessage | UpdateMessageID | UpdateDeleteMessages | UpdateUserTyping | UpdateChatUserTyping | UpdateChatParticipants | UpdateUserStatus | UpdateUserName | UpdateNewAuthorization | UpdateNewEncryptedMessage | UpdateEncryptedChatTyping | UpdateEncryption | UpdateEncryptedMessagesRead | UpdateChatParticipantAdd | UpdateChatParticipantDelete | UpdateDcOptions | UpdateNotifySettings | UpdateServiceNotification | UpdatePrivacy | UpdateUserPhone | UpdateReadHistoryInbox | UpdateReadHistoryOutbox | UpdateWebPage | UpdateReadMessagesContents | UpdateChannelTooLong | UpdateChannel | UpdateNewChannelMessage | UpdateReadChannelInbox | UpdateDeleteChannelMessages | UpdateChannelMessageViews | UpdateChatParticipantAdmin | UpdateNewStickerSet | UpdateStickerSetsOrder | UpdateStickerSets | UpdateSavedGifs | UpdateBotInlineQuery | UpdateBotInlineSend | UpdateEditChannelMessage | UpdateBotCallbackQuery | UpdateEditMessage | UpdateInlineBotCallbackQuery | UpdateReadChannelOutbox | UpdateDraftMessage | UpdateReadFeaturedStickers | UpdateRecentStickers | UpdateConfig | UpdatePtsChanged | UpdateChannelWebPage | UpdateDialogPinned | UpdatePinnedDialogs | UpdateBotWebhookJSON | UpdateBotWebhookJSONQuery | UpdateBotShippingQuery | UpdateBotPrecheckoutQuery | UpdatePhoneCall | UpdateLangPackTooLong | UpdateLangPack | UpdateFavedStickers | UpdateChannelReadMessagesContents | UpdateContactsReset | UpdateChannelAvailableMessages | UpdateDialogUnreadMark | UpdateMessagePoll | UpdateChatDefaultBannedRights | UpdateFolderPeers | UpdatePeerSettings | UpdatePeerLocated | UpdateNewScheduledMessage | UpdateDeleteScheduledMessages | UpdateTheme | UpdateGeoLiveViewed | UpdateLoginToken | UpdateMessagePollVote | UpdateDialogFilter | UpdateDialogFilterOrder | UpdateDialogFilters | UpdatePhoneCallSignalingData | UpdateChannelMessageForwards | UpdateReadChannelDiscussionInbox | UpdateReadChannelDiscussionOutbox | UpdatePeerBlocked | UpdateChannelUserTyping | UpdatePinnedMessages | UpdatePinnedChannelMessages | UpdateChat | UpdateGroupCallParticipants | UpdateGroupCall | UpdatePeerHistoryTTL | UpdateChatParticipant | UpdateChannelParticipant | UpdateBotStopped | UpdateGroupCallConnection | UpdateBotCommands | UpdatePendingJoinRequests | UpdateBotChatInviteRequester | UpdateMessageReactions | UpdateAttachMenuBots | UpdateWebViewResultSent | UpdateBotMenuButton | UpdateSavedRingtones | UpdateTranscribedAudio | UpdateReadFeaturedEmojiStickers | UpdateUserEmojiStatus | UpdateRecentEmojiStatuses | UpdateRecentReactions | UpdateMoveStickerSetToTop | UpdateMessageExtendedMedia | UpdateChannelPinnedTopic | UpdateChannelPinnedTopics | UpdateUser | UpdateAutoSaveSettings | UpdateGroupInvitePrivacyForbidden | UpdateStory | UpdateReadStories | UpdateStoryID | UpdateStoriesStealthMode | UpdateSentStoryReaction;
export type TypeUpdates = UpdatesTooLong | UpdateShortMessage | UpdateShortChatMessage | UpdateShort | UpdatesCombined | Updates | UpdateShortSentMessage;
export type TypeDcOption = DcOption;
export type TypeConfig = Config;
@ -2371,6 +2371,21 @@ namespace Api {
lastName: string;
usernames: Api.TypeUsername[];
};
export class UpdateNewAuthorization extends VirtualClass<{
// flags: undefined;
unconfirmed?: true;
hash: long;
date?: int;
device?: string;
location?: string;
}> {
// flags: undefined;
unconfirmed?: true;
hash: long;
date?: int;
device?: string;
location?: string;
};
export class UpdateNewEncryptedMessage extends VirtualClass<{
message: Api.TypeEncryptedMessage;
qts: int;
@ -2502,13 +2517,17 @@ namespace Api {
ptsCount: int;
};
export class UpdateReadMessagesContents extends VirtualClass<{
// flags: undefined;
messages: int[];
pts: int;
ptsCount: int;
date?: int;
}> {
// flags: undefined;
messages: int[];
pts: int;
ptsCount: int;
date?: int;
};
export class UpdateChannelTooLong extends VirtualClass<{
// flags: undefined;
@ -4013,6 +4032,7 @@ namespace Api {
passwordPending?: true;
encryptedRequestsDisabled?: true;
callRequestsDisabled?: true;
unconfirmed?: true;
hash: long;
deviceModel: string;
platform: string;
@ -4032,6 +4052,7 @@ namespace Api {
passwordPending?: true;
encryptedRequestsDisabled?: true;
callRequestsDisabled?: true;
unconfirmed?: true;
hash: long;
deviceModel: string;
platform: string;
@ -7812,18 +7833,24 @@ namespace Api {
inactive?: true;
hasSettings?: true;
requestWriteAccess?: true;
showInAttachMenu?: true;
showInSideMenu?: true;
sideMenuDisclaimerNeeded?: true;
botId: long;
shortName: string;
peerTypes: Api.TypeAttachMenuPeerType[];
peerTypes?: Api.TypeAttachMenuPeerType[];
icons: Api.TypeAttachMenuBotIcon[];
}> {
// flags: undefined;
inactive?: true;
hasSettings?: true;
requestWriteAccess?: true;
showInAttachMenu?: true;
showInSideMenu?: true;
sideMenuDisclaimerNeeded?: true;
botId: long;
shortName: string;
peerTypes: Api.TypeAttachMenuPeerType[];
peerTypes?: Api.TypeAttachMenuPeerType[];
icons: Api.TypeAttachMenuBotIcon[];
};
export class AttachMenuBotsNotModified extends VirtualClass<void> {};
@ -9669,11 +9696,13 @@ namespace Api {
// flags: undefined;
inactive?: true;
requestWriteAccess?: true;
hasSettings?: true;
app: Api.TypeBotApp;
}> {
// flags: undefined;
inactive?: true;
requestWriteAccess?: true;
hasSettings?: true;
app: Api.TypeBotApp;
};
}
@ -11476,11 +11505,13 @@ namespace Api {
};
export class ChangeAuthorizationSettings extends Request<Partial<{
// flags: undefined;
confirmed?: true;
hash: long;
encryptedRequestsDisabled?: Bool;
callRequestsDisabled?: Bool;
}>, Bool> {
// flags: undefined;
confirmed?: true;
hash: long;
encryptedRequestsDisabled?: Bool;
callRequestsDisabled?: Bool;
@ -13409,15 +13440,19 @@ namespace Api {
export class RequestSimpleWebView extends Request<Partial<{
// flags: undefined;
fromSwitchWebview?: true;
fromSideMenu?: true;
bot: Api.TypeInputUser;
url: string;
url?: string;
startParam?: string;
themeParams?: Api.TypeDataJSON;
platform: string;
}>, Api.TypeSimpleWebViewResult> {
// flags: undefined;
fromSwitchWebview?: true;
fromSideMenu?: true;
bot: Api.TypeInputUser;
url: string;
url?: string;
startParam?: string;
themeParams?: Api.TypeDataJSON;
platform: string;
};

View File

@ -226,6 +226,7 @@ updateChatUserTyping#83487af0 chat_id:long from_id:Peer action:SendMessageAction
updateChatParticipants#7761198 participants:ChatParticipants = Update;
updateUserStatus#e5bdf8de user_id:long status:UserStatus = Update;
updateUserName#a7848924 user_id:long first_name:string last_name:string usernames:Vector<Username> = Update;
updateNewAuthorization#8951abef flags:# unconfirmed:flags.0?true hash:long date:flags.0?int device:flags.0?string location:flags.0?string = Update;
updateNewEncryptedMessage#12bcbd9a message:EncryptedMessage qts:int = Update;
updateEncryptedChatTyping#1710f156 chat_id:int = Update;
updateEncryption#b4a2e88d chat:EncryptedChat date:int = Update;
@ -240,7 +241,7 @@ updateUserPhone#5492a13 user_id:long phone:string = Update;
updateReadHistoryInbox#9c974fdf flags:# folder_id:flags.0?int peer:Peer max_id:int still_unread_count:int pts:int pts_count:int = Update;
updateReadHistoryOutbox#2f2f21bf peer:Peer max_id:int pts:int pts_count:int = Update;
updateWebPage#7f891213 webpage:WebPage pts:int pts_count:int = Update;
updateReadMessagesContents#68c13933 messages:Vector<int> pts:int pts_count:int = Update;
updateReadMessagesContents#f8227181 flags:# messages:Vector<int> pts:int pts_count:int date:flags.0?int = Update;
updateChannelTooLong#108d941f flags:# channel_id:long pts:flags.0?int = Update;
updateChannel#635b4c09 channel_id:long = Update;
updateNewChannelMessage#62ba04d9 message:Message pts:int pts_count:int = Update;
@ -462,7 +463,7 @@ webPageEmpty#eb1477e8 id:long = WebPage;
webPagePending#c586da1c id:long date:int = WebPage;
webPage#e89c45b2 flags:# id:long url:string display_url:string hash:int type:flags.0?string site_name:flags.1?string title:flags.2?string description:flags.3?string photo:flags.4?Photo embed_url:flags.5?string embed_type:flags.5?string embed_width:flags.6?int embed_height:flags.6?int duration:flags.7?int author:flags.8?string document:flags.9?Document cached_page:flags.10?Page attributes:flags.12?Vector<WebPageAttribute> = WebPage;
webPageNotModified#7311ca11 flags:# cached_page_views:flags.0?int = WebPage;
authorization#ad01d61d flags:# current:flags.0?true official_app:flags.1?true password_pending:flags.2?true encrypted_requests_disabled:flags.3?true call_requests_disabled:flags.4?true hash:long device_model:string platform:string system_version:string api_id:int app_name:string app_version:string date_created:int date_active:int ip:string country:string region:string = Authorization;
authorization#ad01d61d flags:# current:flags.0?true official_app:flags.1?true password_pending:flags.2?true encrypted_requests_disabled:flags.3?true call_requests_disabled:flags.4?true unconfirmed:flags.5?true hash:long device_model:string platform:string system_version:string api_id:int app_name:string app_version:string date_created:int date_active:int ip:string country:string region:string = Authorization;
account.authorizations#4bff8ea0 authorization_ttl_days:int authorizations:Vector<Authorization> = account.Authorizations;
account.password#957b50fb flags:# has_recovery:flags.0?true has_secure_values:flags.1?true has_password:flags.2?true current_algo:flags.2?PasswordKdfAlgo srp_B:flags.2?bytes srp_id:flags.2?long hint:flags.3?string email_unconfirmed_pattern:flags.4?string new_algo:PasswordKdfAlgo new_secure_algo:SecurePasswordKdfAlgo secure_random:bytes pending_reset_date:flags.5?int login_email_pattern:flags.6?string = account.Password;
account.passwordSettings#9a5c33e5 flags:# email:flags.0?string secure_settings:flags.1?SecureSecretSettings = account.PasswordSettings;
@ -1027,7 +1028,7 @@ phone.groupCallStreamChannels#d0e482b2 channels:Vector<GroupCallStreamChannel> =
phone.groupCallStreamRtmpUrl#2dbf3432 url:string key:string = phone.GroupCallStreamRtmpUrl;
attachMenuBotIconColor#4576f3f0 name:string color:int = AttachMenuBotIconColor;
attachMenuBotIcon#b2a7386b flags:# name:string icon:Document colors:flags.0?Vector<AttachMenuBotIconColor> = AttachMenuBotIcon;
attachMenuBot#c8aa2cd2 flags:# inactive:flags.0?true has_settings:flags.1?true request_write_access:flags.2?true bot_id:long short_name:string peer_types:Vector<AttachMenuPeerType> icons:Vector<AttachMenuBotIcon> = AttachMenuBot;
attachMenuBot#d90d8dfe flags:# inactive:flags.0?true has_settings:flags.1?true request_write_access:flags.2?true show_in_attach_menu:flags.3?true show_in_side_menu:flags.4?true side_menu_disclaimer_needed:flags.5?true bot_id:long short_name:string peer_types:flags.3?Vector<AttachMenuPeerType> icons:Vector<AttachMenuBotIcon> = AttachMenuBot;
attachMenuBotsNotModified#f1d88a5c = AttachMenuBots;
attachMenuBots#3c4301c0 hash:long bots:Vector<AttachMenuBot> users:Vector<User> = AttachMenuBots;
attachMenuBotsBot#93bf667f bot:AttachMenuBot users:Vector<User> = AttachMenuBotsBot;
@ -1110,7 +1111,7 @@ inputBotAppID#a920bd7a id:long access_hash:long = InputBotApp;
inputBotAppShortName#908c0407 bot_id:InputUser short_name:string = InputBotApp;
botAppNotModified#5da674b7 = BotApp;
botApp#95fcd1d6 flags:# id:long access_hash:long short_name:string title:string description:string photo:Photo document:flags.0?Document hash:long = BotApp;
messages.botApp#eb50adf5 flags:# inactive:flags.0?true request_write_access:flags.1?true app:BotApp = messages.BotApp;
messages.botApp#eb50adf5 flags:# inactive:flags.0?true request_write_access:flags.1?true has_settings:flags.2?true app:BotApp = messages.BotApp;
appWebViewResultUrl#3c1b4f0d url:string = AppWebViewResult;
inlineBotWebView#b57295d5 text:string url:string = InlineBotWebView;
readParticipantDate#4a4ff172 user_id:long date:int = ReadParticipantDate;
@ -1201,7 +1202,7 @@ account.getGlobalPrivacySettings#eb2b4cf6 = GlobalPrivacySettings;
account.setGlobalPrivacySettings#1edaaac2 settings:GlobalPrivacySettings = GlobalPrivacySettings;
account.reportProfilePhoto#fa8cc6f5 peer:InputPeer photo_id:InputPhoto reason:ReportReason message:string = Bool;
account.setAuthorizationTTL#bf899aa0 authorization_ttl_days:int = Bool;
account.changeAuthorizationSettings#40f48462 flags:# hash:long encrypted_requests_disabled:flags.0?Bool call_requests_disabled:flags.1?Bool = Bool;
account.changeAuthorizationSettings#40f48462 flags:# confirmed:flags.3?true hash:long encrypted_requests_disabled:flags.0?Bool call_requests_disabled:flags.1?Bool = Bool;
account.updateEmojiStatus#fbd3de6b emoji_status:EmojiStatus = Bool;
account.getRecentEmojiStatuses#f578105 hash:long = account.EmojiStatuses;
account.reorderUsernames#ef500eab order:Vector<string> = Bool;
@ -1331,7 +1332,7 @@ messages.getAttachMenuBot#77216192 bot:InputUser = AttachMenuBotsBot;
messages.toggleBotInAttachMenu#69f59d69 flags:# write_allowed:flags.0?true bot:InputUser enabled:Bool = Bool;
messages.requestWebView#269dc2c1 flags:# from_bot_menu:flags.4?true silent:flags.5?true peer:InputPeer bot:InputUser url:flags.1?string start_param:flags.3?string theme_params:flags.2?DataJSON platform:string reply_to:flags.0?InputReplyTo send_as:flags.13?InputPeer = WebViewResult;
messages.prolongWebView#b0d81a83 flags:# silent:flags.5?true peer:InputPeer bot:InputUser query_id:long reply_to:flags.0?InputReplyTo send_as:flags.13?InputPeer = Bool;
messages.requestSimpleWebView#299bec8e flags:# from_switch_webview:flags.1?true bot:InputUser url:string theme_params:flags.0?DataJSON platform:string = SimpleWebViewResult;
messages.requestSimpleWebView#1a46500a flags:# from_switch_webview:flags.1?true from_side_menu:flags.2?true bot:InputUser url:flags.3?string start_param:flags.4?string theme_params:flags.0?DataJSON platform:string = SimpleWebViewResult;
messages.sendWebViewResultMessage#a4314f5 bot_query_id:string result:InputBotInlineResult = WebViewMessageSent;
messages.sendWebViewData#dc0242c8 bot:InputUser random_id:long button_text:string data:string = Updates;
messages.transcribeAudio#269e9a49 peer:InputPeer msg_id:int = messages.TranscribedAudio;

View File

@ -279,6 +279,7 @@ updateChatUserTyping#83487af0 chat_id:long from_id:Peer action:SendMessageAction
updateChatParticipants#7761198 participants:ChatParticipants = Update;
updateUserStatus#e5bdf8de user_id:long status:UserStatus = Update;
updateUserName#a7848924 user_id:long first_name:string last_name:string usernames:Vector<Username> = Update;
updateNewAuthorization#8951abef flags:# unconfirmed:flags.0?true hash:long date:flags.0?int device:flags.0?string location:flags.0?string = Update;
updateNewEncryptedMessage#12bcbd9a message:EncryptedMessage qts:int = Update;
updateEncryptedChatTyping#1710f156 chat_id:int = Update;
updateEncryption#b4a2e88d chat:EncryptedChat date:int = Update;
@ -293,7 +294,7 @@ updateUserPhone#5492a13 user_id:long phone:string = Update;
updateReadHistoryInbox#9c974fdf flags:# folder_id:flags.0?int peer:Peer max_id:int still_unread_count:int pts:int pts_count:int = Update;
updateReadHistoryOutbox#2f2f21bf peer:Peer max_id:int pts:int pts_count:int = Update;
updateWebPage#7f891213 webpage:WebPage pts:int pts_count:int = Update;
updateReadMessagesContents#68c13933 messages:Vector<int> pts:int pts_count:int = Update;
updateReadMessagesContents#f8227181 flags:# messages:Vector<int> pts:int pts_count:int date:flags.0?int = Update;
updateChannelTooLong#108d941f flags:# channel_id:long pts:flags.0?int = Update;
updateChannel#635b4c09 channel_id:long = Update;
updateNewChannelMessage#62ba04d9 message:Message pts:int pts_count:int = Update;
@ -552,7 +553,7 @@ webPagePending#c586da1c id:long date:int = WebPage;
webPage#e89c45b2 flags:# id:long url:string display_url:string hash:int type:flags.0?string site_name:flags.1?string title:flags.2?string description:flags.3?string photo:flags.4?Photo embed_url:flags.5?string embed_type:flags.5?string embed_width:flags.6?int embed_height:flags.6?int duration:flags.7?int author:flags.8?string document:flags.9?Document cached_page:flags.10?Page attributes:flags.12?Vector<WebPageAttribute> = WebPage;
webPageNotModified#7311ca11 flags:# cached_page_views:flags.0?int = WebPage;
authorization#ad01d61d flags:# current:flags.0?true official_app:flags.1?true password_pending:flags.2?true encrypted_requests_disabled:flags.3?true call_requests_disabled:flags.4?true hash:long device_model:string platform:string system_version:string api_id:int app_name:string app_version:string date_created:int date_active:int ip:string country:string region:string = Authorization;
authorization#ad01d61d flags:# current:flags.0?true official_app:flags.1?true password_pending:flags.2?true encrypted_requests_disabled:flags.3?true call_requests_disabled:flags.4?true unconfirmed:flags.5?true hash:long device_model:string platform:string system_version:string api_id:int app_name:string app_version:string date_created:int date_active:int ip:string country:string region:string = Authorization;
account.authorizations#4bff8ea0 authorization_ttl_days:int authorizations:Vector<Authorization> = account.Authorizations;
@ -1369,7 +1370,7 @@ attachMenuBotIconColor#4576f3f0 name:string color:int = AttachMenuBotIconColor;
attachMenuBotIcon#b2a7386b flags:# name:string icon:Document colors:flags.0?Vector<AttachMenuBotIconColor> = AttachMenuBotIcon;
attachMenuBot#c8aa2cd2 flags:# inactive:flags.0?true has_settings:flags.1?true request_write_access:flags.2?true bot_id:long short_name:string peer_types:Vector<AttachMenuPeerType> icons:Vector<AttachMenuBotIcon> = AttachMenuBot;
attachMenuBot#d90d8dfe flags:# inactive:flags.0?true has_settings:flags.1?true request_write_access:flags.2?true show_in_attach_menu:flags.3?true show_in_side_menu:flags.4?true side_menu_disclaimer_needed:flags.5?true bot_id:long short_name:string peer_types:flags.3?Vector<AttachMenuPeerType> icons:Vector<AttachMenuBotIcon> = AttachMenuBot;
attachMenuBotsNotModified#f1d88a5c = AttachMenuBots;
attachMenuBots#3c4301c0 hash:long bots:Vector<AttachMenuBot> users:Vector<User> = AttachMenuBots;
@ -1499,7 +1500,7 @@ inputBotAppShortName#908c0407 bot_id:InputUser short_name:string = InputBotApp;
botAppNotModified#5da674b7 = BotApp;
botApp#95fcd1d6 flags:# id:long access_hash:long short_name:string title:string description:string photo:Photo document:flags.0?Document hash:long = BotApp;
messages.botApp#eb50adf5 flags:# inactive:flags.0?true request_write_access:flags.1?true app:BotApp = messages.BotApp;
messages.botApp#eb50adf5 flags:# inactive:flags.0?true request_write_access:flags.1?true has_settings:flags.2?true app:BotApp = messages.BotApp;
appWebViewResultUrl#3c1b4f0d url:string = AppWebViewResult;
@ -1667,7 +1668,7 @@ account.resetPassword#9308ce1b = account.ResetPasswordResult;
account.declinePasswordReset#4c9409f6 = Bool;
account.getChatThemes#d638de89 hash:long = account.Themes;
account.setAuthorizationTTL#bf899aa0 authorization_ttl_days:int = Bool;
account.changeAuthorizationSettings#40f48462 flags:# hash:long encrypted_requests_disabled:flags.0?Bool call_requests_disabled:flags.1?Bool = Bool;
account.changeAuthorizationSettings#40f48462 flags:# confirmed:flags.3?true hash:long encrypted_requests_disabled:flags.0?Bool call_requests_disabled:flags.1?Bool = Bool;
account.getSavedRingtones#e1902288 hash:long = account.SavedRingtones;
account.saveRingtone#3dea5b03 id:InputDocument unsave:Bool = account.SavedRingtone;
account.uploadRingtone#831a83a2 file:InputFile file_name:string mime_type:string = Document;
@ -1879,7 +1880,7 @@ messages.getAttachMenuBot#77216192 bot:InputUser = AttachMenuBotsBot;
messages.toggleBotInAttachMenu#69f59d69 flags:# write_allowed:flags.0?true bot:InputUser enabled:Bool = Bool;
messages.requestWebView#269dc2c1 flags:# from_bot_menu:flags.4?true silent:flags.5?true peer:InputPeer bot:InputUser url:flags.1?string start_param:flags.3?string theme_params:flags.2?DataJSON platform:string reply_to:flags.0?InputReplyTo send_as:flags.13?InputPeer = WebViewResult;
messages.prolongWebView#b0d81a83 flags:# silent:flags.5?true peer:InputPeer bot:InputUser query_id:long reply_to:flags.0?InputReplyTo send_as:flags.13?InputPeer = Bool;
messages.requestSimpleWebView#299bec8e flags:# from_switch_webview:flags.1?true bot:InputUser url:string theme_params:flags.0?DataJSON platform:string = SimpleWebViewResult;
messages.requestSimpleWebView#1a46500a flags:# from_switch_webview:flags.1?true from_side_menu:flags.2?true bot:InputUser url:flags.3?string start_param:flags.4?string theme_params:flags.0?DataJSON platform:string = SimpleWebViewResult;
messages.sendWebViewResultMessage#a4314f5 bot_query_id:string result:InputBotInlineResult = WebViewMessageSent;
messages.sendWebViewData#dc0242c8 bot:InputUser random_id:long button_text:string data:string = Updates;
messages.transcribeAudio#269e9a49 peer:InputPeer msg_id:int = messages.TranscribedAudio;
@ -2121,4 +2122,4 @@ stories.getStoriesViews#9a75d6a6 id:Vector<int> = stories.StoryViews;
stories.exportStoryLink#16e443ce user_id:InputUser id:int = ExportedStoryLink;
stories.report#c95be06a user_id:InputUser id:Vector<int> reason:ReportReason message:string = Bool;
stories.activateStealthMode#57bbd166 flags:# past:flags.0?true future:flags.1?true = Updates;
stories.sendReaction#49aaa9b3 flags:# add_to_recent:flags.0?true user_id:InputUser story_id:int reaction:Reaction = Updates;
stories.sendReaction#49aaa9b3 flags:# add_to_recent:flags.0?true user_id:InputUser story_id:int reaction:Reaction = Updates;

View File

@ -59,7 +59,8 @@ export type WebAppInboundEvent = {
} | {
eventType: 'web_app_set_header_color';
eventData: {
color_key: 'bg_color' | 'secondary_bg_color';
color_key?: 'bg_color' | 'secondary_bg_color';
color?: string;
};
} | {
eventType: 'web_app_open_popup';