diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 60a40c4..7e327f2 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -33,13 +33,13 @@ "message": "Set blur effect on Original Window when popup" }, "enableContainerIdentify": { - "message": "keep open in the same container as original page" + "message": "Keep open in the same container as original page" }, "blurPx": { - "message": "blur effect strengh: " + "message": "Blur effect strengh: " }, "blurTime": { - "message": "blur in specific seconds (s): " + "message": "Blur in specific seconds (s): " }, "keySelection": { "message": "Response when selected key is pressing (Please test to ensure it meets expectations.)" @@ -48,10 +48,10 @@ "message": "Search provider" }, "custom": { - "message": "custom search url (use %s as selected text)" + "message": "Custom (use %s as selected text)" }, "searchDisable": { - "message": "Disable search in popup window" + "message": "Disable" }, "noneKey": { "message": "None" diff --git a/_locales/es/messages.json b/_locales/es/messages.json index efdbbfb..0ea9113 100644 --- a/_locales/es/messages.json +++ b/_locales/es/messages.json @@ -33,13 +33,13 @@ "message": "Aplicar efecto de desenfoque en la ventana original al abrir el popup" }, "enableContainerIdentify": { - "message": "mantener abierto en el mismo contenedor que la página original" + "message": "Mantener abierto en el mismo contenedor que la página original" }, "blurPx": { - "message": "intensidad del efecto de desenfoque: " + "message": "Intensidad del efecto de desenfoque: " }, "blurTime": { - "message": "desenfoque en segundos específicos (s): " + "message": "Desenfoque en segundos específicos (s): " }, "keySelection": { "message": "Respuesta cuando se presiona la tecla seleccionada (Por favor, prueba para asegurarte de que cumple con las expectativas.)" diff --git a/_locales/zh_CN/messages.json b/_locales/zh_CN/messages.json index ca0916b..46b496c 100644 --- a/_locales/zh_CN/messages.json +++ b/_locales/zh_CN/messages.json @@ -48,7 +48,7 @@ "message": "搜索引擎" }, "custom": { - "message": "自定义" + "message": "自定义(选中文本:%s)" }, "searchDisable": { "message": "禁用" diff --git a/background.js b/background.js index fc5bfe6..9f0256d 100644 --- a/background.js +++ b/background.js @@ -85,6 +85,7 @@ chrome.runtime.onMessage.addListener(async (request, sender, sendResponse) => { }); console.log('Current window:', currentWindow); + const userConfigs = await loadUserConfigs(); let { originWindowId } = userConfigs; @@ -135,15 +136,25 @@ chrome.runtime.onMessage.addListener(async (request, sender, sendResponse) => { sendResponse({ status: 'window focus handled' }); } + const zoomFactor = await new Promise((resolve, reject) => { + chrome.tabs.getZoom(sender.tab.id, (zoom) => { + if (chrome.runtime.lastError) { + reject(chrome.runtime.lastError); + } else { + resolve(zoom); + } + }); + }); + await Promise.all([ - saveConfig('lastClientX', request.lastClientX), - saveConfig('lastClientY', request.lastClientY), - saveConfig('lastScreenTop', request.top), - saveConfig('lastScreenLeft', request.left), - saveConfig('lastScreenWidth', request.width), - saveConfig('lastScreenHeight', request.height) + saveConfig('lastClientX', request.lastClientX * zoomFactor), + saveConfig('lastClientY', request.lastClientY * zoomFactor), + saveConfig('lastScreenTop', request.top * zoomFactor), + saveConfig('lastScreenLeft', request.left * zoomFactor), + saveConfig('lastScreenWidth', request.width * zoomFactor), + saveConfig('lastScreenHeight', request.height * zoomFactor) ]); - + const { disabledUrls } = userConfigs; if (isUrlDisabled(sender.tab.url, disabledUrls)) { sendResponse({ status: 'url disabled' }); @@ -174,7 +185,7 @@ async function handleLinkInPopup(linkUrl, tab, currentWindow) { const { lastClientX, lastClientY, enableContainerIdentify, popupHeight, popupWidth, tryOpenAtMousePosition, - lastScreenTop, lastScreenLeft, lastScreenWidth, lastScreenHeight + lastScreenTop, lastScreenLeft, lastScreenWidth, lastScreenHeight, devicePixelRatio } = userConfigs; const height = parseInt(popupHeight, 10) || 800; @@ -185,6 +196,15 @@ async function handleLinkInPopup(linkUrl, tab, currentWindow) { dx = Math.max(lastScreenLeft, Math.min(dx, lastScreenLeft + lastScreenWidth - width)); dy = Math.max(lastScreenTop, Math.min(dy, lastScreenTop + lastScreenHeight - height)); + console.log("tryOpenAtMousePosition: " + tryOpenAtMousePosition ) + console.log("lastScreenLeft: " + lastScreenLeft ) + console.log("lastScreenTop: " + lastScreenTop ) + console.log("lastScreenWidth: " + lastScreenWidth) + console.log("lastScreenHeight: " + lastScreenHeight) + console.log("dx - dy : " + dx + "-" + dy) + console.log("devicePixelRatio: " + devicePixelRatio) + + const createData = { url: linkUrl, type: 'popup', diff --git a/content.js b/content.js index fed34ca..2b8cc2d 100644 --- a/content.js +++ b/content.js @@ -17,16 +17,8 @@ const configs = { async function loadUserConfigs() { return new Promise(resolve => { chrome.storage.local.get(Object.keys(configs), storedConfigs => { - // Merge stored configurations with default configs, setting defaults for undefined keys const mergedConfigs = { ...configs, ...storedConfigs }; - - // Update the main configs object with merged configurations Object.assign(configs, mergedConfigs); - - // Log the merged configurations (optional) - // console.log('Loaded and merged user configurations:', configs); - - // Resolve with the merged configurations resolve(mergedConfigs); }); }); @@ -54,10 +46,16 @@ function removeListeners() { function handleEvent(e) { if (e.type === 'dragstart') { handleDragStart(e); - } else if (['dragover', 'drop', 'dragend', 'mouseup'].includes(e.type)) { + + } else if (['dragover', 'drop', 'dragend'].includes(e.type)) { preventEvent(e); } else if (e.type === 'click') { handleClick(e); + } else if (e.type === 'mouseup') { + if (e.target.tagName === 'A' && e.target.href) { + e.preventDefault(); + e.stopImmediatePropagation(); + } } } @@ -84,7 +82,8 @@ async function handleDragStart(e) { } if (e.target.tagName === 'A' || (selectionText && searchEngine !== 'None')) { - preventEvent(e); + e.preventDefault(); + e.stopImmediatePropagation(); if (blurEnabled) { document.body.style.filter = `blur(${blurPx}px)`; @@ -108,8 +107,9 @@ function handleClick(e) { preventEvent(e); isDragging = false; } + } - + function isUrlDisabled(url, disabledUrls) { return disabledUrls.some(disabledUrl => { if (disabledUrl.includes('*')) { @@ -182,10 +182,10 @@ window.addEventListener('focus', async () => { try { document.body.style.filter = ''; const data = await loadUserConfigs(['closeWhenFocusedInitialWindow']); - const message = data.closeWhenFocusedInitialWindow + const message = data.closeWhenFocusedInitialWindow ? { action: 'windowRegainedFocus', checkContextMenuItem: true } : { checkContextMenuItem: true }; - + const response = await sendMessageToBackground(message); console.log("Background script responded:", response); } catch (error) { diff --git a/manifest.json b/manifest.json index 0551b24..35c2967 100644 --- a/manifest.json +++ b/manifest.json @@ -2,7 +2,7 @@ "manifest_version": 2, "name": "__MSG_extensionName__", "description": "__MSG_extensionDescription__", - "version": "0.0.20", + "version": "0.0.21", "default_locale": "en", "icons": { "48": "icon.svg", diff --git a/options/options.css b/options/options.css index 3768589..a4b0d19 100644 --- a/options/options.css +++ b/options/options.css @@ -9,27 +9,32 @@ border-radius: 4px; } -input[type="text"], input[type="number"], textarea { +input[type="text"], +input[type="number"], +textarea { min-width: 40%; margin-right: 4px; } textarea { width: 100%; - box-sizing: border-box; /* Ensure the textarea takes the full width */ + box-sizing: border-box; + /* Ensure the textarea takes the full width */ margin-top: 5px; padding: 5px; font-size: 14px; - resize: vertical; /* Allow vertical resize */ + resize: vertical; + /* Allow vertical resize */ } legend { background-color: #0000007d; color: #fff; padding: 3px 6px; - } +} + - /* Dark Mode */ +/* Dark Mode */ @media (prefers-color-scheme: dark) { body { background-color: #121212; @@ -49,7 +54,9 @@ legend { border-radius: 4px; } - input[type="text"], input[type="number"], textarea { + input[type="text"], + input[type="number"], + textarea { min-width: 40%; margin-right: 4px; background-color: #1e1e1e; @@ -59,11 +66,13 @@ legend { textarea { width: 100%; - box-sizing: border-box; /* Ensure the textarea takes the full width */ + box-sizing: border-box; + /* Ensure the textarea takes the full width */ margin-top: 5px; padding: 5px; font-size: 14px; - resize: vertical; /* Allow vertical resize */ + resize: vertical; + /* Allow vertical resize */ background-color: #1e1e1e; color: #e0e0e0; border: 1px solid #333; @@ -74,4 +83,4 @@ legend { color: #e0e0e0; padding: 3px 6px; } -} +} \ No newline at end of file diff --git a/options/options.html b/options/options.html index 0a0d3fe..4e76464 100644 --- a/options/options.html +++ b/options/options.html @@ -25,6 +25,7 @@ +

@@ -33,23 +34,31 @@

Select Search Engine - - + + + + + + - +
+ + + +

diff --git a/options/options.js b/options/options.js index 16be409..26cfcce 100644 --- a/options/options.js +++ b/options/options.js @@ -1,18 +1,45 @@ +const configs = { + 'closeWhenFocusedInitialWindow': true, + 'tryOpenAtMousePosition': false, + 'hideBrowserControls': true, + 'popupHeight': 800, + 'popupWidth': 1000, + 'searchEngine': 'https://www.google.com/search?q=%s', + 'disabledUrls': [], + 'enableContainerIdentify': true, + 'blurEnabled': true, + 'blurPx': 3, + 'blurTime': 1, + 'modifiedKey': 'None', + 'originWindowId': '' +}; + document.addEventListener("DOMContentLoaded", init); -async function init() { - const userConfigs = await loadUserConfigs(); - setupPage(userConfigs); +function init() { + loadUserConfigs(setupPage); } -function setupPage(userConfigs = {}) { +function setupPage(userConfigs) { + userConfigs = userConfigs || {}; + + // Elements to translate and set labels for const elementsToTranslate = [ - 'keySelection', 'searchEngineSelection', 'popupSettings', 'blurEffectSettings', 'blacklist' + { id: 'keySelection', messageId: 'keySelection' }, + { id: 'searchEngineSelection', messageId: 'searchEngineSelection' }, + { id: 'popupSettings', messageId: 'popupSettings' }, + { id: 'blurEffectSettings', messageId: 'blurEffectSettings' }, + { id: 'blacklist', messageId: 'blacklist' } ]; - elementsToTranslate.forEach(id => setTextContent(id, id)); - ['custom', 'searchDisable', 'noneKey'].forEach(id => setInputLabel(id, id)); + elementsToTranslate.forEach(({ id, messageId }) => setTextContent(id, messageId)); + + // Set specific labels + setInputLabel('custom', 'custom'); + setInputLabel('searchDisable', 'searchDisable'); + setInputLabel('noneKey', 'noneKey'); + // Initialize input elements Object.keys(configs).forEach(key => { const input = document.getElementById(key); if (input) { @@ -21,18 +48,20 @@ function setupPage(userConfigs = {}) { } }); + // Initialize textarea and sliders initializeTextarea('disabledUrls', userConfigs); - initializeSlider('blurPx', userConfigs.blurPx ?? 3); - initializeSlider('blurTime', userConfigs.blurTime ?? 1); + initializeSlider('blurPx', 3); + initializeSlider('blurTime', 1); + + // Set modified key setModifiedKey(userConfigs.modifiedKey); + + // Setup search engine selection setupSearchEngineSelection(userConfigs.searchEngine); } function setTextContent(elementId, messageId) { - const element = document.getElementById(elementId); - if (element) { - element.textContent = chrome.i18n.getMessage(messageId); - } + document.getElementById(elementId).textContent = chrome.i18n.getMessage(messageId); } function setInputLabel(inputId, messageId) { @@ -63,8 +92,8 @@ function createLabel(input, key) { function addInputListener(input, key) { input.addEventListener("input", () => { - const value = input.type === 'checkbox' ? input.checked : input.value; - saveSingleSetting(key, value); + configs[key] = input.type === 'checkbox' ? input.checked : input.value; + saveAllSettings(); }); } @@ -73,8 +102,8 @@ function initializeTextarea(textareaId, userConfigs) { if (textarea) { textarea.value = (userConfigs[textareaId] ?? configs[textareaId]).join('\n'); textarea.addEventListener('input', () => { - const value = textarea.value.split('\n').filter(line => line.trim()); - saveSingleSetting(textareaId, value); + configs[textareaId] = textarea.value.split('\n').filter(line => line.trim()); + saveAllSettings(); }); } } @@ -88,95 +117,86 @@ function initializeSlider(id, defaultValue) { output.textContent = initialValue; input.addEventListener('input', () => { - const value = input.value; - output.textContent = value; - localStorage.setItem(id, value); - saveSingleSetting(id, value); + output.textContent = input.value; + localStorage.setItem(id, input.value); }); } -function setModifiedKey(modifiedKey = 'noneKey') { - const modifiedKeyInput = document.querySelector(`input[name="modifiedKey"][value="${modifiedKey}"]`); - if (modifiedKeyInput) { - modifiedKeyInput.checked = true; - } +function setModifiedKey(modifiedKey) { + modifiedKey = modifiedKey ?? 'None'; + document.querySelector(`input[name="modifiedKey"][value="${modifiedKey}"]`).checked = true; document.querySelectorAll('input[name="modifiedKey"]').forEach(input => { input.addEventListener('change', event => { - saveSingleSetting('modifiedKey', event.target.value); + chrome.storage.local.set({ modifiedKey: event.target.value }); }); }); } function setupSearchEngineSelection(searchEngine) { const customInput = document.getElementById('customSearchEngine'); - const searchEngines = ['google', 'bing', 'baidu', 'yandex', 'wiki', 'duckduckgo', 'custom', 'searchDisable']; + const searchEngines = ['google', 'bing', 'baidu', 'duckduckgo', 'custom', 'searchDisable', 'wiki', 'yandex']; + // Ensure the custom input event listener is set up properly customInput.addEventListener('input', () => { - saveSingleSetting('searchEngine', customInput.value); + chrome.storage.local.set({ searchEngine: customInput.value }); }); searchEngines.forEach(engine => { const radio = document.getElementById(engine); radio.addEventListener('change', () => { if (radio.checked) { - const searchEngineValue = engine === 'custom' ? customInput.value : radio.value; - customInput.style.display = engine === 'custom' ? 'block' : 'none'; - saveSingleSetting('searchEngine', searchEngineValue); + let searchEngineValue; + if (engine === 'custom') { + customInput.style.display = 'block'; + searchEngineValue = customInput.value; + } else { + customInput.style.display = 'none'; + searchEngineValue = radio.value; + } + chrome.storage.local.set({ searchEngine: searchEngineValue }); } }); + // Restore saved value on load if (searchEngine === radio.value) { radio.checked = true; customInput.style.display = engine === 'custom' ? 'block' : 'none'; } }); + // Special handling for initial load if 'custom' is selected if (!searchEngines.some(engine => searchEngine === document.getElementById(engine)?.value)) { const customRadio = document.getElementById('custom'); - if (customRadio) { - customRadio.checked = true; - customInput.style.display = 'block'; - customInput.value = searchEngine; - } + customRadio.checked = true; + customInput.style.display = 'block'; + customInput.value = searchEngine; } } -async function loadUserConfigs() { +function loadUserConfigs(callback) { const keys = Object.keys(configs); - return new Promise(resolve => { - chrome.storage.local.get(keys, userConfigs => { - Object.keys(configs).forEach(key => { - if (userConfigs[key] === undefined) { - userConfigs[key] = configs[key]; - } - }); - resolve(userConfigs); + chrome.storage.local.get(keys, function (userConfigs) { + userConfigs.searchEngine = userConfigs.searchEngine ?? configs.searchEngine; + userConfigs.modifiedKey = userConfigs.modifiedKey ?? configs.modifiedKey; + + keys.forEach(key => { + if (userConfigs[key] !== null && userConfigs[key] !== undefined) { + configs[key] = userConfigs[key]; + } }); - }); -} -function saveAllSettings() { - debounce(() => { - chrome.storage.local.set(configs); - }, 300)(); + if (callback) callback(userConfigs); + }); } -function saveSingleSetting(key, value) { +function saveConfig(key, value) { configs[key] = value; - debounce(() => { - chrome.storage.local.set({ [key]: value }); - }, 300)(); + let data = {}; + data[key] = value; + chrome.storage.local.set(data); } -function debounce(func, wait) { - let timeout; - return function executedFunction(...args) { - const later = () => { - clearTimeout(timeout); - func(...args); - }; - clearTimeout(timeout); - timeout = setTimeout(later, wait); - }; -} +function saveAllSettings() { + chrome.storage.local.set(configs); +} \ No newline at end of file