diff --git a/packages/trace-viewer/src/ui/attachmentsTab.css b/packages/trace-viewer/src/ui/attachmentsTab.css index c2455fc3c5..7d487bb3f2 100644 --- a/packages/trace-viewer/src/ui/attachmentsTab.css +++ b/packages/trace-viewer/src/ui/attachmentsTab.css @@ -55,3 +55,11 @@ a.codicon-cloud-download:hover{ background-color: var(--vscode-list-inactiveSelectionBackground) } + +.yellow-flash { + animation: yellowflash-bg 2s; +} +@keyframes yellowflash-bg { + from { background: var(--vscode-peekViewEditor-matchHighlightBackground); } + to { background: transparent; } +} diff --git a/packages/trace-viewer/src/ui/attachmentsTab.tsx b/packages/trace-viewer/src/ui/attachmentsTab.tsx index cf9ed2e681..31a9355810 100644 --- a/packages/trace-viewer/src/ui/attachmentsTab.tsx +++ b/packages/trace-viewer/src/ui/attachmentsTab.tsx @@ -17,7 +17,7 @@ import * as React from 'react'; import './attachmentsTab.css'; import { ImageDiffView } from '@web/shared/imageDiffView'; -import type { ActionTraceEventInContext, MultiTraceModel } from './modelUtil'; +import type { MultiTraceModel } from './modelUtil'; import { PlaceholderPanel } from './placeholderPanel'; import type { AfterActionTraceEventAttachment } from '@trace/trace'; import { CodeMirrorWrapper, lineHeight } from '@web/components/codeMirrorWrapper'; @@ -26,15 +26,27 @@ import { Expandable } from '@web/components/expandable'; import { linkifyText } from '@web/renderUtils'; import { clsx } from '@web/uiUtils'; +// flash is retriggered whenever the value changes +function useFlash(flash: any | undefined) { + const [flashState, setFlashState] = React.useState(false); + React.useEffect(() => { + if (flash) { + setFlashState(true); + const timeout = setTimeout(() => setFlashState(false), 1000); + return () => clearTimeout(timeout); + } + }, [flash]); + return flashState; +} + type Attachment = AfterActionTraceEventAttachment & { traceUrl: string }; type ExpandableAttachmentProps = { attachment: Attachment; - reveal: boolean; - highlight: boolean; + reveal?: any; }; -const ExpandableAttachment: React.FunctionComponent = ({ attachment, reveal, highlight }) => { +const ExpandableAttachment: React.FunctionComponent = ({ attachment, reveal }) => { const [expanded, setExpanded] = React.useState(false); const [attachmentText, setAttachmentText] = React.useState(null); const [placeholder, setPlaceholder] = React.useState(null); @@ -47,6 +59,7 @@ const ExpandableAttachment: React.FunctionComponent = if (reveal) ref.current?.scrollIntoView({ behavior: 'smooth' }); }, [reveal]); + const flash = useFlash(reveal); React.useEffect(() => { if (expanded && attachmentText === null && placeholder === null) { @@ -66,14 +79,14 @@ const ExpandableAttachment: React.FunctionComponent = }, [attachmentText]); const title = - {linkifyText(attachment.name)} + {linkifyText(attachment.name)} {hasContent && download} ; if (!isTextAttachment || !hasContent) return
{title}
; - return <> + return
{placeholder && {placeholder}} @@ -87,14 +100,13 @@ const ExpandableAttachment: React.FunctionComponent = wrapLines={false}>
} - ; + ; }; export const AttachmentsTab: React.FunctionComponent<{ model: MultiTraceModel | undefined, - selectedAction: ActionTraceEventInContext | undefined, revealedAttachment?: AfterActionTraceEventAttachment, -}> = ({ model, selectedAction, revealedAttachment }) => { +}> = ({ model, revealedAttachment }) => { const { diffMap, screenshots, attachments } = React.useMemo(() => { const attachments = new Set(); const screenshots = new Set(); @@ -153,8 +165,7 @@ export const AttachmentsTab: React.FunctionComponent<{ return
isEqualAttachment(a, selected)) ?? false} - reveal={!!revealedAttachment && isEqualAttachment(a, revealedAttachment)} + reveal={(!!revealedAttachment && isEqualAttachment(a, revealedAttachment)) ? revealedAttachment : undefined} />
; })} diff --git a/packages/trace-viewer/src/ui/workbench.tsx b/packages/trace-viewer/src/ui/workbench.tsx index c6fcd7e54c..423522b0f8 100644 --- a/packages/trace-viewer/src/ui/workbench.tsx +++ b/packages/trace-viewer/src/ui/workbench.tsx @@ -148,7 +148,7 @@ export const Workbench: React.FunctionComponent<{ const revealAttachment = React.useCallback((attachment: AfterActionTraceEventAttachment) => { selectPropertiesTab('attachments'); - setRevealedAttachment(attachment); + setRevealedAttachment({ ...attachment }); // copy to force re-render }, [selectPropertiesTab]); React.useEffect(() => { @@ -238,7 +238,7 @@ export const Workbench: React.FunctionComponent<{ id: 'attachments', title: 'Attachments', count: attachments.length, - render: () => + render: () => }; const tabs: TabbedPaneTabModel[] = [