diff --git a/src/components/Hero.jsx b/src/components/Hero.jsx index 76620d7..52670ad 100644 --- a/src/components/Hero.jsx +++ b/src/components/Hero.jsx @@ -3,7 +3,7 @@ import { ethers, BigNumber } from 'ethers'; import { useAccount, useContractReads, useContractRead, usePrepareContractWrite, useContractWrite, useWaitForTransaction, erc721ABI } from 'wagmi'; import { NotificationContainer, NotificationManager } from 'react-notifications'; import debounce from 'lodash'; -import { StatsPanel } from './Panels'; +import { StatsPanel, TrollboxPanel } from './Panels'; import MainABI from '../abi/main.json'; import '../styles/hero.css'; @@ -357,6 +357,10 @@ export function Hero(props) { bombsAssembled={options.bombsAssembled} bombsExploded={options.bombsExploded} /> + ) } diff --git a/src/components/Panels.jsx b/src/components/Panels.jsx index 0902ef5..52ee8ad 100644 --- a/src/components/Panels.jsx +++ b/src/components/Panels.jsx @@ -1,4 +1,5 @@ -import React from 'react'; +import React, { useEffect, useState } from 'react'; +import useWebSocket, { ReadyState } from 'react-use-websocket'; import Unaboomer from '../img/unaboomer.png'; @@ -53,4 +54,108 @@ export class StatsPanel extends React.Component { ) } +} + +export function TrollboxPanel(props) { + const [showChat, setShowChat] = useState(false); + const [history, setHistory] = useState(() => { + const saved = localStorage.getItem('trollboxHistory'); + return saved || JSON.stringify([]) + }); + + const { sendJsonMessage, readyState } = useWebSocket(props.ws, { + onOpen: () => { + console.log('WebSocket connection established.'); + }, + onMessage: (msg) => { + console.log(JSON.parse(msg.data)) + let h = JSON.parse(history); + if (h.length > 500) { + h = h.splice(-500); + } + h.push(JSON.parse(msg.data)); + setHistory(JSON.stringify(h)); + }, + shouldReconnect: () => true + }); + + + useEffect(() => { + localStorage.setItem('trollboxHistory', history); + }, [history]); + + const connectionStatus = { + [ReadyState.CONNECTING]: 'Connecting', + [ReadyState.OPEN]: 'Open', + [ReadyState.CLOSING]: 'Closing', + [ReadyState.CLOSED]: 'Closed', + [ReadyState.UNINSTANTIATED]: 'Uninstantiated', + }[readyState]; + + function send(event) { + const message = (new FormData(event.target)).get("message"); + if (message) { + sendJsonMessage({ + from: props.address, + date: new Date(), + message + }) + } + event.target.reset(); + return false; + } + + return ( + <> + {props.ws && props.address && ( +
+ {readyState == ReadyState.OPEN && showChat && ( + <> + +
{ + ev.preventDefault(); + send(ev); + }}> + + +
+ + + + )} + + {readyState == ReadyState.OPEN && !showChat && ( + + )} + + {readyState == ReadyState.CONNECTING && ( +

connecting to trollbox...

+ )} +
+ )} + + ) } \ No newline at end of file diff --git a/src/index.js b/src/index.js index fec2789..5d61014 100644 --- a/src/index.js +++ b/src/index.js @@ -38,7 +38,10 @@ ReactDOM.createRoot(document.getElementById("root")).render( - + ); diff --git a/src/styles/hero.css b/src/styles/hero.css index 4328f66..30265fa 100644 --- a/src/styles/hero.css +++ b/src/styles/hero.css @@ -83,7 +83,7 @@ button.doThing:disabled { left: 0; background-color: #231f20; text-align: left; - width: 30%; + width: 20%; margin: 0; max-height: 400px; overflow-y: auto; @@ -93,4 +93,63 @@ button.doThing:disabled { min-width: 300px; border-right: 4px solid #f9f9f9; border-top: 4px solid #f9f9f9; +} + +#trollbox { + position: fixed; + bottom: 0; + right: 0; + background-color: black; + text-align: left; + width: 40%; + margin: 0; + max-height: 400px; + overflow-y: auto; + word-wrap: break-word; + display: flex; + flex-direction: column-reverse; + min-width: 400px; + border-left: 4px solid #f9f9f9; + border-top: 4px solid #f9f9f9; +} + +@media (max-width: 600px) { + #statsbox { + min-width: 300px; + } + #trollbox { + min-width: 200px; + } + .messageDate { + display: none; + } +} + +#trollbox ul li, #trollbox span, #trollbox a { + list-style-type: none; + /* font-family: monospace; */ +} + +#trollbox form { + margin: .8em 0; +} + +#trollbox form input[type="text"] { + width: 60%; +} + +.fromAddress { + margin: 4px 4px 0 0; +} + +.messageLine { + width: 100%; + flex-direction: column-reverse; +} + +.messageDate { + font-size: 8px; + float: right; + line-height: 1em; + padding-right: 8px; } \ No newline at end of file