Imported the directory structure from egg trainer
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
const Break = () => {
|
||||
return (
|
||||
<>
|
||||
<span className='mobile hide'> - </span>
|
||||
<br className='mobile show' />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
const Footer = () => {
|
||||
return (
|
||||
<footer>
|
||||
<p className='text centered'>© <a href='https://krgamestudios.com'>KR Game Studios</a> 2020-2021<Break /><Link to='/privacypolicy'>Privacy Policy</Link><Break /><Link to='/credits'>Credits</Link></p>
|
||||
</footer>
|
||||
);
|
||||
};
|
||||
|
||||
export default Footer;
|
||||
@@ -0,0 +1,51 @@
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import dateFormat from 'dateformat';
|
||||
|
||||
import MarkdownPanel from '../utilities/markdown-panel';
|
||||
|
||||
const NewsFeed = props => {
|
||||
const [articles, setArticles] = useState([]);
|
||||
const aborter = useRef(new AbortController()); //BUGFIX: double-renders = double fetches + react update after unmount
|
||||
|
||||
useEffect(() => {
|
||||
//this... um...
|
||||
fetch(`${process.env.NEWS_URI}/news`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Access-Control-Allow-Origin': '*'
|
||||
},
|
||||
signal: aborter.current.signal //oh dear
|
||||
})
|
||||
.then(blob => blob.json())
|
||||
.then(json => setArticles(json))
|
||||
.catch(e => null) //swallow errors
|
||||
;
|
||||
|
||||
return () => aborter.current.abort(); //This is an ugly, ugly solution, but it's the only one that works
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className='panel'>
|
||||
<h1 className='text centered'>News Feed</h1>
|
||||
{articles.map((article, index) => {
|
||||
return (
|
||||
<div key={index} className='panel'>
|
||||
<hr />
|
||||
<h2>{article.title}</h2>
|
||||
<br />
|
||||
<p><em>Written by <strong>{article.author}</strong>, {
|
||||
article.edits > 0 ?
|
||||
<span>Last Updated {dateFormat(article.updatedAt, 'fullDate')} ({`${article.edits} edit${article.edits > 1 ? 's': ''}`})</span> :
|
||||
<span>Published {dateFormat(article.createdAt, 'fullDate')}</span>
|
||||
}</em></p>
|
||||
<br />
|
||||
<MarkdownPanel style={{whiteSpace: 'pre-wrap'}} content={article.body} />
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default NewsFeed;
|
||||
@@ -0,0 +1,114 @@
|
||||
import React, { useState, useEffect, useRef, useContext } from 'react';
|
||||
import { TokenContext } from '../utilities/token-provider';
|
||||
import { io } from 'socket.io-client';
|
||||
|
||||
import '../../styles/popup-chat.css';
|
||||
|
||||
//TODO: I very much need to move this out of global state
|
||||
const socket = io(`${process.env.CHAT_URI}/chat`);
|
||||
|
||||
const PopupChat = props => {
|
||||
const [open, setOpen] = useState(false);
|
||||
const [chatlog, setChatlog] = useState([{ emphasis: true, text: 'If chat doesn\'t load, reload the page' }]);
|
||||
|
||||
const inputRef = useRef();
|
||||
const sendRef = useRef();
|
||||
const endRef = useRef();
|
||||
|
||||
const authTokens = useContext(TokenContext);
|
||||
|
||||
const pushChatlog = line => setChatlog(prevChatlog => [...prevChatlog, line]);
|
||||
|
||||
useEffect(() => {
|
||||
socket.on('message', message => pushChatlog(message));
|
||||
socket.on('backlog', messages => setChatlog(prev => [...prev, ...messages]));
|
||||
socket.on('disconnect', reason => pushChatlog({ emphasis: true, text: 'Lost connection' }));
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (open) {
|
||||
endRef.current.scrollIntoView();
|
||||
}
|
||||
}, [chatlog, open]);
|
||||
|
||||
if (!open) {
|
||||
return (
|
||||
<div className='chat'>
|
||||
<button type='button' className='open' onClick={() => authTokens.tokenCallback(accessToken => handleOpen(setOpen, accessToken))}>Open Chat</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='chat'>
|
||||
<div className='log'>
|
||||
<ul className='scrollable'>
|
||||
{chatlog.map((line, index) => processLine(line, index, authTokens.accessToken))}
|
||||
<li ref={endRef} />
|
||||
</ul>
|
||||
</div>
|
||||
<input type='text' className='input' placeholder='message' onKeyPress={evt => evt.key == 'Enter' ? sendRef.current.click() : ''} ref={inputRef} />
|
||||
<button type='button' className='send' onClick={() => authTokens.tokenCallback(accessToken => handleSend(inputRef, pushChatlog, authTokens.getPayload().username, accessToken))} ref={sendRef}>Send</button>
|
||||
<button type='button' className='close' onClick={() => handleClose(setOpen)}>Close Chat</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
//handlers
|
||||
const handleOpen = (setOpen, accessToken) => {
|
||||
setOpen(true);
|
||||
|
||||
socket.emit('open chat', {
|
||||
accessToken
|
||||
});
|
||||
};
|
||||
|
||||
const handleClose = setOpen => {
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
const handleSend = (inputRef, pushChatlog, username, accessToken) => {
|
||||
if (inputRef.current.value == '') {
|
||||
return;
|
||||
}
|
||||
|
||||
socket.emit('message', {
|
||||
accessToken,
|
||||
text: inputRef.current.value
|
||||
});
|
||||
|
||||
if (!inputRef.current.value.startsWith('/')) {
|
||||
pushChatlog({ username: username, text: inputRef.current.value });
|
||||
}
|
||||
|
||||
inputRef.current.value = '';
|
||||
};
|
||||
|
||||
//render each line
|
||||
const processLine = (line, index, accessToken) => {
|
||||
let content = <div className='content'>{line.username ? <span className='username'>{line.username}: </span> : ''}{line.text ? <span className='text'>{line.text}</span> : ''}</div>;
|
||||
|
||||
//decorators
|
||||
if (line.emphasis) {
|
||||
content = <em>{content}</em>;
|
||||
}
|
||||
|
||||
if (line.strong) {
|
||||
content = <strong>{content}</strong>;
|
||||
}
|
||||
|
||||
return <li key={index} className='line'>{content}<a className='report' onClick={() => processReport(line, accessToken)}>!!!</a></li>;
|
||||
};
|
||||
|
||||
const processReport = (line, accessToken) => {
|
||||
const yes = confirm('Report this message?');
|
||||
|
||||
if (yes) {
|
||||
socket.emit('report', {
|
||||
accessToken,
|
||||
index: line.index
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export default PopupChat;
|
||||
Reference in New Issue
Block a user