feat(chat): port chat widget components from Dart to React
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
"use client";
|
||||
/**
|
||||
* FullscreenImageViewer 全屏图片查看器
|
||||
*
|
||||
* 原始 Dart: lib/ui/chat/widgets/fullscreen_image_viewer.dart(76 行)
|
||||
*
|
||||
* 行为:
|
||||
* - 全屏黑色背景 + 图片居中(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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user