[🐴] Make status checks easier, fix load state (#4010)

* Make status checks easier, fix load state

* Make naming more clear

* Split up types for easier re-use

* Replace hacky usage
This commit is contained in:
Eric Bailey 2024-05-14 11:59:53 -05:00 committed by GitHub
parent bffb9b5906
commit 1c51a48764
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 154 additions and 101 deletions

View file

@ -3,11 +3,20 @@ import {AppState} from 'react-native'
import {useFocusEffect, useIsFocused} from '@react-navigation/native'
import {Convo} from '#/state/messages/convo/agent'
import {ConvoParams, ConvoState} from '#/state/messages/convo/types'
import {
ConvoParams,
ConvoState,
ConvoStateBackgrounded,
ConvoStateReady,
ConvoStateSuspended,
} from '#/state/messages/convo/types'
import {isConvoActive} from '#/state/messages/convo/util'
import {useMessagesEventBus} from '#/state/messages/events'
import {useMarkAsReadMutation} from '#/state/queries/messages/conversation'
import {useAgent} from '#/state/session'
export * from '#/state/messages/convo/util'
const ChatContext = React.createContext<ConvoState | null>(null)
export function useConvo() {
@ -18,6 +27,27 @@ export function useConvo() {
return ctx
}
/**
* This hook should only be used when the Convo is "active", meaning the chat
* is loaded and ready to be used, or its in a suspended or background state,
* and ready for resumption.
*/
export function useConvoActive() {
const ctx = useContext(ChatContext) as
| ConvoStateReady
| ConvoStateBackgrounded
| ConvoStateSuspended
if (!ctx) {
throw new Error('useConvo must be used within a ConvoProvider')
}
if (!isConvoActive(ctx)) {
throw new Error(
`useConvoActive must only be rendered when the Convo is ready.`,
)
}
return ctx
}
export function ConvoProvider({
children,
convoId,

View file

@ -107,82 +107,88 @@ export type ConvoItem =
retry: () => void
}
type DeleteMessage = (messageId: string) => Promise<void>
type SendMessage = (
message: ChatBskyConvoSendMessage.InputSchema['message'],
) => Promise<void>
type FetchMessageHistory = () => Promise<void>
export type ConvoStateUninitialized = {
status: ConvoStatus.Uninitialized
items: []
convo: undefined
error: undefined
sender: undefined
recipients: undefined
isFetchingHistory: false
deleteMessage: undefined
sendMessage: undefined
fetchMessageHistory: undefined
}
export type ConvoStateInitializing = {
status: ConvoStatus.Initializing
items: []
convo: undefined
error: undefined
sender: undefined
recipients: undefined
isFetchingHistory: boolean
deleteMessage: undefined
sendMessage: undefined
fetchMessageHistory: undefined
}
export type ConvoStateReady = {
status: ConvoStatus.Ready
items: ConvoItem[]
convo: ChatBskyConvoDefs.ConvoView
error: undefined
sender: AppBskyActorDefs.ProfileViewBasic
recipients: AppBskyActorDefs.ProfileViewBasic[]
isFetchingHistory: boolean
deleteMessage: DeleteMessage
sendMessage: SendMessage
fetchMessageHistory: FetchMessageHistory
}
export type ConvoStateBackgrounded = {
status: ConvoStatus.Backgrounded
items: ConvoItem[]
convo: ChatBskyConvoDefs.ConvoView
error: undefined
sender: AppBskyActorDefs.ProfileViewBasic
recipients: AppBskyActorDefs.ProfileViewBasic[]
isFetchingHistory: boolean
deleteMessage: DeleteMessage
sendMessage: SendMessage
fetchMessageHistory: FetchMessageHistory
}
export type ConvoStateSuspended = {
status: ConvoStatus.Suspended
items: ConvoItem[]
convo: ChatBskyConvoDefs.ConvoView
error: undefined
sender: AppBskyActorDefs.ProfileViewBasic
recipients: AppBskyActorDefs.ProfileViewBasic[]
isFetchingHistory: boolean
deleteMessage: DeleteMessage
sendMessage: SendMessage
fetchMessageHistory: FetchMessageHistory
}
export type ConvoStateError = {
status: ConvoStatus.Error
items: []
convo: undefined
error: any
sender: undefined
recipients: undefined
isFetchingHistory: false
deleteMessage: undefined
sendMessage: undefined
fetchMessageHistory: undefined
}
export type ConvoState =
| {
status: ConvoStatus.Uninitialized
items: []
convo: undefined
error: undefined
sender: undefined
recipients: undefined
isFetchingHistory: false
deleteMessage: undefined
sendMessage: undefined
fetchMessageHistory: undefined
}
| {
status: ConvoStatus.Initializing
items: []
convo: undefined
error: undefined
sender: undefined
recipients: undefined
isFetchingHistory: boolean
deleteMessage: undefined
sendMessage: undefined
fetchMessageHistory: undefined
}
| {
status: ConvoStatus.Ready
items: ConvoItem[]
convo: ChatBskyConvoDefs.ConvoView
error: undefined
sender: AppBskyActorDefs.ProfileViewBasic
recipients: AppBskyActorDefs.ProfileViewBasic[]
isFetchingHistory: boolean
deleteMessage: (messageId: string) => Promise<void>
sendMessage: (
message: ChatBskyConvoSendMessage.InputSchema['message'],
) => void
fetchMessageHistory: () => void
}
| {
status: ConvoStatus.Suspended
items: ConvoItem[]
convo: ChatBskyConvoDefs.ConvoView
error: undefined
sender: AppBskyActorDefs.ProfileViewBasic
recipients: AppBskyActorDefs.ProfileViewBasic[]
isFetchingHistory: boolean
deleteMessage: (messageId: string) => Promise<void>
sendMessage: (
message: ChatBskyConvoSendMessage.InputSchema['message'],
) => Promise<void>
fetchMessageHistory: () => Promise<void>
}
| {
status: ConvoStatus.Backgrounded
items: ConvoItem[]
convo: ChatBskyConvoDefs.ConvoView
error: undefined
sender: AppBskyActorDefs.ProfileViewBasic
recipients: AppBskyActorDefs.ProfileViewBasic[]
isFetchingHistory: boolean
deleteMessage: (messageId: string) => Promise<void>
sendMessage: (
message: ChatBskyConvoSendMessage.InputSchema['message'],
) => Promise<void>
fetchMessageHistory: () => Promise<void>
}
| {
status: ConvoStatus.Error
items: []
convo: undefined
error: any
sender: undefined
recipients: undefined
isFetchingHistory: false
deleteMessage: undefined
sendMessage: undefined
fetchMessageHistory: undefined
}
| ConvoStateUninitialized
| ConvoStateInitializing
| ConvoStateReady
| ConvoStateBackgrounded
| ConvoStateSuspended
| ConvoStateError

View file

@ -0,0 +1,22 @@
import {
ConvoState,
ConvoStateBackgrounded,
ConvoStateReady,
ConvoStateSuspended,
ConvoStatus,
} from './types'
/**
* Checks if a `Convo` has a `status` that is "active", meaning the chat is
* loaded and ready to be used, or its in a suspended or background state, and
* ready for resumption.
*/
export function isConvoActive(
convo: ConvoState,
): convo is ConvoStateReady | ConvoStateBackgrounded | ConvoStateSuspended {
return (
convo.status === ConvoStatus.Ready ||
convo.status === ConvoStatus.Backgrounded ||
convo.status === ConvoStatus.Suspended
)
}