@kudoai/chatgpt.js 3.8.1 → 3.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +26 -0
- package/README.md +16 -12
- package/chatgpt.js +70 -46
- package/dist/chatgpt.min.js +25 -19
- package/docs/README.md +17 -12
- package/docs/USERGUIDE.md +14 -12
- package/package.json +11 -11
- package/starters/chrome/extension/components/icons.js +28 -21
- package/starters/chrome/extension/components/modals.js +5 -2
- package/starters/chrome/extension/content.js +3 -3
- package/starters/chrome/extension/icons/faded/icon128.png +0 -0
- package/starters/chrome/extension/icons/faded/icon16.png +0 -0
- package/starters/chrome/extension/icons/faded/icon32.png +0 -0
- package/starters/chrome/extension/icons/faded/icon64.png +0 -0
- package/starters/chrome/extension/icons/icon128.png +0 -0
- package/starters/chrome/extension/icons/icon16.png +0 -0
- package/starters/chrome/extension/icons/icon32.png +0 -0
- package/starters/chrome/extension/icons/icon64.png +0 -0
- package/starters/chrome/extension/lib/chatgpt.js +70 -46
- package/starters/chrome/extension/lib/settings.js +11 -4
- package/starters/chrome/extension/manifest.json +1 -1
- package/starters/chrome/extension/popup/controller.js +196 -65
- package/starters/chrome/extension/popup/index.html +3 -3
- package/starters/chrome/extension/popup/style.css +88 -25
- package/starters/chrome/extension/service-worker.js +1 -2
- package/starters/greasemonkey/chatgpt.js-greasemonkey-starter.user.js +4 -4
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
(async () => {
|
|
2
2
|
|
|
3
|
+
// Init SCHEME
|
|
4
|
+
if (window.matchMedia?.('(prefers-color-scheme: dark)').matches)
|
|
5
|
+
document.documentElement.classList.add('dark')
|
|
6
|
+
|
|
3
7
|
// Import JS resources
|
|
4
8
|
for (const resource of ['components/icons.js', 'lib/dom.js', 'lib/settings.js'])
|
|
5
9
|
await import(chrome.runtime.getURL(resource))
|
|
@@ -7,7 +11,8 @@
|
|
|
7
11
|
// Init ENV context
|
|
8
12
|
window.env = {
|
|
9
13
|
site: new URL((await chrome.tabs.query({ active: true, currentWindow: true }))[0].url)
|
|
10
|
-
.hostname.split('.').slice(-2, -1)[0] // extract 2nd-level domain
|
|
14
|
+
.hostname.split('.').slice(-2, -1)[0], // extract 2nd-level domain
|
|
15
|
+
menu: { isDark: document.documentElement.classList.contains('dark') }
|
|
11
16
|
}
|
|
12
17
|
|
|
13
18
|
// Import DATA
|
|
@@ -16,39 +21,112 @@
|
|
|
16
21
|
// Define FUNCTIONS
|
|
17
22
|
|
|
18
23
|
function createMenuEntry(entryData) {
|
|
24
|
+
|
|
25
|
+
// Assemble elems
|
|
19
26
|
const entry = {
|
|
20
27
|
div: dom.create.elem('div', {
|
|
21
28
|
id: entryData.key, class: 'menu-entry highlight-on-hover', title: entryData.helptip || '' }),
|
|
22
|
-
leftElem: dom.create.elem('div', { class: `menu-icon ${ entryData.type || '' }`
|
|
29
|
+
leftElem: dom.create.elem('div', { class: `menu-icon ${ entryData.type || '' }`}),
|
|
23
30
|
label: dom.create.elem('span')
|
|
24
31
|
}
|
|
25
32
|
entry.label.textContent = entryData.label
|
|
33
|
+
entry.div.append(entry.leftElem, entry.label)
|
|
26
34
|
if (entryData.type == 'toggle') { // add track to left, init knob pos
|
|
27
35
|
entry.leftElem.append(dom.create.elem('span', { class: 'track' }))
|
|
28
36
|
entry.leftElem.classList.toggle('on', settings.typeIsEnabled(entryData.key))
|
|
29
37
|
} else { // add symbol to left, append status to right
|
|
30
|
-
entry.leftElem.textContent = entryData.symbol || '⚙️'
|
|
38
|
+
entry.leftElem.textContent = entryData.symbol || '⚙️' ; entry.label.style.flexGrow = 1
|
|
31
39
|
if (entryData.status) entry.label.textContent += ` — ${entryData.status}`
|
|
40
|
+
if (entryData.type == 'link') {
|
|
41
|
+
entry.label.after(entry.rightElem = dom.create.elem('div', { class: 'menu-right-elem' }))
|
|
42
|
+
entry.rightElem.append(icons.create({ key: 'open', size: 17, fill: 'black' }))
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (entryData.type == 'category')
|
|
46
|
+
entry.div.append(icons.create({ key: 'caretDown', size: 11, class: 'menu-caret menu-right-elem' }))
|
|
47
|
+
else if (entryData.type == 'slider') { // append slider, add listeners, remove .highlight-on-hover
|
|
48
|
+
entry.slider = dom.create.elem('input', { class: 'slider', type: 'range',
|
|
49
|
+
min: entryData.min || 0, max: entryData.max || 100, value: config[entryData.key] })
|
|
50
|
+
if (entryData.step || env.browser.isFF) // use val from entryData or default to 2% in FF for being laggy
|
|
51
|
+
entry.slider.step = entryData.step || ( 0.02 * entry.slider.max - entry.slider.min )
|
|
52
|
+
entry.label.textContent += `: ${entry.slider.value}${ entryData.labelSuffix || '' }`
|
|
53
|
+
entry.slider.style.setProperty('--track-fill-percent', `${ entry.slider.value / entry.slider.max *100 }%`)
|
|
54
|
+
entry.slider.oninput = ({ target: { value }}) => { // update label/color
|
|
55
|
+
settings.save(entryData.key, parseInt(value)) ; sync.configToUI({ updatedKey: entryData.key })
|
|
56
|
+
entry.label.textContent = `${entryData.label}: ${value}${ entryData.labelSuffix || '' }`
|
|
57
|
+
entry.slider.style.setProperty('--track-fill-percent', `${ value / entry.slider.max *100 }%`)
|
|
58
|
+
}
|
|
59
|
+
entry.div.onwheel = event => { // move slider by 2 steps
|
|
60
|
+
entry.slider.value = parseInt(entry.slider.value) -Math.sign(event.deltaY) *2
|
|
61
|
+
entry.slider.dispatchEvent(new Event('input'))
|
|
62
|
+
}
|
|
63
|
+
entry.div.append(entry.slider) ; entry.div.classList.remove('highlight-on-hover')
|
|
64
|
+
}
|
|
65
|
+
if (entryData.dependencies) {
|
|
66
|
+
const toDisable = Object.values(entryData.dependencies).flat().some(dep => !settings.typeIsEnabled(dep))
|
|
67
|
+
Object.assign(entry.div.style, {
|
|
68
|
+
transition: '', minHeight: 'auto', opacity: +!toDisable,
|
|
69
|
+
height: toDisable ? 0 : 'auto', visibility: toDisable ? 'hidden' : 'visible'
|
|
70
|
+
})
|
|
32
71
|
}
|
|
33
|
-
|
|
72
|
+
|
|
73
|
+
// Add click listener
|
|
34
74
|
entry.div.onclick = () => {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
75
|
+
const now = Date.now()
|
|
76
|
+
const throttleMs = typeof entryData.throttle == 'number' ? entryData.throttle
|
|
77
|
+
: entryData.throttle ? 1500 : 0
|
|
78
|
+
if (throttleMs && now -( entry.div.lastClickTime || 0 ) < throttleMs) return
|
|
79
|
+
entry.div.classList.remove('disabled') ; entry.div.lastClickTime = now
|
|
80
|
+
;({
|
|
81
|
+
category: () => toggleCategorySettingsVisiblity({ key: entryData.key }),
|
|
82
|
+
toggle: () => {
|
|
83
|
+
entry.leftElem.classList.toggle('on')
|
|
84
|
+
settings.save(entryData.key, !config[entryData.key])
|
|
85
|
+
sync.configToUI({ updatedKey: entryData.key })
|
|
86
|
+
requestAnimationFrame(() => notify(`${entryData.label} ${chrome.i18n.getMessage(`state_${
|
|
87
|
+
settings.typeIsEnabled(entryData.key) ? 'on' : 'off' }`).toUpperCase()}`))
|
|
88
|
+
},
|
|
89
|
+
link: () => { open(entryData.url) ; close() }
|
|
90
|
+
})[entryData.type]()
|
|
91
|
+
|
|
92
|
+
// Throttle re-click
|
|
93
|
+
if (entryData.throttle) {
|
|
94
|
+
entry.div.classList.add('disabled')
|
|
95
|
+
setTimeout(() => entry.div.classList.remove('disabled'), throttleMs)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Enable/disable dependent entries
|
|
99
|
+
for (const [ctrlKey, ctrlData] of Object.entries({ ...settings.categories, ...settings.controls }))
|
|
100
|
+
if (Object.values(ctrlData.dependencies || {}).flat().includes(entryData.key)) {
|
|
101
|
+
const depDiv = document.querySelector(`div#${ctrlKey}`) ; if (!depDiv) continue
|
|
102
|
+
const ctgChildrenDiv = depDiv.closest('.categorized-entries'),
|
|
103
|
+
ctgChildren = ctgChildrenDiv.querySelectorAll('.menu-entry'),
|
|
104
|
+
toDisable = !settings.typeIsEnabled(entryData.key)
|
|
105
|
+
requestAnimationFrame(() => Object.assign(depDiv.closest('.categorized-entries').style, {
|
|
106
|
+
height: `${dom.get.computedHeight(ctgChildren)}px`,
|
|
107
|
+
transition: env.browser.isFF || toDisable ? '' : 'height 0.25s'
|
|
108
|
+
}))
|
|
109
|
+
Object.assign(depDiv.style, {
|
|
110
|
+
transition: toDisable ? '' : 'opacity 0.15s ease-in', height: toDisable ? 0 : 'auto',
|
|
111
|
+
visibility: toDisable ? 'hidden' : 'visible', opacity: +!toDisable
|
|
112
|
+
})
|
|
113
|
+
depDiv.classList.toggle('disabled', toDisable)
|
|
114
|
+
}
|
|
42
115
|
}
|
|
43
|
-
|
|
116
|
+
|
|
44
117
|
return entry.div
|
|
45
118
|
}
|
|
46
119
|
|
|
120
|
+
function depIsEnabled(ctrlKey) {
|
|
121
|
+
const deps = settings.controls[ctrlKey]?.dependencies
|
|
122
|
+
return !deps || Object.values(deps).flat(Infinity).some(depKey => settings.typeIsEnabled(depKey))
|
|
123
|
+
}
|
|
124
|
+
|
|
47
125
|
function notify(msg, pos = 'bottom-right') { sendMsgToActiveTab('notify', { msg, pos }) }
|
|
48
126
|
|
|
49
127
|
async function sendMsgToActiveTab(action, options) {
|
|
50
|
-
const
|
|
51
|
-
return await chrome.tabs.sendMessage(
|
|
128
|
+
const activeTabID = (await chrome.tabs.query({ active: true, currentWindow: true }))[0].id
|
|
129
|
+
return await chrome.tabs.sendMessage(activeTabID, { action, options })
|
|
52
130
|
}
|
|
53
131
|
|
|
54
132
|
const sync = {
|
|
@@ -61,51 +139,70 @@
|
|
|
61
139
|
))})
|
|
62
140
|
|
|
63
141
|
// Menu elems
|
|
64
|
-
document.querySelectorAll('.logo, .menu-title, .menu-entry
|
|
65
|
-
elem
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
142
|
+
document.querySelectorAll('.logo, .menu-title, .menu-entry, .slider, .categorized-entries')
|
|
143
|
+
.forEach((elem, idx) => {
|
|
144
|
+
if (elem.id && (elem.matches(`#${elem.id}:has(> div.link)`) || elem.id == 'aboutEntry'))
|
|
145
|
+
return // never disable link/About entries
|
|
146
|
+
elem.style.transition = config.extensionDisabled ? '' : 'opacity 0.15s ease-in'
|
|
147
|
+
const toDisable = config.extensionIsDisabled || !depIsEnabled(elem.id)
|
|
148
|
+
if (elem.classList.contains('categorized-entries')) { // fade category strip
|
|
149
|
+
elem.style.transition = toDisable ? 'none' : 'var(--border-transition)'
|
|
150
|
+
elem.style.borderImage = elem.style.borderImage.replace(
|
|
151
|
+
/rgba?\(([\d,\s]+)(?:,\s*[\d.]+)?\)/,
|
|
152
|
+
`rgba($1,${ toDisable ? 0.3 : env.menu.isDark ? 0.5 : 1 })`
|
|
153
|
+
)
|
|
154
|
+
} else // fade entry
|
|
155
|
+
setTimeout(() => elem.classList.toggle('disabled', toDisable),
|
|
156
|
+
toDisable ? 0 : idx *10) // fade-out abruptly, fade-in staggered
|
|
157
|
+
})
|
|
69
158
|
},
|
|
70
159
|
|
|
71
160
|
configToUI(options) { return sendMsgToActiveTab('syncConfigToUI', options) }
|
|
72
161
|
}
|
|
73
162
|
|
|
74
|
-
function toggleCategorySettingsVisiblity(
|
|
163
|
+
function toggleCategorySettingsVisiblity({ key, transitions = true, action }) {
|
|
75
164
|
const transitionDuration = 350, // ms
|
|
76
|
-
|
|
77
|
-
caret =
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
if (action != 'hide' && dom.get.computedHeight(
|
|
81
|
-
|
|
82
|
-
Object.assign(
|
|
165
|
+
ctgDiv = document.getElementById(key),
|
|
166
|
+
caret = ctgDiv.querySelector('.menu-caret'),
|
|
167
|
+
ctgChildrenDiv = ctgDiv.nextSibling,
|
|
168
|
+
ctgChild = ctgChildrenDiv.querySelectorAll('.menu-entry')
|
|
169
|
+
if (action != 'hide' && dom.get.computedHeight(ctgChildrenDiv) == 0) { // show category settings
|
|
170
|
+
ctgDiv.classList.toggle('expanded', true)
|
|
171
|
+
Object.assign(ctgChildrenDiv.style, { height: `${dom.get.computedHeight(ctgChild)}px`,
|
|
83
172
|
transition: transitions ? 'height 0.25s' : '' })
|
|
84
173
|
Object.assign(caret.style, { // point it down
|
|
85
174
|
transform: 'rotate(0deg)', transition: transitions ? 'transform 0.15s ease-out' : '' })
|
|
86
|
-
|
|
175
|
+
ctgChild.forEach(row => { // reset styles to support continuous transition on rapid show/hide
|
|
87
176
|
row.style.transition = 'none' ; row.style.opacity = 0 })
|
|
88
|
-
|
|
89
|
-
|
|
177
|
+
ctgChildrenDiv.offsetHeight // force reflow to insta-apply reset
|
|
178
|
+
ctgChild.forEach((row, idx) => { // fade-in staggered
|
|
90
179
|
if (transitions) row.style.transition = `opacity ${ transitionDuration /1000 }s ease-in-out`
|
|
91
180
|
setTimeout(() => row.style.opacity = 1, transitions ? idx * transitionDuration /10 : 0)
|
|
92
181
|
})
|
|
93
|
-
document.querySelectorAll(`.menu-entry:has(.menu-caret):not(#${
|
|
94
|
-
toggleCategorySettingsVisiblity(
|
|
182
|
+
document.querySelectorAll(`.menu-entry:has(.menu-caret):not(#${key})`).forEach(otherCtgDiv =>
|
|
183
|
+
toggleCategorySettingsVisiblity({ key: otherCtgDiv.id, action: 'hide' }))
|
|
95
184
|
} else { // hide category settings
|
|
96
|
-
|
|
97
|
-
Object.assign(
|
|
185
|
+
ctgDiv.classList.toggle('expanded', false)
|
|
186
|
+
Object.assign(ctgChildrenDiv.style, { height: 0, transition: '' })
|
|
98
187
|
Object.assign(caret.style, { transform: 'rotate(-90deg)', transition: '' }) // point it right
|
|
99
188
|
}
|
|
100
189
|
}
|
|
101
190
|
|
|
102
191
|
// Run MAIN routine
|
|
103
192
|
|
|
193
|
+
// Append RISING PARTICLES styles
|
|
194
|
+
['gray', 'white'].forEach(color => document.head.append(
|
|
195
|
+
dom.create.elem('link', { rel: 'stylesheet',
|
|
196
|
+
href: `https://cdn.jsdelivr.net/gh/adamlui/ai-web-extensions@71695ca/assets/styles/rising-particles/dist/${
|
|
197
|
+
color}.min.css`
|
|
198
|
+
})))
|
|
199
|
+
dom.addRisingParticles(document.body, { lightScheme: env.menu.isDark ? 'white' : 'gray' })
|
|
200
|
+
|
|
104
201
|
// Init MASTER TOGGLE
|
|
105
202
|
const masterToggle = {
|
|
106
203
|
div: document.querySelector('.master-toggle'),
|
|
107
|
-
switch: dom.create.elem('div', { class: 'toggle menu-icon highlight-on-hover' }),
|
|
108
|
-
track: dom.create.elem('span', { class: 'track' })
|
|
204
|
+
switch: dom.create.elem('div', { class: 'toggle menu-icon highlight-on-hover', style: 'height: 26px' }),
|
|
205
|
+
track: dom.create.elem('span', { class: 'track', style: 'position: relative ; top: 7.5px' })
|
|
109
206
|
}
|
|
110
207
|
masterToggle.div.append(masterToggle.switch) ; masterToggle.switch.append(masterToggle.track)
|
|
111
208
|
await settings.load('extensionDisabled') ; masterToggle.switch.classList.toggle('on', !config.extensionDisabled)
|
|
@@ -125,7 +222,7 @@
|
|
|
125
222
|
// Group controls by category
|
|
126
223
|
const categorizedCtrls = {}
|
|
127
224
|
Object.entries(settings.controls).forEach(([key, ctrl]) =>
|
|
128
|
-
( categorizedCtrls[ctrl.category || 'general'] ??= {} )[key] = { ...ctrl, key
|
|
225
|
+
( categorizedCtrls[ctrl.category || 'general'] ??= {} )[key] = { ...ctrl, key })
|
|
129
226
|
|
|
130
227
|
// Create/append general controls
|
|
131
228
|
Object.values(categorizedCtrls.general || {}).forEach(ctrl => menuEntriesDiv.append(createMenuEntry(ctrl)))
|
|
@@ -133,43 +230,77 @@
|
|
|
133
230
|
// Create/append categorized controls
|
|
134
231
|
Object.entries(categorizedCtrls).forEach(([category, ctrls]) => {
|
|
135
232
|
if (category == 'general') return
|
|
136
|
-
const
|
|
137
|
-
|
|
138
|
-
if (
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
233
|
+
const ctgData = { ...settings.categories[category], key: category, type: 'category' },
|
|
234
|
+
ctgChildrenDiv = dom.create.elem('div', { class: 'categorized-entries' })
|
|
235
|
+
if (ctgData.color) { // color the stripe
|
|
236
|
+
const [r, g, b] = ctgData.color.match(/\w\w/g).map(v => parseInt(v, 16))
|
|
237
|
+
ctgChildrenDiv.style.borderImage = `linear-gradient(transparent, rgba(${r},${g},${b},${
|
|
238
|
+
env.menu.isDark ? 0.5 : 1 })) 30 100% ${ env.menu.isDark ? '/ 100' : '' }`
|
|
239
|
+
}
|
|
240
|
+
menuEntriesDiv.append(createMenuEntry(ctgData), ctgChildrenDiv)
|
|
241
|
+
Object.values(ctrls).forEach(ctrl => ctgChildrenDiv.append(createMenuEntry(ctrl)))
|
|
142
242
|
})
|
|
143
243
|
}
|
|
144
244
|
|
|
145
|
-
//
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
245
|
+
// Create/append ABOUT entry
|
|
246
|
+
const aboutEntry = {
|
|
247
|
+
div: createMenuEntry({ key: 'aboutEntry', symbol: '💡', label: 'About...', helptip: `About ${app.name}` }),
|
|
248
|
+
ticker: {
|
|
249
|
+
xGap: '   ',
|
|
250
|
+
span: dom.create.elem('span', { class: 'ticker' }), innerDiv: dom.create.elem('div')
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
aboutEntry.div.querySelector('div.menu-icon').style.paddingLeft = '10px'
|
|
254
|
+
aboutEntry.div.querySelector('span').style.paddingLeft = '2.5px'
|
|
255
|
+
aboutEntry.ticker.content = `Version: <span class="ticker-em">v${ app.version + aboutEntry.ticker.xGap }</span>`
|
|
256
|
+
+ `Powered by <span class="ticker-em">chatgpt.js</span>${aboutEntry.ticker.xGap}`
|
|
257
|
+
for (let i = 0 ; i < 7 ; i++) aboutEntry.ticker.content += aboutEntry.ticker.content // make long af
|
|
258
|
+
aboutEntry.ticker.innerDiv.innerHTML = aboutEntry.ticker.content
|
|
259
|
+
aboutEntry.ticker.span.append(aboutEntry.ticker.innerDiv)
|
|
260
|
+
aboutEntry.div.append(aboutEntry.ticker.span) ; footer.before(aboutEntry.div)
|
|
261
|
+
aboutEntry.div.onclick = () => { chrome.runtime.sendMessage({ action: 'showAbout' }) ; close() }
|
|
150
262
|
|
|
151
|
-
|
|
263
|
+
// Create/append CHATGPT entry
|
|
264
|
+
const activeTabURL = (await chrome.tabs.query({ active: true, currentWindow: true }))[0].url,
|
|
265
|
+
chatgptURL = chrome.runtime.getManifest().content_scripts[0].matches.map(url => url.replace(/\/\*$/, ''))
|
|
266
|
+
if (!activeTabURL.includes(chatgptURL)) footer.before(createMenuEntry({
|
|
267
|
+
key: 'chatgptEntry', type: 'link', symbol: '🤖', label: 'Open ChatGPT', url: chatgptURL, helptip: chatgptURL }))
|
|
152
268
|
|
|
153
|
-
//
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
|
|
269
|
+
// Create/append LATEST CHANGES entry
|
|
270
|
+
const latestChangesURL = `${app.urls.github}/commits`
|
|
271
|
+
footer.before(createMenuEntry({
|
|
272
|
+
key: 'latestChangesEntry', type: 'link', symbol: '🚀',
|
|
273
|
+
label: 'Latest Changes...', url: latestChangesURL, helptip: latestChangesURL
|
|
274
|
+
}))
|
|
157
275
|
|
|
158
|
-
// Init
|
|
159
|
-
const
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
276
|
+
// Init FOOTER
|
|
277
|
+
const footerElems = { // left-to-right
|
|
278
|
+
chatgptjs: { logo: footer.querySelector('.chatgptjs-logo') },
|
|
279
|
+
about: { span: footer.querySelector('.about-span') },
|
|
280
|
+
moreExt: { span: footer.querySelector('.more-ext-span') }
|
|
281
|
+
}
|
|
282
|
+
footerElems.chatgptjs.logo.src = 'https://cdn.jsdelivr.net/gh/KudoAI/chatgpt.js@858b952'
|
|
283
|
+
+ `/assets/images/badges/powered-by-chatgpt.js/${ env.menu.isDark ? 'white' : 'black' }/with-robot/95x19.png`
|
|
284
|
+
footerElems.chatgptjs.logo.onclick = () => { open(app.urls.chatgptjs) ; close() }
|
|
285
|
+
footerElems.about.span.title = `About ${app.name}`
|
|
286
|
+
footerElems.about.span.append(icons.create({ key: 'questionMark', width: 15, height: 13 }))
|
|
287
|
+
footerElems.about.span.onclick = () => { chrome.runtime.sendMessage({ action: 'showAbout' }) ; close() }
|
|
288
|
+
footerElems.moreExt.span.title = 'More AI Extensions'
|
|
289
|
+
footerElems.moreExt.span.append(icons.create({ key: 'plus' }))
|
|
290
|
+
footerElems.moreExt.span.onclick = () => { open(app.urls.relatedExtensions) ; close() }
|
|
163
291
|
|
|
164
|
-
//
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
292
|
+
// AUTO-EXPAND categories
|
|
293
|
+
document.querySelectorAll('.menu-entry:has(.menu-caret)').forEach(ctgDiv => {
|
|
294
|
+
if (settings.categories[ctgDiv.id]?.autoExpand)
|
|
295
|
+
toggleCategorySettingsVisiblity({ key: ctgDiv.id, transitions: false })
|
|
296
|
+
})
|
|
169
297
|
|
|
170
|
-
//
|
|
298
|
+
// REMOVE LOADING spinner after imgs load
|
|
171
299
|
Promise.all([...document.querySelectorAll('img')].map(img =>
|
|
172
300
|
img.complete ? Promise.resolve() : new Promise(resolve => img.onload = resolve)
|
|
173
|
-
)).then(() =>
|
|
301
|
+
)).then(() => {
|
|
302
|
+
document.querySelectorAll('[class^=loading]').forEach(elem => elem.remove())
|
|
303
|
+
sync.fade() // based on master toggle state
|
|
304
|
+
})
|
|
174
305
|
|
|
175
306
|
})()
|
|
@@ -10,16 +10,16 @@
|
|
|
10
10
|
</div>
|
|
11
11
|
<header>
|
|
12
12
|
<div class="logo">
|
|
13
|
-
<img src="
|
|
13
|
+
<img src="data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20width='180'%20height='180'%20fill='none'%3e%3cstyle%3e%20:root%20{%20--primary-fill:%20%23000;%20--secondary-fill:%20%23fff;%20}%20@media%20(prefers-color-scheme:%20dark)%20{%20:root%20{%20--primary-fill:%20%23fff;%20--secondary-fill:%20%23000;%20}%20}%20%3c/style%3e%3cg%20clip-path='url(%23a)'%3e%3crect%20width='180'%20height='180'%20fill='var(--primary-fill)'%20rx='90'%20/%3e%3cg%20clip-path='url(%23b)'%3e%3cpath%20fill='var(--secondary-fill)'%20d='M75.91%2073.628V62.232c0-.96.36-1.68%201.199-2.16l22.912-13.194c3.119-1.8%206.838-2.639%2010.676-2.639%2014.394%200%2023.511%2011.157%2023.511%2023.032%200%20.839%200%201.799-.12%202.758l-23.752-13.914c-1.439-.84-2.879-.84-4.318%200L75.91%2073.627Zm53.499%2044.383v-27.23c0-1.68-.72-2.88-2.159-3.719L97.142%2069.55l9.836-5.638c.839-.48%201.559-.48%202.399%200l22.912%2013.195c6.598%203.839%2011.035%2011.995%2011.035%2019.912%200%209.116-5.397%2017.513-13.915%2020.992v.001Zm-60.577-23.99-9.836-5.758c-.84-.48-1.2-1.2-1.2-2.16v-26.39c0-12.834%209.837-22.55%2023.152-22.55%205.039%200%209.716%201.679%2013.676%204.678L70.993%2055.516c-1.44.84-2.16%202.039-2.16%203.719v34.787-.002Zm21.173%2012.234L75.91%2098.339V81.546l14.095-7.917%2014.094%207.917v16.793l-14.094%207.916Zm9.056%2036.467c-5.038%200-9.716-1.68-13.675-4.678l23.631-13.676c1.439-.839%202.159-2.038%202.159-3.718V85.863l9.956%205.757c.84.48%201.2%201.2%201.2%202.16v26.389c0%2012.835-9.957%2022.552-23.27%2022.552v.001Zm-28.43-26.75L47.72%20102.778c-6.599-3.84-11.036-11.996-11.036-19.913%200-9.236%205.518-17.513%2014.034-20.992v27.35c0%201.68.72%202.879%202.16%203.718l29.989%2017.393-9.837%205.638c-.84.48-1.56.48-2.399%200Zm-1.318%2019.673c-13.555%200-23.512-10.196-23.512-22.792%200-.959.12-1.919.24-2.879l23.63%2013.675c1.44.84%202.88.84%204.32%200l30.108-17.392v11.395c0%20.96-.361%201.68-1.2%202.16l-22.912%2013.194c-3.119%201.8-6.837%202.639-10.675%202.639Zm29.748%2014.274c14.515%200%2026.63-10.316%2029.39-23.991%2013.434-3.479%2022.071-16.074%2022.071-28.91%200-8.396-3.598-16.553-10.076-22.43.6-2.52.96-5.039.96-7.557%200-17.153-13.915-29.99-29.989-29.99-3.239%200-6.358.48-9.477%201.56-5.398-5.278-12.835-8.637-20.992-8.637-14.515%200-26.63%2010.316-29.39%2023.991-13.434%203.48-22.07%2016.074-22.07%2028.91%200%208.396%203.598%2016.553%2010.075%2022.431-.6%202.519-.96%205.038-.96%207.556%200%2017.154%2013.915%2029.989%2029.99%2029.989%203.238%200%206.357-.479%209.476-1.559%205.397%205.278%2012.835%208.637%2020.992%208.637Z'%20/%3e%3c/g%3e%3c/g%3e%3cdefs%3e%3cclipPath%20id='a'%3e%3cpath%20d='M0%200h180v180H0z'%20/%3e%3c/clipPath%3e%3cclipPath%20id='b'%3e%3cpath%20d='M29.487%2029.964h121.035v119.954H29.487z'%20/%3e%3c/clipPath%3e%3c/defs%3e%3c/svg%3e"
|
|
14
14
|
width=26 alt="">
|
|
15
15
|
</div>
|
|
16
16
|
<div class="menu-title">ChatGPT Extension</div>
|
|
17
17
|
<div class="master-toggle"></div>
|
|
18
18
|
</header>
|
|
19
19
|
<footer>
|
|
20
|
-
<span><img class="
|
|
20
|
+
<span><img class="chatgptjs-logo"></span>
|
|
21
21
|
<span class="about-span menu-icon highlight-on-hover"></span>
|
|
22
|
-
<span class="more-
|
|
22
|
+
<span class="more-ext-span menu-icon highlight-on-hover"></span>
|
|
23
23
|
</footer>
|
|
24
24
|
<script src="controller.js"></script>
|
|
25
25
|
</body>
|
|
@@ -1,20 +1,25 @@
|
|
|
1
1
|
/* General */
|
|
2
|
+
:root {
|
|
3
|
+
--entry-highlighted-bg: rgb(100,149,237) ;
|
|
4
|
+
--track-filled-color: #000 ; --track-empty-color: #e0e0e0 ; --thumb-color: #000 ; --thumb-border: #fff
|
|
5
|
+
}
|
|
2
6
|
html { height: fit-content ; min-height: 89px }
|
|
3
7
|
body {
|
|
4
|
-
width:
|
|
8
|
+
width: 268px ; margin: 0 ; font-size: .905rem ;
|
|
5
9
|
font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", Roboto,
|
|
6
|
-
"PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", sans-serif
|
|
10
|
+
"PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Helvetica Neue", sans-serif ;
|
|
11
|
+
background-image: linear-gradient(180deg, #b6ebff -163px, white 65px)
|
|
7
12
|
}
|
|
8
13
|
|
|
9
14
|
/* Color/fade mods */
|
|
10
|
-
.highlight-on-hover:hover { background:
|
|
11
|
-
.highlight-on-hover:hover span:not(.track), .highlight-on-hover:hover .menu-
|
|
12
|
-
filter: invert(1) }
|
|
13
|
-
.disabled { opacity: 0.3 ; pointer-events: none }
|
|
15
|
+
.highlight-on-hover:hover { background: var(--entry-highlighted-bg) }
|
|
16
|
+
.highlight-on-hover:hover span:not(.track), .highlight-on-hover:hover svg, span.menu-icon.highlight-on-hover:hover img {
|
|
17
|
+
filter: invert(1) } /* invert setting labels on hover */
|
|
18
|
+
.disabled { opacity: 0.3 !important ; pointer-events: none }
|
|
14
19
|
|
|
15
20
|
/* Loader */
|
|
16
21
|
.loading-bg {
|
|
17
|
-
background
|
|
22
|
+
background: white ; width: 100% ; height: 100% ; position: absolute ; z-index: 1111 ;
|
|
18
23
|
display: inline-grid ; align-content: center ; justify-content: center /* center spinner */
|
|
19
24
|
}
|
|
20
25
|
.loading-spinner {
|
|
@@ -22,13 +27,13 @@ body {
|
|
|
22
27
|
animation: loader-move-head-tail 0.8s infinite linear alternate, loader-rotate 1.6s infinite linear
|
|
23
28
|
}
|
|
24
29
|
@keyframes loader-move-head-tail {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
0% { clip-path: polygon(50% 50%, 0 0, 50% 0, 50% 0, 50% 0, 50% 0, 50% 0) }
|
|
31
|
+
12.5% { clip-path: polygon(50% 50%, 0 0, 50% 0, 100% 0, 100% 0, 100% 0, 100% 0) }
|
|
32
|
+
25% { clip-path: polygon(50% 50%, 0 0, 50% 0, 100% 0, 100% 100%, 100% 100%, 100% 100%) }
|
|
33
|
+
50% { clip-path: polygon(50% 50%, 0 0, 50% 0, 100% 0, 100% 100%, 50% 100%, 0 100%) }
|
|
34
|
+
62.5% { clip-path: polygon(50% 50%, 100% 0, 100% 0%, 100% 0, 100% 100%, 50% 100%, 0 100%) }
|
|
35
|
+
75% { clip-path: polygon(50% 50%, 100% 100%, 100% 100%, 100% 100%, 100% 100%, 50% 100%, 0 100%) }
|
|
36
|
+
100% { clip-path: polygon(50% 50%, 50% 100%, 50% 100%, 50% 100%, 50% 100%, 50% 100%, 0 100%) }
|
|
32
37
|
}
|
|
33
38
|
@keyframes loader-rotate {
|
|
34
39
|
0% { transform: scaleY(1) rotate(0deg) } 49.99% { transform: scaleY(1) rotate(135deg) }
|
|
@@ -38,8 +43,8 @@ body {
|
|
|
38
43
|
/* Header */
|
|
39
44
|
header {
|
|
40
45
|
border-bottom: solid 1px lightgrey ; padding: 5px 5px 5px 0 ; margin: 0 ;
|
|
41
|
-
|
|
42
|
-
.logo { margin:
|
|
46
|
+
height: 38px ; display: flex ; align-items: center }
|
|
47
|
+
.logo { margin: 0 8px 0 12px ; position: relative ; top: 3px }
|
|
43
48
|
.menu-title { font-size: 0.85rem ; font-weight: 600 ; padding-right: 3px }
|
|
44
49
|
.master-toggle { margin-left: auto ; display: flex }
|
|
45
50
|
|
|
@@ -48,14 +53,37 @@ header {
|
|
|
48
53
|
position: relative ; align-items: center ; border-bottom: 1px solid lightgrey ;
|
|
49
54
|
display: flex ; min-height: 2rem ; padding: 0 14px 0 2px ; white-space: nowrap ; font-size: 91%
|
|
50
55
|
}
|
|
51
|
-
.menu-icon { padding: 8px }
|
|
56
|
+
.menu-icon { padding: 8px ; justify-content: center }
|
|
52
57
|
.menu-entry > label > .track { transform: scale(0.95) ; top: 1px } /* make child toggles smaller */
|
|
58
|
+
.menu-right-elem { display: flex ; height: 33px ; align-items: center ; padding: 0 11.5px ; margin-right: -14px }
|
|
53
59
|
.menu-caret { position: absolute ; right: 14px ; transform: rotate(-90deg) }
|
|
54
|
-
.
|
|
55
|
-
|
|
56
|
-
border-
|
|
60
|
+
.menu-right-elem, .menu-caret { filter: drop-shadow(5px 5px 5px rgba(0, 0, 0, 0.1)) }
|
|
61
|
+
.categorized-entries { /* add left-stripe + bg */
|
|
62
|
+
border-left: 5px solid transparent ; height: 0 ;
|
|
63
|
+
overflow: hidden ; /* for y-pos calc */
|
|
64
|
+
border-image: linear-gradient(transparent, rgb(161,161,161)) 30 100% ;
|
|
65
|
+
--border-transition: border-image 0.35s ease-in
|
|
66
|
+
}
|
|
67
|
+
.anchored { pointer-events: none } /* disable collapse */
|
|
68
|
+
.expanded > span { font-weight: 600 ; transform: scale(1.05) ; margin-left: 5px }
|
|
69
|
+
|
|
70
|
+
/* Slider */
|
|
71
|
+
div.menu-entry > input.slider {
|
|
72
|
+
--track-fill-percent: 100% ; width: 100% ; margin: -2px -5px 7px 8px ; padding: 8.5px 3px ; cursor: pointer ;
|
|
73
|
+
-webkit-appearance: none ; appearance: none ; background: none
|
|
74
|
+
}
|
|
75
|
+
.slider::-webkit-slider-runnable-track {
|
|
76
|
+
height: 5px ; border-radius: 10px ;
|
|
77
|
+
background: linear-gradient(to right,
|
|
78
|
+
var(--track-filled-color) 0%, var(--track-filled-color) var(--track-fill-percent),
|
|
79
|
+
var(--track-empty-color) var(--track-fill-percent), var(--track-empty-color) 100%
|
|
80
|
+
)
|
|
81
|
+
}
|
|
82
|
+
.slider::-webkit-slider-thumb {
|
|
83
|
+
-webkit-appearance: none ; width: 12px ; height: 26.5px ; background: var(--thumb-color) ; margin-top: -10.5px ;
|
|
84
|
+
border: 4px solid var(--thumb-border) ; border-radius: 16px ; cursor: ew-resize ; transition: transform 0.05s ease
|
|
57
85
|
}
|
|
58
|
-
.
|
|
86
|
+
.slider::-webkit-slider-thumb:hover { transform: scaleX(1.325) }
|
|
59
87
|
|
|
60
88
|
/* Toggle elements */
|
|
61
89
|
.toggle .track {
|
|
@@ -68,19 +96,54 @@ header {
|
|
|
68
96
|
border: 1px solid black ; border-radius: 50% ; background: white ; transition: transform 0.08s ease-in-out
|
|
69
97
|
}
|
|
70
98
|
.toggle.on .track::before { transform: translateX(9px) ; transition: transform 0.15s ease-in-out }
|
|
99
|
+
|
|
100
|
+
/* About entry */
|
|
101
|
+
div#about > div.menu-icon { padding: 8px 10px 8px 11px }
|
|
102
|
+
.ticker {
|
|
103
|
+
align-content: center ; overflow: hidden ; font-size: 10px ; width: 105px ;
|
|
104
|
+
--mask: linear-gradient(to right, transparent, black 20%, black 89%, transparent) ;
|
|
105
|
+
mask-image: var(--mask) ; -webkit-mask-image: var(--mask) /* eslint-disable-line */
|
|
106
|
+
}
|
|
107
|
+
.ticker-em { color: green } .highlight-on-hover:hover .ticker-em { color: #28ee28 }
|
|
108
|
+
.ticker > div { animation: ticker linear 75s infinite }
|
|
109
|
+
@keyframes ticker { 0% { transform: translateX(100%) } 100% { transform: translateX(-2000%) }}
|
|
71
110
|
|
|
72
111
|
/* Footer */
|
|
73
112
|
footer { display: flex ; align-items: center ; background: #f5f5f5 ; height: 40px ; padding: 0 7px }
|
|
74
|
-
.
|
|
113
|
+
.chatgptjs-logo { opacity: 0.5 } .chatgptjs-logo:hover { opacity: 1 ; transition: 0.25s }
|
|
75
114
|
footer > .menu-icon {
|
|
76
115
|
display: flex ; opacity: 0.7 ; align-items: center ; padding: 8px 5px ;
|
|
77
116
|
box-sizing: border-box ; height: 96% ; width: 26px
|
|
78
117
|
}
|
|
79
118
|
footer img[src*=question-mark] { position: relative ; top: 1px }
|
|
80
119
|
|
|
120
|
+
/* Dark styles */
|
|
121
|
+
html.dark {
|
|
122
|
+
--entry-highlighted-bg: white ;
|
|
123
|
+
--track-filled-color: white ; --track-empty-color: #b2b2b2 ; --thumb-color: white ; --thumb-border: black
|
|
124
|
+
}
|
|
125
|
+
html.dark .loading-bg { background: black } html.dark .loading-spinner { border-color: white }
|
|
126
|
+
html.dark body { background-image: linear-gradient(180deg, #99a8a6 -245px, black 185px) }
|
|
127
|
+
html.dark, html.dark header, html.dark footer { color: white } html.dark footer { background: none }
|
|
128
|
+
html.dark div.categorized-entries { border-image: linear-gradient(transparent, rgba(161,161,161,0.5)) 30 100% / 100 }
|
|
129
|
+
html.dark .toggle .track {
|
|
130
|
+
background: var(--track-empty-color) ; border-color: black ; height: 8px ; width: 20px ; transition: none }
|
|
131
|
+
html.dark .toggle.on .track { background: var(--track-filled-color) }
|
|
132
|
+
html.dark .toggle .track::before { top: -3px ; left: -2px ; border: 2px solid black } /* toggle knob */
|
|
133
|
+
html.dark .master-toggle .toggle .track::before { border-color: #444343 } /* master toggle knob */
|
|
134
|
+
html.dark .master-toggle:hover .toggle .track { background: #444343 }
|
|
135
|
+
html.dark .toggle.on .track::before { transform: translateX(11px) }
|
|
136
|
+
html.dark .highlight-on-hover:hover .track { background: black }
|
|
137
|
+
html.dark .menu-icon, html.dark .chatgptjs-logo { opacity: 1 }
|
|
138
|
+
html.dark .menu-icon svg, html.dark .menu-right-elem, html.dark .menu-right-elem > svg { fill: white }
|
|
139
|
+
html.dark .menu-icon img { filter: brightness(0) invert(1) }
|
|
140
|
+
html.dark .menu-icon:hover img { filter: none }
|
|
141
|
+
html.dark .ticker-em { color: #28ee28 } html.dark .highlight-on-hover:hover .ticker-em { color: green }
|
|
142
|
+
|
|
81
143
|
/* Non-baseline features */
|
|
82
|
-
@supports (cursor: pointer) { .highlight-on-hover:hover, .toggle .track, .
|
|
144
|
+
@supports (cursor: pointer) { .highlight-on-hover:hover, .toggle .track, .chatgptjs-logo { cursor: pointer }}
|
|
83
145
|
@supports (overflow: clip) { body { overflow: clip }}
|
|
84
|
-
@supports selector(:has(> .
|
|
85
|
-
|
|
146
|
+
@supports selector(:has(> input.slider)) { div.menu-entry:has(> input.slider) { flex-wrap: wrap ; padding-top: 2px }}
|
|
147
|
+
@supports selector(:has(> .chatgptjs-logo)) {
|
|
148
|
+
footer > span:has(> .chatgptjs-logo) { display: flex ; align-items: center ; flex-grow: 1 ; padding-left: 2px }}
|
|
86
149
|
@supports (user-select: none) { body, button, input, select, textarea { user-select: none }}
|
|
@@ -6,8 +6,7 @@ chrome.storage.local.set({ app: {
|
|
|
6
6
|
version: chrome.runtime.getManifest().version, symbol: '🤖', cssPrefix: 'chatgpt-extension',
|
|
7
7
|
author: { name: 'KudoAI', url: 'https://kudoai.com' },
|
|
8
8
|
urls: {
|
|
9
|
-
|
|
10
|
-
chatgptJS: 'https://chatgptjs.org',
|
|
9
|
+
chatgptjs: 'https://chatgptjs.org',
|
|
11
10
|
contributors: 'https://docs.chatgptjs.org/#-contributors',
|
|
12
11
|
gitHub: 'https://github.com/KudoAI/chatgpt.js-chrome-starter',
|
|
13
12
|
relatedExtensions: 'https://aiwebextensions.com',
|
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
// @description A Greasemonkey template to start using chatgpt.js like a boss
|
|
4
4
|
// @author chatgpt.js
|
|
5
5
|
// @namespace https://chatgpt.js.org
|
|
6
|
-
// @version 2025.
|
|
6
|
+
// @version 2025.7.28
|
|
7
7
|
// @license MIT
|
|
8
|
-
// @icon
|
|
9
|
-
// @icon64
|
|
8
|
+
// @icon data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20width='180'%20height='180'%20fill='none'%3e%3cstyle%3e%20:root%20{%20--primary-fill:%20%23000;%20--secondary-fill:%20%23fff;%20}%20@media%20(prefers-color-scheme:%20dark)%20{%20:root%20{%20--primary-fill:%20%23fff;%20--secondary-fill:%20%23000;%20}%20}%20%3c/style%3e%3cg%20clip-path='url(%23a)'%3e%3crect%20width='180'%20height='180'%20fill='var(--primary-fill)'%20rx='90'%20/%3e%3cg%20clip-path='url(%23b)'%3e%3cpath%20fill='var(--secondary-fill)'%20d='M75.91%2073.628V62.232c0-.96.36-1.68%201.199-2.16l22.912-13.194c3.119-1.8%206.838-2.639%2010.676-2.639%2014.394%200%2023.511%2011.157%2023.511%2023.032%200%20.839%200%201.799-.12%202.758l-23.752-13.914c-1.439-.84-2.879-.84-4.318%200L75.91%2073.627Zm53.499%2044.383v-27.23c0-1.68-.72-2.88-2.159-3.719L97.142%2069.55l9.836-5.638c.839-.48%201.559-.48%202.399%200l22.912%2013.195c6.598%203.839%2011.035%2011.995%2011.035%2019.912%200%209.116-5.397%2017.513-13.915%2020.992v.001Zm-60.577-23.99-9.836-5.758c-.84-.48-1.2-1.2-1.2-2.16v-26.39c0-12.834%209.837-22.55%2023.152-22.55%205.039%200%209.716%201.679%2013.676%204.678L70.993%2055.516c-1.44.84-2.16%202.039-2.16%203.719v34.787-.002Zm21.173%2012.234L75.91%2098.339V81.546l14.095-7.917%2014.094%207.917v16.793l-14.094%207.916Zm9.056%2036.467c-5.038%200-9.716-1.68-13.675-4.678l23.631-13.676c1.439-.839%202.159-2.038%202.159-3.718V85.863l9.956%205.757c.84.48%201.2%201.2%201.2%202.16v26.389c0%2012.835-9.957%2022.552-23.27%2022.552v.001Zm-28.43-26.75L47.72%20102.778c-6.599-3.84-11.036-11.996-11.036-19.913%200-9.236%205.518-17.513%2014.034-20.992v27.35c0%201.68.72%202.879%202.16%203.718l29.989%2017.393-9.837%205.638c-.84.48-1.56.48-2.399%200Zm-1.318%2019.673c-13.555%200-23.512-10.196-23.512-22.792%200-.959.12-1.919.24-2.879l23.63%2013.675c1.44.84%202.88.84%204.32%200l30.108-17.392v11.395c0%20.96-.361%201.68-1.2%202.16l-22.912%2013.194c-3.119%201.8-6.837%202.639-10.675%202.639Zm29.748%2014.274c14.515%200%2026.63-10.316%2029.39-23.991%2013.434-3.479%2022.071-16.074%2022.071-28.91%200-8.396-3.598-16.553-10.076-22.43.6-2.52.96-5.039.96-7.557%200-17.153-13.915-29.99-29.989-29.99-3.239%200-6.358.48-9.477%201.56-5.398-5.278-12.835-8.637-20.992-8.637-14.515%200-26.63%2010.316-29.39%2023.991-13.434%203.48-22.07%2016.074-22.07%2028.91%200%208.396%203.598%2016.553%2010.075%2022.431-.6%202.519-.96%205.038-.96%207.556%200%2017.154%2013.915%2029.989%2029.99%2029.989%203.238%200%206.357-.479%209.476-1.559%205.397%205.278%2012.835%208.637%2020.992%208.637Z'%20/%3e%3c/g%3e%3c/g%3e%3cdefs%3e%3cclipPath%20id='a'%3e%3cpath%20d='M0%200h180v180H0z'%20/%3e%3c/clipPath%3e%3cclipPath%20id='b'%3e%3cpath%20d='M29.487%2029.964h121.035v119.954H29.487z'%20/%3e%3c/clipPath%3e%3c/defs%3e%3c/svg%3e
|
|
9
|
+
// @icon64 data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20width='180'%20height='180'%20fill='none'%3e%3cstyle%3e%20:root%20{%20--primary-fill:%20%23000;%20--secondary-fill:%20%23fff;%20}%20@media%20(prefers-color-scheme:%20dark)%20{%20:root%20{%20--primary-fill:%20%23fff;%20--secondary-fill:%20%23000;%20}%20}%20%3c/style%3e%3cg%20clip-path='url(%23a)'%3e%3crect%20width='180'%20height='180'%20fill='var(--primary-fill)'%20rx='90'%20/%3e%3cg%20clip-path='url(%23b)'%3e%3cpath%20fill='var(--secondary-fill)'%20d='M75.91%2073.628V62.232c0-.96.36-1.68%201.199-2.16l22.912-13.194c3.119-1.8%206.838-2.639%2010.676-2.639%2014.394%200%2023.511%2011.157%2023.511%2023.032%200%20.839%200%201.799-.12%202.758l-23.752-13.914c-1.439-.84-2.879-.84-4.318%200L75.91%2073.627Zm53.499%2044.383v-27.23c0-1.68-.72-2.88-2.159-3.719L97.142%2069.55l9.836-5.638c.839-.48%201.559-.48%202.399%200l22.912%2013.195c6.598%203.839%2011.035%2011.995%2011.035%2019.912%200%209.116-5.397%2017.513-13.915%2020.992v.001Zm-60.577-23.99-9.836-5.758c-.84-.48-1.2-1.2-1.2-2.16v-26.39c0-12.834%209.837-22.55%2023.152-22.55%205.039%200%209.716%201.679%2013.676%204.678L70.993%2055.516c-1.44.84-2.16%202.039-2.16%203.719v34.787-.002Zm21.173%2012.234L75.91%2098.339V81.546l14.095-7.917%2014.094%207.917v16.793l-14.094%207.916Zm9.056%2036.467c-5.038%200-9.716-1.68-13.675-4.678l23.631-13.676c1.439-.839%202.159-2.038%202.159-3.718V85.863l9.956%205.757c.84.48%201.2%201.2%201.2%202.16v26.389c0%2012.835-9.957%2022.552-23.27%2022.552v.001Zm-28.43-26.75L47.72%20102.778c-6.599-3.84-11.036-11.996-11.036-19.913%200-9.236%205.518-17.513%2014.034-20.992v27.35c0%201.68.72%202.879%202.16%203.718l29.989%2017.393-9.837%205.638c-.84.48-1.56.48-2.399%200Zm-1.318%2019.673c-13.555%200-23.512-10.196-23.512-22.792%200-.959.12-1.919.24-2.879l23.63%2013.675c1.44.84%202.88.84%204.32%200l30.108-17.392v11.395c0%20.96-.361%201.68-1.2%202.16l-22.912%2013.194c-3.119%201.8-6.837%202.639-10.675%202.639Zm29.748%2014.274c14.515%200%2026.63-10.316%2029.39-23.991%2013.434-3.479%2022.071-16.074%2022.071-28.91%200-8.396-3.598-16.553-10.076-22.43.6-2.52.96-5.039.96-7.557%200-17.153-13.915-29.99-29.989-29.99-3.239%200-6.358.48-9.477%201.56-5.398-5.278-12.835-8.637-20.992-8.637-14.515%200-26.63%2010.316-29.39%2023.991-13.434%203.48-22.07%2016.074-22.07%2028.91%200%208.396%203.598%2016.553%2010.075%2022.431-.6%202.519-.96%205.038-.96%207.556%200%2017.154%2013.915%2029.989%2029.99%2029.989%203.238%200%206.357-.479%209.476-1.559%205.397%205.278%2012.835%208.637%2020.992%208.637Z'%20/%3e%3c/g%3e%3c/g%3e%3cdefs%3e%3cclipPath%20id='a'%3e%3cpath%20d='M0%200h180v180H0z'%20/%3e%3c/clipPath%3e%3cclipPath%20id='b'%3e%3cpath%20d='M29.487%2029.964h121.035v119.954H29.487z'%20/%3e%3c/clipPath%3e%3c/defs%3e%3c/svg%3e
|
|
10
10
|
// @match *://chatgpt.com/*
|
|
11
|
-
// @require https://cdn.jsdelivr.net/npm/@kudoai/chatgpt.js@3.8.
|
|
11
|
+
// @require https://cdn.jsdelivr.net/npm/@kudoai/chatgpt.js@3.8.2/dist/chatgpt.min.js
|
|
12
12
|
// @grant GM_getValue
|
|
13
13
|
// @grant GM_setValue
|
|
14
14
|
// @noframes
|