Skip to content

Commit

Permalink
Added font size slider
Browse files Browse the repository at this point in the history
  • Loading branch information
adamlui committed Jun 15, 2024
1 parent 16dc101 commit 1f0ff02
Showing 1 changed file with 119 additions and 32 deletions.
151 changes: 119 additions & 32 deletions googlegpt/greasemonkey/googlegpt.user.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@
// @description:zu Yengeza izimpendulo ze-AI ku-Google Search (inikwa amandla yi-Google Gemma + GPT-4o!)
// @author KudoAI
// @namespace https://kudoai.com
// @version 2024.6.14.2
// @version 2024.6.14.3
// @license MIT
// @icon https://media.googlegpt.io/images/icons/googlegpt/black/icon48.png?8652a6e
// @icon64 https://media.googlegpt.io/images/icons/googlegpt/black/icon64.png?8652a6e
Expand Down Expand Up @@ -410,18 +410,22 @@
const config = {
appName: 'GoogleGPT', appSymbol: '🤖', keyPrefix: 'googleGPT',
appURL: 'https://www.googlegpt.io', gitHubURL: 'https://github.com/KudoAI/googlegpt',
greasyForkURL: 'https://greasyfork.org/scripts/478597-googlegpt' }
greasyForkURL: 'https://greasyfork.org/scripts/478597-googlegpt',
minFontSize: 13, maxFontSize: 24, lineHeightRatio: isMobile ? 1.357 : 1.375
}
config.updateURL = config.greasyForkURL.replace('https://', 'https://update.')
.replace(/(\d+)-?([a-zA-Z-]*)$/, (_, id, name) => `${ id }/${ !name ? 'script' : name }.meta.js`)
config.supportURL = config.gitHubURL + '/issues/new'
config.feedbackURL = config.gitHubURL + '/discussions/new/choose'
config.assetHostURL = config.gitHubURL.replace('github.com', 'cdn.jsdelivr.net/gh') + '@f59023d/'
config.assetHostURL = config.gitHubURL.replace('github.com', 'cdn.jsdelivr.net/gh') + '@c2c72f8/'
config.userLanguage = chatgpt.getUserLanguage()
config.userLocale = window.location.hostname.endsWith('.com') ? 'us'
: window.location.hostname.split('.').pop()
loadSetting('autoget', 'autoFocusChatbarDisabled', 'autoScroll', 'notFirstRun', 'prefixEnabled', 'proxyAPIenabled',
'replyLanguage', 'rqDisabled', 'scheme', 'stickySidebar', 'streamingDisabled', 'suffixEnabled', 'widerSidebar')
loadSetting('autoget', 'autoFocusChatbarDisabled', 'autoScroll', 'fontSize', 'notFirstRun', 'prefixEnabled',
'proxyAPIenabled', 'replyLanguage', 'rqDisabled', 'scheme', 'stickySidebar', 'streamingDisabled',
'suffixEnabled', 'widerSidebar')
if (!config.replyLanguage) saveSetting('replyLanguage', config.userLanguage) // init reply language if unset
if (!config.fontSize) saveSetting('fontSize', isMobile ? 14 : 16) // init reply font size if unset
if (getUserscriptManager() != 'Tampermonkey') saveSetting('streamingDisabled', true) // disable streaming if not TM
if (isMobile && !config.notFirstRun) saveSetting('autoget', true) // reverse default auto-get disabled if mobile
saveSetting('notFirstRun', true)
Expand Down Expand Up @@ -843,7 +847,7 @@
if (!appTitleVisible || !logoVisible) {
const appTitleAnchor = createAnchor(config.appURL, (() => {
if (appLogoImg.loaded) { // size/pos/return app logo img
appLogoImg.width = isMobile ? 197 : isFirefox ? 127 : 125
appLogoImg.width = isMobile ? 177 : isFirefox ? 127 : 125
appLogoImg.style.cssText = (
appLogoImg.loaded ? `position: relative ; top: ${ isMobile ? 4 : isFirefox ? 3 : 2 }px`
+ ( isMobile ? '; margin-left: 1px' : '' ) : '' )
Expand Down Expand Up @@ -883,15 +887,19 @@
+ 'transform: scale(1.185) ; transition: transform 0.05s ease }'
+ '#googlegpt .loading { padding-bottom: 15px ; color: #b6b8ba ; animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite }'
+ '#googlegpt.sidebar-free { margin-left: 60px ; height: fit-content }'
+ '#font-size-slider { width: 98% ; height: 10px ; margin: 15px auto ; background-color: #ccc }'
+ '#font-size-slider-knob { width: 11px ; height: 20px ; background-color: #000 ; border-radius: 30% ; position: relative ; top: -5px ;'
+ 'cursor: grab ; cursor: -webkit-grab ; cursor: -moz-grab }'
+ '#font-size-slider-knob:active { cursor: grabbing ; cursor: -webkit-grabbing ; cursor: -moz-grabbing }'
+ '.standby-btn { width: 100% ; padding: 11px 0 ; cursor: pointer ; margin-top: 20px ;'
+ ( scheme == 'dark' ? 'color: #fff ; background: #000 ;' : '')
+ `border-radius: 4px ; border: 1px solid ${ scheme == 'dark' ? '#fff' : '#000' } ;`
+ 'transform: scale(1) ; transition: transform 0.1s ease }'
+ '.standby-btn:hover { border-radius: 6px ; transform: scale(1.025) ;'
+ `${ scheme == 'dark' ? 'background: white ; color: black' : 'background: black ; color: white' }}`
+ '#googlegpt > pre {'
+ `font-size: ${ isMobile ? '14px' : '1.15em' } ; white-space: pre-wrap ; min-width: 0 ; margin: 16px 0 0 0 ;`
+ `line-height: ${ isMobile ? 19 : 22 }px ; padding: 1.25em ; border-radius: 10px ; overflow: auto ;`
+ `font-size: ${config.fontSize}px ; white-space: pre-wrap ; min-width: 0 ; margin: 16px 0 0 0 ;`
+ `line-height: ${ config.fontSize * config.lineHeightRatio }px ; padding: 1.25em ; border-radius: 10px ; overflow: auto ;`
+ ( scheme == 'dark' ? 'background: #3a3a3a ; color: #f2f2f2 }' : 'background: #eaeaea }' )
+ '@keyframes pulse { 0%, to { opacity: 1 } 50% { opacity: .5 }}'
+ '#googlegpt section.loading { padding: 15px 0 14px 5px }' // left/top-pad loading status when sending replies
Expand All @@ -918,12 +926,12 @@
+ `color: ${ scheme == 'dark' ? '#aaa' : '#c1c1c1' }}`
+ '.fade-in { opacity: 0 ; transform: translateY(10px) ; transition: opacity 0.5s ease, transform 0.5s ease }'
+ '.fade-in.active { opacity: 1 ; transform: translateY(0) }'
+ '.fade-in { opacity: 0 ; transform: translateY(10px) ; transition: opacity 0.5s ease, transform 0.5s ease }'
+ '.fade-in-less { opacity: 0 ; transition: opacity 0.2s ease }'
+ '.fade-in.active, .fade-in-less.active { opacity: 1 ; transform: translateY(0) }'
+ '#send-btn { border: none ; float: right ; position: relative ; background: none ;'
+ `color: ${ scheme == 'dark' ? '#aaa' : 'lightgrey' } ; cursor: pointer }`
+ `#send-btn:hover { color: ${ scheme == 'dark' ? 'white' : '#638ed4' } }`
+ `.kudoai { font-size: ${ isMobile ? 0.85 : 0.75 }rem ; position: relative ; left: ${ isMobile ? 8 : 6 }px ; color: #aaa }`
+ '.kudoai a, .kudoai a:visited { color: #aaa ; text-decoration: none }'
+ '.kudoai a:hover { color:' + ( scheme == 'dark' ? 'white' : 'black' ) + '; text-decoration: none }'
+ ( // markdown styles
'#googlegpt > pre h1 { font-size: 1.25em } #googlegpt > pre h2 { font-size: 1.1em }' // size headings
+ '#googlegpt > pre > p { margin-bottom: -1.25em }' // eliminate bottom gap
Expand Down Expand Up @@ -1026,8 +1034,8 @@
}

function updateTooltip(buttonType) { // text & position
const cornerBtnTypes = ['about', 'speak', 'ssb', 'wsb'],
[ctrAddend, spreadFactor] = document.querySelector('.standby-btn') ? [19, 15] : [10, 25],
const cornerBtnTypes = ['about', 'speak', 'ssb', 'font-size', 'wsb'],
[ctrAddend, spreadFactor] = document.querySelector('.standby-btn') ? [17, 17] : [10, 25],
iniRoffset = spreadFactor * (buttonType == 'send' ? 1.65 : cornerBtnTypes.indexOf(buttonType) + 1) + ctrAddend

// Update text
Expand All @@ -1036,6 +1044,7 @@
: buttonType == 'speak' ? msgs.tooltip_playAnswer || 'Play answer'
: buttonType == 'ssb' ? (( config.stickySidebar ? `${ msgs.prefix_exit || 'Exit' } ` : '' )
+ ( msgs.menuLabel_stickySidebar || 'Sticky Sidebar' ))
: buttonType == 'font-size' ? msgs.tooltip_fontSize || 'Font size'
: buttonType == 'wsb' ? (( config.widerSidebar ? `${ msgs.prefix_exit || 'Exit' } ` : '' )
+ ( msgs.menuLabel_widerSidebar || 'Wider Sidebar' ))
: buttonType == 'send' ? msgs.tooltip_sendReply || 'Send reply' : '' )
Expand Down Expand Up @@ -1189,13 +1198,81 @@

function toggleSidebar(mode) {
saveSetting(mode + 'Sidebar', !config[mode + 'Sidebar'])
if (appDiv.querySelector('#font-size-slider')) toggleFontSizeSlider('off')
updateTweaksStyle()
if (mode == 'wider' && document.querySelector('.corner-btn')) updateWSBsvg() ; else updateSSBsvg()
notify(( msgs[`menuLabel_${ mode }Sidebar`] || mode.charAt(0).toUpperCase() + mode.slice(1) + ' Sidebar' )
+ ' ' + state.word[+config[mode + 'Sidebar']])
refreshMenu()
}

function toggleFontSizeSlider(state = '') {
const hWheelDistance = 10, // px
fadeInDelay = 5, // ms
answerPre = appDiv.querySelector('pre')

// Init slider
let fontSizeSlider = document.getElementById('font-size-slider')
if (!fontSizeSlider) { // create/append container/knob

// Create/append slider elems
fontSizeSlider = document.createElement('div') ; fontSizeSlider.id = 'font-size-slider'
fontSizeSlider.className = 'fade-in-less' ; fontSizeSlider.style.display = 'none'
const sliderKnob = document.createElement('div') ; sliderKnob.id = 'font-size-slider-knob'
fontSizeSlider.append(sliderKnob)
appDiv.insertBefore(fontSizeSlider, appDiv.querySelector('.btn-tooltip,' // desktop
+ 'pre')) // mobile
// Init knob pos
setTimeout(() => {
const sliderWidth = fontSizeSlider.offsetWidth - sliderKnob.offsetWidth,
iniLeft = (config.fontSize - config.minFontSize) / (config.maxFontSize - config.minFontSize) * sliderWidth
sliderKnob.style.left = iniLeft + 'px'
}, fadeInDelay) // to ensure visibility for accurate dimension calcs

// Add event listeners for dragging knob
let isDragging = false, startX, startLeft;
sliderKnob.addEventListener('mousedown', event => {
isDragging = true ; startX = event.clientX ; startLeft = sliderKnob.offsetLeft })
appDiv.addEventListener('mousemove', event => {
if (isDragging) moveKnob(startLeft + event.clientX - startX) })
appDiv.addEventListener('mouseup', () => isDragging = false)

// Add event listener for wheel-scrolling knob
fontSizeSlider.addEventListener('wheel', event => {
event.preventDefault()
moveKnob(sliderKnob.offsetLeft + ( event.deltaY < 0 ? hWheelDistance : -hWheelDistance ))
})

function moveKnob(newLeft) {

// Bound knob
const sliderWidth = fontSizeSlider.offsetWidth - sliderKnob.offsetWidth
if (newLeft < 0) newLeft = 0
if (newLeft > sliderWidth) newLeft = sliderWidth

// Move knob
sliderKnob.style.left = newLeft + 'px'

// Adjust font size based on knob position
const fontSizePercent = newLeft / sliderWidth,
fontSize = config.minFontSize + fontSizePercent * (config.maxFontSize - config.minFontSize)
answerPre.style.fontSize = fontSize + 'px'
answerPre.style.lineHeight = fontSize * config.lineHeightRatio + 'px'
saveSetting('fontSize', fontSize)
}
}

// Toggle visibility
const balloonTip = document.querySelector('.balloon-tip')
if (state == 'on' || (!state && fontSizeSlider.style.display == 'none')) {
fontSizeSlider.style.display = '' ; balloonTip.style.display = 'none'
setTimeout(() => fontSizeSlider.classList.add('active'), fadeInDelay)
} else if (state == 'off' || (!state && fontSizeSlider.style.display != 'none')) {
fontSizeSlider.classList.remove('active') ; balloonTip.style.display = ''
setTimeout(() => fontSizeSlider.style.display = 'none', 55)
}
}

function toggleTooltip(event) { // visibility
tooltipDiv.eventYpos = event.currentTarget.getBoundingClientRect().top // for updateTooltip() y-pos calc
updateTooltip(event.currentTarget.id.replace(/-btn$/, ''))
Expand Down Expand Up @@ -1584,21 +1661,16 @@

reply: function(answer) {

// Hide font size slider if visibile
if (appDiv.querySelector('#font-size-slider')) toggleFontSizeSlider('off')

// Build answer interface up to reply section if missing
if (!appDiv.querySelector('pre')) {
while (appDiv.firstChild) appDiv.removeChild(appDiv.firstChild) // clear app content

// Create/append app title elems
updateTitleElems()

// Create/append 'by KudoAI'
if (!isMobile) {
const kudoAIspan = document.createElement('span')
kudoAIspan.classList.add('kudoai', 'no-user-select') ; kudoAIspan.textContent = 'by '
const kudoAIlink = createAnchor('https://www.kudoai.com', 'KudoAI')
kudoAIspan.append(kudoAIlink) ; appDiv.append(kudoAIspan)
}

// Create/append about button
const aboutSpan = document.createElement('span'),
aboutSVG = document.createElementNS('http://www.w3.org/2000/svg', 'svg'),
Expand Down Expand Up @@ -1632,16 +1704,34 @@
speakSpan.append(speakSVG) ; appDiv.append(speakSpan)
}

if (!isMobile) {

// Create/append Sticky Sidebar button
// Create/append Sticky Sidebar button
if (!isMobile) {
var ssbSpan = document.createElement('span'),
ssbSVG = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
ssbSpan.id = 'ssb-btn' // for updateSSBsvg() + toggleTooltip()
ssbSpan.className = 'corner-btn' ; ssbSpan.style.margin = '-0.05rem 6px 0 0'
ssbSpan.append(ssbSVG) ; appDiv.append(ssbSpan) ; updateSSBsvg()
}

// Create/append font size button
if (answer != 'standby') {
var fontSizeSpan = document.createElement('span'),
fontSizeSVG = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
const fontSizeSVGpathA = document.createElementNS('http://www.w3.org/2000/svg','path'),
fontSizeSVGpathB = document.createElementNS('http://www.w3.org/2000/svg','path')
fontSizeSpan.id = 'font-size-btn' // for toggleTooltip()
fontSizeSpan.className = 'corner-btn' ; fontSizeSpan.style.margin = `${ isMobile ? 3 : -2 }px 10px 0 2px`
const fontSizeSVGattrs = [['width', 19], ['height', 19], ['viewBox', '0 0 512 512']]
fontSizeSVGattrs.forEach(([attr, value]) => fontSizeSVG.setAttribute(attr, value))
fontSizeSVGpathA.setAttribute('d',
'M234.997 448.199h-55.373a6.734 6.734 0 0 1-6.556-5.194l-11.435-48.682a6.734 6.734 0 0 0-6.556-5.194H86.063a6.734 6.734 0 0 0-6.556 5.194l-11.435 48.682a6.734 6.734 0 0 1-6.556 5.194H7.74c-4.519 0-7.755-4.363-6.445-8.687l79.173-261.269a6.734 6.734 0 0 1 6.445-4.781h69.29c2.97 0 5.59 1.946 6.447 4.79l78.795 261.269c1.303 4.322-1.933 8.678-6.448 8.678zm-88.044-114.93l-19.983-84.371c-1.639-6.921-11.493-6.905-13.111.02l-19.705 84.371c-.987 4.224 2.22 8.266 6.558 8.266H140.4c4.346 0 7.555-4.056 6.553-8.286z')
fontSizeSVGpathB.setAttribute('d',
'M502.572 448.199h-77.475a9.423 9.423 0 0 1-9.173-7.268l-16-68.114a9.423 9.423 0 0 0-9.173-7.268H294.19a9.423 9.423 0 0 0-9.173 7.268l-16 68.114a9.423 9.423 0 0 1-9.173 7.268h-75.241c-6.322 0-10.851-6.104-9.017-12.155L286.362 70.491a9.422 9.422 0 0 1 9.017-6.69h96.947a9.422 9.422 0 0 1 9.021 6.702l110.245 365.554c1.825 6.047-2.703 12.142-9.02 12.142zM379.385 287.395l-27.959-118.047c-2.293-9.683-16.081-9.661-18.344.029l-27.57 118.047c-1.38 5.91 3.106 11.565 9.175 11.565h55.529c6.082-.001 10.571-5.676 9.169-11.594z')
fontSizeSVG.append(fontSizeSVGpathA, fontSizeSVGpathB) ; fontSizeSpan.append(fontSizeSVG) ; appDiv.append(fontSizeSpan)
}

// Create/append Wider Sidebar button
// Create/append Wider Sidebar button
if (!isMobile) {
var wsbSpan = document.createElement('span'),
wsbSVG = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
wsbSpan.id = 'wsb-btn' // for updateSSBsvg() + toggleTooltip()
Expand Down Expand Up @@ -1700,9 +1790,10 @@
})
})
ssbSVG?.addEventListener('click', () => toggleSidebar('sticky'))
fontSizeSVG?.addEventListener('click', () => toggleFontSizeSlider())
wsbSVG?.addEventListener('click', () => toggleSidebar('wider'))
if (!isMobile) // add hover listeners for tooltips
[aboutSpan, speakSpan, ssbSpan, wsbSpan].forEach(span => { if (span)
[aboutSpan, speakSpan, ssbSpan, fontSizeSpan, wsbSpan].forEach(span => { if (span)
['mouseover', 'mouseout'].forEach(event => span.addEventListener(event, toggleTooltip)) })

// Show standby state if prefix/suffix mode on
Expand All @@ -1723,12 +1814,8 @@
const balloonTipSpan = document.createElement('span')
var answerPre = document.createElement('pre')
balloonTipSpan.className = 'balloon-tip'
balloonTipSpan.style.cssText = ( // pos it
`top: ${ isMobile ? '5px' : isFirefox ? '0.45em' : '0.219em' } ;`
+ `right: ${ isMobile ? '231px' : (
isFirefox ? ( 14.65 - ( appLogoImg.loaded ? 0 : 2.13 ))
: ( 7.25 - ( appLogoImg.loaded ? 0 : ( hasSidebar ? 1.25 : 1.29 )))) + 'em' }`
)
balloonTipSpan.style.cssText = 'float: left ;'
+ `margin: ${ isMobile ? 39 : 28 }px -15px 0 0 ; left: ${ isMobile ? 12 : 6 }px`
appDiv.append(balloonTipSpan) ; appDiv.append(answerPre)
}
}
Expand Down

0 comments on commit 1f0ff02

Please sign in to comment.