pushfeedback 0.1.69 → 0.1.71
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/{feedback-button_2.cjs.entry.js → canvas-editor_3.cjs.entry.js} +883 -718
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/pushfeedback.cjs.js +1 -1
- package/dist/collection/collection-manifest.json +1 -0
- package/dist/collection/components/canvas-editor/canvas-editor.css +404 -0
- package/dist/collection/components/canvas-editor/canvas-editor.js +1282 -0
- package/dist/collection/components/feedback-button/feedback-button.js +220 -0
- package/dist/collection/components/feedback-modal/feedback-modal.css +2 -458
- package/dist/collection/components/feedback-modal/feedback-modal.js +247 -782
- package/dist/components/canvas-editor.d.ts +11 -0
- package/dist/components/canvas-editor.js +6 -0
- package/dist/components/canvas-editor2.js +917 -0
- package/dist/components/feedback-button.js +40 -1
- package/dist/components/feedback-modal2.js +68 -784
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.js +1 -0
- package/dist/esm/{feedback-button_2.entry.js → canvas-editor_3.entry.js} +883 -719
- package/dist/esm/loader.js +1 -1
- package/dist/esm/pushfeedback.js +1 -1
- package/dist/pushfeedback/p-2c39091c.entry.js +1 -0
- package/dist/pushfeedback/pushfeedback.esm.js +1 -1
- package/dist/types/components/canvas-editor/canvas-editor.d.ts +108 -0
- package/dist/types/components/feedback-button/feedback-button.d.ts +11 -0
- package/dist/types/components/feedback-modal/feedback-modal.d.ts +22 -79
- package/dist/types/components.d.ts +102 -0
- package/package.json +3 -4
- package/dist/pushfeedback/p-e7f48090.entry.js +0 -1
|
@@ -85,26 +85,6 @@ export class FeedbackModal {
|
|
|
85
85
|
document.querySelectorAll('.feedback-modal-element-selected').forEach(el => {
|
|
86
86
|
el.classList.remove('feedback-modal-element-selected');
|
|
87
87
|
});
|
|
88
|
-
// Reset canvas editor states
|
|
89
|
-
this.takingScreenshot = false;
|
|
90
|
-
this.showPreviewModal = false;
|
|
91
|
-
this.showCanvasEditor = false;
|
|
92
|
-
this.annotations = [];
|
|
93
|
-
this.currentAnnotation = null;
|
|
94
|
-
this.isDrawing = false;
|
|
95
|
-
this.canvasRef = null;
|
|
96
|
-
this.canvasContext = null;
|
|
97
|
-
this.originalImageData = null;
|
|
98
|
-
// Reset error states
|
|
99
|
-
this.showScreenshotError = false;
|
|
100
|
-
this.screenshotError = '';
|
|
101
|
-
// Reset resizing states
|
|
102
|
-
this.isResizing = false;
|
|
103
|
-
this.resizingAnnotation = null;
|
|
104
|
-
this.resizeStartSize = 16;
|
|
105
|
-
this.resizeStartDimensions = null;
|
|
106
|
-
this.hoveredAnnotation = null;
|
|
107
|
-
this.resizeHandle = false;
|
|
108
88
|
// Reset form states
|
|
109
89
|
this.formSuccess = false;
|
|
110
90
|
this.formError = false;
|
|
@@ -114,681 +94,50 @@ export class FeedbackModal {
|
|
|
114
94
|
this.resetOverflow();
|
|
115
95
|
}, 200);
|
|
116
96
|
};
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
this.
|
|
120
|
-
this.
|
|
121
|
-
|
|
122
|
-
this.
|
|
123
|
-
this.
|
|
124
|
-
this.isDrawing = false;
|
|
125
|
-
this.hoveredAnnotation = null;
|
|
126
|
-
// Hide the feedback modal temporarily to exclude it from screenshot
|
|
127
|
-
const wasModalVisible = this.showModal;
|
|
128
|
-
this.showModal = false;
|
|
129
|
-
// Also hide any feedback buttons on the page
|
|
130
|
-
this.hideAllFeedbackElements();
|
|
131
|
-
try {
|
|
132
|
-
// Wait a moment for UI to update before capturing
|
|
133
|
-
await new Promise(resolve => setTimeout(resolve, 100));
|
|
134
|
-
// Capture viewport screenshot using browser API
|
|
135
|
-
const dataUrl = await this.captureViewportScreenshot();
|
|
136
|
-
this.encodedScreenshot = dataUrl;
|
|
137
|
-
this.originalImageData = dataUrl;
|
|
138
|
-
// Reset loading state
|
|
139
|
-
this.takingScreenshot = false;
|
|
140
|
-
// Go directly to canvas editor (don't restore modal)
|
|
141
|
-
this.showCanvasEditor = true;
|
|
142
|
-
// Restore feedback elements visibility
|
|
143
|
-
this.showAllFeedbackElements();
|
|
144
|
-
// Initialize canvas after a short delay to ensure DOM is ready
|
|
145
|
-
setTimeout(() => {
|
|
146
|
-
this.initializeCanvas();
|
|
147
|
-
}, 100);
|
|
148
|
-
}
|
|
149
|
-
catch (error) {
|
|
150
|
-
console.error('Failed to capture screenshot:', error);
|
|
151
|
-
// Reset loading state on error
|
|
152
|
-
this.takingScreenshot = false;
|
|
153
|
-
// Restore modal and feedback elements on error
|
|
154
|
-
this.showModal = wasModalVisible;
|
|
155
|
-
this.showAllFeedbackElements();
|
|
156
|
-
// Show error message to user
|
|
157
|
-
this.handleScreenshotError(error);
|
|
158
|
-
}
|
|
159
|
-
};
|
|
160
|
-
this.hideAllFeedbackElements = () => {
|
|
161
|
-
// Hide all feedback buttons and modals on the page
|
|
162
|
-
const feedbackElements = document.querySelectorAll('feedback-button, feedback-modal');
|
|
163
|
-
feedbackElements.forEach(element => {
|
|
164
|
-
element.style.visibility = 'hidden';
|
|
165
|
-
});
|
|
97
|
+
// Handle screenshot events from canvas editor
|
|
98
|
+
this.handleScreenshotReady = (event) => {
|
|
99
|
+
this.encodedScreenshot = event.detail.screenshot;
|
|
100
|
+
this.showModal = true;
|
|
101
|
+
this.takingScreenshot = false;
|
|
102
|
+
this.showCanvasEditor = false;
|
|
103
|
+
this.autoStartCapture = false;
|
|
166
104
|
};
|
|
167
|
-
this.
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
});
|
|
105
|
+
this.handleScreenshotCancelled = () => {
|
|
106
|
+
this.showModal = true;
|
|
107
|
+
this.takingScreenshot = false;
|
|
108
|
+
this.showCanvasEditor = false;
|
|
109
|
+
this.autoStartCapture = false;
|
|
173
110
|
};
|
|
174
|
-
this.handleScreenshotError = (
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
}
|
|
179
|
-
else if (error.name === 'NotSupportedError') {
|
|
180
|
-
errorMessage += 'Screen capture is not supported in this browser.';
|
|
181
|
-
}
|
|
182
|
-
else if (error.name === 'NotFoundError') {
|
|
183
|
-
errorMessage += 'No screen sources available for capture.';
|
|
184
|
-
}
|
|
185
|
-
else if (error.name === 'AbortError') {
|
|
186
|
-
errorMessage += 'Screenshot capture was cancelled.';
|
|
187
|
-
}
|
|
188
|
-
else if (error.message && error.message.includes('not supported')) {
|
|
189
|
-
errorMessage += 'Your browser does not support screen capture. Please use a browser like Chrome, Firefox, or Safari.';
|
|
190
|
-
}
|
|
191
|
-
else {
|
|
192
|
-
errorMessage += 'An unexpected error occurred. Please try again.';
|
|
193
|
-
}
|
|
194
|
-
this.screenshotError = errorMessage;
|
|
111
|
+
this.handleScreenshotError = (event) => {
|
|
112
|
+
console.error('Screenshot error:', event.detail.error);
|
|
113
|
+
// Store error message to display in feedback modal
|
|
114
|
+
this.screenshotError = event.detail.error;
|
|
195
115
|
this.showScreenshotError = true;
|
|
196
|
-
//
|
|
116
|
+
// Close canvas editor and return to feedback modal
|
|
117
|
+
this.showModal = true;
|
|
118
|
+
this.takingScreenshot = false;
|
|
119
|
+
this.showCanvasEditor = false;
|
|
120
|
+
this.autoStartCapture = false;
|
|
121
|
+
// Auto-hide error after 8 seconds
|
|
197
122
|
setTimeout(() => {
|
|
198
123
|
this.showScreenshotError = false;
|
|
199
|
-
},
|
|
124
|
+
}, 8000);
|
|
125
|
+
};
|
|
126
|
+
// Trigger screenshot capture
|
|
127
|
+
this.openScreenShot = () => {
|
|
128
|
+
this.showModal = false;
|
|
129
|
+
this.takingScreenshot = true;
|
|
130
|
+
this.autoStartCapture = true; // Auto-start new screenshot
|
|
131
|
+
this.showCanvasEditor = true;
|
|
200
132
|
};
|
|
133
|
+
// Open canvas editor for existing screenshot
|
|
201
134
|
this.openCanvasEditor = (event) => {
|
|
202
135
|
if (event) {
|
|
203
136
|
event.stopPropagation();
|
|
204
137
|
}
|
|
205
138
|
this.showModal = false;
|
|
139
|
+
this.autoStartCapture = false; // Don't auto-start, just edit existing
|
|
206
140
|
this.showCanvasEditor = true;
|
|
207
|
-
// Initialize canvas after a short delay to ensure DOM is ready
|
|
208
|
-
setTimeout(() => {
|
|
209
|
-
this.initializeCanvas();
|
|
210
|
-
}, 100);
|
|
211
|
-
};
|
|
212
|
-
this.closeCanvasEditor = () => {
|
|
213
|
-
this.showCanvasEditor = false;
|
|
214
|
-
this.showModal = true;
|
|
215
|
-
};
|
|
216
|
-
this.saveAnnotations = () => {
|
|
217
|
-
if (this.canvasRef) {
|
|
218
|
-
// Create final image with annotations
|
|
219
|
-
const finalDataUrl = this.canvasRef.toDataURL('image/png');
|
|
220
|
-
this.encodedScreenshot = finalDataUrl;
|
|
221
|
-
}
|
|
222
|
-
this.showCanvasEditor = false;
|
|
223
|
-
this.showModal = true;
|
|
224
|
-
};
|
|
225
|
-
this.initializeCanvas = () => {
|
|
226
|
-
if (!this.canvasRef || !this.originalImageData)
|
|
227
|
-
return;
|
|
228
|
-
this.canvasContext = this.canvasRef.getContext('2d');
|
|
229
|
-
const img = new Image();
|
|
230
|
-
img.onload = () => {
|
|
231
|
-
// Set canvas to original image dimensions
|
|
232
|
-
this.canvasRef.width = img.width;
|
|
233
|
-
this.canvasRef.height = img.height;
|
|
234
|
-
// Get available container dimensions
|
|
235
|
-
const containerWidth = this.canvasRef.parentElement.clientWidth - 32; // Account for reduced padding (16px * 2)
|
|
236
|
-
const containerHeight = this.canvasRef.parentElement.clientHeight - 32;
|
|
237
|
-
// Calculate scale factors for both dimensions
|
|
238
|
-
const scaleX = containerWidth / img.width;
|
|
239
|
-
const scaleY = containerHeight / img.height;
|
|
240
|
-
// Use the smaller scale to ensure complete image fits
|
|
241
|
-
const scale = Math.min(scaleX, scaleY, 1); // Never scale up, only down
|
|
242
|
-
// Calculate final display dimensions
|
|
243
|
-
const displayWidth = img.width * scale;
|
|
244
|
-
const displayHeight = img.height * scale;
|
|
245
|
-
// Set CSS size for display (this scales the canvas visually)
|
|
246
|
-
this.canvasRef.style.width = `${displayWidth}px`;
|
|
247
|
-
this.canvasRef.style.height = `${displayHeight}px`;
|
|
248
|
-
console.log('Canvas initialized with complete image fit:', {
|
|
249
|
-
originalWidth: img.width,
|
|
250
|
-
originalHeight: img.height,
|
|
251
|
-
displayWidth,
|
|
252
|
-
displayHeight,
|
|
253
|
-
scale,
|
|
254
|
-
scaleX,
|
|
255
|
-
scaleY,
|
|
256
|
-
containerWidth,
|
|
257
|
-
containerHeight,
|
|
258
|
-
usingScale: scale === scaleX ? 'width-limited' : 'height-limited'
|
|
259
|
-
});
|
|
260
|
-
// Draw the original image at full resolution
|
|
261
|
-
this.canvasContext.drawImage(img, 0, 0);
|
|
262
|
-
// Redraw existing annotations
|
|
263
|
-
this.redrawAnnotations();
|
|
264
|
-
};
|
|
265
|
-
img.src = this.originalImageData;
|
|
266
|
-
};
|
|
267
|
-
this.redrawAnnotations = () => {
|
|
268
|
-
if (!this.canvasContext)
|
|
269
|
-
return;
|
|
270
|
-
// Clear and redraw background image
|
|
271
|
-
const img = new Image();
|
|
272
|
-
img.onload = () => {
|
|
273
|
-
this.canvasContext.clearRect(0, 0, this.canvasRef.width, this.canvasRef.height);
|
|
274
|
-
this.canvasContext.drawImage(img, 0, 0);
|
|
275
|
-
// Draw all annotations
|
|
276
|
-
this.annotations.forEach(annotation => {
|
|
277
|
-
this.drawAnnotation(annotation);
|
|
278
|
-
});
|
|
279
|
-
};
|
|
280
|
-
img.src = this.originalImageData;
|
|
281
|
-
};
|
|
282
|
-
this.drawAnnotation = (annotation) => {
|
|
283
|
-
if (!this.canvasContext)
|
|
284
|
-
return;
|
|
285
|
-
this.canvasContext.strokeStyle = annotation.color;
|
|
286
|
-
this.canvasContext.lineWidth = annotation.lineWidth;
|
|
287
|
-
this.canvasContext.lineCap = 'round';
|
|
288
|
-
this.canvasContext.lineJoin = 'round';
|
|
289
|
-
switch (annotation.type) {
|
|
290
|
-
case 'rectangle':
|
|
291
|
-
this.canvasContext.strokeRect(annotation.startX, annotation.startY, annotation.width, annotation.height);
|
|
292
|
-
// Draw resize handle if this annotation is hovered
|
|
293
|
-
if (this.hoveredAnnotation === annotation) {
|
|
294
|
-
this.drawRectangleResizeHandles(annotation);
|
|
295
|
-
}
|
|
296
|
-
break;
|
|
297
|
-
case 'line':
|
|
298
|
-
this.canvasContext.beginPath();
|
|
299
|
-
this.canvasContext.moveTo(annotation.startX, annotation.startY);
|
|
300
|
-
this.canvasContext.lineTo(annotation.endX, annotation.endY);
|
|
301
|
-
this.canvasContext.stroke();
|
|
302
|
-
// Draw resize handles if this annotation is hovered
|
|
303
|
-
if (this.hoveredAnnotation === annotation) {
|
|
304
|
-
this.drawLineResizeHandles(annotation);
|
|
305
|
-
}
|
|
306
|
-
break;
|
|
307
|
-
case 'arrow':
|
|
308
|
-
this.drawArrow(annotation.startX, annotation.startY, annotation.endX, annotation.endY);
|
|
309
|
-
// Draw resize handles if this annotation is hovered
|
|
310
|
-
if (this.hoveredAnnotation === annotation) {
|
|
311
|
-
this.drawLineResizeHandles(annotation); // Same as line
|
|
312
|
-
}
|
|
313
|
-
break;
|
|
314
|
-
case 'text':
|
|
315
|
-
const fontSize = annotation.fontSize || 16;
|
|
316
|
-
this.canvasContext.fillStyle = annotation.color;
|
|
317
|
-
this.canvasContext.font = `${fontSize}px Arial`;
|
|
318
|
-
this.canvasContext.fillText(annotation.text, annotation.x, annotation.y);
|
|
319
|
-
// Draw resize handle if this annotation is hovered
|
|
320
|
-
if (this.hoveredAnnotation === annotation) {
|
|
321
|
-
this.drawTextResizeHandle(annotation);
|
|
322
|
-
}
|
|
323
|
-
break;
|
|
324
|
-
}
|
|
325
|
-
};
|
|
326
|
-
// Draw resize handle for text annotation
|
|
327
|
-
this.drawTextResizeHandle = (annotation) => {
|
|
328
|
-
if (!this.canvasContext || annotation.type !== 'text')
|
|
329
|
-
return;
|
|
330
|
-
const fontSize = annotation.fontSize || 16;
|
|
331
|
-
const textWidth = this.getTextWidth(annotation.text, fontSize);
|
|
332
|
-
const handleSize = 8;
|
|
333
|
-
const handleX = annotation.x + textWidth;
|
|
334
|
-
const handleY = annotation.y;
|
|
335
|
-
// Draw resize handle (small square) - using widget primary color
|
|
336
|
-
this.canvasContext.fillStyle = '#0070F4'; // var(--feedback-primary-color)
|
|
337
|
-
this.canvasContext.strokeStyle = '#ffffff';
|
|
338
|
-
this.canvasContext.lineWidth = 2;
|
|
339
|
-
this.canvasContext.fillRect(handleX - handleSize / 2, handleY - handleSize / 2, handleSize, handleSize);
|
|
340
|
-
this.canvasContext.strokeRect(handleX - handleSize / 2, handleY - handleSize / 2, handleSize, handleSize);
|
|
341
|
-
};
|
|
342
|
-
this.drawArrow = (fromX, fromY, toX, toY) => {
|
|
343
|
-
const headlen = 15; // Arrow head length
|
|
344
|
-
const angle = Math.atan2(toY - fromY, toX - fromX);
|
|
345
|
-
// Draw line
|
|
346
|
-
this.canvasContext.beginPath();
|
|
347
|
-
this.canvasContext.moveTo(fromX, fromY);
|
|
348
|
-
this.canvasContext.lineTo(toX, toY);
|
|
349
|
-
this.canvasContext.stroke();
|
|
350
|
-
// Draw arrow head
|
|
351
|
-
this.canvasContext.beginPath();
|
|
352
|
-
this.canvasContext.moveTo(toX, toY);
|
|
353
|
-
this.canvasContext.lineTo(toX - headlen * Math.cos(angle - Math.PI / 6), toY - headlen * Math.sin(angle - Math.PI / 6));
|
|
354
|
-
this.canvasContext.moveTo(toX, toY);
|
|
355
|
-
this.canvasContext.lineTo(toX - headlen * Math.cos(angle + Math.PI / 6), toY - headlen * Math.sin(angle + Math.PI / 6));
|
|
356
|
-
this.canvasContext.stroke();
|
|
357
|
-
};
|
|
358
|
-
this.undoLastAnnotation = () => {
|
|
359
|
-
this.annotations = this.annotations.slice(0, -1);
|
|
360
|
-
this.redrawAnnotations();
|
|
361
|
-
};
|
|
362
|
-
// Handle color slot editing
|
|
363
|
-
this.handleColorSlotClick = (colorIndex) => {
|
|
364
|
-
if (this.editingColorIndex === colorIndex) {
|
|
365
|
-
// If already editing this slot, just select the color
|
|
366
|
-
this.canvasDrawingColor = this.defaultColors[colorIndex];
|
|
367
|
-
this.showColorPicker = false;
|
|
368
|
-
this.editingColorIndex = -1;
|
|
369
|
-
}
|
|
370
|
-
else {
|
|
371
|
-
// Start editing this color slot
|
|
372
|
-
this.editingColorIndex = colorIndex;
|
|
373
|
-
this.showColorPicker = true;
|
|
374
|
-
this.canvasDrawingColor = this.defaultColors[colorIndex];
|
|
375
|
-
}
|
|
376
|
-
};
|
|
377
|
-
// Update color in slot
|
|
378
|
-
this.updateColorSlot = (newColor) => {
|
|
379
|
-
if (this.editingColorIndex >= 0 && this.editingColorIndex < this.defaultColors.length) {
|
|
380
|
-
this.defaultColors[this.editingColorIndex] = newColor;
|
|
381
|
-
this.canvasDrawingColor = newColor;
|
|
382
|
-
this.showColorPicker = false;
|
|
383
|
-
this.editingColorIndex = -1;
|
|
384
|
-
// Force reactivity
|
|
385
|
-
this.defaultColors = [...this.defaultColors];
|
|
386
|
-
}
|
|
387
|
-
};
|
|
388
|
-
// Handle color picker input without closing
|
|
389
|
-
this.handleColorPickerInput = (event) => {
|
|
390
|
-
event.stopPropagation();
|
|
391
|
-
const newColor = event.target.value;
|
|
392
|
-
if (this.editingColorIndex >= 0 && this.editingColorIndex < this.defaultColors.length) {
|
|
393
|
-
this.defaultColors[this.editingColorIndex] = newColor;
|
|
394
|
-
this.canvasDrawingColor = newColor;
|
|
395
|
-
// Force reactivity
|
|
396
|
-
this.defaultColors = [...this.defaultColors];
|
|
397
|
-
}
|
|
398
|
-
};
|
|
399
|
-
// Handle color picker click to prevent closing
|
|
400
|
-
this.handleColorPickerClick = (event) => {
|
|
401
|
-
event.stopPropagation();
|
|
402
|
-
};
|
|
403
|
-
// Close color picker
|
|
404
|
-
this.closeColorPicker = () => {
|
|
405
|
-
this.showColorPicker = false;
|
|
406
|
-
this.editingColorIndex = -1;
|
|
407
|
-
};
|
|
408
|
-
// Check if point is in resize handle for any annotation type
|
|
409
|
-
this.isPointInResizeHandle = (x, y, annotation) => {
|
|
410
|
-
const handleSize = 8;
|
|
411
|
-
switch (annotation.type) {
|
|
412
|
-
case 'text':
|
|
413
|
-
const textWidth = this.getTextWidth(annotation.text, annotation.fontSize || 16);
|
|
414
|
-
const handleX = annotation.x + textWidth;
|
|
415
|
-
const handleY = annotation.y;
|
|
416
|
-
return x >= handleX - handleSize / 2 && x <= handleX + handleSize / 2 &&
|
|
417
|
-
y >= handleY - handleSize / 2 && y <= handleY + handleSize / 2;
|
|
418
|
-
case 'rectangle':
|
|
419
|
-
const right = annotation.startX + annotation.width;
|
|
420
|
-
const bottom = annotation.startY + annotation.height;
|
|
421
|
-
// Only check bottom-right corner handle
|
|
422
|
-
return x >= right - handleSize / 2 && x <= right + handleSize / 2 &&
|
|
423
|
-
y >= bottom - handleSize / 2 && y <= bottom + handleSize / 2;
|
|
424
|
-
case 'line':
|
|
425
|
-
case 'arrow':
|
|
426
|
-
// Check both endpoint handles
|
|
427
|
-
const lineHandles = [
|
|
428
|
-
{ x: annotation.startX, y: annotation.startY, point: 'start' },
|
|
429
|
-
{ x: annotation.endX, y: annotation.endY, point: 'end' }
|
|
430
|
-
];
|
|
431
|
-
for (const handle of lineHandles) {
|
|
432
|
-
if (x >= handle.x - handleSize / 2 && x <= handle.x + handleSize / 2 &&
|
|
433
|
-
y >= handle.y - handleSize / 2 && y <= handle.y + handleSize / 2) {
|
|
434
|
-
return handle.point; // Return which endpoint was clicked
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
return false;
|
|
438
|
-
default:
|
|
439
|
-
return false;
|
|
440
|
-
}
|
|
441
|
-
};
|
|
442
|
-
// Get text width for resize handle positioning
|
|
443
|
-
this.getTextWidth = (text, fontSize) => {
|
|
444
|
-
// Approximate text width calculation
|
|
445
|
-
return text.length * fontSize * 0.6;
|
|
446
|
-
};
|
|
447
|
-
// Start text resize
|
|
448
|
-
this.startTextResize = (annotation, startPos) => {
|
|
449
|
-
this.isResizing = true;
|
|
450
|
-
this.resizingAnnotation = annotation;
|
|
451
|
-
this.resizeStartSize = annotation.fontSize || 16;
|
|
452
|
-
this.dragStartPos = startPos;
|
|
453
|
-
};
|
|
454
|
-
// Handle text resize
|
|
455
|
-
this.handleTextResize = (currentPos) => {
|
|
456
|
-
if (!this.resizingAnnotation || !this.dragStartPos)
|
|
457
|
-
return;
|
|
458
|
-
const deltaX = currentPos.x - this.dragStartPos.x;
|
|
459
|
-
const deltaY = currentPos.y - this.dragStartPos.y;
|
|
460
|
-
const avgDelta = (deltaX + deltaY) / 2;
|
|
461
|
-
// Calculate new font size (minimum 8px, maximum 72px)
|
|
462
|
-
const newSize = Math.max(8, Math.min(72, this.resizeStartSize + avgDelta * 0.5));
|
|
463
|
-
// Update annotation font size
|
|
464
|
-
const index = this.annotations.findIndex(a => a === this.resizingAnnotation);
|
|
465
|
-
if (index !== -1) {
|
|
466
|
-
this.annotations[index] = Object.assign(Object.assign({}, this.resizingAnnotation), { fontSize: Math.round(newSize) });
|
|
467
|
-
this.resizingAnnotation = this.annotations[index];
|
|
468
|
-
}
|
|
469
|
-
this.redrawAnnotations();
|
|
470
|
-
};
|
|
471
|
-
// Start resize for any annotation type
|
|
472
|
-
this.startResize = (annotation, handle, startPos) => {
|
|
473
|
-
this.isResizing = true;
|
|
474
|
-
this.resizingAnnotation = annotation;
|
|
475
|
-
this.resizeHandle = handle;
|
|
476
|
-
this.dragStartPos = startPos;
|
|
477
|
-
// Store original values for different annotation types
|
|
478
|
-
if (annotation.type === 'text') {
|
|
479
|
-
this.resizeStartSize = annotation.fontSize || 16;
|
|
480
|
-
}
|
|
481
|
-
else if (annotation.type === 'rectangle') {
|
|
482
|
-
this.resizeStartDimensions = { width: annotation.width, height: annotation.height };
|
|
483
|
-
}
|
|
484
|
-
};
|
|
485
|
-
// Enhanced mouse down handler with resize detection for all annotation types
|
|
486
|
-
this.handleCanvasMouseDown = (event) => {
|
|
487
|
-
if (!this.canvasRef)
|
|
488
|
-
return;
|
|
489
|
-
// Disable drawing on mobile devices
|
|
490
|
-
if (window.innerWidth <= 768)
|
|
491
|
-
return;
|
|
492
|
-
// Close color picker if open
|
|
493
|
-
if (this.showColorPicker) {
|
|
494
|
-
this.closeColorPicker();
|
|
495
|
-
}
|
|
496
|
-
const coords = this.getCanvasCoordinates(event);
|
|
497
|
-
// Check if clicking on existing annotation first
|
|
498
|
-
const found = this.findAnnotationAt(coords.x, coords.y);
|
|
499
|
-
if (found) {
|
|
500
|
-
// Check if clicking on resize handle for any annotation type
|
|
501
|
-
const handle = this.isPointInResizeHandle(coords.x, coords.y, found.annotation);
|
|
502
|
-
if (handle) {
|
|
503
|
-
this.startResize(found.annotation, handle, coords);
|
|
504
|
-
this.canvasRef.style.cursor = 'nw-resize';
|
|
505
|
-
return;
|
|
506
|
-
}
|
|
507
|
-
// Start dragging existing annotation
|
|
508
|
-
if (!this.isDrawing) {
|
|
509
|
-
this.isDragging = true;
|
|
510
|
-
this.draggedAnnotation = found.annotation;
|
|
511
|
-
this.dragStartPos = coords;
|
|
512
|
-
this.canvasRef.style.cursor = 'grabbing';
|
|
513
|
-
return;
|
|
514
|
-
}
|
|
515
|
-
}
|
|
516
|
-
// Original drawing logic
|
|
517
|
-
this.isDrawing = true;
|
|
518
|
-
if (this.canvasDrawingTool === 'text') {
|
|
519
|
-
const text = prompt('Enter text:');
|
|
520
|
-
if (text) {
|
|
521
|
-
const annotation = {
|
|
522
|
-
type: 'text',
|
|
523
|
-
x: coords.x,
|
|
524
|
-
y: coords.y,
|
|
525
|
-
text,
|
|
526
|
-
color: this.canvasDrawingColor,
|
|
527
|
-
fontSize: 16
|
|
528
|
-
};
|
|
529
|
-
this.annotations = [...this.annotations, annotation];
|
|
530
|
-
this.redrawAnnotations();
|
|
531
|
-
}
|
|
532
|
-
this.isDrawing = false;
|
|
533
|
-
}
|
|
534
|
-
else {
|
|
535
|
-
this.currentAnnotation = {
|
|
536
|
-
type: this.canvasDrawingTool,
|
|
537
|
-
startX: coords.x,
|
|
538
|
-
startY: coords.y,
|
|
539
|
-
color: this.canvasDrawingColor,
|
|
540
|
-
lineWidth: this.canvasLineWidth
|
|
541
|
-
};
|
|
542
|
-
}
|
|
543
|
-
};
|
|
544
|
-
this.handleCanvasMouseMove = (event) => {
|
|
545
|
-
if (!this.canvasRef)
|
|
546
|
-
return;
|
|
547
|
-
// Disable drawing on mobile devices
|
|
548
|
-
if (window.innerWidth <= 768)
|
|
549
|
-
return;
|
|
550
|
-
const coords = this.getCanvasCoordinates(event);
|
|
551
|
-
// Handle resizing for any annotation type
|
|
552
|
-
if (this.isResizing && this.resizingAnnotation) {
|
|
553
|
-
this.handleResize(coords);
|
|
554
|
-
return;
|
|
555
|
-
}
|
|
556
|
-
// Handle dragging existing annotation
|
|
557
|
-
if (this.isDragging && this.draggedAnnotation && this.dragStartPos) {
|
|
558
|
-
const deltaX = coords.x - this.dragStartPos.x;
|
|
559
|
-
const deltaY = coords.y - this.dragStartPos.y;
|
|
560
|
-
// Update annotation position
|
|
561
|
-
const updatedAnnotation = Object.assign({}, this.draggedAnnotation);
|
|
562
|
-
switch (updatedAnnotation.type) {
|
|
563
|
-
case 'rectangle':
|
|
564
|
-
updatedAnnotation.startX += deltaX;
|
|
565
|
-
updatedAnnotation.startY += deltaY;
|
|
566
|
-
break;
|
|
567
|
-
case 'line':
|
|
568
|
-
case 'arrow':
|
|
569
|
-
updatedAnnotation.startX += deltaX;
|
|
570
|
-
updatedAnnotation.startY += deltaY;
|
|
571
|
-
updatedAnnotation.endX += deltaX;
|
|
572
|
-
updatedAnnotation.endY += deltaY;
|
|
573
|
-
break;
|
|
574
|
-
case 'text':
|
|
575
|
-
updatedAnnotation.x += deltaX;
|
|
576
|
-
updatedAnnotation.y += deltaY;
|
|
577
|
-
break;
|
|
578
|
-
}
|
|
579
|
-
// Update annotation in array
|
|
580
|
-
const index = this.annotations.findIndex(a => a === this.draggedAnnotation);
|
|
581
|
-
if (index !== -1) {
|
|
582
|
-
this.annotations[index] = updatedAnnotation;
|
|
583
|
-
this.draggedAnnotation = updatedAnnotation;
|
|
584
|
-
}
|
|
585
|
-
this.dragStartPos = coords;
|
|
586
|
-
this.redrawAnnotations();
|
|
587
|
-
return;
|
|
588
|
-
}
|
|
589
|
-
// Handle drawing new annotation
|
|
590
|
-
if (this.isDrawing && this.currentAnnotation) {
|
|
591
|
-
if (this.canvasDrawingTool === 'rectangle') {
|
|
592
|
-
this.currentAnnotation.width = coords.x - this.currentAnnotation.startX;
|
|
593
|
-
this.currentAnnotation.height = coords.y - this.currentAnnotation.startY;
|
|
594
|
-
}
|
|
595
|
-
else {
|
|
596
|
-
this.currentAnnotation.endX = coords.x;
|
|
597
|
-
this.currentAnnotation.endY = coords.y;
|
|
598
|
-
}
|
|
599
|
-
this.redrawAnnotations();
|
|
600
|
-
this.drawAnnotation(this.currentAnnotation);
|
|
601
|
-
return;
|
|
602
|
-
}
|
|
603
|
-
// Handle hover states and cursor changes
|
|
604
|
-
const found = this.findAnnotationAt(coords.x, coords.y);
|
|
605
|
-
if (found) {
|
|
606
|
-
// Check if hovering over resize handle for any annotation type
|
|
607
|
-
const handle = this.isPointInResizeHandle(coords.x, coords.y, found.annotation);
|
|
608
|
-
if (handle) {
|
|
609
|
-
this.canvasRef.style.cursor = 'nw-resize';
|
|
610
|
-
this.hoveredAnnotation = found.annotation;
|
|
611
|
-
this.redrawAnnotations();
|
|
612
|
-
return;
|
|
613
|
-
}
|
|
614
|
-
// Regular hover over annotation
|
|
615
|
-
this.canvasRef.style.cursor = 'grab';
|
|
616
|
-
if (this.hoveredAnnotation !== found.annotation) {
|
|
617
|
-
this.hoveredAnnotation = found.annotation;
|
|
618
|
-
this.redrawAnnotations();
|
|
619
|
-
}
|
|
620
|
-
}
|
|
621
|
-
else {
|
|
622
|
-
// No annotation under cursor
|
|
623
|
-
this.canvasRef.style.cursor = 'crosshair';
|
|
624
|
-
if (this.hoveredAnnotation) {
|
|
625
|
-
this.hoveredAnnotation = null;
|
|
626
|
-
this.redrawAnnotations();
|
|
627
|
-
}
|
|
628
|
-
}
|
|
629
|
-
};
|
|
630
|
-
this.handleCanvasMouseUp = () => {
|
|
631
|
-
// Disable drawing on mobile devices
|
|
632
|
-
if (window.innerWidth <= 768)
|
|
633
|
-
return;
|
|
634
|
-
// Handle end of resizing
|
|
635
|
-
if (this.isResizing) {
|
|
636
|
-
this.isResizing = false;
|
|
637
|
-
this.resizingAnnotation = null;
|
|
638
|
-
this.dragStartPos = null;
|
|
639
|
-
this.resizeHandle = false;
|
|
640
|
-
this.resizeStartDimensions = null;
|
|
641
|
-
if (this.canvasRef) {
|
|
642
|
-
this.canvasRef.style.cursor = 'crosshair';
|
|
643
|
-
}
|
|
644
|
-
return;
|
|
645
|
-
}
|
|
646
|
-
// Handle end of dragging
|
|
647
|
-
if (this.isDragging) {
|
|
648
|
-
this.isDragging = false;
|
|
649
|
-
this.draggedAnnotation = null;
|
|
650
|
-
this.dragStartPos = null;
|
|
651
|
-
if (this.canvasRef) {
|
|
652
|
-
this.canvasRef.style.cursor = 'crosshair';
|
|
653
|
-
}
|
|
654
|
-
return;
|
|
655
|
-
}
|
|
656
|
-
// Handle end of drawing
|
|
657
|
-
if (!this.isDrawing || !this.currentAnnotation)
|
|
658
|
-
return;
|
|
659
|
-
this.isDrawing = false;
|
|
660
|
-
this.annotations = [...this.annotations, this.currentAnnotation];
|
|
661
|
-
this.currentAnnotation = null;
|
|
662
|
-
this.redrawAnnotations();
|
|
663
|
-
};
|
|
664
|
-
// Draw resize handles for rectangle annotation (only bottom-right corner)
|
|
665
|
-
this.drawRectangleResizeHandles = (annotation) => {
|
|
666
|
-
if (!this.canvasContext || annotation.type !== 'rectangle')
|
|
667
|
-
return;
|
|
668
|
-
const handleSize = 8;
|
|
669
|
-
const right = annotation.startX + annotation.width;
|
|
670
|
-
const bottom = annotation.startY + annotation.height;
|
|
671
|
-
// Only draw bottom-right corner handle
|
|
672
|
-
const handle = { x: right, y: bottom };
|
|
673
|
-
// Draw the handle
|
|
674
|
-
this.canvasContext.fillStyle = '#0070F4'; // Primary color
|
|
675
|
-
this.canvasContext.strokeStyle = '#ffffff';
|
|
676
|
-
this.canvasContext.lineWidth = 2;
|
|
677
|
-
this.canvasContext.fillRect(handle.x - handleSize / 2, handle.y - handleSize / 2, handleSize, handleSize);
|
|
678
|
-
this.canvasContext.strokeRect(handle.x - handleSize / 2, handle.y - handleSize / 2, handleSize, handleSize);
|
|
679
|
-
};
|
|
680
|
-
// Draw resize handles for line/arrow annotation
|
|
681
|
-
this.drawLineResizeHandles = (annotation) => {
|
|
682
|
-
if (!this.canvasContext || (annotation.type !== 'line' && annotation.type !== 'arrow'))
|
|
683
|
-
return;
|
|
684
|
-
const handleSize = 8;
|
|
685
|
-
// Define handle positions (2 endpoints)
|
|
686
|
-
const handles = [
|
|
687
|
-
{ x: annotation.startX, y: annotation.startY },
|
|
688
|
-
{ x: annotation.endX, y: annotation.endY } // End point
|
|
689
|
-
];
|
|
690
|
-
// Draw each handle
|
|
691
|
-
this.canvasContext.fillStyle = '#0070F4'; // Primary color
|
|
692
|
-
this.canvasContext.strokeStyle = '#ffffff';
|
|
693
|
-
this.canvasContext.lineWidth = 2;
|
|
694
|
-
handles.forEach(handle => {
|
|
695
|
-
this.canvasContext.fillRect(handle.x - handleSize / 2, handle.y - handleSize / 2, handleSize, handleSize);
|
|
696
|
-
this.canvasContext.strokeRect(handle.x - handleSize / 2, handle.y - handleSize / 2, handleSize, handleSize);
|
|
697
|
-
});
|
|
698
|
-
};
|
|
699
|
-
// Convert screen coordinates to canvas coordinates
|
|
700
|
-
this.getCanvasCoordinates = (event) => {
|
|
701
|
-
if (!this.canvasRef)
|
|
702
|
-
return { x: 0, y: 0 };
|
|
703
|
-
const rect = this.canvasRef.getBoundingClientRect();
|
|
704
|
-
// Calculate the scale factor between display size and actual canvas size
|
|
705
|
-
const scaleX = this.canvasRef.width / rect.width;
|
|
706
|
-
const scaleY = this.canvasRef.height / rect.height;
|
|
707
|
-
const x = (event.clientX - rect.left) * scaleX;
|
|
708
|
-
const y = (event.clientY - rect.top) * scaleY;
|
|
709
|
-
return { x, y };
|
|
710
|
-
};
|
|
711
|
-
// Find annotation under mouse cursor
|
|
712
|
-
this.findAnnotationAt = (x, y) => {
|
|
713
|
-
// Check in reverse order (top to bottom)
|
|
714
|
-
for (let i = this.annotations.length - 1; i >= 0; i--) {
|
|
715
|
-
const annotation = this.annotations[i];
|
|
716
|
-
if (this.isPointInAnnotation(x, y, annotation)) {
|
|
717
|
-
return { annotation, index: i };
|
|
718
|
-
}
|
|
719
|
-
}
|
|
720
|
-
return null;
|
|
721
|
-
};
|
|
722
|
-
// Check if point is within annotation bounds
|
|
723
|
-
this.isPointInAnnotation = (x, y, annotation) => {
|
|
724
|
-
const tolerance = 10; // Click tolerance
|
|
725
|
-
switch (annotation.type) {
|
|
726
|
-
case 'rectangle':
|
|
727
|
-
const left = Math.min(annotation.startX, annotation.startX + annotation.width);
|
|
728
|
-
const right = Math.max(annotation.startX, annotation.startX + annotation.width);
|
|
729
|
-
const top = Math.min(annotation.startY, annotation.startY + annotation.height);
|
|
730
|
-
const bottom = Math.max(annotation.startY, annotation.startY + annotation.height);
|
|
731
|
-
return x >= left - tolerance && x <= right + tolerance &&
|
|
732
|
-
y >= top - tolerance && y <= bottom + tolerance;
|
|
733
|
-
case 'line':
|
|
734
|
-
case 'arrow':
|
|
735
|
-
// Distance from point to line
|
|
736
|
-
const A = annotation.endY - annotation.startY;
|
|
737
|
-
const B = annotation.startX - annotation.endX;
|
|
738
|
-
const C = annotation.endX * annotation.startY - annotation.startX * annotation.endY;
|
|
739
|
-
const distance = Math.abs(A * x + B * y + C) / Math.sqrt(A * A + B * B);
|
|
740
|
-
return distance <= tolerance;
|
|
741
|
-
case 'text':
|
|
742
|
-
// Simple bounding box for text
|
|
743
|
-
return x >= annotation.x - tolerance && x <= annotation.x + 100 &&
|
|
744
|
-
y >= annotation.y - 20 && y <= annotation.y + tolerance;
|
|
745
|
-
default:
|
|
746
|
-
return false;
|
|
747
|
-
}
|
|
748
|
-
};
|
|
749
|
-
// Handle resize for different annotation types
|
|
750
|
-
this.handleResize = (currentPos) => {
|
|
751
|
-
if (!this.resizingAnnotation || !this.dragStartPos)
|
|
752
|
-
return;
|
|
753
|
-
const annotation = this.resizingAnnotation;
|
|
754
|
-
const index = this.annotations.findIndex(a => a === annotation);
|
|
755
|
-
if (index === -1)
|
|
756
|
-
return;
|
|
757
|
-
let updatedAnnotation = Object.assign({}, annotation);
|
|
758
|
-
switch (annotation.type) {
|
|
759
|
-
case 'text':
|
|
760
|
-
// Text resize logic (existing)
|
|
761
|
-
const deltaX = currentPos.x - this.dragStartPos.x;
|
|
762
|
-
const deltaY = currentPos.y - this.dragStartPos.y;
|
|
763
|
-
const avgDelta = (deltaX + deltaY) / 2;
|
|
764
|
-
const newSize = Math.max(8, Math.min(72, this.resizeStartSize + avgDelta * 0.5));
|
|
765
|
-
updatedAnnotation.fontSize = Math.round(newSize);
|
|
766
|
-
break;
|
|
767
|
-
case 'rectangle':
|
|
768
|
-
// Rectangle resize logic - only bottom-right corner
|
|
769
|
-
const rectDeltaX = currentPos.x - this.dragStartPos.x;
|
|
770
|
-
const rectDeltaY = currentPos.y - this.dragStartPos.y;
|
|
771
|
-
// Update width and height based on original dimensions plus delta
|
|
772
|
-
updatedAnnotation.width = Math.max(10, this.resizeStartDimensions.width + rectDeltaX); // Minimum width of 10px
|
|
773
|
-
updatedAnnotation.height = Math.max(10, this.resizeStartDimensions.height + rectDeltaY); // Minimum height of 10px
|
|
774
|
-
break;
|
|
775
|
-
case 'line':
|
|
776
|
-
case 'arrow':
|
|
777
|
-
// Line/arrow resize logic - move endpoints
|
|
778
|
-
if (this.resizeHandle === 'start') {
|
|
779
|
-
updatedAnnotation.startX = currentPos.x;
|
|
780
|
-
updatedAnnotation.startY = currentPos.y;
|
|
781
|
-
}
|
|
782
|
-
else if (this.resizeHandle === 'end') {
|
|
783
|
-
updatedAnnotation.endX = currentPos.x;
|
|
784
|
-
updatedAnnotation.endY = currentPos.y;
|
|
785
|
-
}
|
|
786
|
-
break;
|
|
787
|
-
}
|
|
788
|
-
// Update annotation in array
|
|
789
|
-
this.annotations[index] = updatedAnnotation;
|
|
790
|
-
this.resizingAnnotation = updatedAnnotation;
|
|
791
|
-
this.redrawAnnotations();
|
|
792
141
|
};
|
|
793
142
|
this.sending = false;
|
|
794
143
|
this.formMessage = '';
|
|
@@ -804,28 +153,10 @@ export class FeedbackModal {
|
|
|
804
153
|
this.overlayVisible = false;
|
|
805
154
|
this.isAnimating = false;
|
|
806
155
|
this.takingScreenshot = false;
|
|
807
|
-
this.showPreviewModal = false;
|
|
808
|
-
this.screenshotError = '';
|
|
809
156
|
this.showScreenshotError = false;
|
|
157
|
+
this.screenshotError = '';
|
|
810
158
|
this.showCanvasEditor = false;
|
|
811
|
-
this.
|
|
812
|
-
this.canvasDrawingColor = '#ff0000';
|
|
813
|
-
this.canvasLineWidth = 3;
|
|
814
|
-
this.isDrawing = false;
|
|
815
|
-
this.annotations = [];
|
|
816
|
-
this.currentAnnotation = null;
|
|
817
|
-
this.isDragging = false;
|
|
818
|
-
this.draggedAnnotation = null;
|
|
819
|
-
this.dragStartPos = null;
|
|
820
|
-
this.showColorPicker = false;
|
|
821
|
-
this.editingColorIndex = -1;
|
|
822
|
-
this.isResizing = false;
|
|
823
|
-
this.resizingAnnotation = null;
|
|
824
|
-
this.resizeStartSize = 16;
|
|
825
|
-
this.resizeStartDimensions = null;
|
|
826
|
-
this.hoveredAnnotation = null;
|
|
827
|
-
this.resizeHandle = false;
|
|
828
|
-
this.defaultColors = ['#ff0000', '#00ff00', '#0000ff', '#000000'];
|
|
159
|
+
this.autoStartCapture = false;
|
|
829
160
|
this.customFont = false;
|
|
830
161
|
this.emailAddress = '';
|
|
831
162
|
this.hideEmail = false;
|
|
@@ -864,6 +195,17 @@ export class FeedbackModal {
|
|
|
864
195
|
this.canvasEditorTitle = 'Edit screenshot';
|
|
865
196
|
this.canvasEditorCancelText = 'Cancel';
|
|
866
197
|
this.canvasEditorSaveText = 'Save';
|
|
198
|
+
this.editTextButtonText = 'Edit Text';
|
|
199
|
+
this.sizeLabelText = 'Size:';
|
|
200
|
+
this.borderLabelText = 'Border:';
|
|
201
|
+
this.editTextPromptText = 'Edit text:';
|
|
202
|
+
this.screenshotErrorGeneral = 'Failed to capture screenshot.';
|
|
203
|
+
this.screenshotErrorPermission = 'Permission denied. Please allow screen sharing to take screenshots.';
|
|
204
|
+
this.screenshotErrorNotSupported = 'Screen capture is not supported in this browser.';
|
|
205
|
+
this.screenshotErrorNotFound = 'No screen sources available for capture.';
|
|
206
|
+
this.screenshotErrorCancelled = 'Screenshot capture was cancelled.';
|
|
207
|
+
this.screenshotErrorBrowserNotSupported = 'Your browser does not support screen capture. Please use a browser like Chrome, Firefox, or Safari.';
|
|
208
|
+
this.screenshotErrorUnexpected = 'An unexpected error occurred. Please try again.';
|
|
867
209
|
}
|
|
868
210
|
componentWillLoad() {
|
|
869
211
|
if (this.fetchData)
|
|
@@ -898,63 +240,6 @@ export class FeedbackModal {
|
|
|
898
240
|
handleEmailInput(event) {
|
|
899
241
|
this.formEmail = event.target.value;
|
|
900
242
|
}
|
|
901
|
-
async captureViewportScreenshot() {
|
|
902
|
-
try {
|
|
903
|
-
// Check if Screen Capture API is supported
|
|
904
|
-
if (!navigator.mediaDevices || !navigator.mediaDevices.getDisplayMedia) {
|
|
905
|
-
throw new Error('Screen Capture API is not supported in this browser');
|
|
906
|
-
}
|
|
907
|
-
// Request screen capture with preference for current tab
|
|
908
|
-
const stream = await navigator.mediaDevices.getDisplayMedia({
|
|
909
|
-
video: {
|
|
910
|
-
mediaSource: 'screen',
|
|
911
|
-
width: { ideal: window.innerWidth },
|
|
912
|
-
height: { ideal: window.innerHeight }
|
|
913
|
-
},
|
|
914
|
-
audio: false,
|
|
915
|
-
preferCurrentTab: true
|
|
916
|
-
});
|
|
917
|
-
// Create video element to capture frame
|
|
918
|
-
const video = document.createElement('video');
|
|
919
|
-
video.srcObject = stream;
|
|
920
|
-
video.autoplay = true;
|
|
921
|
-
video.muted = true;
|
|
922
|
-
return new Promise((resolve, reject) => {
|
|
923
|
-
video.onloadedmetadata = () => {
|
|
924
|
-
video.play();
|
|
925
|
-
// Wait a moment for video to stabilize
|
|
926
|
-
setTimeout(() => {
|
|
927
|
-
try {
|
|
928
|
-
// Create canvas to capture frame
|
|
929
|
-
const canvas = document.createElement('canvas');
|
|
930
|
-
canvas.width = video.videoWidth;
|
|
931
|
-
canvas.height = video.videoHeight;
|
|
932
|
-
const ctx = canvas.getContext('2d');
|
|
933
|
-
ctx.drawImage(video, 0, 0);
|
|
934
|
-
// Stop the stream
|
|
935
|
-
stream.getTracks().forEach(track => track.stop());
|
|
936
|
-
// Convert to data URL
|
|
937
|
-
const dataUrl = canvas.toDataURL('image/png');
|
|
938
|
-
console.log('Screenshot captured successfully using Screen Capture API');
|
|
939
|
-
resolve(dataUrl);
|
|
940
|
-
}
|
|
941
|
-
catch (error) {
|
|
942
|
-
stream.getTracks().forEach(track => track.stop());
|
|
943
|
-
reject(error);
|
|
944
|
-
}
|
|
945
|
-
}, 100);
|
|
946
|
-
};
|
|
947
|
-
video.onerror = (_) => {
|
|
948
|
-
stream.getTracks().forEach(track => track.stop());
|
|
949
|
-
reject(new Error('Failed to load video for screenshot capture'));
|
|
950
|
-
};
|
|
951
|
-
});
|
|
952
|
-
}
|
|
953
|
-
catch (error) {
|
|
954
|
-
console.error('Screen capture failed:', error);
|
|
955
|
-
throw error;
|
|
956
|
-
}
|
|
957
|
-
}
|
|
958
243
|
handleCheckboxChange(event) {
|
|
959
244
|
this.isPrivacyChecked = event.target.checked;
|
|
960
245
|
}
|
|
@@ -965,7 +250,7 @@ export class FeedbackModal {
|
|
|
965
250
|
this.selectedRating = newRating;
|
|
966
251
|
}
|
|
967
252
|
render() {
|
|
968
|
-
return (h("div", { class: `feedback-modal-wrapper ${this.customFont ? 'feedback-modal-wrapper--custom-font' : ''}` }, this.showScreenshotError && (h("div", { class: "screenshot-error-notification" }, h("div", { class: "screenshot-error-content" }, h("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" }, h("circle", { cx: "12", cy: "12", r: "10" }), h("line", { x1: "15", y1: "9", x2: "9", y2: "15" }), h("line", { x1: "9", y1: "9", x2: "15", y2: "15" })), h("span", null, this.screenshotError), h("button", { class: "error-close-btn", onClick: () => this.showScreenshotError = false, title: "Close" }, h("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" }, h("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), h("line", { x1: "6", y1: "6", x2: "18", y2: "18" })))))), this.showModal && (h("div", { class: `feedback-overlay ${this.isAnimating ? 'feedback-overlay--visible' : ''}` })), this.showModal && (h("div", { class: `feedback-modal-content feedback-modal-content--${this.modalPosition} ${this.isAnimating ? 'feedback-modal-content--open' : ''}`, ref: (el) => (this.modalContent = el) }, h("div", { class: "feedback-modal-header" }, !this.formSuccess && !this.formError ? (h("span", null, this.modalTitle)) : this.formSuccess ? (h("span", null, this.modalTitleSuccess)) : (h("span", null, this.modalTitleError)), h("button", { class: "feedback-modal-close", onClick: this.close }, h("svg", { xmlns: "http://www.w3.org/2000/svg", width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", stroke: "#191919", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", class: "feather feather-x" }, h("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), h("line", { x1: "6", y1: "6", x2: "18", y2: "18" })))), h("div", { class: "feedback-modal-body" }, !this.formSuccess && !this.formError ? (h("form", { onSubmit: this.handleSubmit }, !this.hideRating && (h("div", { class: "feedback-modal-rating" }, this.ratingMode === 'thumbs' ? (h("div", { class: "feedback-modal-rating-content" }, h("span", { class: "feedback-modal-input-heading" }, this.ratingPlaceholder), h("div", { class: "feedback-modal-rating-buttons feedback-modal-rating-buttons--thumbs" }, h("button", { title: "Yes", class: `feedback-modal-rating-button ${this.selectedRating === 1
|
|
253
|
+
return (h("div", { class: `feedback-modal-wrapper ${this.customFont ? 'feedback-modal-wrapper--custom-font' : ''}` }, this.showCanvasEditor && (h("canvas-editor", { ref: (el) => this.canvasEditorRef = el, "canvas-editor-title": this.canvasEditorTitle, "canvas-editor-cancel-text": this.canvasEditorCancelText, "canvas-editor-save-text": this.canvasEditorSaveText, "screenshot-taking-text": this.screenshotTakingText, "screenshot-attached-text": this.screenshotAttachedText, "screenshot-button-text": this.screenshotButtonText, "auto-start-screenshot": this.autoStartCapture, "existing-screenshot": this.encodedScreenshot || '', "edit-text-button-text": this.editTextButtonText, "size-label-text": this.sizeLabelText, "border-label-text": this.borderLabelText, "edit-text-prompt-text": this.editTextPromptText, "screenshot-error-general": this.screenshotErrorGeneral, "screenshot-error-permission": this.screenshotErrorPermission, "screenshot-error-not-supported": this.screenshotErrorNotSupported, "screenshot-error-not-found": this.screenshotErrorNotFound, "screenshot-error-cancelled": this.screenshotErrorCancelled, "screenshot-error-browser-not-supported": this.screenshotErrorBrowserNotSupported, "screenshot-error-unexpected": this.screenshotErrorUnexpected, onScreenshotReady: this.handleScreenshotReady, onScreenshotCancelled: this.handleScreenshotCancelled, onScreenshotFailed: this.handleScreenshotError })), this.showScreenshotError && (h("div", { class: "screenshot-error-notification" }, h("div", { class: "screenshot-error-content" }, h("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" }, h("circle", { cx: "12", cy: "12", r: "10" }), h("line", { x1: "15", y1: "9", x2: "9", y2: "15" }), h("line", { x1: "9", y1: "9", x2: "15", y2: "15" })), h("span", null, this.screenshotError), h("button", { class: "error-close-btn", onClick: () => this.showScreenshotError = false, title: "Close" }, h("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" }, h("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), h("line", { x1: "6", y1: "6", x2: "18", y2: "18" })))))), this.showModal && (h("div", { class: `feedback-overlay ${this.isAnimating ? 'feedback-overlay--visible' : ''}` })), this.showModal && (h("div", { class: `feedback-modal-content feedback-modal-content--${this.modalPosition} ${this.isAnimating ? 'feedback-modal-content--open' : ''}`, ref: (el) => (this.modalContent = el) }, h("div", { class: "feedback-modal-header" }, !this.formSuccess && !this.formError ? (h("span", null, this.modalTitle)) : this.formSuccess ? (h("span", null, this.modalTitleSuccess)) : (h("span", null, this.modalTitleError)), h("button", { class: "feedback-modal-close", onClick: this.close }, h("svg", { xmlns: "http://www.w3.org/2000/svg", width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", stroke: "#191919", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", class: "feather feather-x" }, h("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), h("line", { x1: "6", y1: "6", x2: "18", y2: "18" })))), h("div", { class: "feedback-modal-body" }, !this.formSuccess && !this.formError ? (h("form", { onSubmit: this.handleSubmit }, !this.hideRating && (h("div", { class: "feedback-modal-rating" }, this.ratingMode === 'thumbs' ? (h("div", { class: "feedback-modal-rating-content" }, h("span", { class: "feedback-modal-input-heading" }, this.ratingPlaceholder), h("div", { class: "feedback-modal-rating-buttons feedback-modal-rating-buttons--thumbs" }, h("button", { title: "Yes", class: `feedback-modal-rating-button ${this.selectedRating === 1
|
|
969
254
|
? 'feedback-modal-rating-button--selected'
|
|
970
255
|
: ''}`, onClick: (event) => {
|
|
971
256
|
event.preventDefault();
|
|
@@ -981,7 +266,7 @@ export class FeedbackModal {
|
|
|
981
266
|
event.preventDefault();
|
|
982
267
|
this.handleRatingChange(rating);
|
|
983
268
|
} }, h("svg", { xmlns: "http://www.w3.org/2000/svg", width: "28", height: "28", viewBox: "0 0 24 24", fill: "none", stroke: "#5F6368", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" }, h("polygon", { points: "12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2" })))))))))), h("div", { class: "feedback-modal-text" }, h("textarea", { placeholder: this.messagePlaceholder, value: this.formMessage, onInput: (event) => this.handleMessageInput(event) })), !this.hideEmail && (h("div", { class: "feedback-modal-email" }, h("input", { placeholder: this.emailPlaceholder, type: "email", onInput: (event) => this.handleEmailInput(event), value: this.formEmail, required: this.isEmailRequired }))), h("div", { class: "feedback-verification" }, h("input", { type: "text", name: "verification", style: { display: 'none' }, onInput: (event) => this.handleVerification(event), value: this.formVerification })), !this.hidePrivacyPolicy && (h("div", { class: "feedback-modal-privacy" }, h("input", { type: "checkbox", id: "privacyPolicy", onChange: (ev) => this.handleCheckboxChange(ev), required: true }), h("span", { innerHTML: this.privacyPolicyText }))), h("div", { class: `feedback-modal-buttons ${this.hideScreenshotButton ? 'single' : ''}` }, !this.hideScreenshotButton && (h("button", { type: "button", class: `feedback-modal-button feedback-modal-button--screenshot ${this.encodedScreenshot ? 'feedback-modal-button--active' : ''}`, onClick: this.openScreenShot, disabled: this.sending || this.takingScreenshot }, this.encodedScreenshot && (h("div", { class: "screenshot-preview", onClick: this.openCanvasEditor }, h("img", { src: this.encodedScreenshot, alt: "Screenshot Preview" }))), !this.encodedScreenshot && !this.takingScreenshot && (h("svg", { xmlns: "http://www.w3.org/2000/svg", height: "24", viewBox: "0 -960 960 960", width: "24" }, h("path", { d: "M680-80v-120H560v-80h120v-120h80v120h120v80H760v120h-80ZM200-200v-200h80v120h120v80H200Zm0-360v-200h200v80H280v120h-80Zm480 0v-120H560v-80h200v200h-80Z" }))), this.takingScreenshot && (h("div", { class: "screenshot-loading" }, h("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "#666", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", class: "feather-loader" }, h("line", { x1: "12", y1: "2", x2: "12", y2: "6" }), h("line", { x1: "12", y1: "18", x2: "12", y2: "22" }), h("line", { x1: "4.93", y1: "4.93", x2: "7.76", y2: "7.76" }), h("line", { x1: "16.24", y1: "16.24", x2: "19.07", y2: "19.07" }), h("line", { x1: "2", y1: "12", x2: "6", y2: "12" }), h("line", { x1: "18", y1: "12", x2: "22", y2: "12" }), h("line", { x1: "4.93", y1: "19.07", x2: "7.76", y2: "16.24" }), h("line", { x1: "16.24", y1: "7.76", x2: "19.07", y2: "4.93" })))), this.takingScreenshot ? this.screenshotTakingText :
|
|
984
|
-
this.encodedScreenshot ? this.screenshotAttachedText : this.screenshotButtonText)), h("button", { class: "feedback-modal-button feedback-modal-button--submit", type: "submit", disabled: this.sending }, this.sendButtonText)))) : this.formSuccess && !this.formError ? (h("div", { class: "feedback-modal-success" }, h("p", { class: "feedback-modal-message" }, this.successMessage))) : this.formError && this.formErrorStatus == 404 ? (h("p", { class: "feedback-modal-message" }, this.errorMessage404)) : this.formError && this.formErrorStatus == 403 ? (h("p", { class: "feedback-modal-message" }, this.errorMessage403)) : this.formError ? (h("p", { class: "feedback-modal-message" }, this.errorMessage)) : (h("span", null))), h("div", { class: "feedback-modal-footer" }, h("div", { class: "feedback-logo", style: { display: this.whitelabel ? 'none' : 'block' } }, "Powered by", ' ', h("a", { target: "_blank", href: "https://pushfeedback.com" }, "PushFeedback.com")), this.footerText && (h("div", { class: "feedback-footer-text" }, h("span", { innerHTML: this.footerText }))))))
|
|
269
|
+
this.encodedScreenshot ? this.screenshotAttachedText : this.screenshotButtonText)), h("button", { class: "feedback-modal-button feedback-modal-button--submit", type: "submit", disabled: this.sending }, this.sendButtonText)))) : this.formSuccess && !this.formError ? (h("div", { class: "feedback-modal-success" }, h("p", { class: "feedback-modal-message" }, this.successMessage))) : this.formError && this.formErrorStatus == 404 ? (h("p", { class: "feedback-modal-message" }, this.errorMessage404)) : this.formError && this.formErrorStatus == 403 ? (h("p", { class: "feedback-modal-message" }, this.errorMessage403)) : this.formError ? (h("p", { class: "feedback-modal-message" }, this.errorMessage)) : (h("span", null))), h("div", { class: "feedback-modal-footer" }, h("div", { class: "feedback-logo", style: { display: this.whitelabel ? 'none' : 'block' } }, "Powered by", ' ', h("a", { target: "_blank", href: "https://pushfeedback.com" }, "PushFeedback.com")), this.footerText && (h("div", { class: "feedback-footer-text" }, h("span", { innerHTML: this.footerText }))))))));
|
|
985
270
|
}
|
|
986
271
|
componentDidRender() {
|
|
987
272
|
if (this.showModal) {
|
|
@@ -1693,6 +978,204 @@ export class FeedbackModal {
|
|
|
1693
978
|
"attribute": "canvas-editor-save-text",
|
|
1694
979
|
"reflect": false,
|
|
1695
980
|
"defaultValue": "'Save'"
|
|
981
|
+
},
|
|
982
|
+
"editTextButtonText": {
|
|
983
|
+
"type": "string",
|
|
984
|
+
"mutable": false,
|
|
985
|
+
"complexType": {
|
|
986
|
+
"original": "string",
|
|
987
|
+
"resolved": "string",
|
|
988
|
+
"references": {}
|
|
989
|
+
},
|
|
990
|
+
"required": false,
|
|
991
|
+
"optional": false,
|
|
992
|
+
"docs": {
|
|
993
|
+
"tags": [],
|
|
994
|
+
"text": ""
|
|
995
|
+
},
|
|
996
|
+
"attribute": "edit-text-button-text",
|
|
997
|
+
"reflect": false,
|
|
998
|
+
"defaultValue": "'Edit Text'"
|
|
999
|
+
},
|
|
1000
|
+
"sizeLabelText": {
|
|
1001
|
+
"type": "string",
|
|
1002
|
+
"mutable": false,
|
|
1003
|
+
"complexType": {
|
|
1004
|
+
"original": "string",
|
|
1005
|
+
"resolved": "string",
|
|
1006
|
+
"references": {}
|
|
1007
|
+
},
|
|
1008
|
+
"required": false,
|
|
1009
|
+
"optional": false,
|
|
1010
|
+
"docs": {
|
|
1011
|
+
"tags": [],
|
|
1012
|
+
"text": ""
|
|
1013
|
+
},
|
|
1014
|
+
"attribute": "size-label-text",
|
|
1015
|
+
"reflect": false,
|
|
1016
|
+
"defaultValue": "'Size:'"
|
|
1017
|
+
},
|
|
1018
|
+
"borderLabelText": {
|
|
1019
|
+
"type": "string",
|
|
1020
|
+
"mutable": false,
|
|
1021
|
+
"complexType": {
|
|
1022
|
+
"original": "string",
|
|
1023
|
+
"resolved": "string",
|
|
1024
|
+
"references": {}
|
|
1025
|
+
},
|
|
1026
|
+
"required": false,
|
|
1027
|
+
"optional": false,
|
|
1028
|
+
"docs": {
|
|
1029
|
+
"tags": [],
|
|
1030
|
+
"text": ""
|
|
1031
|
+
},
|
|
1032
|
+
"attribute": "border-label-text",
|
|
1033
|
+
"reflect": false,
|
|
1034
|
+
"defaultValue": "'Border:'"
|
|
1035
|
+
},
|
|
1036
|
+
"editTextPromptText": {
|
|
1037
|
+
"type": "string",
|
|
1038
|
+
"mutable": false,
|
|
1039
|
+
"complexType": {
|
|
1040
|
+
"original": "string",
|
|
1041
|
+
"resolved": "string",
|
|
1042
|
+
"references": {}
|
|
1043
|
+
},
|
|
1044
|
+
"required": false,
|
|
1045
|
+
"optional": false,
|
|
1046
|
+
"docs": {
|
|
1047
|
+
"tags": [],
|
|
1048
|
+
"text": ""
|
|
1049
|
+
},
|
|
1050
|
+
"attribute": "edit-text-prompt-text",
|
|
1051
|
+
"reflect": false,
|
|
1052
|
+
"defaultValue": "'Edit text:'"
|
|
1053
|
+
},
|
|
1054
|
+
"screenshotErrorGeneral": {
|
|
1055
|
+
"type": "string",
|
|
1056
|
+
"mutable": false,
|
|
1057
|
+
"complexType": {
|
|
1058
|
+
"original": "string",
|
|
1059
|
+
"resolved": "string",
|
|
1060
|
+
"references": {}
|
|
1061
|
+
},
|
|
1062
|
+
"required": false,
|
|
1063
|
+
"optional": false,
|
|
1064
|
+
"docs": {
|
|
1065
|
+
"tags": [],
|
|
1066
|
+
"text": ""
|
|
1067
|
+
},
|
|
1068
|
+
"attribute": "screenshot-error-general",
|
|
1069
|
+
"reflect": false,
|
|
1070
|
+
"defaultValue": "'Failed to capture screenshot.'"
|
|
1071
|
+
},
|
|
1072
|
+
"screenshotErrorPermission": {
|
|
1073
|
+
"type": "string",
|
|
1074
|
+
"mutable": false,
|
|
1075
|
+
"complexType": {
|
|
1076
|
+
"original": "string",
|
|
1077
|
+
"resolved": "string",
|
|
1078
|
+
"references": {}
|
|
1079
|
+
},
|
|
1080
|
+
"required": false,
|
|
1081
|
+
"optional": false,
|
|
1082
|
+
"docs": {
|
|
1083
|
+
"tags": [],
|
|
1084
|
+
"text": ""
|
|
1085
|
+
},
|
|
1086
|
+
"attribute": "screenshot-error-permission",
|
|
1087
|
+
"reflect": false,
|
|
1088
|
+
"defaultValue": "'Permission denied. Please allow screen sharing to take screenshots.'"
|
|
1089
|
+
},
|
|
1090
|
+
"screenshotErrorNotSupported": {
|
|
1091
|
+
"type": "string",
|
|
1092
|
+
"mutable": false,
|
|
1093
|
+
"complexType": {
|
|
1094
|
+
"original": "string",
|
|
1095
|
+
"resolved": "string",
|
|
1096
|
+
"references": {}
|
|
1097
|
+
},
|
|
1098
|
+
"required": false,
|
|
1099
|
+
"optional": false,
|
|
1100
|
+
"docs": {
|
|
1101
|
+
"tags": [],
|
|
1102
|
+
"text": ""
|
|
1103
|
+
},
|
|
1104
|
+
"attribute": "screenshot-error-not-supported",
|
|
1105
|
+
"reflect": false,
|
|
1106
|
+
"defaultValue": "'Screen capture is not supported in this browser.'"
|
|
1107
|
+
},
|
|
1108
|
+
"screenshotErrorNotFound": {
|
|
1109
|
+
"type": "string",
|
|
1110
|
+
"mutable": false,
|
|
1111
|
+
"complexType": {
|
|
1112
|
+
"original": "string",
|
|
1113
|
+
"resolved": "string",
|
|
1114
|
+
"references": {}
|
|
1115
|
+
},
|
|
1116
|
+
"required": false,
|
|
1117
|
+
"optional": false,
|
|
1118
|
+
"docs": {
|
|
1119
|
+
"tags": [],
|
|
1120
|
+
"text": ""
|
|
1121
|
+
},
|
|
1122
|
+
"attribute": "screenshot-error-not-found",
|
|
1123
|
+
"reflect": false,
|
|
1124
|
+
"defaultValue": "'No screen sources available for capture.'"
|
|
1125
|
+
},
|
|
1126
|
+
"screenshotErrorCancelled": {
|
|
1127
|
+
"type": "string",
|
|
1128
|
+
"mutable": false,
|
|
1129
|
+
"complexType": {
|
|
1130
|
+
"original": "string",
|
|
1131
|
+
"resolved": "string",
|
|
1132
|
+
"references": {}
|
|
1133
|
+
},
|
|
1134
|
+
"required": false,
|
|
1135
|
+
"optional": false,
|
|
1136
|
+
"docs": {
|
|
1137
|
+
"tags": [],
|
|
1138
|
+
"text": ""
|
|
1139
|
+
},
|
|
1140
|
+
"attribute": "screenshot-error-cancelled",
|
|
1141
|
+
"reflect": false,
|
|
1142
|
+
"defaultValue": "'Screenshot capture was cancelled.'"
|
|
1143
|
+
},
|
|
1144
|
+
"screenshotErrorBrowserNotSupported": {
|
|
1145
|
+
"type": "string",
|
|
1146
|
+
"mutable": false,
|
|
1147
|
+
"complexType": {
|
|
1148
|
+
"original": "string",
|
|
1149
|
+
"resolved": "string",
|
|
1150
|
+
"references": {}
|
|
1151
|
+
},
|
|
1152
|
+
"required": false,
|
|
1153
|
+
"optional": false,
|
|
1154
|
+
"docs": {
|
|
1155
|
+
"tags": [],
|
|
1156
|
+
"text": ""
|
|
1157
|
+
},
|
|
1158
|
+
"attribute": "screenshot-error-browser-not-supported",
|
|
1159
|
+
"reflect": false,
|
|
1160
|
+
"defaultValue": "'Your browser does not support screen capture. Please use a browser like Chrome, Firefox, or Safari.'"
|
|
1161
|
+
},
|
|
1162
|
+
"screenshotErrorUnexpected": {
|
|
1163
|
+
"type": "string",
|
|
1164
|
+
"mutable": false,
|
|
1165
|
+
"complexType": {
|
|
1166
|
+
"original": "string",
|
|
1167
|
+
"resolved": "string",
|
|
1168
|
+
"references": {}
|
|
1169
|
+
},
|
|
1170
|
+
"required": false,
|
|
1171
|
+
"optional": false,
|
|
1172
|
+
"docs": {
|
|
1173
|
+
"tags": [],
|
|
1174
|
+
"text": ""
|
|
1175
|
+
},
|
|
1176
|
+
"attribute": "screenshot-error-unexpected",
|
|
1177
|
+
"reflect": false,
|
|
1178
|
+
"defaultValue": "'An unexpected error occurred. Please try again.'"
|
|
1696
1179
|
}
|
|
1697
1180
|
};
|
|
1698
1181
|
}
|
|
@@ -1712,28 +1195,10 @@ export class FeedbackModal {
|
|
|
1712
1195
|
"overlayVisible": {},
|
|
1713
1196
|
"isAnimating": {},
|
|
1714
1197
|
"takingScreenshot": {},
|
|
1715
|
-
"showPreviewModal": {},
|
|
1716
|
-
"screenshotError": {},
|
|
1717
1198
|
"showScreenshotError": {},
|
|
1199
|
+
"screenshotError": {},
|
|
1718
1200
|
"showCanvasEditor": {},
|
|
1719
|
-
"
|
|
1720
|
-
"canvasDrawingColor": {},
|
|
1721
|
-
"canvasLineWidth": {},
|
|
1722
|
-
"isDrawing": {},
|
|
1723
|
-
"annotations": {},
|
|
1724
|
-
"currentAnnotation": {},
|
|
1725
|
-
"isDragging": {},
|
|
1726
|
-
"draggedAnnotation": {},
|
|
1727
|
-
"dragStartPos": {},
|
|
1728
|
-
"showColorPicker": {},
|
|
1729
|
-
"editingColorIndex": {},
|
|
1730
|
-
"isResizing": {},
|
|
1731
|
-
"resizingAnnotation": {},
|
|
1732
|
-
"resizeStartSize": {},
|
|
1733
|
-
"resizeStartDimensions": {},
|
|
1734
|
-
"hoveredAnnotation": {},
|
|
1735
|
-
"resizeHandle": {},
|
|
1736
|
-
"defaultColors": {}
|
|
1201
|
+
"autoStartCapture": {}
|
|
1737
1202
|
};
|
|
1738
1203
|
}
|
|
1739
1204
|
static get events() {
|