import { defineContentScript } from "wxt/sandbox";
import { defaultBlur, storageKeys } from "@/const";
import { createButton } from "@/utils";
const BLUR_EMOJI = "👀";
const UN_BLUR_EMOJI = "🙈";
// 元素状态
const statusMap = new Map<string, boolean>();
// 资源选择器(需要被模糊屏蔽的媒体资源)
const selectors = [
'[data-testid="tweetPhoto"]',
'[data-testid="videoComponent"]',
'[data-testid="videoPlayer"]',
'[data-testid="card.layoutLarge.media"]',
'[data-testid="collection-hero-image"]',
'[data-testid="article-cover-image"]',
];
async function handleElements() {
const enable = (await storage.getItem<boolean>(storageKeys.enable)) ?? true;
const blur = (await storage.getItem<number>(storageKeys.blur)) ?? defaultBlur;
selectors.forEach((selector) => {
let elements: HTMLElement[] = Array.from(
document.querySelectorAll(selector)
);
elements.forEach((element) => {
let current = element;
let hasBlur = false;
while (current.parentElement !== null) {
current = current.parentElement;
if (current.matches(selectors.join(","))) {
hasBlur = true;
break;
}
}
// 检测是否已存在被处理的父级
if (hasBlur) return;
let comfortId = element.getAttribute("data-comfort-id");
if (!comfortId) {
// 标记待处理元素,生成唯一ID
comfortId = crypto.randomUUID();
element.setAttribute("data-comfort-id", comfortId);
// 添加按钮手动切换元素状态
const button = createButton(comfortId, handleElements);
button.onclick = (e) => {
e.preventDefault();
e.stopPropagation();
const newStatus = !statusMap.get(comfortId!);
statusMap.set(comfortId!, newStatus);
if (newStatus) {
element.style.filter = `blur(${blur}px)`;
button.innerText = BLUR_EMOJI;
} else {
element.style.filter = "none";
button.innerText = UN_BLUR_EMOJI;
}
};
element.parentElement?.insertBefore(button, element);
}
// 保存元素的模糊状态
if (!statusMap.has(comfortId)) {
statusMap.set(comfortId, enable);
}
const targetElement = element as HTMLElement;
const toggleButton = document.getElementById(comfortId) as HTMLElement;
if (!enable) {
targetElement.style.filter = "none";
toggleButton.style.display = "none";
statusMap.clear();
return;
} else {
targetElement.style.transition = ".3s";
toggleButton.style.display = "block";
}
const blurStatus = statusMap.get(comfortId);
if (blurStatus && targetElement.style.filter !== `blur(${blur}px)`) {
targetElement.style.filter = `blur(${blur}px)`;
toggleButton.innerText = BLUR_EMOJI;
}
if (!blurStatus && targetElement.style.filter !== "none") {
targetElement.style.filter = "none";
toggleButton.innerText = UN_BLUR_EMOJI;
}
});
});
}
export default defineContentScript({
// 匹配脚本生效的域名
matches: ["*://x.com/*"],
// 脚本运行时机
runAt: "document_idle",
main(ctx) {
console.log("Hello from X-Comfort-Browser.");
// 监听 自定义参数值 变化
[storageKeys.blur, storageKeys.enable].forEach((key) => {
storage.watch<number | boolean>(key, (v) => {
handleElements();
});
});
// 监听 页面元素 变化
const observer = new MutationObserver(() => handleElements());
observer.observe(document.body, { childList: true, subtree: true });
},
});
评论