|
148 | 148 | // @description:zu Yengeza izimpendulo ze-AI ku-Brave Search (inikwa amandla yi-GPT-4o!) |
149 | 149 | // @author KudoAI |
150 | 150 | // @namespace https://kudoai.com |
151 | | -// @version 2025.5.16.5 |
| 151 | +// @version 2025.5.16.6 |
152 | 152 | // @license MIT |
153 | 153 | // @icon https://assets.bravegpt.com/images/icons/bravegpt/icon48.png?v=df624b0 |
154 | 154 | // @icon64 https://assets.bravegpt.com/images/icons/bravegpt/icon64.png?v=df624b0 |
|
1423 | 1423 |
|
1424 | 1424 | // Define TOGGLE functions |
1425 | 1425 |
|
1426 | | - const toggle = { |
| 1426 | + window.toggle = { |
1427 | 1427 |
|
1428 | 1428 | anchorMode(state = '') { |
1429 | 1429 | const prevState = config.anchored // for restraining notif if no change from Pin menu 'Sidebar' click |
|
2615 | 2615 | } |
2616 | 2616 | } |
2617 | 2617 |
|
2618 | | - const menus = { |
2619 | | - hover: { |
2620 | | - createAppend(menuType) { |
2621 | | - if (!this.styles) this.stylize() |
2622 | | - this[menuType].div = dom.create.elem('div', { |
2623 | | - id: `${app.slug}-${menuType}-menu`, style: 'width: max-content', |
2624 | | - class: `${app.slug}-menu ${app.slug}-tooltip fade-in-less no-user-select` |
2625 | | - }) |
2626 | | - this[menuType].ul = dom.create.elem('ul') |
2627 | | - this[menuType].div.append(this[menuType].ul) ; app.div.append(this[menuType].div) |
2628 | | - this[menuType].div.onmouseenter = this[menuType].div.onmouseleave = this.toggle |
2629 | | - this.update(menuType) ; this[menuType].status = 'hidden' |
2630 | | - }, |
2631 | | - |
2632 | | - hide(menuType) { |
2633 | | - Object.assign(this[menuType].div.style, { display: 'none', opacity: 0 }) |
2634 | | - this[menuType].status = 'hidden' |
2635 | | - }, |
2636 | | - |
2637 | | - stylize() { |
2638 | | - document.head.append(this.styles = dom.create.style(` |
2639 | | - .${app.slug}-menu > ul { color: white } .${app.slug}-menu > ul > li::marker { color: #ffff0000 } |
2640 | | - .${app.slug}-menu > ul > li:first-of-type > svg { /* header entry icon */ |
2641 | | - width: 13px ; height: 13px ; top: 2px ; position: relative ; margin-right: 3px } |
2642 | | - #${app.slug}-api-menu > ul > li:first-of-type > svg { /* API header entry icon */ |
2643 | | - top: 3px ; margin: 0 1px 0 -4px } /* tighten pos */ |
2644 | | - .${app.slug}-menu-item .checkmark-icon { |
2645 | | - position: relative ; float: right ; margin-right: -20px ; top: 3.5px ; fill: #b3f96d } |
2646 | | - .${app.slug}-menu-item:hover .checkmark-icon { fill: green }` |
2647 | | - )) |
2648 | | - }, |
2649 | | - |
2650 | | - toggle(event) { // visibility |
2651 | | - const toggleElem = event.currentTarget, |
2652 | | - reMenuType = /-?(\w+)-(?:btn|menu)$/, |
2653 | | - menuType = reMenuType.exec(toggleElem.id)?.[1] || reMenuType.exec(toggleElem.className)?.[1], |
2654 | | - menu = menus.hover[menuType] |
2655 | | - clearTimeout(menu.hideTimeout) // in case rapid re-enter before ran |
2656 | | - if (!menu.div?.isConnected) menus.hover.createAppend(menuType) |
2657 | | - if (menu.status == 'hidden' && ( |
2658 | | - event.type == 'mouseenter' && event.target != menu.div // btn hovered-on |
2659 | | - || event.type == 'click' ) // btn clicked |
2660 | | - ) { // show menu |
2661 | | - menu.div.style.display = '' // for rects calc |
2662 | | - const rects = { |
2663 | | - appDiv: app.div.getBoundingClientRect(), toggleBtn: toggleElem.getBoundingClientRect(), |
2664 | | - hoverMenu: menu.div.getBoundingClientRect() |
2665 | | - } |
2666 | | - const appIsTooHigh = rects.toggleBtn.top < ( rects.hoverMenu.height +15 ) |
2667 | | - const appIsTooLow = rects.toggleBtn.bottom + rects.hoverMenu.height > ( innerHeight -15 ) |
2668 | | - const pointDirection = menu.preferredDirection == 'up' && appIsTooHigh |
2669 | | - || menu.preferredDirection == 'down' && !appIsTooLow ? 'down' : 'up' |
2670 | | - Object.assign(menu.div.style, { |
2671 | | - top: `${ rects.toggleBtn.top - rects.appDiv.top +( |
2672 | | - pointDirection == 'down' ? 30.5 : -rects.hoverMenu.height -13 )}px`, |
2673 | | - right: `${ rects.appDiv.right - event.clientX - menu.div.offsetWidth |
2674 | | - / ( pointDirection == 'up' ? /* center */ 2 : /* leftish-aligned */ 1.25 )}px`, |
2675 | | - opacity: 1 |
2676 | | - }) |
2677 | | - menu.status = 'visible' |
2678 | | - } else if (/click|mouseleave/.test(event.type)) // menu/btn hovered-off or btn clicked, hide menu |
2679 | | - return menus.hover[menuType].hideTimeout = setTimeout(() => menus.hover.hide(menuType), 55) |
2680 | | - }, |
2681 | | - |
2682 | | - update(menuType) { |
2683 | | - this[menuType].ul.textContent = '' |
2684 | | - this[menuType].entries.forEach((entry, idx) => { |
2685 | | - const item = dom.create.elem('li', { class: `${app.slug}-menu-item` }) |
2686 | | - if (idx == 0) { // header item |
2687 | | - item.innerHTML = `<b>${entry.label}</b>` |
2688 | | - item.classList.add(`${app.slug}-menu-header`) |
2689 | | - item.style.cssText = 'margin-bottom: 1px ; border-bottom: 1px dotted white' |
2690 | | - if (entry.iconType) item.prepend(icons.create({ key: entry.iconType })) |
2691 | | - } else { // child items |
2692 | | - item.textContent = entry.label |
2693 | | - item.style.paddingRight = '24px' // make room for checkmark |
2694 | | - if (idx == 1) item.style.marginTop = '3px' // top-pad first non-header item |
2695 | | - if (entry.iconType) { // prepend it |
2696 | | - const icon = icons.create({ key: entry.iconType }) |
2697 | | - icon.style.cssText = ` |
2698 | | - width: 12px ; height: 12px ; position: relative ; top: 1px ; right: 5px ; margin-left: 5px` |
2699 | | - if (entry.iconType == 'webCorner') icon.style.width = icon.style.height = '11px' // shrink it |
2700 | | - item.prepend(icon) |
2701 | | - } else // indent |
2702 | | - item.style.paddingLeft = '11px' |
2703 | | - if (entry.isActive?.()) |
2704 | | - item.append(icons.create({ key: 'checkmark', class: 'checkmark-icon', size: 12 })) |
2705 | | - } |
2706 | | - item.onclick = () => { |
2707 | | - if (!entry.onclick) return |
2708 | | - const prevOffsetTop = app.div.offsetTop ; entry.onclick() |
2709 | | - if (app.div.offsetTop != prevOffsetTop) this.hide(menuType) // since app moved |
2710 | | - this.update(menuType) |
2711 | | - } |
2712 | | - this[menuType].ul.append(item) |
2713 | | - }) |
2714 | | - }, |
2715 | | - |
2716 | | - api: { |
2717 | | - preferredDirection: 'down', |
2718 | | - entries: [ |
2719 | | - { label: `${app.msgs.menuLabel_preferred} API:`, iconType: 'lightning' }, |
2720 | | - ...[app.msgs.menuLabel_random, ...Object.keys(apis).filter(api => api !== 'OpenAI')].map(api => ({ |
2721 | | - label: api, |
2722 | | - onclick: () => { |
2723 | | - settings.save('preferredAPI', api == app.msgs.menuLabel_random ? false : api) |
2724 | | - feedback.notify(`${app.msgs.menuLabel_preferred} API ${app.msgs.menuLabel_saved.toLowerCase()}`, |
2725 | | - `${ config.anchored ? 'top' : 'bottom' }-right`) |
2726 | | - }, |
2727 | | - isActive: () => !config.preferredAPI && api == app.msgs.menuLabel_random |
2728 | | - || config.preferredAPI == api |
2729 | | - })) |
2730 | | - ] |
2731 | | - }, |
2732 | | - |
2733 | | - pin: { |
2734 | | - preferredDirection: 'down', |
2735 | | - entries: [ |
2736 | | - { label: `${app.msgs.menuLabel_pinTo}...`, iconType: 'pin' }, |
2737 | | - { label: app.msgs.menuLabel_top, iconType: 'webCorner', onclick: () => toggle.sidebar('sticky'), |
2738 | | - isActive: () => config.stickySidebar }, |
2739 | | - { label: app.msgs.menuLabel_sidebar, iconType: 'sidebar', |
2740 | | - onclick: () => { toggle.sidebar('sticky', 'off') ; toggle.anchorMode('off') }, |
2741 | | - isActive: () => !config.stickySidebar && !config.anchored |
2742 | | - }, |
2743 | | - { label: app.msgs.menuLabel_bottom, iconType: 'anchor', onclick: () => toggle.anchorMode(), |
2744 | | - isActive: () => config.anchored } |
2745 | | - ] |
2746 | | - } |
2747 | | - }, |
2748 | | - |
2749 | | - toolbar: { |
2750 | | - state: { |
2751 | | - symbols: ['❌', '✔️'], separator: env.scriptManager.name == 'Tampermonkey' ? ' — ' : ': ', |
2752 | | - words: [app.msgs.state_off.toUpperCase(), app.msgs.state_on.toUpperCase()] |
2753 | | - }, |
2754 | | - |
2755 | | - refresh() { |
2756 | | - if (typeof GM_unregisterMenuCommand == 'undefined') |
2757 | | - return log.debug('GM_unregisterMenuCommand not supported.') |
2758 | | - for (const id of this.entryIDs) { GM_unregisterMenuCommand(id) } this.register() |
2759 | | - }, |
2760 | | - |
2761 | | - register() { |
2762 | | - |
2763 | | - // Add Proxy API Mode toggle |
2764 | | - const pmLabel = this.state.symbols[+config.proxyAPIenabled] + ' ' |
2765 | | - + settings.controls.proxyAPIenabled.label + ' ' |
2766 | | - + this.state.separator + this.state.words[+config.proxyAPIenabled] |
2767 | | - this.entryIDs = [GM_registerMenuCommand(pmLabel, toggle.proxyMode, |
2768 | | - env.scriptManager.supportsTooltips ? { title: settings.controls.proxyAPIenabled.helptip } |
2769 | | - : undefined)] |
2770 | | - // Add About/Settings entries |
2771 | | - ;['about', 'settings'].forEach(entryType => this.entryIDs.push(GM_registerMenuCommand( |
2772 | | - entryType == 'about' ? `💡 ${settings.controls.about.label}` : `⚙️ ${app.msgs.menuLabel_settings}`, |
2773 | | - () => modals.open(entryType), env.scriptManager.supportsTooltips ? { title: ' ' } : undefined |
2774 | | - ))) |
2775 | | - } |
2776 | | - } |
2777 | | - } |
2778 | | - |
2779 | 2618 | window.modals = { |
2780 | 2619 | stack: [], // of types of undismissed modals |
2781 | 2620 | class: `${app.slug}-modal`, |
|
0 commit comments