mirror of
https://github.com/tooot-app/app
synced 2025-01-03 13:10:23 +01:00
Emoji working for compose
This commit is contained in:
parent
b44370d3ec
commit
fb3cfa0db1
@ -7,7 +7,7 @@ import { getInstanceFrequentEmojis } from '@utils/slices/instancesSlice'
|
||||
import { chunk, forEach, groupBy, sortBy } from 'lodash'
|
||||
import React, { PropsWithChildren, RefObject, useEffect, useReducer, useState } from 'react'
|
||||
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 { Edge, SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context'
|
||||
import { useSelector } from 'react-redux'
|
||||
@ -74,14 +74,14 @@ const ComponentEmojis: React.FC<Props & PropsWithChildren> = ({
|
||||
if (data && data.length) {
|
||||
let sortedEmojis: EmojisState['emojis'] = []
|
||||
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) {
|
||||
sortedEmojis.unshift({
|
||||
title: t('componentEmojis:frequentUsed'),
|
||||
data: chunk(
|
||||
frequentEmojis.map(e => e.emoji),
|
||||
5
|
||||
4
|
||||
),
|
||||
type: 'frequent'
|
||||
})
|
||||
@ -125,7 +125,9 @@ const ComponentEmojis: React.FC<Props & PropsWithChildren> = ({
|
||||
<View
|
||||
style={[
|
||||
keyboardShown ? { position: 'absolute', bottom: 0, width: '100%' } : null,
|
||||
{ marginBottom: keyboardShown ? insets.bottom : 0 }
|
||||
{
|
||||
marginBottom: keyboardShown && emojisState.targetIndex === -1 ? insets.bottom : 0
|
||||
}
|
||||
]}
|
||||
children={
|
||||
emojisState.targetIndex !== -1 ? (
|
||||
|
@ -42,7 +42,7 @@ const EmojisList = () => {
|
||||
} = emojisState.inputProps[emojisState.targetIndex]
|
||||
|
||||
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 spaceRear = /\s/g.test(contentRear[0]) ? '' : ' '
|
||||
|
@ -157,32 +157,19 @@ const ComposeActions: React.FC = () => {
|
||||
return colors.secondary
|
||||
}
|
||||
}, [emojisState.emojis.length, emojisState.targetIndex])
|
||||
// useEffect(() => {
|
||||
// const showSubscription = Keyboard.addListener('keyboardWillShow', () => {
|
||||
// composeDispatch({ type: 'emoji/shown', payload: false })
|
||||
// })
|
||||
|
||||
// return () => {
|
||||
// showSubscription.remove()
|
||||
// }
|
||||
// }, [])
|
||||
const emojiOnPress = () => {
|
||||
analytics('compose_actions_emojis_press', {
|
||||
current: emojisState.targetIndex !== -1
|
||||
})
|
||||
if (emojisState.targetIndex === -1) {
|
||||
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 (
|
||||
|
@ -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)
|
Loading…
Reference in New Issue
Block a user