diff --git a/lib/hooks/input-state-container-hooks.js b/lib/hooks/input-state-container-hooks.js --- a/lib/hooks/input-state-container-hooks.js +++ b/lib/hooks/input-state-container-hooks.js @@ -46,6 +46,7 @@ blobHashFromBlobServiceURI, isBlobServiceURI, } from '../utils/blob-service.js'; +import { SendMessageError } from '../utils/errors.js'; import { useSelector, useDispatch } from '../utils/redux-utils.js'; type MediaIDUpdatePayload = { +id: string, +thumbnailID?: string }; @@ -122,9 +123,13 @@ }); if (result.result === 'failure' && result.failedMessageIDs.length > 0) { - const e: any = new Error('Failed to send message to all peers'); - e.failedOutboundP2PMessageIDs = result.failedMessageIDs; - throw e; + const error = new SendMessageError( + 'Failed to send message to all peers', + localID, + messageInfo.threadID, + ); + error.failedOutboundP2PMessageIDs = result.failedMessageIDs; + throw error; } return { localID, @@ -248,9 +253,13 @@ }); if (result.result === 'failure' && result.failedMessageIDs.length > 0) { - const e: any = new Error('Failed to send message to all peers'); - e.failedOutboundP2PMessageIDs = result.failedMessageIDs; - throw e; + const error = new SendMessageError( + 'Failed to send message to all peers', + localID, + messageInfo.threadID, + ); + error.failedOutboundP2PMessageIDs = result.failedMessageIDs; + throw error; } return { result: { diff --git a/lib/types/redux-types.js b/lib/types/redux-types.js --- a/lib/types/redux-types.js +++ b/lib/types/redux-types.js @@ -176,6 +176,7 @@ SetLateResponsePayload, UpdateKeyserverReachabilityPayload, } from '../keyserver-conn/keyserver-conn-types.js'; +import type { SendMessageError } from '../utils/errors.js'; export type BaseAppState = { +navInfo: NavInfo, @@ -732,11 +733,7 @@ | { +type: 'SEND_TEXT_MESSAGE_FAILED', +error: true, - +payload: Error & { - +localID: string, - +threadID: string, - +failedOutboundP2PMessageIDs?: $ReadOnlyArray, - }, + +payload: SendMessageError, +loadingInfo?: LoadingInfo, } | { @@ -752,11 +749,7 @@ | { +type: 'SEND_MULTIMEDIA_MESSAGE_FAILED', +error: true, - +payload: Error & { - +localID: string, - +threadID: string, - +failedOutboundP2PMessageIDs?: $ReadOnlyArray, - }, + +payload: SendMessageError, +loadingInfo?: LoadingInfo, } | { @@ -772,13 +765,7 @@ | { +type: 'SEND_REACTION_MESSAGE_FAILED', +error: true, - +payload: Error & { - +localID: string, - +threadID: string, - +targetMessageID: string, - +reaction: string, - +action: string, - }, + +payload: SendMessageError, +loadingInfo: LoadingInfo, } | { diff --git a/lib/utils/errors.js b/lib/utils/errors.js --- a/lib/utils/errors.js +++ b/lib/utils/errors.js @@ -1,7 +1,5 @@ // @flow -import copyError from 'utils-copy-error'; - import type { PlatformDetails } from '../types/device-types.js'; import type { ServerSocketMessageType } from '../types/socket-types.js'; @@ -52,6 +50,18 @@ } } +class SendMessageError extends ExtendableError { + localID: string; + threadID: string; + failedOutboundP2PMessageIDs: ?$ReadOnlyArray; + + constructor(error: string, localID: string, threadID: string) { + super(error); + this.localID = localID; + this.threadID = threadID; + } +} + function getMessageForException(e: mixed): ?string { if (typeof e === 'string') { return e; @@ -66,16 +76,12 @@ return undefined; } -function cloneError(e: E): E { - return copyError(e); -} - export { ExtendableError, ServerError, FetchTimeout, getMessageForException, - cloneError, SocketOffline, SocketTimeout, + SendMessageError, }; diff --git a/native/chat/reaction-message-utils.js b/native/chat/reaction-message-utils.js --- a/native/chat/reaction-message-utils.js +++ b/native/chat/reaction-message-utils.js @@ -23,7 +23,7 @@ thickThreadTypes, threadTypeIsThick, } from 'lib/types/thread-types-enum.js'; -import { cloneError } from 'lib/utils/errors.js'; +import { SendMessageError, getMessageForException } from 'lib/utils/errors.js'; import { useDispatchActionPromise } from 'lib/utils/redux-promise-utils.js'; import { useSelector } from '../redux/redux-utils.js'; @@ -114,11 +114,12 @@ cancelable: true, }, ); - - const copy = cloneError(e); - copy.localID = localID; - copy.threadID = threadID; - throw copy; + const exceptionMessage = getMessageForException(e) ?? ''; + throw new SendMessageError( + `Exception while sending reaction: ${exceptionMessage}`, + localID, + threadID, + ); } })(); diff --git a/native/input/input-state-container.react.js b/native/input/input-state-container.react.js --- a/native/input/input-state-container.react.js +++ b/native/input/input-state-container.react.js @@ -92,7 +92,7 @@ type NewThickThreadRequest, } from 'lib/types/thread-types.js'; import { getConfig } from 'lib/utils/config.js'; -import { cloneError, getMessageForException } from 'lib/utils/errors.js'; +import { getMessageForException, SendMessageError } from 'lib/utils/errors.js'; import { values } from 'lib/utils/objects.js'; import { type DispatchActionPromise, @@ -358,12 +358,15 @@ const result = await threadCreationPromise; newThreadID = result.threadID; } catch (e) { - const copy = cloneError(e); - copy.localID = messageInfo.localID; - copy.threadID = messageInfo.threadID; + const exceptionMessage = getMessageForException(e) ?? ''; + const payload = new SendMessageError( + `Exception while creating thread: ${exceptionMessage}`, + messageInfo.localID ?? '', + messageInfo.threadID, + ); this.props.dispatch({ type: sendMultimediaMessageActionTypes.failed, - payload: copy, + payload, error: true, }); return; @@ -403,10 +406,12 @@ this.pendingSidebarCreationMessageLocalIDs.delete(localID); return result; } catch (e) { - const copy = cloneError(e); - copy.localID = localID; - copy.threadID = threadID; - throw copy; + const exceptionMessage = getMessageForException(e) ?? ''; + throw new SendMessageError( + `Exception when sending multimedia message: ${exceptionMessage}`, + localID, + threadID, + ); } } @@ -516,12 +521,15 @@ try { threadCreationResult = await this.startThreadCreation(threadInfo); } catch (e) { - const copy = cloneError(e); - copy.localID = messageInfo.localID; - copy.threadID = messageInfo.threadID; + const exceptionMessage = getMessageForException(e) ?? ''; + const payload = new SendMessageError( + `Exception while creating thread: ${exceptionMessage}`, + messageInfo.localID ?? '', + messageInfo.threadID, + ); this.props.dispatch({ type: sendTextMessageActionTypes.failed, - payload: copy, + payload, error: true, }); return; @@ -615,10 +623,12 @@ this.pendingSidebarCreationMessageLocalIDs.delete(localID); return result; } catch (e) { - const copy = cloneError(e); - copy.localID = messageInfo.localID; - copy.threadID = messageInfo.threadID; - throw copy; + const exceptionMessage = getMessageForException(e) ?? ''; + throw new SendMessageError( + `Exception when sending text message: ${exceptionMessage}`, + messageInfo.localID ?? '', + messageInfo.threadID, + ); } } diff --git a/web/chat/reaction-message-utils.js b/web/chat/reaction-message-utils.js --- a/web/chat/reaction-message-utils.js +++ b/web/chat/reaction-message-utils.js @@ -24,7 +24,7 @@ thickThreadTypes, threadTypeIsThick, } from 'lib/types/thread-types-enum.js'; -import { cloneError } from 'lib/utils/errors.js'; +import { SendMessageError, getMessageForException } from 'lib/utils/errors.js'; import { useDispatchActionPromise } from 'lib/utils/redux-promise-utils.js'; import Alert from '../modals/alert.react.js'; @@ -117,11 +117,12 @@ Please try again later , ); - - const copy = cloneError(e); - copy.localID = localID; - copy.threadID = threadID; - throw copy; + const exceptionMessage = getMessageForException(e) ?? ''; + throw new SendMessageError( + `Exception while sending reaction: ${exceptionMessage}`, + localID, + threadID, + ); } })(); diff --git a/web/input/input-state-container.react.js b/web/input/input-state-container.react.js --- a/web/input/input-state-container.react.js +++ b/web/input/input-state-container.react.js @@ -95,7 +95,7 @@ makeBlobServiceEndpointURL, } from 'lib/utils/blob-service.js'; import { getConfig } from 'lib/utils/config.js'; -import { cloneError, getMessageForException } from 'lib/utils/errors.js'; +import { getMessageForException, SendMessageError } from 'lib/utils/errors.js'; import { type DispatchActionPromise, useDispatchActionPromise, @@ -493,12 +493,15 @@ const result = await threadCreationPromise; newThreadID = result.threadID; } catch (e) { - const copy = cloneError(e); - copy.localID = messageInfo.localID; - copy.threadID = messageInfo.threadID; + const exceptionMessage = getMessageForException(e) ?? ''; + const payload = new SendMessageError( + `Exception when creating thread: ${exceptionMessage}`, + messageInfo.localID ?? '', + messageInfo.threadID, + ); this.props.dispatch({ type: sendMultimediaMessageActionTypes.failed, - payload: copy, + payload, error: true, }); return; @@ -586,10 +589,12 @@ }); return result; } catch (e) { - const copy = cloneError(e); - copy.localID = localID; - copy.threadID = threadID; - throw copy; + const exceptionMessage = getMessageForException(e) ?? ''; + throw new SendMessageError( + `Exception while sending multimedia message: ${exceptionMessage}`, + localID, + threadID, + ); } } @@ -1353,12 +1358,15 @@ try { threadCreationResult = await this.startThreadCreation(threadInfo); } catch (e) { - const copy = cloneError(e); - copy.localID = messageInfo.localID; - copy.threadID = messageInfo.threadID; + const exceptionMessage = getMessageForException(e) ?? ''; + const payload = new SendMessageError( + `Exception while creating thread: ${exceptionMessage}`, + messageInfo.localID ?? '', + messageInfo.threadID, + ); this.props.dispatch({ type: sendTextMessageActionTypes.failed, - payload: copy, + payload, error: true, }); return; @@ -1425,10 +1433,12 @@ this.pendingSidebarCreationMessageLocalIDs.delete(localID); return result; } catch (e) { - const copy = cloneError(e); - copy.localID = messageInfo.localID; - copy.threadID = messageInfo.threadID; - throw copy; + const exceptionMessage = getMessageForException(e) ?? ''; + throw new SendMessageError( + `Exception while sending text message: ${exceptionMessage}`, + messageInfo.localID ?? '', + messageInfo.threadID, + ); } }