Files
blurweb/content.js
2025-12-11 13:41:09 +08:00

1003 lines
31 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// content.js - 核心功能实现
(function() {
'use strict';
console.log('[BlurText] Content script loaded');
let isBlurMode = false;
let blurMode = 'element'; // 'element', 'selection', or 'area'
let blurIntensity = 10;
let blurredElements = new Set();
let hintElement = null;
let blurButton = null; // 浮动模糊按钮
let elementTooltip = null; // 元素模式悬停提示
// 区域模式相关变量
let isDrawing = false;
let startX = 0;
let startY = 0;
let drawingBox = null;
let areaOverlays = []; // 存储所有区域覆盖层
// 初始化:从存储中加载配置
chrome.storage.local.get(['blurIntensity'], (result) => {
if (result.blurIntensity) {
blurIntensity = result.blurIntensity;
console.log('[BlurText] Loaded blur intensity:', blurIntensity);
}
});
// 监听来自 popup 的消息
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
console.log('[BlurText] Received message:', request);
if (request.action === 'toggleBlurMode') {
isBlurMode = request.enabled;
blurMode = request.mode || 'element';
blurIntensity = request.intensity || 10;
console.log('[BlurText] Toggle blur mode:', isBlurMode, 'mode:', blurMode, 'intensity:', blurIntensity);
if (isBlurMode) {
enableBlurMode();
} else {
disableBlurMode();
}
sendResponse({ success: true });
} else if (request.action === 'clearAll') {
console.log('[BlurText] Clear all blurs');
clearAllBlurs();
sendResponse({ success: true });
} else if (request.action === 'updateIntensity') {
blurIntensity = request.intensity;
console.log('[BlurText] Update intensity:', blurIntensity);
updateAllBlurIntensity();
sendResponse({ success: true });
} else if (request.action === 'switchMode') {
blurMode = request.mode;
console.log('[BlurText] Switch mode:', blurMode);
updateModeUI();
sendResponse({ success: true });
}
return true; // 保持消息通道开放
});
// 启用模糊模式
function enableBlurMode() {
console.log('[BlurText] Enabling blur mode, mode:', blurMode);
let modeText = '元素模式 - 点击元素进行模糊';
if (blurMode === 'selection') {
modeText = '文本选择模式 - 拖动选择文字后点击模糊按钮';
} else if (blurMode === 'area') {
modeText = '区域模式 - 拖动鼠标绘制模糊区域';
}
showHint(`模糊模式已开启 - ${modeText},按 ESC 退出`);
// 根据模式添加对应的样式和事件
if (blurMode === 'element') {
document.body.classList.add('blurtext-mode');
document.addEventListener('click', handleClick, true);
document.addEventListener('mouseover', handleMouseOver, true);
document.addEventListener('mouseout', handleMouseOut, true);
} else if (blurMode === 'selection') {
// 文本选择模式不需要 crosshair 光标
document.addEventListener('mouseup', handleTextSelection, true);
} else if (blurMode === 'area') {
// 区域模式:使用 crosshair 光标并添加绘制事件
document.body.classList.add('blurtext-mode');
document.addEventListener('mousedown', handleAreaMouseDown, true);
document.addEventListener('mousemove', handleAreaMouseMove, true);
document.addEventListener('mouseup', handleAreaMouseUp, true);
}
// 键盘事件对所有模式都需要
document.addEventListener('keydown', handleKeydown, true);
console.log('[BlurText] Event listeners attached');
}
// 禁用模糊模式
function disableBlurMode() {
document.body.classList.remove('blurtext-mode');
hideHint();
hideBlurButton();
hideDrawingBox();
hideElementTooltip();
// 移除所有事件监听
document.removeEventListener('click', handleClick, true);
document.removeEventListener('keydown', handleKeydown, true);
document.removeEventListener('mouseover', handleMouseOver, true);
document.removeEventListener('mouseout', handleMouseOut, true);
document.removeEventListener('mouseup', handleTextSelection, true);
document.removeEventListener('mousedown', handleAreaMouseDown, true);
document.removeEventListener('mousemove', handleAreaMouseMove, true);
document.removeEventListener('mouseup', handleAreaMouseUp, true);
// 清除所有高亮和预览
removeAllHighlights();
}
// 更新模式UI
function updateModeUI() {
if (!isBlurMode) return;
console.log('[BlurText] Switching mode to:', blurMode);
// 先移除所有旧的事件监听和样式
document.body.classList.remove('blurtext-mode');
document.removeEventListener('click', handleClick, true);
document.removeEventListener('mouseover', handleMouseOver, true);
document.removeEventListener('mouseout', handleMouseOut, true);
document.removeEventListener('mouseup', handleTextSelection, true);
document.removeEventListener('mousedown', handleAreaMouseDown, true);
document.removeEventListener('mousemove', handleAreaMouseMove, true);
document.removeEventListener('mouseup', handleAreaMouseUp, true);
// 清除旧模式的UI元素
hideBlurButton();
removeAllHighlights();
hideDrawingBox();
hideElementTooltip();
// 根据新模式添加事件监听和样式
if (blurMode === 'element') {
document.body.classList.add('blurtext-mode');
document.addEventListener('click', handleClick, true);
document.addEventListener('mouseover', handleMouseOver, true);
document.addEventListener('mouseout', handleMouseOut, true);
showHint('已切换到元素模式 - 点击元素进行模糊', 3000);
} else if (blurMode === 'selection') {
// 文本选择模式不需要 crosshair 光标
document.addEventListener('mouseup', handleTextSelection, true);
showHint('已切换到文本选择模式 - 拖动选择文字后点击模糊按钮', 3000);
} else if (blurMode === 'area') {
// 区域模式
document.body.classList.add('blurtext-mode');
document.addEventListener('mousedown', handleAreaMouseDown, true);
document.addEventListener('mousemove', handleAreaMouseMove, true);
document.addEventListener('mouseup', handleAreaMouseUp, true);
showHint('已切换到区域模式 - 拖动鼠标绘制模糊区域', 3000);
}
console.log('[BlurText] Mode switched successfully');
}
// 处理点击事件
function handleClick(e) {
console.log('[BlurText] Click detected, isBlurMode:', isBlurMode, 'blurMode:', blurMode);
if (!isBlurMode || blurMode !== 'element') return;
// 阻止默认行为
e.preventDefault();
e.stopPropagation();
let target = e.target;
console.log('[BlurText] Target element:', target.tagName, target.className, 'text:', target.textContent?.substring(0, 20));
// 如果是提示元素,忽略
if (target.classList.contains('blurtext-hint')) {
console.log('[BlurText] Ignored hint element');
return;
}
// 切换模糊状态
toggleBlur(target);
}
// 处理键盘事件ESC 退出)
function handleKeydown(e) {
if (e.key === 'Escape' && isBlurMode) {
isBlurMode = false;
disableBlurMode();
// 通知 popup
chrome.runtime.sendMessage({ action: 'blurModeDisabled' });
}
}
// 处理文本选择(文本选择模式)
function handleTextSelection(e) {
if (!isBlurMode || blurMode !== 'selection') return;
// 避免点击模糊按钮时触发
if (e.target.classList.contains('blurtext-blur-button')) {
return;
}
// 避免点击已模糊的文本段落时触发(这些段落有自己的点击事件)
if (e.target.classList.contains('blurtext-selection-wrapped')) {
return;
}
const selection = window.getSelection();
const selectedText = selection.toString().trim();
console.log('[BlurText] Text selection:', selectedText);
if (selectedText.length > 0) {
// 显示模糊按钮
showBlurButton(selection);
} else {
// 没有选中文本,隐藏按钮
hideBlurButton();
}
}
// 显示模糊按钮
function showBlurButton(selection) {
// 移除旧按钮
hideBlurButton();
// 获取选区的位置
const range = selection.getRangeAt(0);
const rect = range.getBoundingClientRect();
// 创建模糊按钮
blurButton = document.createElement('div');
blurButton.className = 'blurtext-blur-button';
blurButton.textContent = '🔒 模糊选中文本';
blurButton.style.position = 'fixed';
blurButton.style.left = `${rect.left + rect.width / 2}px`;
blurButton.style.top = `${rect.bottom + 10}px`;
blurButton.style.transform = 'translateX(-50%)';
blurButton.style.zIndex = '2147483647';
// 点击按钮模糊文本
blurButton.addEventListener('click', (e) => {
e.preventDefault();
e.stopPropagation();
blurSelectedText();
});
document.body.appendChild(blurButton);
}
// 隐藏模糊按钮
function hideBlurButton() {
if (blurButton && blurButton.parentNode) {
blurButton.parentNode.removeChild(blurButton);
blurButton = null;
}
}
// 显示元素悬停提示
function showElementTooltip(element, text) {
// 移除旧提示
hideElementTooltip();
// 获取元素位置
const rect = element.getBoundingClientRect();
// 创建提示元素
elementTooltip = document.createElement('div');
elementTooltip.className = 'blurtext-element-tooltip';
elementTooltip.textContent = text;
elementTooltip.style.left = `${rect.left + rect.width / 2}px`;
elementTooltip.style.top = `${rect.top + rect.height / 2}px`;
elementTooltip.style.transform = 'translate(-50%, -50%)';
document.body.appendChild(elementTooltip);
}
// 隐藏元素悬停提示
function hideElementTooltip() {
if (elementTooltip && elementTooltip.parentNode) {
elementTooltip.parentNode.removeChild(elementTooltip);
elementTooltip = null;
}
}
// 模糊选中的文本
function blurSelectedText() {
const selection = window.getSelection();
if (!selection.rangeCount) return;
try {
const range = selection.getRangeAt(0);
// 获取选中的文本内容
const selectedText = range.toString();
// 验证选区是否符合要求
if (!selectedText.trim()) {
console.log('[BlurText] No text selected');
hideBlurButton();
return;
}
// 限制:不允许包含换行
if (selectedText.includes('\n') || selectedText.includes('\r')) {
console.log('[BlurText] Selection contains line breaks');
showSelectionError(selection, '不支持跨行选择');
hideBlurButton();
return;
}
// 限制:不允许包含多个空格(允许单个空格)
if (/\s{2,}/.test(selectedText)) {
console.log('[BlurText] Selection contains multiple spaces');
showSelectionError(selection, '不支持多个连续空格');
hideBlurButton();
return;
}
// 限制:检查是否跨越多个元素
const startContainer = range.startContainer;
const endContainer = range.endContainer;
// 如果起始和结束容器不同,则跨越了多个节点
if (startContainer !== endContainer) {
console.log('[BlurText] Selection spans multiple elements');
showSelectionError(selection, '不支持跨元素选择');
hideBlurButton();
return;
}
// 限制:只能选择文本节点
if (startContainer.nodeType !== Node.TEXT_NODE) {
console.log('[BlurText] Selection is not in a text node');
showSelectionError(selection, '请选择纯文本内容');
hideBlurButton();
return;
}
// 创建 span 包裹选中的文本
const span = document.createElement('span');
span.className = 'blurtext-blurred blurtext-selection-wrapped';
span.style.setProperty('--blur-intensity', `${blurIntensity}px`);
span.style.cursor = 'pointer';
// 添加鼠标悬停事件,显示恢复提示
span.addEventListener('mouseenter', () => {
showElementTooltip(span, '点击恢复此文本');
});
span.addEventListener('mouseleave', () => {
hideElementTooltip();
});
// 添加点击事件,允许单独恢复
span.addEventListener('click', (e) => {
e.preventDefault();
e.stopPropagation();
hideElementTooltip(); // 点击后立即隐藏提示
unblurSelectionSpan(span);
});
// 使用 surroundContents在严格限制下应该不会失败
range.surroundContents(span);
// 添加到模糊元素集合
blurredElements.add(span);
console.log('[BlurText] Text selection blurred, total elements:', blurredElements.size);
// 清除选择
selection.removeAllRanges();
// 隐藏按钮
hideBlurButton();
// 保存到存储
saveBlurData();
} catch (error) {
console.error('[BlurText] Error blurring selection:', error);
showSelectionError(selection, '无法模糊该选区');
hideBlurButton();
}
}
// 在选区位置显示错误提示
function showSelectionError(selection, message) {
if (!selection.rangeCount) return;
const range = selection.getRangeAt(0);
const rect = range.getBoundingClientRect();
// 创建错误提示元素
const errorTooltip = document.createElement('div');
errorTooltip.className = 'blurtext-selection-error';
errorTooltip.textContent = message;
errorTooltip.style.position = 'fixed';
errorTooltip.style.left = `${rect.left + rect.width / 2}px`;
errorTooltip.style.top = `${rect.bottom + 10}px`;
errorTooltip.style.transform = 'translateX(-50%)';
errorTooltip.style.zIndex = '2147483647';
document.body.appendChild(errorTooltip);
// 清除选择
selection.removeAllRanges();
// 2秒后自动移除
setTimeout(() => {
if (errorTooltip.parentNode) {
errorTooltip.parentNode.removeChild(errorTooltip);
}
}, 2000);
}
// 恢复单个选择模式的模糊段落
function unblurSelectionSpan(span) {
if (!span || !span.parentNode) return;
console.log('[BlurText] Unblurring selection span');
// 从集合中移除
blurredElements.delete(span);
// 获取 span 的内容(保持子节点结构)
const fragment = document.createDocumentFragment();
while (span.firstChild) {
fragment.appendChild(span.firstChild);
}
// 用原内容替换 span
span.parentNode.replaceChild(fragment, span);
console.log('[BlurText] Selection span removed, remaining elements:', blurredElements.size);
// 保存到存储
saveBlurData();
}
// 鼠标悬停高亮
function handleMouseOver(e) {
if (!isBlurMode || blurMode !== 'element') return;
const target = e.target;
if (target.classList.contains('blurtext-hint')) {
return;
}
// 如果是已模糊的元素,显示恢复提示(不添加高亮)
if (target.classList.contains('blurtext-blurred')) {
removeAllHighlights(); // 移除其他高亮
showElementTooltip(target, '点击取消模糊');
return;
}
// 移除之前的高亮和提示
removeAllHighlights();
hideElementTooltip();
// 直接高亮元素
target.classList.add('blurtext-highlight');
}
// 移除所有高亮
function removeAllHighlights() {
const highlighted = document.querySelectorAll('.blurtext-highlight');
highlighted.forEach(el => {
el.classList.remove('blurtext-highlight');
});
}
// 鼠标移出取消高亮
function handleMouseOut(e) {
if (!isBlurMode || blurMode !== 'element') return;
// 隐藏提示
hideElementTooltip();
// 延迟移除,避免在元素间移动时闪烁
setTimeout(() => {
// 检查鼠标是否还在模糊模式下的元素上
const hoveredElement = document.elementFromPoint(e.clientX, e.clientY);
if (!hoveredElement ||
hoveredElement.classList.contains('blurtext-hint') ||
hoveredElement.classList.contains('blurtext-blurred')) {
return;
}
// 如果鼠标不在任何高亮元素上,清除所有高亮
const highlighted = document.querySelector('.blurtext-highlight:hover');
if (!highlighted) {
removeAllHighlights();
}
}, 100);
}
// 切换元素模糊状态
function toggleBlur(element) {
if (blurredElements.has(element)) {
// 取消模糊
console.log('[BlurText] Removing blur from element');
element.classList.remove('blurtext-blurred');
element.style.removeProperty('--blur-intensity');
blurredElements.delete(element);
// 隐藏提示气泡(因为元素已不再模糊)
hideElementTooltip();
} else {
// 添加模糊
console.log('[BlurText] Adding blur to element, intensity:', blurIntensity);
element.classList.add('blurtext-blurred');
element.style.setProperty('--blur-intensity', `${blurIntensity}px`);
blurredElements.add(element);
}
console.log('[BlurText] Total blurred elements:', blurredElements.size);
// 保存到存储
saveBlurData();
}
// 清除所有模糊
function clearAllBlurs() {
blurredElements.forEach(element => {
element.classList.remove('blurtext-blurred');
element.style.removeProperty('--blur-intensity');
});
blurredElements.clear();
// 清除所有区域覆盖层
areaOverlays.forEach(overlay => {
if (overlay.parentNode) {
overlay.parentNode.removeChild(overlay);
}
});
areaOverlays = [];
// 清除存储数据
clearPageBlurData();
// 如果在模糊模式下,显示提示
if (isBlurMode) {
showHint('已清除所有模糊效果', 2000);
}
}
// ========== 区域模式相关函数 ==========
// 处理区域模式鼠标按下
function handleAreaMouseDown(e) {
if (!isBlurMode || blurMode !== 'area') return;
// 忽略提示元素和已有的区域覆盖层
if (e.target.classList.contains('blurtext-hint') ||
e.target.classList.contains('blurtext-area-overlay') ||
e.target.classList.contains('blurtext-area-close')) {
return;
}
// 检查是否点击了关闭按钮
if (e.target.classList.contains('blurtext-area-close')) {
const overlay = e.target.parentElement;
removeAreaOverlay(overlay);
e.preventDefault();
e.stopPropagation();
return;
}
isDrawing = true;
startX = e.pageX;
startY = e.pageY;
// 创建绘制框
drawingBox = document.createElement('div');
drawingBox.className = 'blurtext-drawing-box';
drawingBox.style.position = 'absolute';
drawingBox.style.left = startX + 'px';
drawingBox.style.top = startY + 'px';
drawingBox.style.width = '0px';
drawingBox.style.height = '0px';
drawingBox.style.zIndex = '2147483646';
document.body.appendChild(drawingBox);
e.preventDefault();
e.stopPropagation();
}
// 处理区域模式鼠标移动
function handleAreaMouseMove(e) {
if (!isBlurMode || blurMode !== 'area' || !isDrawing || !drawingBox) return;
const currentX = e.pageX;
const currentY = e.pageY;
const width = Math.abs(currentX - startX);
const height = Math.abs(currentY - startY);
const left = Math.min(currentX, startX);
const top = Math.min(currentY, startY);
drawingBox.style.left = left + 'px';
drawingBox.style.top = top + 'px';
drawingBox.style.width = width + 'px';
drawingBox.style.height = height + 'px';
}
// 处理区域模式鼠标释放
function handleAreaMouseUp(e) {
if (!isBlurMode || blurMode !== 'area' || !isDrawing || !drawingBox) return;
isDrawing = false;
const width = parseInt(drawingBox.style.width);
const height = parseInt(drawingBox.style.height);
// 只有当区域足够大时才创建模糊覆盖层(至少 20x20 像素)
if (width > 20 && height > 20) {
createAreaOverlay(
parseInt(drawingBox.style.left),
parseInt(drawingBox.style.top),
width,
height
);
}
// 移除绘制框
if (drawingBox.parentNode) {
drawingBox.parentNode.removeChild(drawingBox);
}
drawingBox = null;
e.preventDefault();
e.stopPropagation();
}
// 创建区域覆盖层
function createAreaOverlay(left, top, width, height) {
const overlay = document.createElement('div');
overlay.className = 'blurtext-area-overlay';
overlay.style.position = 'absolute';
overlay.style.left = left + 'px';
overlay.style.top = top + 'px';
overlay.style.width = width + 'px';
overlay.style.height = height + 'px';
overlay.style.setProperty('--blur-intensity', `${blurIntensity}px`);
overlay.style.zIndex = '2147483645';
// 点击覆盖层恢复区域
overlay.addEventListener('click', (e) => {
e.preventDefault();
e.stopPropagation();
removeAreaOverlay(overlay);
});
document.body.appendChild(overlay);
areaOverlays.push(overlay);
// 添加到模糊元素集合(用于统一管理强度)
blurredElements.add(overlay);
console.log('[BlurText] Area overlay created, total overlays:', areaOverlays.length);
// 保存到存储
saveBlurData();
}
// 移除区域覆盖层
function removeAreaOverlay(overlay) {
const index = areaOverlays.indexOf(overlay);
if (index > -1) {
areaOverlays.splice(index, 1);
}
blurredElements.delete(overlay);
if (overlay.parentNode) {
overlay.parentNode.removeChild(overlay);
}
console.log('[BlurText] Area overlay removed, remaining:', areaOverlays.length);
// 保存到存储
saveBlurData();
}
// 隐藏绘制框
function hideDrawingBox() {
if (drawingBox && drawingBox.parentNode) {
drawingBox.parentNode.removeChild(drawingBox);
drawingBox = null;
}
isDrawing = false;
}
// ========== 区域模式函数结束 ==========
// 更新所有已模糊元素的强度
function updateAllBlurIntensity() {
blurredElements.forEach(element => {
element.style.setProperty('--blur-intensity', `${blurIntensity}px`);
});
}
// 显示提示
function showHint(message, duration = null) {
// 移除旧提示
hideHint();
// 创建新提示
hintElement = document.createElement('div');
hintElement.className = 'blurtext-hint';
hintElement.textContent = message;
document.body.appendChild(hintElement);
// 如果指定了持续时间,自动隐藏
if (duration) {
setTimeout(() => {
hideHint();
}, duration);
}
}
// 隐藏提示
function hideHint() {
if (hintElement && hintElement.parentNode) {
hintElement.parentNode.removeChild(hintElement);
hintElement = null;
}
}
// ========== 模糊记忆功能(持久化存储)==========
// 获取当前页面的存储键
function getPageKey() {
return window.location.href;
}
// 生成元素的唯一选择器
function generateSelector(element) {
if (element.id) {
return '#' + element.id;
}
// 构建路径选择器
const path = [];
let current = element;
while (current && current !== document.body) {
let selector = current.tagName.toLowerCase();
// 添加类名(如果有)
if (current.className && typeof current.className === 'string') {
const classes = current.className.split(' ').filter(c =>
c && !c.startsWith('blurtext-')
).join('.');
if (classes) {
selector += '.' + classes;
}
}
// 计算同类型元素的索引
if (current.parentNode) {
const siblings = Array.from(current.parentNode.children).filter(
el => el.tagName === current.tagName
);
if (siblings.length > 1) {
const index = siblings.indexOf(current) + 1;
selector += `:nth-of-type(${index})`;
}
}
path.unshift(selector);
current = current.parentNode;
}
return path.join(' > ');
}
// 生成文本节点的 XPath
function getTextNodeXPath(textNode) {
const parent = textNode.parentNode;
if (!parent) return null;
const parentXPath = getElementXPath(parent);
const textNodes = Array.from(parent.childNodes).filter(
node => node.nodeType === Node.TEXT_NODE
);
const index = textNodes.indexOf(textNode) + 1;
return `${parentXPath}/text()[${index}]`;
}
// 生成元素的 XPath
function getElementXPath(element) {
if (element.id) {
return `//*[@id="${element.id}"]`;
}
const path = [];
let current = element;
while (current && current !== document.body) {
const tagName = current.tagName.toLowerCase();
const siblings = Array.from(current.parentNode.children).filter(
el => el.tagName === current.tagName
);
let selector = tagName;
if (siblings.length > 1) {
const index = siblings.indexOf(current) + 1;
selector += `[${index}]`;
}
path.unshift(selector);
current = current.parentNode;
}
return '/html/body/' + path.join('/');
}
// 根据 XPath 查找元素
function getElementByXPath(xpath) {
const result = document.evaluate(
xpath,
document,
null,
XPathResult.FIRST_ORDERED_NODE_TYPE,
null
);
return result.singleNodeValue;
}
// 保存模糊数据到存储
function saveBlurData() {
const pageKey = getPageKey();
const data = {
elements: [],
selections: [],
areas: [],
timestamp: Date.now()
};
// 收集所有模糊数据
blurredElements.forEach(element => {
if (element.classList.contains('blurtext-area-overlay')) {
// 区域模式
data.areas.push({
left: parseInt(element.style.left),
top: parseInt(element.style.top),
width: parseInt(element.style.width),
height: parseInt(element.style.height),
intensity: blurIntensity
});
} else if (element.classList.contains('blurtext-selection-wrapped')) {
// 文本选择模式
const textNode = element.firstChild;
if (textNode && textNode.nodeType === Node.TEXT_NODE) {
const xpath = getTextNodeXPath(textNode);
if (xpath) {
data.selections.push({
text: textNode.textContent,
xpath: xpath,
parentXPath: getElementXPath(element.parentNode),
intensity: blurIntensity
});
}
}
} else {
// 元素模式
const selector = generateSelector(element);
data.elements.push({
selector: selector,
intensity: blurIntensity
});
}
});
// 存储到 chrome.storage.local
chrome.storage.local.get(['blurredData'], (result) => {
const blurredData = result.blurredData || {};
blurredData[pageKey] = data;
chrome.storage.local.set({ blurredData }, () => {
console.log('[BlurText] Blur data saved for:', pageKey, data);
});
});
}
// 从存储中恢复模糊数据
function restoreBlurData() {
const pageKey = getPageKey();
chrome.storage.local.get(['blurredData'], (result) => {
const blurredData = result.blurredData || {};
const pageData = blurredData[pageKey];
if (!pageData) {
console.log('[BlurText] No saved blur data for this page');
return;
}
console.log('[BlurText] Restoring blur data:', pageData);
// 恢复元素模式的模糊
pageData.elements?.forEach(item => {
try {
const element = document.querySelector(item.selector);
if (element) {
element.classList.add('blurtext-blurred');
element.style.setProperty('--blur-intensity', `${item.intensity}px`);
blurredElements.add(element);
console.log('[BlurText] Restored element blur:', item.selector);
}
} catch (error) {
console.warn('[BlurText] Failed to restore element:', item.selector, error);
}
});
// 恢复文本选择模式的模糊
pageData.selections?.forEach(item => {
try {
const textNode = getElementByXPath(item.xpath);
if (textNode && textNode.nodeType === Node.TEXT_NODE) {
const text = textNode.textContent;
const index = text.indexOf(item.text);
if (index !== -1) {
// 创建 Range 并包裹文本
const range = document.createRange();
range.setStart(textNode, index);
range.setEnd(textNode, index + item.text.length);
const span = document.createElement('span');
span.className = 'blurtext-blurred blurtext-selection-wrapped';
span.style.setProperty('--blur-intensity', `${item.intensity}px`);
span.style.cursor = 'pointer';
// 添加鼠标悬停和点击事件
span.addEventListener('mouseenter', () => {
showElementTooltip(span, '点击恢复此文本');
});
span.addEventListener('mouseleave', () => {
hideElementTooltip();
});
span.addEventListener('click', (e) => {
e.preventDefault();
e.stopPropagation();
hideElementTooltip();
unblurSelectionSpan(span);
// 注意unblurSelectionSpan 内部会调用 saveBlurData()
});
range.surroundContents(span);
blurredElements.add(span);
console.log('[BlurText] Restored selection blur:', item.text);
}
}
} catch (error) {
console.warn('[BlurText] Failed to restore selection:', item.text, error);
}
});
// 恢复区域模式的模糊
pageData.areas?.forEach(item => {
try {
createAreaOverlay(item.left, item.top, item.width, item.height);
console.log('[BlurText] Restored area blur:', item);
} catch (error) {
console.warn('[BlurText] Failed to restore area:', item, error);
}
});
// 如果恢复了模糊效果,显示提示
if (blurredElements.size > 0) {
showHint(`已恢复 ${blurredElements.size} 个模糊效果`, 3000);
}
});
}
// 清除当前页面的存储数据
function clearPageBlurData() {
const pageKey = getPageKey();
chrome.storage.local.get(['blurredData'], (result) => {
const blurredData = result.blurredData || {};
delete blurredData[pageKey];
chrome.storage.local.set({ blurredData }, () => {
console.log('[BlurText] Cleared blur data for:', pageKey);
});
});
}
// 页面加载完成后,恢复之前的模糊状态
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', restoreBlurData);
} else {
restoreBlurData();
}
})();