From 1cb65e3f313c9050c4287d8caf5335758188968f Mon Sep 17 00:00:00 2001
From: Russell Stringer <rstring3@jhu.edu>
Date: Fri, 7 Jan 2022 15:19:36 -0500
Subject: [PATCH] fix #2174 - icarus message will no longer stack an unbounded
 number of alerts

AlertManager now stores a hash for each incoming alert and compares the
hash of any newly arriving alert against those still in the queue.
---
 src/ui/React/AlertManager.tsx | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/src/ui/React/AlertManager.tsx b/src/ui/React/AlertManager.tsx
index 05c5903f7..d780a49cc 100644
--- a/src/ui/React/AlertManager.tsx
+++ b/src/ui/React/AlertManager.tsx
@@ -3,12 +3,14 @@ import { EventEmitter } from "../../utils/EventEmitter";
 import { Modal } from "../../ui/React/Modal";
 import Typography from "@mui/material/Typography";
 import Box from "@mui/material/Box";
+import {sha256} from "js-sha256";
 
 export const AlertEvents = new EventEmitter<[string | JSX.Element]>();
 
 interface Alert {
   id: string;
   text: string | JSX.Element;
+  hash: string;
 }
 
 let i = 0;
@@ -20,11 +22,17 @@ export function AlertManager(): React.ReactElement {
         const id = i + "";
         i++;
         setAlerts((old) => {
+          const hash = getMessageHash(text);
+          if (old.some(a => a.hash === hash)) {
+            console.log('Duplicate message');
+            return old;
+          }
           return [
             ...old,
             {
               id: id,
               text: text,
+              hash: hash,
             },
           ];
         });
@@ -42,6 +50,11 @@ export function AlertManager(): React.ReactElement {
     return () => document.removeEventListener("keydown", handle);
   }, []);
 
+  function getMessageHash(text: string | JSX.Element): string {
+    if (typeof text === 'string') return sha256(text);
+    return sha256(JSON.stringify(text.props));
+  }
+
   function close(): void {
     setAlerts((old) => {
       return old.slice(1, 1e99);