feat(background): 添加消息监听以支持复制文本功能
新增 `chrome.runtime.onMessage` 监听器,用于接收来自 popup 或 sidepanel 的 `copyText` 消息,并将该消息转发至当前活动标签页的内容脚本,实现跨组件通信 与剪贴板写入功能。同时更新 manifest.json 权限声明,增加 clipboardWrite 和 clipboardRead 权限以支持 navigator.clipboard API 的调用。 此外,简化了 sidepanel 的 HTML 结构并增强时间戳工具功能,包括动态切换时间戳 单位、实时刷新与复制到剪贴板等交互逻辑。
This commit is contained in:
+17
-1
@@ -1,6 +1,22 @@
|
|||||||
chrome.action.onClicked.addListener(async (tab) => {
|
chrome.action.onClicked.addListener(async (tab) => {
|
||||||
await chrome.scripting.executeScript({
|
await chrome.scripting.executeScript({
|
||||||
target: { tabId: tab.id },
|
target: { tabId: tab.id },
|
||||||
files: ["content.js"]
|
files: ['content.js'],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
||||||
|
if (message.action === 'copyText') {
|
||||||
|
// 转发到当前活动的标签页
|
||||||
|
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
|
||||||
|
if (tabs[0]?.id) {
|
||||||
|
chrome.tabs.sendMessage(tabs[0].id, message, (response) => {
|
||||||
|
sendResponse(response);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
sendResponse({ success: false });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return true; // 异步响应
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|||||||
+13
@@ -82,4 +82,17 @@
|
|||||||
iframe.style.transform = visible ? 'translateX(0)' : 'translateX(100%)';
|
iframe.style.transform = visible ? 'translateX(0)' : 'translateX(100%)';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
||||||
|
if (message.action === 'copyText') {
|
||||||
|
navigator.clipboard
|
||||||
|
.writeText(message.data)
|
||||||
|
.then(() => sendResponse({ success: true }))
|
||||||
|
.catch((err) => {
|
||||||
|
console.error('❌ 复制失败:', err);
|
||||||
|
sendResponse({ success: false, error: err });
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
})();
|
})();
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
"name": "Floating Sidebar with Toggle Button",
|
"name": "Floating Sidebar with Toggle Button",
|
||||||
"version": "1.1",
|
"version": "1.1",
|
||||||
"description": "带有可折叠隐藏按钮的浮动侧边栏",
|
"description": "带有可折叠隐藏按钮的浮动侧边栏",
|
||||||
"permissions": ["activeTab", "scripting"],
|
"permissions": ["activeTab", "scripting", "clipboardWrite", "clipboardRead"],
|
||||||
"background": {
|
"background": {
|
||||||
"service_worker": "background.js"
|
"service_worker": "background.js"
|
||||||
},
|
},
|
||||||
|
|||||||
+35
-138
@@ -1,150 +1,47 @@
|
|||||||
<!-- sidepanel/index.html -->
|
<!-- sidepanel/index.html -->
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="zh-CN">
|
<html lang="zh-CN">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>测试工具</title>
|
<title>测试工具</title>
|
||||||
<link rel="stylesheet" href="index.css" />
|
<link rel="stylesheet" href="index.css" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app">
|
<div id="app">
|
||||||
<!-- 导航栏 -->
|
<!-- 导航栏 -->
|
||||||
<nav class="navbar">
|
<nav class="navbar">
|
||||||
<button id="nav-timestamp" class="nav-button active">时间戳转换</button>
|
<button id="nav-timestamp" class="nav-button active">时间戳转换</button>
|
||||||
<button id="nav-other" class="nav-button">其他工具</button>
|
<button id="nav-other" class="nav-button">其他工具</button>
|
||||||
<button id="close" class="close-button">X</button>
|
<button id="close" class="close-button">X</button>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<!-- 页面内容容器 -->
|
<!-- 页面内容容器 -->
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<!-- 时间戳转换页面 -->
|
<!-- 时间戳工具页面 -->
|
||||||
<div id="page-timestamp" class="page active">
|
<div id="page-timestamp" class="page active">
|
||||||
<div class="bg-white border rounded-lg p-2 mb-4">
|
<h2>时间戳工具</h2>
|
||||||
<h2 class="text-lg font-bold mb-3">当前时间戳</h2>
|
<div>
|
||||||
<p class="text-3xl font-mono mb-3">
|
<h2>当前时间戳</h2>
|
||||||
<a href="javascript:;" class="hover:text-blue-500">1762793622638</a>
|
<p>
|
||||||
<span class="text-sm ml-2">毫秒</span>
|
<a href="javascript:;" id="current-timestamp">1762873747965</a>
|
||||||
</p>
|
<span id="timestamp-unit">毫秒</span>
|
||||||
<div class="flex space-x-3">
|
<button id="toggle-timestamp-btn">切换单位</button>
|
||||||
<button class="inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 bg-white text-gray-700 shadow waves-effect">
|
<button id="copy-timestamp-btn">复制</button>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" class="h-4 w-4 mr-2">
|
<button id="stop-timestamp-btn">停止</button>
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M5.25 5.653c0-.856.917-1.398 1.667-.986l11.54 6.347a1.125 1.125 0 0 1 0 1.972l-11.54 6.347a1.125 1.125 0 0 1-1.667-.986V5.653Z"></path>
|
<button id="start-timestamp-btn" style="display: none">开始</button>
|
||||||
</svg>
|
</p>
|
||||||
开始
|
|
||||||
</button>
|
|
||||||
<button class="inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors disabled:opacity-50 bg-white text-gray-700 shadow waves-effect">
|
|
||||||
单个转换
|
|
||||||
</button>
|
|
||||||
<button class="inline-flex items-center justify-center whitespace-nowrap rounded-md px-2 py-1 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 waves-effect">
|
|
||||||
批量转换
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<!-- 其他工具页面 -->
|
||||||
<div class="text-lg text-gray-600 font-bold mb-4 flex items-center">
|
<div id="page-other" class="page">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" class="h-5 w-5 mr-2">
|
<h2>其他工具页面</h2>
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M12 6v6h4.5m4.5 0a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z"></path>
|
<p>这里可以放置其他工具的内容。</p>
|
||||||
</svg>
|
|
||||||
时间戳转换
|
|
||||||
</div>
|
|
||||||
<div class="flex items-center mb-3">
|
|
||||||
<input type="text" placeholder="输入时间戳" id="jsTimestampI" class="flex-1 border border-gray-300 rounded-md px-2 py-1 w-0">
|
|
||||||
<select id="timestampUnit" class="ml-2 flex-1 border border-gray-300 rounded-md px-2 py-1">
|
|
||||||
<option value="s">秒(s)</option>
|
|
||||||
<option value="ms">毫秒(ms)</option>
|
|
||||||
</select>
|
|
||||||
<button id="convertTimestamp" class="inline-flex items-center justify-center whitespace-nowrap text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 bg-gray-800 text-gray-100 shadow hover:bg-gray-800/90 h-8 px-3 py-1 rounded-md waves-effect ml-2">
|
|
||||||
转换
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="flex gap-3 flex-grow items-center">
|
|
||||||
<input type="text" placeholder="转换结果" id="jsTimestampO" class="flex-[2] border border-gray-300 rounded-md px-2 py-1 w-0">
|
|
||||||
<div tabindex="-1" class="multiselect flex-1" role="combobox" aria-owns="listbox-null">
|
|
||||||
<div class="multiselect__select"></div>
|
|
||||||
<div class="multiselect__tags">
|
|
||||||
<div class="multiselect__tags-wrap" style="display: none;"></div>
|
|
||||||
<div class="multiselect__spinner" style="display: none;"></div>
|
|
||||||
<input name="" type="text" autocomplete="off" spellcheck="false" placeholder="选择时区" tabindex="0" class="multiselect__input" aria-controls="listbox-null" style="width: 0px; position: absolute; padding: 0px;">
|
|
||||||
<span class="multiselect__single">Asia/Shanghai</span>
|
|
||||||
</div>
|
|
||||||
<div class="multiselect__content-wrapper" tabindex="-1" style="max-height: 300px; display: none;">
|
|
||||||
<ul class="multiselect__content" role="listbox" id="listbox-null" style="display: inline-block;">
|
|
||||||
<li class="multiselect__element" id="null-0" role="option">
|
|
||||||
<span class="multiselect__option--highlight multiselect__option--selected multiselect__option" data-select="Press enter to select" data-selected="Selected" data-deselect="Press enter to remove">
|
|
||||||
<span>Asia/Shanghai</span>
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
<!-- 更多时区选项... -->
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<button class="inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground h-8 px-3 py-1 waves-effect">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" class="h-4 w-4 mr-2">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0 3.181 3.183a8.25 8.25 0 0 0 13.803-3.7M4.031 9.865a8.25 8.25 0 0 1 13.803-3.7l3.181 3.182m0-4.991v4.99"></path>
|
|
||||||
</svg>
|
|
||||||
切换单位
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mt-6">
|
|
||||||
<div class="text-lg text-gray-600 font-bold mb-4 flex items-center">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" class="h-5 w-5 mr-2">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M2.25 7.5h19.5m-19.5 0A3.75 3.75 0 0 1 6 3.75m0 0h12a3.75 3.75 0 0 1 3.75 3.75m0 0H6m0 0v12.75A3.75 3.75 0 0 1 6 15.75m0 0v-12Zm0 12h12m-12 0a3.75 3.75 0 0 0 3.75 3.75m0 0h6.75a3.75 3.75 0 0 0 3.75-3.75m0 0H9.75"></path>
|
|
||||||
</svg>
|
|
||||||
日期时间转换
|
|
||||||
</div>
|
|
||||||
<div class="flex items-center mb-3">
|
|
||||||
<input type="text" placeholder="输入日期时间 (如: 2023-10-27 10:30:00)" id="jsDatetimeI" class="flex-1 border border-gray-300 rounded-md px-2 py-1 w-0">
|
|
||||||
<div tabindex="-1" class="multiselect flex-1 ml-2" role="combobox" aria-owns="listbox-null">
|
|
||||||
<div class="multiselect__select"></div>
|
|
||||||
<div class="multiselect__tags">
|
|
||||||
<div class="multiselect__tags-wrap" style="display: none;"></div>
|
|
||||||
<div class="multiselect__spinner" style="display: none;"></div>
|
|
||||||
<input name="" type="text" autocomplete="off" spellcheck="false" placeholder="选择时区" tabindex="0" class="multiselect__input" aria-controls="listbox-null" style="width: 0px; position: absolute; padding: 0px;">
|
|
||||||
<span class="multiselect__single">Asia/Shanghai</span>
|
|
||||||
</div>
|
|
||||||
<div class="multiselect__content-wrapper" tabindex="-1" style="max-height: 300px; display: none;">
|
|
||||||
<ul class="multiselect__content" role="listbox" id="listbox-null" style="display: inline-block;">
|
|
||||||
<li class="multiselect__element" id="null-0" role="option">
|
|
||||||
<span class="multiselect__option--highlight multiselect__option--selected multiselect__option" data-select="Press enter to select" data-selected="Selected" data-deselect="Press enter to remove">
|
|
||||||
<span>Asia/Shanghai</span>
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
<!-- 更多时区选项... -->
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<button id="convertDatetime" class="inline-flex items-center justify-center whitespace-nowrap text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 bg-gray-800 text-gray-100 shadow hover:bg-gray-800/90 h-8 px-3 py-1 rounded-md waves-effect ml-2">
|
|
||||||
转换
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="flex gap-3 flex-grow items-center">
|
|
||||||
<input type="text" placeholder="转换结果" id="jsDatetimeO" class="flex-[2] border border-gray-300 rounded-md px-2 py-1 w-0">
|
|
||||||
<select id="datetimeUnit" class="ml-2 flex-1 border border-gray-300 rounded-md px-2 py-1">
|
|
||||||
<option value="s">秒(s)</option>
|
|
||||||
<option value="ms">毫秒(ms)</option>
|
|
||||||
</select>
|
|
||||||
<button class="inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground h-8 px-3 py-1 waves-effect">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true" data-slot="icon" class="h-4 w-4 mr-2">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0 3.181 3.183a8.25 8.25 0 0 0 13.803-3.7M4.031 9.865a8.25 8.25 0 0 1 13.803-3.7l3.181 3.182m0-4.991v4.99"></path>
|
|
||||||
</svg>
|
|
||||||
切换单位
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 其他工具页面 -->
|
|
||||||
<div id="page-other" class="page">
|
|
||||||
<h2>其他工具页面</h2>
|
|
||||||
<p>这里可以放置其他工具的内容。</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<script src="index.js"></script>
|
<script src="index.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
+66
-12
@@ -4,34 +4,88 @@ document.getElementById('close').addEventListener('click', () => {
|
|||||||
|
|
||||||
// sidepanel/index.js
|
// sidepanel/index.js
|
||||||
// 页面切换逻辑
|
// 页面切换逻辑
|
||||||
document.getElementById("nav-timestamp").addEventListener("click", () => {
|
document.getElementById('nav-timestamp').addEventListener('click', () => {
|
||||||
switchPage("timestamp");
|
switchPage('timestamp');
|
||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById("nav-other").addEventListener("click", () => {
|
document.getElementById('nav-other').addEventListener('click', () => {
|
||||||
switchPage("other");
|
switchPage('other');
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新时间戳显示
|
||||||
|
*/
|
||||||
|
function updateTimestamp(showMilliseconds = true) {
|
||||||
|
const currentTimestamp = document.getElementById('current-timestamp');
|
||||||
|
const currentTimestampUnit = document.getElementById('timestamp-unit');
|
||||||
|
const timestamp = Date.now();
|
||||||
|
const unit = showMilliseconds ? '毫秒' : '秒';
|
||||||
|
currentTimestamp.textContent = showMilliseconds ? timestamp : Math.floor(timestamp / 1000);
|
||||||
|
currentTimestampUnit.textContent = unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
const toggleTimestampBtn = document.getElementById('toggle-timestamp-btn');
|
||||||
|
const stopTimestampBtn = document.getElementById('stop-timestamp-btn');
|
||||||
|
const startTimestampBtn = document.getElementById('start-timestamp-btn');
|
||||||
|
|
||||||
|
stopTimestampBtn.addEventListener('click', () => {
|
||||||
|
clearInterval(timestampInterval);
|
||||||
|
stopTimestampBtn.style.display = 'none';
|
||||||
|
startTimestampBtn.style.display = 'inline-block';
|
||||||
|
});
|
||||||
|
|
||||||
|
startTimestampBtn.addEventListener('click', () => {
|
||||||
|
timestampInterval = setInterval(() => updateTimestamp(showMilliseconds), 100);
|
||||||
|
startTimestampBtn.style.display = 'none';
|
||||||
|
stopTimestampBtn.style.display = 'inline-block';
|
||||||
|
});
|
||||||
|
|
||||||
|
let showMilliseconds = true;
|
||||||
|
updateTimestamp(showMilliseconds); // 初始化时更新一次时间戳
|
||||||
|
let timestampInterval = setInterval(() => updateTimestamp(showMilliseconds), 100);
|
||||||
|
toggleTimestampBtn.addEventListener('click', () => {
|
||||||
|
showMilliseconds = !showMilliseconds;
|
||||||
|
updateTimestamp(showMilliseconds);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 复制时间戳到剪贴板
|
||||||
|
const copyTimestampBtn = document.getElementById('copy-timestamp-btn');
|
||||||
|
const currentTimestamp = document.getElementById('current-timestamp');
|
||||||
|
copyTimestampBtn.addEventListener('click', () => {
|
||||||
|
// 获取时间戳文本
|
||||||
|
const timestampText = currentTimestamp.textContent;
|
||||||
|
|
||||||
|
chrome.runtime.sendMessage({ action: 'copyText', data: timestampText }, (res) => {
|
||||||
|
if (chrome.runtime.lastError) {
|
||||||
|
console.error('❌ 传送时间戳文本失败:', chrome.runtime.lastError);
|
||||||
|
} else if (res?.success) {
|
||||||
|
console.log('✅ 已复制:', timestampText);
|
||||||
|
} else {
|
||||||
|
console.error('❌ 复制失败:', res);
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function switchPage(pageName) {
|
function switchPage(pageName) {
|
||||||
// 隐藏所有页面
|
// 隐藏所有页面
|
||||||
document.querySelectorAll(".page").forEach(page => {
|
document.querySelectorAll('.page').forEach((page) => {
|
||||||
page.classList.remove("active");
|
page.classList.remove('active');
|
||||||
});
|
});
|
||||||
|
|
||||||
// 移除所有导航按钮的 active 状态
|
// 移除所有导航按钮的 active 状态
|
||||||
document.querySelectorAll(".nav-button").forEach(button => {
|
document.querySelectorAll('.nav-button').forEach((button) => {
|
||||||
button.classList.remove("active");
|
button.classList.remove('active');
|
||||||
});
|
});
|
||||||
|
|
||||||
// 显示目标页面
|
// 显示目标页面
|
||||||
document.getElementById(`page-${pageName}`).classList.add("active");
|
document.getElementById(`page-${pageName}`).classList.add('active');
|
||||||
|
|
||||||
// 激活对应的导航按钮
|
// 激活对应的导航按钮
|
||||||
document.getElementById(`nav-${pageName}`).classList.add("active");
|
document.getElementById(`nav-${pageName}`).classList.add('active');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 关闭按钮逻辑 (使用消息传递)
|
// 关闭按钮逻辑 (使用消息传递)
|
||||||
document.getElementById("close").addEventListener("click", () => {
|
document.getElementById('close').addEventListener('click', () => {
|
||||||
// 向父页面发送消息请求关闭
|
// 向父页面发送消息请求关闭
|
||||||
window.parent.postMessage({ action: "closeSidebar" }, "*");
|
window.parent.postMessage({ action: 'closeSidebar' }, '*');
|
||||||
});
|
});
|
||||||
Reference in New Issue
Block a user