-
Notifications
You must be signed in to change notification settings - Fork 65
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: support maxLength prop in web #505
feat: support maxLength prop in web #505
Conversation
Screen.Recording.2024-09-26.at.12.16.40.mov |
Screen.Recording.2024-09-26.at.12.27.45.mov |
@Skalakid in the latest commit, I have made the
To test the behavior, please modify the For |
in pasteText event
Small change on the latest commit: I tested the paste text in native, and it seems like the app will cut off the inserted text until it fits the maxLength, or do not paste anything at all (keep the old text), so I updated the web implementation to reflect that. |
Okay, thank you. Now everything works fine :D There is one more thing that I wanted to fix there. How about adding value cutting on the first rerender? Currently, when you pass the long text in the (In the image, I have I know the same thing happens on the default RN TextInput, but I think it's worth fixing in our case. What do you think about it? |
Bug: Text isn't being replaced when you reach the limit of Screen.Recording.2024-09-27.at.13.37.50.movExpected behavior: Screen.Recording.2024-09-27.at.13.45.04.mov |
…suffix paste event - web platform
@Skalakid fixed! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall, it looks good :D Left some small comments
src/MarkdownTextInput.web.tsx
Outdated
inputType === 'pasteText' ? pasteContent.current || '' : parseInnerHTMLToText(e.target as MarkdownTextInputElement, inputType, contentSelection.current.start), | ||
); | ||
|
||
if (pasteContent.current) { | ||
pasteContent.current = null; | ||
} | ||
|
||
if (typeof maxLength === 'number' && parsedText.length > maxLength) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (typeof maxLength === 'number' && parsedText.length > maxLength) { | |
if (maxLength !== undefined && parsedText.length > maxLength) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
src/MarkdownTextInput.web.tsx
Outdated
let availableLength = text.length; | ||
const prefix = divRef.current.value.substring(0, contentSelection.current.start); | ||
const suffix = divRef.current.value.substring(contentSelection.current.end); | ||
if (typeof maxLength === 'number') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
src/MarkdownTextInput.tsx
Outdated
const IS_FABRIC = 'nativeFabricUIManager' in global; | ||
|
||
const markdownStyle = React.useMemo(() => processMarkdownStyle(props.markdownStyle), [props.markdownStyle]); | ||
|
||
const processedText = React.useMemo(() => { | ||
if (typeof maxLength === 'number') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (typeof maxLength === 'number') { | |
if (maxLength !== undefined) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
src/MarkdownTextInput.tsx
Outdated
}, [value, maxLength]); | ||
|
||
React.useLayoutEffect(() => { | ||
if (typeof maxLength !== 'number' || !value || value.length <= maxLength || !onChangeText) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (typeof maxLength !== 'number' || !value || value.length <= maxLength || !onChangeText) { | |
if (maxLength === undefined || !value || value.length <= maxLength || !onChangeText) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
src/MarkdownTextInput.tsx
Outdated
value={processedText} | ||
onChangeText={onChangeText} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if the component was supposed to be uncontrolled? I don't really like this logic here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you suggest otherwise? For me it looks completely fine. The intention is to cut off the initial value
props if it is provided, and if possible, use onChangeText
to update the state in the parent component.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the component was supposed to be uncontrolled then the value
props should be undefined
, hence we don't have to worry about this case.
@tomekzaw do you have any further concerns? Could we merge this PR? |
@dominictb Why can't we just pass |
@tomekzaw it's coming from here: #505 (comment). Basically for Now we have 2 options:
@Skalakid favors the second option, so I need to update the native implementation accordingly |
@dominictb Thanks for the response
Isn't it something we should fix directly in react-native? Or, alternatively, fix this inside E/App for Android and iOS? I'd like |
Actually, a regular |
Alright, I can revert the change. One moment. |
Okay, @tomekzaw convinced me, let's revert changes on the native side and focus on implementing the |
Basically, For Android and iOS, let's just pass this prop to For web, we'll need to implement All other logic should be moved to E/App. |
done! |
@dominictb Thanks! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Resolved conflicts! |
Waiting for your final say @Skalakid. |
Details
This PR includes the implementation of
maxLength
prop in webRelated Issues
Expensify/App#46766
Manual Tests
Paste this text file (over 400k characters)
default.txt
Check that the text input in both web and native is cut off to 30k length
Linked PRs
Pending App PR