add mentions

This commit is contained in:
HF 2020-05-12 14:00:56 +02:00
parent a7b43c2854
commit d278edb9b1
3 changed files with 93 additions and 22 deletions

View File

@ -13,23 +13,21 @@ import { MAX_CHAT_MESSAGES } from '../core/constants';
import type { State } from '../reducers';
import ChatInput from './ChatInput';
import { saveSelection, restoreSelection } from '../utils/storeSelection';
import { colorFromText, splitCoordsInString } from '../core/utils';
import { colorFromText, splitChatMessage } from '../core/utils';
function ChatMessage({ name, text, country }) {
if (!name || !text) {
function ChatMessage({ name, msgArray, country }) {
if (!name || !msgArray) {
return null;
}
const msgText = text.trim();
const isInfo = (name === 'info');
let className = 'msg';
if (isInfo) {
className += ' info';
} else if (text.charAt(0) === '>') {
} else if (msgArray[0][1].charAt(0) === '>') {
className += ' greentext';
}
const splitMsg = splitCoordsInString(msgText);
return (
<p className="chatmsg">
@ -60,26 +58,35 @@ function ChatMessage({ name, text, country }) {
)
}
{
splitMsg.map((txt, i) => {
if (i % 2 === 0) {
msgArray.map((msgPart) => {
const [type, txt] = msgPart;
if (type === 't') {
return (<span className={className}>{txt}</span>);
} if (type === 'c') {
return (<a href={`./${txt}`}>{txt}</a>);
} if (type === 'p') {
return (<span className="ping">{txt}</span>);
} if (type === 'm') {
return (
<span
className={className}
>
{txt}
</span>
className="mention"
style={{
color: colorFromText(txt),
}}
>{txt}</span>
);
}
return (<a href={`./${txt}`}>{txt}</a>);
return null;
})
}
</p>
);
}
const Chat = ({ chatMessages, chatChannel }) => {
const Chat = ({ chatMessages, chatChannel, ownName }) => {
const listRef = useRef();
const [selection, setSelection] = useState(null);
const [nameRegExp, setNameRegExp] = useState(null);
const { stayScrolled } = useStayScrolled(listRef, {
initialScroll: Infinity,
});
@ -94,7 +101,14 @@ const Chat = ({ chatMessages, chatChannel }) => {
if (channelMessages.length === MAX_CHAT_MESSAGES) {
restoreSelection(selection);
}
});
}, [channelMessages]);
useEffect(() => {
const regExp = (ownName)
? new RegExp(`(^|\\s+)(@${ownName})(\\s+|$)`, 'g')
: null;
setNameRegExp(regExp);
}, [ownName]);
return (
<div style={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
@ -109,7 +123,7 @@ const Chat = ({ chatMessages, chatChannel }) => {
channelMessages.map((message) => (
<ChatMessage
name={message[0]}
text={message[1]}
msgArray={splitChatMessage(message[1], nameRegExp)}
country={message[2]}
/>
))
@ -121,9 +135,9 @@ const Chat = ({ chatMessages, chatChannel }) => {
};
function mapStateToProps(state: State) {
const { chatMessages } = state.user;
const { chatMessages, name } = state.user;
const { chatChannel } = state.gui;
return { chatMessages, chatChannel };
return { chatMessages, chatChannel, ownName: name };
}
export default connect(mapStateToProps)(Chat);

View File

@ -227,10 +227,55 @@ export function colorFromText(str: string) {
return `#${'00000'.substring(0, 6 - c.length)}${c}`;
}
/*
* splits chat message into array of what it represents
* [[type, text],[type, text], ...]
* type:
* 't': text
* 'p': ping
* 'c': coordinates
* 'm': mention of somebody else
* nameRegExp has to be in the form of:
new RegExp(`(^|\\s+)(@${ownName})(\\s+|$)`, 'g');
*/
const linkRegExp = /(#[a-z]*,-?[0-9]*,-?[0-9]*(,-?[0-9]+)?)/gi;
export function splitCoordsInString(text) {
const arr = text
.split(linkRegExp)
.filter((val, ind) => ((ind % 3) !== 2));
const linkRegExpFilter = (val, ind) => ((ind % 3) !== 2);
const mentionRegExp = /(^|\s+)(@\S+)(\s+|$)/g;
const spaceFilter = (val) => (val !== ' ');
function splitChatMessageRegexp(
msgArray,
regExp,
ident,
filter = () => true,
) {
return msgArray.map((msgPart) => {
const [type, part] = msgPart;
if (type !== 't') {
return [msgPart];
}
return part
.split(regExp)
.filter(filter)
.map((stri, i) => {
if (i % 2 === 0) {
return ['t', stri];
}
return [ident, stri];
})
.filter((el) => !!el)
}).flat(1);
}
export function splitChatMessage(message, nameRegExp = null) {
if (!message) {
return null;
}
let arr = [['t', message.trim()]];
arr = splitChatMessageRegexp(arr, linkRegExp, 'c', linkRegExpFilter);
if (nameRegExp) {
arr = splitChatMessageRegexp(arr, nameRegExp, 'p', spaceFilter);
}
arr = splitChatMessageRegexp(arr, mentionRegExp, 'm', spaceFilter);
return arr;
}

View File

@ -403,6 +403,18 @@ tr:nth-child(even) {
.msg.greentext{
color: green;
}
.ping {
background-color: #ffff87;
border-style: solid;
border-color: black;
border-width: 1px;
color: #1d1c1c;
border-radius: 6px;
}
.mention, .ping {
margin-left: 5px;
margin-right: 5px;
}
#chatlink {
position: absolute;
font-weight: bold;