252 lines
7.8 KiB
TypeScript

import type { FC } from '../../../lib/teact/teact';
import React, {
memo, useEffect, useRef, useState,
} from '../../../lib/teact/teact';
import { getActions } from '../../../global';
import type { FolderEditDispatch } from '../../../hooks/reducers/useFoldersReducer';
import type { SettingsScreens } from '../../../types';
import { LeftColumnContent } from '../../../types';
import { PRODUCTION_URL } from '../../../config';
import buildClassName from '../../../util/buildClassName';
import { IS_ELECTRON, IS_TOUCH_ENV } from '../../../util/windowEnvironment';
import useForumPanelRender from '../../../hooks/useForumPanelRender';
import useLastCallback from '../../../hooks/useLastCallback';
import useOldLang from '../../../hooks/useOldLang';
import useShowTransitionDeprecated from '../../../hooks/useShowTransitionDeprecated';
import Button from '../../ui/Button';
import Transition from '../../ui/Transition';
import NewChatButton from '../NewChatButton';
import LeftSearch from '../search/LeftSearch.async';
import ChatFolders from './ChatFolders';
import ContactList from './ContactList.async';
import ForumPanel from './ForumPanel';
import LeftMainHeader from './LeftMainHeader';
import './LeftMain.scss';
type OwnProps = {
content: LeftColumnContent;
searchQuery?: string;
searchDate?: number;
contactsFilter: string;
shouldSkipTransition?: boolean;
foldersDispatch: FolderEditDispatch;
isAppUpdateAvailable?: boolean;
isElectronUpdateAvailable?: boolean;
isForumPanelOpen?: boolean;
isClosingSearch?: boolean;
onSearchQuery: (query: string) => void;
onContentChange: (content: LeftColumnContent) => void;
onSettingsScreenSelect: (screen: SettingsScreens) => void;
onTopicSearch: NoneToVoidFunction;
onReset: () => void;
};
const TRANSITION_RENDER_COUNT = Object.keys(LeftColumnContent).length / 2;
const BUTTON_CLOSE_DELAY_MS = 250;
let closeTimeout: number | undefined;
const LeftMain: FC<OwnProps> = ({
content,
searchQuery,
searchDate,
isClosingSearch,
contactsFilter,
shouldSkipTransition,
foldersDispatch,
isAppUpdateAvailable,
isElectronUpdateAvailable,
isForumPanelOpen,
onSearchQuery,
onContentChange,
onSettingsScreenSelect,
onReset,
onTopicSearch,
}) => {
const { closeForumPanel } = getActions();
const [isNewChatButtonShown, setIsNewChatButtonShown] = useState(IS_TOUCH_ENV);
const [isElectronAutoUpdateEnabled, setIsElectronAutoUpdateEnabled] = useState(false);
useEffect(() => {
window.electron?.getIsAutoUpdateEnabled().then(setIsElectronAutoUpdateEnabled);
}, []);
const {
shouldRenderForumPanel, handleForumPanelAnimationEnd,
handleForumPanelAnimationStart, isAnimationStarted,
} = useForumPanelRender(isForumPanelOpen);
const isForumPanelRendered = isForumPanelOpen && content === LeftColumnContent.ChatList;
const isForumPanelVisible = isForumPanelRendered && isAnimationStarted;
const {
shouldRender: shouldRenderUpdateButton,
transitionClassNames: updateButtonClassNames,
} = useShowTransitionDeprecated(isAppUpdateAvailable || isElectronUpdateAvailable);
const isMouseInside = useRef(false);
const handleMouseEnter = useLastCallback(() => {
if (content !== LeftColumnContent.ChatList) {
return;
}
isMouseInside.current = true;
setIsNewChatButtonShown(true);
});
const handleMouseLeave = useLastCallback(() => {
isMouseInside.current = false;
if (closeTimeout) {
clearTimeout(closeTimeout);
closeTimeout = undefined;
}
closeTimeout = window.setTimeout(() => {
if (!isMouseInside.current) {
setIsNewChatButtonShown(false);
}
}, BUTTON_CLOSE_DELAY_MS);
});
const handleSelectSettings = useLastCallback(() => {
onContentChange(LeftColumnContent.Settings);
});
const handleSelectContacts = useLastCallback(() => {
onContentChange(LeftColumnContent.Contacts);
});
const handleSelectArchived = useLastCallback(() => {
onContentChange(LeftColumnContent.Archived);
closeForumPanel();
});
const handleUpdateClick = useLastCallback(() => {
if (IS_ELECTRON && !isElectronAutoUpdateEnabled) {
window.open(`${PRODUCTION_URL}/get`, '_blank', 'noopener');
} else if (isElectronUpdateAvailable) {
window.electron?.installUpdate();
} else {
window.location.reload();
}
});
const handleSelectNewChannel = useLastCallback(() => {
onContentChange(LeftColumnContent.NewChannelStep1);
});
const handleSelectNewGroup = useLastCallback(() => {
onContentChange(LeftColumnContent.NewGroupStep1);
});
useEffect(() => {
let autoCloseTimeout: number | undefined;
if (content !== LeftColumnContent.ChatList) {
autoCloseTimeout = window.setTimeout(() => {
setIsNewChatButtonShown(false);
}, BUTTON_CLOSE_DELAY_MS);
} else if (isMouseInside.current || IS_TOUCH_ENV) {
setIsNewChatButtonShown(true);
}
return () => {
if (autoCloseTimeout) {
clearTimeout(autoCloseTimeout);
autoCloseTimeout = undefined;
}
};
}, [content]);
const lang = useOldLang();
return (
<div
id="LeftColumn-main"
onMouseEnter={!IS_TOUCH_ENV ? handleMouseEnter : undefined}
onMouseLeave={!IS_TOUCH_ENV ? handleMouseLeave : undefined}
>
<LeftMainHeader
shouldHideSearch={isForumPanelVisible}
content={content}
contactsFilter={contactsFilter}
onSearchQuery={onSearchQuery}
onSelectSettings={handleSelectSettings}
onSelectContacts={handleSelectContacts}
onSelectArchived={handleSelectArchived}
onReset={onReset}
shouldSkipTransition={shouldSkipTransition}
isClosingSearch={isClosingSearch}
/>
<Transition
name={shouldSkipTransition ? 'none' : 'zoomFade'}
renderCount={TRANSITION_RENDER_COUNT}
activeKey={content}
shouldCleanup
cleanupExceptionKey={LeftColumnContent.ChatList}
shouldWrap
wrapExceptionKey={LeftColumnContent.ChatList}
>
{(isActive) => {
switch (content) {
case LeftColumnContent.ChatList:
return (
<ChatFolders
shouldHideFolderTabs={isForumPanelVisible}
onSettingsScreenSelect={onSettingsScreenSelect}
onLeftColumnContentChange={onContentChange}
foldersDispatch={foldersDispatch}
isForumPanelOpen={isForumPanelVisible}
/>
);
case LeftColumnContent.GlobalSearch:
return (
<LeftSearch
searchQuery={searchQuery}
searchDate={searchDate}
isActive={isActive}
onReset={onReset}
/>
);
case LeftColumnContent.Contacts:
return <ContactList filter={contactsFilter} isActive={isActive} onReset={onReset} />;
default:
return undefined;
}
}}
</Transition>
{shouldRenderUpdateButton && (
<Button
fluid
badge
className={buildClassName('btn-update', updateButtonClassNames)}
onClick={handleUpdateClick}
>
{lang('lng_update_telegram')}
</Button>
)}
{shouldRenderForumPanel && (
<ForumPanel
isOpen={isForumPanelOpen}
isHidden={!isForumPanelRendered}
onTopicSearch={onTopicSearch}
onOpenAnimationStart={handleForumPanelAnimationStart}
onCloseAnimationEnd={handleForumPanelAnimationEnd}
/>
)}
<NewChatButton
isShown={isNewChatButtonShown}
onNewPrivateChat={handleSelectContacts}
onNewChannel={handleSelectNewChannel}
onNewGroup={handleSelectNewGroup}
/>
</div>
);
};
export default memo(LeftMain);