Bluesky app fork with some witchin' additions 💫
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

[Clipclops] Moar error (#3837)

* Add history error

* Log error

* Add period

authored by

Eric Bailey and committed by
GitHub
051e897a 1e484c63

+132 -34
+54
src/screens/Messages/Conversation/MessageListError.tsx
··· 1 + import React from 'react' 2 + import {View} from 'react-native' 3 + import {msg} from '@lingui/macro' 4 + import {useLingui} from '@lingui/react' 5 + 6 + import {ConvoError, ConvoItem} from '#/state/messages/convo' 7 + import {atoms as a, useTheme} from '#/alf' 8 + import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/icons/CircleInfo' 9 + import {InlineLinkText} from '#/components/Link' 10 + import {Text} from '#/components/Typography' 11 + 12 + export function MessageListError({ 13 + item, 14 + }: { 15 + item: ConvoItem & {type: 'error-recoverable'} 16 + }) { 17 + const t = useTheme() 18 + const {_} = useLingui() 19 + const message = React.useMemo(() => { 20 + return { 21 + [ConvoError.HistoryFailed]: _(msg`Failed to load past messages.`), 22 + }[item.code] 23 + }, [_, item.code]) 24 + 25 + return ( 26 + <View style={[a.py_md, a.align_center]}> 27 + <View 28 + style={[ 29 + a.align_center, 30 + a.pt_md, 31 + a.pb_lg, 32 + a.px_3xl, 33 + a.rounded_md, 34 + t.atoms.bg_contrast_25, 35 + {maxWidth: 300}, 36 + ]}> 37 + <CircleInfo size="lg" fill={t.palette.negative_400} /> 38 + <Text style={[a.pt_sm, a.leading_snug]}> 39 + {message}{' '} 40 + <InlineLinkText 41 + to="#" 42 + label={_(msg`Press to retry`)} 43 + onPress={e => { 44 + e.preventDefault() 45 + item.retry() 46 + return false 47 + }}> 48 + {_(msg`Retry.`)} 49 + </InlineLinkText> 50 + </Text> 51 + </View> 52 + </View> 53 + ) 54 + }
+3
src/screens/Messages/Conversation/MessagesList.tsx
··· 17 17 import {ConvoItem, ConvoStatus} from '#/state/messages/convo' 18 18 import {useSetMinimalShellMode} from '#/state/shell' 19 19 import {MessageInput} from '#/screens/Messages/Conversation/MessageInput' 20 + import {MessageListError} from '#/screens/Messages/Conversation/MessageListError' 20 21 import {atoms as a} from '#/alf' 21 22 import {Button, ButtonText} from '#/components/Button' 22 23 import {MessageItem} from '#/components/dms/MessageItem' ··· 63 64 return <Text>Deleted message</Text> 64 65 } else if (item.type === 'pending-retry') { 65 66 return <RetryButton onPress={item.retry} /> 67 + } else if (item.type === 'error-recoverable') { 68 + return <MessageListError item={item} /> 66 69 } 67 70 68 71 return null
+75 -34
src/state/messages/convo.ts
··· 25 25 Suspended = 'suspended', 26 26 } 27 27 28 + export enum ConvoError { 29 + HistoryFailed = 'historyFailed', 30 + } 31 + 28 32 export type ConvoItem = 29 33 | { 30 34 type: 'message' | 'pending-message' ··· 48 52 type: 'pending-retry' 49 53 key: string 50 54 retry: () => void 55 + } 56 + | { 57 + type: 'error-recoverable' 58 + key: string 59 + code: ConvoError 60 + retry: () => void 61 + } 62 + | { 63 + type: 'error-fatal' 64 + code: ConvoError 65 + key: string 51 66 } 52 67 53 68 export type ConvoState = ··· 169 184 > = new Map() 170 185 private deletedMessages: Set<string> = new Set() 171 186 private footerItems: Map<string, ConvoItem> = new Map() 187 + private headerItems: Map<string, ConvoItem> = new Map() 172 188 173 189 private pendingEventIngestion: Promise<void> | undefined 174 190 private isProcessingPendingMessages = false ··· 366 382 */ 367 383 if (this.isFetchingHistory) return 368 384 369 - this.isFetchingHistory = true 370 - this.commit() 371 - 372 385 /* 373 - * Delay if paginating while scrolled to prevent momentum scrolling from 374 - * jerking the list around, plus makes it feel a little more human. 386 + * If we've rendered a retry state for history fetching, exit. Upon retry, 387 + * this will be removed and we'll try again. 375 388 */ 376 - if (this.pastMessages.size > 0) { 377 - await new Promise(y => setTimeout(y, 500)) 378 - } 389 + if (this.headerItems.has(ConvoError.HistoryFailed)) return 390 + 391 + try { 392 + this.isFetchingHistory = true 393 + this.commit() 394 + 395 + /* 396 + * Delay if paginating while scrolled to prevent momentum scrolling from 397 + * jerking the list around, plus makes it feel a little more human. 398 + */ 399 + if (this.pastMessages.size > 0) { 400 + await new Promise(y => setTimeout(y, 500)) 401 + // throw new Error('UNCOMMENT TO TEST RETRY') 402 + } 379 403 380 - const response = await this.agent.api.chat.bsky.convo.getMessages( 381 - { 382 - cursor: this.historyCursor, 383 - convoId: this.convoId, 384 - limit: isNative ? 25 : 50, 385 - }, 386 - { 387 - headers: { 388 - Authorization: this.__tempFromUserDid, 404 + const response = await this.agent.api.chat.bsky.convo.getMessages( 405 + { 406 + cursor: this.historyCursor, 407 + convoId: this.convoId, 408 + limit: isNative ? 25 : 50, 409 + }, 410 + { 411 + headers: { 412 + Authorization: this.__tempFromUserDid, 413 + }, 389 414 }, 390 - }, 391 - ) 392 - const {cursor, messages} = response.data 415 + ) 416 + const {cursor, messages} = response.data 393 417 394 - this.historyCursor = cursor || null 418 + this.historyCursor = cursor ?? null 395 419 396 - for (const message of messages) { 397 - if ( 398 - ChatBskyConvoDefs.isMessageView(message) || 399 - ChatBskyConvoDefs.isDeletedMessageView(message) 400 - ) { 401 - this.pastMessages.set(message.id, message) 402 - 403 - // set to latest rev 420 + for (const message of messages) { 404 421 if ( 405 - message.rev > (this.eventsCursor = this.eventsCursor || message.rev) 422 + ChatBskyConvoDefs.isMessageView(message) || 423 + ChatBskyConvoDefs.isDeletedMessageView(message) 406 424 ) { 407 - this.eventsCursor = message.rev 425 + this.pastMessages.set(message.id, message) 426 + 427 + // set to latest rev 428 + if ( 429 + message.rev > (this.eventsCursor = this.eventsCursor || message.rev) 430 + ) { 431 + this.eventsCursor = message.rev 432 + } 408 433 } 409 434 } 435 + } catch (e: any) { 436 + logger.error('Convo: failed to fetch message history') 437 + 438 + this.headerItems.set(ConvoError.HistoryFailed, { 439 + type: 'error-recoverable', 440 + key: ConvoError.HistoryFailed, 441 + code: ConvoError.HistoryFailed, 442 + retry: () => { 443 + this.headerItems.delete(ConvoError.HistoryFailed) 444 + this.fetchMessageHistory() 445 + }, 446 + }) 447 + } finally { 448 + this.isFetchingHistory = false 449 + this.commit() 410 450 } 411 - 412 - this.isFetchingHistory = false 413 - this.commit() 414 451 } 415 452 416 453 private async pollEvents() { ··· 728 765 nextMessage: null, 729 766 }) 730 767 } 768 + }) 769 + 770 + this.headerItems.forEach(item => { 771 + items.push(item) 731 772 }) 732 773 733 774 return items