From 7c7da1bc312dfe6b2e7a01681eb65a80caf19d96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20W=C4=85sowicz?= Date: Thu, 12 Sep 2024 14:56:49 +0200 Subject: [PATCH] Enhance DMActivityHandler Summary: This differential addresses Ashoat review for this diff: https://phab.comm.dev/D13246 Test Plan: 1. Create thick thread between users A and B. 2. Log in as user A on two devices (on web and on native) and log in as user B on third device. 3. Send message from B to A. Open the thread as A on web. Ensure rescinding happens on native. 4. Open the thread as A on native. Change opened thread as A on web. Send messages from B to A. Ensure that thread remains read on web. Reviewers: tomek, kamil, ashoat Reviewed By: ashoat Differential Revision: https://phab.comm.dev/D13305 --- lib/handlers/dm-activity-handler.js | 11 +++-------- native/components/dm-activity-handler.react.js | 18 +++--------------- native/navigation/nav-selectors.js | 15 +++++++++++++++ native/socket.react.js | 9 ++------- web/components/dm-activity-handler.react.js | 17 +++-------------- web/selectors/nav-selectors.js | 16 ++++++++++++++++ web/socket.react.js | 11 ++--------- 7 files changed, 44 insertions(+), 53 deletions(-) diff --git a/lib/handlers/dm-activity-handler.js b/lib/handlers/dm-activity-handler.js index 25c06a5e8a..a749f7df41 100644 --- a/lib/handlers/dm-activity-handler.js +++ b/lib/handlers/dm-activity-handler.js @@ -1,8 +1,8 @@ // @flow + import invariant from 'invariant'; import * as React from 'react'; -import { updateActivityActionTypes } from '../actions/activity-actions.js'; import { type OutboundDMOperationSpecification, dmOperationSpecificationTypes, @@ -10,7 +10,6 @@ import { import { useProcessAndSendDMOperation } from '../shared/dm-ops/process-dm-ops.js'; import { getMostRecentNonLocalMessageID } from '../shared/message-utils.js'; import { threadIsPending } from '../shared/thread-utils.js'; -import type { ActivityUpdateSuccessPayload } from '../types/activity-types.js'; import type { DMChangeThreadReadStatusOperation } from '../types/dm-ops.js'; import type { RawThreadInfo } from '../types/minimally-encoded-thread-permissions-types.js'; import { threadTypeIsThick } from '../types/thread-types-enum.js'; @@ -20,7 +19,7 @@ import { useSelector } from '../utils/redux-utils.js'; function useUpdateDMActivity(): ( viewerID: string, activeThreadInfo: RawThreadInfo, -) => Promise { +) => Promise { const processAndSendDMOperation = useProcessAndSendDMOperation(); return React.useCallback( async (viewerID: string, activeThreadInfo: RawThreadInfo) => { @@ -43,7 +42,6 @@ function useUpdateDMActivity(): ( }; await processAndSendDMOperation(opSpecification); - return { activityUpdates: {}, result: { unfocusedToUnread: [] } }; }, [processAndSendDMOperation], ); @@ -89,10 +87,7 @@ function useDMActivityHandler(activeThread: ?string): void { return; } - void dispatchActionPromise( - updateActivityActionTypes, - updateDMActivity(viewerID, activeThreadInfo), - ); + void updateDMActivity(viewerID, activeThreadInfo); }, [ updateDMActivity, dispatchActionPromise, diff --git a/native/components/dm-activity-handler.react.js b/native/components/dm-activity-handler.react.js index 14e69ae48d..609d31dd1a 100644 --- a/native/components/dm-activity-handler.react.js +++ b/native/components/dm-activity-handler.react.js @@ -1,25 +1,13 @@ // @flow + import * as React from 'react'; import useDMActivityHandler from 'lib/handlers/dm-activity-handler.js'; -import { isLoggedIn } from 'lib/selectors/user-selectors.js'; -import { activeMessageListSelector } from '../navigation/nav-selectors.js'; -import { NavContext } from '../navigation/navigation-context.js'; -import { useSelector } from '../redux/redux-utils.js'; +import { useForegroundActiveThread } from '../navigation/nav-selectors.js'; function DMActivityHandler(): React.Node { - const active = useSelector( - state => isLoggedIn(state) && state.lifecycleState !== 'background', - ); - const navContext = React.useContext(NavContext); - const activeThread = React.useMemo(() => { - if (!active) { - return null; - } - return activeMessageListSelector(navContext); - }, [active, navContext]); - + const activeThread = useForegroundActiveThread(); useDMActivityHandler(activeThread); return null; } diff --git a/native/navigation/nav-selectors.js b/native/navigation/nav-selectors.js index 7df61edaba..28b8b6782f 100644 --- a/native/navigation/nav-selectors.js +++ b/native/navigation/nav-selectors.js @@ -8,6 +8,7 @@ import { createSelector } from 'reselect'; import { nonThreadCalendarFiltersSelector } from 'lib/selectors/calendar-filter-selectors.js'; import { currentCalendarQuery } from 'lib/selectors/nav-selectors.js'; +import { isLoggedIn } from 'lib/selectors/user-selectors.js'; import { useCanEditMessage } from 'lib/shared/edit-messages-utils.js'; import type { CalendarQuery } from 'lib/types/entry-types.js'; import type { CalendarFilter } from 'lib/types/filter-types.js'; @@ -209,6 +210,19 @@ const activeMessageListSelector: (context: ?NavContextType) => ?string = activeThread(navigationState, messageListRouteNames), ); +function useForegroundActiveThread(): ?string { + const active = useSelector( + state => isLoggedIn(state) && state.lifecycleState !== 'background', + ); + const navContext = React.useContext(NavContext); + return React.useMemo(() => { + if (!active) { + return null; + } + return activeMessageListSelector(navContext); + }, [active, navContext]); +} + function useActiveThread(): ?string { const navContext = React.useContext(NavContext); return React.useMemo(() => { @@ -442,4 +456,5 @@ export { getTabNavState, getChatNavStateFromTabNavState, useCanEditMessageNative, + useForegroundActiveThread, }; diff --git a/native/socket.react.js b/native/socket.react.js index 4db9da6502..779e7c36ee 100644 --- a/native/socket.react.js +++ b/native/socket.react.js @@ -18,8 +18,8 @@ import { useDispatchActionPromise } from 'lib/utils/redux-promise-utils.js'; import { useDispatch } from 'lib/utils/redux-utils.js'; import { - activeMessageListSelector, nativeCalendarQuery, + useForegroundActiveThread, } from './navigation/nav-selectors.js'; import { NavContext } from './navigation/navigation-context.js'; import { useSelector } from './redux/redux-utils.js'; @@ -77,12 +77,7 @@ const NativeSocket: React.ComponentType = }), ); - const activeThread = React.useMemo(() => { - if (!active) { - return null; - } - return activeMessageListSelector(navContext); - }, [active, navContext]); + const activeThread = useForegroundActiveThread(); const lastCommunicatedPlatformDetails = useSelector( lastCommunicatedPlatformDetailsSelector(keyserverID), diff --git a/web/components/dm-activity-handler.react.js b/web/components/dm-activity-handler.react.js index 71d55e568d..026e4b4f09 100644 --- a/web/components/dm-activity-handler.react.js +++ b/web/components/dm-activity-handler.react.js @@ -1,25 +1,14 @@ // @flow + import * as React from 'react'; import useDMActivityHandler from 'lib/handlers/dm-activity-handler.js'; -import { isLoggedIn } from 'lib/selectors/user-selectors.js'; import { useSelector } from '../redux/redux-utils.js'; -import { activeThreadSelector } from '../selectors/nav-selectors.js'; +import { foregroundActiveThreadSelector } from '../selectors/nav-selectors.js'; function DMActivityHandler(): React.Node { - const active = useSelector( - state => isLoggedIn(state) && state.lifecycleState !== 'background', - ); - const reduxActiveThread = useSelector(activeThreadSelector); - const windowActive = useSelector(state => state.windowActive); - const activeThread = React.useMemo(() => { - if (!active || !windowActive) { - return null; - } - return reduxActiveThread; - }, [active, windowActive, reduxActiveThread]); - + const activeThread = useSelector(foregroundActiveThreadSelector); useDMActivityHandler(activeThread); return null; } diff --git a/web/selectors/nav-selectors.js b/web/selectors/nav-selectors.js index 124fd57096..bbb1cac07b 100644 --- a/web/selectors/nav-selectors.js +++ b/web/selectors/nav-selectors.js @@ -5,6 +5,7 @@ import { createSelector } from 'reselect'; import { nonThreadCalendarFiltersSelector } from 'lib/selectors/calendar-filter-selectors.js'; import { currentCalendarQuery } from 'lib/selectors/nav-selectors.js'; +import { isLoggedIn } from 'lib/selectors/user-selectors.js'; import type { CalendarQuery } from 'lib/types/entry-types.js'; import type { CalendarFilter } from 'lib/types/filter-types.js'; import type { @@ -86,6 +87,20 @@ function activeThreadSelector(state: AppState): ?string { return state.navInfo.tab === 'chat' ? state.navInfo.activeChatThreadID : null; } +const foregroundActiveThreadSelector: (state: AppState) => ?string = + createSelector( + (state: AppState) => + isLoggedIn(state) && state.lifecycleState !== 'background', + (state: AppState) => state.windowActive, + activeThreadSelector, + (active: boolean, windowActive: boolean, activeThread: ?string) => { + if (!active || !windowActive) { + return null; + } + return activeThread; + }, + ); + const webCalendarQuery: (state: AppState) => () => CalendarQuery = createSelector( currentCalendarQuery, @@ -137,4 +152,5 @@ export { nonThreadCalendarQuery, navTabSelector, navSettingsSectionSelector, + foregroundActiveThreadSelector, }; diff --git a/web/socket.react.js b/web/socket.react.js index 57f191227f..b1c774db18 100644 --- a/web/socket.react.js +++ b/web/socket.react.js @@ -19,8 +19,8 @@ import { useDispatch } from 'lib/utils/redux-utils.js'; import { useNetworkConnected } from './redux/keyserver-reachability-handler.js'; import { useSelector } from './redux/redux-utils.js'; import { - activeThreadSelector, webCalendarQuery, + foregroundActiveThreadSelector, } from './selectors/nav-selectors.js'; import { sessionIdentificationSelector, @@ -65,14 +65,7 @@ const WebSocket: React.ComponentType = ); const currentCalendarQuery = useSelector(webCalendarQuery); - const reduxActiveThread = useSelector(activeThreadSelector); - const windowActive = useSelector(state => state.windowActive); - const activeThread = React.useMemo(() => { - if (!active || !windowActive) { - return null; - } - return reduxActiveThread; - }, [active, windowActive, reduxActiveThread]); + const activeThread = useSelector(foregroundActiveThreadSelector); const dispatch = useDispatch(); const dispatchActionPromise = useDispatchActionPromise();