diff --git a/examples/web-chat/src/ChatList.tsx b/examples/web-chat/src/ChatList.tsx
index 001e73f7..9dce4928 100644
--- a/examples/web-chat/src/ChatList.tsx
+++ b/examples/web-chat/src/ChatList.tsx
@@ -3,7 +3,7 @@ import { Message } from "./Message";
import type { ChatListProps } from "./types";
export default function ChatList(props: ChatListProps) {
- const renderedMessages = props.messages.map((message) => (
+ const renderedMessages = props.messages.array.map((message) => (
);
}
diff --git a/examples/web-chat/src/Message.ts b/examples/web-chat/src/Message.ts
index 11c5dabb..c853402d 100644
--- a/examples/web-chat/src/Message.ts
+++ b/examples/web-chat/src/Message.ts
@@ -11,6 +11,18 @@ export class Message {
this.sentTimestamp = sentTimestamp;
}
+ static cmp(left: Message, right: Message): boolean {
+ return left.timestamp.getTime() < right.timestamp.getTime();
+ }
+
+ static isEqual(left: Message, right: Message): boolean {
+ return (
+ left.timestamp.valueOf() === right.timestamp.valueOf() &&
+ left.chatMessage.nick === right.chatMessage.nick &&
+ left.chatMessage.payloadAsUtf8 === right.chatMessage.payloadAsUtf8
+ );
+ }
+
static fromWakuMessage(wakuMsg: IDecodedMessage): Message | undefined {
if (wakuMsg.payload) {
try {
diff --git a/examples/web-chat/src/hooks.ts b/examples/web-chat/src/hooks.ts
index 32b0be69..97a01907 100644
--- a/examples/web-chat/src/hooks.ts
+++ b/examples/web-chat/src/hooks.ts
@@ -12,6 +12,7 @@ import type {
UsePeersParams,
UsePeersResults,
} from "./types";
+import { OrderedSet } from "./ordered_array";
export const usePersistentNick = (): [
string,
@@ -40,15 +41,22 @@ export const useMessages = (params: UseMessagesParams): UseMessagesResult => {
setLocalMessages((prev) => [...prev, ...msgs]);
};
- const allMessages = React.useMemo((): Message[] => {
- return [...storedMessages, ...newMessages]
+ const allMessages = React.useMemo((): OrderedSet => {
+ const allMessages = new OrderedSet(Message.cmp, Message.isEqual);
+
+ const tomorrow = new Date();
+ tomorrow.setDate(tomorrow.getDate() + 1);
+
+ const _msgs = [...storedMessages, ...newMessages]
.map(Message.fromWakuMessage)
- .concat(localMessages)
.filter((v): v is Message => !!v)
.filter((v) => v.payloadAsUtf8 !== "")
- .sort(
- (left, right) => left.timestamp.getTime() - right.timestamp.getTime()
- );
+ // Filter out messages that are "sent" tomorrow are they are likely to be flukes
+ .filter((m) => m.timestamp.valueOf() < tomorrow.valueOf());
+ allMessages.push(..._msgs);
+ allMessages.push(...localMessages);
+
+ return allMessages;
}, [storedMessages, newMessages, localMessages]);
return [allMessages, pushMessages];
diff --git a/examples/web-chat/src/ordered_array.ts b/examples/web-chat/src/ordered_array.ts
new file mode 100644
index 00000000..1bfbb52e
--- /dev/null
+++ b/examples/web-chat/src/ordered_array.ts
@@ -0,0 +1,32 @@
+export class OrderedSet {
+ array: Array;
+
+ constructor(
+ public orderCmp: (a: T, b: T) => boolean,
+ public isEqual: (a: T, b: T) => boolean
+ ) {
+ this.array = [];
+ }
+
+ push(...items: T[]): void {
+ for (const item of items) {
+ this.insertInOrder(this.array, item);
+ }
+ }
+
+ insertInOrder(array: T[], item: T): T[] {
+ let i = 0;
+ while (i < array.length) {
+ if (this.isEqual(item, array[i])) {
+ continue;
+ }
+ if (this.orderCmp(item, array[i])) {
+ break;
+ }
+ i++;
+ }
+
+ array.splice(i, 0, item);
+ return array;
+ }
+}
diff --git a/examples/web-chat/src/types.ts b/examples/web-chat/src/types.ts
index c4dcd927..2b7202a7 100644
--- a/examples/web-chat/src/types.ts
+++ b/examples/web-chat/src/types.ts
@@ -2,6 +2,7 @@ import type { PeerId } from "@libp2p/interface-peer-id";
import type { LightNode, StoreQueryOptions, Waku } from "@waku/interfaces";
import type { Decoder } from "@waku/sdk";
import type { Message } from "./Message";
+import { OrderedSet } from "./ordered_array";
export type UsePeersParams = {
node: undefined | Waku;
@@ -20,10 +21,10 @@ export type UseMessagesParams = {
options: StoreQueryOptions;
};
-export type UseMessagesResult = [Message[], (v: Message[]) => void];
+export type UseMessagesResult = [OrderedSet, (v: Message[]) => void];
export interface ChatListProps {
- messages: Message[];
+ messages: OrderedSet;
}
export interface MessageInputProps {
@@ -32,7 +33,7 @@ export interface MessageInputProps {
}
export interface RoomProps {
- messages: Message[];
+ messages: OrderedSet;
commandHandler: (cmd: string) => void;
nick: string;
}