161 lines
5.2 KiB
TypeScript
161 lines
5.2 KiB
TypeScript
import { memo, useMemo, useRef, useSignal } from '@teact';
|
|
import { setExtraStyles } from '@teact/teact-dom';
|
|
import { withGlobal } from '../../../../global';
|
|
|
|
import type { ApiPromoData, ApiSession } from '../../../../api/types';
|
|
|
|
import { FRESH_AUTH_PERIOD } from '../../../../config';
|
|
import { requestMutation } from '../../../../lib/fasterdom/fasterdom';
|
|
import { selectIsCurrentUserFrozen, selectIsForumPanelOpen } from '../../../../global/selectors';
|
|
import buildClassName from '../../../../util/buildClassName';
|
|
import { getServerTime } from '../../../../util/serverTime';
|
|
import { REM } from '../../../common/helpers/mediaDimensions';
|
|
|
|
import useEffectOnce from '../../../../hooks/useEffectOnce';
|
|
import useShowTransition from '../../../../hooks/useShowTransition';
|
|
import { useSignalEffect } from '../../../../hooks/useSignalEffect';
|
|
import { applyAnimationState, type PaneState } from '../../../middle/hooks/useHeaderPane';
|
|
|
|
import FrozenAccountPane from './FrozenAccountPane';
|
|
import GiftAuctionPane from './GiftAuctionPane';
|
|
import SuggestionPane from './SuggestionPane';
|
|
import UnconfirmedSessionPane from './UnconfirmedSessionPane';
|
|
|
|
import styles from './ChatListPanes.module.scss';
|
|
|
|
type OwnProps = {
|
|
className?: string;
|
|
onHeightChange: (height: number) => void;
|
|
};
|
|
|
|
type StateProps = {
|
|
sessions: Record<string, ApiSession>;
|
|
promoData?: ApiPromoData;
|
|
isAccountFrozen?: boolean;
|
|
isForumPanelOpen?: boolean;
|
|
};
|
|
|
|
const ITEM_MARGIN = 0.25 * REM;
|
|
const BOTTOM_MARGIN = 0.5 * REM;
|
|
const FALLBACK_PANE_STATE = { height: 0 };
|
|
|
|
const ChatListPanes = ({
|
|
className,
|
|
sessions,
|
|
promoData,
|
|
isAccountFrozen,
|
|
isForumPanelOpen,
|
|
onHeightChange,
|
|
}: OwnProps & StateProps) => {
|
|
const [getUnconfirmedSessionHeight, setUnconfirmedSessionHeight] = useSignal<PaneState>(FALLBACK_PANE_STATE);
|
|
const [getFrozenAccountState, setFrozenAccountState] = useSignal<PaneState>(FALLBACK_PANE_STATE);
|
|
const [getGiftAuctionState, setGiftAuctionState] = useSignal<PaneState>(FALLBACK_PANE_STATE);
|
|
const [getSuggestionState, setSuggestionState] = useSignal<PaneState>(FALLBACK_PANE_STATE);
|
|
|
|
const isFirstRenderRef = useRef(true);
|
|
const {
|
|
shouldRender,
|
|
ref,
|
|
} = useShowTransition({
|
|
isOpen: true,
|
|
withShouldRender: true,
|
|
noMountTransition: true,
|
|
});
|
|
|
|
useEffectOnce(() => {
|
|
isFirstRenderRef.current = false;
|
|
});
|
|
|
|
const unconfirmedSession = useMemo(() => {
|
|
const sessionsArray = Object.values(sessions || {});
|
|
const current = sessionsArray.find((session) => session.isCurrent);
|
|
if (!current || getServerTime() - current.dateCreated < FRESH_AUTH_PERIOD) return undefined;
|
|
|
|
return sessionsArray.find((session) => session.isUnconfirmed);
|
|
}, [sessions]);
|
|
|
|
const canShowUnconfirmedSession = !isAccountFrozen && !isForumPanelOpen && unconfirmedSession;
|
|
const canShowSuggestions = !isAccountFrozen && !isForumPanelOpen && !unconfirmedSession && promoData;
|
|
const canShowGiftAuctions = !isAccountFrozen && !isForumPanelOpen;
|
|
|
|
useSignalEffect(() => {
|
|
const unconfirmedSessionHeight = getUnconfirmedSessionHeight();
|
|
const frozenAccountHeight = getFrozenAccountState();
|
|
const giftAuctionHeight = getGiftAuctionState();
|
|
const suggestionHeight = getSuggestionState();
|
|
|
|
// Keep in sync with the order of the panes in the DOM
|
|
const stateArray = [
|
|
unconfirmedSessionHeight,
|
|
frozenAccountHeight,
|
|
giftAuctionHeight,
|
|
{ height: giftAuctionHeight.height ? ITEM_MARGIN : 0, isSpacer: true },
|
|
suggestionHeight,
|
|
{ height: BOTTOM_MARGIN, isSpacer: true },
|
|
];
|
|
|
|
const isFirstRender = isFirstRenderRef.current;
|
|
const totalHeight = stateArray.reduce((acc, state) => acc + state.height, 0);
|
|
const panelsHeight = totalHeight - BOTTOM_MARGIN;
|
|
|
|
onHeightChange(panelsHeight !== 0 ? totalHeight : 0);
|
|
|
|
const leftColumn = document.getElementById('LeftColumn');
|
|
if (!leftColumn) return;
|
|
|
|
applyAnimationState({
|
|
list: stateArray,
|
|
noTransition: isFirstRender,
|
|
zIndexIncrease: true,
|
|
});
|
|
|
|
requestMutation(() => {
|
|
setExtraStyles(leftColumn, {
|
|
'--chat-list-panes-height': `${totalHeight}px`,
|
|
});
|
|
});
|
|
}, [getUnconfirmedSessionHeight, getFrozenAccountState, getSuggestionState, getGiftAuctionState]);
|
|
|
|
if (!shouldRender) return undefined;
|
|
|
|
return (
|
|
<div
|
|
ref={ref}
|
|
className={
|
|
buildClassName(
|
|
styles.root,
|
|
className,
|
|
)
|
|
}
|
|
>
|
|
<FrozenAccountPane
|
|
isAccountFrozen={isAccountFrozen}
|
|
onPaneStateChange={setFrozenAccountState}
|
|
/>
|
|
<UnconfirmedSessionPane
|
|
unconfirmedSession={canShowUnconfirmedSession ? unconfirmedSession : undefined}
|
|
onPaneStateChange={setUnconfirmedSessionHeight}
|
|
/>
|
|
<GiftAuctionPane
|
|
canShow={canShowGiftAuctions}
|
|
onPaneStateChange={setGiftAuctionState}
|
|
/>
|
|
<SuggestionPane
|
|
promoData={canShowSuggestions ? promoData : undefined}
|
|
onPaneStateChange={setSuggestionState}
|
|
/>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default memo(withGlobal<OwnProps>(
|
|
(global): Complete<StateProps> => {
|
|
return {
|
|
isForumPanelOpen: selectIsForumPanelOpen(global),
|
|
sessions: global.activeSessions.byHash,
|
|
promoData: global.promoData,
|
|
isAccountFrozen: selectIsCurrentUserFrozen(global),
|
|
};
|
|
},
|
|
)(ChatListPanes));
|