diff --git a/src/screens/Messages/Conversation/MessageListError.tsx b/src/screens/Messages/Conversation/MessageListError.tsx index 5f5df4fc..38a63b0f 100644 --- a/src/screens/Messages/Conversation/MessageListError.tsx +++ b/src/screens/Messages/Conversation/MessageListError.tsx @@ -5,8 +5,9 @@ import {useLingui} from '@lingui/react' import {ConvoItem, ConvoItemError} from '#/state/messages/convo/types' import {atoms as a, useTheme} from '#/alf' +import {Button, ButtonIcon, ButtonText} from '#/components/Button' +import {ArrowRotateCounterClockwise_Stroke2_Corner0_Rounded as Refresh} from '#/components/icons/ArrowRotateCounterClockwise' import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/icons/CircleInfo' -import {InlineLinkText} from '#/components/Link' import {Text} from '#/components/Typography' export function MessageListError({ @@ -21,39 +22,52 @@ export function MessageListError({ [ConvoItemError.Network]: _( msg`There was an issue connecting to the chat.`, ), - [ConvoItemError.HistoryFailed]: _(msg`Failed to load past messages.`), - [ConvoItemError.PollFailed]: _( + [ConvoItemError.FirehoseFailed]: _( msg`This chat was disconnected due to a network error.`, ), + [ConvoItemError.HistoryFailed]: _(msg`Failed to load past messages.`), + [ConvoItemError.PendingFailed]: _(msg`Failed to send message(s).`), }[item.code] }, [_, item.code]) return ( - + - - - {message}{' '} - { - e.preventDefault() - item.retry() - return false - }}> - {_(msg`Retry.`)} - - + + + + {message} + + + + ) diff --git a/src/screens/Messages/Conversation/MessagesList.tsx b/src/screens/Messages/Conversation/MessagesList.tsx index 0b8ab524..f99a41b7 100644 --- a/src/screens/Messages/Conversation/MessagesList.tsx +++ b/src/screens/Messages/Conversation/MessagesList.tsx @@ -8,8 +8,6 @@ import {runOnJS, useSharedValue} from 'react-native-reanimated' import {ReanimatedScrollEvent} from 'react-native-reanimated/lib/typescript/reanimated2/hook/commonTypes' import {useSafeAreaInsets} from 'react-native-safe-area-context' import {AppBskyRichtextFacet, RichText} from '@atproto/api' -import {msg, Trans} from '@lingui/macro' -import {useLingui} from '@lingui/react' import {shortenLinks} from '#/lib/strings/rich-text-manip' import {isIOS} from '#/platform/detection' @@ -22,7 +20,6 @@ import {List} from 'view/com/util/List' import {MessageInput} from '#/screens/Messages/Conversation/MessageInput' import {MessageListError} from '#/screens/Messages/Conversation/MessageListError' import {atoms as a, useBreakpoints} from '#/alf' -import {Button, ButtonText} from '#/components/Button' import {MessageItem} from '#/components/dms/MessageItem' import {Loader} from '#/components/Loader' import {Text} from '#/components/Typography' @@ -41,25 +38,6 @@ function MaybeLoader({isLoading}: {isLoading: boolean}) { ) } -function RetryButton({onPress}: {onPress: () => unknown}) { - const {_} = useLingui() - - return ( - - - - ) -} - function renderItem({item}: {item: ConvoItem}) { if (item.type === 'message' || item.type === 'pending-message') { return ( @@ -71,8 +49,6 @@ function renderItem({item}: {item: ConvoItem}) { ) } else if (item.type === 'deleted-message') { return Deleted message - } else if (item.type === 'pending-retry') { - return } else if (item.type === 'error-recoverable') { return } diff --git a/src/state/messages/convo/agent.ts b/src/state/messages/convo/agent.ts index 25e138fb..12e24577 100644 --- a/src/state/messages/convo/agent.ts +++ b/src/state/messages/convo/agent.ts @@ -401,7 +401,7 @@ export class Convo { // throw new Error('UNCOMMENT TO TEST INIT FAILURE') this.dispatch({event: ConvoDispatchEvent.Ready}) } catch (e: any) { - logger.error('Convo: setup() failed') + logger.error(e, {context: 'Convo: setup failed'}) this.dispatch({ event: ConvoDispatchEvent.Error, @@ -413,6 +413,7 @@ export class Convo { }, }, }) + this.commit() } } @@ -500,7 +501,7 @@ export class Convo { this.sender = sender || this.sender this.recipients = recipients || this.recipients } catch (e: any) { - logger.error(`Convo: failed to refresh convo`) + logger.error(e, {context: `Convo: failed to refresh convo`}) this.footerItems.set(ConvoItemError.Network, { type: 'error-recoverable', @@ -601,17 +602,17 @@ export class Convo { } onFirehoseConnect() { - this.footerItems.delete(ConvoItemError.PollFailed) + this.footerItems.delete(ConvoItemError.FirehoseFailed) this.commit() } onFirehoseError(error?: MessagesEventBusError) { - this.footerItems.set(ConvoItemError.PollFailed, { + this.footerItems.set(ConvoItemError.FirehoseFailed, { type: 'error-recoverable', - key: ConvoItemError.PollFailed, - code: ConvoItemError.PollFailed, + key: ConvoItemError.FirehoseFailed, + code: ConvoItemError.FirehoseFailed, retry: () => { - this.footerItems.delete(ConvoItemError.PollFailed) + this.footerItems.delete(ConvoItemError.FirehoseFailed) this.commit() error?.retry() }, @@ -772,13 +773,21 @@ export class Convo { await this.processPendingMessages() this.commit() - } catch (e) { - this.footerItems.set('pending-retry', { - type: 'pending-retry', - key: 'pending-retry', - retry: this.batchRetryPendingMessages.bind(this), + } catch (e: any) { + logger.error(e, {context: `Convo: failed to send message`}) + this.footerItems.set(ConvoItemError.PendingFailed, { + type: 'error-recoverable', + key: ConvoItemError.PendingFailed, + code: ConvoItemError.PendingFailed, + retry: () => { + this.footerItems.delete(ConvoItemError.PendingFailed) + this.commit() + this.batchRetryPendingMessages() + }, }) this.commit() + } finally { + this.isProcessingPendingMessages = false } } @@ -789,10 +798,8 @@ export class Convo { logger.DebugContext.convo, ) - this.footerItems.delete('pending-retry') - this.commit() - try { + // throw new Error('UNCOMMENT TO TEST RETRY') const messageArray = Array.from(this.pendingMessages.values()) const {data} = await networkRetry(2, () => { return this.agent.api.chat.bsky.convo.sendMessageBatch( @@ -831,11 +838,23 @@ export class Convo { } this.commit() - } catch (e) { - this.footerItems.set('pending-retry', { - type: 'pending-retry', - key: 'pending-retry', - retry: this.batchRetryPendingMessages.bind(this), + + logger.debug( + `Convo: sent ${this.pendingMessages.size} pending messages`, + {}, + logger.DebugContext.convo, + ) + } catch (e: any) { + logger.error(e, {context: `Convo: failed to batch retry messages`}) + this.footerItems.set(ConvoItemError.PendingFailed, { + type: 'error-recoverable', + key: ConvoItemError.PendingFailed, + code: ConvoItemError.PendingFailed, + retry: () => { + this.footerItems.delete(ConvoItemError.PendingFailed) + this.commit() + this.batchRetryPendingMessages() + }, }) this.commit() } @@ -862,7 +881,8 @@ export class Convo { }, ) }) - } catch (e) { + } catch (e: any) { + logger.error(e, {context: `Convo: failed to delete message`}) this.deletedMessages.delete(messageId) this.commit() throw e @@ -875,10 +895,6 @@ export class Convo { getItems(): ConvoItem[] { const items: ConvoItem[] = [] - this.headerItems.forEach(item => { - items.push(item) - }) - this.pastMessages.forEach(m => { if (ChatBskyConvoDefs.isMessageView(m)) { items.unshift({ @@ -897,6 +913,10 @@ export class Convo { } }) + this.headerItems.forEach(item => { + items.unshift(item) + }) + this.newMessages.forEach(m => { if (ChatBskyConvoDefs.isMessageView(m)) { items.push({ diff --git a/src/state/messages/convo/types.ts b/src/state/messages/convo/types.ts index 2ed2eeaf..920635c8 100644 --- a/src/state/messages/convo/types.ts +++ b/src/state/messages/convo/types.ts @@ -24,9 +24,22 @@ export enum ConvoStatus { } export enum ConvoItemError { - HistoryFailed = 'historyFailed', - PollFailed = 'pollFailed', + /** + * Generic error + */ Network = 'network', + /** + * Error connecting to event firehose + */ + FirehoseFailed = 'firehoseFailed', + /** + * Error fetching past messages + */ + HistoryFailed = 'historyFailed', + /** + * Error sending new message + */ + PendingFailed = 'pendingFailed', } export enum ConvoErrorCode { @@ -88,11 +101,6 @@ export type ConvoItem = | ChatBskyConvoDefs.DeletedMessageView | null } - | { - type: 'pending-retry' - key: string - retry: () => void - } | { type: 'error-recoverable' key: string