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}`);
+  }
+}