[Perf] Get rid of redundant wrappers: #root, #UiLoader and #LeftColumn
This commit is contained in:
parent
ac1033b673
commit
982ba8c3a7
40
src/components/App.module.scss
Normal file
40
src/components/App.module.scss
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
.bg {
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
background-color: var(--theme-background-color);
|
||||||
|
background-position: center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: 100% 100%;
|
||||||
|
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
height: calc(var(--vh, 1vh) * 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(html.theme-light) & {
|
||||||
|
background-image: url('../assets/chat-bg-br.png');
|
||||||
|
}
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
background-image: url('../assets/chat-bg-pattern-light.png');
|
||||||
|
background-position: top right;
|
||||||
|
background-size: 510px auto;
|
||||||
|
background-repeat: repeat;
|
||||||
|
mix-blend-mode: overlay;
|
||||||
|
|
||||||
|
:global(html.theme-dark) & {
|
||||||
|
background-image: url('../assets/chat-bg-pattern-dark.png');
|
||||||
|
mix-blend-mode: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
bottom: auto;
|
||||||
|
height: calc(var(--vh, 1vh) * 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,37 +1,43 @@
|
|||||||
import type { FC } from './lib/teact/teact';
|
import type { FC } from '../lib/teact/teact';
|
||||||
import React, { useEffect } from './lib/teact/teact';
|
import React, { useEffect, useLayoutEffect } from '../lib/teact/teact';
|
||||||
import { getActions, withGlobal } from './global';
|
import { getActions, withGlobal } from '../global';
|
||||||
|
|
||||||
import type { GlobalState } from './global/types';
|
import type { GlobalState } from '../global/types';
|
||||||
import type { UiLoaderPage } from './components/common/UiLoader';
|
import type { UiLoaderPage } from './common/UiLoader';
|
||||||
|
import type { ThemeKey } from '../types';
|
||||||
|
|
||||||
import { IS_INSTALL_PROMPT_SUPPORTED, IS_MULTITAB_SUPPORTED, PLATFORM_ENV } from './util/windowEnvironment';
|
import { IS_INSTALL_PROMPT_SUPPORTED, IS_MULTITAB_SUPPORTED, PLATFORM_ENV } from '../util/windowEnvironment';
|
||||||
import { INACTIVE_MARKER, PAGE_TITLE } from './config';
|
import {
|
||||||
import { selectTabState } from './global/selectors';
|
DARK_THEME_BG_COLOR, INACTIVE_MARKER, LIGHT_THEME_BG_COLOR, PAGE_TITLE,
|
||||||
import { updateSizes } from './util/windowSize';
|
} from '../config';
|
||||||
import { addActiveTabChangeListener } from './util/activeTabMonitor';
|
import { selectTabState, selectTheme } from '../global/selectors';
|
||||||
import { hasStoredSession } from './util/sessions';
|
import { updateSizes } from '../util/windowSize';
|
||||||
import { setupBeforeInstallPrompt } from './util/installPrompt';
|
import { addActiveTabChangeListener } from '../util/activeTabMonitor';
|
||||||
import buildClassName from './util/buildClassName';
|
import { hasStoredSession } from '../util/sessions';
|
||||||
import { parseInitialLocationHash } from './util/routing';
|
import buildClassName from '../util/buildClassName';
|
||||||
import useFlag from './hooks/useFlag';
|
import { parseInitialLocationHash } from '../util/routing';
|
||||||
import usePrevious from './hooks/usePrevious';
|
import useFlag from '../hooks/useFlag';
|
||||||
import useAppLayout from './hooks/useAppLayout';
|
import usePrevious from '../hooks/usePrevious';
|
||||||
|
import useAppLayout from '../hooks/useAppLayout';
|
||||||
|
|
||||||
import Auth from './components/auth/Auth';
|
import Auth from './auth/Auth';
|
||||||
import Main from './components/main/Main.async';
|
import Main from './main/Main.async';
|
||||||
import LockScreen from './components/main/LockScreen.async';
|
import LockScreen from './main/LockScreen.async';
|
||||||
import AppInactive from './components/main/AppInactive';
|
import AppInactive from './main/AppInactive';
|
||||||
import Transition from './components/ui/Transition';
|
import Transition from './ui/Transition';
|
||||||
import UiLoader from './components/common/UiLoader';
|
import UiLoader from './common/UiLoader';
|
||||||
// import Test from './components/test/TestNoRedundancy';
|
// import Test from './components/test/TestNoRedundancy';
|
||||||
|
|
||||||
|
import styles from './App.module.scss';
|
||||||
|
import { setupBeforeInstallPrompt } from '../util/installPrompt';
|
||||||
|
|
||||||
type StateProps = {
|
type StateProps = {
|
||||||
authState: GlobalState['authState'];
|
authState: GlobalState['authState'];
|
||||||
isScreenLocked?: boolean;
|
isScreenLocked?: boolean;
|
||||||
hasPasscode?: boolean;
|
hasPasscode?: boolean;
|
||||||
isInactiveAuth?: boolean;
|
isInactiveAuth?: boolean;
|
||||||
hasWebAuthTokenFailed?: boolean;
|
hasWebAuthTokenFailed?: boolean;
|
||||||
|
theme: ThemeKey;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum AppScreens {
|
enum AppScreens {
|
||||||
@ -47,8 +53,9 @@ const App: FC<StateProps> = ({
|
|||||||
authState,
|
authState,
|
||||||
isScreenLocked,
|
isScreenLocked,
|
||||||
hasPasscode,
|
hasPasscode,
|
||||||
hasWebAuthTokenFailed,
|
|
||||||
isInactiveAuth,
|
isInactiveAuth,
|
||||||
|
hasWebAuthTokenFailed,
|
||||||
|
theme,
|
||||||
}) => {
|
}) => {
|
||||||
const { disconnect } = getActions();
|
const { disconnect } = getActions();
|
||||||
|
|
||||||
@ -185,6 +192,17 @@ const App: FC<StateProps> = ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
document.body.classList.add(styles.bg);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
document.body.style.setProperty(
|
||||||
|
'--theme-background-color',
|
||||||
|
theme === 'dark' ? DARK_THEME_BG_COLOR : LIGHT_THEME_BG_COLOR,
|
||||||
|
);
|
||||||
|
}, [theme]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<UiLoader key="Loader" page={page} isMobile={isMobile}>
|
<UiLoader key="Loader" page={page} isMobile={isMobile}>
|
||||||
<Transition
|
<Transition
|
||||||
@ -210,6 +228,7 @@ export default withGlobal(
|
|||||||
hasPasscode: global.passcode?.hasPasscode,
|
hasPasscode: global.passcode?.hasPasscode,
|
||||||
isInactiveAuth: selectTabState(global).isInactive,
|
isInactiveAuth: selectTabState(global).isInactive,
|
||||||
hasWebAuthTokenFailed: global.hasWebAuthTokenFailed || global.hasWebAuthTokenPasswordRequired,
|
hasWebAuthTokenFailed: global.hasWebAuthTokenFailed || global.hasWebAuthTokenPasswordRequired,
|
||||||
|
theme: selectTheme(global),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
)(App);
|
)(App);
|
||||||
@ -1,44 +1,3 @@
|
|||||||
.bg {
|
|
||||||
height: 100%;
|
|
||||||
|
|
||||||
background-color: var(--theme-background-color);
|
|
||||||
background-position: center;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-size: 100% 100%;
|
|
||||||
|
|
||||||
@media (max-width: 600px) {
|
|
||||||
height: calc(var(--vh, 1vh) * 100);
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(html.theme-light) & {
|
|
||||||
background-image: url('../../assets/chat-bg-br.png');
|
|
||||||
}
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
bottom: 0;
|
|
||||||
right: 0;
|
|
||||||
background-image: url('../../assets/chat-bg-pattern-light.png');
|
|
||||||
background-position: top right;
|
|
||||||
background-size: 510px auto;
|
|
||||||
background-repeat: repeat;
|
|
||||||
mix-blend-mode: overlay;
|
|
||||||
|
|
||||||
:global(html.theme-dark) & {
|
|
||||||
background-image: url('../../assets/chat-bg-pattern-dark.png');
|
|
||||||
mix-blend-mode: unset;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 600px) {
|
|
||||||
bottom: auto;
|
|
||||||
height: calc(var(--vh, 1vh) * 100);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.mask {
|
.mask {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
|||||||
@ -3,16 +3,10 @@ import { getActions, getGlobal, withGlobal } from '../../global';
|
|||||||
|
|
||||||
import { ApiMediaFormat } from '../../api/types';
|
import { ApiMediaFormat } from '../../api/types';
|
||||||
import type { TabState } from '../../global/types';
|
import type { TabState } from '../../global/types';
|
||||||
import type { ThemeKey } from '../../types';
|
|
||||||
import type { FC } from '../../lib/teact/teact';
|
import type { FC } from '../../lib/teact/teact';
|
||||||
|
|
||||||
import { getChatAvatarHash } from '../../global/helpers/chats'; // Direct import for better module splitting
|
import { getChatAvatarHash } from '../../global/helpers/chats'; // Direct import for better module splitting
|
||||||
import {
|
import { selectIsRightColumnShown, selectTabState } from '../../global/selectors';
|
||||||
selectIsRightColumnShown,
|
|
||||||
selectTheme,
|
|
||||||
selectTabState,
|
|
||||||
} from '../../global/selectors';
|
|
||||||
import { DARK_THEME_BG_COLOR, LIGHT_THEME_BG_COLOR } from '../../config';
|
|
||||||
import { pause } from '../../util/schedulers';
|
import { pause } from '../../util/schedulers';
|
||||||
import { preloadImage } from '../../util/files';
|
import { preloadImage } from '../../util/files';
|
||||||
import preloadFonts from '../../util/fonts';
|
import preloadFonts from '../../util/fonts';
|
||||||
@ -25,6 +19,7 @@ import useShowTransition from '../../hooks/useShowTransition';
|
|||||||
import useEffectOnce from '../../hooks/useEffectOnce';
|
import useEffectOnce from '../../hooks/useEffectOnce';
|
||||||
|
|
||||||
import styles from './UiLoader.module.scss';
|
import styles from './UiLoader.module.scss';
|
||||||
|
import appStyles from '../App.module.scss';
|
||||||
|
|
||||||
// Workaround for incorrect bundling by Webpack: force including in the main chunk
|
// Workaround for incorrect bundling by Webpack: force including in the main chunk
|
||||||
import '../ui/Modal.scss';
|
import '../ui/Modal.scss';
|
||||||
@ -54,7 +49,6 @@ type OwnProps = {
|
|||||||
type StateProps = Pick<TabState, 'uiReadyState' | 'shouldSkipHistoryAnimations'> & {
|
type StateProps = Pick<TabState, 'uiReadyState' | 'shouldSkipHistoryAnimations'> & {
|
||||||
isRightColumnShown?: boolean;
|
isRightColumnShown?: boolean;
|
||||||
leftColumnWidth?: number;
|
leftColumnWidth?: number;
|
||||||
theme: ThemeKey;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const MAX_PRELOAD_DELAY = 700;
|
const MAX_PRELOAD_DELAY = 700;
|
||||||
@ -111,7 +105,6 @@ const UiLoader: FC<OwnProps & StateProps> = ({
|
|||||||
isRightColumnShown,
|
isRightColumnShown,
|
||||||
shouldSkipHistoryAnimations,
|
shouldSkipHistoryAnimations,
|
||||||
leftColumnWidth,
|
leftColumnWidth,
|
||||||
theme,
|
|
||||||
}) => {
|
}) => {
|
||||||
const { setIsUiReady } = getActions();
|
const { setIsUiReady } = getActions();
|
||||||
|
|
||||||
@ -154,11 +147,7 @@ const UiLoader: FC<OwnProps & StateProps> = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<>
|
||||||
id="UiLoader"
|
|
||||||
className={styles.bg}
|
|
||||||
style={`--theme-background-color: ${theme === 'dark' ? DARK_THEME_BG_COLOR : LIGHT_THEME_BG_COLOR}`}
|
|
||||||
>
|
|
||||||
{children}
|
{children}
|
||||||
{shouldRenderMask && !shouldSkipHistoryAnimations && Boolean(page) && (
|
{shouldRenderMask && !shouldSkipHistoryAnimations && Boolean(page) && (
|
||||||
<div className={buildClassName(styles.mask, transitionClassNames)}>
|
<div className={buildClassName(styles.mask, transitionClassNames)}>
|
||||||
@ -168,23 +157,22 @@ const UiLoader: FC<OwnProps & StateProps> = ({
|
|||||||
className={styles.left}
|
className={styles.left}
|
||||||
style={leftColumnWidth ? `width: ${leftColumnWidth}px` : undefined}
|
style={leftColumnWidth ? `width: ${leftColumnWidth}px` : undefined}
|
||||||
/>
|
/>
|
||||||
<div className={buildClassName(styles.middle, styles.bg)} />
|
<div className={buildClassName(styles.middle, appStyles.bg)} />
|
||||||
{isRightColumnShown && <div className={styles.right} />}
|
{isRightColumnShown && <div className={styles.right} />}
|
||||||
</div>
|
</div>
|
||||||
) : (page === 'inactive' || page === 'lock') ? (
|
) : (page === 'inactive' || page === 'lock') ? (
|
||||||
<div className={buildClassName(styles.blank, styles.bg)} />
|
<div className={buildClassName(styles.blank, appStyles.bg)} />
|
||||||
) : (
|
) : (
|
||||||
<div className={styles.blank} />
|
<div className={styles.blank} />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default withGlobal<OwnProps>(
|
export default withGlobal<OwnProps>(
|
||||||
(global, { isMobile }): StateProps => {
|
(global, { isMobile }): StateProps => {
|
||||||
const theme = selectTheme(global);
|
|
||||||
const tabState = selectTabState(global);
|
const tabState = selectTabState(global);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -192,7 +180,6 @@ export default withGlobal<OwnProps>(
|
|||||||
uiReadyState: tabState.uiReadyState,
|
uiReadyState: tabState.uiReadyState,
|
||||||
isRightColumnShown: selectIsRightColumnShown(global, isMobile),
|
isRightColumnShown: selectIsRightColumnShown(global, isMobile),
|
||||||
leftColumnWidth: global.leftColumnWidth,
|
leftColumnWidth: global.leftColumnWidth,
|
||||||
theme,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
)(UiLoader);
|
)(UiLoader);
|
||||||
|
|||||||
@ -406,95 +406,98 @@ const LeftColumn: FC<StateProps> = ({
|
|||||||
setSettingsScreen(screen);
|
setSettingsScreen(screen);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
function renderContent(isActive: boolean) {
|
||||||
|
switch (contentType) {
|
||||||
|
case ContentType.Archived:
|
||||||
|
return (
|
||||||
|
<ArchivedChats
|
||||||
|
isActive={isActive}
|
||||||
|
onReset={handleReset}
|
||||||
|
onTopicSearch={handleTopicSearch}
|
||||||
|
foldersDispatch={foldersDispatch}
|
||||||
|
onSettingsScreenSelect={handleSettingsScreenSelect}
|
||||||
|
onLeftColumnContentChange={setContent}
|
||||||
|
isForumPanelOpen={isForumPanelOpen}
|
||||||
|
archiveSettings={archiveSettings}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
case ContentType.Settings:
|
||||||
|
return (
|
||||||
|
<Settings
|
||||||
|
isActive={isActive}
|
||||||
|
currentScreen={settingsScreen}
|
||||||
|
foldersState={foldersState}
|
||||||
|
foldersDispatch={foldersDispatch}
|
||||||
|
onScreenSelect={handleSettingsScreenSelect}
|
||||||
|
onReset={handleReset}
|
||||||
|
shouldSkipTransition={shouldSkipHistoryAnimations}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
case ContentType.NewChannel:
|
||||||
|
return (
|
||||||
|
<NewChat
|
||||||
|
key={lastResetTime}
|
||||||
|
isActive={isActive}
|
||||||
|
isChannel
|
||||||
|
content={content}
|
||||||
|
onContentChange={setContent}
|
||||||
|
onReset={handleReset}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
case ContentType.NewGroup:
|
||||||
|
return (
|
||||||
|
<NewChat
|
||||||
|
key={lastResetTime}
|
||||||
|
isActive={isActive}
|
||||||
|
content={content}
|
||||||
|
onContentChange={setContent}
|
||||||
|
onReset={handleReset}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
default:
|
||||||
|
return (
|
||||||
|
<LeftMain
|
||||||
|
content={content}
|
||||||
|
isClosingSearch={isClosingSearch}
|
||||||
|
searchQuery={searchQuery}
|
||||||
|
searchDate={searchDate}
|
||||||
|
contactsFilter={contactsFilter}
|
||||||
|
foldersDispatch={foldersDispatch}
|
||||||
|
onContentChange={setContent}
|
||||||
|
onSearchQuery={handleSearchQuery}
|
||||||
|
onSettingsScreenSelect={handleSettingsScreenSelect}
|
||||||
|
onReset={handleReset}
|
||||||
|
shouldSkipTransition={shouldSkipHistoryAnimations}
|
||||||
|
isUpdateAvailable={isUpdateAvailable}
|
||||||
|
isForumPanelOpen={isForumPanelOpen}
|
||||||
|
onTopicSearch={handleTopicSearch}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<Transition
|
||||||
id="LeftColumn"
|
|
||||||
ref={resizeRef}
|
ref={resizeRef}
|
||||||
|
name={shouldSkipHistoryAnimations ? 'none' : LAYERS_ANIMATION_NAME}
|
||||||
|
renderCount={RENDER_COUNT}
|
||||||
|
activeKey={contentType}
|
||||||
|
shouldCleanup
|
||||||
|
cleanupExceptionKey={ContentType.Main}
|
||||||
|
id="LeftColumn"
|
||||||
>
|
>
|
||||||
<Transition
|
{(isActive) => (
|
||||||
name={shouldSkipHistoryAnimations ? 'none' : LAYERS_ANIMATION_NAME}
|
<>
|
||||||
renderCount={RENDER_COUNT}
|
{renderContent(isActive)}
|
||||||
activeKey={contentType}
|
<div
|
||||||
shouldCleanup
|
className="resize-handle"
|
||||||
cleanupExceptionKey={ContentType.Main}
|
onMouseDown={initResize}
|
||||||
>
|
onMouseUp={handleMouseUp}
|
||||||
{(isActive) => {
|
onDoubleClick={resetResize}
|
||||||
switch (contentType) {
|
/>
|
||||||
case ContentType.Archived:
|
</>
|
||||||
return (
|
)}
|
||||||
<ArchivedChats
|
</Transition>
|
||||||
isActive={isActive}
|
|
||||||
onReset={handleReset}
|
|
||||||
onTopicSearch={handleTopicSearch}
|
|
||||||
foldersDispatch={foldersDispatch}
|
|
||||||
onSettingsScreenSelect={handleSettingsScreenSelect}
|
|
||||||
onLeftColumnContentChange={setContent}
|
|
||||||
isForumPanelOpen={isForumPanelOpen}
|
|
||||||
archiveSettings={archiveSettings}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
case ContentType.Settings:
|
|
||||||
return (
|
|
||||||
<Settings
|
|
||||||
isActive={isActive}
|
|
||||||
currentScreen={settingsScreen}
|
|
||||||
foldersState={foldersState}
|
|
||||||
foldersDispatch={foldersDispatch}
|
|
||||||
onScreenSelect={handleSettingsScreenSelect}
|
|
||||||
onReset={handleReset}
|
|
||||||
shouldSkipTransition={shouldSkipHistoryAnimations}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
case ContentType.NewChannel:
|
|
||||||
return (
|
|
||||||
<NewChat
|
|
||||||
key={lastResetTime}
|
|
||||||
isActive={isActive}
|
|
||||||
isChannel
|
|
||||||
content={content}
|
|
||||||
onContentChange={setContent}
|
|
||||||
onReset={handleReset}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
case ContentType.NewGroup:
|
|
||||||
return (
|
|
||||||
<NewChat
|
|
||||||
key={lastResetTime}
|
|
||||||
isActive={isActive}
|
|
||||||
content={content}
|
|
||||||
onContentChange={setContent}
|
|
||||||
onReset={handleReset}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
default:
|
|
||||||
return (
|
|
||||||
<LeftMain
|
|
||||||
content={content}
|
|
||||||
isClosingSearch={isClosingSearch}
|
|
||||||
searchQuery={searchQuery}
|
|
||||||
searchDate={searchDate}
|
|
||||||
contactsFilter={contactsFilter}
|
|
||||||
foldersDispatch={foldersDispatch}
|
|
||||||
onContentChange={setContent}
|
|
||||||
onSearchQuery={handleSearchQuery}
|
|
||||||
onSettingsScreenSelect={handleSettingsScreenSelect}
|
|
||||||
onReset={handleReset}
|
|
||||||
shouldSkipTransition={shouldSkipHistoryAnimations}
|
|
||||||
isUpdateAvailable={isUpdateAvailable}
|
|
||||||
isForumPanelOpen={isForumPanelOpen}
|
|
||||||
onTopicSearch={handleTopicSearch}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
</Transition>
|
|
||||||
<div
|
|
||||||
className="resize-handle"
|
|
||||||
onMouseDown={initResize}
|
|
||||||
onMouseUp={handleMouseUp}
|
|
||||||
onDoubleClick={resetResize}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +0,0 @@
|
|||||||
#Dialogs {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100vw;
|
|
||||||
height: 100vh;
|
|
||||||
z-index: var(--z-modal);
|
|
||||||
}
|
|
||||||
@ -18,8 +18,6 @@ import Modal from '../ui/Modal';
|
|||||||
import Button from '../ui/Button';
|
import Button from '../ui/Button';
|
||||||
import Avatar from '../common/Avatar';
|
import Avatar from '../common/Avatar';
|
||||||
|
|
||||||
import './Dialogs.scss';
|
|
||||||
|
|
||||||
type StateProps = {
|
type StateProps = {
|
||||||
dialogs: (ApiError | ApiInviteInfo | ApiContact)[];
|
dialogs: (ApiError | ApiInviteInfo | ApiContact)[];
|
||||||
animationLevel: AnimationLevel;
|
animationLevel: AnimationLevel;
|
||||||
@ -179,11 +177,7 @@ const Dialogs: FC<StateProps> = ({ dialogs, animationLevel }) => {
|
|||||||
return renderError(dialog);
|
return renderError(dialog);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return Boolean(dialogs.length) && renderDialog(dialogs[dialogs.length - 1]);
|
||||||
<div id="Dialogs">
|
|
||||||
{Boolean(dialogs.length) && renderDialog(dialogs[dialogs.length - 1])}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function getErrorHeader(error: ApiError) {
|
function getErrorHeader(error: ApiError) {
|
||||||
|
|||||||
@ -28,22 +28,17 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
#LeftColumn {
|
#LeftColumn {
|
||||||
width: 33vw;
|
|
||||||
|
|
||||||
--left-column-min-width: 16rem;
|
--left-column-min-width: 16rem;
|
||||||
--left-column-max-width: 26.5rem;
|
--left-column-max-width: 26.5rem;
|
||||||
|
|
||||||
|
width: 33vw;
|
||||||
min-width: var(--left-column-min-width);
|
min-width: var(--left-column-min-width);
|
||||||
max-width: var(--left-column-max-width);
|
max-width: var(--left-column-max-width);
|
||||||
|
|
||||||
height: 100%;
|
height: 100%;
|
||||||
position: relative;
|
position: relative;
|
||||||
background-color: var(--color-background);
|
overflow: hidden;
|
||||||
|
|
||||||
& > div {
|
background-color: var(--color-background);
|
||||||
height: 100%;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 600px) {
|
@media (max-width: 600px) {
|
||||||
height: calc(var(--vh, 1vh) * 100);
|
height: calc(var(--vh, 1vh) * 100);
|
||||||
|
|||||||
@ -18,7 +18,7 @@
|
|||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
background: var(--color-background);
|
background: var(--color-background);
|
||||||
z-index: 1;
|
z-index: var(--z-symbol-menu-mobile);
|
||||||
|
|
||||||
transition: transform var(--layer-transition);
|
transition: transform var(--layer-transition);
|
||||||
padding-right: env(safe-area-inset-right);
|
padding-right: env(safe-area-inset-right);
|
||||||
|
|||||||
@ -43,13 +43,12 @@
|
|||||||
<link rel="manifest" id="the-manifest-placeholder" href="./<%= htmlWebpackPlugin.options.manifest %>">
|
<link rel="manifest" id="the-manifest-placeholder" href="./<%= htmlWebpackPlugin.options.manifest %>">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body id="root">
|
||||||
<noscript>
|
<noscript>
|
||||||
<video src="./nojs.mp4" class="nojs-video" muted loop autoplay playsinline disablePictureInPicture></video>
|
<video src="./nojs.mp4" class="nojs-video" muted loop autoplay playsinline disablePictureInPicture></video>
|
||||||
<h1>Telegram Web</h1>
|
<h1>Telegram Web</h1>
|
||||||
<p>Please, enable JavaScript to open the app.</p>
|
<p>Please, enable JavaScript to open the app.</p>
|
||||||
</noscript>
|
</noscript>
|
||||||
<div id="root"></div>
|
|
||||||
<div id="portals"></div>
|
<div id="portals"></div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@ -17,7 +17,7 @@ import { requestGlobal, subscribeToMultitabBroadcastChannel } from './util/multi
|
|||||||
import { onBeforeUnload } from './util/schedulers';
|
import { onBeforeUnload } from './util/schedulers';
|
||||||
import { selectTabState } from './global/selectors';
|
import { selectTabState } from './global/selectors';
|
||||||
|
|
||||||
import App from './App';
|
import App from './components/App';
|
||||||
|
|
||||||
import './styles/index.scss';
|
import './styles/index.scss';
|
||||||
|
|
||||||
|
|||||||
@ -242,6 +242,7 @@ $color-message-reaction-own-hover: #b5e0a4;
|
|||||||
--z-register-add-avatar: 5;
|
--z-register-add-avatar: 5;
|
||||||
--z-forum-panel: 5;
|
--z-forum-panel: 5;
|
||||||
--z-media-viewer-head: 3;
|
--z-media-viewer-head: 3;
|
||||||
|
--z-symbol-menu-mobile: 2;
|
||||||
--z-resize-handle: 2;
|
--z-resize-handle: 2;
|
||||||
--z-below: -1;
|
--z-below: -1;
|
||||||
|
|
||||||
|
|||||||
@ -26,7 +26,6 @@
|
|||||||
html,
|
html,
|
||||||
body,
|
body,
|
||||||
#root,
|
#root,
|
||||||
#UiLoader,
|
|
||||||
#Main,
|
#Main,
|
||||||
#MiddleColumn,
|
#MiddleColumn,
|
||||||
.MessageList,
|
.MessageList,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user