adding examples
This commit is contained in:
@@ -0,0 +1,304 @@
|
||||
// DevTools Panel UI with Real Connection and Data
|
||||
|
||||
// Debug what you're actually getting
|
||||
console.log('inspectedWindow.tabId:', chrome.devtools.inspectedWindow.tabId);
|
||||
|
||||
// Let's also check what chrome.tabs.query gives us for comparison
|
||||
chrome.tabs.query({}, (tabs) => {
|
||||
console.log('All tabs:', tabs);
|
||||
|
||||
// Find the tab with the same ID
|
||||
const inspectedTab = tabs.find(tab => tab.id === chrome.devtools.inspectedWindow.tabId);
|
||||
console.log('Inspected tab details:', inspectedTab);
|
||||
});
|
||||
|
||||
// Also check the inspected window URL
|
||||
console.log('inspectedWindow.url:', chrome.devtools.inspectedWindow.url);
|
||||
|
||||
const tabId = chrome.devtools.inspectedWindow.tabId;
|
||||
let selectedMessageIndex = -1;
|
||||
let messages = [];
|
||||
let consoleLogCount = 0;
|
||||
let port = null;
|
||||
|
||||
// Initialize UI
|
||||
function initializeUI() {
|
||||
// Connect to background script
|
||||
port = chrome.runtime.connect({ name: 'panel' });
|
||||
|
||||
// Listen for state updates
|
||||
port.onMessage.addListener((msg) => {
|
||||
if (msg.type === 'state' && msg.tabId === tabId) {
|
||||
updateUI(msg.connected, msg.status);
|
||||
} else if (msg.type === 'messages' && msg.tabId === tabId) {
|
||||
// Update messages from background
|
||||
messages = msg.messages || [];
|
||||
renderMessages();
|
||||
} else if (msg.type === 'consoleCount' && msg.tabId === tabId) {
|
||||
// Update console count from background
|
||||
consoleLogCount = msg.count || 0;
|
||||
updateConsoleCount();
|
||||
}
|
||||
});
|
||||
|
||||
// Subscribe to state updates for this tab
|
||||
port.postMessage({ type: 'subscribe', tabId });
|
||||
|
||||
// Event listeners
|
||||
document.getElementById('toggle').addEventListener('change', handleToggleChange);
|
||||
document.getElementById('clear-logs').addEventListener('click', handleClearLogs);
|
||||
document.getElementById('clear-messages').addEventListener('click', handleClearMessages);
|
||||
document.getElementById('messages-list').addEventListener('click', handleMessageClick);
|
||||
document.addEventListener('keydown', handleKeyDown);
|
||||
|
||||
// Resize handle
|
||||
initializeResizeHandle();
|
||||
}
|
||||
|
||||
// Update UI based on connection state
|
||||
function updateUI(connected, status = 'disconnected') {
|
||||
const toggle = document.getElementById('toggle');
|
||||
const toggleContainer = toggle.parentElement;
|
||||
const statusEl = document.getElementById('status');
|
||||
const statusText = statusEl.querySelector('.status-text');
|
||||
const tabInfo = document.getElementById('tab-info');
|
||||
|
||||
// Remove existing classes
|
||||
statusEl.classList.remove('connected', 'disconnected', 'retrying');
|
||||
toggleContainer.classList.remove('connected', 'disconnected', 'retrying');
|
||||
|
||||
switch (status) {
|
||||
case 'connected':
|
||||
toggle.checked = true;
|
||||
toggle.disabled = false;
|
||||
statusEl.classList.add('connected');
|
||||
toggleContainer.classList.add('connected');
|
||||
statusText.textContent = 'Connected';
|
||||
tabInfo.textContent = `Tab: ${tabId} - Connected`;
|
||||
break;
|
||||
|
||||
case 'retrying':
|
||||
toggle.checked = true;
|
||||
toggle.disabled = false;
|
||||
statusEl.classList.add('retrying');
|
||||
toggleContainer.classList.add('retrying');
|
||||
statusText.textContent = 'Retrying...';
|
||||
tabInfo.textContent = `Tab: ${tabId} - Reconnecting`;
|
||||
break;
|
||||
|
||||
case 'disconnected':
|
||||
default:
|
||||
toggle.checked = false;
|
||||
toggle.disabled = false;
|
||||
statusEl.classList.add('disconnected');
|
||||
toggleContainer.classList.add('disconnected');
|
||||
statusText.textContent = 'Disconnected';
|
||||
tabInfo.textContent = 'Tab: Not connected';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Render messages
|
||||
function renderMessages() {
|
||||
const messagesList = document.getElementById('messages-list');
|
||||
const messagesContainer = document.querySelector('.messages-container');
|
||||
|
||||
// Toggle class based on whether we have messages
|
||||
messagesContainer.classList.toggle('has-messages', messages.length > 0);
|
||||
|
||||
if (messages.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
messagesList.innerHTML = '';
|
||||
|
||||
messages.forEach((msg, index) => {
|
||||
const messageEl = document.createElement('div');
|
||||
messageEl.className = 'message';
|
||||
if (index === selectedMessageIndex) {
|
||||
messageEl.classList.add('selected');
|
||||
}
|
||||
|
||||
const arrow = msg.direction === 'outgoing' ? '⬆' : '⬇'; // Up arrow for outgoing, down arrow for incoming
|
||||
const arrowClass = msg.direction === 'outgoing' ? 'outgoing' : 'incoming';
|
||||
|
||||
// Show the raw JSON data
|
||||
const dataText = JSON.stringify(msg.data);
|
||||
|
||||
messageEl.innerHTML = `
|
||||
<div class="message-data">
|
||||
<span class="message-arrow ${arrowClass}">${arrow}</span>
|
||||
${dataText}
|
||||
</div>
|
||||
<div class="message-time">${formatTime(msg.timestamp)}</div>
|
||||
`;
|
||||
|
||||
messageEl.dataset.index = index;
|
||||
messagesList.appendChild(messageEl);
|
||||
});
|
||||
|
||||
// Scroll to bottom
|
||||
messagesList.scrollTop = messagesList.scrollHeight;
|
||||
}
|
||||
|
||||
// Format timestamp
|
||||
function formatTime(date) {
|
||||
// Convert string to Date if needed
|
||||
const dateObj = typeof date === 'string' ? new Date(date) : date;
|
||||
return dateObj.toLocaleTimeString('en-US', {
|
||||
hour12: false,
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
second: '2-digit'
|
||||
});
|
||||
}
|
||||
|
||||
// Handle message click
|
||||
function handleMessageClick(e) {
|
||||
const messageEl = e.target.closest('.message');
|
||||
if (!messageEl) return;
|
||||
|
||||
const index = parseInt(messageEl.dataset.index);
|
||||
selectMessage(index);
|
||||
}
|
||||
|
||||
// Select message
|
||||
function selectMessage(index) {
|
||||
selectedMessageIndex = index;
|
||||
|
||||
// Update selected state
|
||||
document.querySelectorAll('.message').forEach((el, i) => {
|
||||
el.classList.toggle('selected', i === index);
|
||||
});
|
||||
|
||||
// Show detail view
|
||||
const detailContainer = document.getElementById('detail-container');
|
||||
const detailContent = document.getElementById('detail-content');
|
||||
|
||||
if (index >= 0 && index < messages.length) {
|
||||
detailContainer.classList.add('visible');
|
||||
const message = messages[index];
|
||||
const data = message.data;
|
||||
|
||||
// Check if this is a screenshot response
|
||||
if (data.type === 'response' && data.success && data.result && data.result.data &&
|
||||
data.result.mimeType && data.result.mimeType.startsWith('image/')) {
|
||||
// Create image preview for screenshot
|
||||
const img = document.createElement('img');
|
||||
img.src = `data:${data.result.mimeType};base64,${data.result.data}`;
|
||||
img.style.cssText = 'max-width: 100%; height: auto; cursor: pointer; display: block; border: 1px solid #e0e0e0; border-radius: 4px;';
|
||||
img.title = 'Click to open in new tab';
|
||||
|
||||
// Open in new tab on click
|
||||
img.addEventListener('click', () => {
|
||||
window.open(img.src, '_blank');
|
||||
});
|
||||
|
||||
// Show image and data
|
||||
detailContent.innerHTML = '';
|
||||
detailContent.appendChild(img);
|
||||
|
||||
// Add the rest of the data below the image
|
||||
const dataInfo = document.createElement('pre');
|
||||
dataInfo.textContent = JSON.stringify(data.result, null, 2);
|
||||
dataInfo.style.cssText = 'margin-top: 10px; font-size: 12px; overflow: auto;';
|
||||
detailContent.appendChild(dataInfo);
|
||||
} else {
|
||||
// Show only the actual message data, not the wrapper
|
||||
detailContent.innerHTML = '';
|
||||
const pre = document.createElement('pre');
|
||||
pre.style.cssText = 'margin: 0; font-size: 12px; overflow: auto;';
|
||||
pre.textContent = JSON.stringify(message.data, null, 2);
|
||||
detailContent.appendChild(pre);
|
||||
}
|
||||
} else {
|
||||
detailContainer.classList.remove('visible');
|
||||
}
|
||||
}
|
||||
|
||||
// Handle keyboard navigation
|
||||
function handleKeyDown(e) {
|
||||
if (e.key === 'ArrowUp' && selectedMessageIndex > 0) {
|
||||
selectMessage(selectedMessageIndex - 1);
|
||||
e.preventDefault();
|
||||
} else if (e.key === 'ArrowDown' && selectedMessageIndex < messages.length - 1) {
|
||||
selectMessage(selectedMessageIndex + 1);
|
||||
e.preventDefault();
|
||||
} else if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
|
||||
// Clear messages
|
||||
handleClearMessages();
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
// Handle toggle change
|
||||
function handleToggleChange(e) {
|
||||
const checked = e.target.checked;
|
||||
|
||||
chrome.runtime.sendMessage(
|
||||
{
|
||||
type: checked ? 'connect' : 'disconnect',
|
||||
tabId: tabId
|
||||
},
|
||||
(response) => {
|
||||
if (response?.error) {
|
||||
console.error('Toggle error:', response.error);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Handle clear logs
|
||||
function handleClearLogs() {
|
||||
// Request background to clear console logs
|
||||
port.postMessage({ type: 'clearConsoleLogs', tabId });
|
||||
}
|
||||
|
||||
// Handle clear messages
|
||||
function handleClearMessages() {
|
||||
// Request background to clear messages
|
||||
port.postMessage({ type: 'clearMessages', tabId });
|
||||
|
||||
// Clear the detail view
|
||||
const detailContainer = document.getElementById('detail-container');
|
||||
detailContainer.classList.remove('visible');
|
||||
selectedMessageIndex = -1;
|
||||
}
|
||||
|
||||
// Update console count
|
||||
function updateConsoleCount() {
|
||||
document.getElementById('console-count').textContent = `Console: ${consoleLogCount}`;
|
||||
}
|
||||
|
||||
// Initialize resize handle
|
||||
function initializeResizeHandle() {
|
||||
const resizeHandle = document.getElementById('resize-handle');
|
||||
const detailContainer = document.getElementById('detail-container');
|
||||
let isResizing = false;
|
||||
let startY = 0;
|
||||
let startHeight = 0;
|
||||
|
||||
resizeHandle.addEventListener('mousedown', (e) => {
|
||||
isResizing = true;
|
||||
startY = e.clientY;
|
||||
startHeight = detailContainer.offsetHeight;
|
||||
document.body.style.cursor = 'ns-resize';
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
document.addEventListener('mousemove', (e) => {
|
||||
if (!isResizing) return;
|
||||
|
||||
const deltaY = startY - e.clientY;
|
||||
const newHeight = Math.min(Math.max(100, startHeight + deltaY), 500);
|
||||
detailContainer.style.height = `${newHeight}px`;
|
||||
});
|
||||
|
||||
document.addEventListener('mouseup', () => {
|
||||
isResizing = false;
|
||||
document.body.style.cursor = '';
|
||||
});
|
||||
}
|
||||
|
||||
// Initialize when DOM is ready
|
||||
document.addEventListener('DOMContentLoaded', initializeUI);
|
||||
Reference in New Issue
Block a user