An ATproto social media client -- with an independent Appview.

Fix Android composer cursor bug by removing `setTimeout` from native composer `onChangeText` (#4922)

authored by hailey.at and committed by

GitHub db7a7444 75c19b2d

+44 -56
+44 -56
src/view/com/composer/text-input/TextInput.tsx
··· 85 85 const pastSuggestedUris = useRef(new Set<string>()) 86 86 const prevDetectedUris = useRef(new Map<string, LinkFacetMatch>()) 87 87 const onChangeText = useCallback( 88 - (newText: string) => { 89 - /* 90 - * This is a hack to bump the rendering of our styled 91 - * `textDecorated` to _after_ whatever processing is happening 92 - * within the `PasteInput` library. Without this, the elements in 93 - * `textDecorated` are not correctly painted to screen. 94 - * 95 - * NB: we tried a `0` timeout as well, but only positive values worked. 96 - * 97 - * @see https://github.com/bluesky-social/social-app/issues/929 98 - */ 99 - setTimeout(async () => { 100 - const mayBePaste = newText.length > prevLength.current + 1 88 + async (newText: string) => { 89 + const mayBePaste = newText.length > prevLength.current + 1 101 90 102 - const newRt = new RichText({text: newText}) 103 - newRt.detectFacetsWithoutResolution() 104 - setRichText(newRt) 91 + const newRt = new RichText({text: newText}) 92 + newRt.detectFacetsWithoutResolution() 93 + setRichText(newRt) 105 94 106 - const prefix = getMentionAt( 107 - newText, 108 - textInputSelection.current?.start || 0, 109 - ) 110 - if (prefix) { 111 - setAutocompletePrefix(prefix.value) 112 - } else if (autocompletePrefix) { 113 - setAutocompletePrefix('') 114 - } 95 + const prefix = getMentionAt( 96 + newText, 97 + textInputSelection.current?.start || 0, 98 + ) 99 + if (prefix) { 100 + setAutocompletePrefix(prefix.value) 101 + } else if (autocompletePrefix) { 102 + setAutocompletePrefix('') 103 + } 115 104 116 - const nextDetectedUris = new Map<string, LinkFacetMatch>() 117 - if (newRt.facets) { 118 - for (const facet of newRt.facets) { 119 - for (const feature of facet.features) { 120 - if (AppBskyRichtextFacet.isLink(feature)) { 121 - if (isUriImage(feature.uri)) { 122 - const res = await downloadAndResize({ 123 - uri: feature.uri, 124 - width: POST_IMG_MAX.width, 125 - height: POST_IMG_MAX.height, 126 - mode: 'contain', 127 - maxSize: POST_IMG_MAX.size, 128 - timeout: 15e3, 129 - }) 105 + const nextDetectedUris = new Map<string, LinkFacetMatch>() 106 + if (newRt.facets) { 107 + for (const facet of newRt.facets) { 108 + for (const feature of facet.features) { 109 + if (AppBskyRichtextFacet.isLink(feature)) { 110 + if (isUriImage(feature.uri)) { 111 + const res = await downloadAndResize({ 112 + uri: feature.uri, 113 + width: POST_IMG_MAX.width, 114 + height: POST_IMG_MAX.height, 115 + mode: 'contain', 116 + maxSize: POST_IMG_MAX.size, 117 + timeout: 15e3, 118 + }) 130 119 131 - if (res !== undefined) { 132 - onPhotoPasted(res.path) 133 - } 134 - } else { 135 - nextDetectedUris.set(feature.uri, {facet, rt: newRt}) 120 + if (res !== undefined) { 121 + onPhotoPasted(res.path) 136 122 } 123 + } else { 124 + nextDetectedUris.set(feature.uri, {facet, rt: newRt}) 137 125 } 138 126 } 139 127 } 140 128 } 141 - const suggestedUri = suggestLinkCardUri( 142 - mayBePaste, 143 - nextDetectedUris, 144 - prevDetectedUris.current, 145 - pastSuggestedUris.current, 146 - ) 147 - prevDetectedUris.current = nextDetectedUris 148 - if (suggestedUri) { 149 - onNewLink(suggestedUri) 150 - } 151 - prevLength.current = newText.length 152 - }, 1) 129 + } 130 + const suggestedUri = suggestLinkCardUri( 131 + mayBePaste, 132 + nextDetectedUris, 133 + prevDetectedUris.current, 134 + pastSuggestedUris.current, 135 + ) 136 + prevDetectedUris.current = nextDetectedUris 137 + if (suggestedUri) { 138 + onNewLink(suggestedUri) 139 + } 140 + prevLength.current = newText.length 153 141 }, 154 142 [setRichText, autocompletePrefix, onPhotoPasted, onNewLink], 155 143 )