Size HTML firmware previews by board (480x320 for 3.5).

EOF

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-10-23 18:45:24 +08:00
parent 2dd97f95ad
commit cf617592d4
4 changed files with 26 additions and 9 deletions

View File

@@ -31,7 +31,13 @@ export function FirmwareCard({
: "border-[var(--line)] bg-[rgba(0,0,0,0.22)] hover:-translate-y-0.5 hover:border-[rgba(240,197,10,0.35)] hover:bg-[rgba(240,197,10,0.04)]" : "border-[var(--line)] bg-[rgba(0,0,0,0.22)] hover:-translate-y-0.5 hover:border-[rgba(240,197,10,0.35)] hover:bg-[rgba(240,197,10,0.04)]"
)} )}
> >
<div className="relative aspect-[4/3] w-full overflow-hidden border-b border-[var(--line)]"> <div
className={
fw.boardId === "esp32-3248s035"
? "relative aspect-[3/2] w-full overflow-hidden border-b border-[var(--line)]"
: "relative aspect-[4/3] w-full overflow-hidden border-b border-[var(--line)]"
}
>
<FirmwarePreview fw={fw} /> <FirmwarePreview fw={fw} />
<div className="pointer-events-none absolute bottom-2 left-2 flex gap-1"> <div className="pointer-events-none absolute bottom-2 left-2 flex gap-1">
{hasPreview && ( {hasPreview && (

View File

@@ -36,7 +36,13 @@ export function FirmwareDetail({
</h3> </h3>
</div> </div>
<div className="aspect-[4/3] w-full border-b border-[var(--line)] bg-black/40"> <div
className={
fw.boardId === "esp32-3248s035"
? "aspect-[3/2] w-full border-b border-[var(--line)] bg-black/40"
: "aspect-[4/3] w-full border-b border-[var(--line)] bg-black/40"
}
>
{fw.media.preview ? ( {fw.media.preview ? (
<FirmwarePreview fw={fw} /> <FirmwarePreview fw={fw} />
) : fw.media.video ? ( ) : fw.media.video ? (

View File

@@ -3,12 +3,10 @@
import { useEffect, useRef, useState } from "react"; import { useEffect, useRef, useState } from "react";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import type { FirmwareInfo } from "@/lib/firmware"; import type { FirmwareInfo } from "@/lib/firmware";
import { boardPreviewSize } from "@/lib/boards";
import { sensorMediaForProject } from "@/lib/sensor-media"; import { sensorMediaForProject } from "@/lib/sensor-media";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
const SCREEN_W = 320;
const SCREEN_H = 240;
type Tab = "ui" | "sensor"; type Tab = "ui" | "sensor";
/** On-device HTML UI mock + optional hardware still, switchable via tabs. */ /** On-device HTML UI mock + optional hardware still, switchable via tabs. */
@@ -24,6 +22,7 @@ export function FirmwarePreview({
const t = useTranslations("firmware"); const t = useTranslations("firmware");
const hostRef = useRef<HTMLDivElement>(null); const hostRef = useRef<HTMLDivElement>(null);
const [scale, setScale] = useState(1); const [scale, setScale] = useState(1);
const { w: screenW, h: screenH } = boardPreviewSize(fw.boardId);
const sensor = sensorMediaForProject(fw.project); const sensor = sensorMediaForProject(fw.project);
const hasUi = Boolean(fw.media.preview); const hasUi = Boolean(fw.media.preview);
const [tab, setTab] = useState<Tab>(hasUi ? "ui" : "sensor"); const [tab, setTab] = useState<Tab>(hasUi ? "ui" : "sensor");
@@ -39,14 +38,14 @@ export function FirmwarePreview({
const update = () => { const update = () => {
const { width, height } = el.getBoundingClientRect(); const { width, height } = el.getBoundingClientRect();
if (width <= 0 || height <= 0) return; if (width <= 0 || height <= 0) return;
setScale(Math.min(width / SCREEN_W, height / SCREEN_H)); setScale(Math.min(width / screenW, height / screenH));
}; };
update(); update();
const ro = new ResizeObserver(update); const ro = new ResizeObserver(update);
ro.observe(el); ro.observe(el);
return () => ro.disconnect(); return () => ro.disconnect();
}, [fw.media.preview, tab]); }, [fw.media.preview, tab, screenW, screenH]);
const showTabs = hasUi && Boolean(sensor); const showTabs = hasUi && Boolean(sensor);
@@ -113,8 +112,8 @@ export function FirmwarePreview({
<iframe <iframe
title={title || `${fw.name} UI preview`} title={title || `${fw.name} UI preview`}
src={fw.media.preview!} src={fw.media.preview!}
width={SCREEN_W} width={screenW}
height={SCREEN_H} height={screenH}
loading="lazy" loading="lazy"
sandbox="allow-scripts" sandbox="allow-scripts"
tabIndex={-1} tabIndex={-1}

View File

@@ -60,3 +60,9 @@ export function resolveBoardId(boardField: string | null | undefined): string {
export function getBoard(id: string): BoardDefinition | undefined { export function getBoard(id: string): BoardDefinition | undefined {
return BOARDS.find((b) => b.id === id); return BOARDS.find((b) => b.id === id);
} }
/** Logical UI resolution used by HTML firmware previews (matches UX/UY). */
export function boardPreviewSize(boardId: string): { w: number; h: number } {
if (boardId === "esp32-3248s035") return { w: 480, h: 320 };
return { w: 320, h: 240 };
}