127 lines
2.9 KiB
JavaScript
Raw Normal View History

2021-07-28 10:18:13 +10:00
import './App.css';
2021-07-28 12:45:41 +10:00
import { getStatusFleetNodes, Waku, WakuMessage } from 'js-waku';
2021-07-28 12:20:43 +10:00
import * as React from 'react';
2021-07-28 15:12:37 +10:00
import protons from 'protons';
2021-07-28 10:18:13 +10:00
2021-07-28 12:45:41 +10:00
const ContentTopic = `/relay-guide/1/chat/proto`;
2021-07-28 13:21:03 +10:00
const initialMessageState = {
messages: [],
};
2021-07-28 15:12:37 +10:00
const proto = protons(`
message SimpleChatMessage {
float timestamp = 1;
string text = 2;
}
`);
2021-07-28 10:18:13 +10:00
function App() {
2021-07-28 12:20:43 +10:00
const [waku, setWaku] = React.useState(undefined);
2021-07-28 12:37:05 +10:00
const [wakuStatus, setWakuStatus] = React.useState('NotStarted');
2021-07-28 13:21:03 +10:00
const [messagesState, dispatchMessages] = React.useReducer(
reduceMessages,
initialMessageState
);
2021-07-28 12:20:43 +10:00
React.useEffect(() => {
if (!!waku) return;
2021-07-28 12:37:05 +10:00
if (wakuStatus !== 'NotStarted') return;
2021-07-28 12:20:43 +10:00
2021-07-28 12:37:05 +10:00
setWakuStatus('Starting');
2021-07-28 12:20:43 +10:00
Waku.create().then((waku) => {
setWaku(waku);
2021-07-28 12:37:05 +10:00
setWakuStatus('Connecting');
bootstrapWaku(waku).then(() => {
setWakuStatus('Ready');
});
2021-07-28 12:20:43 +10:00
});
2021-07-28 12:37:05 +10:00
}, [waku, wakuStatus]);
2021-07-28 12:20:43 +10:00
2021-07-28 13:07:41 +10:00
// Need to keep the same reference around to add and delete from relay observer
const processIncomingMessage = React.useCallback((wakuMessage) => {
2021-07-28 15:12:37 +10:00
if (!wakuMessage.payload) return;
const { timestamp, text } = proto.SimpleChatMessage.decode(
wakuMessage.payload
);
dispatchMessages({
type: 'Add',
message: {
timestamp: new Date(timestamp),
text,
},
});
2021-07-28 13:07:41 +10:00
}, []);
React.useEffect(() => {
if (!waku) return;
waku.relay.addObserver(processIncomingMessage, [ContentTopic]);
return function cleanUp() {
waku.relay.deleteObserver(processIncomingMessage, [ContentTopic]);
};
}, [waku, wakuStatus, processIncomingMessage]);
2021-07-28 12:45:41 +10:00
const sendMessageOnClick = () => {
if (wakuStatus !== 'Ready') return;
sendMessage('Here is a message', waku).then(() =>
console.log('Message sent')
);
};
2021-07-28 10:18:13 +10:00
return (
<div className="App">
<header className="App-header">
2021-07-28 12:20:43 +10:00
<p>{wakuStatus}</p>
2021-07-28 12:45:41 +10:00
<button onClick={sendMessageOnClick} disabled={wakuStatus !== 'Ready'}>
Send Message
</button>
2021-07-28 13:21:03 +10:00
<ul>
{messagesState.messages.map((msg) => {
2021-07-28 15:12:37 +10:00
return (
<li>
<p>
{msg.timestamp.toString()}: {msg.text}
</p>
</li>
);
2021-07-28 13:21:03 +10:00
})}
</ul>
2021-07-28 10:18:13 +10:00
</header>
</div>
);
}
export default App;
2021-07-28 12:37:05 +10:00
async function bootstrapWaku(waku) {
const nodes = await getStatusFleetNodes();
await Promise.all(nodes.map((addr) => waku.dial(addr)));
}
2021-07-28 12:45:41 +10:00
async function sendMessage(message, waku) {
2021-07-28 15:12:37 +10:00
const payload = proto.SimpleChatMessage.encode({
timestamp: Date.now(),
text: message,
});
const wakuMessage = await WakuMessage.fromBytes(payload, ContentTopic);
2021-07-28 12:45:41 +10:00
await waku.relay.send(wakuMessage);
}
2021-07-28 13:21:03 +10:00
function reduceMessages(state, action) {
switch (action.type) {
case 'Add':
const messages = state.messages.slice();
messages.push(action.message);
return { ...state, messages };
default:
return state;
}
}