|
3 | 3 | // @description Add AI chat & product/category summaries to Amazon shopping, powered by the latest LLMs like GPT-4o! |
4 | 4 | // @author KudoAI |
5 | 5 | // @namespace https://kudoai.com |
6 | | -// @version 2025.5.9 |
| 6 | +// @version 2025.5.9.1 |
7 | 7 | // @license MIT |
8 | 8 | // @icon https://amazongpt.kudoai.com/assets/images/icons/app/black-gold-teal/icon48.png?v=8e8ed1c |
9 | 9 | // @icon64 https://amazongpt.kudoai.com/assets/images/icons/app/black-gold-teal/icon64.png?v=8e8ed1c |
|
124 | 124 | name: (() => { try { return GM_info.scriptHandler } catch (err) { return 'unknown' }})(), |
125 | 125 | version: (() => { try { return GM_info.version } catch (err) { return 'unknown' }})() |
126 | 126 | } |
127 | | - }; |
128 | | - ['Chromium', 'Firefox', 'Chrome', 'Edge', 'Brave', 'Mobile'].forEach(platform => |
| 127 | + } ; ['Chromium', 'Firefox', 'Chrome', 'Edge', 'Brave', 'Mobile'].forEach(platform => |
129 | 128 | env.browser[`is${ platform == 'Firefox' ? 'FF' : platform }`] = chatgpt.browser['is' + platform]()) |
130 | 129 | env.browser.isPortrait = env.browser.isMobile && ( innerWidth < innerHeight ) |
131 | 130 | env.browser.isPhone = env.browser.isMobile && innerWidth <= 480 |
|
466 | 465 | + settings.controls.proxyAPIenabled.label + ' ' |
467 | 466 | + this.state.separator + this.state.words[+config.proxyAPIenabled] |
468 | 467 | this.entryIDs = [GM_registerMenuCommand(pmLabel, toggle.proxyMode, |
469 | | - env.scriptManager.supportsTooltips ? { title: settings.controls.proxyAPIenabled.helptip } : undefined)]; |
| 468 | + env.scriptManager.supportsTooltips ? { title: settings.controls.proxyAPIenabled.helptip } : undefined)] |
470 | 469 |
|
471 | 470 | // Add About/Settings entries |
472 | | - ['about', 'settings'].forEach(entryType => this.entryIDs.push(GM_registerMenuCommand( |
| 471 | + ;['about', 'settings'].forEach(entryType => this.entryIDs.push(GM_registerMenuCommand( |
473 | 472 | entryType == 'about' ? `💡 ${settings.controls.about.label}` : `⚙️ ${app.msgs.menuLabel_settings}`, |
474 | 473 | () => modals.open(entryType), env.scriptManager.supportsTooltips ? { title: ' ' } : undefined |
475 | 474 | ))) |
|
750 | 749 | transition: '0.1s', '-webkit-transition': '0.1s', '-moz-transition': '0.1s', |
751 | 750 | '-o-transition': '0.1s', '-ms-transition': '0.1s' |
752 | 751 | }) |
753 | | - document.body.style.cursor = 'grabbing'; // update cursor |
754 | | - [...modals.draggingModal.children] // prevent hover FX if drag lags behind cursor |
755 | | - .forEach(child => child.style.pointerEvents = 'none'); |
756 | | - ['mousemove', 'mouseup'].forEach(eventType => // add listeners |
| 752 | + document.body.style.cursor = 'grabbing' // update cursor |
| 753 | + ;[...modals.draggingModal.children] // prevent hover FX if drag lags behind cursor |
| 754 | + .forEach(child => child.style.pointerEvents = 'none') |
| 755 | + ;['mousemove', 'mouseup'].forEach(eventType => // add listeners |
757 | 756 | document.addEventListener(eventType, modals.handlers.drag[eventType])) |
758 | 757 | const draggingModalRect = modals.draggingModal.getBoundingClientRect() |
759 | 758 | modals.handlers.drag.offsetX = event.clientX - draggingModalRect.left +21 |
|
774 | 773 | transition: 'inherit', '-webkit-transition': 'inherit', '-moz-transition': 'inherit', |
775 | 774 | '-o-transition': 'inherit', '-ms-transition': 'inherit' |
776 | 775 | }) |
777 | | - document.body.style.cursor = ''; // restore cursor |
778 | | - [...modals.draggingModal.children] // restore pointer events |
779 | | - .forEach(child => child.style.pointerEvents = ''); |
780 | | - ['mousemove', 'mouseup'].forEach(eventType => // remove listeners |
| 776 | + document.body.style.cursor = '' // restore cursor |
| 777 | + ;[...modals.draggingModal.children] // restore pointer events |
| 778 | + .forEach(child => child.style.pointerEvents = '') |
| 779 | + ;['mousemove', 'mouseup'].forEach(eventType => // remove listeners |
781 | 780 | document.removeEventListener(eventType, modals.handlers.drag[eventType])) |
782 | 781 | modals.draggingModal = null |
783 | 782 | } |
|
3304 | 3303 | const downloadBtn = dom.create.elem('btn', { id: `${app.slug}-download-btn` }), |
3305 | 3304 | downloadSVGs = { download: icons.download.create(), downloaded: icons.checkmarkDouble.create() } |
3306 | 3305 | Object.entries(downloadSVGs).forEach(([svgType, svg]) => { |
3307 | | - svg.id = `${app.slug}-${svgType}-icon`; |
3308 | | - ['width', 'height'].forEach(attr => svg.setAttribute(attr, 15)) |
| 3306 | + svg.id = `${app.slug}-${svgType}-icon` |
| 3307 | + ;['width', 'height'].forEach(attr => svg.setAttribute(attr, 15)) |
3309 | 3308 | }) |
3310 | 3309 | downloadBtn.append(downloadSVGs.download) |
3311 | 3310 | downloadBtn.onclick = event => { // download code, update icon + tooltip status |
|
3446 | 3445 | id: `${app.slug}-chatbar`, rows: 1, placeholder: `${app.msgs.tooltip_sendReply}...` }) |
3447 | 3446 | continueChatDiv.append(chatTextarea) |
3448 | 3447 | replyForm.append(continueChatDiv) ; replySection.append(replyForm) |
3449 | | - appDiv.querySelector('.reply-bubble').after(replySection); |
| 3448 | + appDiv.querySelector('.reply-bubble').after(replySection) |
3450 | 3449 |
|
3451 | 3450 | // Create/append chatbar buttons |
3452 | | - ['send', 'shuffle'].forEach(btnType => { |
| 3451 | + ;['send', 'shuffle'].forEach(btnType => { |
3453 | 3452 | const btn = dom.create.elem('button', { |
3454 | 3453 | id: `${app.slug}-${btnType}-btn`, class: `${app.slug}-chatbar-btn no-mobile-tap-outline` }) |
3455 | 3454 | btn.style.right = `${ btnType == 'send' ? ( env.browser.isFF ? 12 : 9 ) |
|
3495 | 3494 | hljs.highlightAll() // highlight code |
3496 | 3495 | replyPre.querySelectorAll('code').forEach(codeBlock => // add linebreaks after semicolons |
3497 | 3496 | codeBlock.innerHTML = codeBlock.innerHTML.replace(/;\s*/g, ';<br>')) |
3498 | | - update.replyPrefix(); // prepend '>> ' if dark scheme w/ bg animations to emulate terminal |
| 3497 | + update.replyPrefix() // prepend '>> ' if dark scheme w/ bg animations to emulate terminal |
3499 | 3498 |
|
3500 | 3499 | // Typeset math |
3501 | | - [replyPre, ...replyPre.querySelectorAll('*')].forEach(elem => |
| 3500 | + ;[replyPre, ...replyPre.querySelectorAll('*')].forEach(elem => |
3502 | 3501 | renderMathInElement(elem, { delimiters: katexDelimiters, throwOnError: false })) |
3503 | 3502 |
|
3504 | 3503 | // Auto-scroll if active |
|
3547 | 3546 | }) |
3548 | 3547 | const copySVGs = { copy: icons.copy.create(), copied: icons.checkmarkDouble.create() } |
3549 | 3548 | Object.entries(copySVGs).forEach(([svgType, svg]) => { |
3550 | | - svg.id = `${app.slug}-${svgType}-icon`; |
3551 | | - ['width', 'height'].forEach(attr => svg.setAttribute(attr, 15)) |
| 3549 | + svg.id = `${app.slug}-${svgType}-icon` |
| 3550 | + ;['width', 'height'].forEach(attr => svg.setAttribute(attr, 15)) |
3552 | 3551 | }) |
3553 | 3552 | this.copy.append(copySVGs.copy) |
3554 | 3553 | this.copy.listeners = {} |
|
3581 | 3580 | id: `${app.slug}-share-btn`, class: 'no-mobile-tap-outline', |
3582 | 3581 | style: this.styles + 'margin-right: 10px' |
3583 | 3582 | }) |
3584 | | - const shareSVG = icons.arrowShare.create(); |
3585 | | - ['width', 'height'].forEach(attr => shareSVG.setAttribute(attr, 16)) |
| 3583 | + const shareSVG = icons.arrowShare.create() |
| 3584 | + ;['width', 'height'].forEach(attr => shareSVG.setAttribute(attr, 16)) |
3586 | 3585 | this.share.append(shareSVG) |
3587 | 3586 | if (!env.browser.isMobile) this.share.onmouseenter = this.share.onmouseleave = tooltip.toggle |
3588 | 3587 | this.share.onclick = event => { |
|
3609 | 3608 | }) |
3610 | 3609 | const regenSVGwrapper = dom.create.elem('div', { // to spin while respecting ini icon tilt |
3611 | 3610 | style: 'display: flex' }) // wrap the icon tightly |
3612 | | - const regenSVG = icons.arrowsCyclic.create(); |
3613 | | - ['width', 'height'].forEach(attr => regenSVG.setAttribute(attr, 14)) |
| 3611 | + const regenSVG = icons.arrowsCyclic.create() |
| 3612 | + ;['width', 'height'].forEach(attr => regenSVG.setAttribute(attr, 14)) |
3614 | 3613 | regenSVGwrapper.append(regenSVG) ; this.regen.append(regenSVGwrapper) |
3615 | 3614 | if (!env.browser.isMobile) this.regen.onmouseenter = this.regen.onmouseleave = tooltip.toggle |
3616 | 3615 | this.regen.onclick = event => { |
|
3632 | 3631 | const speakSVGscroller = dom.create.elem('div', { // to scroll the icons |
3633 | 3632 | style: `display: flex ; /* align the SVGs horizontally */ |
3634 | 3633 | width: 41px ; height: 22px /* rectangle to fit both icons */` }) |
3635 | | - const speakSVGs = { speak: icons.soundwave.create() } ; speakSVGs.speak.id = `${app.slug}-speak-icon`; |
3636 | | - ['generating', 'playing'].forEach(state => { |
| 3634 | + const speakSVGs = { speak: icons.soundwave.create() } ; speakSVGs.speak.id = `${app.slug}-speak-icon` |
| 3635 | + ;['generating', 'playing'].forEach(state => { |
3637 | 3636 | speakSVGs[state] = [] |
3638 | 3637 | for (let i = 0 ; i < 2 ; i++) { // push/id 2 of each state icon for continuous scroll animation |
3639 | 3638 | speakSVGs[state].push( |
|
3759 | 3758 | // Create/ID/classify/listenerize/stylize APP container |
3760 | 3759 | const appDiv = dom.create.elem('div', { id: app.slug, class: 'anchored fade-in' }) |
3761 | 3760 | addListeners.appDiv() ; if (config.expanded) appDiv.classList.add('expanded') |
3762 | | - document.head.append(app.styles = dom.create.style()) ; update.appStyle(); |
3763 | | - ['rpg', 'rpw'].forEach(cssType => // rising particles |
| 3761 | + document.head.append(app.styles = dom.create.style()) ; update.appStyle() |
| 3762 | + ;['rpg', 'rpw'].forEach(cssType => // rising particles |
3764 | 3763 | document.head.append(dom.create.style(GM_getResourceText(`${cssType}CSS`)))) |
3765 | 3764 |
|
3766 | 3765 | // Hide GF alert on GitHub if found |
|
0 commit comments