Skip to content

Add chat drafts to conversation state.#111

Open
loganmhb wants to merge 3 commits intojkk:masterfrom
loganmhb:drafts
Open

Add chat drafts to conversation state.#111
loganmhb wants to merge 3 commits intojkk:masterfrom
loganmhb:drafts

Conversation

@loganmhb
Copy link

@loganmhb loganmhb commented May 6, 2017

First of all, thanks for a great-looking app! I'm really looking forward to seeing this grow. I did some work on #92 because it seemed like a nice-sized task to start learning my way around the codebase.

This pull request allows drafts to be stored per conversation instead of keeping the same draft for all conversations, resolving #92. However, it doesn't (yet?) handle drafts in game chats (it ignores them), because those conversations are not stored in the same way as far as I can tell. I'd be happy to work on improving that as well, but I figured I'd go ahead and put this up for feedback first.

Disclaimer: I'm a backend developer by day and I don't have much experience with React/Flow, so if there are rookie mistakes, obvious problems, or you want to take a different approach that feedback is more than welcome. I also haven't figured out how to test against an API server that's not KGS itself, so I haven't tested submission of chat messages.

This allows drafts to be stored per conversation instead of keeping
the same draft for all conversations. However, it doesn't handle
drafts in game chats the same way, because those conversations are
not stored in the same way.
@jkk
Copy link
Owner

jkk commented May 6, 2017

Hi Logan. Thanks for the PR! This is a good start. There are a few things to mention.

First and biggest: the approach you took is to save the draft text into a conversation record after every change to the text input. While this is the simplest, most straight-forward approach, in practice doing it this way can bog down performance. Currently Shin uses a single store for the entire app, and when its state changes, the entire app re-renders from top to bottom. So after each keypress, the entire screen re-renders, not just the message bar.

To fix this, you can use component-local state to store the latest value of the input, and do a rate-limited update to the global conversation state (maybe 'SAVE_CHAT_DRAFT' as a message type). If you wanted to get fancy, you could even create a reusable text input with that feature built-in (value changes as you type, and then runs a debounced callback every X milliseconds).

Sidebar: in the future, we may have components subscribe to only the subset of state they need from the store, so app state changes don't trigger unnecessary render checks everywhere (we do use PureComponent which does not re-render unless props actually change). For most cases (other than inputs), a single top-down data flow is simpler.

Other issues:

  1. Check the browser console for errors and warnings. There are a few.

  2. Remove console.log calls

  3. Bug: if you're in a room and enter text into the message bar, then switch to another room (which you haven't been in yet), the message bar text persists. It does work if you have different text typed into each room's message bar.

  4. There are a few code conventions I'd like to see followed. I'll make inline comments about those

type Props = {
conversation: ?Conversation,
onSubmit: string => any;
onDraft: string => any;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that this is not used for games, I'd make it optional: onDraft?: string => any

}
}

_onChange(event: SyntheticEvent) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The convention we're using in Shin is to use class property arrow functions for event handlers:

_onChange = (event: SyntheticEvent) => {

This convention sets this appropriately, removing the need for bind later on.

type='text'
placeholder={placeholder}
value={draft === '' ? null : draft}
onChange={this._onChange.bind(this)}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see prior comment about arrow functions for event handlers

}}
onSubmit={this._onChat} />
onSubmit={this._onChat}
onDraft={()=>{}}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see previous comment about making onDraft optional, in which case this can be left out

@loganmhb
Copy link
Author

loganmhb commented May 6, 2017

Thanks for the thorough feedback! I'll start taking care of those things.

At a first glance, it looks like storing the input text value in component local state and making onDraft
an optional function that periodically propagates it into the app store might also eliminate the need to treat the game screen text input differently from the chat screen one.

@loganmhb
Copy link
Author

loganmhb commented May 9, 2017

Regarding debouncing -- do you have a preference for adding a dependency (e.g. lodash.debounce) vs sticking a debounce implementation in the utils?

@jkk
Copy link
Owner

jkk commented May 9, 2017

@loganmhb A debounce util function is preferred

@loganmhb
Copy link
Author

I think the latest commit finishes implementing your suggestions. Let me know if there's anything else you notice or would like changed.

@jkk
Copy link
Owner

jkk commented May 10, 2017

thanks, will review when I get a chance

@jkk
Copy link
Owner

jkk commented May 19, 2017

Almost there! A couple issues:

  1. Sending the chat (pressing enter) does not clear it

  2. In the Chat section, enter some text. Navigate to the Watch section, then back to Chat. The text is gone (but comes back if you toggle between rooms)

Code wise it's looking nice. 👍

@hadim hadim added this to the 0.4 milestone Sep 13, 2018
@hadim
Copy link
Collaborator

hadim commented Sep 13, 2018

@loganmhb Could you rebase this PR?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

Comments