From af90fa403c024a3ceb9b8303c91185227733a990 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20W=C4=85sowicz?= Date: Wed, 4 Sep 2024 14:26:18 +0200 Subject: [PATCH] Implement maunally marking DM thread as read/unread Summary: This differential implements marking dm thread as read/unread manually (by toggle). Test Plan: Play around marking a thread as read/unrad on one device and ensure that changes are reflected in the UI of another device (if app is active) or result in correct badge updates/rescinds (inactive app) Reviewers: tomek, kamil Reviewed By: tomek Subscribers: ashoat Differential Revision: https://phab.comm.dev/D13238 --- lib/actions/activity-actions.js | 53 +++++++++++++++++++++++++++++-- lib/hooks/toggle-unread-status.js | 6 ++-- 2 files changed, 55 insertions(+), 4 deletions(-) diff --git a/lib/actions/activity-actions.js b/lib/actions/activity-actions.js index 201b249a11..ce77fd9d04 100644 --- a/lib/actions/activity-actions.js +++ b/lib/actions/activity-actions.js @@ -1,17 +1,27 @@ // @flow +import invariant from 'invariant'; +import * as React from 'react'; + import { extractKeyserverIDFromID, extractKeyserverIDFromIDOptional, } from '../keyserver-conn/keyserver-call-utils.js'; import { useKeyserverCall } from '../keyserver-conn/keyserver-call.js'; import type { CallKeyserverEndpoint } from '../keyserver-conn/keyserver-conn-types.js'; +import type { OutboundDMOperationSpecification } from '../shared/dm-ops/dm-op-utils.js'; +import { dmOperationSpecificationTypes } from '../shared/dm-ops/dm-op-utils.js'; +import { useProcessAndSendDMOperation } from '../shared/dm-ops/process-dm-ops.js'; import type { ActivityUpdate, ActivityUpdateSuccessPayload, SetThreadUnreadStatusPayload, SetThreadUnreadStatusRequest, } from '../types/activity-types.js'; +import type { DMChangeThreadReadStatusOperation } from '../types/dm-ops.js'; +import type { ThreadInfo } from '../types/minimally-encoded-thread-permissions-types'; +import { threadTypeIsThick } from '../types/thread-types-enum.js'; +import { useSelector } from '../utils/redux-utils.js'; export type UpdateActivityInput = { +activityUpdates: $ReadOnlyArray, @@ -98,10 +108,49 @@ const setThreadUnreadStatus = }; }; -function useSetThreadUnreadStatus(): ( +function useSetThreadUnreadStatus( + threadInfo: ThreadInfo, +): ( request: SetThreadUnreadStatusRequest, ) => Promise { - return useKeyserverCall(setThreadUnreadStatus); + const viewerID = useSelector( + state => state.currentUserInfo && state.currentUserInfo.id, + ); + const processAndSendDMOperation = useProcessAndSendDMOperation(); + const keyserverCall = useKeyserverCall(setThreadUnreadStatus); + + return React.useCallback( + async (input: SetThreadUnreadStatusRequest) => { + if (!threadTypeIsThick(threadInfo.type)) { + return await keyserverCall(input); + } + + invariant(viewerID, 'viewerID must be set'); + const op: DMChangeThreadReadStatusOperation = { + type: 'change_thread_read_status', + time: Date.now(), + threadID: threadInfo.id, + creatorID: viewerID, + unread: !threadInfo.currentUser.unread, + }; + + const opSpecification: OutboundDMOperationSpecification = { + type: dmOperationSpecificationTypes.OUTBOUND, + op, + recipients: { + type: 'self_devices', + }, + }; + + await processAndSendDMOperation(opSpecification); + return { + resetToUnread: false, + threadID: threadInfo.id, + }; + }, + + [keyserverCall, threadInfo, viewerID, processAndSendDMOperation], + ); } export { diff --git a/lib/hooks/toggle-unread-status.js b/lib/hooks/toggle-unread-status.js index f9378e00b2..24de6c4cc9 100644 --- a/lib/hooks/toggle-unread-status.js +++ b/lib/hooks/toggle-unread-status.js @@ -22,7 +22,9 @@ function useToggleUnreadStatus( const { currentUser } = threadInfo; const boundSetThreadUnreadStatus: ( request: SetThreadUnreadStatusRequest, - ) => Promise = useSetThreadUnreadStatus(); + ) => Promise = + useSetThreadUnreadStatus(threadInfo); + const toggleUnreadStatus = React.useCallback(() => { const request = { threadID: threadInfo.id, @@ -40,7 +42,7 @@ function useToggleUnreadStatus( ); afterAction(); }, [ - threadInfo.id, + threadInfo, currentUser.unread, mostRecentNonLocalMessage, dispatchActionPromise,