Bluesky app fork with some witchin' additions 💫
0
fork

Configure Feed

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

[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

authored by

Hailey and committed by
GitHub
db968b76 268e30d2

+128 -11
+104 -10
src/screens/Messages/Conversation/index.tsx
··· 1 1 import React from 'react' 2 - import {msg} from '@lingui/macro' 2 + import {TouchableOpacity, View} from 'react-native' 3 + import {AppBskyActorDefs} from '@atproto/api' 4 + import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' 5 + import {msg, Trans} from '@lingui/macro' 3 6 import {useLingui} from '@lingui/react' 7 + import {useNavigation} from '@react-navigation/native' 4 8 import {NativeStackScreenProps} from '@react-navigation/native-stack' 5 9 6 - import {CommonNavigatorParams} from '#/lib/routes/types' 10 + import {CommonNavigatorParams, NavigationProp} from '#/lib/routes/types' 7 11 import {useGate} from '#/lib/statsig/statsig' 8 - import {ViewHeader} from '#/view/com/util/ViewHeader' 12 + import {BACK_HITSLOP} from 'lib/constants' 13 + import {isWeb} from 'platform/detection' 14 + import {useSession} from 'state/session' 15 + import {UserAvatar} from 'view/com/util/UserAvatar' 9 16 import {CenteredView} from 'view/com/util/Views' 10 17 import {MessagesList} from '#/screens/Messages/Conversation/MessagesList' 18 + import {useChatQuery} from '#/screens/Messages/Temp/query/query' 19 + import {atoms as a, useBreakpoints, useTheme} from '#/alf' 20 + import {Button, ButtonIcon} from '#/components/Button' 21 + import {DotGrid_Stroke2_Corner0_Rounded} from '#/components/icons/DotGrid' 22 + import {ListMaybePlaceholder} from '#/components/Lists' 23 + import {Text} from '#/components/Typography' 11 24 import {ClipClopGate} from '../gate' 12 25 13 26 type Props = NativeStackScreenProps< ··· 15 28 'MessagesConversation' 16 29 > 17 30 export function MessagesConversationScreen({route}: Props) { 31 + const gate = useGate() 18 32 const chatId = route.params.conversation 19 - const {_} = useLingui() 20 - const gate = useGate() 33 + const {currentAccount} = useSession() 34 + const myDid = currentAccount?.did 35 + 36 + const {data: chat, isError: isError} = useChatQuery(chatId) 37 + const otherProfile = React.useMemo(() => { 38 + return chat?.members?.find(m => m.did !== myDid) 39 + }, [chat?.members, myDid]) 21 40 22 41 if (!gate('dms')) return <ClipClopGate /> 23 42 43 + if (!chat || !otherProfile) { 44 + return ( 45 + <CenteredView style={{flex: 1}} sideBorders> 46 + <ListMaybePlaceholder isLoading={true} isError={isError} /> 47 + </CenteredView> 48 + ) 49 + } 50 + 24 51 return ( 25 52 <CenteredView style={{flex: 1}} sideBorders> 26 - <ViewHeader 27 - title={_(msg`Chat with ${chatId}`)} 28 - showOnDesktop 29 - showBorder 30 - /> 53 + <Header profile={otherProfile} /> 31 54 <MessagesList chatId={chatId} /> 32 55 </CenteredView> 33 56 ) 34 57 } 58 + 59 + function Header({profile}: {profile: AppBskyActorDefs.ProfileViewBasic}) { 60 + const t = useTheme() 61 + const {_} = useLingui() 62 + const {gtTablet} = useBreakpoints() 63 + const navigation = useNavigation<NavigationProp>() 64 + 65 + const onPressBack = React.useCallback(() => { 66 + if (isWeb) { 67 + navigation.replace('MessagesList') 68 + } else { 69 + navigation.pop() 70 + } 71 + }, [navigation]) 72 + 73 + return ( 74 + <View 75 + style={[ 76 + t.atoms.bg, 77 + t.atoms.border_contrast_low, 78 + a.border_b, 79 + a.flex_row, 80 + a.justify_between, 81 + a.gap_lg, 82 + a.px_lg, 83 + a.py_sm, 84 + ]}> 85 + {!gtTablet ? ( 86 + <TouchableOpacity 87 + testID="viewHeaderDrawerBtn" 88 + onPress={onPressBack} 89 + hitSlop={BACK_HITSLOP} 90 + style={{ 91 + width: 30, 92 + height: 30, 93 + }} 94 + accessibilityRole="button" 95 + accessibilityLabel={_(msg`Back`)} 96 + accessibilityHint={_(msg`Access navigation links and settings`)}> 97 + <FontAwesomeIcon 98 + size={18} 99 + icon="angle-left" 100 + style={{ 101 + marginTop: 6, 102 + }} 103 + color={t.atoms.text.color} 104 + /> 105 + </TouchableOpacity> 106 + ) : ( 107 + <View style={{width: 30}} /> 108 + )} 109 + <View style={[a.align_center, a.gap_sm]}> 110 + <UserAvatar size={32} avatar={profile.avatar} /> 111 + <Text style={[a.text_lg, a.font_bold]}> 112 + <Trans>{profile.displayName}</Trans> 113 + </Text> 114 + </View> 115 + <View> 116 + <Button 117 + label={_(msg`Chat settings`)} 118 + color="secondary" 119 + size="large" 120 + variant="ghost" 121 + style={[{height: 'auto', width: 'auto'}, a.px_sm, a.py_sm]} 122 + onPress={() => {}}> 123 + <ButtonIcon icon={DotGrid_Stroke2_Corner0_Rounded} /> 124 + </Button> 125 + </View> 126 + </View> 127 + ) 128 + }
+24
src/screens/Messages/Temp/query/query.ts
··· 73 73 const chatJson = 74 74 (await chatResponse.json()) as TempDmChatGetChat.OutputSchema 75 75 76 + queryClient.setQueryData(['chatQuery', chatId], chatJson.chat) 77 + 76 78 const newChat = { 77 79 chatId, 78 80 messages: messagesJson.messages, ··· 275 277 getNextPageParam: lastPage => lastPage.cursor, 276 278 }) 277 279 } 280 + 281 + export function useChatQuery(chatId: string) { 282 + const headers = useHeaders() 283 + const {serviceUrl} = useDmServiceUrlStorage() 284 + 285 + return useQuery({ 286 + queryKey: ['chatQuery', chatId], 287 + queryFn: async () => { 288 + const chatResponse = await fetch( 289 + `${serviceUrl}/xrpc/temp.dm.getChat?chatId=${chatId}`, 290 + { 291 + headers, 292 + }, 293 + ) 294 + 295 + if (!chatResponse.ok) throw new Error('Failed to fetch chat') 296 + 297 + const json = (await chatResponse.json()) as TempDmChatGetChat.OutputSchema 298 + return json.chat 299 + }, 300 + }) 301 + }
-1
src/screens/Messages/Temp/useDmServiceUrlStorage.tsx
··· 35 35 React.useEffect(() => { 36 36 ;(async () => { 37 37 const v = await getItem() 38 - console.log(v) 39 38 setServiceUrl(v ?? '') 40 39 })() 41 40 }, [getItem])