/** * 侧边栏管理类 */ class SidebarManager { /** * @constant {Object} 配置常量 */ static CONFIG = { SIDEBAR_ID: "paiwise-sidebar", WRAPPER_ID: "paiwise-main-wrapper", STORAGE_KEY: "sidebarOpen", }; constructor() { this.sidebarId = SidebarManager.CONFIG.SIDEBAR_ID; this.wrapperId = SidebarManager.CONFIG.WRAPPER_ID; this.isOpen = false; this.init(); } /** * 初始化侧边栏 */ async init() { try { await this.checkAndRestoreState(); this.setupEventListeners(); } catch (error) { console.error("Sidebar initialization failed:", error); } } /** * 设置事件监听器 */ setupEventListeners() { // 监听页面加载完成事件 window.addEventListener("load", () => this.checkAndRestoreState()); // 监听来自 sidebar 的消息 window.addEventListener("message", this.handleMessage.bind(this)); // 监听窗口大小变化 window.addEventListener( "resize", Utils.debounce(() => this.handleResize(), 100) ); // 监听页面可见性变化 document.addEventListener("visibilitychange", () => { if (!document.hidden) { this.checkAndRestoreState(); } }); // 监听 history 变化 window.addEventListener("popstate", () => { this.checkAndRestoreState(); }); // 监听页面 URL 变化 let lastUrl = location.href; new MutationObserver(() => { const url = location.href; if (url !== lastUrl) { lastUrl = url; this.checkAndRestoreState(); } }).observe(document, { subtree: true, childList: true }); // 监听来自sidebar的消息 window.addEventListener("message", async (event) => { if (event.data.type === "COPY_TO_CLIPBOARD") { try { await navigator.clipboard.writeText(event.data.text); // 可选:发送成功消息回sidebar event.source.postMessage( { type: "COPY_SUCCESS", }, "*" ); } catch (err) { console.error("Failed to copy text:", err); // 可选:发送失败消息回sidebar event.source.postMessage( { type: "COPY_ERROR", error: err.message, }, "*" ); } } }); } /** * 处理接收到的消息 * @param {MessageEvent} event */ handleMessage(event) { if (event.data.action === "closeSidebar") { this.removeSidebar(); } } /** * 处理窗口大小变化 */ handleResize() { const sidebar = document.getElementById(this.sidebarId); if (sidebar && this.isOpen) { sidebar.style.height = `${window.innerHeight}px`; } } /** * 检查并恢复侧边栏状态 */ async checkAndRestoreState() { try { const isOpen = await Utils.getStorageData( SidebarManager.CONFIG.STORAGE_KEY ); if (isOpen && !this.isOpen) { // 只有当应该打开且当前未打开时才创建 this.createSidebar(); } else if (!isOpen && this.isOpen) { // 只有当应该关闭且当前打开时才移除 this.removeSidebar(); } } catch (error) { console.error("Failed to restore sidebar state:", error); } } /** * 包装页面内容 */ wrapPageContent() { if (document.getElementById(this.wrapperId)) return; const wrapper = document.createElement("div"); wrapper.id = this.wrapperId; // 添加初始样式 wrapper.style.width = "100%"; while (document.body.firstChild) { if (document.body.firstChild.id !== this.sidebarId) { wrapper.appendChild(document.body.firstChild); } else { document.body.removeChild(document.body.firstChild); } } document.body.appendChild(wrapper); } /** * 解除页面内容包装 */ unwrapPageContent() { const wrapper = document.getElementById(this.wrapperId); if (!wrapper) return; while (wrapper.firstChild) { document.body.insertBefore(wrapper.firstChild, wrapper); } wrapper.remove(); } /** * 创建侧边栏 */ async createSidebar() { if (document.getElementById(this.sidebarId)) return; try { this.wrapPageContent(); const iframe = document.createElement("iframe"); iframe.id = this.sidebarId; iframe.src = chrome.runtime.getURL("sidebar.html"); document.body.appendChild(iframe); // 使用 RAF 确保 DOM 更新后再添加动画类 requestAnimationFrame(() => { const wrapper = document.getElementById(this.wrapperId); const sidebar = document.getElementById(this.sidebarId); // 先触发重排 sidebar.getBoundingClientRect(); // 添加动画类 if (wrapper) wrapper.classList.add("sidebar-open"); if (sidebar) sidebar.classList.add("show"); }); this.isOpen = true; await Utils.setStorageData(SidebarManager.CONFIG.STORAGE_KEY, true); } catch (error) { console.error("Failed to create sidebar:", error); this.unwrapPageContent(); } } /** * 移除侧边栏 */ async removeSidebar() { if (!this.isOpen) return; try { const sidebar = document.getElementById(this.sidebarId); const wrapper = document.getElementById(this.wrapperId); if (sidebar && wrapper) { // 移除动画类 wrapper.classList.remove("sidebar-open"); sidebar.classList.remove("show"); // 等待动画完成后再移除元素 await new Promise((resolve) => { sidebar.addEventListener( "transitionend", () => { this.unwrapPageContent(); sidebar.remove(); resolve(); }, { once: true } ); }); } this.isOpen = false; await Utils.setStorageData(SidebarManager.CONFIG.STORAGE_KEY, false); } catch (error) { console.error("Failed to remove sidebar:", error); } } /** * 切换侧边栏显示状态 */ toggle() { if (this.isOpen) { this.removeSidebar(); } else { this.createSidebar(); } } } // 初始化侧边栏管理器 const sidebarManager = new SidebarManager(); // 监听来自背景脚本的消息 chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { if (message.action === "toggleSidebar") { sidebarManager.toggle(); sendResponse({ success: true }); } }); // 创建一个新的js文件用于处理侧边栏内部的关闭按钮事件