@dynamicu/chromedebug-mcp 2.6.7 → 2.7.0
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/CLAUDE.md +1 -1
- package/README.md +1 -1
- package/chrome-extension/background.js +611 -505
- package/chrome-extension/browser-recording-manager.js +1 -1
- package/chrome-extension/chrome-debug-logger.js +168 -0
- package/chrome-extension/console-interception-library.js +430 -0
- package/chrome-extension/content.css +16 -16
- package/chrome-extension/content.js +458 -126
- package/chrome-extension/extension-config.js +1 -1
- package/chrome-extension/license-helper.js +26 -0
- package/chrome-extension/manifest.free.json +0 -3
- package/chrome-extension/options.js +1 -1
- package/chrome-extension/popup.html +221 -191
- package/chrome-extension/popup.js +88 -379
- package/chrome-extension/pro/enhanced-capture.js +406 -0
- package/chrome-extension/pro/frame-editor.html +410 -0
- package/chrome-extension/pro/frame-editor.js +1496 -0
- package/chrome-extension/pro/function-tracker.js +843 -0
- package/chrome-extension/pro/jszip.min.js +13 -0
- package/dist/chromedebug-extension-free.zip +0 -0
- package/package.json +3 -1
- package/scripts/webpack.config.free.cjs +8 -8
- package/scripts/webpack.config.pro.cjs +2 -0
- package/src/cli.js +2 -2
- package/src/database.js +55 -7
- package/src/index.js +9 -6
- package/src/mcp/server.js +2 -2
- package/src/services/process-manager.js +10 -6
- package/src/services/process-tracker.js +10 -5
- package/src/services/profile-manager.js +17 -2
- package/src/validation/schemas.js +2 -2
- package/src/index-direct.js +0 -157
- package/src/index-modular.js +0 -219
- package/src/index-monolithic-backup.js +0 -2230
- package/src/legacy/chrome-controller-old.js +0 -1406
- package/src/legacy/index-express.js +0 -625
- package/src/legacy/index-old.js +0 -977
- package/src/legacy/routes.js +0 -260
- package/src/legacy/shared-storage.js +0 -101
|
@@ -297,7 +297,7 @@ function getSelector(element) {
|
|
|
297
297
|
}
|
|
298
298
|
|
|
299
299
|
if (element.className && typeof element.className === 'string') {
|
|
300
|
-
const classes = element.className.trim().split(/\s+/).filter(c => !c.startsWith('chrome-
|
|
300
|
+
const classes = element.className.trim().split(/\s+/).filter(c => !c.startsWith('chrome-debug'));
|
|
301
301
|
if (classes.length > 0) {
|
|
302
302
|
return `${element.tagName.toLowerCase()}.${classes.join('.')}`;
|
|
303
303
|
}
|
|
@@ -460,7 +460,7 @@ if (isExtensionValid()) {
|
|
|
460
460
|
// Show the recording ID in the floating UI
|
|
461
461
|
console.log('Recording complete with ID:', request.recordingId);
|
|
462
462
|
if (recordingOverlay) {
|
|
463
|
-
const statusDiv = document.getElementById('chrome-
|
|
463
|
+
const statusDiv = document.getElementById('chrome-debug-recording-status');
|
|
464
464
|
if (statusDiv && request.recordingId) {
|
|
465
465
|
statusDiv.innerHTML = `<strong style="color: #4CAF50;">Recording saved!</strong><br>ID: <code style="background: #f0f0f0; padding: 2px 6px; border-radius: 3px; font-family: monospace;">${request.recordingId}</code>`;
|
|
466
466
|
|
|
@@ -494,14 +494,31 @@ if (isExtensionValid()) {
|
|
|
494
494
|
sendResponse({ success: true });
|
|
495
495
|
} else if (request.action === 'startWorkflowRecording') {
|
|
496
496
|
console.log('[ChromeDebug MCP] Starting workflow recording with settings:', request.screenshotSettings);
|
|
497
|
+
// Store tabId for use when stopping recording from mini-menu
|
|
498
|
+
workflowTabId = request.tabId;
|
|
497
499
|
startWorkflowRecording(request.screenshotSettings);
|
|
498
500
|
sendResponse({ success: true });
|
|
499
|
-
} else if (request.action === '
|
|
500
|
-
|
|
501
|
-
|
|
501
|
+
} else if (request.action === 'getWorkflowData') {
|
|
502
|
+
// Called by background script to retrieve workflow data
|
|
503
|
+
// This happens when popup stops the recording (not mini-menu)
|
|
504
|
+
console.log('[ChromeDebug MCP] Getting workflow data');
|
|
505
|
+
stopWorkflowRecording().then(async workflow => {
|
|
502
506
|
sendResponse({ success: true, workflow: workflow });
|
|
507
|
+
|
|
508
|
+
// CRITICAL FIX: Show completion UI in mini-menu after data is sent
|
|
509
|
+
// When popup stops recording, the mini-menu needs to show the completion state
|
|
510
|
+
// Get the workflowId from storage (set by background.js when recording started)
|
|
511
|
+
try {
|
|
512
|
+
const storedData = await chrome.storage.local.get(['currentWorkflowId']);
|
|
513
|
+
const workflowId = storedData.currentWorkflowId || 'Recording saved';
|
|
514
|
+
const actionCount = workflow.actions?.length || 0;
|
|
515
|
+
console.log('[ChromeDebug MCP] Showing completion UI with workflowId:', workflowId, 'actionCount:', actionCount);
|
|
516
|
+
showWorkflowRecordingComplete(workflowId, actionCount);
|
|
517
|
+
} catch (e) {
|
|
518
|
+
console.log('[ChromeDebug MCP] Could not show completion UI:', e);
|
|
519
|
+
}
|
|
503
520
|
}).catch(error => {
|
|
504
|
-
console.error('[ChromeDebug MCP] Error
|
|
521
|
+
console.error('[ChromeDebug MCP] Error getting workflow data:', error);
|
|
505
522
|
sendResponse({ success: false, error: error.message });
|
|
506
523
|
});
|
|
507
524
|
return true; // Keep channel open for async response
|
|
@@ -634,7 +651,7 @@ async function playWorkflowRecording(workflow, actions) {
|
|
|
634
651
|
try {
|
|
635
652
|
// Show playback indicator
|
|
636
653
|
const playbackIndicator = document.createElement('div');
|
|
637
|
-
playbackIndicator.id = 'chrome-
|
|
654
|
+
playbackIndicator.id = 'chrome-debug-playback-indicator';
|
|
638
655
|
playbackIndicator.style.cssText = `
|
|
639
656
|
position: fixed;
|
|
640
657
|
top: 20px;
|
|
@@ -857,6 +874,7 @@ let isWorkflowRecording = false;
|
|
|
857
874
|
let workflowActions = [];
|
|
858
875
|
let workflowRecordingIndicator = null;
|
|
859
876
|
let workflowScreenshotSettings = null;
|
|
877
|
+
let workflowTabId = null; // Store tabId for use when stopping recording
|
|
860
878
|
let lastScreenshotTime = 0;
|
|
861
879
|
let pendingScreenshots = []; // Track pending screenshot captures
|
|
862
880
|
|
|
@@ -936,7 +954,7 @@ function getUniqueSelector(element) {
|
|
|
936
954
|
// Try unique class combination
|
|
937
955
|
if (element.className && typeof element.className === 'string') {
|
|
938
956
|
const classes = element.className.trim().split(/\s+/)
|
|
939
|
-
.filter(c => !c.startsWith('chrome-
|
|
957
|
+
.filter(c => !c.startsWith('chrome-debug'))
|
|
940
958
|
.filter(c => !c.includes(':')) // Filter out pseudo-class artifacts
|
|
941
959
|
.map(c => {
|
|
942
960
|
// Escape special characters in class names
|
|
@@ -985,18 +1003,17 @@ function getXPath(element) {
|
|
|
985
1003
|
|
|
986
1004
|
// Create workflow recording indicator
|
|
987
1005
|
function createWorkflowRecordingIndicator() {
|
|
988
|
-
|
|
989
|
-
|
|
1006
|
+
// CRITICAL FIX: If old indicator exists (showing completion), remove it completely
|
|
1007
|
+
// This ensures the old popup closes immediately before showing the new recording indicator
|
|
1008
|
+
if (workflowRecordingIndicator && workflowRecordingIndicator.parentNode) {
|
|
1009
|
+
workflowRecordingIndicator.parentNode.removeChild(workflowRecordingIndicator);
|
|
1010
|
+
workflowRecordingIndicator = null;
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
// Always create fresh element for new recording
|
|
990
1014
|
workflowRecordingIndicator = document.createElement('div');
|
|
991
|
-
workflowRecordingIndicator.id = 'chrome-
|
|
992
|
-
|
|
993
|
-
<div style="display: flex; align-items: center; gap: 8px;">
|
|
994
|
-
<span style="color: #9c27b0; font-size: 20px; animation: pulse 1.5s infinite;">●</span>
|
|
995
|
-
<span>Recording Workflow...</span>
|
|
996
|
-
<span id="workflow-action-count" style="background: rgba(255,255,255,0.2); padding: 2px 8px; border-radius: 12px; font-size: 12px;">0 actions</span>
|
|
997
|
-
</div>
|
|
998
|
-
`;
|
|
999
|
-
|
|
1015
|
+
workflowRecordingIndicator.id = 'chrome-debug-workflow-indicator';
|
|
1016
|
+
|
|
1000
1017
|
Object.assign(workflowRecordingIndicator.style, {
|
|
1001
1018
|
position: 'fixed',
|
|
1002
1019
|
bottom: '20px',
|
|
@@ -1012,11 +1029,77 @@ function createWorkflowRecordingIndicator() {
|
|
|
1012
1029
|
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.3)',
|
|
1013
1030
|
backdropFilter: 'blur(10px)',
|
|
1014
1031
|
WebkitBackdropFilter: 'blur(10px)',
|
|
1015
|
-
pointerEvents: '
|
|
1032
|
+
pointerEvents: 'auto',
|
|
1016
1033
|
userSelect: 'none'
|
|
1017
1034
|
});
|
|
1018
|
-
|
|
1035
|
+
|
|
1036
|
+
workflowRecordingIndicator.innerHTML = `
|
|
1037
|
+
<div style="display: flex; align-items: center; gap: 12px;">
|
|
1038
|
+
<div style="display: flex; align-items: center; gap: 8px; flex: 1;">
|
|
1039
|
+
<span style="color: #9c27b0; font-size: 20px; animation: pulse 1.5s infinite;">●</span>
|
|
1040
|
+
<span>Recording Workflow...</span>
|
|
1041
|
+
<span id="workflow-action-count" style="background: rgba(255,255,255,0.2); padding: 2px 8px; border-radius: 12px; font-size: 12px;">0 actions</span>
|
|
1042
|
+
</div>
|
|
1043
|
+
<button id="workflow-stop-btn" style="background: #f44336; color: white; border: none; padding: 6px 16px; border-radius: 15px; font-size: 12px; font-weight: 500; cursor: pointer; font-family: inherit;">Stop</button>
|
|
1044
|
+
<button id="workflow-close-btn" style="background: transparent; color: white; border: none; padding: 4px 8px; font-size: 16px; cursor: pointer; font-family: inherit; opacity: 0.7;" title="Close notification">×</button>
|
|
1045
|
+
</div>
|
|
1046
|
+
`;
|
|
1047
|
+
|
|
1019
1048
|
document.body.appendChild(workflowRecordingIndicator);
|
|
1049
|
+
|
|
1050
|
+
// Add stop button click handler
|
|
1051
|
+
const stopBtn = document.getElementById('workflow-stop-btn');
|
|
1052
|
+
const closeBtn = document.getElementById('workflow-close-btn');
|
|
1053
|
+
|
|
1054
|
+
if (stopBtn) {
|
|
1055
|
+
stopBtn.addEventListener('click', async (e) => {
|
|
1056
|
+
e.stopPropagation();
|
|
1057
|
+
stopBtn.disabled = true;
|
|
1058
|
+
stopBtn.textContent = 'Stopping...';
|
|
1059
|
+
|
|
1060
|
+
try {
|
|
1061
|
+
// Stop workflow recording via background script (which handles saving automatically)
|
|
1062
|
+
// Include tabId explicitly - sender.tab.id can be undefined in some edge cases
|
|
1063
|
+
chrome.runtime.sendMessage({
|
|
1064
|
+
action: 'stopWorkflowRecording',
|
|
1065
|
+
tabId: workflowTabId
|
|
1066
|
+
}, (response) => {
|
|
1067
|
+
if (chrome.runtime.lastError) {
|
|
1068
|
+
console.error('[WorkflowRecording] Error:', chrome.runtime.lastError.message);
|
|
1069
|
+
stopBtn.textContent = 'Error';
|
|
1070
|
+
stopBtn.style.background = '#666';
|
|
1071
|
+
return;
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
if (response && response.success) {
|
|
1075
|
+
console.log('[WorkflowRecording] Stop response:', response);
|
|
1076
|
+
const workflowId = response.workflow?.sessionId || 'unknown';
|
|
1077
|
+
const actionCount = response.workflow?.actions?.length || 0;
|
|
1078
|
+
console.log('[WorkflowRecording] Extracted workflowId:', workflowId, 'actionCount:', actionCount);
|
|
1079
|
+
// Show completion with action buttons
|
|
1080
|
+
showWorkflowRecordingComplete(workflowId, actionCount);
|
|
1081
|
+
} else {
|
|
1082
|
+
console.error('[WorkflowRecording] Failed to save:', response?.error);
|
|
1083
|
+
// Don't remove indicator, just show error
|
|
1084
|
+
stopBtn.textContent = 'Error';
|
|
1085
|
+
stopBtn.style.background = '#666';
|
|
1086
|
+
}
|
|
1087
|
+
});
|
|
1088
|
+
} catch (error) {
|
|
1089
|
+
console.error('[WorkflowRecording] Error stopping:', error);
|
|
1090
|
+
// Don't remove indicator, just show error
|
|
1091
|
+
stopBtn.textContent = 'Error';
|
|
1092
|
+
stopBtn.style.background = '#666';
|
|
1093
|
+
}
|
|
1094
|
+
});
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
if (closeBtn) {
|
|
1098
|
+
closeBtn.addEventListener('click', (e) => {
|
|
1099
|
+
e.stopPropagation();
|
|
1100
|
+
removeWorkflowRecordingIndicator();
|
|
1101
|
+
});
|
|
1102
|
+
}
|
|
1020
1103
|
}
|
|
1021
1104
|
|
|
1022
1105
|
function removeWorkflowRecordingIndicator() {
|
|
@@ -1033,6 +1116,97 @@ function updateWorkflowActionCount() {
|
|
|
1033
1116
|
}
|
|
1034
1117
|
}
|
|
1035
1118
|
|
|
1119
|
+
// Show workflow recording completion with action buttons
|
|
1120
|
+
function showWorkflowRecordingComplete(workflowId, actionCount) {
|
|
1121
|
+
if (!workflowRecordingIndicator) return;
|
|
1122
|
+
|
|
1123
|
+
workflowRecordingIndicator.innerHTML = `
|
|
1124
|
+
<div style="display: flex; flex-direction: column; gap: 10px; position: relative; padding-right: 30px;">
|
|
1125
|
+
<button class="wf-close-complete" style="position: absolute; top: -8px; right: -8px; background: transparent; color: white; border: none; padding: 4px 8px; font-size: 20px; cursor: pointer; font-family: inherit; opacity: 0.7; line-height: 1;" title="Close notification">×</button>
|
|
1126
|
+
|
|
1127
|
+
<div style="display: flex; align-items: center; gap: 8px;">
|
|
1128
|
+
<span style="color: #4CAF50; font-size: 16px;">✓</span>
|
|
1129
|
+
<span style="font-weight: 600; font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 400px;" title="${workflowId}">${workflowId}</span>
|
|
1130
|
+
</div>
|
|
1131
|
+
|
|
1132
|
+
<div style="font-size: 11px; color: rgba(255,255,255,0.7); margin-top: -5px;">
|
|
1133
|
+
${actionCount} actions • ${new Date().toLocaleString()}
|
|
1134
|
+
</div>
|
|
1135
|
+
|
|
1136
|
+
<div style="display: flex; gap: 6px; flex-wrap: wrap;">
|
|
1137
|
+
<button class="wf-copy-id" data-id="${workflowId}" style="background: #2196F3; color: white; border: none; padding: 6px 12px; border-radius: 12px; font-size: 11px; cursor: pointer; font-family: inherit; font-weight: 500;">Copy ID</button>
|
|
1138
|
+
<button class="wf-copy-prompt" data-id="${workflowId}" style="background: #4CAF50; color: white; border: none; padding: 6px 12px; border-radius: 12px; font-size: 11px; cursor: pointer; font-family: inherit; font-weight: 500;">Copy Prompt</button>
|
|
1139
|
+
<button class="wf-view" data-id="${workflowId}" style="background: #9C27B0; color: white; border: none; padding: 6px 12px; border-radius: 12px; font-size: 11px; cursor: pointer; font-family: inherit; font-weight: 500;">View</button>
|
|
1140
|
+
<button class="wf-delete" data-id="${workflowId}" style="background: #f44336; color: white; border: none; padding: 6px 12px; border-radius: 12px; font-size: 11px; cursor: pointer; font-family: inherit; font-weight: 500;">Delete</button>
|
|
1141
|
+
</div>
|
|
1142
|
+
</div>
|
|
1143
|
+
`;
|
|
1144
|
+
|
|
1145
|
+
// Add event listeners for action buttons
|
|
1146
|
+
const copyIdBtn = workflowRecordingIndicator.querySelector('.wf-copy-id');
|
|
1147
|
+
const copyPromptBtn = workflowRecordingIndicator.querySelector('.wf-copy-prompt');
|
|
1148
|
+
const viewBtn = workflowRecordingIndicator.querySelector('.wf-view');
|
|
1149
|
+
const deleteBtn = workflowRecordingIndicator.querySelector('.wf-delete');
|
|
1150
|
+
const closeBtn = workflowRecordingIndicator.querySelector('.wf-close-complete');
|
|
1151
|
+
|
|
1152
|
+
if (copyIdBtn) {
|
|
1153
|
+
copyIdBtn.addEventListener('click', async () => {
|
|
1154
|
+
try {
|
|
1155
|
+
await navigator.clipboard.writeText(workflowId);
|
|
1156
|
+
copyIdBtn.textContent = 'Copied!';
|
|
1157
|
+
setTimeout(() => copyIdBtn.textContent = 'Copy ID', 2000);
|
|
1158
|
+
} catch (error) {
|
|
1159
|
+
console.error('[WorkflowRecording] Failed to copy ID:', error);
|
|
1160
|
+
}
|
|
1161
|
+
});
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
if (copyPromptBtn) {
|
|
1165
|
+
copyPromptBtn.addEventListener('click', async () => {
|
|
1166
|
+
const prompt = `Please use the get_workflow_recording function in Chrome Debug to load the workflow recording "${workflowId}".`;
|
|
1167
|
+
try {
|
|
1168
|
+
await navigator.clipboard.writeText(prompt);
|
|
1169
|
+
copyPromptBtn.textContent = 'Copied!';
|
|
1170
|
+
setTimeout(() => copyPromptBtn.textContent = 'Copy Prompt', 2000);
|
|
1171
|
+
} catch (error) {
|
|
1172
|
+
console.error('[WorkflowRecording] Failed to copy prompt:', error);
|
|
1173
|
+
}
|
|
1174
|
+
});
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1177
|
+
if (viewBtn) {
|
|
1178
|
+
viewBtn.addEventListener('click', () => {
|
|
1179
|
+
// Ask background to open frame editor (content scripts can't create tabs)
|
|
1180
|
+
chrome.runtime.sendMessage({
|
|
1181
|
+
action: 'openFrameEditor',
|
|
1182
|
+
sessionId: workflowId,
|
|
1183
|
+
type: 'workflow'
|
|
1184
|
+
});
|
|
1185
|
+
});
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
if (deleteBtn) {
|
|
1189
|
+
deleteBtn.addEventListener('click', async () => {
|
|
1190
|
+
if (confirm('Delete this workflow recording?')) {
|
|
1191
|
+
chrome.runtime.sendMessage({
|
|
1192
|
+
action: 'deleteWorkflowRecording',
|
|
1193
|
+
workflowId: workflowId
|
|
1194
|
+
}, (response) => {
|
|
1195
|
+
if (response && response.success) {
|
|
1196
|
+
removeWorkflowRecordingIndicator();
|
|
1197
|
+
}
|
|
1198
|
+
});
|
|
1199
|
+
}
|
|
1200
|
+
});
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
if (closeBtn) {
|
|
1204
|
+
closeBtn.addEventListener('click', () => {
|
|
1205
|
+
removeWorkflowRecordingIndicator();
|
|
1206
|
+
});
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1036
1210
|
// Enhanced click tracking helper functions - Pro Feature
|
|
1037
1211
|
// Try to import enhanced capture module (only exists in pro build)
|
|
1038
1212
|
let enhancedCaptureModule = null;
|
|
@@ -1076,12 +1250,9 @@ async function shouldEnhanceCapture() {
|
|
|
1076
1250
|
// Record click action
|
|
1077
1251
|
function recordClick(event) {
|
|
1078
1252
|
if (!isWorkflowRecording) {
|
|
1079
|
-
console.log('[ChromePilot] Click ignored - not recording');
|
|
1080
1253
|
return;
|
|
1081
1254
|
}
|
|
1082
1255
|
|
|
1083
|
-
console.log('[ChromePilot] Recording click event');
|
|
1084
|
-
|
|
1085
1256
|
let element = event.target;
|
|
1086
1257
|
|
|
1087
1258
|
// If clicking on an SVG element or its children, find the parent button/link
|
|
@@ -1116,8 +1287,6 @@ function recordClick(event) {
|
|
|
1116
1287
|
shouldEnhanceCapture().then(enhanceCapture => {
|
|
1117
1288
|
if (enhanceCapture) {
|
|
1118
1289
|
try {
|
|
1119
|
-
console.log('[ChromePilot] Capturing enhanced click data asynchronously...');
|
|
1120
|
-
|
|
1121
1290
|
// Capture enhanced element data (only include fields with meaningful values)
|
|
1122
1291
|
const capturedHTML = captureElementHTML(element);
|
|
1123
1292
|
if (capturedHTML) {
|
|
@@ -1168,14 +1337,13 @@ function recordClick(event) {
|
|
|
1168
1337
|
}
|
|
1169
1338
|
}
|
|
1170
1339
|
|
|
1171
|
-
|
|
1340
|
+
// Enhanced click data captured successfully - no need to log
|
|
1172
1341
|
} catch (error) {
|
|
1173
1342
|
console.warn('[ChromePilot] Error capturing enhanced click data:', error);
|
|
1174
1343
|
// Continue with basic click recording if enhanced capture fails
|
|
1175
1344
|
}
|
|
1176
|
-
} else {
|
|
1177
|
-
console.log('[ChromePilot] Enhanced click capture disabled - using basic capture only');
|
|
1178
1345
|
}
|
|
1346
|
+
// Enhanced capture setting checked - no need to log state
|
|
1179
1347
|
}).catch(error => {
|
|
1180
1348
|
console.error('[ChromePilot] Error checking enhanced capture setting:', error);
|
|
1181
1349
|
});
|
|
@@ -1334,8 +1502,9 @@ function startWorkflowRecording(screenshotSettings) {
|
|
|
1334
1502
|
timestamp: event.timestamp,
|
|
1335
1503
|
stack: event.call_stack || null
|
|
1336
1504
|
});
|
|
1337
|
-
|
|
1338
|
-
console.log
|
|
1505
|
+
|
|
1506
|
+
// REMOVED: console.log that logged EVERY function execution (thousands per second)
|
|
1507
|
+
// Function traces are already stored in workflowActions array - no need to log each one
|
|
1339
1508
|
}
|
|
1340
1509
|
});
|
|
1341
1510
|
};
|
|
@@ -1344,7 +1513,8 @@ function startWorkflowRecording(screenshotSettings) {
|
|
|
1344
1513
|
window.ChromePilotTracker._setRecordingStatus(true);
|
|
1345
1514
|
console.log('[ChromePilot] Connected workflow recording to FunctionTracker');
|
|
1346
1515
|
} else {
|
|
1347
|
-
|
|
1516
|
+
// FunctionTracker is a PRO feature - use debug level to avoid confusing FREE users
|
|
1517
|
+
console.debug('[ChromePilot] FunctionTracker not available (PRO feature)');
|
|
1348
1518
|
}
|
|
1349
1519
|
|
|
1350
1520
|
// Add event listeners for recording
|
|
@@ -1373,7 +1543,9 @@ function startWorkflowRecording(screenshotSettings) {
|
|
|
1373
1543
|
// Stop workflow recording
|
|
1374
1544
|
async function stopWorkflowRecording() {
|
|
1375
1545
|
isWorkflowRecording = false;
|
|
1376
|
-
|
|
1546
|
+
workflowTabId = null; // Reset tabId when recording stops
|
|
1547
|
+
// DON'T remove indicator here - let the completion screen handle it
|
|
1548
|
+
// removeWorkflowRecordingIndicator();
|
|
1377
1549
|
|
|
1378
1550
|
console.log(`[ChromePilot] Stopping recording. Captured ${workflowActions.length} actions`);
|
|
1379
1551
|
|
|
@@ -1802,8 +1974,6 @@ async function recordScreenClick(event) {
|
|
|
1802
1974
|
const enhanceCapture = await shouldEnhanceCapture();
|
|
1803
1975
|
if (enhanceCapture) {
|
|
1804
1976
|
try {
|
|
1805
|
-
console.log('[ChromePilot] Capturing enhanced screen click data...');
|
|
1806
|
-
|
|
1807
1977
|
// Capture enhanced element data (only include fields with meaningful values)
|
|
1808
1978
|
const capturedHTML = captureElementHTML(element);
|
|
1809
1979
|
if (capturedHTML) {
|
|
@@ -1854,14 +2024,13 @@ async function recordScreenClick(event) {
|
|
|
1854
2024
|
}
|
|
1855
2025
|
}
|
|
1856
2026
|
|
|
1857
|
-
|
|
2027
|
+
// Enhanced screen click data captured successfully - no need to log
|
|
1858
2028
|
} catch (error) {
|
|
1859
2029
|
console.warn('[ChromePilot] Error capturing enhanced screen click data:', error);
|
|
1860
2030
|
// Continue with basic click recording if enhanced capture fails
|
|
1861
2031
|
}
|
|
1862
|
-
} else {
|
|
1863
|
-
console.log('[ChromePilot] Enhanced screen click capture disabled - using basic capture only');
|
|
1864
2032
|
}
|
|
2033
|
+
// Enhanced capture setting checked - no need to log state
|
|
1865
2034
|
|
|
1866
2035
|
sendScreenInteraction(interaction);
|
|
1867
2036
|
|
|
@@ -2157,7 +2326,7 @@ function showRecordingInterface() {
|
|
|
2157
2326
|
|
|
2158
2327
|
// Create recording overlay
|
|
2159
2328
|
recordingOverlay = document.createElement('div');
|
|
2160
|
-
recordingOverlay.id = 'chrome-
|
|
2329
|
+
recordingOverlay.id = 'chrome-debug-recording-overlay';
|
|
2161
2330
|
recordingOverlay.style.cssText = `
|
|
2162
2331
|
position: fixed;
|
|
2163
2332
|
bottom: 20px;
|
|
@@ -2175,13 +2344,13 @@ function showRecordingInterface() {
|
|
|
2175
2344
|
recordingOverlay.innerHTML = `
|
|
2176
2345
|
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;">
|
|
2177
2346
|
<h3 style="margin: 0; font-size: 16px; color: #333;">Screen Recording</h3>
|
|
2178
|
-
<button id="chrome-
|
|
2347
|
+
<button id="chrome-debug-close-recording" style="background: none; border: none; font-size: 20px; cursor: pointer; color: #666;">×</button>
|
|
2179
2348
|
</div>
|
|
2180
2349
|
<p style="margin: 0 0 15px 0; font-size: 13px; color: #666;">
|
|
2181
2350
|
Recording this tab with console logs
|
|
2182
2351
|
</p>
|
|
2183
|
-
<div id="chrome-
|
|
2184
|
-
<button id="chrome-
|
|
2352
|
+
<div id="chrome-debug-recording-status" style="text-align: center; margin-bottom: 15px; font-size: 14px; color: #666;"></div>
|
|
2353
|
+
<button id="chrome-debug-record-btn" style="
|
|
2185
2354
|
width: 100%;
|
|
2186
2355
|
padding: 10px;
|
|
2187
2356
|
background: #f44336;
|
|
@@ -2192,13 +2361,13 @@ function showRecordingInterface() {
|
|
|
2192
2361
|
font-size: 14px;
|
|
2193
2362
|
font-weight: 500;
|
|
2194
2363
|
">Start Recording</button>
|
|
2195
|
-
<div id="chrome-
|
|
2364
|
+
<div id="chrome-debug-recording-result" style="margin-top: 15px; display: none;"></div>
|
|
2196
2365
|
`;
|
|
2197
2366
|
|
|
2198
2367
|
document.body.appendChild(recordingOverlay);
|
|
2199
2368
|
|
|
2200
2369
|
// Add event listeners
|
|
2201
|
-
document.getElementById('chrome-
|
|
2370
|
+
document.getElementById('chrome-debug-close-recording').addEventListener('click', () => {
|
|
2202
2371
|
if (isRecording) {
|
|
2203
2372
|
if (confirm('Stop recording and close?')) {
|
|
2204
2373
|
stopRecording();
|
|
@@ -2211,7 +2380,7 @@ function showRecordingInterface() {
|
|
|
2211
2380
|
}
|
|
2212
2381
|
});
|
|
2213
2382
|
|
|
2214
|
-
document.getElementById('chrome-
|
|
2383
|
+
document.getElementById('chrome-debug-record-btn').addEventListener('click', () => {
|
|
2215
2384
|
if (!isRecording) {
|
|
2216
2385
|
startRecording();
|
|
2217
2386
|
} else {
|
|
@@ -2222,8 +2391,8 @@ function showRecordingInterface() {
|
|
|
2222
2391
|
|
|
2223
2392
|
// Start recording from content script
|
|
2224
2393
|
function startRecording() {
|
|
2225
|
-
const recordBtn = document.getElementById('chrome-
|
|
2226
|
-
const statusDiv = document.getElementById('chrome-
|
|
2394
|
+
const recordBtn = document.getElementById('chrome-debug-record-btn');
|
|
2395
|
+
const statusDiv = document.getElementById('chrome-debug-recording-status');
|
|
2227
2396
|
|
|
2228
2397
|
recordBtn.disabled = true;
|
|
2229
2398
|
recordBtn.textContent = 'Starting...';
|
|
@@ -2270,9 +2439,9 @@ function startRecording() {
|
|
|
2270
2439
|
|
|
2271
2440
|
// Stop recording
|
|
2272
2441
|
function stopRecording() {
|
|
2273
|
-
const recordBtn = document.getElementById('chrome-
|
|
2274
|
-
const statusDiv = document.getElementById('chrome-
|
|
2275
|
-
const resultDiv = document.getElementById('chrome-
|
|
2442
|
+
const recordBtn = document.getElementById('chrome-debug-record-btn');
|
|
2443
|
+
const statusDiv = document.getElementById('chrome-debug-recording-status');
|
|
2444
|
+
const resultDiv = document.getElementById('chrome-debug-recording-result');
|
|
2276
2445
|
|
|
2277
2446
|
recordBtn.disabled = true;
|
|
2278
2447
|
recordBtn.textContent = 'Stopping...';
|
|
@@ -2734,6 +2903,7 @@ class ScreenCaptureVisualFeedback {
|
|
|
2734
2903
|
init() {
|
|
2735
2904
|
// Listen for screen capture events
|
|
2736
2905
|
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
|
2906
|
+
console.log('[ScreenCapture] Received message:', message.type, message);
|
|
2737
2907
|
switch (message.type) {
|
|
2738
2908
|
case 'start-screen-capture-tracking':
|
|
2739
2909
|
this.handleStartScreenCapture(message);
|
|
@@ -2747,11 +2917,27 @@ class ScreenCaptureVisualFeedback {
|
|
|
2747
2917
|
case 'stop-screen-capture-tracking':
|
|
2748
2918
|
this.handleStopScreenCapture(message);
|
|
2749
2919
|
break;
|
|
2920
|
+
case 'recording-complete-show-ui':
|
|
2921
|
+
// Show completion UI when stopped from popup (not from mini menu button)
|
|
2922
|
+
console.log('[ScreenCapture] Processing recording-complete-show-ui, sessionId:', message.sessionId, 'actionCount:', this.actionCount);
|
|
2923
|
+
if (message.sessionId) {
|
|
2924
|
+
console.log('[ScreenCapture] Calling showScreenRecordingComplete with sessionId:', message.sessionId);
|
|
2925
|
+
this.showScreenRecordingComplete(message.sessionId, this.actionCount);
|
|
2926
|
+
} else {
|
|
2927
|
+
console.log('[ScreenCapture] ERROR: No sessionId in recording-complete-show-ui message!');
|
|
2928
|
+
}
|
|
2929
|
+
break;
|
|
2930
|
+
default:
|
|
2931
|
+
// Log unknown message types for debugging
|
|
2932
|
+
if (message.type && message.type.includes('screen-capture') || message.type && message.type.includes('recording')) {
|
|
2933
|
+
console.log('[ScreenCapture] Unknown screen capture message type:', message.type);
|
|
2934
|
+
}
|
|
2750
2935
|
}
|
|
2751
2936
|
});
|
|
2752
2937
|
}
|
|
2753
2938
|
|
|
2754
2939
|
handleStartScreenCapture(message) {
|
|
2940
|
+
console.log('[ScreenCapture] Starting new recording, current indicator exists:', !!this.recordingIndicatorElement);
|
|
2755
2941
|
this.isRecording = true;
|
|
2756
2942
|
this.actionCount = 0;
|
|
2757
2943
|
this.showRecordingIndicator();
|
|
@@ -2798,9 +2984,11 @@ class ScreenCaptureVisualFeedback {
|
|
|
2798
2984
|
|
|
2799
2985
|
handleStopScreenCapture(message) {
|
|
2800
2986
|
this.isRecording = false;
|
|
2801
|
-
|
|
2987
|
+
// DON'T hide indicator here - let the completion screen handle it
|
|
2988
|
+
// this.hideRecordingIndicator();
|
|
2802
2989
|
this.hideActionCounter();
|
|
2803
|
-
|
|
2990
|
+
// Don't cleanup yet - we want to keep the indicator visible
|
|
2991
|
+
// this.cleanup();
|
|
2804
2992
|
}
|
|
2805
2993
|
|
|
2806
2994
|
showClickHighlight(x, y) {
|
|
@@ -2836,80 +3024,96 @@ class ScreenCaptureVisualFeedback {
|
|
|
2836
3024
|
}
|
|
2837
3025
|
|
|
2838
3026
|
showRecordingIndicator() {
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
3027
|
+
// CRITICAL FIX: Clear any existing countdown interval FIRST
|
|
3028
|
+
if (this.countdownInterval) {
|
|
3029
|
+
console.log('[ScreenCapture] Clearing existing countdown interval');
|
|
3030
|
+
clearInterval(this.countdownInterval);
|
|
3031
|
+
this.countdownInterval = null;
|
|
3032
|
+
}
|
|
3033
|
+
|
|
3034
|
+
// CRITICAL FIX: If old indicator exists (showing completion), remove it completely
|
|
3035
|
+
// This ensures the old popup closes immediately before showing the new countdown
|
|
3036
|
+
if (this.recordingIndicatorElement && this.recordingIndicatorElement.parentNode) {
|
|
3037
|
+
console.log('[ScreenCapture] Removing old indicator element from DOM');
|
|
3038
|
+
this.recordingIndicatorElement.parentNode.removeChild(this.recordingIndicatorElement);
|
|
3039
|
+
this.recordingIndicatorElement = null;
|
|
3040
|
+
console.log('[ScreenCapture] Old indicator removed successfully');
|
|
3041
|
+
} else {
|
|
3042
|
+
console.log('[ScreenCapture] No old indicator to remove, creating fresh');
|
|
3043
|
+
}
|
|
3044
|
+
|
|
3045
|
+
// Add required CSS styles if not already added
|
|
3046
|
+
if (!document.getElementById('screen-capture-styles')) {
|
|
3047
|
+
const style = document.createElement('style');
|
|
3048
|
+
style.id = 'screen-capture-styles';
|
|
3049
|
+
style.textContent = `
|
|
3050
|
+
@keyframes pulse {
|
|
3051
|
+
0% { opacity: 1; }
|
|
3052
|
+
50% { opacity: 0.5; }
|
|
3053
|
+
100% { opacity: 1; }
|
|
3054
|
+
}
|
|
3055
|
+
@keyframes screen-capture-pulse {
|
|
3056
|
+
0% { opacity: 1; transform: scale(1); }
|
|
3057
|
+
50% { opacity: 0.7; transform: scale(1.1); }
|
|
3058
|
+
100% { opacity: 1; transform: scale(1); }
|
|
3059
|
+
}
|
|
3060
|
+
.screen-capture-click-highlight {
|
|
3061
|
+
position: fixed;
|
|
3062
|
+
width: 40px;
|
|
3063
|
+
height: 40px;
|
|
3064
|
+
border: 3px solid #4CAF50;
|
|
3065
|
+
border-radius: 50%;
|
|
3066
|
+
background: rgba(76, 175, 80, 0.3);
|
|
3067
|
+
transform: translate(-50%, -50%);
|
|
3068
|
+
pointer-events: none;
|
|
3069
|
+
z-index: 2147483646;
|
|
3070
|
+
animation: screen-capture-ripple 0.5s ease-out;
|
|
3071
|
+
}
|
|
3072
|
+
@keyframes screen-capture-ripple {
|
|
3073
|
+
0% {
|
|
3074
|
+
transform: translate(-50%, -50%) scale(0);
|
|
3075
|
+
opacity: 1;
|
|
2866
3076
|
}
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
opacity: 1;
|
|
2871
|
-
}
|
|
2872
|
-
100% {
|
|
2873
|
-
transform: translate(-50%, -50%) scale(1);
|
|
2874
|
-
opacity: 0;
|
|
2875
|
-
}
|
|
3077
|
+
100% {
|
|
3078
|
+
transform: translate(-50%, -50%) scale(1);
|
|
3079
|
+
opacity: 0;
|
|
2876
3080
|
}
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
3081
|
+
}
|
|
3082
|
+
`;
|
|
3083
|
+
document.head.appendChild(style);
|
|
3084
|
+
}
|
|
3085
|
+
|
|
3086
|
+
// Always create fresh element for new recording
|
|
3087
|
+
this.recordingIndicatorElement = document.createElement('div');
|
|
3088
|
+
this.recordingIndicatorElement.className = 'screen-capture-recording-indicator-unified';
|
|
3089
|
+
|
|
3090
|
+
// Use inline styles to match workflow recording exactly
|
|
3091
|
+
Object.assign(this.recordingIndicatorElement.style, {
|
|
3092
|
+
position: 'fixed',
|
|
3093
|
+
bottom: '80px', // Keep different from workflow to avoid collision
|
|
3094
|
+
left: '20px',
|
|
3095
|
+
background: 'rgba(0, 0, 0, 0.9)',
|
|
3096
|
+
color: 'white',
|
|
3097
|
+
padding: '12px 20px',
|
|
3098
|
+
borderRadius: '25px',
|
|
3099
|
+
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif',
|
|
3100
|
+
fontSize: '14px',
|
|
3101
|
+
fontWeight: '500',
|
|
3102
|
+
zIndex: '2147483647',
|
|
3103
|
+
display: 'flex',
|
|
3104
|
+
alignItems: 'center',
|
|
3105
|
+
gap: '8px',
|
|
3106
|
+
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.3)',
|
|
3107
|
+
backdropFilter: 'blur(10px)',
|
|
3108
|
+
WebkitBackdropFilter: 'blur(10px)',
|
|
3109
|
+
pointerEvents: 'none',
|
|
3110
|
+
userSelect: 'none'
|
|
3111
|
+
});
|
|
2906
3112
|
|
|
2907
|
-
|
|
2908
|
-
this.startCountdownSequence();
|
|
2909
|
-
document.body.appendChild(this.recordingIndicatorElement);
|
|
2910
|
-
}
|
|
3113
|
+
document.body.appendChild(this.recordingIndicatorElement);
|
|
2911
3114
|
|
|
2912
|
-
|
|
3115
|
+
// Start countdown sequence
|
|
3116
|
+
this.startCountdownSequence();
|
|
2913
3117
|
}
|
|
2914
3118
|
|
|
2915
3119
|
startCountdownSequence() {
|
|
@@ -2932,18 +3136,146 @@ class ScreenCaptureVisualFeedback {
|
|
|
2932
3136
|
<span class="action-count-badge" style="background: rgba(255,255,255,0.2); padding: 2px 8px; border-radius: 12px; font-size: 12px;">0 actions</span>
|
|
2933
3137
|
`;
|
|
2934
3138
|
} else {
|
|
2935
|
-
// Switch to recording display
|
|
3139
|
+
// Switch to recording display with stop button
|
|
3140
|
+
this.recordingIndicatorElement.style.pointerEvents = 'auto'; // Enable clicking
|
|
2936
3141
|
this.recordingIndicatorElement.innerHTML = `
|
|
2937
|
-
<
|
|
2938
|
-
|
|
2939
|
-
|
|
3142
|
+
<div style="display: flex; align-items: center; gap: 12px;">
|
|
3143
|
+
<div style="display: flex; align-items: center; gap: 8px; flex: 1;">
|
|
3144
|
+
<span style="color: #4CAF50; font-size: 20px; animation: pulse 1.5s infinite;">●</span>
|
|
3145
|
+
<span>Recording Screen Capture...</span>
|
|
3146
|
+
<span class="action-count-badge" style="background: rgba(255,255,255,0.2); padding: 2px 8px; border-radius: 12px; font-size: 12px;">0 actions</span>
|
|
3147
|
+
</div>
|
|
3148
|
+
<button id="screen-stop-btn" style="background: #f44336; color: white; border: none; padding: 6px 16px; border-radius: 15px; font-size: 12px; font-weight: 500; cursor: pointer; font-family: inherit;">Stop</button>
|
|
3149
|
+
<button id="screen-close-btn" style="background: transparent; color: white; border: none; padding: 4px 8px; font-size: 16px; cursor: pointer; font-family: inherit; opacity: 0.7;" title="Close notification">×</button>
|
|
3150
|
+
</div>
|
|
2940
3151
|
`;
|
|
2941
3152
|
clearInterval(this.countdownInterval);
|
|
2942
3153
|
this.countdownInterval = null;
|
|
3154
|
+
|
|
3155
|
+
// Add stop button click handler
|
|
3156
|
+
const stopBtn = document.getElementById('screen-stop-btn');
|
|
3157
|
+
const closeBtn = document.getElementById('screen-close-btn');
|
|
3158
|
+
|
|
3159
|
+
if (stopBtn) {
|
|
3160
|
+
stopBtn.addEventListener('click', async (e) => {
|
|
3161
|
+
e.stopPropagation();
|
|
3162
|
+
stopBtn.disabled = true;
|
|
3163
|
+
stopBtn.textContent = 'Stopping...';
|
|
3164
|
+
|
|
3165
|
+
// Send message to background to stop recording (correct action name)
|
|
3166
|
+
chrome.runtime.sendMessage({ action: 'stopRecording' }, (response) => {
|
|
3167
|
+
if (response && response.success && response.sessionId) {
|
|
3168
|
+
// Show completion with action buttons
|
|
3169
|
+
this.showScreenRecordingComplete(response.sessionId, this.actionCount);
|
|
3170
|
+
} else {
|
|
3171
|
+
console.error('[ScreenRecording] Failed to stop:', response?.error);
|
|
3172
|
+
// Don't hide indicator, just show error
|
|
3173
|
+
stopBtn.textContent = 'Error';
|
|
3174
|
+
stopBtn.style.background = '#666';
|
|
3175
|
+
}
|
|
3176
|
+
});
|
|
3177
|
+
});
|
|
3178
|
+
}
|
|
3179
|
+
|
|
3180
|
+
if (closeBtn) {
|
|
3181
|
+
closeBtn.addEventListener('click', (e) => {
|
|
3182
|
+
e.stopPropagation();
|
|
3183
|
+
this.hideRecordingIndicator();
|
|
3184
|
+
});
|
|
3185
|
+
}
|
|
2943
3186
|
}
|
|
2944
3187
|
}, 1000);
|
|
2945
3188
|
}
|
|
2946
3189
|
|
|
3190
|
+
showScreenRecordingComplete(sessionId, actionCount) {
|
|
3191
|
+
if (!this.recordingIndicatorElement) return;
|
|
3192
|
+
|
|
3193
|
+
this.recordingIndicatorElement.innerHTML = `
|
|
3194
|
+
<div style="display: flex; flex-direction: column; gap: 10px; position: relative; padding-right: 30px;">
|
|
3195
|
+
<button class="sc-close-complete" style="position: absolute; top: -8px; right: -8px; background: transparent; color: white; border: none; padding: 4px 8px; font-size: 20px; cursor: pointer; font-family: inherit; opacity: 0.7; line-height: 1;" title="Close notification">×</button>
|
|
3196
|
+
|
|
3197
|
+
<div style="display: flex; align-items: center; gap: 8px;">
|
|
3198
|
+
<span style="color: #4CAF50; font-size: 16px;">🎬</span>
|
|
3199
|
+
<span style="font-weight: 600; font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 400px;" title="${sessionId}">${sessionId} (frames)</span>
|
|
3200
|
+
</div>
|
|
3201
|
+
|
|
3202
|
+
<div style="font-size: 11px; color: rgba(255,255,255,0.7); margin-top: -5px;">
|
|
3203
|
+
${actionCount} actions • ${new Date().toLocaleString()}
|
|
3204
|
+
</div>
|
|
3205
|
+
|
|
3206
|
+
<div style="display: flex; gap: 6px; flex-wrap: wrap;">
|
|
3207
|
+
<button class="sc-copy-id" data-id="${sessionId}" style="background: #2196F3; color: white; border: none; padding: 6px 12px; border-radius: 12px; font-size: 11px; cursor: pointer; font-family: inherit; font-weight: 500;">Copy ID</button>
|
|
3208
|
+
<button class="sc-copy-prompt" data-id="${sessionId}" style="background: #4CAF50; color: white; border: none; padding: 6px 12px; border-radius: 12px; font-size: 11px; cursor: pointer; font-family: inherit; font-weight: 500;">Copy Prompt</button>
|
|
3209
|
+
<button class="sc-view" data-id="${sessionId}" style="background: #9C27B0; color: white; border: none; padding: 6px 12px; border-radius: 12px; font-size: 11px; cursor: pointer; font-family: inherit; font-weight: 500;">View</button>
|
|
3210
|
+
<button class="sc-delete" data-id="${sessionId}" style="background: #f44336; color: white; border: none; padding: 6px 12px; border-radius: 12px; font-size: 11px; cursor: pointer; font-family: inherit; font-weight: 500;">Delete</button>
|
|
3211
|
+
</div>
|
|
3212
|
+
</div>
|
|
3213
|
+
`;
|
|
3214
|
+
|
|
3215
|
+
// Add event listeners for action buttons
|
|
3216
|
+
const copyIdBtn = this.recordingIndicatorElement.querySelector('.sc-copy-id');
|
|
3217
|
+
const copyPromptBtn = this.recordingIndicatorElement.querySelector('.sc-copy-prompt');
|
|
3218
|
+
const viewBtn = this.recordingIndicatorElement.querySelector('.sc-view');
|
|
3219
|
+
const deleteBtn = this.recordingIndicatorElement.querySelector('.sc-delete');
|
|
3220
|
+
const closeBtn = this.recordingIndicatorElement.querySelector('.sc-close-complete');
|
|
3221
|
+
|
|
3222
|
+
if (copyIdBtn) {
|
|
3223
|
+
copyIdBtn.addEventListener('click', async () => {
|
|
3224
|
+
try {
|
|
3225
|
+
await navigator.clipboard.writeText(sessionId);
|
|
3226
|
+
copyIdBtn.textContent = 'Copied!';
|
|
3227
|
+
setTimeout(() => copyIdBtn.textContent = 'Copy ID', 2000);
|
|
3228
|
+
} catch (error) {
|
|
3229
|
+
console.error('[ScreenRecording] Failed to copy ID:', error);
|
|
3230
|
+
}
|
|
3231
|
+
});
|
|
3232
|
+
}
|
|
3233
|
+
|
|
3234
|
+
if (copyPromptBtn) {
|
|
3235
|
+
copyPromptBtn.addEventListener('click', async () => {
|
|
3236
|
+
const prompt = `Please use the chrome_debug_show_frames function in Chrome Debug to display the screen recording "${sessionId}".`;
|
|
3237
|
+
try {
|
|
3238
|
+
await navigator.clipboard.writeText(prompt);
|
|
3239
|
+
copyPromptBtn.textContent = 'Copied!';
|
|
3240
|
+
setTimeout(() => copyPromptBtn.textContent = 'Copy Prompt', 2000);
|
|
3241
|
+
} catch (error) {
|
|
3242
|
+
console.error('[ScreenRecording] Failed to copy prompt:', error);
|
|
3243
|
+
}
|
|
3244
|
+
});
|
|
3245
|
+
}
|
|
3246
|
+
|
|
3247
|
+
if (viewBtn) {
|
|
3248
|
+
viewBtn.addEventListener('click', () => {
|
|
3249
|
+
// Ask background to open frame editor (content scripts can't create tabs)
|
|
3250
|
+
chrome.runtime.sendMessage({
|
|
3251
|
+
action: 'openFrameEditor',
|
|
3252
|
+
sessionId: sessionId
|
|
3253
|
+
});
|
|
3254
|
+
});
|
|
3255
|
+
}
|
|
3256
|
+
|
|
3257
|
+
if (deleteBtn) {
|
|
3258
|
+
deleteBtn.addEventListener('click', async () => {
|
|
3259
|
+
if (confirm('Delete this screen recording?')) {
|
|
3260
|
+
chrome.runtime.sendMessage({
|
|
3261
|
+
action: 'deleteScreenRecording',
|
|
3262
|
+
sessionId: sessionId
|
|
3263
|
+
}, (response) => {
|
|
3264
|
+
if (response && response.success) {
|
|
3265
|
+
this.hideRecordingIndicator();
|
|
3266
|
+
}
|
|
3267
|
+
});
|
|
3268
|
+
}
|
|
3269
|
+
});
|
|
3270
|
+
}
|
|
3271
|
+
|
|
3272
|
+
if (closeBtn) {
|
|
3273
|
+
closeBtn.addEventListener('click', () => {
|
|
3274
|
+
this.hideRecordingIndicator();
|
|
3275
|
+
});
|
|
3276
|
+
}
|
|
3277
|
+
}
|
|
3278
|
+
|
|
2947
3279
|
hideRecordingIndicator() {
|
|
2948
3280
|
// Clear countdown interval if running
|
|
2949
3281
|
if (this.countdownInterval) {
|