diff --git a/src/components/Emojis.tsx b/src/components/Emojis.tsx index 8db4570d..755d2b84 100644 --- a/src/components/Emojis.tsx +++ b/src/components/Emojis.tsx @@ -1,20 +1,12 @@ import EmojisButton from '@components/Emojis/Button' import EmojisList from '@components/Emojis/List' -import { PasteInputRef } from '@mattermost/react-native-paste-input' import { useAccessibility } from '@utils/accessibility/AccessibilityManager' import { useEmojisQuery } from '@utils/queryHooks/emojis' import { getInstanceFrequentEmojis } from '@utils/slices/instancesSlice' import { chunk, forEach, groupBy, sortBy } from 'lodash' -import React, { - createRef, - PropsWithChildren, - RefObject, - useEffect, - useReducer, - useState -} from 'react' +import React, { createRef, PropsWithChildren, useEffect, useReducer, useState } from 'react' import { useTranslation } from 'react-i18next' -import { Keyboard, KeyboardAvoidingView, TextInput, View } from 'react-native' +import { Keyboard, KeyboardAvoidingView, 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' @@ -49,7 +41,6 @@ const prefetchEmojis = ( export type Props = { inputProps: EmojisState['inputProps'] - focusRef?: RefObject customButton?: boolean customEdges?: Edge[] customBehavior?: 'height' | 'padding' | 'position' @@ -60,7 +51,6 @@ export const emojis: Emojis = createRef() const ComponentEmojis: React.FC = ({ children, inputProps, - focusRef, customButton = false, customEdges = ['bottom'], customBehavior @@ -79,14 +69,14 @@ const ComponentEmojis: React.FC = ({ if (data && data.length) { let sortedEmojis: NonNullable = [] forEach(groupBy(sortBy(data, ['category', 'shortcode']), 'category'), (value, key) => - sortedEmojis.push({ title: key, data: chunk(value, 4) }) + sortedEmojis.push({ title: key, data: chunk(value, 5) }) ) if (frequentEmojis.length) { sortedEmojis.unshift({ title: t('componentEmojis:frequentUsed'), data: chunk( frequentEmojis.map(e => e.emoji), - 4 + 5 ), type: 'frequent' }) @@ -115,11 +105,6 @@ const ComponentEmojis: React.FC = ({ hideSubscription.remove() } }, [inputProps]) - useEffect(() => { - if (focusRef) { - setTimeout(() => focusRef.current?.focus(), 500) - } - }, []) return ( @@ -129,7 +114,7 @@ const ComponentEmojis: React.FC = ({ {children} { const { reduceMotionEnabled } = useAccessibility() const { t } = useTranslation() - const { emojisState } = useContext(EmojisContext) + const { emojisState, emojisDispatch } = useContext(EmojisContext) const { colors, mode } = useTheme() const addEmoji = (shortcode: string) => { @@ -165,6 +165,17 @@ const EmojisList = () => { autoCorrect={false} spellCheck={false} /> + { + if (emojisState.targetIndex !== -1) { + emojisState.inputProps[emojisState.targetIndex].ref?.current?.focus() + } + emojisDispatch({ type: 'target', payload: -1 }) + }} + > + + void] selection: [{ start: number; end?: number }, (selection: { start: number; end?: number }) => void] isFocused: MutableRefObject - ref?: RefObject // For controlling focus + ref: RefObject // For controlling focus maxLength?: number - addFunc?: (add: string) => void // For none default state update } export type Emojis = MutableRefObject< diff --git a/src/screens/Compose.tsx b/src/screens/Compose.tsx index 241460ee..bf4d802b 100644 --- a/src/screens/Compose.tsx +++ b/src/screens/Compose.tsx @@ -365,7 +365,8 @@ const ScreenCompose: React.FC> = ({ selection => composeDispatch({ type: 'text', payload: { selection } }) ], isFocused: composeState.textInputFocus.isFocused.text, - maxLength: maxTootChars - (composeState.spoiler.active ? composeState.spoiler.count : 0) + maxLength: maxTootChars - (composeState.spoiler.active ? composeState.spoiler.count : 0), + ref: composeState.textInputFocus.refs.text }, { value: [ @@ -377,7 +378,8 @@ const ScreenCompose: React.FC> = ({ selection => composeDispatch({ type: 'spoiler', payload: { selection } }) ], isFocused: composeState.textInputFocus.isFocused.spoiler, - maxLength: maxTootChars - composeState.text.count + maxLength: maxTootChars - composeState.text.count, + ref: composeState.textInputFocus.refs.spoiler } ] diff --git a/src/screens/Compose/EditAttachment.tsx b/src/screens/Compose/EditAttachment.tsx index 56a66523..fd9b6967 100644 --- a/src/screens/Compose/EditAttachment.tsx +++ b/src/screens/Compose/EditAttachment.tsx @@ -1,7 +1,7 @@ import { HeaderLeft } from '@components/Header' import { createNativeStackNavigator } from '@react-navigation/native-stack' import { ScreenComposeStackScreenProps } from '@utils/navigation/navigators' -import React, { useCallback } from 'react' +import React from 'react' import { useTranslation } from 'react-i18next' import { KeyboardAvoidingView, Platform } from 'react-native' import { SafeAreaView } from 'react-native-safe-area-context' diff --git a/src/screens/Compose/Root.tsx b/src/screens/Compose/Root.tsx index 8d427385..c8ba0af3 100644 --- a/src/screens/Compose/Root.tsx +++ b/src/screens/Compose/Root.tsx @@ -1,9 +1,7 @@ import ComponentSeparator from '@components/Separator' -import { useEmojisQuery } from '@utils/queryHooks/emojis' import { useSearchQuery } from '@utils/queryHooks/search' import { StyleConstants } from '@utils/styles/constants' import { useTheme } from '@utils/styles/ThemeManager' -import { chunk, forEach, groupBy, sortBy } from 'lodash' import React, { useContext, useEffect, useMemo, useRef } from 'react' import { AccessibilityInfo, findNodeHandle, FlatList, View } from 'react-native' import { Circle } from 'react-native-animated-spinkit' @@ -14,19 +12,13 @@ import ComposeRootHeader from './Root/Header' import ComposeRootSuggestion from './Root/Suggestion' import ComposeContext from './utils/createContext' import ComposeDrafts from './Root/Drafts' -import { useAccessibility } from '@utils/accessibility/AccessibilityManager' import { useSelector } from 'react-redux' -import { - getInstanceConfigurationStatusCharsURL, - getInstanceFrequentEmojis -} from '@utils/slices/instancesSlice' -import { useTranslation } from 'react-i18next' +import { getInstanceConfigurationStatusCharsURL } from '@utils/slices/instancesSlice' export let instanceConfigurationStatusCharsURL = 23 const ComposeRoot = React.memo( () => { - const { reduceMotionEnabled } = useAccessibility() const { colors } = useTheme() instanceConfigurationStatusCharsURL = useSelector( @@ -42,7 +34,7 @@ const ComposeRoot = React.memo( tagDrafts && AccessibilityInfo.setAccessibilityFocus(tagDrafts) }, [accessibleRefDrafts.current]) - const { composeState, composeDispatch } = useContext(ComposeContext) + const { composeState } = useContext(ComposeContext) const mapSchemaToType = () => { if (composeState.tag) { @@ -71,30 +63,6 @@ const ComposeRoot = React.memo( } }, [composeState.tag]) - const { t } = useTranslation() - const { data: emojisData } = useEmojisQuery({}) - const frequentEmojis = useSelector(getInstanceFrequentEmojis, () => true) - useEffect(() => { - if (emojisData && emojisData.length) { - const sortedEmojis: { - title: string - data: Pick[][] - }[] = [] - forEach(groupBy(sortBy(emojisData, ['category', 'shortcode']), 'category'), (value, key) => - sortedEmojis.push({ title: key, data: chunk(value, 5) }) - ) - if (frequentEmojis.length) { - sortedEmojis.unshift({ - title: t('componentEmojis:frequentUsed'), - data: chunk( - frequentEmojis.map(e => e.emoji), - 5 - ) - }) - } - } - }, [emojisData, reduceMotionEnabled]) - const listEmpty = useMemo(() => { if (isFetching) { return ( diff --git a/src/screens/Compose/Root/Header/SpoilerInput.tsx b/src/screens/Compose/Root/Header/SpoilerInput.tsx index b1483bbf..b16ae90e 100644 --- a/src/screens/Compose/Root/Header/SpoilerInput.tsx +++ b/src/screens/Compose/Root/Header/SpoilerInput.tsx @@ -21,6 +21,7 @@ const ComposeSpoilerInput: React.FC = () => { return ( = { replyToStatus: undefined, textInputFocus: { current: 'text', - refs: { text: createRef() }, + refs: { text: createRef(), spoiler: createRef() }, isFocused: { text: createRef(), spoiler: createRef() } } } diff --git a/src/screens/Compose/utils/types.d.ts b/src/screens/Compose/utils/types.d.ts index a3290747..3500bee6 100644 --- a/src/screens/Compose/utils/types.d.ts +++ b/src/screens/Compose/utils/types.d.ts @@ -1,3 +1,4 @@ +import { RefObject } from 'react'; import { Asset } from 'react-native-image-picker' export type ExtendedAttachment = { @@ -39,10 +40,6 @@ export type ComposeState = { index: number lastIndex: number raw: string - // type: 'url' | 'accounts' | 'hashtags' - // text: string - // offset: number - // length: number } poll: { active: boolean @@ -62,7 +59,7 @@ export type ComposeState = { replyToStatus?: Mastodon.Status textInputFocus: { current: 'text' | 'spoiler' - refs: { text: RefObject } + refs: { text: RefObject, spoiler: RefObject } isFocused: { text: MutableRefObject, spoiler: MutableRefObject } } } diff --git a/src/screens/Tabs/Me/Profile/Fields.tsx b/src/screens/Tabs/Me/Profile/Fields.tsx index ed115bc5..a39b62d6 100644 --- a/src/screens/Tabs/Me/Profile/Fields.tsx +++ b/src/screens/Tabs/Me/Profile/Fields.tsx @@ -9,7 +9,7 @@ import { StyleConstants } from '@utils/styles/constants' import { useTheme } from '@utils/styles/ThemeManager' import React, { Dispatch, RefObject, SetStateAction, useEffect, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' -import { Alert, ScrollView } from 'react-native' +import { Alert, ScrollView, TextInput } from 'react-native' import FlashMessage from 'react-native-flash-message' const Field: React.FC<{ @@ -21,19 +21,23 @@ const Field: React.FC<{ const { colors } = useTheme() const { t } = useTranslation('screenTabs') + const nameRef = useRef(null) + const valueRef = useRef(null) const [name, setName] = useState(field?.name || '') const [value, setValue] = useState(field?.value || '') allProps[index * 2] = { value: [name, setName], selection: useState({ start: name.length }), isFocused: useRef(false), - maxLength: 255 + maxLength: 255, + ref: nameRef } allProps[index * 2 + 1] = { value: [value, setValue], selection: useState({ start: value.length }), isFocused: useRef(false), - maxLength: 255 + maxLength: 255, + ref: valueRef } useEffect(() => { diff --git a/src/screens/Tabs/Me/Profile/Name.tsx b/src/screens/Tabs/Me/Profile/Name.tsx index 3e5ac432..0760ef7a 100644 --- a/src/screens/Tabs/Me/Profile/Name.tsx +++ b/src/screens/Tabs/Me/Profile/Name.tsx @@ -93,7 +93,7 @@ const TabMeProfileName: React.FC< }, [theme, i18n.language, dirty, status, value]) return ( - + +