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,6 +50,7 @@ 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 }}>
<ThemeProvider>
<Room <Room
nick={nick} nick={nick}
lines={stateMessages} lines={stateMessages}
@ -64,6 +66,7 @@ export default function App() {
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([], {
}
function Message(props: MessageProps) {
const chatMsg = props.message;
const timestamp = chatMsg.timestamp.toLocaleString([], {
month: 'short', month: 'short',
day: 'numeric', day: 'numeric',
hour: 'numeric', hour: 'numeric',
minute: '2-digit', minute: '2-digit',
hour12: false, 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
variant="outlined"
label="Send a message"
value={inputText}
fullWidth={true}
InputLabelProps={{
shrink: true,
}}
onChange={messageHandler} onChange={messageHandler}
onKeyPress={keyPressHandler} active={waku}
disabled={!waku} onButtonClick={sendMessage}
/>
</Grid>
<Grid item xs={1}>
<Button
variant="contained"
color="primary"
size="large"
onClick={sendMessage}
disabled={!waku}
> >
Send <Row align="center">
</Button> <Fill>
</Grid> <TextInput value={inputText} />
</Grid> </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 { 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,13 +22,10 @@ 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={
@ -44,7 +42,6 @@ export default function Room(props: Props) {
} }
/> />
</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"
]
} }