The tiptap useEditor() hook creates an awkward challenge for passing event handlers into its plugins and native events. By introducing a memoized editor, we should be able to shuttle events out of tiptap without retriggering the useEditor hook. The emitter can then change its registered handlers with each state update.zio/stable
parent
5e63d3164b
commit
4a59178cd2
|
@ -70,6 +70,7 @@
|
|||
"base64-js": "^1.5.1",
|
||||
"bcp-47-match": "^2.0.3",
|
||||
"email-validator": "^2.0.4",
|
||||
"eventemitter3": "^5.0.1",
|
||||
"expo": "~48.0.18",
|
||||
"expo-application": "~5.1.1",
|
||||
"expo-build-properties": "~0.5.1",
|
||||
|
|
|
@ -151,7 +151,7 @@ export const ComposePost = observer(function ComposePost({
|
|||
[gallery, track],
|
||||
)
|
||||
|
||||
const onPressPublish = async (rt: RichText) => {
|
||||
const onPressPublish = async () => {
|
||||
if (isProcessing || graphemeLength > MAX_GRAPHEME_LENGTH) {
|
||||
return
|
||||
}
|
||||
|
@ -161,7 +161,7 @@ export const ComposePost = observer(function ComposePost({
|
|||
|
||||
setError('')
|
||||
|
||||
if (rt.text.trim().length === 0 && gallery.isEmpty) {
|
||||
if (richtext.text.trim().length === 0 && gallery.isEmpty) {
|
||||
setError('Did you want to say anything?')
|
||||
return
|
||||
}
|
||||
|
@ -170,7 +170,7 @@ export const ComposePost = observer(function ComposePost({
|
|||
|
||||
try {
|
||||
await apilib.post(store, {
|
||||
rawText: rt.text,
|
||||
rawText: richtext.text,
|
||||
replyTo: replyTo?.uri,
|
||||
images: gallery.images,
|
||||
quote,
|
||||
|
@ -245,9 +245,7 @@ export const ComposePost = observer(function ComposePost({
|
|||
) : canPost ? (
|
||||
<TouchableOpacity
|
||||
testID="composerPublishBtn"
|
||||
onPress={() => {
|
||||
onPressPublish(richtext)
|
||||
}}
|
||||
onPress={onPressPublish}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel={replyTo ? 'Publish reply' : 'Publish post'}
|
||||
accessibilityHint={
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import React from 'react'
|
||||
import {StyleSheet, View} from 'react-native'
|
||||
import {RichText} from '@atproto/api'
|
||||
import EventEmitter from 'eventemitter3'
|
||||
import {useEditor, EditorContent, JSONContent} from '@tiptap/react'
|
||||
import {Document} from '@tiptap/extension-document'
|
||||
import History from '@tiptap/extension-history'
|
||||
|
@ -53,6 +54,22 @@ export const TextInput = React.forwardRef(
|
|||
'ProseMirror-dark',
|
||||
)
|
||||
|
||||
// we use a memoized emitter to propagate events out of tiptap
|
||||
// without triggering re-runs of the useEditor hook
|
||||
const emitter = React.useMemo(() => new EventEmitter(), [])
|
||||
React.useEffect(() => {
|
||||
emitter.addListener('publish', onPressPublish)
|
||||
return () => {
|
||||
emitter.removeListener('publish', onPressPublish)
|
||||
}
|
||||
}, [emitter, onPressPublish])
|
||||
React.useEffect(() => {
|
||||
emitter.addListener('photo-pasted', onPhotoPasted)
|
||||
return () => {
|
||||
emitter.removeListener('photo-pasted', onPhotoPasted)
|
||||
}
|
||||
}, [emitter, onPhotoPasted])
|
||||
|
||||
const editor = useEditor(
|
||||
{
|
||||
extensions: [
|
||||
|
@ -87,17 +104,13 @@ export const TextInput = React.forwardRef(
|
|||
return
|
||||
}
|
||||
|
||||
getImageFromUri(items, onPhotoPasted)
|
||||
getImageFromUri(items, (uri: string) => {
|
||||
emitter.emit('photo-pasted', uri)
|
||||
})
|
||||
},
|
||||
handleKeyDown: (_, event) => {
|
||||
if ((event.metaKey || event.ctrlKey) && event.code === 'Enter') {
|
||||
// Workaround relying on previous state from `setRichText` to
|
||||
// get the updated text content during editor initialization
|
||||
setRichText((state: RichText) => {
|
||||
onPressPublish(state)
|
||||
return state
|
||||
})
|
||||
return true
|
||||
emitter.emit('publish')
|
||||
}
|
||||
},
|
||||
},
|
||||
|
@ -118,7 +131,7 @@ export const TextInput = React.forwardRef(
|
|||
}
|
||||
},
|
||||
},
|
||||
[modeClass],
|
||||
[modeClass, emitter],
|
||||
)
|
||||
|
||||
React.useImperativeHandle(ref, () => ({
|
||||
|
|
|
@ -10150,6 +10150,11 @@ eventemitter3@^4.0.0, eventemitter3@^4.0.4:
|
|||
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f"
|
||||
integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==
|
||||
|
||||
eventemitter3@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.1.tgz#53f5ffd0a492ac800721bb42c66b841de96423c4"
|
||||
integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==
|
||||
|
||||
events@3.3.0, events@^3.2.0, events@^3.3.0:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400"
|
||||
|
|
Loading…
Reference in New Issue