Emoji working for compose

This commit is contained in:
xmflsct 2022-09-19 22:22:52 +02:00
parent b44370d3ec
commit fb3cfa0db1
4 changed files with 16 additions and 188 deletions

View File

@ -7,7 +7,7 @@ import { getInstanceFrequentEmojis } from '@utils/slices/instancesSlice'
import { chunk, forEach, groupBy, sortBy } from 'lodash' import { chunk, forEach, groupBy, sortBy } from 'lodash'
import React, { PropsWithChildren, RefObject, useEffect, useReducer, useState } from 'react' import React, { PropsWithChildren, RefObject, useEffect, useReducer, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { Keyboard, KeyboardAvoidingView, Platform, TextInput, View } from 'react-native' import { Keyboard, KeyboardAvoidingView, TextInput, View } from 'react-native'
import FastImage from 'react-native-fast-image' import FastImage from 'react-native-fast-image'
import { Edge, SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context' import { Edge, SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context'
import { useSelector } from 'react-redux' import { useSelector } from 'react-redux'
@ -74,14 +74,14 @@ const ComponentEmojis: React.FC<Props & PropsWithChildren> = ({
if (data && data.length) { if (data && data.length) {
let sortedEmojis: EmojisState['emojis'] = [] let sortedEmojis: EmojisState['emojis'] = []
forEach(groupBy(sortBy(data, ['category', 'shortcode']), 'category'), (value, key) => forEach(groupBy(sortBy(data, ['category', 'shortcode']), 'category'), (value, key) =>
sortedEmojis.push({ title: key, data: chunk(value, 5) }) sortedEmojis.push({ title: key, data: chunk(value, 4) })
) )
if (frequentEmojis.length) { if (frequentEmojis.length) {
sortedEmojis.unshift({ sortedEmojis.unshift({
title: t('componentEmojis:frequentUsed'), title: t('componentEmojis:frequentUsed'),
data: chunk( data: chunk(
frequentEmojis.map(e => e.emoji), frequentEmojis.map(e => e.emoji),
5 4
), ),
type: 'frequent' type: 'frequent'
}) })
@ -125,7 +125,9 @@ const ComponentEmojis: React.FC<Props & PropsWithChildren> = ({
<View <View
style={[ style={[
keyboardShown ? { position: 'absolute', bottom: 0, width: '100%' } : null, keyboardShown ? { position: 'absolute', bottom: 0, width: '100%' } : null,
{ marginBottom: keyboardShown ? insets.bottom : 0 } {
marginBottom: keyboardShown && emojisState.targetIndex === -1 ? insets.bottom : 0
}
]} ]}
children={ children={
emojisState.targetIndex !== -1 ? ( emojisState.targetIndex !== -1 ? (

View File

@ -42,7 +42,7 @@ const EmojisList = () => {
} = emojisState.inputProps[emojisState.targetIndex] } = emojisState.inputProps[emojisState.targetIndex]
const contentFront = value.slice(0, selection.start) const contentFront = value.slice(0, selection.start)
const contentRear = value.slice(selection.end) const contentRear = value.slice(selection.end || selection.start)
const spaceFront = value.length === 0 || /\s/g.test(contentFront.slice(-1)) ? '' : ' ' const spaceFront = value.length === 0 || /\s/g.test(contentFront.slice(-1)) ? '' : ' '
const spaceRear = /\s/g.test(contentRear[0]) ? '' : ' ' const spaceRear = /\s/g.test(contentRear[0]) ? '' : ' '

View File

@ -157,32 +157,19 @@ const ComposeActions: React.FC = () => {
return colors.secondary return colors.secondary
} }
}, [emojisState.emojis.length, emojisState.targetIndex]) }, [emojisState.emojis.length, emojisState.targetIndex])
// useEffect(() => {
// const showSubscription = Keyboard.addListener('keyboardWillShow', () => {
// composeDispatch({ type: 'emoji/shown', payload: false })
// })
// return () => {
// showSubscription.remove()
// }
// }, [])
const emojiOnPress = () => { const emojiOnPress = () => {
analytics('compose_actions_emojis_press', {
current: emojisState.targetIndex !== -1
})
if (emojisState.targetIndex === -1) { if (emojisState.targetIndex === -1) {
Keyboard.dismiss() Keyboard.dismiss()
const focusedPropsIndex = emojisState.inputProps?.findIndex(props => props.isFocused.current)
if (focusedPropsIndex === -1) return
emojisDispatch({ type: 'target', payload: focusedPropsIndex })
} else {
emojisDispatch({ type: 'target', payload: -1 })
return
} }
const focusedPropsIndex = emojisState.inputProps?.findIndex(props => props.isFocused.current)
if (focusedPropsIndex === -1) return
emojisDispatch({ type: 'target', payload: focusedPropsIndex })
// Keyboard.dismiss()
// analytics('compose_actions_emojis_press', {
// current: composeState.emoji.active
// })
// if (composeState.emoji.emojis) {
// composeDispatch({
// type: 'emoji',
// payload: { ...composeState.emoji, active: !composeState.emoji.active }
// })
// }
} }
return ( return (

View File

@ -1,161 +0,0 @@
import haptics from '@components/haptics'
import CustomText from '@components/Text'
import { useAppDispatch } from '@root/store'
import { useAccessibility } from '@utils/accessibility/AccessibilityManager'
import { countInstanceEmoji } from '@utils/slices/instancesSlice'
import { getSettingsStaticEmoji } from '@utils/slices/settingsSlice'
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React, { RefObject, useCallback, useContext, useEffect } from 'react'
import { useTranslation } from 'react-i18next'
import {
AccessibilityInfo,
findNodeHandle,
Image,
Pressable,
SectionList,
View
} from 'react-native'
import FastImage from 'react-native-fast-image'
import { useSelector } from 'react-redux'
import validUrl from 'valid-url'
import updateText from '../../updateText'
import ComposeContext from '../../utils/createContext'
export interface Props {
accessibleRefEmojis: RefObject<SectionList>
}
const ComposeEmojis: React.FC<Props> = ({ accessibleRefEmojis }) => {
const { composeState, composeDispatch } = useContext(ComposeContext)
const { reduceMotionEnabled } = useAccessibility()
const { colors } = useTheme()
const { t } = useTranslation()
const dispatch = useAppDispatch()
const staticEmoji = useSelector(getSettingsStaticEmoji)
useEffect(() => {
const tagEmojis = findNodeHandle(accessibleRefEmojis.current)
if (composeState.emoji.active) {
tagEmojis && AccessibilityInfo.setAccessibilityFocus(tagEmojis)
}
}, [composeState.emoji.active])
const listItem = useCallback(
({ index, item }: { item: Mastodon.Emoji[]; index: number }) => {
return (
<View
key={index}
style={{
flex: 1,
flexWrap: 'wrap',
marginTop: StyleConstants.Spacing.M,
marginLeft: StyleConstants.Spacing.M
}}
>
{item.map(emoji => {
const uri = reduceMotionEnabled ? emoji.static_url : emoji.url
if (validUrl.isHttpsUri(uri)) {
return (
<Pressable
key={emoji.shortcode}
onPress={() => {
haptics('Light')
updateText({
composeState,
composeDispatch,
newText: `:${emoji.shortcode}:`,
type: 'emoji'
})
dispatch(countInstanceEmoji(emoji))
}}
>
{staticEmoji ? (
<Image
accessibilityLabel={t(
'common:customEmoji.accessibilityLabel',
{
emoji: emoji.shortcode
}
)}
accessibilityHint={t(
'screenCompose:content.root.footer.emojis.accessibilityHint'
)}
source={{ uri }}
style={{
width: 36,
height: 36,
padding: StyleConstants.Spacing.S,
margin: StyleConstants.Spacing.S
}}
/>
) : (
<FastImage
accessibilityLabel={t(
'common:customEmoji.accessibilityLabel',
{
emoji: emoji.shortcode
}
)}
accessibilityHint={t(
'screenCompose:content.root.footer.emojis.accessibilityHint'
)}
source={{ uri }}
style={{
width: 36,
height: 36,
padding: StyleConstants.Spacing.S,
margin: StyleConstants.Spacing.S
}}
/>
)}
</Pressable>
)
} else {
return null
}
})}
</View>
)
},
[composeState]
)
return (
<View
style={{
flex: 1,
flexDirection: 'row',
flexWrap: 'wrap',
justifyContent: 'space-around',
height: 280
}}
>
<SectionList
accessible
ref={accessibleRefEmojis}
horizontal
keyboardShouldPersistTaps='always'
sections={composeState.emoji.emojis || []}
keyExtractor={item => item[0].shortcode}
renderSectionHeader={({ section: { title } }) => (
<CustomText
fontStyle='S'
style={{
position: 'absolute',
left: StyleConstants.Spacing.L,
color: colors.secondary
}}
>
{title}
</CustomText>
)}
renderItem={listItem}
windowSize={2}
/>
</View>
)
}
export default React.memo(ComposeEmojis, () => true)