feat(chat): port chat widget components from Dart to React

This commit is contained in:
2026-06-09 20:19:52 +08:00
parent 199a14650e
commit 109a3e3855
48 changed files with 2463 additions and 382 deletions
@@ -0,0 +1,49 @@
"use client";
/**
* FullscreenImageViewer 全屏图片查看器
*
* 原始 Dart: lib/ui/chat/widgets/fullscreen_image_viewer.dart76 行)
*
* 行为:
* - 全屏黑色背景 + 图片居中(contain)
* - 点击空白 / 下滑手势 → 关闭
* - 双指缩放(CSS `touch-action: pinch-zoom`
*/
import { useEffect } from "react";
import styles from "./fullscreen-image-viewer.module.css";
export interface FullscreenImageViewerProps {
imageUrl: string;
onClose: () => void;
}
export function FullscreenImageViewer({ imageUrl, onClose }: FullscreenImageViewerProps) {
useEffect(() => {
const handleKey = (e: KeyboardEvent) => {
if (e.key === "Escape") onClose();
};
document.addEventListener("keydown", handleKey);
return () => document.removeEventListener("keydown", handleKey);
}, [onClose]);
return (
<div
className={styles.viewer}
onClick={onClose}
role="dialog"
aria-label="Fullscreen image"
>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src={imageUrl.startsWith("data:") || imageUrl.startsWith("http") ? imageUrl : `data:image/png;base64,${imageUrl}`}
alt=""
onError={(e) => {
(e.currentTarget as HTMLImageElement).style.display = "none";
(e.currentTarget.parentElement as HTMLElement).innerHTML =
'<div class="error">🖼</div>';
}}
/>
</div>
);
}