Can send a message from text input using submit button

This commit is contained in:
Gabe Kangas
2022-05-04 23:06:35 -07:00
parent c56c45d904
commit f96bde4f71
4 changed files with 54 additions and 43 deletions

View File

@@ -1,10 +1,12 @@
import { SmileOutlined } from '@ant-design/icons'; import { SmileOutlined } from '@ant-design/icons';
import { Button, Input } from 'antd'; import { Button, Input } from 'antd';
import { useRef, useState } from 'react'; import React, { useRef, useState } from 'react';
import { useRecoilValue } from 'recoil'; import { useRecoilValue } from 'recoil';
import ContentEditable from 'react-contenteditable'; import ContentEditable from 'react-contenteditable';
import WebsocketService from '../../../services/websocket-service'; import WebsocketService from '../../../services/websocket-service';
import { websocketServiceAtom } from '../../stores/ClientConfigStore'; import { websocketServiceAtom } from '../../stores/ClientConfigStore';
import { getCaretPosition, convertToText, convertOnPaste } from '../chat';
import { MessageType } from '../../../interfaces/socket-events';
import s from './ChatTextField.module.scss'; import s from './ChatTextField.module.scss';
interface Props { interface Props {
@@ -22,8 +24,27 @@ export default function ChatTextField(props: Props) {
// large is 40px // large is 40px
const size = 'small'; const size = 'small';
const sendMessage = () => {
if (!websocketService) {
console.log('websocketService is not defined');
return;
}
const message = convertToText(value);
websocketService.send({ type: MessageType.CHAT, body: message });
setValue('');
};
const handleChange = evt => { const handleChange = evt => {
text.current = evt.target.value; text.current = evt.target.value;
setValue(evt.target.value);
};
const handleKeyDown = event => {
const key = event && event.key;
if (key === 'Enter') {
}
}; };
return ( return (
@@ -33,11 +54,14 @@ export default function ChatTextField(props: Props) {
style={{ width: '60%', maxHeight: '50px', padding: '5px' }} style={{ width: '60%', maxHeight: '50px', padding: '5px' }}
html={text.current} html={text.current}
onChange={handleChange} onChange={handleChange}
onKeyDown={e => {
handleKeyDown(e);
}}
/> />
<Button type="default" ghost title="Emoji" onClick={() => setShowEmojis(!showEmojis)}> <Button type="default" ghost title="Emoji" onClick={() => setShowEmojis(!showEmojis)}>
<SmileOutlined style={{ color: 'rgba(0,0,0,.45)' }} /> <SmileOutlined style={{ color: 'rgba(0,0,0,.45)' }} />
</Button> </Button>
<Button size={size} type="primary"> <Button size={size} type="primary" onClick={sendMessage}>
Submit Submit
</Button> </Button>
</Input.Group> </Input.Group>

View File

@@ -1,8 +1,8 @@
import { // import {
CHAT_INITIAL_PLACEHOLDER_TEXT, // CHAT_INITIAL_PLACEHOLDER_TEXT,
CHAT_PLACEHOLDER_TEXT, // CHAT_PLACEHOLDER_TEXT,
CHAT_PLACEHOLDER_OFFLINE, // CHAT_PLACEHOLDER_OFFLINE,
} from './constants.js'; // } from './constants.js';
// Taken from https://stackoverflow.com/a/46902361 // Taken from https://stackoverflow.com/a/46902361
export function getCaretPosition(node) { export function getCaretPosition(node) {
@@ -26,8 +26,8 @@ export function getCaretPosition(node) {
// Might not need this anymore // Might not need this anymore
// Pieced together from parts of https://stackoverflow.com/questions/6249095/how-to-set-caretcursor-position-in-contenteditable-element-div // Pieced together from parts of https://stackoverflow.com/questions/6249095/how-to-set-caretcursor-position-in-contenteditable-element-div
export function setCaretPosition(editableDiv, position) { export function setCaretPosition(editableDiv, position) {
var range = document.createRange(); const range = document.createRange();
var sel = window.getSelection(); const sel = window.getSelection();
range.selectNode(editableDiv); range.selectNode(editableDiv);
range.setStart(editableDiv.childNodes[0], position); range.setStart(editableDiv.childNodes[0], position);
range.collapse(true); range.collapse(true);
@@ -36,21 +36,21 @@ export function setCaretPosition(editableDiv, position) {
sel.addRange(range); sel.addRange(range);
} }
export function generatePlaceholderText(isEnabled, hasSentFirstChatMessage) { // export function generatePlaceholderText(isEnabled, hasSentFirstChatMessage) {
if (isEnabled) { // if (isEnabled) {
return hasSentFirstChatMessage // return hasSentFirstChatMessage
? CHAT_PLACEHOLDER_TEXT // ? CHAT_PLACEHOLDER_TEXT
: CHAT_INITIAL_PLACEHOLDER_TEXT; // : CHAT_INITIAL_PLACEHOLDER_TEXT;
} // }
return CHAT_PLACEHOLDER_OFFLINE; // return CHAT_PLACEHOLDER_OFFLINE;
} // }
export function extraUserNamesFromMessageHistory(messages) { export function extraUserNamesFromMessageHistory(messages) {
const list = []; const list = [];
if (messages) { if (messages) {
messages messages
.filter((m) => m.user && m.user.displayName) .filter(m => m.user && m.user.displayName)
.forEach(function (message) { .forEach(message => {
if (!list.includes(message.user.displayName)) { if (!list.includes(message.user.displayName)) {
list.push(message.user.displayName); list.push(message.user.displayName);
} }
@@ -87,9 +87,7 @@ export function convertToText(str = '') {
// Trim each line. // Trim each line.
value = value value = value
.split('\n') .split('\n')
.map((line = '') => { .map((line = '') => line.trim())
return line.trim();
})
.join('\n'); .join('\n');
// No more than 2x newline, per "paragraph". // No more than 2x newline, per "paragraph".
@@ -145,19 +143,9 @@ export function convertOnPaste(event = { preventDefault() {} }, emojiList) {
export function createEmojiMarkup(data, isCustom) { export function createEmojiMarkup(data, isCustom) {
const emojiUrl = isCustom ? data.emoji : data.url; const emojiUrl = isCustom ? data.emoji : data.url;
const emojiName = ( const emojiName = (
isCustom isCustom ? data.name : data.url.split('\\').pop().split('/').pop().split('.').shift()
? data.name
: data.url.split('\\').pop().split('/').pop().split('.').shift()
).toLowerCase(); ).toLowerCase();
return ( return `<img class="emoji" alt=":${emojiName}:" title=":${emojiName}:" src="${emojiUrl}"/>`;
'<img class="emoji" alt=":' +
emojiName +
':" title=":' +
emojiName +
':" src="' +
emojiUrl +
'"/>'
);
} }
// trim html white space characters from ends of messages for more accurate counting // trim html white space characters from ends of messages for more accurate counting
@@ -168,7 +156,7 @@ export function trimNbsp(html) {
export function emojify(HTML, emojiList) { export function emojify(HTML, emojiList) {
const textValue = convertToText(HTML); const textValue = convertToText(HTML);
for (var lastPos = textValue.length; lastPos >= 0; lastPos--) { for (let lastPos = textValue.length; lastPos >= 0; lastPos--) {
const endPos = textValue.lastIndexOf(':', lastPos); const endPos = textValue.lastIndexOf(':', lastPos);
if (endPos <= 0) { if (endPos <= 0) {
break; break;
@@ -178,13 +166,13 @@ export function emojify(HTML, emojiList) {
break; break;
} }
const typedEmoji = textValue.substring(startPos + 1, endPos).trim(); const typedEmoji = textValue.substring(startPos + 1, endPos).trim();
const emojiIndex = emojiList.findIndex(function (emojiItem) { const emojiIndex = emojiList.findIndex(
return emojiItem.name.toLowerCase() === typedEmoji.toLowerCase(); emojiItem => emojiItem.name.toLowerCase() === typedEmoji.toLowerCase(),
}); );
if (emojiIndex != -1) { if (emojiIndex != -1) {
const emojiImgElement = createEmojiMarkup(emojiList[emojiIndex], true); const emojiImgElement = createEmojiMarkup(emojiList[emojiIndex], true);
HTML = HTML.replace(':' + typedEmoji + ':', emojiImgElement); HTML = HTML.replace(`:${typedEmoji}:`, emojiImgElement);
} }
} }
return HTML; return HTML;

View File

@@ -75,12 +75,11 @@ export function ClientConfigStore() {
const [websocketService, setWebsocketService] = const [websocketService, setWebsocketService] =
useRecoilState<WebsocketService>(websocketServiceAtom); useRecoilState<WebsocketService>(websocketServiceAtom);
// let websocketService: WebsocketService; let ws: WebsocketService;
const updateClientConfig = async () => { const updateClientConfig = async () => {
try { try {
const config = await ClientConfigService.getConfig(); const config = await ClientConfigService.getConfig();
// console.log(`ClientConfig: ${JSON.stringify(config)}`);
setClientConfig(config); setClientConfig(config);
setAppState(AppState.Online); setAppState(AppState.Online);
} catch (error) { } catch (error) {
@@ -133,7 +132,7 @@ export function ClientConfigStore() {
const startChat = async () => { const startChat = async () => {
setChatState(ChatState.Loading); setChatState(ChatState.Loading);
try { try {
const ws = new WebsocketService(accessToken, '/ws'); ws = new WebsocketService(accessToken, '/ws');
ws.handleMessage = handleMessage; ws.handleMessage = handleMessage;
setWebsocketService(ws); setWebsocketService(ws);
} catch (error) { } catch (error) {

View File

@@ -32,7 +32,7 @@ export const Example = Template.bind({});
export const LongerMessage = Template.bind({}); export const LongerMessage = Template.bind({});
LongerMessage.args = { LongerMessage.args = {
value: value:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.', 'Lorem ipsum dolor sit amet, <img src="https://watch.owncast.online/img/emoji/bluntparrot.gif" width="40px" /> consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
}; };
LongerMessage.parameters = { LongerMessage.parameters = {