diff --git a/lib/hooks/invite-links.js b/lib/hooks/invite-links.js --- a/lib/hooks/invite-links.js +++ b/lib/hooks/invite-links.js @@ -15,6 +15,7 @@ } from '../actions/thread-actions.js'; import { extractKeyserverIDFromID } from '../keyserver-conn/keyserver-call-utils.js'; import { createLoadingStatusSelector } from '../selectors/loading-selectors.js'; +import { threadInfoSelector } from '../selectors/thread-selectors.js'; import { isLoggedInToKeyserver } from '../selectors/user-selectors.js'; import type { KeyserverOverride } from '../shared/invite-links.js'; import { useIsKeyserverURLValid } from '../shared/keyserver-utils.js'; @@ -27,6 +28,7 @@ InviteLinkVerificationResponse, } from '../types/link-types.js'; import type { LoadingStatus } from '../types/loading-types.js'; +import type { ThreadInfo } from '../types/minimally-encoded-thread-permissions-types.js'; import type { ThreadJoinPayload } from '../types/thread-types.js'; import { useDispatchActionPromise } from '../utils/redux-promise-utils.js'; import { useDispatch, useSelector } from '../utils/redux-utils.js'; @@ -155,8 +157,9 @@ +inviteSecret: string, +keyserverOverride: ?KeyserverOverride, +calendarQuery: () => CalendarQuery, - +onFinish: () => mixed, + +closeModal: () => mixed, +setLinkStatus: SetState, + +navigateToThread: ThreadInfo => mixed, }; function useAcceptInviteLink(params: AcceptInviteLinkParams): { +joinCommunity: () => mixed, @@ -167,8 +170,9 @@ inviteSecret, keyserverOverride, calendarQuery, - onFinish, + closeModal, setLinkStatus, + navigateToThread, } = params; const dispatch = useDispatch(); @@ -271,6 +275,7 @@ setLinkStatus, ]); + const [joined, setJoined] = React.useState(false); React.useEffect(() => { void (async () => { if (!ongoingJoinData || !isAuthenticated) { @@ -292,7 +297,7 @@ }, inviteLinkSecret: inviteSecret, }); - onFinish(); + setJoined(true); ongoingJoinData.resolve(result); } catch (e) { setLinkStatus(status => (status === 'valid' ? 'invalid' : status)); @@ -308,10 +313,29 @@ inviteSecret, isAuthenticated, ongoingJoinData, - onFinish, + closeModal, setLinkStatus, ]); + const threadInfos = useSelector(threadInfoSelector); + React.useEffect(() => { + if (!joined) { + return; + } + const threadID = verificationResponse.community?.id; + if (!threadID || !threadInfos[threadID]) { + closeModal(); + return; + } + navigateToThread(threadInfos[threadID]); + }, [ + joined, + navigateToThread, + closeModal, + threadInfos, + verificationResponse.community?.id, + ]); + const dispatchActionPromise = useDispatchActionPromise(); const joinCommunity = React.useCallback(() => { void dispatchActionPromise( diff --git a/native/navigation/invite-link-modal.react.js b/native/navigation/invite-link-modal.react.js --- a/native/navigation/invite-link-modal.react.js +++ b/native/navigation/invite-link-modal.react.js @@ -11,6 +11,7 @@ import { threadInfoSelector } from 'lib/selectors/thread-selectors.js'; import type { KeyserverOverride } from 'lib/shared/invite-links'; import type { InviteLinkVerificationResponse } from 'lib/types/link-types.js'; +import type { ThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types'; import { nonThreadCalendarQuery } from './nav-selectors.js'; import { NavContext } from './navigation-context.js'; @@ -50,13 +51,22 @@ }), ); + const navigateToThreadWithParams = useNavigateToThread(); + const navigateToThread = React.useCallback( + (threadInfo: ThreadInfo) => { + navigateToThreadWithParams({ threadInfo }); + }, + [navigateToThreadWithParams], + ); + const { joinCommunity, joinThreadLoadingStatus } = useAcceptInviteLink({ verificationResponse: invitationDetails, inviteSecret: secret, keyserverOverride, calendarQuery, - onFinish: props.navigation.goBack, + closeModal: props.navigation.goBack, setLinkStatus, + navigateToThread, }); const header = React.useMemo(() => { @@ -90,7 +100,6 @@ ]); const threadInfos = useSelector(threadInfoSelector); - const navigateToThread = useNavigateToThread(); const closeModal = React.useCallback(() => { const communityID = invitationDetails.community?.id; if ( @@ -98,7 +107,7 @@ communityID && threadInfos[communityID] ) { - navigateToThread({ threadInfo: threadInfos[communityID] }); + navigateToThread(threadInfos[communityID]); } else { props.navigation.goBack(); } diff --git a/web/invite-links/accept-invite-modal.react.js b/web/invite-links/accept-invite-modal.react.js --- a/web/invite-links/accept-invite-modal.react.js +++ b/web/invite-links/accept-invite-modal.react.js @@ -11,9 +11,12 @@ import type { LinkStatus } from 'lib/hooks/invite-links.js'; import type { KeyserverOverride } from 'lib/shared/invite-links.js'; import { type InviteLinkVerificationResponse } from 'lib/types/link-types.js'; +import type { ThreadInfo } from 'lib/types/minimally-encoded-thread-permissions-types.js'; +import { useDispatch } from 'lib/utils/redux-utils.js'; import css from './accept-invite-modal.css'; import Button, { buttonThemes } from '../components/button.react.js'; +import { updateNavInfoActionType } from '../redux/action-types.js'; import { useSelector } from '../redux/redux-utils.js'; import { nonThreadCalendarQuery } from '../selectors/nav-selectors.js'; @@ -33,13 +36,30 @@ const { popModal } = useModalContext(); const calendarQuery = useSelector(nonThreadCalendarQuery); + const dispatch = useDispatch(); + const navigateToThread = React.useCallback( + (threadInfo: ThreadInfo) => { + dispatch({ + type: updateNavInfoActionType, + payload: { + chatMode: 'view', + activeChatThreadID: threadInfo.id, + tab: 'chat', + }, + }); + popModal(); + }, + [dispatch, popModal], + ); + const { joinCommunity, joinThreadLoadingStatus } = useAcceptInviteLink({ verificationResponse, inviteSecret, keyserverOverride, calendarQuery, - onFinish: popModal, + closeModal: popModal, setLinkStatus, + navigateToThread, }); let content;