You've already forked Nano-Banana-AI-Image-Editor
优化 调整了历史记录预览窗口的实现
This commit is contained in:
26
src/App.tsx
26
src/App.tsx
@@ -24,6 +24,8 @@ function AppContent() {
|
|||||||
|
|
||||||
const { showPromptPanel, setShowPromptPanel, setShowHistory } = useAppStore();
|
const { showPromptPanel, setShowPromptPanel, setShowHistory } = useAppStore();
|
||||||
const [hoveredImage, setHoveredImage] = useState<{url: string, title: string, width?: number, height?: number} | null>(null);
|
const [hoveredImage, setHoveredImage] = useState<{url: string, title: string, width?: number, height?: number} | null>(null);
|
||||||
|
const [previewPosition, setPreviewPosition] = useState<{x: number, y: number} | null>(null);
|
||||||
|
const [isPreviewVisible, setIsPreviewVisible] = useState(false);
|
||||||
|
|
||||||
// 在挂载时初始化IndexedDB并清理base64数据
|
// 在挂载时初始化IndexedDB并清理base64数据
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -73,6 +75,19 @@ function AppContent() {
|
|||||||
return () => clearInterval(interval);
|
return () => clearInterval(interval);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
// 控制预览窗口的显示和隐藏动画
|
||||||
|
useEffect(() => {
|
||||||
|
if (hoveredImage) {
|
||||||
|
// 延迟一小段时间后设置为可见,以触发动画
|
||||||
|
const timer = setTimeout(() => {
|
||||||
|
setIsPreviewVisible(true);
|
||||||
|
}, 10);
|
||||||
|
return () => clearTimeout(timer);
|
||||||
|
} else {
|
||||||
|
setIsPreviewVisible(false);
|
||||||
|
}
|
||||||
|
}, [hoveredImage]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="h-screen bg-gray-50 text-gray-900 flex flex-col font-sans">
|
<div className="h-screen bg-gray-50 text-gray-900 flex flex-col font-sans">
|
||||||
<div className="card card-lg rounded-none">
|
<div className="card card-lg rounded-none">
|
||||||
@@ -92,7 +107,7 @@ function AppContent() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="flex-shrink-0">
|
<div className="flex-shrink-0">
|
||||||
<div className="h-full card card-lg">
|
<div className="h-full card card-lg">
|
||||||
<HistoryPanel setHoveredImage={setHoveredImage} />
|
<HistoryPanel setHoveredImage={setHoveredImage} setPreviewPosition={setPreviewPosition} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -102,7 +117,14 @@ function AppContent() {
|
|||||||
<div
|
<div
|
||||||
className="fixed inset-0 z-[99999] flex items-center justify-center pointer-events-none"
|
className="fixed inset-0 z-[99999] flex items-center justify-center pointer-events-none"
|
||||||
>
|
>
|
||||||
<div className="bg-white rounded-xl shadow-2xl border border-gray-300 overflow-hidden max-w-2xl max-h-[80vh] flex flex-col">
|
<div
|
||||||
|
className="bg-white rounded-xl shadow-2xl border border-gray-300 overflow-hidden max-w-2xl max-h-[80vh] flex flex-col transition-all duration-200 ease-out"
|
||||||
|
style={{
|
||||||
|
transform: isPreviewVisible ? 'scale(1)' : 'scale(0.8)',
|
||||||
|
opacity: isPreviewVisible ? 1 : 0,
|
||||||
|
transformOrigin: previewPosition ? `${previewPosition.x}px ${previewPosition.y}px` : 'center'
|
||||||
|
}}
|
||||||
|
>
|
||||||
<div className="bg-gray-900 text-white text-sm p-3 truncate font-medium">
|
<div className="bg-gray-900 text-white text-sm p-3 truncate font-medium">
|
||||||
{hoveredImage.title}
|
{hoveredImage.title}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -9,7 +9,10 @@ import { useIndexedDBListener } from '../hooks/useIndexedDBListener';
|
|||||||
import { DayPicker } from 'react-day-picker';
|
import { DayPicker } from 'react-day-picker';
|
||||||
import zhCN from 'react-day-picker/dist/locale/zh-CN';
|
import zhCN from 'react-day-picker/dist/locale/zh-CN';
|
||||||
|
|
||||||
export const HistoryPanel: React.FC<{ setHoveredImage: (image: {url: string, title: string, width?: number, height?: number} | null) => void }> = ({ setHoveredImage }) => {
|
export const HistoryPanel: React.FC<{
|
||||||
|
setHoveredImage: (image: {url: string, title: string, width?: number, height?: number} | null) => void,
|
||||||
|
setPreviewPosition?: (position: {x: number, y: number} | null) => void
|
||||||
|
}> = ({ setHoveredImage, setPreviewPosition }) => {
|
||||||
const {
|
const {
|
||||||
currentProject,
|
currentProject,
|
||||||
canvasImage,
|
canvasImage,
|
||||||
@@ -534,6 +537,10 @@ export const HistoryPanel: React.FC<{ setHoveredImage: (image: {url: string, tit
|
|||||||
width: img.width,
|
width: img.width,
|
||||||
height: img.height
|
height: img.height
|
||||||
});
|
});
|
||||||
|
// 传递鼠标位置信息给App组件
|
||||||
|
if (setPreviewPosition) {
|
||||||
|
setPreviewPosition({ x: e.clientX, y: e.clientY });
|
||||||
|
}
|
||||||
};
|
};
|
||||||
img.onerror = (error) => {
|
img.onerror = (error) => {
|
||||||
console.error('图像加载失败:', error);
|
console.error('图像加载失败:', error);
|
||||||
@@ -544,6 +551,10 @@ export const HistoryPanel: React.FC<{ setHoveredImage: (image: {url: string, tit
|
|||||||
width: 0,
|
width: 0,
|
||||||
height: 0
|
height: 0
|
||||||
});
|
});
|
||||||
|
// 传递鼠标位置信息给App组件
|
||||||
|
if (setPreviewPosition) {
|
||||||
|
setPreviewPosition({ x: e.clientX, y: e.clientY });
|
||||||
|
}
|
||||||
};
|
};
|
||||||
img.src = imageUrl;
|
img.src = imageUrl;
|
||||||
}
|
}
|
||||||
@@ -553,6 +564,9 @@ export const HistoryPanel: React.FC<{ setHoveredImage: (image: {url: string, tit
|
|||||||
}}
|
}}
|
||||||
onMouseLeave={() => {
|
onMouseLeave={() => {
|
||||||
setHoveredImage(null);
|
setHoveredImage(null);
|
||||||
|
if (setPreviewPosition) {
|
||||||
|
setPreviewPosition(null);
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{(() => {
|
{(() => {
|
||||||
@@ -631,6 +645,10 @@ export const HistoryPanel: React.FC<{ setHoveredImage: (image: {url: string, tit
|
|||||||
width: img.width,
|
width: img.width,
|
||||||
height: img.height
|
height: img.height
|
||||||
});
|
});
|
||||||
|
// 传递鼠标位置信息给App组件
|
||||||
|
if (setPreviewPosition) {
|
||||||
|
setPreviewPosition({ x: e.clientX, y: e.clientY });
|
||||||
|
}
|
||||||
};
|
};
|
||||||
img.onerror = (error) => {
|
img.onerror = (error) => {
|
||||||
console.error('图像加载失败:', error);
|
console.error('图像加载失败:', error);
|
||||||
@@ -641,6 +659,10 @@ export const HistoryPanel: React.FC<{ setHoveredImage: (image: {url: string, tit
|
|||||||
width: 0,
|
width: 0,
|
||||||
height: 0
|
height: 0
|
||||||
});
|
});
|
||||||
|
// 传递鼠标位置信息给App组件
|
||||||
|
if (setPreviewPosition) {
|
||||||
|
setPreviewPosition({ x: e.clientX, y: e.clientY });
|
||||||
|
}
|
||||||
};
|
};
|
||||||
img.src = imageUrl;
|
img.src = imageUrl;
|
||||||
}
|
}
|
||||||
@@ -650,6 +672,9 @@ export const HistoryPanel: React.FC<{ setHoveredImage: (image: {url: string, tit
|
|||||||
}}
|
}}
|
||||||
onMouseLeave={() => {
|
onMouseLeave={() => {
|
||||||
setHoveredImage(null);
|
setHoveredImage(null);
|
||||||
|
if (setPreviewPosition) {
|
||||||
|
setPreviewPosition(null);
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{(() => {
|
{(() => {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ const UPLOAD_URL = import.meta.env.VITE_UPLOAD_API
|
|||||||
const uploadCache = new Map<string, UploadResult>()
|
const uploadCache = new Map<string, UploadResult>()
|
||||||
|
|
||||||
// 缓存配置
|
// 缓存配置
|
||||||
const MAX_CACHE_SIZE = 50 // 减少最大缓存条目数
|
const MAX_CACHE_SIZE = 20 // 减少最大缓存条目数
|
||||||
const CACHE_EXPIRY_TIME = 15 * 60 * 1000 // 缓存过期时间15分钟
|
const CACHE_EXPIRY_TIME = 15 * 60 * 1000 // 缓存过期时间15分钟
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user