mirror of https://github.com/waku-org/js-waku.git
Merge #113
113: Use waku store to retrieve archived messages in browser app r=D4nte a=D4nte Resolves #69 Co-authored-by: Franck Royer <franck@status.im>
This commit is contained in:
commit
2c72c6d388
File diff suppressed because it is too large
Load Diff
|
@ -5,7 +5,6 @@
|
||||||
"homepage": "/js-waku",
|
"homepage": "/js-waku",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@livechat/ui-kit": "*",
|
"@livechat/ui-kit": "*",
|
||||||
"peer-id": "^0.14.8",
|
|
||||||
"react": "^16.14.0",
|
"react": "^16.14.0",
|
||||||
"react-dom": "^16.14.0",
|
"react-dom": "^16.14.0",
|
||||||
"server-name-generator": "^1.0.5",
|
"server-name-generator": "^1.0.5",
|
||||||
|
|
|
@ -5,6 +5,7 @@ import './App.css';
|
||||||
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 { RelayDefaultTopic } from 'waku/waku_relay';
|
import { RelayDefaultTopic } from 'waku/waku_relay';
|
||||||
|
import { StoreCodec } from 'waku/waku_store';
|
||||||
import handleCommand from './command';
|
import handleCommand from './command';
|
||||||
import Room from './Room';
|
import Room from './Room';
|
||||||
import Waku from 'waku/waku';
|
import Waku from 'waku/waku';
|
||||||
|
@ -23,7 +24,29 @@ export default function App() {
|
||||||
const handleNewMessages = (event: { data: Uint8Array }) => {
|
const handleNewMessages = (event: { data: Uint8Array }) => {
|
||||||
const chatMsg = decodeWakuMessage(event.data);
|
const chatMsg = decodeWakuMessage(event.data);
|
||||||
if (chatMsg) {
|
if (chatMsg) {
|
||||||
copyAndReplace([chatMsg], stateMessages, setMessages);
|
copyAppendReplace([chatMsg], stateMessages, setMessages);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleProtocolChange = async (
|
||||||
|
waku: Waku,
|
||||||
|
{ peerId, protocols }: { peerId: PeerId; protocols: string[] }
|
||||||
|
) => {
|
||||||
|
if (protocols.includes(StoreCodec)) {
|
||||||
|
console.log(
|
||||||
|
`Retrieving archived messages from ${peerId.toB58String()}`
|
||||||
|
);
|
||||||
|
const response = await waku.store.queryHistory(peerId, [
|
||||||
|
ChatContentTopic,
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (response) {
|
||||||
|
const messages = response
|
||||||
|
.map((wakuMsg) => wakuMsg.payload)
|
||||||
|
.filter((payload) => !!payload)
|
||||||
|
.map((payload) => ChatMessage.decode(payload as Uint8Array));
|
||||||
|
copyMergeUniqueReplace(messages, stateMessages, setMessages);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -34,12 +57,21 @@ export default function App() {
|
||||||
} else {
|
} else {
|
||||||
stateWaku.libp2p.pubsub.on(RelayDefaultTopic, handleNewMessages);
|
stateWaku.libp2p.pubsub.on(RelayDefaultTopic, handleNewMessages);
|
||||||
|
|
||||||
|
stateWaku.libp2p.peerStore.once(
|
||||||
|
'change:protocols',
|
||||||
|
handleProtocolChange.bind({}, stateWaku)
|
||||||
|
);
|
||||||
|
|
||||||
// To clean up listener when component unmounts
|
// To clean up listener when component unmounts
|
||||||
return () => {
|
return () => {
|
||||||
stateWaku?.libp2p.pubsub.removeListener(
|
stateWaku?.libp2p.pubsub.removeListener(
|
||||||
RelayDefaultTopic,
|
RelayDefaultTopic,
|
||||||
handleNewMessages
|
handleNewMessages
|
||||||
);
|
);
|
||||||
|
stateWaku?.libp2p.peerStore.removeListener(
|
||||||
|
'change:protocols',
|
||||||
|
handleProtocolChange.bind({}, stateWaku)
|
||||||
|
);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}, [stateWaku, stateMessages]);
|
}, [stateWaku, stateMessages]);
|
||||||
|
@ -63,7 +95,7 @@ export default function App() {
|
||||||
const commandMessages = response.map((msg) => {
|
const commandMessages = response.map((msg) => {
|
||||||
return new ChatMessage(new Date(), command, msg);
|
return new ChatMessage(new Date(), command, msg);
|
||||||
});
|
});
|
||||||
copyAndReplace(commandMessages, stateMessages, setMessages);
|
copyAppendReplace(commandMessages, stateMessages, setMessages);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
|
@ -104,7 +136,7 @@ function decodeWakuMessage(data: Uint8Array): null | ChatMessage {
|
||||||
return ChatMessage.decode(wakuMsg.payload);
|
return ChatMessage.decode(wakuMsg.payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
function copyAndReplace<T>(
|
function copyAppendReplace<T>(
|
||||||
newValues: Array<T>,
|
newValues: Array<T>,
|
||||||
currentValues: Array<T>,
|
currentValues: Array<T>,
|
||||||
setter: (val: Array<T>) => void
|
setter: (val: Array<T>) => void
|
||||||
|
@ -112,3 +144,26 @@ function copyAndReplace<T>(
|
||||||
const copy = currentValues.slice();
|
const copy = currentValues.slice();
|
||||||
setter(copy.concat(newValues));
|
setter(copy.concat(newValues));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function copyMergeUniqueReplace(
|
||||||
|
newValues: ChatMessage[],
|
||||||
|
currentValues: ChatMessage[],
|
||||||
|
setter: (val: ChatMessage[]) => void
|
||||||
|
) {
|
||||||
|
const copy = currentValues.slice();
|
||||||
|
newValues.forEach((msg) => {
|
||||||
|
if (!copy.find(isEqual.bind({}, msg))) {
|
||||||
|
copy.push(msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
copy.sort((a, b) => a.timestamp.valueOf() - b.timestamp.valueOf());
|
||||||
|
setter(copy);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isEqual(lhs: ChatMessage, rhs: ChatMessage): boolean {
|
||||||
|
return (
|
||||||
|
lhs.nick === rhs.nick &&
|
||||||
|
lhs.message === rhs.message &&
|
||||||
|
lhs.timestamp.toString() === rhs.timestamp.toString()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -11,7 +11,8 @@ export default function ChatList(props: Props) {
|
||||||
|
|
||||||
const listItems = messages.map((currentMessage) => (
|
const listItems = messages.map((currentMessage) => (
|
||||||
<Message
|
<Message
|
||||||
key={currentMessage.timestamp.toString()}
|
// We assume that the same user is not sending two messages in the same second
|
||||||
|
key={currentMessage.timestamp.toString() + currentMessage.nick}
|
||||||
authorName={currentMessage.nick}
|
authorName={currentMessage.nick}
|
||||||
date={formatDisplayDate(currentMessage)}
|
date={formatDisplayDate(currentMessage)}
|
||||||
>
|
>
|
||||||
|
|
|
@ -40,7 +40,7 @@ export default function MessageInput(props: Props) {
|
||||||
<TextComposer
|
<TextComposer
|
||||||
onKeyDown={keyPressHandler}
|
onKeyDown={keyPressHandler}
|
||||||
onChange={messageHandler}
|
onChange={messageHandler}
|
||||||
active={waku}
|
active={!!waku}
|
||||||
onButtonClick={sendMessage}
|
onButtonClick={sendMessage}
|
||||||
>
|
>
|
||||||
<Row align="center">
|
<Row align="center">
|
||||||
|
|
Loading…
Reference in New Issue