Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 9 additions & 15 deletions src/react/components/panels/Common/MediaDebugOverlay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { cn } from '@/ui';
import type { MediaDebugMetadata } from '@/core';

interface MediaDebugOverlayProps {
featureKey: string;
metadata: MediaDebugMetadata | null;
translationPrefix: 'panels.video.debug' | 'panels.image.debug';
className?: string;
Expand All @@ -27,7 +26,6 @@ function formatTimeline(metadata: MediaDebugMetadata): string | null {
}

export const MediaDebugOverlay: React.FC<MediaDebugOverlayProps> = ({
featureKey,
metadata,
translationPrefix,
className,
Expand All @@ -39,8 +37,6 @@ export const MediaDebugOverlay: React.FC<MediaDebugOverlayProps> = ({
}

const items = [
{ label: t(`${translationPrefix}.feature`), value: featureKey, breakAll: true },
{ label: t(`${translationPrefix}.dtype`), value: metadata.dtype },
{
label: t(`${translationPrefix}.fps`),
value: metadata.fps != null ? String(metadata.fps) : null,
Expand All @@ -64,27 +60,25 @@ export const MediaDebugOverlay: React.FC<MediaDebugOverlayProps> = ({
{ label: t(`${translationPrefix}.clipRange`), value: formatTimeline(metadata) },
].filter((item) => item.value);

if (items.length === 0) {
return null;
}

return (
<div
aria-hidden="true"
className={cn(
'pointer-events-none absolute left-2 top-2 z-10 flex max-w-[calc(100%-1rem)] items-center gap-2 overflow-hidden whitespace-nowrap rounded-md border border-white/10 bg-black/70 px-2 py-1 text-[10px] text-white opacity-0 shadow-lg backdrop-blur-sm transition-opacity duration-150 group-hover:opacity-100 group-focus-within:opacity-100',
'absolute left-2 top-2 z-10 max-h-[50%] max-w-[min(16rem,calc(100%-1rem))] overflow-y-auto rounded-md border border-white/10 bg-black/70 px-2.5 py-2 text-[11px] text-white opacity-0 shadow-lg backdrop-blur-sm transition-opacity duration-150 group-hover:opacity-100 group-focus-within:opacity-100',
className,
)}
>
<p className="shrink-0 font-semibold uppercase tracking-[0.12em] text-white/70">
{t(`${translationPrefix}.title`)}
</p>
<dl className="flex min-w-0 items-center gap-2 overflow-hidden border-l border-white/15 pl-2">
<dl className="flex flex-col gap-1">
{items.map((item) => (
<div
key={item.label}
className={cn('flex shrink-0 items-baseline gap-1', item.breakAll && 'min-w-0 shrink')}
className="grid grid-cols-[auto_1fr] items-baseline gap-x-3 gap-y-0"
>
<dt className="shrink-0 text-white/60">{item.label}</dt>
<dd
className={cn('font-mono tabular-nums', item.breakAll && 'min-w-0 max-w-48 truncate')}
>
<dt className="shrink-0 text-white/55">{item.label}</dt>
<dd className="min-w-0 break-all text-right font-mono tabular-nums text-white/95">
{item.value}
</dd>
</div>
Expand Down
6 changes: 1 addition & 5 deletions src/react/components/panels/ImagePanel/ImagePanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -278,11 +278,7 @@ export const ImagePanel: React.FC<ImagePanelProps> = ({ params }) => {

return (
<div className="group relative flex h-full w-full items-center justify-center overflow-hidden bg-black">
<MediaDebugOverlay
featureKey={featureKey}
metadata={debugMetadata}
translationPrefix="panels.image.debug"
/>
<MediaDebugOverlay metadata={debugMetadata} translationPrefix="panels.image.debug" />

{/* canvas 始终保留,帧更新直接 drawImage,无 React 渲染 */}
<canvas
Expand Down
6 changes: 1 addition & 5 deletions src/react/components/panels/VideoPanel/VideoPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -313,11 +313,7 @@ const VideoPanelContent: React.FC<VideoPanelProps> = ({ params }) => {

return (
<div className="group relative flex h-full w-full items-center justify-center overflow-hidden bg-black">
<MediaDebugOverlay
featureKey={featureKey}
metadata={debugMetadata}
translationPrefix="panels.video.debug"
/>
<MediaDebugOverlay metadata={debugMetadata} translationPrefix="panels.video.debug" />

{/* Video - 始终可见,无过渡效果 */}
<video
Expand Down
8 changes: 0 additions & 8 deletions src/react/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -468,10 +468,6 @@
"title": "Video Panel",
"placeholder": "Waiting for video file...",
"debug": {
"title": "Media debug",
"feature": "Feature",
"dtype": "DType",
"shape": "Shape",
"fps": "FPS",
"resolution": "Resolution",
"codec": "Codec",
Expand All @@ -487,10 +483,6 @@
"title": "Image Panel",
"placeholder": "Waiting for image file...",
"debug": {
"title": "Media debug",
"feature": "Feature",
"dtype": "DType",
"shape": "Shape",
"fps": "FPS",
"resolution": "Resolution",
"codec": "Codec",
Expand Down
8 changes: 0 additions & 8 deletions src/react/locales/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -465,10 +465,6 @@
"title": "视频面板",
"placeholder": "等待加载视频文件...",
"debug": {
"title": "媒体调试信息",
"feature": "Feature",
"dtype": "类型",
"shape": "Shape",
"fps": "FPS",
"resolution": "分辨率",
"codec": "编码",
Expand All @@ -484,10 +480,6 @@
"title": "图像面板",
"placeholder": "等待加载图像文件...",
"debug": {
"title": "媒体调试信息",
"feature": "Feature",
"dtype": "类型",
"shape": "Shape",
"fps": "FPS",
"resolution": "分辨率",
"codec": "编码",
Expand Down
9 changes: 6 additions & 3 deletions tests/media-debug-overlay.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,12 @@ vi.mock('react-i18next', () => ({
}));

describe('MediaDebugOverlay', () => {
it('renders hover-only overlay classes and metadata rows', () => {
it('renders vertical hover-only overlay with media metadata rows', () => {
const markup = renderToStaticMarkup(
React.createElement(
'div',
{ className: 'group' },
React.createElement(MediaDebugOverlay, {
featureKey: 'observation.images.cam',
translationPrefix: 'panels.video.debug',
metadata: {
dtype: 'video',
Expand All @@ -38,9 +37,13 @@ describe('MediaDebugOverlay', () => {
);

expect(markup).toContain('group-hover:opacity-100');
expect(markup).toContain('observation.images.cam');
expect(markup).toContain('flex-col');
expect(markup).toContain('1280 x 720');
expect(markup).toContain('h264');
expect(markup).toContain('0.00s - 1.50s');
expect(markup).not.toContain('observation.images.cam');
expect(markup).not.toContain('panels.video.debug.feature');
expect(markup).not.toContain('panels.video.debug.dtype');
expect(markup).not.toContain('panels.video.debug.title');
});
});