import React, { useCallback, useReducer } from 'react' import { ThemedView } from '@/components/ThemedView' import { ThemedText } from '@/components/ThemedText' import { Alert, Linking, Platform, StyleSheet } from 'react-native' import { MaterialIcons } from '@expo/vector-icons' import { GiftedChat, IMessage, Send, SendProps, SystemMessage, } from 'react-native-gifted-chat' import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context' import AccessoryBar from '@/components/chat/AccessoryBar' import CustomActions from '@/components/chat/CustomActions' import CustomView from '@/components/chat/CustomView' import earlierMessages from '@/components/chat/data/earlierMessages' import messagesData from '@/components/chat/data/messages' import * as Clipboard from 'expo-clipboard' //import NavBar from '@/components/chat/NavBar' const user = { _id: 1, name: 'Developer', } interface IState { messages: any[] step: number loadEarlier?: boolean isLoadingEarlier?: boolean isTyping: boolean } enum ActionKind { SEND_MESSAGE = 'SEND_MESSAGE', LOAD_EARLIER_MESSAGES = 'LOAD_EARLIER_MESSAGES', LOAD_EARLIER_START = 'LOAD_EARLIER_START', SET_IS_TYPING = 'SET_IS_TYPING', // LOAD_EARLIER_END = 'LOAD_EARLIER_END', } // An interface for our actions interface StateAction { type: ActionKind payload?: any } function reducer (state: IState, action: StateAction) { switch (action.type) { case ActionKind.SEND_MESSAGE: { return { ...state, step: state.step + 1, messages: action.payload, } } case ActionKind.LOAD_EARLIER_MESSAGES: { return { ...state, loadEarlier: true, isLoadingEarlier: false, messages: action.payload, } } case ActionKind.LOAD_EARLIER_START: { return { ...state, isLoadingEarlier: true, } } case ActionKind.SET_IS_TYPING: { return { ...state, isTyping: action.payload, } } } } const App = () => { const [state, dispatch] = useReducer(reducer, { messages: messagesData, step: 0, loadEarlier: true, isLoadingEarlier: false, isTyping: false, }) const onSend = useCallback( (messages: any[]) => { const sentMessages = [{ ...messages[0], sent: true, received: true }] const newMessages = GiftedChat.append( state.messages, sentMessages, Platform.OS !== 'web' ) dispatch({ type: ActionKind.SEND_MESSAGE, payload: newMessages }) }, [dispatch, state.messages] ) const onLoadEarlier = useCallback(() => { dispatch({ type: ActionKind.LOAD_EARLIER_START }) setTimeout(() => { const newMessages = GiftedChat.prepend( state.messages, earlierMessages() as IMessage[], Platform.OS !== 'web' ) dispatch({ type: ActionKind.LOAD_EARLIER_MESSAGES, payload: newMessages }) }, 1500) // simulating network }, [dispatch, state.messages]) const parsePatterns = useCallback(() => { return [ { pattern: /#(\w+)/, style: { textDecorationLine: 'underline', color: 'darkorange' }, onPress: () => Linking.openURL('https://gbrown.org'), }, ] }, []) const onLongPressAvatar = useCallback((pressedUser: any) => { Alert.alert(JSON.stringify(pressedUser)) }, []) const onPressAvatar = useCallback(() => { Alert.alert('On avatar press') }, []) const handleLongPress = useCallback((context: unknown, currentMessage: object) => { if (!currentMessage.text) return const options = [ 'Copy text', 'Cancel', ] const cancelButtonIndex = options.length - 1 // eslint-disable-next-line @typescript-eslint/no-explicit-any ;(context as any).actionSheet().showActionSheetWithOptions( { options, cancelButtonIndex, }, (buttonIndex: number) => { switch (buttonIndex) { case 0: Clipboard.setStringAsync(currentMessage.text) break default: break } } ) }, []) const onQuickReply = useCallback((replies: any[]) => { const createdAt = new Date() if (replies.length === 1) onSend([ { createdAt, _id: Math.round(Math.random() * 1000000), text: replies[0].title, user, }, ]) else if (replies.length > 1) onSend([ { createdAt, _id: Math.round(Math.random() * 1000000), text: replies.map(reply => reply.title).join(', '), user, }, ]) else console.warn('replies param is not set correctly') }, []) const renderQuickReplySend = useCallback(() => { return {' custom send =>'} }, []) const setIsTyping = useCallback( (isTyping: boolean) => { dispatch({ type: ActionKind.SET_IS_TYPING, payload: isTyping }) }, [dispatch] ) const onSendFromUser = useCallback( (messages: IMessage[] = []) => { const createdAt = new Date() const messagesToUpload = messages.map(message => ({ ...message, user, createdAt, _id: Math.round(Math.random() * 1000000), })) onSend(messagesToUpload) }, [onSend] ) const renderAccessory = useCallback(() => { return ( setIsTyping(!state.isTyping)} /> ) }, [onSendFromUser, setIsTyping, state.isTyping]) const renderCustomActions = useCallback( props => Platform.OS === 'web' ? null : ( ), [onSendFromUser] ) const renderSystemMessage = useCallback(props => { return ( ) }, []) const renderCustomView = useCallback(props => { return }, []) const renderSend = useCallback((props: SendProps) => { return ( ) }, []) return ( ) } const AppWrapper = () => { return ( ) } const styles = StyleSheet.create({ fill: { flex: 1, }, sendLine: { } }) export default AppWrapper