ChatContainer.tsx 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. import {
  2. Chat,
  3. ChatComposers,
  4. ChatInput,
  5. ChatList,
  6. Peer,
  7. StayDownContainer
  8. } from '@andyet/simplewebrtc';
  9. import KeyboardArrowDownIcon from 'material-icons-svg/components/baseline/KeyboardArrowDown';
  10. import React from 'react';
  11. import styled from 'styled-components';
  12. import mq from '../styles/media-queries';
  13. const Container = styled.div({
  14. display: 'flex',
  15. flexDirection: 'column',
  16. minHeight: '50vh',
  17. borderTop: '1px #e9ecec solid',
  18. zIndex: 300,
  19. backgroundColor: 'white',
  20. [mq.SMALL_DESKTOP]: {
  21. width: '200px',
  22. borderTop: 'none',
  23. borderLeft: '1px #e9ecec solid'
  24. }
  25. });
  26. // const staydownContainerClass = css`
  27. // flex: 1;
  28. // overflow: scroll;
  29. // height: 0px; /* This is important to get Flexbox to overflow properly. */
  30. // margin-bottom: 16px;
  31. // `;
  32. const Header = styled.button({
  33. border: '1px #e9ecec solid',
  34. display: 'block',
  35. padding: '10px',
  36. fontSize: '18px',
  37. outline: 'none',
  38. backgroundColor: 'white',
  39. '&:active': {
  40. borderStyle: 'solid'
  41. },
  42. '& svg': {
  43. verticalAlign: 'middle',
  44. fontSize: '20px',
  45. marginRight: '5px'
  46. }
  47. });
  48. const StyledStayDownContainer = styled(StayDownContainer)({
  49. flex: 1,
  50. overflow: 'scroll',
  51. height: '0px',
  52. marginBottom: '16px'
  53. });
  54. const InputContainer = styled.div({
  55. '& textarea': {
  56. width: '100%',
  57. height: '90px',
  58. minHeight: 0,
  59. padding: '8px',
  60. margin: 0,
  61. outline: 'none',
  62. border: 'none',
  63. borderTop: '1px #e9ecec solid',
  64. display: 'block',
  65. fontSize: '14px',
  66. fontFamily: 'inherit',
  67. resize: 'none'
  68. },
  69. '& input': {
  70. marginRight: '5px'
  71. },
  72. '& label': {
  73. fontSize: '12px'
  74. }
  75. });
  76. const Message = styled.div({
  77. borderBottom: '1px #e9ecec solid',
  78. position: 'relative',
  79. padding: '10px',
  80. fontSize: '14px',
  81. '& p': {
  82. margin: 0
  83. }
  84. });
  85. const MessageAuthor = styled.p({
  86. fontWeight: 'bold'
  87. });
  88. const MessageTime = styled.span({
  89. position: 'absolute',
  90. top: '10px',
  91. right: '10px',
  92. color: '#848d90',
  93. fontSize: '12px'
  94. });
  95. const MessageText = styled.p({
  96. wordBreak: 'break-all'
  97. });
  98. interface ChatMessageGroupProps {
  99. chats: Chat[];
  100. peer: Peer | undefined;
  101. }
  102. const ChatMessageGroup: React.SFC<ChatMessageGroupProps> = ({
  103. chats,
  104. peer
  105. }) => (
  106. <Message key={chats[0].id}>
  107. <MessageAuthor>
  108. {chats[0].displayName ? chats[0].displayName : 'Anonymous'}
  109. </MessageAuthor>
  110. <MessageTime>{chats[0].time.toLocaleTimeString()}</MessageTime>
  111. {chats.map(message => (
  112. <MessageText key={message.id}>{message.body}</MessageText>
  113. ))}
  114. </Message>
  115. );
  116. const ComposersContainer = styled.div({
  117. minHeight: '30px'
  118. });
  119. interface Props {
  120. roomAddress: string;
  121. sendRtt: boolean;
  122. toggleRtt: () => void;
  123. toggleChat: () => void;
  124. }
  125. // ChatContainer renders all the UI for the chat room inside a Room. It
  126. // includes a message display embedded inside a StayDownContainer so that
  127. // it remains scrolled to the bottom, a ChatInput to type messages, and a
  128. // text element that displays currently typing peers.
  129. const ChatContainer: React.SFC<Props> = ({
  130. roomAddress,
  131. sendRtt,
  132. toggleRtt,
  133. toggleChat
  134. }) => (
  135. <Container>
  136. <Header onClick={toggleChat}>
  137. <KeyboardArrowDownIcon />
  138. <span>Chat</span>
  139. </Header>
  140. <StyledStayDownContainer>
  141. <ChatList
  142. room={roomAddress}
  143. renderGroup={({ chats, peer }) => (
  144. <ChatMessageGroup chats={chats} peer={peer} />
  145. )}
  146. />
  147. </StyledStayDownContainer>
  148. <InputContainer>
  149. <ChatInput
  150. room={roomAddress}
  151. rtt={sendRtt}
  152. placeholder="Send a message..."
  153. />
  154. <label style={{ display: 'block' }}>
  155. <input type="checkbox" checked={sendRtt} onChange={toggleRtt} />
  156. Send as I type
  157. </label>
  158. <ComposersContainer>
  159. <ChatComposers room={roomAddress} />
  160. </ComposersContainer>
  161. </InputContainer>
  162. </Container>
  163. );
  164. export default ChatContainer;