import haptics from '@components/haptics' import { ParseEmojis } from '@components/Parse' import { ComposeContext } from '@screens/Shared/Compose' import ComposeActions from '@screens/Shared/Compose/Actions' import ComposeRootFooter from '@screens/Shared/Compose/Root/Footer' import ComposeRootHeader from '@screens/Shared/Compose/Root/Header' import updateText from '@screens/Shared/Compose/updateText' import { emojisFetch } from '@utils/fetches/emojisFetch' import { searchFetch } from '@utils/fetches/searchFetch' import { StyleConstants } from '@utils/styles/constants' import { useTheme } from '@utils/styles/ThemeManager' import { forEach, groupBy, sortBy } from 'lodash' import React, { Dispatch, useCallback, useContext, useEffect, useMemo } from 'react' import { View, FlatList, Pressable, StyleSheet, Text, Image } from 'react-native' import { Chase } from 'react-native-animated-spinkit' import { useQuery } from 'react-query' import { ComposeAction, ComposeState } from './utils/types' const ListItem = React.memo( ({ item, composeState, composeDispatch }: { item: Mastodon.Account & Mastodon.Tag composeState: ComposeState composeDispatch: Dispatch }) => { const { theme } = useTheme() const onPress = useCallback(() => { const focusedInput = composeState.textInputFocus.current updateText({ composeState: { ...composeState, [focusedInput]: { ...composeState[focusedInput], selection: { start: composeState.tag!.offset, end: composeState.tag!.offset + composeState.tag!.text.length + 1 } } }, composeDispatch, newText: item.acct ? `@${item.acct}` : `#${item.name}`, type: 'suggestion' }) haptics('Success') }, []) const children = useMemo( () => item.acct ? ( @{item.acct} ) : ( #{item.name} ), [] ) return ( ) }, () => true ) const ComposeRoot: React.FC = () => { const { theme } = useTheme() const { composeState, composeDispatch } = useContext(ComposeContext) const { isFetching, data, refetch } = useQuery( [ 'Search', { type: composeState.tag?.type, term: composeState.tag?.text.substring(1) } ], searchFetch, { enabled: false } ) useEffect(() => { if (composeState.tag?.text) { refetch() } }, [composeState.tag?.text]) const { data: emojisData } = useQuery(['Emojis'], emojisFetch) useEffect(() => { if (emojisData && emojisData.length) { let sortedEmojis: { title: string; data: Mastodon.Emoji[] }[] = [] forEach( groupBy(sortBy(emojisData, ['category', 'shortcode']), 'category'), (value, key) => sortedEmojis.push({ title: key, data: value }) ) composeDispatch({ type: 'emoji', payload: { ...composeState.emoji, emojis: sortedEmojis } }) } }, [emojisData]) const listEmpty = useMemo(() => { if (isFetching) { return ( ) } }, [isFetching]) const listItem = useCallback( ({ item }) => ( ), [composeState] ) return ( item.acct || item.name} /> ) } const styles = StyleSheet.create({ base: { flex: 1 }, contentView: { flex: 1 }, suggestion: { flex: 1 }, account: { flex: 1, flexDirection: 'row', alignItems: 'center', paddingTop: StyleConstants.Spacing.S, paddingBottom: StyleConstants.Spacing.S, marginLeft: StyleConstants.Spacing.Global.PagePadding, marginRight: StyleConstants.Spacing.Global.PagePadding, borderBottomWidth: StyleSheet.hairlineWidth }, accountAvatar: { width: StyleConstants.Font.LineHeight.M * 2, height: StyleConstants.Font.LineHeight.M * 2, marginRight: StyleConstants.Spacing.S, borderRadius: StyleConstants.Avatar.M }, accountName: { ...StyleConstants.FontStyle.S, fontWeight: StyleConstants.Font.Weight.Bold, marginBottom: StyleConstants.Spacing.XS }, accountAccount: { ...StyleConstants.FontStyle.S }, hashtag: { flex: 1, paddingTop: StyleConstants.Spacing.S, paddingBottom: StyleConstants.Spacing.S, marginLeft: StyleConstants.Spacing.Global.PagePadding, marginRight: StyleConstants.Spacing.Global.PagePadding, borderBottomWidth: StyleSheet.hairlineWidth }, hashtagText: { ...StyleConstants.FontStyle.S, fontWeight: StyleConstants.Font.Weight.Bold, marginBottom: StyleConstants.Spacing.XS }, loading: { flex: 1, alignItems: 'center' } }) export default ComposeRoot