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,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 { 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 @@
 function useUpdateDMActivity(): (
   viewerID: string,
   activeThreadInfo: RawThreadInfo,
-) => Promise<ActivityUpdateSuccessPayload> {
+) => Promise<void> {
   const processAndSendDMOperation = useProcessAndSendDMOperation();
   return React.useCallback(
     async (viewerID: string, activeThreadInfo: RawThreadInfo) => {
@@ -43,7 +42,6 @@
       };
 
       await processAndSendDMOperation(opSpecification);
-      return { activityUpdates: {}, result: { unfocusedToUnread: [] } };
     },
     [processAndSendDMOperation],
   );
@@ -89,10 +87,7 @@
       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
--- 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
--- a/native/navigation/nav-selectors.js
+++ b/native/navigation/nav-selectors.js
@@ -8,6 +8,7 @@
 
 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 @@
       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 @@
   getTabNavState,
   getChatNavStateFromTabNavState,
   useCanEditMessageNative,
+  useForegroundActiveThread,
 };
diff --git a/native/socket.react.js b/native/socket.react.js
--- a/native/socket.react.js
+++ b/native/socket.react.js
@@ -18,8 +18,8 @@
 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 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
--- 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
--- a/web/selectors/nav-selectors.js
+++ b/web/selectors/nav-selectors.js
@@ -5,6 +5,7 @@
 
 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 @@
   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 @@
   nonThreadCalendarQuery,
   navTabSelector,
   navSettingsSectionSelector,
+  foregroundActiveThreadSelector,
 };
diff --git a/web/socket.react.js b/web/socket.react.js
--- a/web/socket.react.js
+++ b/web/socket.react.js
@@ -19,8 +19,8 @@
 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 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();