[Clipclops] Header for chat (#3775)

* add temp `getchat` query

* properly get the other profile

* add basic header

* normalize layout on all devices

* remove unused imports, adjust style

* remove unnecessary log

* remove another log

* remove some more imports

* cleanup

* use `Button` instead in the header

* lint
zio/stable
Hailey 2024-04-30 15:04:17 -07:00 committed by GitHub
parent 268e30d21a
commit db968b7610
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 128 additions and 11 deletions

View File

@ -1,13 +1,26 @@
import React from 'react' import React from 'react'
import {msg} from '@lingui/macro' import {TouchableOpacity, View} from 'react-native'
import {AppBskyActorDefs} from '@atproto/api'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react' import {useLingui} from '@lingui/react'
import {useNavigation} from '@react-navigation/native'
import {NativeStackScreenProps} from '@react-navigation/native-stack' import {NativeStackScreenProps} from '@react-navigation/native-stack'
import {CommonNavigatorParams} from '#/lib/routes/types' import {CommonNavigatorParams, NavigationProp} from '#/lib/routes/types'
import {useGate} from '#/lib/statsig/statsig' import {useGate} from '#/lib/statsig/statsig'
import {ViewHeader} from '#/view/com/util/ViewHeader' import {BACK_HITSLOP} from 'lib/constants'
import {isWeb} from 'platform/detection'
import {useSession} from 'state/session'
import {UserAvatar} from 'view/com/util/UserAvatar'
import {CenteredView} from 'view/com/util/Views' import {CenteredView} from 'view/com/util/Views'
import {MessagesList} from '#/screens/Messages/Conversation/MessagesList' import {MessagesList} from '#/screens/Messages/Conversation/MessagesList'
import {useChatQuery} from '#/screens/Messages/Temp/query/query'
import {atoms as a, useBreakpoints, useTheme} from '#/alf'
import {Button, ButtonIcon} from '#/components/Button'
import {DotGrid_Stroke2_Corner0_Rounded} from '#/components/icons/DotGrid'
import {ListMaybePlaceholder} from '#/components/Lists'
import {Text} from '#/components/Typography'
import {ClipClopGate} from '../gate' import {ClipClopGate} from '../gate'
type Props = NativeStackScreenProps< type Props = NativeStackScreenProps<
@ -15,20 +28,101 @@ type Props = NativeStackScreenProps<
'MessagesConversation' 'MessagesConversation'
> >
export function MessagesConversationScreen({route}: Props) { export function MessagesConversationScreen({route}: Props) {
const chatId = route.params.conversation
const {_} = useLingui()
const gate = useGate() const gate = useGate()
const chatId = route.params.conversation
const {currentAccount} = useSession()
const myDid = currentAccount?.did
const {data: chat, isError: isError} = useChatQuery(chatId)
const otherProfile = React.useMemo(() => {
return chat?.members?.find(m => m.did !== myDid)
}, [chat?.members, myDid])
if (!gate('dms')) return <ClipClopGate /> if (!gate('dms')) return <ClipClopGate />
if (!chat || !otherProfile) {
return (
<CenteredView style={{flex: 1}} sideBorders>
<ListMaybePlaceholder isLoading={true} isError={isError} />
</CenteredView>
)
}
return ( return (
<CenteredView style={{flex: 1}} sideBorders> <CenteredView style={{flex: 1}} sideBorders>
<ViewHeader <Header profile={otherProfile} />
title={_(msg`Chat with ${chatId}`)}
showOnDesktop
showBorder
/>
<MessagesList chatId={chatId} /> <MessagesList chatId={chatId} />
</CenteredView> </CenteredView>
) )
} }
function Header({profile}: {profile: AppBskyActorDefs.ProfileViewBasic}) {
const t = useTheme()
const {_} = useLingui()
const {gtTablet} = useBreakpoints()
const navigation = useNavigation<NavigationProp>()
const onPressBack = React.useCallback(() => {
if (isWeb) {
navigation.replace('MessagesList')
} else {
navigation.pop()
}
}, [navigation])
return (
<View
style={[
t.atoms.bg,
t.atoms.border_contrast_low,
a.border_b,
a.flex_row,
a.justify_between,
a.gap_lg,
a.px_lg,
a.py_sm,
]}>
{!gtTablet ? (
<TouchableOpacity
testID="viewHeaderDrawerBtn"
onPress={onPressBack}
hitSlop={BACK_HITSLOP}
style={{
width: 30,
height: 30,
}}
accessibilityRole="button"
accessibilityLabel={_(msg`Back`)}
accessibilityHint={_(msg`Access navigation links and settings`)}>
<FontAwesomeIcon
size={18}
icon="angle-left"
style={{
marginTop: 6,
}}
color={t.atoms.text.color}
/>
</TouchableOpacity>
) : (
<View style={{width: 30}} />
)}
<View style={[a.align_center, a.gap_sm]}>
<UserAvatar size={32} avatar={profile.avatar} />
<Text style={[a.text_lg, a.font_bold]}>
<Trans>{profile.displayName}</Trans>
</Text>
</View>
<View>
<Button
label={_(msg`Chat settings`)}
color="secondary"
size="large"
variant="ghost"
style={[{height: 'auto', width: 'auto'}, a.px_sm, a.py_sm]}
onPress={() => {}}>
<ButtonIcon icon={DotGrid_Stroke2_Corner0_Rounded} />
</Button>
</View>
</View>
)
}

View File

@ -73,6 +73,8 @@ export function useChat(chatId: string) {
const chatJson = const chatJson =
(await chatResponse.json()) as TempDmChatGetChat.OutputSchema (await chatResponse.json()) as TempDmChatGetChat.OutputSchema
queryClient.setQueryData(['chatQuery', chatId], chatJson.chat)
const newChat = { const newChat = {
chatId, chatId,
messages: messagesJson.messages, messages: messagesJson.messages,
@ -275,3 +277,25 @@ export function useListChats() {
getNextPageParam: lastPage => lastPage.cursor, getNextPageParam: lastPage => lastPage.cursor,
}) })
} }
export function useChatQuery(chatId: string) {
const headers = useHeaders()
const {serviceUrl} = useDmServiceUrlStorage()
return useQuery({
queryKey: ['chatQuery', chatId],
queryFn: async () => {
const chatResponse = await fetch(
`${serviceUrl}/xrpc/temp.dm.getChat?chatId=${chatId}`,
{
headers,
},
)
if (!chatResponse.ok) throw new Error('Failed to fetch chat')
const json = (await chatResponse.json()) as TempDmChatGetChat.OutputSchema
return json.chat
},
})
}

View File

@ -35,7 +35,6 @@ export function DmServiceUrlProvider({children}: {children: React.ReactNode}) {
React.useEffect(() => { React.useEffect(() => {
;(async () => { ;(async () => {
const v = await getItem() const v = await getItem()
console.log(v)
setServiceUrl(v ?? '') setServiceUrl(v ?? '')
})() })()
}, [getItem]) }, [getItem])