mirror of
https://github.com/stackblitz/bolt.new
synced 2025-03-12 06:51:11 +00:00
merge main into image
This commit is contained in:
parent
a936c5a990
commit
6ffcdd8b3c
@ -1 +1 @@
|
|||||||
{ "commit": "4cfabd94ee8ab91a1466cf644dbf9c74ab1324d7" }
|
{ "commit": "a936c5a99036e0ea65c976e19b3bdb39f8d7cd40" }
|
||||||
|
@ -289,14 +289,20 @@ export const Preview = memo(() => {
|
|||||||
>
|
>
|
||||||
{activePreview ? (
|
{activePreview ? (
|
||||||
<>
|
<>
|
||||||
<iframe ref={iframeRef} title="preview" className="border-none w-full h-full bg-white" src={iframeUrl} allowFullScreen />
|
<iframe
|
||||||
|
ref={iframeRef}
|
||||||
|
title="preview"
|
||||||
|
className="border-none w-full h-full bg-white"
|
||||||
|
src={iframeUrl}
|
||||||
|
allowFullScreen
|
||||||
|
/>
|
||||||
<ScreenshotSelector
|
<ScreenshotSelector
|
||||||
isSelectionMode={isSelectionMode}
|
isSelectionMode={isSelectionMode}
|
||||||
setIsSelectionMode={setIsSelectionMode}
|
setIsSelectionMode={setIsSelectionMode}
|
||||||
containerRef={iframeRef}
|
containerRef={iframeRef}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex w-full h-full justify-center items-center bg-white">No preview available</div>
|
<div className="flex w-full h-full justify-center items-center bg-white">No preview available</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@ export const ScreenshotSelector = memo(
|
|||||||
videoRef.current.remove();
|
videoRef.current.remove();
|
||||||
videoRef.current = null;
|
videoRef.current = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mediaStreamRef.current) {
|
if (mediaStreamRef.current) {
|
||||||
mediaStreamRef.current.getTracks().forEach((track) => track.stop());
|
mediaStreamRef.current.getTracks().forEach((track) => track.stop());
|
||||||
mediaStreamRef.current = null;
|
mediaStreamRef.current = null;
|
||||||
@ -52,10 +53,12 @@ export const ScreenshotSelector = memo(
|
|||||||
videoRef.current.remove();
|
videoRef.current.remove();
|
||||||
videoRef.current = null;
|
videoRef.current = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mediaStreamRef.current) {
|
if (mediaStreamRef.current) {
|
||||||
mediaStreamRef.current.getTracks().forEach((track) => track.stop());
|
mediaStreamRef.current.getTracks().forEach((track) => track.stop());
|
||||||
mediaStreamRef.current = null;
|
mediaStreamRef.current = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
setIsSelectionMode(false);
|
setIsSelectionMode(false);
|
||||||
setSelectionStart(null);
|
setSelectionStart(null);
|
||||||
setSelectionEnd(null);
|
setSelectionEnd(null);
|
||||||
@ -84,16 +87,23 @@ export const ScreenshotSelector = memo(
|
|||||||
toast.error('Failed to initialize screen capture');
|
toast.error('Failed to initialize screen capture');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return mediaStreamRef.current;
|
return mediaStreamRef.current;
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCopySelection = useCallback(async () => {
|
const handleCopySelection = useCallback(async () => {
|
||||||
if (!isSelectionMode || !selectionStart || !selectionEnd || !containerRef.current) return;
|
if (!isSelectionMode || !selectionStart || !selectionEnd || !containerRef.current) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
setIsCapturing(true);
|
setIsCapturing(true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const stream = await initializeStream();
|
const stream = await initializeStream();
|
||||||
if (!stream || !videoRef.current) return;
|
|
||||||
|
if (!stream || !videoRef.current) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Wait for video to be ready
|
// Wait for video to be ready
|
||||||
await new Promise((resolve) => setTimeout(resolve, 300));
|
await new Promise((resolve) => setTimeout(resolve, 300));
|
||||||
@ -102,6 +112,7 @@ export const ScreenshotSelector = memo(
|
|||||||
const tempCanvas = document.createElement('canvas');
|
const tempCanvas = document.createElement('canvas');
|
||||||
tempCanvas.width = videoRef.current.videoWidth;
|
tempCanvas.width = videoRef.current.videoWidth;
|
||||||
tempCanvas.height = videoRef.current.videoHeight;
|
tempCanvas.height = videoRef.current.videoHeight;
|
||||||
|
|
||||||
const tempCtx = tempCanvas.getContext('2d');
|
const tempCtx = tempCanvas.getContext('2d');
|
||||||
|
|
||||||
if (!tempCtx) {
|
if (!tempCtx) {
|
||||||
@ -140,6 +151,7 @@ export const ScreenshotSelector = memo(
|
|||||||
const canvas = document.createElement('canvas');
|
const canvas = document.createElement('canvas');
|
||||||
canvas.width = Math.round(Math.abs(selectionEnd.x - selectionStart.x));
|
canvas.width = Math.round(Math.abs(selectionEnd.x - selectionStart.x));
|
||||||
canvas.height = Math.round(Math.abs(selectionEnd.y - selectionStart.y));
|
canvas.height = Math.round(Math.abs(selectionEnd.y - selectionStart.y));
|
||||||
|
|
||||||
const ctx = canvas.getContext('2d');
|
const ctx = canvas.getContext('2d');
|
||||||
|
|
||||||
if (!ctx) {
|
if (!ctx) {
|
||||||
@ -152,18 +164,23 @@ export const ScreenshotSelector = memo(
|
|||||||
// Convert to blob
|
// Convert to blob
|
||||||
const blob = await new Promise<Blob>((resolve, reject) => {
|
const blob = await new Promise<Blob>((resolve, reject) => {
|
||||||
canvas.toBlob((blob) => {
|
canvas.toBlob((blob) => {
|
||||||
if (blob) resolve(blob);
|
if (blob) {
|
||||||
else reject(new Error('Failed to create blob'));
|
resolve(blob);
|
||||||
|
} else {
|
||||||
|
reject(new Error('Failed to create blob'));
|
||||||
|
}
|
||||||
}, 'image/png');
|
}, 'image/png');
|
||||||
});
|
});
|
||||||
|
|
||||||
// Create a FileReader to convert blob to base64
|
// Create a FileReader to convert blob to base64
|
||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
|
|
||||||
reader.onload = (e) => {
|
reader.onload = (e) => {
|
||||||
const base64Image = e.target?.result as string;
|
const base64Image = e.target?.result as string;
|
||||||
|
|
||||||
// Find the textarea element
|
// Find the textarea element
|
||||||
const textarea = document.querySelector('textarea');
|
const textarea = document.querySelector('textarea');
|
||||||
|
|
||||||
if (textarea) {
|
if (textarea) {
|
||||||
// Get the setters from the BaseChat component
|
// Get the setters from the BaseChat component
|
||||||
const setUploadedFiles = (window as any).__BOLT_SET_UPLOADED_FILES__;
|
const setUploadedFiles = (window as any).__BOLT_SET_UPLOADED_FILES__;
|
||||||
@ -186,6 +203,7 @@ export const ScreenshotSelector = memo(
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to capture screenshot:', error);
|
console.error('Failed to capture screenshot:', error);
|
||||||
toast.error('Failed to capture screenshot');
|
toast.error('Failed to capture screenshot');
|
||||||
|
|
||||||
if (mediaStreamRef.current) {
|
if (mediaStreamRef.current) {
|
||||||
mediaStreamRef.current.getTracks().forEach((track) => track.stop());
|
mediaStreamRef.current.getTracks().forEach((track) => track.stop());
|
||||||
mediaStreamRef.current = null;
|
mediaStreamRef.current = null;
|
||||||
@ -202,7 +220,11 @@ export const ScreenshotSelector = memo(
|
|||||||
(e: React.MouseEvent) => {
|
(e: React.MouseEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
if (!isSelectionMode) return;
|
|
||||||
|
if (!isSelectionMode) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const rect = e.currentTarget.getBoundingClientRect();
|
const rect = e.currentTarget.getBoundingClientRect();
|
||||||
const x = e.clientX - rect.left;
|
const x = e.clientX - rect.left;
|
||||||
const y = e.clientY - rect.top;
|
const y = e.clientY - rect.top;
|
||||||
@ -216,7 +238,11 @@ export const ScreenshotSelector = memo(
|
|||||||
(e: React.MouseEvent) => {
|
(e: React.MouseEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
if (!isSelectionMode || !selectionStart) return;
|
|
||||||
|
if (!isSelectionMode || !selectionStart) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const rect = e.currentTarget.getBoundingClientRect();
|
const rect = e.currentTarget.getBoundingClientRect();
|
||||||
const x = e.clientX - rect.left;
|
const x = e.clientX - rect.left;
|
||||||
const y = e.clientY - rect.top;
|
const y = e.clientY - rect.top;
|
||||||
@ -225,7 +251,9 @@ export const ScreenshotSelector = memo(
|
|||||||
[isSelectionMode, selectionStart],
|
[isSelectionMode, selectionStart],
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!isSelectionMode) return null;
|
if (!isSelectionMode) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
Loading…
Reference in New Issue
Block a user