Skip to content
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

Video 3728 add input field and send button #451

Merged
merged 14 commits into from
Mar 11, 2021

Conversation

olipyskoty
Copy link
Contributor

Contributing to Twilio

All third party contributors acknowledge that any contributions they provide will be made under the same open source license that the open source project is provided under.

  • I acknowledge that all my contributions will be made under the project's license.

Pull Request Details

JIRA link(s):

Description

This PR adds an input field and send button to the chat window so the user can type and send messages to other participants. The send button will be highlighted in blue when anything other than whitespace is typed. Users can press enter or click the button to send a message, while enter + shift creates a new line. Please note that actually sending a message in this PR will throw an error until the new server is complete and merged. We also decided to keep the blue outline around the <TextareaAutosize /> when it is focused for accessibility reasons.

web:
3728

mobile:
3728-2

Burndown

Before review

  • Updated CHANGELOG.md if necessary
  • Added unit tests if necessary
  • Updated affected documentation
  • Verified locally with npm test
  • Manually sanity tested running locally
  • Included screenshot as PR comment (if needed)
  • Ready for review

Before merge

  • Got one or more +1s
  • Re-tested if necessary

Comment on lines 76 to 77
onKeyPress={isMobile ? () => null : event => handleReturnKeyPress(event)}
onChange={event => handleChange(event)}
Copy link
Contributor

Choose a reason for hiding this comment

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

Here we can simply pass the functions themselves:

Suggested change
onKeyPress={isMobile ? () => null : event => handleReturnKeyPress(event)}
onChange={event => handleChange(event)}
onKeyPress={handleReturnKeyPress}
onChange={handleChange}

I think the isMobile check can be up on line 54. See my other comment.


// ensures pressing enter + shift creates a new line, so that enter on its own only sends the message:
const handleReturnKeyPress = (event: React.KeyboardEvent) => {
if (event.key === 'Enter' && !event.shiftKey) {
Copy link
Contributor

Choose a reason for hiding this comment

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

We can simplify line 76 by including the isMobile check here:

Suggested change
if (event.key === 'Enter' && !event.shiftKey) {
if (!isMobile && event.key === 'Enter' && !event.shiftKey) {

Comment on lines 38 to 42
interface InputFieldProps {
conversation: Conversation;
}

export default function InputField({ conversation }: InputFieldProps) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's call this ChatInput to be consistent with the filename:

Suggested change
interface InputFieldProps {
conversation: Conversation;
}
export default function InputField({ conversation }: InputFieldProps) {
interface ChatInputProps {
conversation: Conversation;
}
export default function ChatInput({ conversation }: InputFieldProps) {

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ahh good catch - missed this one 👍

.parent()
.simulate('click');
expect(mockHandleSendMessage).toHaveBeenCalled();
});
Copy link
Contributor

@timmydoza timmydoza Mar 10, 2021

Choose a reason for hiding this comment

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

All these tests look good! But I think we could use some additional tests for the handleReturnKeyPress function. We'll need to test that it works correctly for the different values of isMobile, event.key, and event.shiftKey.

CircleCI provides a test coverage report for each PR (which can also be generated locally with npm run test:ci), which can be used to see if there are any tests that are missing: https://1225-216070925-gh.circle-artifacts.com/0/coverage/lcov-report/src/components/ChatWindow/ChatInput/ChatInput.tsx.html

.find(SendMessageIcon)
.parent()
.simulate('click');
expect(mockHandleSendMessage).toHaveBeenCalled();
Copy link
Contributor

Choose a reason for hiding this comment

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

Even better is:

Suggested change
expect(mockHandleSendMessage).toHaveBeenCalled();
expect(mockHandleSendMessage).toHaveBeenCalledWith('I am a message!!!');

Also, we could have a test to make sure that the whitespace is being trimmed. We could probably just use this same test for that:

wrapper.find(TextareaAutosize).simulate('change', { target: { value: ' I am a message!!! \n ' } });

padding: '1em 1.2em 1em',
},
textArea: {
paddingTop: '0.2em',
Copy link
Contributor

Choose a reason for hiding this comment

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

I used this for my screenshots in slack:

padding: '0.75em 1em`,
marginTop: `0.4em`

But feel free to play with it. padding: '0.75em 1em makes the padding identical to the padding on the text inputs you see before you enter a room.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

i think this looks good and i like how it stays consistent with the inputs on the "login" page

@olipyskoty
Copy link
Contributor Author

@timmydoza updating the <div> to <button> tag in the <ChatWindowHeader> now includes the blue outline when tabbing to the <button>, or when clicking on it. just fyi - but good for accessibility!

@@ -21,6 +21,8 @@ const useStyles = makeStyles(() =>
closeChatWindow: {
cursor: 'pointer',
display: 'flex',
background: 'transparent',
border: '0',
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: I think adding padding: '0.4em' helps a little. It makes the blue border square when it is focused. Previously it was a little rectangular.

image

Comment on lines 84 to 89
<button
className={clsx(classes.sendButton, { [classes.activeSendButton]: isValidMessage })}
onClick={() => handleSendMessage(messageBody)}
>
<SendMessageIcon />
</div>
</button>
Copy link
Contributor

@timmydoza timmydoza Mar 11, 2021

Choose a reason for hiding this comment

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

Looks good! But now that this is a button, I think we should use the disabled prop when the button isn't supposed to be clickable:

      <button className={classes.sendButton} onClick={() => handleSendMessage(messageBody)} disabled={!isValidMessage}>
        <SendMessageIcon />
      </button>

When disabled is true, it tells the browser that the button isn't supposed to be clickable. As a result, the button won't be tabbable when it's disabled. So I think it goes a little further than just changing the styles so that it doesn't look clickable.

Also, with this change, we can take advantage of the :disabled pseudo-class to apply the right styles when it's disabled. This way we don't have to worry about conditionally applying the styles ourselves. So the sendButton class can look like:

  sendButton: {
    height: '40px',
    width: '40px',
    border: '0',
    borderRadius: '4px',
    float: 'right',
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'center',
    marginTop: '1em',
    background: '#0263E0',
    cursor: 'pointer',
    '&:disabled': {
      background: 'none',
      cursor: 'default',
    },
  },

The & is just a substitute for the classname of the parent object. So '&:disabled' gets turned into .sendButton:disabled.

Then, the test will have to be updated to look for the disabled prop instead of the activeSendButton class (which we can get rid of). For example:

    expect(
      wrapper
        .find(SendMessageIcon)
        .parent()
        .prop('disabled')
    ).toBe(true);

Copy link
Contributor Author

Choose a reason for hiding this comment

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

good point! this looks nicer too

@olipyskoty olipyskoty merged commit e18f291 into feature/conversations Mar 11, 2021
@olipyskoty olipyskoty deleted the VIDEO-3728-input-field-and-send branch March 11, 2021 19:05
timmydoza pushed a commit that referenced this pull request Mar 31, 2021
* VIDEO 3731 Conversations UI - create chat window (#421)

* Video 4078 add flip camera button to mobile menu (#433)

VIDEO 4078 Conversations - Add flip camera button to 'more' mobile menu

* Video 3730 add conversation hooks (#438)

* Add initial hooks for chat

* Update hooks in chat provider

* Add tests for conversationProvider component

* Fix DeviceSelectionScreen tests

* Update variable names

* Revert proxy url in package.json

* Fix linting issues

* Make error handling more user friendly

* Fix a test in src/state

* Temporarily disable cypress tests

* Undo prettier changes to config.yml

* Update chatProvider test

* Cleanup ChatProvider

* Video 3732 Conversations UI - create message components (#441)

* Add links to TextMessage component (#446)

* Add links to TextMessage component

* Update CSS in TextMessage

* Update snapshot test

* Fix issue in addLinks function

* Use forEach loop in addLinks function

* Add new server (#443)

* Use new server with reused code

* Add firebase auth to server

* Convert server to typescript

* Add tests for firebaseAuthMiddleware

* Refactor server

* Add more server tests

* Add tests for CreateExpressHandler

* Fix linter issue

* Delete old server

* Fix linter issues

* Fix some server issues

* Set up server build steps

* Change request to match new server api

* Fix token fetch test

* Add server build step to circleci config

* Enable cyress tests in CI

* Undo prettier changes in config.yml

* install plugin-rtc from npm

* Fix firebaseAuth test

* Add create_conversation:true to token requests

* Upgrade plugin-rtc to 0.8.0

* Temorarily remove firebaseAuthMiddleware and recording rules route

* Add ChatProvider back in

* Update .env.example

* Change build:server script

* Add firebaseAuthMiddleware

* Add comments to firebaseAuthMiddleware

* Update useFirebaseAuth tests

* Video 3728 Conversations UI - add input field and send button (#451)

* Chat notification (#454)

* Add notification to chat icon

* Add tests for ToggleChatButton

* Some cleanup

* Fix linting issue

* Video-4525 loading screen (#461)

* Video 4454 Conversations UI -  message list scrolling (#467)

* Update MessageList component to change how messages are grouped (#469)

* Update MessageList component to change how messages are grouped

* Simplify MessageList code

* Video 3888 file input for conversations (#458)

* Add FileAttachmentIcon

* Add File Input to ChatInput component

* Add change handler to file input

* Create MediaMessage component and add it to MessageList

* Toggle ChatWindow visibility with CSS

* Update messageList tests

* Add function to format the file size

* Update error handling in ChatInput component

* Add tests for MediaMessage component

* Update snapshot test

* Add tests for ChatInput

* Fix linting issue

* Update filesize formatting

* Update error language and tests

* Reset file input value after file sent

* Center icon in MediaMessage

* Update Icon size

* Fix breaking ChatInput test

* Update snapshot

* Use accept attribute on file input element

* Update readme to add information about the chat feature and conversations api

* Cross browser fixes (#472)

* Update app.yaml for the new server

* Add cache controls for static assets

* Only hide Screenshare button on mobile devices

* Auto focus on chat input when user opens chat window

* Fix iOS bug with media messages

* Fix issues in MessageListScrollContainer

* Fix app.yaml

* Fix infinite loop when there is a conversations error

* Update tests for ChatInput

* Update mediamessage test

* Update menubar tests

* Update messageList snapshot

* Fix linting issue

* Add comments to the server

* Video 3727 - cypress testing (#473)

* Video 4597 feature flag (#475)

* Update plugin-rtc version

* Add feature flag for Twilio Conversations

* Add tests

* Add info to .env.example

* Update readme with info about twilio conversations (#476)

* Update readme with info about twilio conversations

* Update readme to address feedback

* Release 0.3.0 (#479)

* Bump version and update changelog

* Add plugin-rtc upgrade instructions to the readme

Co-authored-by: olipyskoty <77076398+olipyskoty@users.noreply.github.com>
Co-authored-by: Sean Coleman <smcoleman27@gmail.com>
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.

2 participants