95: Use off-the-shelf React Templates for UI r=D4nte a=littlealex003

- **What kind of change does this PR introduce?** (Bug fix, feature, docs update, ...)
Refactor

- **What is the current behavior?** (You can also link to an open issue here)
Custom React Material UI Implementation

- **What is the new behavior (if this is a feature change)?**
Off the shelf React Material Chat UI Implementation


Co-authored-by: littlealex003 <littlealex003@gmail.com>
This commit is contained in:
bors[bot] 2021-04-29 11:19:05 +00:00 committed by GitHub
commit d32fa7d03e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 946 additions and 701 deletions

View File

@ -33,6 +33,7 @@
"lastpub", "lastpub",
"libauth", "libauth",
"libp", "libp",
"livechat",
"mkdir", "mkdir",
"multiaddr", "multiaddr",
"multiaddrs", "multiaddrs",

File diff suppressed because it is too large Load Diff

View File

@ -4,10 +4,10 @@
"private": true, "private": true,
"homepage": "/js-waku", "homepage": "/js-waku",
"dependencies": { "dependencies": {
"@material-ui/core": "^4.11.3", "@livechat/ui-kit": "*",
"peer-id": "^0.14.8", "peer-id": "^0.14.8",
"react": "^17.0.2", "react": "^16.14.0",
"react-dom": "^17.0.2", "react-dom": "^16.14.0",
"server-name-generator": "^1.0.5", "server-name-generator": "^1.0.5",
"waku": "file:../build/main/lib", "waku": "file:../build/main/lib",
"waku-chat": "file:../build/main/chat", "waku-chat": "file:../build/main/chat",

View File

@ -9,6 +9,7 @@ import handleCommand from './command';
import Room from './Room'; import Room from './Room';
import Waku from 'waku/waku'; import Waku from 'waku/waku';
import { WakuContext } from './WakuContext'; import { WakuContext } from './WakuContext';
import { ThemeProvider } from '@livechat/ui-kit';
import { generate } from 'server-name-generator'; import { generate } from 'server-name-generator';
export const ChatContentTopic = 'dingpu'; export const ChatContentTopic = 'dingpu';
@ -49,21 +50,23 @@ export default function App() {
style={{ height: '100vh', width: '100vw', overflow: 'hidden' }} style={{ height: '100vh', width: '100vw', overflow: 'hidden' }}
> >
<WakuContext.Provider value={{ waku: stateWaku }}> <WakuContext.Provider value={{ waku: stateWaku }}>
<Room <ThemeProvider>
nick={nick} <Room
lines={stateMessages} nick={nick}
commandHandler={(input: string) => { lines={stateMessages}
const { command, response } = handleCommand( commandHandler={(input: string) => {
input, const { command, response } = handleCommand(
stateWaku, input,
setNick stateWaku,
); setNick
const commandMessages = response.map((msg) => { );
return new ChatMessage(new Date(), command, msg); const commandMessages = response.map((msg) => {
}); return new ChatMessage(new Date(), command, msg);
copyAndReplace(commandMessages, stateMessages, setMessages); });
}} copyAndReplace(commandMessages, stateMessages, setMessages);
/> }}
/>
</ThemeProvider>
</WakuContext.Provider> </WakuContext.Provider>
</div> </div>
); );

View File

@ -1,13 +1,6 @@
import { import { useEffect, useRef } from 'react';
Card,
CardContent,
List,
ListItem,
ListItemText,
Typography,
} from '@material-ui/core';
import React, { useEffect, useRef } from 'react';
import { ChatMessage } from '../../build/main/chat/chat_message'; import { ChatMessage } from '../../build/main/chat/chat_message';
import { Message, MessageText, MessageGroup } from '@livechat/ui-kit';
interface Props { interface Props {
messages: ChatMessage[]; messages: ChatMessage[];
@ -16,59 +9,32 @@ interface Props {
export default function ChatList(props: Props) { export default function ChatList(props: Props) {
const messages = props.messages; const messages = props.messages;
const listItems = messages.map((message) => ( const listItems = messages.map((currentMessage) => (
<ListItem key={message.timestamp.toString()}> <Message
<ListItemText primary={<Message message={message} />} /> key={currentMessage.timestamp.toString()}
</ListItem> authorName={currentMessage.nick}
date={formatDisplayDate(currentMessage)}
>
<MessageText>{currentMessage.message}</MessageText>
</Message>
)); ));
return ( return (
<List dense={true}> <MessageGroup>
{listItems} {listItems}
<AlwaysScrollToBottom messages={messages} /> <AlwaysScrollToBottom messages={messages} />
</List> </MessageGroup>
); );
}
interface MessageProps { function formatDisplayDate(message: ChatMessage) {
message: ChatMessage; return message.timestamp.toLocaleString([], {
} month: 'short',
day: 'numeric',
function Message(props: MessageProps) { hour: 'numeric',
const chatMsg = props.message; minute: '2-digit',
const timestamp = chatMsg.timestamp.toLocaleString([], { hour12: false,
month: 'short', });
day: 'numeric', }
hour: 'numeric',
minute: '2-digit',
hour12: false,
});
// {`<${timestamp}> ${chatMsg.nick}: ${chatMsg.message}`}
return (
<Card className="chat-message" variant="outlined">
<CardContent>
<Typography className="chat-nick" variant="subtitle2">
{chatMsg.nick}
<Typography
className="chat-timestamp"
color="textSecondary"
variant="caption"
style={{ marginLeft: 3 }}
>
{timestamp}
</Typography>
</Typography>
<Typography
className="chat-message-content"
variant="body1"
component="p"
>
{chatMsg.message}
</Typography>
</CardContent>
</Card>
);
} }
const AlwaysScrollToBottom = (props: Props) => { const AlwaysScrollToBottom = (props: Props) => {

View File

@ -1,6 +1,13 @@
import React, { ChangeEvent, KeyboardEvent, useState } from 'react'; import { ChangeEvent, KeyboardEvent, useState } from 'react';
import { Button, Grid, TextField } from '@material-ui/core';
import { useWaku } from './WakuContext'; import { useWaku } from './WakuContext';
import {
TextInput,
TextComposer,
Row,
Fill,
Fit,
SendButton,
} from '@livechat/ui-kit';
interface Props { interface Props {
messageHandler: (msg: string) => void; messageHandler: (msg: string) => void;
@ -30,32 +37,20 @@ export default function MessageInput(props: Props) {
}; };
return ( return (
<Grid container direction="row" alignItems="center"> <TextComposer
<Grid item xs={11}> onKeyDown={keyPressHandler}
<TextField onChange={messageHandler}
variant="outlined" active={waku}
label="Send a message" onButtonClick={sendMessage}
value={inputText} >
fullWidth={true} <Row align="center">
InputLabelProps={{ <Fill>
shrink: true, <TextInput value={inputText} />
}} </Fill>
onChange={messageHandler} <Fit>
onKeyPress={keyPressHandler} <SendButton />
disabled={!waku} </Fit>
/> </Row>
</Grid> </TextComposer>
<Grid item xs={1}>
<Button
variant="contained"
color="primary"
size="large"
onClick={sendMessage}
disabled={!waku}
>
Send
</Button>
</Grid>
</Grid>
); );
} }

View File

@ -1,10 +1,11 @@
import React, { useState } from 'react'; import { useState } from 'react';
import { ChatMessage } from 'waku-chat/chat_message'; import { ChatMessage } from 'waku-chat/chat_message';
import { WakuMessage } from 'waku/waku_message'; import { WakuMessage } from 'waku/waku_message';
import { ChatContentTopic } from './App'; import { ChatContentTopic } from './App';
import ChatList from './ChatList'; import ChatList from './ChatList';
import MessageInput from './MessageInput'; import MessageInput from './MessageInput';
import { useWaku } from './WakuContext'; import { useWaku } from './WakuContext';
import { TitleBar, MessageList } from '@livechat/ui-kit';
interface Props { interface Props {
lines: ChatMessage[]; lines: ChatMessage[];
@ -21,29 +22,25 @@ export default function Room(props: Props) {
className="chat-container" className="chat-container"
style={{ height: '98vh', display: 'flex', flexDirection: 'column' }} style={{ height: '98vh', display: 'flex', flexDirection: 'column' }}
> >
<div <TitleBar title="Waku v2 chat app" />
className="chat-list" <MessageList active containScrollInSubtree>
style={{ display: 'flex', flexGrow: 1, overflowY: 'scroll' }}
>
<ChatList messages={props.lines} /> <ChatList messages={props.lines} />
</div> </MessageList>
<div className="chat-input" style={{ display: 'flex', padding: 20 }}> <MessageInput
<MessageInput messageHandler={setMessageToSend}
messageHandler={setMessageToSend} sendMessage={
sendMessage={ waku
waku ? async () => {
? async () => { return handleMessage(
return handleMessage( messageToSend,
messageToSend, props.nick,
props.nick, props.commandHandler,
props.commandHandler, waku.relay.send.bind(waku.relay)
waku.relay.send.bind(waku.relay) );
); }
} : undefined
: undefined }
} />
/>
</div>
</div> </div>
); );
} }

1
web-chat/src/types/types.d.ts vendored Normal file
View File

@ -0,0 +1 @@
declare module '@livechat/ui-kit';

View File

@ -1,11 +1,7 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "es5", "target": "es5",
"lib": [ "lib": ["dom", "dom.iterable", "esnext"],
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true, "allowJs": true,
"skipLibCheck": true, "skipLibCheck": true,
"esModuleInterop": true, "esModuleInterop": true,
@ -18,9 +14,8 @@
"resolveJsonModule": true, "resolveJsonModule": true,
"isolatedModules": true, "isolatedModules": true,
"noEmit": true, "noEmit": true,
"jsx": "react-jsx" "jsx": "react-jsx",
"typeRoots": ["node_modules/@types", "src/types"]
}, },
"include": [ "include": ["src"]
"src"
]
} }