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",
"libauth",
"libp",
"livechat",
"mkdir",
"multiaddr",
"multiaddrs",

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

@ -1,10 +1,11 @@
import React, { useState } from 'react';
import { useState } from 'react';
import { ChatMessage } from 'waku-chat/chat_message';
import { WakuMessage } from 'waku/waku_message';
import { ChatContentTopic } from './App';
import ChatList from './ChatList';
import MessageInput from './MessageInput';
import { useWaku } from './WakuContext';
import { TitleBar, MessageList } from '@livechat/ui-kit';
interface Props {
lines: ChatMessage[];
@ -21,29 +22,25 @@ export default function Room(props: Props) {
className="chat-container"
style={{ height: '98vh', display: 'flex', flexDirection: 'column' }}
>
<div
className="chat-list"
style={{ display: 'flex', flexGrow: 1, overflowY: 'scroll' }}
>
<TitleBar title="Waku v2 chat app" />
<MessageList active containScrollInSubtree>
<ChatList messages={props.lines} />
</div>
<div className="chat-input" style={{ display: 'flex', padding: 20 }}>
<MessageInput
messageHandler={setMessageToSend}
sendMessage={
waku
? async () => {
return handleMessage(
messageToSend,
props.nick,
props.commandHandler,
waku.relay.send.bind(waku.relay)
);
}
: undefined
}
/>
</div>
</MessageList>
<MessageInput
messageHandler={setMessageToSend}
sendMessage={
waku
? async () => {
return handleMessage(
messageToSend,
props.nick,
props.commandHandler,
waku.relay.send.bind(waku.relay)
);
}
: undefined
}
/>
</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": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
@ -18,9 +14,8 @@
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
"jsx": "react-jsx",
"typeRoots": ["node_modules/@types", "src/types"]
},
"include": [
"src"
]
"include": ["src"]
}