Introduce Mini-Apps (#3868)
This commit is contained in:
parent
548430bd2e
commit
acc962bcf5
5
src/@types/global.d.ts
vendored
5
src/@types/global.d.ts
vendored
@ -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;
|
||||
|
||||
@ -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,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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),
|
||||
};
|
||||
},
|
||||
|
||||
255
src/components/left/main/LeftSideMenuItems.tsx
Normal file
255
src/components/left/main/LeftSideMenuItems.tsx
Normal 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));
|
||||
@ -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}
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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]);
|
||||
|
||||
@ -113,6 +113,7 @@ const InlineBotTooltip: FC<OwnProps> = ({
|
||||
url: switchWebview!.url,
|
||||
buttonText: switchWebview!.text,
|
||||
theme,
|
||||
isFromSwitchWebView: true,
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@ -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>
|
||||
);
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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: {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
const api = require('./api');
|
||||
|
||||
const LAYER = 162;
|
||||
const LAYER = 163;
|
||||
const tlobjects = {};
|
||||
|
||||
for (const tl of Object.values(api)) {
|
||||
|
||||
45
src/lib/gramjs/tl/api.d.ts
vendored
45
src/lib/gramjs/tl/api.d.ts
vendored
@ -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;
|
||||
};
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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';
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user