Skip to content

Commit 8dbd823

Browse files
committed
wip
1 parent 8379209 commit 8dbd823

File tree

3 files changed

+56
-12
lines changed

3 files changed

+56
-12
lines changed

src/components/eventStream/EventStream.tsx

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,15 @@ import { useSnackbar } from "notistack";
1212
import { useASAuthorizationStatus } from "../../hooks/useIsAuthorized";
1313
import { getMessageFromEvent, protoBlobToText } from "../../protobuf/protobuf";
1414
import { eventStreamEnabledAtom } from "../../state/eventStream";
15+
import { useUnreadEventCount } from "../../state/notifications";
1516
import { EventMessage } from "../eventMessages/EventMessage";
1617
import { useIsEventStreamInstalled } from "./useIsEventStreamInstalled";
1718

1819
export const EventStream = () => {
1920
const isEventStreamInstalled = useIsEventStreamInstalled();
2021
const [location, setLocation] = useState<string | null>(null);
2122
const { enqueueSnackbar } = useSnackbar();
23+
const { incrementCount } = useUnreadEventCount();
2224
const asRole = useASAuthorizationStatus();
2325

2426
const { data, error: streamError } = useGetEventStream({
@@ -69,11 +71,13 @@ export const EventStream = () => {
6971

7072
const handleWebSocketMessage = useCallback(
7173
(event: MessageEvent) => {
74+
console.log("message");
7275
if (event.data instanceof Blob) {
7376
protoBlobToText(event.data)
7477
.then((textData) => {
7578
const message = getMessageFromEvent(textData);
7679
if (message) {
80+
incrementCount();
7781
enqueueSnackbar(<EventMessage message={message} />, {
7882
variant: "default",
7983
anchorOrigin: { horizontal: "right", vertical: "bottom" },
@@ -97,10 +101,19 @@ export const EventStream = () => {
97101
console.warn("Received non-Blob WebSocket message:", event.data);
98102
}
99103
},
100-
[enqueueSnackbar],
104+
[enqueueSnackbar, incrementCount],
101105
);
102106

103-
const wsUrl = eventStreamEnabled && asRole ? (location?.replace("ws", "wss") ?? null) : null;
107+
let wsUrl = null;
108+
if (eventStreamEnabled && asRole && location) {
109+
const url = new URL(location);
110+
url.protocol = "wss:";
111+
url.search = new URLSearchParams({
112+
// stream_from_timestamp: encodeURIComponent("2025-07-1T12:00:00Z"),
113+
stream_from_ordinal: "1",
114+
}).toString();
115+
wsUrl = url.toString();
116+
}
104117

105118
useWebSocket(wsUrl, {
106119
onOpen: handleWebSocketOpen,

src/layouts/navigation/UserMenu.tsx

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import { AccountCircle as AccountCircleIcon } from "@mui/icons-material";
2-
import { Box, Fade, IconButton, Paper, Popper, Tooltip } from "@mui/material";
2+
import { Badge, Box, Fade, IconButton, Paper, Popper, Tooltip } from "@mui/material";
33
import { bindPopper, bindToggle, usePopupState } from "material-ui-popup-state/hooks";
44

55
import { useKeycloakUser } from "../../hooks/useKeycloakUser";
6+
import { useUnreadEventCount } from "../../state/notifications";
67
import { UserMenuContent } from "./UserMenuContent";
78

89
/**
@@ -11,20 +12,32 @@ import { UserMenuContent } from "./UserMenuContent";
1112
export const UserMenu = () => {
1213
const popupState = usePopupState({ variant: "popper", popupId: "user-menu" });
1314
const { isLoading } = useKeycloakUser();
15+
const { count, resetCount } = useUnreadEventCount();
16+
17+
// Reset count when menu is opened
18+
const handleToggle = bindToggle(popupState);
19+
const handleMenuToggle = (event: React.MouseEvent<HTMLButtonElement>) => {
20+
if (!popupState.isOpen) {
21+
resetCount();
22+
}
23+
handleToggle.onClick(event);
24+
};
1425

1526
return (
1627
<>
1728
<Tooltip title="Account">
1829
<span>
19-
<IconButton
20-
color="inherit"
21-
disabled={isLoading}
22-
edge="end"
23-
{...bindToggle(popupState)}
24-
size="large"
25-
>
26-
<AccountCircleIcon />
27-
</IconButton>
30+
<Badge badgeContent={count} color="success" max={99}>
31+
<IconButton
32+
color="inherit"
33+
disabled={isLoading}
34+
edge="end"
35+
size="large"
36+
onClick={handleMenuToggle}
37+
>
38+
<AccountCircleIcon />
39+
</IconButton>
40+
</Badge>
2841
</span>
2942
</Tooltip>
3043

src/state/notifications.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { atom, useAtom } from "jotai";
2+
3+
/**
4+
* Atom to track the number of unread event notifications
5+
*/
6+
export const unreadEventCountAtom = atom(0);
7+
8+
/**
9+
* Hook to access and update the unread event count
10+
*/
11+
export const useUnreadEventCount = () => {
12+
const [count, setCount] = useAtom(unreadEventCountAtom);
13+
14+
const incrementCount = () => setCount((prev) => prev + 1);
15+
const resetCount = () => setCount(0);
16+
17+
return { count, incrementCount, resetCount };
18+
};

0 commit comments

Comments
 (0)