Page MenuHomePhabricator

[Web] Added current cursor position to StateInput
ClosedPublic

Authored by przemek on Nov 10 2022, 7:24 AM.
Tags
None
Referenced Files
Unknown Object (File)
Tue, Apr 23, 8:57 PM
Unknown Object (File)
Tue, Apr 23, 8:57 PM
Unknown Object (File)
Tue, Apr 23, 8:57 PM
Unknown Object (File)
Tue, Apr 23, 8:57 PM
Unknown Object (File)
Tue, Apr 23, 8:57 PM
Unknown Object (File)
Tue, Apr 23, 8:57 PM
Unknown Object (File)
Tue, Apr 23, 8:52 PM
Unknown Object (File)
Sun, Apr 7, 3:36 AM

Details

Summary

Added current cursor position in textarea input of chatInputBar to StateInput. It will be used in typeahead as we will need to track cursor position. Putting it in context provides us with extra benefit of saving cursor position when jumping between different chats and channels.
Code from this diff doesn't call anything them yet.

Test Plan

Runned web. Everything works fine.
New property and function are visible in chat-input-bar.reat.js via this.props.stateInput.

Diff Detail

Repository
rCOMM Comm
Lint
Lint Not Applicable
Unit
Tests Not Applicable

Event Timeline

tomek requested changes to this revision.Nov 14 2022, 4:43 AM
tomek added inline comments.
web/input/input-state-container.react.js
158–176 ↗(On Diff #18317)

Are you sure this code works correctly? Why do we assign pendingUploads to textCursorPositions and later textCursorPositions to stateUpdate.pendingUploads? Looks like a bug.

488 ↗(On Diff #18317)

?? syntax could be used

1085–1090 ↗(On Diff #18317)

Shouldn't we clear the old state when a thread becomes realized (newThreadID !== threadID)

This revision now requires changes to proceed.Nov 14 2022, 4:43 AM
przemek marked 3 inline comments as done.

Responded to inlines.

web/input/input-state-container.react.js
488 ↗(On Diff #18317)

Right, also changed the line above.

1085–1090 ↗(On Diff #18317)

It's already done in reassignToRealizedThreads function on props update.

tomek requested changes to this revision.Nov 16 2022, 1:12 AM

We're storing cursor position for each thread. How does this work when switching between the threads? Do we really need to have it per thread, or is it enough to have a single value?

web/input/input-state-container.react.js
163–165 ↗(On Diff #18436)

If the only updated property is textCursorPositions then we're going to early exit from this method. We have to make sure that the test plan covers checking getDerivedStateFromProps method.

This revision now requires changes to proceed.Nov 16 2022, 1:12 AM

I'd say, if we save drafts, we should also save cursorPosition. It may be frustrating for user to edit two drafts at the same time, and have they cursor revert to the start of textarea every time. I'm not really sure how to estimate cost of keeping it, but if it isn't too high I'd keep it as nice to have feature.

On entering new thread we position cursor as it was left, so if user was editing some text, then jumped to another thread, replied to some messages there and went back to the original thread where he was editing some long message, their cursor will stay in the same place.

Fixed conditional, so it saves cursor position in pending threads.

I'd say, if we save drafts, we should also save cursorPosition. It may be frustrating for user to edit two drafts at the same time, and have they cursor revert to the start of textarea every time. I'm not really sure how to estimate cost of keeping it, but if it isn't too high I'd keep it as nice to have feature.

On entering new thread we position cursor as it was left, so if user was editing some text, then jumped to another thread, replied to some messages there and went back to the original thread where he was editing some long message, their cursor will stay in the same place.

Ok, that makes sense

This revision is now accepted and ready to land.Nov 16 2022, 9:39 AM

@atul should take a look since this touches InputStateContainer

Putting it in context provides us with extra benefit of saving cursor position when jumping between different chats and channels.

Makes sense to me

web/input/input-state.js
38 ↗(On Diff #18477)

All of this should probably be $ReadOnly (eg. prefix each property with +) but not sure if that will introduce Flow errors

This revision now requires review to proceed.Nov 16 2022, 7:45 PM
przemek marked an inline comment as done.

Changed context properties to read-only.

web/input/input-state.js
38 ↗(On Diff #18477)

Makes sense, I changed it and it haven't invoked any flow errors, so I'm amending it.

This looks reasonable to me.

(Did we take a look at any prior work for this? This seems like the sort of problem that others have probably run into before and there might be established or simpler solutions we could work off of?)

web/input/input-state-container.react.js
488 ↗(On Diff #18510)

Should we be defaulting to 0 here? What if the cursor isn't in the text? Shouldn't we instead set things to -1 or null so we can handle that case separately?

Feel free to correct me if I'm wrong/missing context

This revision is now accepted and ready to land.Nov 17 2022, 9:35 AM
przemek marked an inline comment as done.EditedNov 18 2022, 1:48 AM

(Did we take a look at any prior work for this? This seems like the sort of problem that others have probably run into before and there might be established or simpler solutions we could work off of?)

@atul I'm not sure what "this" refers to in your sentence (so ironic in JS review thread :D) Can you clarify what problem you're referring to? If you meant saving cursor position it was only reasonable solution I could think of. If we save draft texts in this manner, I thought it is okay to keep cursor positions in those drafts as well. And I need that that to save cursor position between renders of ChatInputBar.

web/input/input-state-container.react.js
488 ↗(On Diff #18510)

In future diffs, I'll set cursor in textarea to value from this context, so if it wasn't set yet, 0 is good default value meaning start of the text. Cursor position is only ever relevant when we're editing text. If textarea isn't focused it doesn't really matter

This revision was automatically updated to reflect the committed changes.
przemek marked an inline comment as done.

Do we still need to save cursor positions in a hypothetical solution where we use contenteditable = true?

I think saving caret position is not strictly necessary now. I preferred to use it, as we treat textarea as controlled component, so we want to control it via state we can update use.
Without saving cursor position:

  1. We would need to rely on selection start and end from textarea element. With editable div, we would rely on global Selection object.
  2. We wouldn't get that nice-to-have saving cursor position when jumping between threads

We wouldn't get that nice-to-have saving cursor position when jumping between threads

This part still applies for contenteditable = true?

Yes, ff we swap textarea to contentEditable and keep saving caret position in context we keep the feature of saving its position when changing threads. It would require some changes, but nothing to serious.