From db738658c68fe4cc51e2aba7624505a65c2c85b8 Mon Sep 17 00:00:00 2001 From: kudo-sync-bot Date: Mon, 2 Dec 2024 05:49:28 -0800 Subject: [PATCH] Revamped modal stack management to not rely on deprecated mutation events (https://chromestatus.com/feature/5083947249172480) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ± Expanded modal stack management to more types ↞ [auto-sync from https://github.com/adamlui/ai-web-extensions] --- .../chatgpt-infinity/chatgpt-infinity.user.js | 327 +++++++++--------- 1 file changed, 170 insertions(+), 157 deletions(-) diff --git a/chatgpt/chatgpt-infinity/chatgpt-infinity.user.js b/chatgpt/chatgpt-infinity/chatgpt-infinity.user.js index d5a43c106..7f1749911 100644 --- a/chatgpt/chatgpt-infinity/chatgpt-infinity.user.js +++ b/chatgpt/chatgpt-infinity/chatgpt-infinity.user.js @@ -199,7 +199,7 @@ // @description:zh-TW 從無所不知的 ChatGPT 生成無窮無盡的答案 (用任何語言!) // @author Adam Lui // @namespace https://github.com/adamlui -// @version 2024.12.2.1 +// @version 2024.12.2.2 // @license MIT // @match *://chatgpt.com/* // @match *://chat.openai.com/* @@ -384,8 +384,8 @@ // Show "Disabled (extension installed)" if (env.extensionInstalled) - GM_registerMenuCommand(`${menu.state.symbols[0]} ${app.msgs.menuLabel_disabled}`, modals.about.show, - tooltipsSupported ? { title: ' ' } : undefined) + GM_registerMenuCommand(`${menu.state.symbols[0]} ${app.msgs.menuLabel_disabled}`, + () => modals.open('about'), tooltipsSupported ? { title: ' ' } : undefined ) // ...or add settings entries else { @@ -459,14 +459,14 @@ // Add About entry const aboutLabel = `💡 ${app.msgs.menuLabel_about} ${app.msgs.appName}` - menu.ids.push(GM_registerMenuCommand(aboutLabel, modals.about.show, - tooltipsSupported ? { title: ' ' } : undefined)) + menu.ids.push(GM_registerMenuCommand(aboutLabel, () => modals.open('about'), + tooltipsSupported ? { title: ' ' } : undefined )) // Add Donate entry if (!env.extensionInstalled) { const donateLabel = `💖 ${app.msgs.menuLabel_donate}` - menu.ids.push(GM_registerMenuCommand(donateLabel, modals.donate.show, - tooltipsSupported ? { title: ' ' } : undefined)) + menu.ids.push(GM_registerMenuCommand(donateLabel, () => modals.open('donate'), + tooltipsSupported ? { title: ' ' } : undefined )) } }, @@ -521,7 +521,7 @@ `${app.msgs.appName} (v${currentVer}) ${app.msgs.alert_isUpToDate}!`, // msg '', '', updateAlertWidth ) - modals.about.show() + modals.open('about') }})} function toTitleCase(str) { @@ -555,21 +555,39 @@ } function siteAlert(title = '', msg = '', btns = '', checkbox = '', width = '') { - const alertID = chatgpt.alert(title, msg, btns, checkbox, width ), - alert = document.getElementById(alertID).firstChild - modals.setup(alert) // add class + starry BG + drag handlers - return alert + const alertID = chatgpt.alert(title, msg, btns, checkbox, width) + return document.getElementById(alertID).firstChild } // Define MODAL functions const modals = { - stack: [], + stack: [], // of types of undismissed modals - setup(modal) { + open(modalType) { + this.stack.unshift(modalType) // add to stack + const modal = modals[modalType]() // show modal modal.classList.add('chatgpt-infinity-modal') modal.onmousedown = modals.dragHandlers.mousedown - dom.fillStarryBG(modal) + dom.fillStarryBG(modal) // fill BG w/ rising stars + this.observeRemoval(modal, modalType) // to maintain stack for proper nav + }, + + observeRemoval(modal, type) { // to maintain stack for proper nav + const modalBG = modal.parentNode + new MutationObserver(([mutation], obs) => { + mutation.removedNodes.forEach(removedNode => { if (removedNode == modalBG) { + if (modals.stack[0] == type) { // new modal not launched, implement nav back logic + modals.stack.shift() // remove this modal type from stack + const nextModalType = modals.stack[0] + if (nextModalType) { // queue exists, open next modal + modals.stack.shift() // remove next modal type from stack since re-added on next open + modals.open(nextModalType) + } + } + obs.disconnect() + }}) + }).observe(modalBG.parentNode, { childList: true, subtree: true }) }, dragHandlers: { @@ -601,155 +619,150 @@ } }, - about: { - show() { - modals.stack.unshift('about') ; modals.stack = [...new Set(modals.stack)] // track for nav - - // Init styles - const headingStyle = 'font-size: 1.15rem', - pStyle = 'position: relative ; left: 3px', - pBrStyle = 'position: relative ; left: 4px ', - aStyle = 'color: ' + ( chatgpt.isDarkMode() ? '#c67afb' : '#8325c4' ) // purple - - // Show modal - const aboutModal = siteAlert( - `${app.symbol} ${app.msgs.appName}`, // title - `🏷️ ${app.msgs.about_version}: ` - + `${app.version}\n` - + `${app.msgs.about_poweredBy}: ` - + `` - + `` - + `chatgpt.js v${app.chatgptJSver}\n` - + `📜 ${app.msgs.about_sourceCode}:\n` - + `` - + app.urls.gitHub + '', - [ // buttons - function checkForUpdates() { updateCheck() }, - function getSupport(){}, - function rateUs() { modals.feedback.show() }, - function moreAIextensions(){} - ], '', 546 // set width - ) - - // Format text - aboutModal.querySelector('h2').style.cssText = 'text-align: center ; font-size: 37px ; padding: 9px' - aboutModal.querySelector('p').style.cssText = 'text-align: center' - - // Hack buttons - aboutModal.querySelectorAll('button').forEach(btn => { - btn.style.cssText = 'cursor: pointer !important' // since tweaks won't load on script auto-disable - - // Replace link buttons w/ clones that don't dismissAlert() - if (/support|extensions/i.test(btn.textContent)) { - const btnClone = btn.cloneNode(true) - btn.parentNode.replaceChild(btnClone, btn) ; btn = btnClone - btn.onclick = () => modals.safeWinOpen(app.urls[ - btn.textContent.includes(app.msgs.btnLabel_getSupport) ? 'support' : 'relatedExtensions' ]) - } - - // Prepend emoji + localize labels - if (/updates/i.test(btn.textContent)) - btn.textContent = `🚀 ${app.msgs.btnLabel_updateCheck}` - else if (/support/i.test(btn.textContent)) - btn.textContent = `🧠 ${app.msgs.btnLabel_getSupport}` - else if (/rate/i.test(btn.textContent)) - btn.textContent = `⭐ ${app.msgs.btnLabel_rateUs}` - else if (/extensions/i.test(btn.textContent)) - btn.textContent = `🤖 ${app.msgs.btnLabel_moreAIextensions}` - - // Hide Dismiss button - else btn.style.display = 'none' - }) - } - }, - - donate: { - longCOVIDwikiLink: 'https://en.wikipedia.org/wiki/Long_COVID', - - show() { - modals.stack.unshift('donate') ; modals.stack = [...new Set(modals.stack)] // track for nav - - // Show alert - const donateModal = siteAlert( - `💖 ${app.msgs.alert_showYourSupport}`, // title - `

${app.msgs.appName} ${app.msgs.alert_isOSS}.

` - + `

${app.msgs.alert_despiteAffliction} ` - + `` - + `${app.msgs.alert_longCOVID} ` - + `${app.msgs.alert_since2020}, ${app.msgs.alert_byDonatingResults}.

` - + `

${app.msgs.alert_yourContrib}, ${app.msgs.alert_noMatterSize}, ` - + `${app.msgs.alert_directlySupports}.

` - + `

${app.msgs.alert_tyForSupport}!

` - + '' - + `

` - + `${app.msgs.appAuthor}, ${app.msgs.alert_author}

`, - [ // buttons - function paypal(){}, - function githubSponsors(){}, - function cashApp(){}, - function rateUs() { modals.feedback.show() } - ], '', 478 // set width - ) - - // Format text - donateModal.querySelectorAll('p').forEach(p => // v-pad text, shrink line height - p.style.cssText = 'padding: 8px 0 ; line-height: 20px') - - // Hack buttons - const btns = donateModal.querySelectorAll('button') - btns.forEach((btn, idx) => { - - // Replace link buttons w/ clones that don't dismissAlert() - if (!/dismiss|rate/i.test(btn.textContent)) { - const btnClone = btn.cloneNode(true) - btn.parentNode.replaceChild(btnClone, btn) ; btn = btnClone - btn.onclick = () => modals.safeWinOpen(app.urls.donate[ - btnClone.textContent == 'Cash App' ? 'cashApp' - : btnClone.textContent == 'GitHub' ? 'gitHub' - : 'payPal' - ]) - } + about() { + + // Init styles + const headingStyle = 'font-size: 1.15rem', + pStyle = 'position: relative ; left: 3px', + pBrStyle = 'position: relative ; left: 4px ', + aStyle = 'color: ' + ( chatgpt.isDarkMode() ? '#c67afb' : '#8325c4' ) // purple + + // Show modal + const aboutModal = siteAlert( + `${app.symbol} ${app.msgs.appName}`, // title + `🏷️ ${app.msgs.about_version}: ` + + `${app.version}\n` + + `${app.msgs.about_poweredBy}: ` + + `` + + `` + + `chatgpt.js v${app.chatgptJSver}\n` + + `📜 ${app.msgs.about_sourceCode}:\n` + + `` + + app.urls.gitHub + '', + [ // buttons + function checkForUpdates() { updateCheck() }, + function getSupport(){}, + function rateUs() { modals.open('feedback') }, + function moreAIextensions(){} + ], '', 546 // set width + ) + + // Format text + aboutModal.querySelector('h2').style.cssText = 'text-align: center ; font-size: 37px ; padding: 9px' + aboutModal.querySelector('p').style.cssText = 'text-align: center' + + // Hack buttons + aboutModal.querySelectorAll('button').forEach(btn => { + btn.style.cssText = 'cursor: pointer !important' // since tweaks won't load on script auto-disable + + // Replace link buttons w/ clones that don't dismissAlert() + if (/support|extensions/i.test(btn.textContent)) { + const btnClone = btn.cloneNode(true) + btn.parentNode.replaceChild(btnClone, btn) ; btn = btnClone + btn.onclick = () => modals.safeWinOpen(app.urls[ + btn.textContent.includes(app.msgs.btnLabel_getSupport) ? 'support' : 'relatedExtensions' ]) + } - // Format buttons - if (idx == 0) btn.style.display = 'none' // hide Dismiss button - else { - btn.style.cssText = 'padding: 8px 6px !important ; margin-top: -14px ;' - + ' width: 107px ; line-height: 14px' - if (idx == btns.length -1) // de-emphasize right-most button - btn.classList.remove('primary-modal-btn') - else if (/rate/i.test(btn.textContent)) // localize 'Rate Us' label - btn.textContent = app.msgs.btnLabel_rateUs - } - }) - } + // Prepend emoji + localize labels + if (/updates/i.test(btn.textContent)) + btn.textContent = `🚀 ${app.msgs.btnLabel_updateCheck}` + else if (/support/i.test(btn.textContent)) + btn.textContent = `🧠 ${app.msgs.btnLabel_getSupport}` + else if (/rate/i.test(btn.textContent)) + btn.textContent = `⭐ ${app.msgs.btnLabel_rateUs}` + else if (/extensions/i.test(btn.textContent)) + btn.textContent = `🤖 ${app.msgs.btnLabel_moreAIextensions}` + + // Hide Dismiss button + else btn.style.display = 'none' + }) + + return aboutModal }, - feedback: { - show() { - const feedbackModal = siteAlert( - `${app.msgs.alert_choosePlatform}:`, '', // title - [ function greasyFork(){}, function productHunt(){}, function alternativeto(){} ] // buttons - ) - - // Hack buttons - feedbackModal.querySelectorAll('button').forEach((btn, idx) => { - if (idx == 0) btn.style.display = 'none' // hide Dismiss button - - // Replace buttons w/ clones that don't dismissAlert() + donate() { + + // Show modal + const donateModal = siteAlert( + `💖 ${app.msgs.alert_showYourSupport}`, // title + `

${app.msgs.appName} ${app.msgs.alert_isOSS}.

` + + `

${app.msgs.alert_despiteAffliction} ` + + '' + + `${app.msgs.alert_longCOVID} ` + + `${app.msgs.alert_since2020}, ${app.msgs.alert_byDonatingResults}.

` + + `

${app.msgs.alert_yourContrib}, ${app.msgs.alert_noMatterSize}, ` + + `${app.msgs.alert_directlySupports}.

` + + `

${app.msgs.alert_tyForSupport}!

` + + '' + + `

` + + `${app.msgs.appAuthor}, ${app.msgs.alert_author}

`, + [ // buttons + function paypal(){}, + function githubSponsors(){}, + function cashApp(){}, + function rateUs() { modals.open('feedback') } + ], '', 478 // set width + ) + + // Format text + donateModal.querySelectorAll('p').forEach(p => // v-pad text, shrink line height + p.style.cssText = 'padding: 8px 0 ; line-height: 20px') + + // Hack buttons + const btns = donateModal.querySelectorAll('button') + btns.forEach((btn, idx) => { + + // Replace link buttons w/ clones that don't dismissAlert() + if (!/dismiss|rate/i.test(btn.textContent)) { const btnClone = btn.cloneNode(true) btn.parentNode.replaceChild(btnClone, btn) ; btn = btnClone - btn.onclick = () => modals.safeWinOpen(app.urls.review[ - btn.textContent == 'Greasy Fork' ? 'greasyFork' - : btn.textContent == 'Product Hunt' ? 'productHunt' - : 'alternativeTo' + btn.onclick = () => modals.safeWinOpen(app.urls.donate[ + btnClone.textContent == 'Cash App' ? 'cashApp' + : btnClone.textContent == 'GitHub' ? 'gitHub' + : 'payPal' ]) - }) + } - // Nav back - feedbackModal.addEventListener('DOMNodeRemoved', () => modals[modals.stack[0]]?.show() ) - } + // Format buttons + if (idx == 0) btn.style.display = 'none' // hide Dismiss button + else { + btn.style.cssText = 'padding: 8px 6px !important ; margin-top: -14px ;' + + ' width: 107px ; line-height: 14px' + if (idx == btns.length -1) // de-emphasize right-most button + btn.classList.remove('primary-modal-btn') + else if (/rate/i.test(btn.textContent)) // localize 'Rate Us' label + btn.textContent = app.msgs.btnLabel_rateUs + } + }) + + return donateModal + }, + + feedback() { + + // Show modal + const feedbackModal = siteAlert( + `${app.msgs.alert_choosePlatform}:`, '', // title + [ function greasyFork(){}, function productHunt(){}, function alternativeto(){} ] // buttons + ) + + // Hack buttons + feedbackModal.querySelectorAll('button').forEach((btn, idx) => { + if (idx == 0) btn.style.display = 'none' // hide Dismiss button + + // Replace buttons w/ clones that don't dismissAlert() + const btnClone = btn.cloneNode(true) + btn.parentNode.replaceChild(btnClone, btn) ; btn = btnClone + btn.onclick = () => modals.safeWinOpen(app.urls.review[ + btn.textContent == 'Greasy Fork' ? 'greasyFork' + : btn.textContent == 'Product Hunt' ? 'productHunt' + : 'alternativeTo' + ]) + }) + + return feedbackModal }, safeWinOpen(url) { open(url, '_blank', 'noopener') } // to prevent backdoor vulnerabilities