diff options
Diffstat (limited to 'src/screens')
-rw-r--r-- | src/screens/Messages/Conversation/MessageItem.tsx | 12 | ||||
-rw-r--r-- | src/screens/Messages/Conversation/MessagesList.tsx | 9 | ||||
-rw-r--r-- | src/screens/Messages/List/index.tsx | 43 | ||||
-rw-r--r-- | src/screens/Messages/Temp/query/query.ts | 79 |
4 files changed, 99 insertions, 44 deletions
diff --git a/src/screens/Messages/Conversation/MessageItem.tsx b/src/screens/Messages/Conversation/MessageItem.tsx index 74e65488e..822b17804 100644 --- a/src/screens/Messages/Conversation/MessageItem.tsx +++ b/src/screens/Messages/Conversation/MessageItem.tsx @@ -1,12 +1,16 @@ import React from 'react' import {View} from 'react-native' +import {useAgent} from '#/state/session' import {atoms as a, useTheme} from '#/alf' import {Text} from '#/components/Typography' import * as TempDmChatDefs from '#/temp/dm/defs' export function MessageItem({item}: {item: TempDmChatDefs.MessageView}) { const t = useTheme() + const {getAgent} = useAgent() + + const fromMe = item.sender?.did === getAgent().session?.did return ( <View @@ -15,13 +19,17 @@ export function MessageItem({item}: {item: TempDmChatDefs.MessageView}) { a.px_md, a.my_xs, a.rounded_md, + fromMe ? a.self_end : a.self_start, { - backgroundColor: t.palette.primary_500, + backgroundColor: fromMe + ? t.palette.primary_500 + : t.palette.contrast_50, maxWidth: '65%', borderRadius: 17, }, ]}> - <Text style={[a.text_md, {lineHeight: 1.2, color: 'white'}]}> + <Text + style={[a.text_md, a.leading_snug, fromMe && {color: t.palette.white}]}> {item.text} </Text> </View> diff --git a/src/screens/Messages/Conversation/MessagesList.tsx b/src/screens/Messages/Conversation/MessagesList.tsx index aafed42af..e3b518f65 100644 --- a/src/screens/Messages/Conversation/MessagesList.tsx +++ b/src/screens/Messages/Conversation/MessagesList.tsx @@ -1,5 +1,6 @@ import React, {useCallback, useMemo, useRef, useState} from 'react' -import {Alert, FlatList, View, ViewToken} from 'react-native' +import {FlatList, View, ViewToken} from 'react-native' +import {Alert} from 'react-native' import {KeyboardAvoidingView} from 'react-native-keyboard-controller' import {isWeb} from 'platform/detection' @@ -64,6 +65,7 @@ export function MessagesList({chatId}: {chatId: string}) { const totalMessages = useRef(10) // TODO later + const [_, setShowSpinner] = useState(false) // Query Data @@ -147,6 +149,8 @@ export function MessagesList({chatId}: {chatId: string}) { }, ) totalMessages.current = filtered.length + + return filtered }, [chat]) return ( @@ -162,7 +166,7 @@ export function MessagesList({chatId}: {chatId: string}) { contentContainerStyle={{paddingHorizontal: 10}} // In the future, we might want to adjust this value. Not very concerning right now as long as we are only // dealing with text. But whenever we have images or other media and things are taller, we will want to lower - // this...probably + // this...probably. initialNumToRender={20} // Same with the max to render per batch. Let's be safe for now though. maxToRenderPerBatch={25} @@ -175,7 +179,6 @@ export function MessagesList({chatId}: {chatId: string}) { maintainVisibleContentPosition={{ minIndexForVisible: 0, }} - // This is actually a header since we are inverted! ListFooterComponent={<MaybeLoader isLoading={false} />} removeClippedSubviews={true} ref={flatListRef} diff --git a/src/screens/Messages/List/index.tsx b/src/screens/Messages/List/index.tsx index b13ddd291..ff4e8e83e 100644 --- a/src/screens/Messages/List/index.tsx +++ b/src/screens/Messages/List/index.tsx @@ -1,4 +1,4 @@ -import React, {useCallback, useState} from 'react' +import React, {useCallback, useMemo, useState} from 'react' import {View} from 'react-native' import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' @@ -20,10 +20,11 @@ import {SettingsSliderVertical_Stroke2_Corner0_Rounded as SettingsSlider} from ' import {Link} from '#/components/Link' import {ListFooter, ListMaybePlaceholder} from '#/components/Lists' import {Text} from '#/components/Typography' +import {NewChat} from '../../../components/dms/NewChat' import {ClipClopGate} from '../gate' type Props = NativeStackScreenProps<MessagesTabNavigatorParams, 'MessagesList'> -export function MessagesListScreen({}: Props) { +export function MessagesListScreen({navigation}: Props) { const {_} = useLingui() const t = useTheme() @@ -53,14 +54,14 @@ export function MessagesListScreen({}: Props) { const isError = !!error - const conversations = React.useMemo(() => { + const conversations = useMemo(() => { if (data?.pages) { return data.pages.flat() } return [] }, [data]) - const onRefresh = React.useCallback(async () => { + const onRefresh = useCallback(async () => { setIsPTRing(true) try { await refetch() @@ -70,7 +71,7 @@ export function MessagesListScreen({}: Props) { setIsPTRing(false) }, [refetch, setIsPTRing]) - const onEndReached = React.useCallback(async () => { + const onEndReached = useCallback(async () => { if (isFetchingNextPage || !hasNextPage || isError) return try { await fetchNextPage() @@ -79,26 +80,35 @@ export function MessagesListScreen({}: Props) { } }, [isFetchingNextPage, hasNextPage, isError, fetchNextPage]) + const onNewChat = useCallback( + (conversation: string) => + navigation.navigate('MessagesConversation', {conversation}), + [navigation], + ) + const gate = useGate() if (!gate('dms')) return <ClipClopGate /> if (conversations.length < 1) { return ( - <ListMaybePlaceholder - isLoading={isLoading} - isError={isError} - emptyType="results" - emptyMessage={_( - msg`You have no messages yet. Start a conversation with someone!`, - )} - errorMessage={cleanError(error)} - onRetry={isError ? refetch : undefined} - /> + <> + <ListMaybePlaceholder + isLoading={isLoading} + isError={isError} + emptyType="results" + emptyMessage={_( + msg`You have no messages yet. Start a conversation with someone!`, + )} + errorMessage={cleanError(error)} + onRetry={isError ? refetch : undefined} + /> + <NewChat onNewChat={onNewChat} /> + </> ) } return ( - <View> + <View style={a.flex_1}> <ViewHeader title={_(msg`Messages`)} showOnDesktop @@ -106,6 +116,7 @@ export function MessagesListScreen({}: Props) { showBorder canGoBack={false} /> + <NewChat onNewChat={onNewChat} /> <List data={conversations} renderItem={({item}) => { diff --git a/src/screens/Messages/Temp/query/query.ts b/src/screens/Messages/Temp/query/query.ts index 2477dc569..26f9e625f 100644 --- a/src/screens/Messages/Temp/query/query.ts +++ b/src/screens/Messages/Temp/query/query.ts @@ -1,20 +1,24 @@ import {useMutation, useQuery, useQueryClient} from '@tanstack/react-query' -import {useSession} from 'state/session' -import {useDmServiceUrlStorage} from '#/screens/Messages/Temp/useDmServiceUrlStorage' +import {useAgent} from '#/state/session' import * as TempDmChatDefs from '#/temp/dm/defs' import * as TempDmChatGetChat from '#/temp/dm/getChat' +import * as TempDmChatGetChatForMembers from '#/temp/dm/getChatForMembers' import * as TempDmChatGetChatLog from '#/temp/dm/getChatLog' import * as TempDmChatGetChatMessages from '#/temp/dm/getChatMessages' +import {useDmServiceUrlStorage} from '../useDmServiceUrlStorage' /** * TEMPORARY, PLEASE DO NOT JUDGE ME REACT QUERY OVERLORDS 🙏 * (and do not try this at home) */ -function createHeaders(did: string) { +const useHeaders = () => { + const {getAgent} = useAgent() return { - Authorization: did, + get Authorization() { + return getAgent().session!.did + }, } } @@ -27,10 +31,8 @@ type Chat = { export function useChat(chatId: string) { const queryClient = useQueryClient() - + const headers = useHeaders() const {serviceUrl} = useDmServiceUrlStorage() - const {currentAccount} = useSession() - const did = currentAccount?.did ?? '' return useQuery({ queryKey: ['chat', chatId], @@ -44,7 +46,7 @@ export function useChat(chatId: string) { const messagesResponse = await fetch( `${serviceUrl}/xrpc/temp.dm.getChatMessages?chatId=${chatId}`, { - headers: createHeaders(did), + headers, }, ) @@ -56,7 +58,7 @@ export function useChat(chatId: string) { const chatResponse = await fetch( `${serviceUrl}/xrpc/temp.dm.getChat?chatId=${chatId}`, { - headers: createHeaders(did), + headers, }, ) @@ -90,10 +92,8 @@ export function createTempId() { export function useSendMessageMutation(chatId: string) { const queryClient = useQueryClient() - + const headers = useHeaders() const {serviceUrl} = useDmServiceUrlStorage() - const {currentAccount} = useSession() - const did = currentAccount?.did ?? '' return useMutation< TempDmChatDefs.Message, @@ -108,7 +108,7 @@ export function useSendMessageMutation(chatId: string) { { method: 'POST', headers: { - ...createHeaders(did), + ...headers, 'Content-Type': 'application/json', }, body: JSON.stringify({ @@ -130,8 +130,10 @@ export function useSendMessageMutation(chatId: string) { ...prev, messages: [ { + $type: 'temp.dm.defs#messageView', id: variables.tempId, text: variables.message, + sender: {did: headers.Authorization}, // TODO a real DID get }, ...prev.messages, ], @@ -165,10 +167,8 @@ export function useSendMessageMutation(chatId: string) { export function useChatLogQuery() { const queryClient = useQueryClient() - + const headers = useHeaders() const {serviceUrl} = useDmServiceUrlStorage() - const {currentAccount} = useSession() - const did = currentAccount?.did ?? '' return useQuery({ queryKey: ['chatLog'], @@ -183,7 +183,7 @@ export function useChatLogQuery() { prevLog?.cursor ?? '' }`, { - headers: createHeaders(did), + headers, }, ) @@ -193,13 +193,10 @@ export function useChatLogQuery() { (await response.json()) as TempDmChatGetChatLog.OutputSchema for (const log of json.logs) { - if (TempDmChatDefs.isLogDeleteMessage(log)) { + if (TempDmChatDefs.isLogCreateMessage(log)) { queryClient.setQueryData(['chat', log.chatId], (prev: Chat) => { - // What to do in this case - if (!prev) return - - // HACK we don't know who the creator of a message is, so just filter by id for now - if (prev.messages.find(m => m.id === log.message.id)) return prev + // TODO hack filter out duplicates + if (prev?.messages.find(m => m.id === log.message.id)) return return { ...prev, @@ -217,3 +214,39 @@ export function useChatLogQuery() { refetchInterval: 5000, }) } + +export function useGetChatFromMembers({ + onSuccess, + onError, +}: { + onSuccess?: (data: TempDmChatGetChatForMembers.OutputSchema) => void + onError?: (error: Error) => void +}) { + const queryClient = useQueryClient() + const headers = useHeaders() + const {serviceUrl} = useDmServiceUrlStorage() + + return useMutation({ + mutationFn: async (members: string[]) => { + const response = await fetch( + `${serviceUrl}/xrpc/temp.dm.getChatForMembers?members=${members.join( + ',', + )}`, + {headers}, + ) + + if (!response.ok) throw new Error('Failed to fetch chat') + + return (await response.json()) as TempDmChatGetChatForMembers.OutputSchema + }, + onSuccess: data => { + queryClient.setQueryData(['chat', data.chat.id], { + chatId: data.chat.id, + messages: [], + lastRev: data.chat.rev, + }) + onSuccess?.(data) + }, + onError, + }) +} |