2022-08-31 12:58:18 +10:00

129 lines
3.0 KiB
JavaScript

import { waitForRemotePeer, utils } from "js-waku";
import * as React from "react";
import protons from "protons";
import { createWaku } from "js-waku/lib/create_waku";
const ContentTopic = "/toy-chat/2/huilong/proto";
const proto = protons(`
message ChatMessage {
uint64 timestamp = 1;
string nick = 2;
bytes text = 3;
}
`);
function App() {
const [waku, setWaku] = React.useState(undefined);
const [wakuStatus, setWakuStatus] = React.useState("None");
const [messages, setMessages] = React.useState([]);
React.useEffect(() => {
if (wakuStatus !== "None") return;
setWakuStatus("Starting");
createWaku({ defaultBootstrap: true }).then((waku) => {
waku.start().then(() => {
setWaku(waku);
setWakuStatus("Connecting");
});
});
}, [waku, wakuStatus]);
React.useEffect(() => {
if (!waku) return;
// We do not handle disconnection/re-connection in this example
if (wakuStatus === "Connected") return;
waitForRemotePeer(waku, ["store"]).then(() => {
// We are now connected to a store node
setWakuStatus("Connected");
});
}, [waku, wakuStatus]);
React.useEffect(() => {
if (wakuStatus !== "Connected") return;
const processMessages = (retrievedMessages) => {
const messages = retrievedMessages.map(decodeMessage).filter(Boolean);
setMessages((currentMessages) => {
return currentMessages.concat(messages.reverse());
});
};
const startTime = new Date();
// 7 days/week, 24 hours/day, 60min/hour, 60secs/min, 100ms/sec
startTime.setTime(startTime.getTime() - 7 * 24 * 60 * 60 * 1000);
waku.store
.queryHistory([ContentTopic], {
callback: processMessages,
timeFilter: { startTime, endTime: new Date() },
})
.catch((e) => {
console.log("Failed to retrieve messages", e);
setWakuStatus("Error Encountered");
});
}, [waku, wakuStatus]);
return (
<div className="App">
<header className="App-header">
<h2>{wakuStatus}</h2>
<h3>Messages</h3>
<ul>
<Messages messages={messages} />
</ul>
</header>
</div>
);
}
export default App;
function decodeMessage(wakuMessage) {
if (!wakuMessage.payload) return;
const { timestamp, nick, text } = proto.ChatMessage.decode(
wakuMessage.payload
);
if (!timestamp || !text || !nick) return;
const time = new Date();
time.setTime(timestamp);
const utf8Text = utils.bytesToUtf8(text);
return {
text: utf8Text,
timestamp: time,
nick,
timestampInt: wakuMessage.timestamp,
};
}
function Messages(props) {
return props.messages.map(({ text, timestamp, nick, timestampInt }) => {
return (
<li key={timestampInt}>
({formatDate(timestamp)}) {nick}: {text}
</li>
);
});
}
function formatDate(timestamp) {
return timestamp.toLocaleString([], {
month: "short",
day: "numeric",
hour: "numeric",
minute: "2-digit",
second: "2-digit",
hour12: false,
});
}