diff --git a/lib/handlers/dm-activity-handler.js b/lib/handlers/dm-activity-handler.js --- a/lib/handlers/dm-activity-handler.js +++ b/lib/handlers/dm-activity-handler.js @@ -1,6 +1,7 @@ // @flow import invariant from 'invariant'; +import _debounce from 'lodash/debounce.js'; import * as React from 'react'; import { @@ -11,11 +12,13 @@ import { getMostRecentNonLocalMessageID } from '../shared/message-utils.js'; import { threadIsPending } from '../shared/thread-utils.js'; import type { DMChangeThreadReadStatusOperation } from '../types/dm-ops.js'; -import type { RawThreadInfo } from '../types/minimally-encoded-thread-permissions-types.js'; +import { type RawThreadInfo } from '../types/minimally-encoded-thread-permissions-types.js'; import { threadTypeIsThick } from '../types/thread-types-enum.js'; import { useDispatchActionPromise } from '../utils/redux-promise-utils.js'; import { useSelector } from '../utils/redux-utils.js'; +const ACTIVITY_UPDATE_DURATION = 5000; + function useUpdateDMActivity(): ( viewerID: string, activeThreadInfo: RawThreadInfo, @@ -47,6 +50,22 @@ ); } +function getUpateActivityAfterLatestMessageChange( + viewerID: ?string, + activeThreadInfo: ?RawThreadInfo, + updateDMActivity: ( + viewerID: string, + activeThreadInfo: RawThreadInfo, + ) => Promise, +) { + return _debounce(() => { + if (!activeThreadInfo || !viewerID) { + return; + } + void updateDMActivity(viewerID, activeThreadInfo); + }, ACTIVITY_UPDATE_DURATION); +} + function useDMActivityHandler(activeThread: ?string): void { const activeThreadInfo = useSelector(state => activeThread ? state.threadStore.threadInfos[activeThread] : null, @@ -67,6 +86,14 @@ const updateDMActivity = useUpdateDMActivity(); const dispatchActionPromise = useDispatchActionPromise(); + const updateActivityAfterLatestMessageChangeRef = React.useRef( + getUpateActivityAfterLatestMessageChange( + viewerID, + activeThreadInfo, + updateDMActivity, + ), + ); + React.useEffect(() => { const prevActiveThread = prevActiveThreadRef.current; const prevActiveThreadLatestMessage = @@ -75,19 +102,39 @@ prevActiveThreadRef.current = activeThread; prevActiveThreadLatestMessageRef.current = activeThreadLatestMessage; + const activeThreadChanged = prevActiveThread !== activeThread; + if (activeThreadChanged) { + updateActivityAfterLatestMessageChangeRef.current = + getUpateActivityAfterLatestMessageChange( + viewerID, + activeThreadInfo, + updateDMActivity, + ); + } + if ( !viewerID || !activeThread || !activeThreadInfo || !threadTypeIsThick(activeThreadInfo.type) || - threadIsPending(activeThread) || - (activeThread === prevActiveThread && - activeThreadLatestMessage === prevActiveThreadLatestMessage) + threadIsPending(activeThread) ) { return; } - void updateDMActivity(viewerID, activeThreadInfo); + if (activeThreadInfo.currentUser.unread) { + void updateDMActivity(viewerID, activeThreadInfo); + return; + } + + if ( + activeThreadChanged || + activeThreadLatestMessage === prevActiveThreadLatestMessage + ) { + return; + } + + updateActivityAfterLatestMessageChangeRef.current(); }, [ updateDMActivity, dispatchActionPromise, diff --git a/web/redux/redux-setup.js b/web/redux/redux-setup.js --- a/web/redux/redux-setup.js +++ b/web/redux/redux-setup.js @@ -58,6 +58,7 @@ import type { SyncedMetadataStore } from 'lib/types/synced-metadata-types.js'; import type { GlobalThemeInfo } from 'lib/types/theme-types.js'; import type { ThreadActivityStore } from 'lib/types/thread-activity-types'; +import { threadTypeIsThick } from 'lib/types/thread-types-enum.js'; import type { ThreadStore } from 'lib/types/thread-types.js'; import type { TunnelbrokerDeviceToken } from 'lib/types/tunnelbroker-device-token-types.js'; import type { CurrentUserInfo, UserStore } from 'lib/types/user-types.js'; @@ -455,7 +456,8 @@ 'hasFocus' in document && document.hasFocus() && !state.navInfo.pendingThread && - state.threadStore.threadInfos[activeThread].currentUser.unread + state.threadStore.threadInfos[activeThread].currentUser.unread && + !threadTypeIsThick(state.threadStore.threadInfos[activeThread].type) ) { // Makes sure a currently focused thread is never unread const activeThreadInfo = state.threadStore.threadInfos[activeThread];