diff --git a/web/sidebar/community-drawer-item-handlers.react.js b/web/sidebar/community-drawer-item-handlers.react.js index 85a491f34..5c5831258 100644 --- a/web/sidebar/community-drawer-item-handlers.react.js +++ b/web/sidebar/community-drawer-item-handlers.react.js @@ -1,74 +1,74 @@ // @flow import * as React from 'react'; import { useDispatch } from 'react-redux'; import type { ThreadInfo } from 'lib/types/thread-types.js'; import type { CommunityDrawerItemHandler } from './community-drawer-item-handler.react.js'; import { updateCalendarCommunityFilter } from '../redux/action-types.js'; import { useCommunityIsPicked } from '../selectors/calendar-selectors.js'; import { useOnClickThread, useThreadIsActive, } from '../selectors/thread-selectors.js'; import type { NavigationTab } from '../types/nav-types.js'; -type HandlerProps = { +export type HandlerProps = { +setHandler: (handler: CommunityDrawerItemHandler) => void, +threadInfo: ThreadInfo, }; function ChatDrawerItemHandler(props: HandlerProps): React.Node { const { setHandler, threadInfo } = props; const onClick = useOnClickThread(threadInfo); const isActive = useThreadIsActive(threadInfo.id); const handler = React.useMemo(() => ({ onClick, isActive }), [ isActive, onClick, ]); React.useEffect(() => { setHandler(handler); }, [handler, setHandler]); return null; } function CalendarDrawerItemHandler(props: HandlerProps): React.Node { const { setHandler, threadInfo } = props; const dispatch = useDispatch(); const onClick = React.useCallback(() => { dispatch({ type: updateCalendarCommunityFilter, payload: threadInfo.id, }); }, [dispatch, threadInfo.id]); const isActive = useCommunityIsPicked(threadInfo.id); const handler = React.useMemo(() => ({ onClick, isActive }), [ onClick, isActive, ]); React.useEffect(() => { setHandler(handler); }, [handler, setHandler]); return null; } const communityDrawerItemHandlers: { +[tab: NavigationTab]: React.ComponentType, } = Object.freeze({ chat: ChatDrawerItemHandler, calendar: CalendarDrawerItemHandler, }); function getCommunityDrawerItemHandler( tab: NavigationTab, ): React.ComponentType { return communityDrawerItemHandlers[tab] ?? ChatDrawerItemHandler; } export { getCommunityDrawerItemHandler }; diff --git a/web/sidebar/community-drawer-item.react.js b/web/sidebar/community-drawer-item.react.js index 1a30c5b6a..3d7dd412c 100644 --- a/web/sidebar/community-drawer-item.react.js +++ b/web/sidebar/community-drawer-item.react.js @@ -1,163 +1,163 @@ // @flow import classnames from 'classnames'; import * as React from 'react'; import type { CommunityDrawerItemData } from 'lib/utils/drawer-utils.react.js'; import { useResolvedThreadInfo } from 'lib/utils/entity-helpers.js'; -import { getCommunityDrawerItemHandler } from './community-drawer-item-handlers.react.js'; +import type { HandlerProps } from './community-drawer-item-handlers.react.js'; import css from './community-drawer-item.css'; import { ExpandButton } from './expand-buttons.react.js'; import SubchannelsButton from './subchannels-button.react.js'; -import { useSelector } from '../redux/redux-utils.js'; export type DrawerItemProps = { +itemData: CommunityDrawerItemData, +toggleExpanded?: (threadID: string) => void, +expanded: boolean, +paddingLeft: number, +expandable?: boolean, + +handler: React.ComponentType, }; const indentation = 14; const subchannelsButtonIndentation = 24; function CommunityDrawerItem(props: DrawerItemProps): React.Node { const { itemData: { threadInfo, itemChildren, hasSubchannelsButton, labelStyle }, expanded, toggleExpanded, paddingLeft, expandable = true, + handler: Handler, } = props; const children = React.useMemo(() => { if (!expanded) { return null; } if (hasSubchannelsButton) { const buttonPaddingLeft = paddingLeft + subchannelsButtonIndentation; return (
); } if (!itemChildren) { return null; } return itemChildren.map(item => ( )); }, [ expanded, hasSubchannelsButton, itemChildren, paddingLeft, - expandable, threadInfo, + expandable, + Handler, ]); const onExpandToggled = React.useCallback( () => (toggleExpanded ? toggleExpanded(threadInfo.id) : null), [toggleExpanded, threadInfo.id], ); const itemExpandButton = React.useMemo(() => { if (!expandable) { return null; } if (itemChildren?.length === 0 && !hasSubchannelsButton) { return (
); } return (
); }, [ expandable, itemChildren?.length, hasSubchannelsButton, onExpandToggled, expanded, ]); - const Handler = useSelector(state => - getCommunityDrawerItemHandler(state.navInfo.tab), - ); - const [handler, setHandler] = React.useState({ // eslint-disable-next-line no-unused-vars onClick: event => {}, }); const { uiName } = useResolvedThreadInfo(threadInfo); const titleLabel = classnames(css.title, css[labelStyle]); const style = React.useMemo(() => ({ paddingLeft }), [paddingLeft]); const threadEntry = classnames({ [css.threadEntry]: true, [css.active]: handler.isActive, }); return ( <>
{itemExpandButton}
{uiName}
{children}
); } export type CommunityDrawerItemChatProps = { +itemData: CommunityDrawerItemData, +paddingLeft: number, +expandable?: boolean, + +handler: React.ComponentType, }; function CommunityDrawerItemChat( props: CommunityDrawerItemChatProps, ): React.Node { const [expanded, setExpanded] = React.useState(false); const toggleExpanded = React.useCallback(() => { setExpanded(isExpanded => !isExpanded); }, []); return ( ); } const MemoizedCommunityDrawerItemChat: React.ComponentType = React.memo( CommunityDrawerItemChat, ); const MemoizedCommunityDrawerItem: React.ComponentType = React.memo( CommunityDrawerItem, ); export default MemoizedCommunityDrawerItem; diff --git a/web/sidebar/community-drawer.react.js b/web/sidebar/community-drawer.react.js index 51f208aa5..002614ea3 100644 --- a/web/sidebar/community-drawer.react.js +++ b/web/sidebar/community-drawer.react.js @@ -1,90 +1,96 @@ // @flow import * as React from 'react'; import { childThreadInfos, communityThreadSelector, } from 'lib/selectors/thread-selectors.js'; import { createRecursiveDrawerItemsData, appendSuffix, } from 'lib/utils/drawer-utils.react.js'; import { useResolvedThreadInfos } from 'lib/utils/entity-helpers.js'; import CommunityDrawerItemCommunity from './community-drawer-item-community.react.js'; +import { getCommunityDrawerItemHandler } from './community-drawer-item-handlers.react.js'; import css from './community-drawer.css'; import { ThreadListProvider } from '../chat/thread-list-provider.js'; import { useSelector } from '../redux/redux-utils.js'; const maxDepth = 2; const labelStyles = ['titleLevel0', 'titleLevel1', 'titleLevel2']; +const HandlerChat = getCommunityDrawerItemHandler('chat'); +const HandlerCal = getCommunityDrawerItemHandler('calendar'); + function CommunityDrawer(): React.Node { const tab = useSelector(state => state.navInfo.tab); const childThreadInfosMap = useSelector(childThreadInfos); const communities = useSelector(communityThreadSelector); const resolvedCommunities = useResolvedThreadInfos(communities); const communitiesSuffixed = React.useMemo( () => appendSuffix(resolvedCommunities), [resolvedCommunities], ); const drawerItemsData = createRecursiveDrawerItemsData( childThreadInfosMap, communitiesSuffixed, labelStyles, maxDepth, ); const [openCommunity, setOpenCommunity] = React.useState( communitiesSuffixed.length === 1 ? communitiesSuffixed[0].id : null, ); const setOpenCommunityOrClose = React.useCallback((index: string) => { setOpenCommunity(open => (open === index ? null : index)); }, []); const communitiesComponentsDefault = React.useMemo( () => drawerItemsData.map(item => ( )), [drawerItemsData, openCommunity, setOpenCommunityOrClose], ); const communitiesComponentsCal = React.useMemo( () => drawerItemsData.map(item => ( )), [drawerItemsData], ); const defaultStyle = tab === 'calendar' ? css.hidden : null; const calStyle = tab !== 'calendar' ? css.hidden : null; return (
{communitiesComponentsDefault}
{communitiesComponentsCal}
); } export default CommunityDrawer;