添加模糊记忆功能
This commit is contained in:
293
content.js
293
content.js
@@ -43,18 +43,24 @@
|
||||
} 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; // 保持消息通道开放
|
||||
});
|
||||
|
||||
// 启用模糊模式
|
||||
@@ -375,6 +381,9 @@
|
||||
|
||||
// 隐藏按钮
|
||||
hideBlurButton();
|
||||
|
||||
// 保存到存储
|
||||
saveBlurData();
|
||||
} catch (error) {
|
||||
console.error('[BlurText] Error blurring selection:', error);
|
||||
showSelectionError(selection, '无法模糊该选区');
|
||||
@@ -431,6 +440,9 @@
|
||||
span.parentNode.replaceChild(fragment, span);
|
||||
|
||||
console.log('[BlurText] Selection span removed, remaining elements:', blurredElements.size);
|
||||
|
||||
// 保存到存储
|
||||
saveBlurData();
|
||||
}
|
||||
|
||||
// 鼠标悬停高亮
|
||||
@@ -509,6 +521,9 @@
|
||||
blurredElements.add(element);
|
||||
}
|
||||
console.log('[BlurText] Total blurred elements:', blurredElements.size);
|
||||
|
||||
// 保存到存储
|
||||
saveBlurData();
|
||||
}
|
||||
|
||||
// 清除所有模糊
|
||||
@@ -527,6 +542,9 @@
|
||||
});
|
||||
areaOverlays = [];
|
||||
|
||||
// 清除存储数据
|
||||
clearPageBlurData();
|
||||
|
||||
// 如果在模糊模式下,显示提示
|
||||
if (isBlurMode) {
|
||||
showHint('已清除所有模糊效果', 2000);
|
||||
@@ -647,6 +665,9 @@
|
||||
blurredElements.add(overlay);
|
||||
|
||||
console.log('[BlurText] Area overlay created, total overlays:', areaOverlays.length);
|
||||
|
||||
// 保存到存储
|
||||
saveBlurData();
|
||||
}
|
||||
|
||||
// 移除区域覆盖层
|
||||
@@ -660,6 +681,9 @@
|
||||
overlay.parentNode.removeChild(overlay);
|
||||
}
|
||||
console.log('[BlurText] Area overlay removed, remaining:', areaOverlays.length);
|
||||
|
||||
// 保存到存储
|
||||
saveBlurData();
|
||||
}
|
||||
|
||||
// 隐藏绘制框
|
||||
@@ -707,7 +731,272 @@
|
||||
}
|
||||
}
|
||||
|
||||
// 页面加载完成后,恢复之前的模糊状态(未来功能)
|
||||
// 这里可以添加持久化存储功能
|
||||
// ========== 模糊记忆功能(持久化存储)==========
|
||||
|
||||
// 获取当前页面的存储键
|
||||
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();
|
||||
}
|
||||
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user