diff --git a/web/chat/chat-tabs.react.js b/web/chat/chat-tabs.react.js index 2da8c4674..03397ffef 100644 --- a/web/chat/chat-tabs.react.js +++ b/web/chat/chat-tabs.react.js @@ -1,55 +1,77 @@ // @flow import * as React from 'react'; import { unreadBackgroundCount } from 'lib/selectors/thread-selectors'; +import { threadIsTopLevel } from 'lib/shared/thread-utils'; import { useSelector } from '../redux/redux-utils'; +import { activeChatThreadItem as activeChatThreadItemSelector } from '../selectors/chat-selectors'; import css from './chat-tabs.css'; import ChatThreadBackground from './chat-thread-background.react'; import ChatThreadHome from './chat-thread-home.react'; import ChatThreadTab from './chat-thread-tab.react'; type Props = {| +setModal: (modal: ?React.Node) => void, |}; function ChatTabs(props: Props) { let backgroundTitle = 'BACKGROUND'; const unreadBackgroundCountVal = useSelector(unreadBackgroundCount); if (unreadBackgroundCountVal) { backgroundTitle += ` (${unreadBackgroundCountVal})`; } const [activeTab, setActiveTab] = React.useState('HOME'); const onClickHome = React.useCallback(() => setActiveTab('HOME'), []); const onClickBackground = React.useCallback( () => setActiveTab('BACKGROUND'), [], ); + const activeChatThreadItem = useSelector(activeChatThreadItemSelector); + const activeThreadInfo = activeChatThreadItem?.threadInfo; + const activeThreadFromHomeTab = + activeThreadInfo?.currentUser.subscription.home; + const activeThreadID = activeThreadInfo?.id; + const activeThreadHasSpecificTab = threadIsTopLevel(activeThreadInfo); + const activeThreadIsFromDifferentTab = + (activeTab === 'BACKGROUND' && activeThreadFromHomeTab) || + (activeTab === 'HOME' && !activeThreadFromHomeTab); + const prevActiveThreadIDRef = React.useRef(); + const shouldChangeTab = + activeThreadHasSpecificTab && activeThreadIsFromDifferentTab; + React.useEffect(() => { + const prevActiveThreadID = prevActiveThreadIDRef.current; + prevActiveThreadIDRef.current = activeThreadID; + if (activeThreadID !== prevActiveThreadID && shouldChangeTab) { + setActiveTab(activeThreadFromHomeTab ? 'HOME' : 'BACKGROUND'); + } + }, [activeThreadID, activeThreadFromHomeTab, shouldChangeTab]); + const threadList = activeTab === 'HOME' ? ( ) : ( ); return (
{threadList}
); } export default ChatTabs; diff --git a/web/selectors/chat-selectors.js b/web/selectors/chat-selectors.js index 8ca936db0..6fa57af2c 100644 --- a/web/selectors/chat-selectors.js +++ b/web/selectors/chat-selectors.js @@ -1,142 +1,142 @@ // @flow import invariant from 'invariant'; import { createSelector } from 'reselect'; import { messageInfoSelector, type ChatThreadItem, createChatThreadItem, chatListData, type ChatMessageItem, createChatMessageItems, } from 'lib/selectors/chat-selectors'; import { threadInfoSelector, threadInfoFromSourceMessageIDSelector, } from 'lib/selectors/thread-selectors'; import type { MessageStore, MessageInfo } from 'lib/types/message-types'; import { type ThreadInfo, threadTypes } from 'lib/types/thread-types'; import type { AppState } from '../redux/redux-setup'; const activeChatThreadItem: ( state: AppState, ) => ?ChatThreadItem = createSelector( threadInfoSelector, (state: AppState) => state.messageStore, messageInfoSelector, (state: AppState) => state.navInfo.activeChatThreadID, ( threadInfos: { [id: string]: ThreadInfo }, messageStore: MessageStore, messageInfos: { [id: string]: MessageInfo }, activeChatThreadID: ?string, ): ?ChatThreadItem => { if (!activeChatThreadID) { return null; } const threadInfo = threadInfos[activeChatThreadID]; if (!threadInfo) { return null; } return createChatThreadItem(threadInfo, messageStore, messageInfos, null); }, ); const webChatListData: (state: AppState) => ChatThreadItem[] = createSelector( chatListData, activeChatThreadItem, (data: ChatThreadItem[], activeItem: ?ChatThreadItem): ChatThreadItem[] => { if (!activeItem) { return data; } const result = []; for (const item of data) { if (item.threadInfo.id === activeItem.threadInfo.id) { return data; } if ( activeItem.threadInfo.type !== threadTypes.SIDEBAR || activeItem.threadInfo.parentThreadID !== item.threadInfo.id ) { result.push(item); continue; } const { parentThreadID } = activeItem.threadInfo; invariant( parentThreadID, `thread ID ${activeItem.threadInfo.id} is a sidebar without a parent`, ); for (const sidebarItem of item.sidebars) { if (sidebarItem.type !== 'sidebar') { continue; } else if (sidebarItem.threadInfo.id === activeItem.threadInfo.id) { return data; } } let newSidebarItemInserted = false; const newSidebarItems = []; for (const sidebarItem of item.sidebars) { if ( !newSidebarItemInserted && (sidebarItem.lastUpdatedTime === undefined || sidebarItem.lastUpdatedTime < activeItem.lastUpdatedTime) ) { newSidebarItemInserted = true; newSidebarItems.push({ type: 'sidebar', lastUpdatedTime: activeItem.lastUpdatedTime, mostRecentNonLocalMessage: activeItem.mostRecentNonLocalMessage, threadInfo: activeItem.threadInfo, }); } newSidebarItems.push(sidebarItem); } result.push({ ...item, sidebars: newSidebarItems, }); } if (activeItem.threadInfo.type !== threadTypes.SIDEBAR) { result.unshift(activeItem); } return result; }, ); const webMessageListData: ( state: AppState, ) => ?(ChatMessageItem[]) = createSelector( (state: AppState) => state.navInfo.activeChatThreadID, (state: AppState) => state.messageStore, messageInfoSelector, threadInfoSelector, threadInfoFromSourceMessageIDSelector, ( threadID: ?string, messageStore: MessageStore, messageInfos: { [id: string]: MessageInfo }, threadInfos: { [id: string]: ThreadInfo }, threadInfoFromSourceMessageID: { [id: string]: ThreadInfo }, ): ?(ChatMessageItem[]) => { if (!threadID) { return null; } return createChatMessageItems( threadID, messageStore, messageInfos, threadInfos, threadInfoFromSourceMessageID, ); }, ); -export { webChatListData, webMessageListData }; +export { webChatListData, webMessageListData, activeChatThreadItem };