ed-mcconnell commited on
Commit
6ffcdd8
·
1 Parent(s): a936c5a

merge main into image

Browse files
app/commit.json CHANGED
@@ -1 +1 @@
1
- { "commit": "4cfabd94ee8ab91a1466cf644dbf9c74ab1324d7" }
 
1
+ { "commit": "a936c5a99036e0ea65c976e19b3bdb39f8d7cd40" }
app/components/workbench/Preview.tsx CHANGED
@@ -289,14 +289,20 @@ export const Preview = memo(() => {
289
  >
290
  {activePreview ? (
291
  <>
292
- <iframe ref={iframeRef} title="preview" className="border-none w-full h-full bg-white" src={iframeUrl} allowFullScreen />
 
 
 
 
 
 
293
  <ScreenshotSelector
294
- isSelectionMode={isSelectionMode}
295
- setIsSelectionMode={setIsSelectionMode}
296
- containerRef={iframeRef}
297
- />
298
- </>
299
- ) : (
300
  <div className="flex w-full h-full justify-center items-center bg-white">No preview available</div>
301
  )}
302
 
 
289
  >
290
  {activePreview ? (
291
  <>
292
+ <iframe
293
+ ref={iframeRef}
294
+ title="preview"
295
+ className="border-none w-full h-full bg-white"
296
+ src={iframeUrl}
297
+ allowFullScreen
298
+ />
299
  <ScreenshotSelector
300
+ isSelectionMode={isSelectionMode}
301
+ setIsSelectionMode={setIsSelectionMode}
302
+ containerRef={iframeRef}
303
+ />
304
+ </>
305
+ ) : (
306
  <div className="flex w-full h-full justify-center items-center bg-white">No preview available</div>
307
  )}
308
 
app/components/workbench/ScreenshotSelector.tsx CHANGED
@@ -24,6 +24,7 @@ export const ScreenshotSelector = memo(
24
  videoRef.current.remove();
25
  videoRef.current = null;
26
  }
 
27
  if (mediaStreamRef.current) {
28
  mediaStreamRef.current.getTracks().forEach((track) => track.stop());
29
  mediaStreamRef.current = null;
@@ -52,10 +53,12 @@ export const ScreenshotSelector = memo(
52
  videoRef.current.remove();
53
  videoRef.current = null;
54
  }
 
55
  if (mediaStreamRef.current) {
56
  mediaStreamRef.current.getTracks().forEach((track) => track.stop());
57
  mediaStreamRef.current = null;
58
  }
 
59
  setIsSelectionMode(false);
60
  setSelectionStart(null);
61
  setSelectionEnd(null);
@@ -84,16 +87,23 @@ export const ScreenshotSelector = memo(
84
  toast.error('Failed to initialize screen capture');
85
  }
86
  }
 
87
  return mediaStreamRef.current;
88
  };
89
 
90
  const handleCopySelection = useCallback(async () => {
91
- if (!isSelectionMode || !selectionStart || !selectionEnd || !containerRef.current) return;
 
 
92
 
93
  setIsCapturing(true);
 
94
  try {
95
  const stream = await initializeStream();
96
- if (!stream || !videoRef.current) return;
 
 
 
97
 
98
  // Wait for video to be ready
99
  await new Promise((resolve) => setTimeout(resolve, 300));
@@ -102,6 +112,7 @@ export const ScreenshotSelector = memo(
102
  const tempCanvas = document.createElement('canvas');
103
  tempCanvas.width = videoRef.current.videoWidth;
104
  tempCanvas.height = videoRef.current.videoHeight;
 
105
  const tempCtx = tempCanvas.getContext('2d');
106
 
107
  if (!tempCtx) {
@@ -140,6 +151,7 @@ export const ScreenshotSelector = memo(
140
  const canvas = document.createElement('canvas');
141
  canvas.width = Math.round(Math.abs(selectionEnd.x - selectionStart.x));
142
  canvas.height = Math.round(Math.abs(selectionEnd.y - selectionStart.y));
 
143
  const ctx = canvas.getContext('2d');
144
 
145
  if (!ctx) {
@@ -152,18 +164,23 @@ export const ScreenshotSelector = memo(
152
  // Convert to blob
153
  const blob = await new Promise<Blob>((resolve, reject) => {
154
  canvas.toBlob((blob) => {
155
- if (blob) resolve(blob);
156
- else reject(new Error('Failed to create blob'));
 
 
 
157
  }, 'image/png');
158
  });
159
 
160
  // Create a FileReader to convert blob to base64
161
  const reader = new FileReader();
 
162
  reader.onload = (e) => {
163
  const base64Image = e.target?.result as string;
164
 
165
  // Find the textarea element
166
  const textarea = document.querySelector('textarea');
 
167
  if (textarea) {
168
  // Get the setters from the BaseChat component
169
  const setUploadedFiles = (window as any).__BOLT_SET_UPLOADED_FILES__;
@@ -186,6 +203,7 @@ export const ScreenshotSelector = memo(
186
  } catch (error) {
187
  console.error('Failed to capture screenshot:', error);
188
  toast.error('Failed to capture screenshot');
 
189
  if (mediaStreamRef.current) {
190
  mediaStreamRef.current.getTracks().forEach((track) => track.stop());
191
  mediaStreamRef.current = null;
@@ -202,7 +220,11 @@ export const ScreenshotSelector = memo(
202
  (e: React.MouseEvent) => {
203
  e.preventDefault();
204
  e.stopPropagation();
205
- if (!isSelectionMode) return;
 
 
 
 
206
  const rect = e.currentTarget.getBoundingClientRect();
207
  const x = e.clientX - rect.left;
208
  const y = e.clientY - rect.top;
@@ -216,7 +238,11 @@ export const ScreenshotSelector = memo(
216
  (e: React.MouseEvent) => {
217
  e.preventDefault();
218
  e.stopPropagation();
219
- if (!isSelectionMode || !selectionStart) return;
 
 
 
 
220
  const rect = e.currentTarget.getBoundingClientRect();
221
  const x = e.clientX - rect.left;
222
  const y = e.clientY - rect.top;
@@ -225,7 +251,9 @@ export const ScreenshotSelector = memo(
225
  [isSelectionMode, selectionStart],
226
  );
227
 
228
- if (!isSelectionMode) return null;
 
 
229
 
230
  return (
231
  <div
 
24
  videoRef.current.remove();
25
  videoRef.current = null;
26
  }
27
+
28
  if (mediaStreamRef.current) {
29
  mediaStreamRef.current.getTracks().forEach((track) => track.stop());
30
  mediaStreamRef.current = null;
 
53
  videoRef.current.remove();
54
  videoRef.current = null;
55
  }
56
+
57
  if (mediaStreamRef.current) {
58
  mediaStreamRef.current.getTracks().forEach((track) => track.stop());
59
  mediaStreamRef.current = null;
60
  }
61
+
62
  setIsSelectionMode(false);
63
  setSelectionStart(null);
64
  setSelectionEnd(null);
 
87
  toast.error('Failed to initialize screen capture');
88
  }
89
  }
90
+
91
  return mediaStreamRef.current;
92
  };
93
 
94
  const handleCopySelection = useCallback(async () => {
95
+ if (!isSelectionMode || !selectionStart || !selectionEnd || !containerRef.current) {
96
+ return;
97
+ }
98
 
99
  setIsCapturing(true);
100
+
101
  try {
102
  const stream = await initializeStream();
103
+
104
+ if (!stream || !videoRef.current) {
105
+ return;
106
+ }
107
 
108
  // Wait for video to be ready
109
  await new Promise((resolve) => setTimeout(resolve, 300));
 
112
  const tempCanvas = document.createElement('canvas');
113
  tempCanvas.width = videoRef.current.videoWidth;
114
  tempCanvas.height = videoRef.current.videoHeight;
115
+
116
  const tempCtx = tempCanvas.getContext('2d');
117
 
118
  if (!tempCtx) {
 
151
  const canvas = document.createElement('canvas');
152
  canvas.width = Math.round(Math.abs(selectionEnd.x - selectionStart.x));
153
  canvas.height = Math.round(Math.abs(selectionEnd.y - selectionStart.y));
154
+
155
  const ctx = canvas.getContext('2d');
156
 
157
  if (!ctx) {
 
164
  // Convert to blob
165
  const blob = await new Promise<Blob>((resolve, reject) => {
166
  canvas.toBlob((blob) => {
167
+ if (blob) {
168
+ resolve(blob);
169
+ } else {
170
+ reject(new Error('Failed to create blob'));
171
+ }
172
  }, 'image/png');
173
  });
174
 
175
  // Create a FileReader to convert blob to base64
176
  const reader = new FileReader();
177
+
178
  reader.onload = (e) => {
179
  const base64Image = e.target?.result as string;
180
 
181
  // Find the textarea element
182
  const textarea = document.querySelector('textarea');
183
+
184
  if (textarea) {
185
  // Get the setters from the BaseChat component
186
  const setUploadedFiles = (window as any).__BOLT_SET_UPLOADED_FILES__;
 
203
  } catch (error) {
204
  console.error('Failed to capture screenshot:', error);
205
  toast.error('Failed to capture screenshot');
206
+
207
  if (mediaStreamRef.current) {
208
  mediaStreamRef.current.getTracks().forEach((track) => track.stop());
209
  mediaStreamRef.current = null;
 
220
  (e: React.MouseEvent) => {
221
  e.preventDefault();
222
  e.stopPropagation();
223
+
224
+ if (!isSelectionMode) {
225
+ return;
226
+ }
227
+
228
  const rect = e.currentTarget.getBoundingClientRect();
229
  const x = e.clientX - rect.left;
230
  const y = e.clientY - rect.top;
 
238
  (e: React.MouseEvent) => {
239
  e.preventDefault();
240
  e.stopPropagation();
241
+
242
+ if (!isSelectionMode || !selectionStart) {
243
+ return;
244
+ }
245
+
246
  const rect = e.currentTarget.getBoundingClientRect();
247
  const x = e.clientX - rect.left;
248
  const y = e.clientY - rect.top;
 
251
  [isSelectionMode, selectionStart],
252
  );
253
 
254
+ if (!isSelectionMode) {
255
+ return null;
256
+ }
257
 
258
  return (
259
  <div