[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 React, { useEffect } from './lib/teact/teact';
|
||||
import { getActions, withGlobal } from './global';
|
||||
import type { FC } from '../lib/teact/teact';
|
||||
import React, { useEffect, useLayoutEffect } from '../lib/teact/teact';
|
||||
import { getActions, withGlobal } from '../global';
|
||||
|
||||
import type { GlobalState } from './global/types';
|
||||
import type { UiLoaderPage } from './components/common/UiLoader';
|
||||
import type { GlobalState } from '../global/types';
|
||||
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 { INACTIVE_MARKER, PAGE_TITLE } from './config';
|
||||
import { selectTabState } from './global/selectors';
|
||||
import { updateSizes } from './util/windowSize';
|
||||
import { addActiveTabChangeListener } from './util/activeTabMonitor';
|
||||
import { hasStoredSession } from './util/sessions';
|
||||
import { setupBeforeInstallPrompt } from './util/installPrompt';
|
||||
import buildClassName from './util/buildClassName';
|
||||
import { parseInitialLocationHash } from './util/routing';
|
||||
import useFlag from './hooks/useFlag';
|
||||
import usePrevious from './hooks/usePrevious';
|
||||
import useAppLayout from './hooks/useAppLayout';
|
||||
import { IS_INSTALL_PROMPT_SUPPORTED, IS_MULTITAB_SUPPORTED, PLATFORM_ENV } from '../util/windowEnvironment';
|
||||
import {
|
||||
DARK_THEME_BG_COLOR, INACTIVE_MARKER, LIGHT_THEME_BG_COLOR, PAGE_TITLE,
|
||||
} from '../config';
|
||||
import { selectTabState, selectTheme } from '../global/selectors';
|
||||
import { updateSizes } from '../util/windowSize';
|
||||
import { addActiveTabChangeListener } from '../util/activeTabMonitor';
|
||||
import { hasStoredSession } from '../util/sessions';
|
||||
import buildClassName from '../util/buildClassName';
|
||||
import { parseInitialLocationHash } from '../util/routing';
|
||||
import useFlag from '../hooks/useFlag';
|
||||
import usePrevious from '../hooks/usePrevious';
|
||||
import useAppLayout from '../hooks/useAppLayout';
|
||||
|
||||
import Auth from './components/auth/Auth';
|
||||
import Main from './components/main/Main.async';
|
||||
import LockScreen from './components/main/LockScreen.async';
|
||||
import AppInactive from './components/main/AppInactive';
|
||||
import Transition from './components/ui/Transition';
|
||||
import UiLoader from './components/common/UiLoader';
|
||||
import Auth from './auth/Auth';
|
||||
import Main from './main/Main.async';
|
||||
import LockScreen from './main/LockScreen.async';
|
||||
import AppInactive from './main/AppInactive';
|
||||
import Transition from './ui/Transition';
|
||||
import UiLoader from './common/UiLoader';
|
||||
// import Test from './components/test/TestNoRedundancy';
|
||||
|
||||
import styles from './App.module.scss';
|
||||
import { setupBeforeInstallPrompt } from '../util/installPrompt';
|
||||
|
||||
type StateProps = {
|
||||
authState: GlobalState['authState'];
|
||||
isScreenLocked?: boolean;
|
||||
hasPasscode?: boolean;
|
||||
isInactiveAuth?: boolean;
|
||||
hasWebAuthTokenFailed?: boolean;
|
||||
theme: ThemeKey;
|
||||
};
|
||||
|
||||
enum AppScreens {
|
||||
@ -47,8 +53,9 @@ const App: FC<StateProps> = ({
|
||||
authState,
|
||||
isScreenLocked,
|
||||
hasPasscode,
|
||||
hasWebAuthTokenFailed,
|
||||
isInactiveAuth,
|
||||
hasWebAuthTokenFailed,
|
||||
theme,
|
||||
}) => {
|
||||
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 (
|
||||
<UiLoader key="Loader" page={page} isMobile={isMobile}>
|
||||
<Transition
|
||||
@ -210,6 +228,7 @@ export default withGlobal(
|
||||
hasPasscode: global.passcode?.hasPasscode,
|
||||
isInactiveAuth: selectTabState(global).isInactive,
|
||||
hasWebAuthTokenFailed: global.hasWebAuthTokenFailed || global.hasWebAuthTokenPasswordRequired,
|
||||
theme: selectTheme(global),
|
||||
};
|
||||
},
|
||||
)(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 {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
|
||||
@ -3,16 +3,10 @@ import { getActions, getGlobal, withGlobal } from '../../global';
|
||||
|
||||
import { ApiMediaFormat } from '../../api/types';
|
||||
import type { TabState } from '../../global/types';
|
||||
import type { ThemeKey } from '../../types';
|
||||
import type { FC } from '../../lib/teact/teact';
|
||||
|
||||
import { getChatAvatarHash } from '../../global/helpers/chats'; // Direct import for better module splitting
|
||||
import {
|
||||
selectIsRightColumnShown,
|
||||
selectTheme,
|
||||
selectTabState,
|
||||
} from '../../global/selectors';
|
||||
import { DARK_THEME_BG_COLOR, LIGHT_THEME_BG_COLOR } from '../../config';
|
||||
import { selectIsRightColumnShown, selectTabState } from '../../global/selectors';
|
||||
import { pause } from '../../util/schedulers';
|
||||
import { preloadImage } from '../../util/files';
|
||||
import preloadFonts from '../../util/fonts';
|
||||
@ -25,6 +19,7 @@ import useShowTransition from '../../hooks/useShowTransition';
|
||||
import useEffectOnce from '../../hooks/useEffectOnce';
|
||||
|
||||
import styles from './UiLoader.module.scss';
|
||||
import appStyles from '../App.module.scss';
|
||||
|
||||
// Workaround for incorrect bundling by Webpack: force including in the main chunk
|
||||
import '../ui/Modal.scss';
|
||||
@ -54,7 +49,6 @@ type OwnProps = {
|
||||
type StateProps = Pick<TabState, 'uiReadyState' | 'shouldSkipHistoryAnimations'> & {
|
||||
isRightColumnShown?: boolean;
|
||||
leftColumnWidth?: number;
|
||||
theme: ThemeKey;
|
||||
};
|
||||
|
||||
const MAX_PRELOAD_DELAY = 700;
|
||||
@ -111,7 +105,6 @@ const UiLoader: FC<OwnProps & StateProps> = ({
|
||||
isRightColumnShown,
|
||||
shouldSkipHistoryAnimations,
|
||||
leftColumnWidth,
|
||||
theme,
|
||||
}) => {
|
||||
const { setIsUiReady } = getActions();
|
||||
|
||||
@ -154,11 +147,7 @@ const UiLoader: FC<OwnProps & StateProps> = ({
|
||||
});
|
||||
|
||||
return (
|
||||
<div
|
||||
id="UiLoader"
|
||||
className={styles.bg}
|
||||
style={`--theme-background-color: ${theme === 'dark' ? DARK_THEME_BG_COLOR : LIGHT_THEME_BG_COLOR}`}
|
||||
>
|
||||
<>
|
||||
{children}
|
||||
{shouldRenderMask && !shouldSkipHistoryAnimations && Boolean(page) && (
|
||||
<div className={buildClassName(styles.mask, transitionClassNames)}>
|
||||
@ -168,23 +157,22 @@ const UiLoader: FC<OwnProps & StateProps> = ({
|
||||
className={styles.left}
|
||||
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} />}
|
||||
</div>
|
||||
) : (page === 'inactive' || page === 'lock') ? (
|
||||
<div className={buildClassName(styles.blank, styles.bg)} />
|
||||
<div className={buildClassName(styles.blank, appStyles.bg)} />
|
||||
) : (
|
||||
<div className={styles.blank} />
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default withGlobal<OwnProps>(
|
||||
(global, { isMobile }): StateProps => {
|
||||
const theme = selectTheme(global);
|
||||
const tabState = selectTabState(global);
|
||||
|
||||
return {
|
||||
@ -192,7 +180,6 @@ export default withGlobal<OwnProps>(
|
||||
uiReadyState: tabState.uiReadyState,
|
||||
isRightColumnShown: selectIsRightColumnShown(global, isMobile),
|
||||
leftColumnWidth: global.leftColumnWidth,
|
||||
theme,
|
||||
};
|
||||
},
|
||||
)(UiLoader);
|
||||
|
||||
@ -406,95 +406,98 @@ const LeftColumn: FC<StateProps> = ({
|
||||
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 (
|
||||
<div
|
||||
id="LeftColumn"
|
||||
<Transition
|
||||
ref={resizeRef}
|
||||
name={shouldSkipHistoryAnimations ? 'none' : LAYERS_ANIMATION_NAME}
|
||||
renderCount={RENDER_COUNT}
|
||||
activeKey={contentType}
|
||||
shouldCleanup
|
||||
cleanupExceptionKey={ContentType.Main}
|
||||
id="LeftColumn"
|
||||
>
|
||||
<Transition
|
||||
name={shouldSkipHistoryAnimations ? 'none' : LAYERS_ANIMATION_NAME}
|
||||
renderCount={RENDER_COUNT}
|
||||
activeKey={contentType}
|
||||
shouldCleanup
|
||||
cleanupExceptionKey={ContentType.Main}
|
||||
>
|
||||
{(isActive) => {
|
||||
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}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}}
|
||||
</Transition>
|
||||
<div
|
||||
className="resize-handle"
|
||||
onMouseDown={initResize}
|
||||
onMouseUp={handleMouseUp}
|
||||
onDoubleClick={resetResize}
|
||||
/>
|
||||
</div>
|
||||
{(isActive) => (
|
||||
<>
|
||||
{renderContent(isActive)}
|
||||
<div
|
||||
className="resize-handle"
|
||||
onMouseDown={initResize}
|
||||
onMouseUp={handleMouseUp}
|
||||
onDoubleClick={resetResize}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</Transition>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -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 Avatar from '../common/Avatar';
|
||||
|
||||
import './Dialogs.scss';
|
||||
|
||||
type StateProps = {
|
||||
dialogs: (ApiError | ApiInviteInfo | ApiContact)[];
|
||||
animationLevel: AnimationLevel;
|
||||
@ -179,11 +177,7 @@ const Dialogs: FC<StateProps> = ({ dialogs, animationLevel }) => {
|
||||
return renderError(dialog);
|
||||
};
|
||||
|
||||
return (
|
||||
<div id="Dialogs">
|
||||
{Boolean(dialogs.length) && renderDialog(dialogs[dialogs.length - 1])}
|
||||
</div>
|
||||
);
|
||||
return Boolean(dialogs.length) && renderDialog(dialogs[dialogs.length - 1]);
|
||||
};
|
||||
|
||||
function getErrorHeader(error: ApiError) {
|
||||
|
||||
@ -28,22 +28,17 @@
|
||||
}
|
||||
|
||||
#LeftColumn {
|
||||
width: 33vw;
|
||||
|
||||
--left-column-min-width: 16rem;
|
||||
--left-column-max-width: 26.5rem;
|
||||
|
||||
width: 33vw;
|
||||
min-width: var(--left-column-min-width);
|
||||
max-width: var(--left-column-max-width);
|
||||
|
||||
height: 100%;
|
||||
position: relative;
|
||||
background-color: var(--color-background);
|
||||
overflow: hidden;
|
||||
|
||||
& > div {
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
background-color: var(--color-background);
|
||||
|
||||
@media (max-width: 600px) {
|
||||
height: calc(var(--vh, 1vh) * 100);
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: var(--color-background);
|
||||
z-index: 1;
|
||||
z-index: var(--z-symbol-menu-mobile);
|
||||
|
||||
transition: transform var(--layer-transition);
|
||||
padding-right: env(safe-area-inset-right);
|
||||
|
||||
@ -43,13 +43,12 @@
|
||||
<link rel="manifest" id="the-manifest-placeholder" href="./<%= htmlWebpackPlugin.options.manifest %>">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<body id="root">
|
||||
<noscript>
|
||||
<video src="./nojs.mp4" class="nojs-video" muted loop autoplay playsinline disablePictureInPicture></video>
|
||||
<h1>Telegram Web</h1>
|
||||
<p>Please, enable JavaScript to open the app.</p>
|
||||
</noscript>
|
||||
<div id="root"></div>
|
||||
<div id="portals"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@ -17,7 +17,7 @@ import { requestGlobal, subscribeToMultitabBroadcastChannel } from './util/multi
|
||||
import { onBeforeUnload } from './util/schedulers';
|
||||
import { selectTabState } from './global/selectors';
|
||||
|
||||
import App from './App';
|
||||
import App from './components/App';
|
||||
|
||||
import './styles/index.scss';
|
||||
|
||||
|
||||
@ -242,6 +242,7 @@ $color-message-reaction-own-hover: #b5e0a4;
|
||||
--z-register-add-avatar: 5;
|
||||
--z-forum-panel: 5;
|
||||
--z-media-viewer-head: 3;
|
||||
--z-symbol-menu-mobile: 2;
|
||||
--z-resize-handle: 2;
|
||||
--z-below: -1;
|
||||
|
||||
|
||||
@ -26,7 +26,6 @@
|
||||
html,
|
||||
body,
|
||||
#root,
|
||||
#UiLoader,
|
||||
#Main,
|
||||
#MiddleColumn,
|
||||
.MessageList,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user