mirror of
https://github.com/waku-org/js-waku.git
synced 2025-02-27 19:40:52 +00:00
Merge #95
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:
commit
d32fa7d03e
@ -33,6 +33,7 @@
|
|||||||
"lastpub",
|
"lastpub",
|
||||||
"libauth",
|
"libauth",
|
||||||
"libp",
|
"libp",
|
||||||
|
"livechat",
|
||||||
"mkdir",
|
"mkdir",
|
||||||
"multiaddr",
|
"multiaddr",
|
||||||
"multiaddrs",
|
"multiaddrs",
|
||||||
|
1421
web-chat/package-lock.json
generated
1421
web-chat/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -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",
|
||||||
|
@ -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>
|
||||||
);
|
);
|
||||||
|
@ -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) => {
|
||||||
|
@ -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>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -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
1
web-chat/src/types/types.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
declare module '@livechat/ui-kit';
|
@ -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"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user