// ==UserScript== // @name 小窗预览 轻量版 // @version 2.7 // @description 使用修饰键拖拽链接时在弹出窗口中打开链接,并在打开前提供预览,使用 Edge 的预读技术。同时在小窗口打开时在背后添加亚克力效果。 // @author hiisme // @match *://*/* // @grant GM_registerMenuCommand // @grant GM_getValue // @grant GM_setValue // @grant GM_info // @namespace https://greasyfork.org/users/217852 // @downloadURL none // ==/UserScript== (function () { 'use strict'; const state = { isDragging: false, linkToPreload: null, popupWindow: null, acrylicOverlay: null, }; const config = { windowWidth: GM_getValue('windowWidth', 870), windowHeight: GM_getValue('windowHeight', 530), screenLeft: (window.screen.width - GM_getValue('windowWidth', 870)) / 2, screenTop: (window.screen.height - GM_getValue('windowHeight', 530)) / 3, blurIntensity: GM_getValue('blurIntensity', 20), // Changed to match script 2 blurEnabled: GM_getValue('blurEnabled', true), closeOnMouseClick: GM_getValue('closeOnMouseClick', true), closeOnScroll: GM_getValue('closeOnScroll', true), }; function delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } async function preloadLink(link, attributes = {}) { const preloadElement = document.createElement('link'); preloadElement.rel = 'preload'; preloadElement.href = link; preloadElement.as = '*/*'; Object.assign(preloadElement, attributes); document.head.appendChild(preloadElement); await delay(1); } function createAcrylicOverlay() { const acrylicOverlay = document.createElement('div'); acrylicOverlay.style.position = 'fixed'; acrylicOverlay.style.top = '0'; acrylicOverlay.style.left = '0'; acrylicOverlay.style.width = '100%'; acrylicOverlay.style.height = '100%'; acrylicOverlay.style.zIndex = '9999'; // Apply the blur effect from script 2 acrylicOverlay.style.backdropFilter = config.blurEnabled ? 'blur(20px)' : 'none'; if (config.closeOnMouseClick) { acrylicOverlay.addEventListener('click', handleAcrylicOverlayClick); } document.body.appendChild(acrylicOverlay); return acrylicOverlay; } function handleAcrylicOverlayClick(event) { if (event.target === state.acrylicOverlay) { closePopupWindow(); } } function removeAcrylicOverlay() { if (state.acrylicOverlay) { document.body.removeChild(state.acrylicOverlay); state.acrylicOverlay = null; } } function openPopupWindow(link) { if (!state.popupWindow || state.popupWindow.closed) { state.acrylicOverlay = createAcrylicOverlay(); state.popupWindow = window.open(link, '_blank', `width=${config.windowWidth},height=${config.windowHeight},left=${config.screenLeft},top=${config.screenTop}`); // 启动定时检查弹出窗口状态 state.popupWindowChecker = setInterval(checkPopupWindowStatus, 200); } } function closePopupWindow() { if (state.popupWindow && !state.popupWindow.closed) { state.popupWindow.close(); state.popupWindow = null; removeAcrylicOverlay(); // 移除模糊效果 if (state.linkToPreload) { removePreloadedLink(state.linkToPreload); } window.removeEventListener('scroll', closePopupOnScroll); } } function checkPopupWindowStatus() { if (state.popupWindow) { if (state.popupWindow.closed) { removeAcrylicOverlay(); // 弹出窗口关闭时移除模糊效果 clearInterval(state.popupWindowChecker); } else { const width = state.popupWindow.innerWidth; const height = state.popupWindow.innerHeight; const left = state.popupWindow.screenX; const top = state.popupWindow.screenY; // 可以根据需要处理窗口尺寸和位置变化 } } } function removePreloadedLink(link) { const preloadElement = document.querySelector(`link[href="${link}"]`); if (preloadElement) { document.head.removeChild(preloadElement); } } function closePopupOnScroll() { if (state.popupWindow && !state.popupWindow.closed) { closePopupWindow(); } } function registerMenuCommand(label, action) { return GM_registerMenuCommand(label, () => { action(); updateMenuCommands(); }); } const menuCommands = [ { label: `切换模糊效果 (${config.blurEnabled ? '开' : '关'})`, action: toggleBlurEffect }, { label: `设置模糊强度 (${config.blurIntensity})`, action: setBlurIntensity }, { label: `切换点击关闭小窗 (${config.closeOnMouseClick ? '开' : '关'})`, action: toggleCloseOnMouseClick }, { label: `切换滚动关闭小窗 (${config.closeOnScroll ? '开' : '关'})`, action: toggleCloseOnScroll }, { label: `设置小窗宽度 (${config.windowWidth})`, action: () => { setWindowSize('width'); } }, { label: `设置小窗高度 (${config.windowHeight})`, action: () => { setWindowSize('height'); } } ]; function toggleBlurEffect() { config.blurEnabled = !config.blurEnabled; GM_setValue('blurEnabled', config.blurEnabled); } function setBlurIntensity() { const intensity = prompt('输入模糊强度(0-10):', config.blurIntensity); if (intensity !== null) { config.blurIntensity = parseInt(intensity, 10); GM_setValue('blurIntensity', config.blurIntensity); } } function toggleCloseOnMouseClick() { config.closeOnMouseClick = !config.closeOnMouseClick; GM_setValue('closeOnMouseClick', config.closeOnMouseClick); } function toggleCloseOnScroll() { config.closeOnScroll = !config.closeOnScroll; handleScrollCommand(); GM_setValue('closeOnScroll', config.closeOnScroll); } function handleScrollCommand() { if (config.closeOnScroll) { window.addEventListener('scroll', closePopupOnScroll, { once: true }); } else { window.removeEventListener('scroll', closePopupOnScroll); } } function setWindowSize(dimension) { const size = prompt(`输入小窗口${dimension}(像素):`, config[dimension === 'width' ? 'windowWidth' : 'windowHeight']); if (size !== null) { config[dimension === 'width' ? 'windowWidth' : 'windowHeight'] = parseInt(size, 10); GM_setValue(dimension === 'width' ? 'windowWidth' : 'windowHeight', config[dimension === 'width' ? 'windowWidth' : 'windowHeight']); if (state.popupWindow && !state.popupWindow.closed) { state.popupWindow.resizeTo(config.windowWidth, config.windowHeight); } } } function updateMenuCommands() { menuCommands.forEach((command) => { const menuCommand = registerMenuCommand(command.label, command.action); GM_info[`menuCommand${toTitleCase(command.label)}`] = menuCommand; }); } function toTitleCase(str) { return str.replace(/\w\S*/g, (txt) => { return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); }); } updateMenuCommands(); document.body.addEventListener('dragstart', async (event) => { const linkElement = event.target.tagName === 'A' ? event.target : event.target.closest('a'); if (linkElement) { const link = linkElement.href; state.isDragging = true; state.linkToPreload = link; await preloadLink(state.linkToPreload, { importance: 'high' }); if (config.closeOnScroll) { window.addEventListener('scroll', closePopupOnScroll, { once: true }); } } }); document.body.addEventListener('dragend', () => { if (state.isDragging && state.linkToPreload) { state.isDragging = false; openPopupWindow(state.linkToPreload); state.linkToPreload = null; } }); document.body.addEventListener('wheel', () => { if (config.closeOnScroll) { closePopupWindow(); } }); document.body.addEventListener('click', (event) => { if (event.target === state.acrylicOverlay) { removeAcrylicOverlay(); } }); })();