From b083da50b1399aae90b41f5f9c2f60e3baa2f89a Mon Sep 17 00:00:00 2001 From: "DESKTOP-PUHFO60\\dsx2016" Date: Fri, 23 Oct 2026 16:09:20 +0800 Subject: [PATCH] Add Hardware tab with sensor stills next to UI previews. Map each firmware project to a Commons or original module photo for local catalog browsing. Co-authored-by: Cursor --- README.md | 2 + components/firmware-preview.tsx | 138 ++++++++++++++++++++++-------- lib/sensor-media.ts | 86 +++++++++++++++++++ messages/en.json | 4 +- messages/zh.json | 4 +- public/sensors/ATTRIBUTION.md | 36 ++++++++ public/sensors/bh1750.jpg | Bin 0 -> 246650 bytes public/sensors/bluetooth_icon.svg | Bin 0 -> 55409 bytes public/sensors/button.jpg | Bin 0 -> 41992 bytes public/sensors/buzzer.jpg | Bin 0 -> 217815 bytes public/sensors/dht.jpg | Bin 0 -> 38753 bytes public/sensors/lcd1602.jpg | Bin 0 -> 84144 bytes public/sensors/ld2420.jpg | Bin 0 -> 231326 bytes public/sensors/led.jpg | Bin 0 -> 81673 bytes public/sensors/mic.jpg | Bin 0 -> 76689 bytes public/sensors/microsd.jpg | Bin 0 -> 51190 bytes public/sensors/pir.jpg | Bin 0 -> 172846 bytes public/sensors/rgb.jpg | Bin 0 -> 33262 bytes public/sensors/sd.jpg | Bin 0 -> 130078 bytes public/sensors/sgp30.jpg | Bin 0 -> 235877 bytes public/sensors/sound_sensor.jpg | Bin 0 -> 215821 bytes public/sensors/speaker.jpg | Bin 0 -> 106872 bytes public/sensors/tm1637.jpg | Bin 0 -> 239568 bytes public/sensors/ttp223.jpg | Bin 0 -> 268384 bytes public/sensors/white_led.jpg | Bin 0 -> 233684 bytes public/sensors/wifi_icon.svg | Bin 0 -> 23899 bytes 26 files changed, 232 insertions(+), 38 deletions(-) create mode 100644 lib/sensor-media.ts create mode 100644 public/sensors/ATTRIBUTION.md create mode 100644 public/sensors/bh1750.jpg create mode 100644 public/sensors/bluetooth_icon.svg create mode 100644 public/sensors/button.jpg create mode 100644 public/sensors/buzzer.jpg create mode 100644 public/sensors/dht.jpg create mode 100644 public/sensors/lcd1602.jpg create mode 100644 public/sensors/ld2420.jpg create mode 100644 public/sensors/led.jpg create mode 100644 public/sensors/mic.jpg create mode 100644 public/sensors/microsd.jpg create mode 100644 public/sensors/pir.jpg create mode 100644 public/sensors/rgb.jpg create mode 100644 public/sensors/sd.jpg create mode 100644 public/sensors/sgp30.jpg create mode 100644 public/sensors/sound_sensor.jpg create mode 100644 public/sensors/speaker.jpg create mode 100644 public/sensors/tm1637.jpg create mode 100644 public/sensors/ttp223.jpg create mode 100644 public/sensors/white_led.jpg create mode 100644 public/sensors/wifi_icon.svg diff --git a/README.md b/README.md index 7dec6c9..2d794fa 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,8 @@ After rebuilding a project, run its `firmware\export_from_build.ps1`, then click Preferred card preview: **`media/preview.html`** — HTML recreation of the on-device LVGL UI (320×240). Auto-detected if present. +Cards also offer a **Hardware** tab (sensor / module still). Mapping lives in `lib/sensor-media.ts`; images under `public/sensors/` (see `ATTRIBUTION.md`). + Optional `meta.json` beside the `.bin` files: ```json diff --git a/components/firmware-preview.tsx b/components/firmware-preview.tsx index c27339c..4ac2774 100644 --- a/components/firmware-preview.tsx +++ b/components/firmware-preview.tsx @@ -1,13 +1,17 @@ "use client"; import { useEffect, useRef, useState } from "react"; +import { useTranslations } from "next-intl"; import type { FirmwareInfo } from "@/lib/firmware"; +import { sensorMediaForProject } from "@/lib/sensor-media"; import { cn } from "@/lib/utils"; const SCREEN_W = 320; const SCREEN_H = 240; -/** Renders HTML on-device UI mock (preferred) — never uses raster covers. */ +type Tab = "ui" | "sensor"; + +/** On-device HTML UI mock + optional hardware still, switchable via tabs. */ export function FirmwarePreview({ fw, className, @@ -17,12 +21,20 @@ export function FirmwarePreview({ className?: string; title?: string; }) { + const t = useTranslations("firmware"); const hostRef = useRef(null); const [scale, setScale] = useState(1); + const sensor = sensorMediaForProject(fw.project); + const hasUi = Boolean(fw.media.preview); + const [tab, setTab] = useState(hasUi ? "ui" : "sensor"); + + useEffect(() => { + setTab(hasUi ? "ui" : sensor ? "sensor" : "ui"); + }, [fw.id, hasUi, sensor]); useEffect(() => { const el = hostRef.current; - if (!el) return; + if (!el || tab !== "ui") return; const update = () => { const { width, height } = el.getBoundingClientRect(); @@ -34,34 +46,9 @@ export function FirmwarePreview({ const ro = new ResizeObserver(update); ro.observe(el); return () => ro.disconnect(); - }, [fw.media.preview]); + }, [fw.media.preview, tab]); - if (fw.media.preview) { - return ( -
-