From 96fcbf134526fabe0a1ddbb5080075e3d8bf1bce Mon Sep 17 00:00:00 2001 From: William Grant <willmgrant@gmail.com> Date: Thu, 8 Jun 2023 15:32:25 +1000 Subject: [PATCH] feat: added start enum to interaction status improved error handling, consolidated types --- .../ConversationListItem.tsx | 8 +-- .../InteractionItem.tsx | 12 +--- ts/hooks/useParamSelector.ts | 20 +++---- ts/interactions/conversationInteractions.ts | 60 +++++++++++++------ 4 files changed, 56 insertions(+), 44 deletions(-) diff --git a/ts/components/leftpane/conversation-list-item/ConversationListItem.tsx b/ts/components/leftpane/conversation-list-item/ConversationListItem.tsx index 8f20c5f95..abc561af2 100644 --- a/ts/components/leftpane/conversation-list-item/ConversationListItem.tsx +++ b/ts/components/leftpane/conversation-list-item/ConversationListItem.tsx @@ -82,7 +82,7 @@ const ConversationListItem = (props: Props) => { let isBlocked = useIsBlocked(conversationId); const isSearch = useSelector(isSearching); const selectedConvo = useSelectedConversationKey(); - const conversationInteractionProps = useConversationInteractionState(conversationId); + const interactionProps = useConversationInteractionState(conversationId); const isSelectedConvo = conversationId === selectedConvo && !isNil(selectedConvo); @@ -132,11 +132,7 @@ const ConversationListItem = (props: Props) => { <AvatarItem /> <div className="module-conversation-list-item__content"> <ConversationListItemHeaderItem /> - {conversationInteractionProps?.interactionType ? ( - <InteractionItem {...conversationInteractionProps} /> - ) : ( - <MessageItem /> - )} + {interactionProps ? <InteractionItem {...interactionProps} /> : <MessageItem />} </div> </div> <Portal> diff --git a/ts/components/leftpane/conversation-list-item/InteractionItem.tsx b/ts/components/leftpane/conversation-list-item/InteractionItem.tsx index f4c6a8821..d629acd86 100644 --- a/ts/components/leftpane/conversation-list-item/InteractionItem.tsx +++ b/ts/components/leftpane/conversation-list-item/InteractionItem.tsx @@ -5,6 +5,7 @@ import { useIsPrivate, useIsPublic } from '../../../hooks/useParamSelector'; import { MessageBody } from '../../conversation/message/message-content/MessageBody'; import { assertUnreachable } from '../../../types/sqlSharedTypes'; import { + ConversationInteractionProps, ConversationInteractionStatus, ConversationInteractionType, } from '../../../interactions/conversationInteractions'; @@ -14,23 +15,16 @@ const StyledInteractionItemText = styled.div<{ isError: boolean }>` ${props => props.isError && 'color: var(--danger-color) !important;'} `; -export type InteractionItemProps = { - conversationId?: string; - interactionType?: ConversationInteractionType; - interactionStatus?: ConversationInteractionStatus; -}; - -export const InteractionItem = (props: InteractionItemProps) => { +export const InteractionItem = (props: ConversationInteractionProps) => { const { conversationId, interactionStatus, interactionType } = props; const isGroup = !useIsPrivate(conversationId); const isCommunity = useIsPublic(conversationId); - if (!conversationId || !interactionType) { + if (isEmpty(conversationId) || isEmpty(interactionType) || isEmpty(interactionStatus)) { return null; } let text = ''; - switch (interactionType) { case ConversationInteractionType.Leave: const failText = isCommunity diff --git a/ts/hooks/useParamSelector.ts b/ts/hooks/useParamSelector.ts index 080e5e047..2d7d9b655 100644 --- a/ts/hooks/useParamSelector.ts +++ b/ts/hooks/useParamSelector.ts @@ -10,10 +10,7 @@ import { StateType } from '../state/reducer'; import { getMessageReactsProps } from '../state/selectors/conversations'; import { isPrivateAndFriend } from '../state/selectors/selectedConversation'; import { CONVERSATION } from '../session/constants'; -import { - ConversationInteractionStatus, - ConversationInteractionType, -} from '../interactions/conversationInteractions'; +import { ConversationInteractionProps } from '../interactions/conversationInteractions'; export function useAvatarPath(convoId: string | undefined) { const convoProps = useConversationPropsById(convoId); @@ -274,11 +271,7 @@ export function useIsTyping(conversationId?: string): boolean { export function useConversationInteractionState( conversationId?: string -): { - conversationId?: string; - interactionStatus?: ConversationInteractionStatus; - interactionType?: ConversationInteractionType; -} | null { +): ConversationInteractionProps | null { if (!conversationId) { return null; } @@ -291,9 +284,12 @@ export function useConversationInteractionState( const interactionType = convoProps.interactionType; const interactionStatus = convoProps.interactionStatus; - window.log.debug( - `WIP: useConversationInteractionState: ${conversationId} ${interactionType} ${interactionStatus}` - ); + if (!interactionType || !interactionStatus) { + window.log.warn( + `useConversationInteractionState() missing interactionType or interactionStatus` + ); + return null; + } return { conversationId, interactionType, interactionStatus }; } diff --git a/ts/interactions/conversationInteractions.ts b/ts/interactions/conversationInteractions.ts index 3fcbcff05..fbe59a872 100644 --- a/ts/interactions/conversationInteractions.ts +++ b/ts/interactions/conversationInteractions.ts @@ -45,15 +45,22 @@ import { Storage, setLastProfileUpdateTimestamp } from '../util/storage'; import { UserGroupsWrapperActions } from '../webworker/workers/browser/libsession_worker_interface'; export enum ConversationInteractionStatus { - Success = 'success', - Error = 'error', + Start = 'start', Loading = 'loading', + Error = 'error', + Complete = 'complete', } export enum ConversationInteractionType { Leave = 'leave', } +export type ConversationInteractionProps = { + conversationId: string; + interactionType: ConversationInteractionType; + interactionStatus: ConversationInteractionStatus; +}; + export async function copyPublicKeyByConvoId(convoId: string) { if (OpenGroupUtils.isOpenGroupV2(convoId)) { const fromWrapper = await UserGroupsWrapperActions.getCommunityByFullUrl(convoId); @@ -251,18 +258,16 @@ export function showLeavePrivateConversationbyConvoId(conversationId: string, na await updateConversationInteractionState({ conversationId, type: ConversationInteractionType.Leave, + status: ConversationInteractionStatus.Start, }); await getConversationController().delete1o1(conversationId, { fromSyncMessage: false, justHidePrivate: true, }); onClickClose(); + // Note (Will): This is probably redundant since this is a destructive interaction and therefore the conversation will be undefined - await updateConversationInteractionState({ - conversationId, - type: ConversationInteractionType.Leave, - status: ConversationInteractionStatus.Success, - }); + await clearConversationInteractionState({ conversationId }); } catch (err) { window.log.warn(`showLeavePrivateConversationbyConvoId error: ${err}`); await updateConversationInteractionState({ @@ -310,6 +315,7 @@ export function showLeaveGroupByConvoId(conversationId: string, name?: string) { await updateConversationInteractionState({ conversationId, type: ConversationInteractionType.Leave, + status: ConversationInteractionStatus.Start, }); if (isPublic) { await getConversationController().deleteCommunity(conversation.id, { @@ -322,12 +328,9 @@ export function showLeaveGroupByConvoId(conversationId: string, name?: string) { }); } onClickClose(); + // Note (Will): This is probably redundant since this is a destructive interaction and therefore the conversation will be undefined - await updateConversationInteractionState({ - conversationId, - type: ConversationInteractionType.Leave, - status: ConversationInteractionStatus.Success, - }); + await clearConversationInteractionState({ conversationId }); } catch (err) { window.log.warn(`showLeaveGroupByConvoId error: ${err}`); await updateConversationInteractionState({ @@ -653,6 +656,12 @@ export async function callRecipient(pubkey: string, canCall: boolean) { } } +/** + * Updates the interaction state for a conversation. Remember to run clearConversationInteractionState() when the interaction is complete and we don't want to show it in the UI anymore. + * @param conversationId + * @param type the type of conversation interaciton we are doing + * @param status the status of that interaction + */ export async function updateConversationInteractionState({ conversationId, type, @@ -660,18 +669,35 @@ export async function updateConversationInteractionState({ }: { conversationId: string; type: ConversationInteractionType; - status?: ConversationInteractionStatus; + status: ConversationInteractionStatus; }) { const convo = getConversationController().get(conversationId); if (convo) { convo.set('interactionType', type); - convo.set('interactionStatus', status ? status : undefined); + convo.set('interactionStatus', status); await convo.commit(); window.log.debug( - `WIP: updateConversationInteractionState for ${conversationId} to ${type}${ - status ? ` ${status}` : '' - }` + `WIP: updateConversationInteractionState for ${conversationId} to ${type} ${status}` ); } } + +/** + * Clears the interaction state for a conversation. We would use this when we don't need to show anything in the UI once an action is complete. + * @param conversationId + */ +export async function clearConversationInteractionState({ + conversationId, +}: { + conversationId: string; +}) { + const convo = getConversationController().get(conversationId); + if (convo) { + convo.set('interactionType', undefined); + convo.set('interactionStatus', undefined); + + await convo.commit(); + window.log.debug(`WIP: clearConversationInteractionState() for ${conversationId}`); + } +}