feat: add marker in recent events to show which events are new
Build / build (push) Successful in 2m10s Details
Test / test (push) Successful in 38s Details

This commit is contained in:
Ash Keel 2024-04-25 22:03:41 +02:00
parent 5bdc05ced8
commit a1fab34a70
No known key found for this signature in database
GPG Key ID: 53A9E9A6035DD109
4 changed files with 102 additions and 18 deletions

View File

@ -267,6 +267,7 @@
"header": "Recent events",
"warning": "This section only contains events that happened while {{APPNAME}} was open, so only use it for recent stuff",
"anonymous": "An anonymous viewer",
"marker": "Events from previous sessions",
"events": {
"follow": "<n>{{name}}</n> followed you",
"redemption": "<n>{{name}}</n> redeemed <r>{{reward}}</r>",

View File

@ -152,6 +152,7 @@
"anonymous": "Uno spettatore anonimo",
"header": "Eventi recenti",
"warning": "Questa sezione contiene solo gli eventi accaduti mentre {{APPNAME}} era aperto, quindi utilizzala solo per cose recenti",
"marker": "Eventi delle sessioni precedenti",
"events": {
"channel-updated": "Informazioni stream modificate",
"cheered": "<n>{{name}}</n> ti ha tifato con <b>{{bits}} bit</b>",

View File

@ -1,8 +1,7 @@
import { ClipboardCopyIcon, Cross2Icon, SizeIcon } from '@radix-ui/react-icons';
import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useSelector } from 'react-redux';
import { RootState } from 'src/store';
import { useAppSelector } from 'src/store';
import * as DialogPrimitive from '@radix-ui/react-dialog';
import { delay } from '~/lib/time';
import { ProcessedLogEntry } from '~/store/logging/reducer';
@ -294,12 +293,14 @@ export function LogItem({ data, expandDefault }: LogItemProps) {
const details = Object.entries(data.data).filter(([key]) => key.length > 1);
const [copied, setCopied] = useState(false);
const [showDetails, setShowDetails] = useState(expandDefault ?? false);
const copyToClipboard = async () => {
await navigator.clipboard.writeText(JSON.stringify(data.data));
setCopied(true);
await delay(2000);
setCopied(false);
};
return (
<LogEntryContainer level={levelStyle}>
<LogTime level={levelStyle}>{formatTime(data.time)}</LogTime>
@ -355,7 +356,7 @@ interface LogDialogProps {
}
function LogDialog({ initialFilter }: LogDialogProps) {
const logEntries = useSelector((state: RootState) => state.logging.messages);
const logEntries = useAppSelector((state) => state.logging.messages);
const [filter, setFilter] = useState({
...emptyFilter,
...Object.fromEntries(initialFilter.map((f) => [f, true])),
@ -440,7 +441,7 @@ function LogDialog({ initialFilter }: LogDialogProps) {
}
function LogViewer() {
const logEntries = useSelector((state: RootState) => state.logging.messages);
const logEntries = useAppSelector((state) => state.logging.messages);
const [activeDialog, setActiveDialog] = useState<LogLevel>(null);
const count = logEntries.reduce(

View File

@ -16,7 +16,11 @@ import { modules } from '~/store/api/reducer';
import * as HoverCard from '@radix-ui/react-hover-card';
import { useEffect, useState } from 'react';
import { main } from '@wailsapp/go/models';
import { GetProblems, GetTwitchAuthURL } from '@wailsapp/go/main/App';
import {
GetLastLogs,
GetProblems,
GetTwitchAuthURL,
} from '@wailsapp/go/main/App';
import { BrowserOpenURL } from '@wailsapp/runtime/runtime';
import {
PageContainer,
@ -362,8 +366,64 @@ function TwitchEvent({ data }: { data: EventSubNotification }) {
);
}
function TwitchEventLog({ events }: { events: EventSubNotification[] }) {
const block = {
content: '""',
display: 'inline-block',
width: '1rem',
height: '0.1rem',
margin: '0 0.5rem',
backgroundColor: '$gray9',
};
const SessionMarker = styled('div', {
textTransform: 'uppercase',
fontWeight: '600',
fontSize: '0.75rem',
color: '$gray11',
margin: '0.25rem',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
'&::before': block,
'&::after': block,
});
interface TwitchEventLogProps {
events: EventSubNotification[];
dateMarker: number;
}
type EventItem =
| { type: 'marker' }
| { type: 'event'; event: EventSubNotification };
function TwitchEventLog({ events, dateMarker }: TwitchEventLogProps) {
const { t } = useTranslation();
// Filter only supported events and order them by date
const orderedEvents: EventItem[] = events
.filter((ev) => supportedMessages.includes(ev.subscription.type))
.sort((a, b) =>
a.date && b.date
? Date.parse(b.date) - Date.parse(a.date)
: Date.parse(b.subscription.created_at) -
Date.parse(a.subscription.created_at),
)
.map((ev) => ({ type: 'event', event: ev }));
// Add marker
if (dateMarker) {
const index = orderedEvents.findIndex((ev) => {
if (ev.type !== 'event') {
return false;
}
return Date.parse(ev.event.date) < dateMarker;
});
if (index >= 0) {
orderedEvents.splice(index, 0, { type: 'marker' });
}
}
return (
<>
<HoverCard.Root>
@ -383,17 +443,23 @@ function TwitchEventLog({ events }: { events: EventSubNotification[] }) {
</HoverCard.Root>
<Scrollbar vertical={true} viewport={{ maxHeight: '250px' }}>
<EventListContainer>
{events
.filter((ev) => supportedMessages.includes(ev.subscription.type))
.sort((a, b) =>
a.date && b.date
? Date.parse(b.date) - Date.parse(a.date)
: Date.parse(b.subscription.created_at) -
Date.parse(a.subscription.created_at),
)
.map((ev) => (
<TwitchEvent key={eventSubKeyFunction(ev)} data={ev} />
))}
{orderedEvents.map((ev) => {
switch (ev.type) {
case 'marker':
return (
<SessionMarker key="marker">
{t('pages.dashboard.twitch-events.marker')}
</SessionMarker>
);
default:
return (
<TwitchEvent
key={eventSubKeyFunction(ev.event)}
data={ev.event}
/>
);
}
})}
</EventListContainer>
</Scrollbar>
</>
@ -439,6 +505,19 @@ function TwitchSection() {
const twitchInfo = useLiveKey<StreamInfo[]>('twitch/stream-info');
const kv = useAppSelector((state) => state.api.client);
const [twitchEvents, setTwitchEvents] = useState<EventSubNotification[]>([]);
const [oldestLog, setOldestLog] = useState(Date.now());
useEffect(() => {
GetLastLogs().then((res) => {
// Get oldest log entry
const oldest = res.reduce<number>((acc, log) => {
const parsedDate = Date.parse(log.time);
return parsedDate < acc ? parsedDate : acc;
}, Date.now());
setOldestLog(oldest);
});
}, []);
const keyfn = (ev: EventSubNotification) => JSON.stringify(ev);
@ -493,7 +572,9 @@ function TwitchSection() {
) : (
<TextBlock>{t('pages.dashboard.not-live')}</TextBlock>
)}
{twitchEvents ? <TwitchEventLog events={twitchEvents} /> : null}
{twitchEvents ? (
<TwitchEventLog events={twitchEvents} dateMarker={oldestLog} />
) : null}
</>
);
}