tooot/src/screens/Compose/Root/Footer/Emojis.tsx

139 lines
3.9 KiB
TypeScript
Raw Normal View History

2021-01-01 17:52:14 +01:00
import haptics from '@components/haptics'
import { useAccessibility } from '@utils/accessibility/AccessibilityManager'
2022-02-13 22:14:16 +01:00
import { countInstanceEmoji } from '@utils/slices/instancesSlice'
2021-01-01 17:52:14 +01:00
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
2021-05-23 23:19:37 +02:00
import React, { RefObject, useCallback, useContext, useEffect } from 'react'
2021-04-09 21:43:12 +02:00
import { useTranslation } from 'react-i18next'
import {
AccessibilityInfo,
findNodeHandle,
Pressable,
SectionList,
StyleSheet,
Text,
View
} from 'react-native'
2021-03-27 00:02:32 +01:00
import FastImage from 'react-native-fast-image'
2022-02-13 22:14:16 +01:00
import { useDispatch } from 'react-redux'
import validUrl from 'valid-url'
import updateText from '../../updateText'
import ComposeContext from '../../utils/createContext'
2020-12-03 22:03:06 +01:00
2021-04-09 21:43:12 +02:00
export interface Props {
accessibleRefEmojis: RefObject<SectionList>
}
const ComposeEmojis: React.FC<Props> = ({ accessibleRefEmojis }) => {
2021-05-23 23:19:37 +02:00
const { composeState, composeDispatch } = useContext(ComposeContext)
const { reduceMotionEnabled } = useAccessibility()
2022-02-12 14:51:01 +01:00
const { colors } = useTheme()
2021-05-23 23:19:37 +02:00
const { t } = useTranslation()
2022-02-13 22:14:16 +01:00
const dispatch = useDispatch()
2020-12-03 22:03:06 +01:00
2021-04-09 21:43:12 +02:00
useEffect(() => {
const tagEmojis = findNodeHandle(accessibleRefEmojis.current)
if (composeState.emoji.active) {
tagEmojis && AccessibilityInfo.setAccessibilityFocus(tagEmojis)
}
}, [composeState.emoji.active])
2020-12-10 19:19:56 +01:00
const listHeader = useCallback(
({ section: { title } }) => (
2022-02-12 14:51:01 +01:00
<Text style={[styles.group, { color: colors.secondary }]}>{title}</Text>
2020-12-10 19:19:56 +01:00
),
[]
)
const listItem = useCallback(
2021-05-23 23:19:37 +02:00
({ index, item }: { item: Mastodon.Emoji[]; index: number }) => {
return (
<View key={index} style={styles.emojis}>
{item.map(emoji => {
const uri = reduceMotionEnabled ? emoji.static_url : emoji.url
if (validUrl.isHttpsUri(uri)) {
return (
<Pressable
key={emoji.shortcode}
onPress={() => {
2022-02-13 22:14:16 +01:00
haptics('Light')
2021-05-23 23:19:37 +02:00
updateText({
composeState,
composeDispatch,
newText: `:${emoji.shortcode}:`,
type: 'emoji'
})
2022-02-13 22:14:16 +01:00
dispatch(countInstanceEmoji(emoji))
2021-05-23 23:19:37 +02:00
}}
>
<FastImage
accessibilityLabel={t(
'common:customEmoji.accessibilityLabel',
{
emoji: emoji.shortcode
}
)}
accessibilityHint={t(
'screenCompose:content.root.footer.emojis.accessibilityHint'
)}
source={{ uri }}
style={styles.emoji}
/>
</Pressable>
)
} else {
return null
}
})}
2020-12-10 19:19:56 +01:00
</View>
2021-05-23 23:19:37 +02:00
)
},
[composeState]
2020-12-10 19:19:56 +01:00
)
2020-12-03 22:03:06 +01:00
return (
<View style={styles.base}>
<SectionList
2021-04-09 21:43:12 +02:00
accessible
ref={accessibleRefEmojis}
2020-12-03 22:03:06 +01:00
horizontal
2021-03-18 23:32:31 +01:00
keyboardShouldPersistTaps='always'
2021-01-22 01:34:20 +01:00
sections={composeState.emoji.emojis || []}
2021-05-23 23:19:37 +02:00
keyExtractor={item => item[0].shortcode}
2020-12-10 19:19:56 +01:00
renderSectionHeader={listHeader}
renderItem={listItem}
windowSize={2}
2020-12-03 22:03:06 +01:00
/>
</View>
)
}
const styles = StyleSheet.create({
base: {
flex: 1,
flexDirection: 'row',
flexWrap: 'wrap',
justifyContent: 'space-around',
height: 260
},
group: {
position: 'absolute',
left: StyleConstants.Spacing.L,
...StyleConstants.FontStyle.S
2020-12-03 22:03:06 +01:00
},
emojis: {
flex: 1,
flexWrap: 'wrap',
marginTop: StyleConstants.Spacing.M,
marginLeft: StyleConstants.Spacing.M
},
emoji: {
width: 32,
height: 32,
padding: StyleConstants.Spacing.S,
margin: StyleConstants.Spacing.S
}
})
export default React.memo(ComposeEmojis, () => true)