@kudoai/chatgpt.js 3.3.5 → 3.5.0
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/README.md +29 -21
- package/chatgpt.js +149 -94
- package/dist/chatgpt.min.js +3 -3
- package/docs/README.md +29 -21
- package/docs/SECURITY.md +1 -3
- package/docs/USERGUIDE.md +3 -3
- package/package.json +18 -11
- package/starters/chrome/docs/README.md +10 -8
- package/starters/chrome/extension/components/icons.js +31 -0
- package/starters/chrome/extension/components/modals.js +148 -0
- package/starters/chrome/extension/content.js +108 -47
- 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/lib/chatgpt.js +149 -94
- package/starters/chrome/extension/lib/dom.js +35 -0
- package/starters/chrome/extension/lib/settings.js +30 -0
- package/starters/chrome/extension/manifest.json +22 -22
- package/starters/chrome/extension/popup/controller.js +140 -0
- package/starters/chrome/extension/popup/index.html +7 -44
- package/starters/chrome/extension/popup/style.css +33 -10
- package/starters/chrome/extension/service-worker.js +41 -0
- package/starters/greasemonkey/chatgpt.js-greasemonkey-starter.user.js +12 -12
- package/starters/greasemonkey/docs/README.md +2 -0
- package/starters/chrome/extension/background.js +0 -14
- package/starters/chrome/extension/lib/settings-utils.js +0 -24
- package/starters/chrome/extension/popup/popup.js +0 -92
- package/starters/chrome/media/images/icons/refresh/icon16.png +0 -0
- package/starters/chrome/media/images/icons/refresh/icon50.png +0 -0
- /package/starters/chrome/{media/images → images}/icons/question-mark/icon16.png +0 -0
- /package/starters/chrome/{media/images → images}/icons/question-mark/icon512.png +0 -0
- /package/starters/chrome/{media/images → images}/screenshots/chatgpt-extension-in-list.png +0 -0
- /package/starters/chrome/{media/images → images}/screenshots/developer-mode-toggle.png +0 -0
- /package/starters/chrome/{media/images → images}/screenshots/developer-mode-toggle.psd +0 -0
- /package/starters/chrome/{media/images → images}/screenshots/extension-loaded.png +0 -0
- /package/starters/chrome/{media/images → images}/screenshots/load-unpacked-button.png +0 -0
- /package/starters/chrome/{media/images → images}/screenshots/reload-extension-button.png +0 -0
- /package/starters/chrome/{media/images → images}/screenshots/reload-page-button.png +0 -0
- /package/starters/chrome/{media/images → images}/screenshots/select-extension-folder.png +0 -0
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
|
|
29
29
|
<br>
|
|
30
30
|
|
|
31
|
-
<img src="../
|
|
31
|
+
<img src="../images/screenshots/extension-loaded.png">
|
|
32
32
|
|
|
33
33
|
## ⚡ Installation
|
|
34
34
|
|
|
@@ -39,36 +39,38 @@
|
|
|
39
39
|
3. Visit `chrome://extensions` in Chrome (or any Chromium browser)
|
|
40
40
|
|
|
41
41
|
4. Ensure **Develper mode** toggle is activated<br>
|
|
42
|
-

|
|
43
43
|
|
|
44
44
|
5. Click **Load unpacked**<br><br>
|
|
45
|
-
<img src="../
|
|
45
|
+
<img src="../images/screenshots/load-unpacked-button.png">
|
|
46
46
|
<br>
|
|
47
47
|
|
|
48
48
|
6. In pop-up window, select the **extension** folder > click **Select Folder**<br><br><br>
|
|
49
|
-
<img src="../
|
|
49
|
+
<img src="../images/screenshots/select-extension-folder.png"><br><br>
|
|
50
50
|
|
|
51
51
|
That's it! **ChatGPT Extension** will now appear in extension list:
|
|
52
52
|
|
|
53
53
|
<br>
|
|
54
54
|
|
|
55
|
-
<img src="../
|
|
55
|
+
<img src="../images/screenshots/chatgpt-extension-in-list.png">
|
|
56
56
|
|
|
57
57
|
<p><br>
|
|
58
58
|
|
|
59
|
-
**💡 TIP:** _To reflect changes from source code, click **Reload** on extension tile + reload any Chrome tabs
|
|
59
|
+
**💡 TIP:** _To reflect changes from source code, click **Reload** on extension tile + reload any Chrome tabs content scripts are running on:_
|
|
60
60
|
|
|
61
61
|
<div align="center">
|
|
62
62
|
|
|
63
63
|
<br>
|
|
64
64
|
|
|
65
|
-
<img src="../
|
|
66
|
-
<img src="../
|
|
65
|
+
<img src="../images/screenshots/reload-extension-button.png">
|
|
66
|
+
<img src="../images/screenshots/reload-page-button.png">
|
|
67
67
|
|
|
68
68
|
<p><br>
|
|
69
69
|
|
|
70
70
|
</div>
|
|
71
71
|
|
|
72
|
+
_For advanced Chrome API methods, see: https://developer.chrome.com/docs/extensions/reference/api_
|
|
73
|
+
|
|
72
74
|
## 🤖 Made with chatgpt.js
|
|
73
75
|
|
|
74
76
|
These are some of the extensions featured by Google that use chatgpt.js:
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// Requires lib/dom.js
|
|
2
|
+
|
|
3
|
+
window.icons = {
|
|
4
|
+
imports: {
|
|
5
|
+
import(deps) { // { app }
|
|
6
|
+
for (const depName in deps) this[depName] = deps[depName] }
|
|
7
|
+
},
|
|
8
|
+
|
|
9
|
+
create({ name, size = 16, width, height, ...additionalAttrs }) {
|
|
10
|
+
const iconData = icons[name],
|
|
11
|
+
iconAttrs = { width: width || size, height: height || size, ...additionalAttrs }
|
|
12
|
+
if (iconData.type == 'svg') {
|
|
13
|
+
const svg = dom.create.svgElem('svg', { viewBox: iconData.viewBox, ...iconAttrs })
|
|
14
|
+
iconData.elems.forEach(([tag, attrs]) => svg.append(dom.create.svgElem(tag, attrs)))
|
|
15
|
+
return svg
|
|
16
|
+
} else // img w/ src
|
|
17
|
+
return dom.create.elem('img', { src: iconData.src, ...iconAttrs })
|
|
18
|
+
},
|
|
19
|
+
|
|
20
|
+
plus: {
|
|
21
|
+
type: 'svg', viewBox: '0 0 1024 1024',
|
|
22
|
+
elems: [
|
|
23
|
+
[ 'path', { d: 'M899.901 600.38H600.728v299.173c0 74.383-179.503 74.383-179.503 0V600.38H122.051c-74.384 0-74.384-179.503 0-179.503h299.173V121.703c0-74.384 179.503-74.384 179.503 0v299.174H899.9c74.385 0 74.385 179.503.001 179.503z' }]
|
|
24
|
+
]
|
|
25
|
+
},
|
|
26
|
+
|
|
27
|
+
questionMark: {
|
|
28
|
+
type: 'png',
|
|
29
|
+
get src() { return `${icons.imports.app.urls.assetHost}@b5551ac/images/icons/question-mark/icon16.png` }
|
|
30
|
+
}
|
|
31
|
+
};
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
// Requires lib/chatgpt.js + lib/dom.js
|
|
2
|
+
|
|
3
|
+
window.modals = {
|
|
4
|
+
stack: [], // of types of undismissed modals
|
|
5
|
+
get class() { return `${this.imports.app.cssPrefix}-modal` },
|
|
6
|
+
|
|
7
|
+
imports: {
|
|
8
|
+
import(deps) { // { app, env }
|
|
9
|
+
for (const depName in deps) this[depName] = deps[depName] }
|
|
10
|
+
},
|
|
11
|
+
|
|
12
|
+
alert(title = '', msg = '', btns = '', checkbox = '', width = '') { // generic one from chatgpt.alert()
|
|
13
|
+
const alertID = chatgpt.alert(title, msg, btns, checkbox, width),
|
|
14
|
+
alert = document.getElementById(alertID).firstChild
|
|
15
|
+
this.init(alert) // add classes + starry bg
|
|
16
|
+
return alert
|
|
17
|
+
},
|
|
18
|
+
|
|
19
|
+
open(modalType) {
|
|
20
|
+
const modal = this[modalType]() // show modal
|
|
21
|
+
this.stack.unshift(modalType) // add to stack
|
|
22
|
+
this.init(alert) // add classes + starry bg
|
|
23
|
+
this.observeRemoval(modal, modalType) // to maintain stack for proper nav
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
init(modal) {
|
|
27
|
+
if (!this.styles) this.stylize() // to init/append stylesheet
|
|
28
|
+
modal.classList.add(this.class) ; modal.parentNode.classList.add(`${this.class}-bg`) // add classes
|
|
29
|
+
dom.fillStarryBG(modal) // add starry bg
|
|
30
|
+
},
|
|
31
|
+
|
|
32
|
+
stylize() {
|
|
33
|
+
if (!this.styles) {
|
|
34
|
+
this.styles = dom.create.elem('style') ; this.styles.id = `${this.class}-styles`
|
|
35
|
+
document.head.append(this.styles)
|
|
36
|
+
}
|
|
37
|
+
this.styles.innerText = (
|
|
38
|
+
`.${this.class} {` // modals
|
|
39
|
+
+ 'font-family: -apple-system, system-ui, BlinkMacSystemFont, Segoe UI, Roboto,'
|
|
40
|
+
+ 'Oxygen-Sans, Ubuntu, Cantarell, Helvetica Neue, sans-serif ;'
|
|
41
|
+
+ 'padding: 20px 25px 24px 25px !important ; font-size: 20px ;'
|
|
42
|
+
+ `color: ${ this.imports.env.ui.scheme == 'dark' ? 'white' : 'black' } !important ;`
|
|
43
|
+
+ `background-image: linear-gradient(180deg, ${
|
|
44
|
+
this.imports.env.ui.scheme == 'dark' ? '#99a8a6 -200px, black 200px'
|
|
45
|
+
: '#b6ebff -296px, white 171px' }) }`
|
|
46
|
+
+ `.${this.class} [class*=modal-close-btn] {`
|
|
47
|
+
+ 'position: absolute !important ; float: right ; top: 14px !important ; right: 16px !important ;'
|
|
48
|
+
+ 'cursor: pointer ; width: 33px ; height: 33px ; border-radius: 20px }'
|
|
49
|
+
+ `.${this.class} [class*=modal-close-btn] svg { height: 10px }`
|
|
50
|
+
+ `.${this.class} [class*=modal-close-btn] path {`
|
|
51
|
+
+ `${ this.imports.env.ui.scheme == 'dark' ? 'stroke: white ; fill: white'
|
|
52
|
+
: 'stroke: #9f9f9f ; fill: #9f9f9f' }}`
|
|
53
|
+
+ ( this.imports.env.ui.scheme == 'dark' ? // invert dark mode hover paths
|
|
54
|
+
`.${this.class} [class*=modal-close-btn]:hover path { stroke: black ; fill: black }` : '' )
|
|
55
|
+
+ `.${this.class} [class*=modal-close-btn]:hover { background-color: #f2f2f2 }` // hover underlay
|
|
56
|
+
+ `.${this.class} [class*=modal-close-btn] svg { margin: 11.5px }` // center SVG for hover underlay
|
|
57
|
+
+ `.${this.class} a {`
|
|
58
|
+
+ `color: #${ this.imports.env.ui.scheme == 'dark' ? '00cfff' : '1e9ebb' } !important }`
|
|
59
|
+
+ `.${this.class} h2 { font-weight: bold }`
|
|
60
|
+
+ `.${this.class} button {`
|
|
61
|
+
+ 'font-size: 14px ; text-transform: uppercase ;' // shrink/uppercase labels
|
|
62
|
+
+ 'border-radius: 0 !important ;' // square borders
|
|
63
|
+
+ 'transition: transform 0.1s ease-in-out, box-shadow 0.1s ease-in-out ;' // smoothen hover fx
|
|
64
|
+
+ 'cursor: pointer !important ;' // add finger cursor
|
|
65
|
+
+ `border: 1px solid ${ this.imports.env.ui.scheme == 'dark' ? 'white' : 'black' } !important ;`
|
|
66
|
+
+ 'padding: 8px !important ; min-width: 102px }' // resize
|
|
67
|
+
+ `.${this.class} button:hover {` // add zoom, re-scheme
|
|
68
|
+
+ 'transform: scale(1.055) ; color: black !important ;'
|
|
69
|
+
+ `background-color: #${ this.imports.env.ui.scheme == 'dark' ? '00cfff' : '9cdaff' } !important }`
|
|
70
|
+
+ ( !this.imports.env.browser.isMobile ?
|
|
71
|
+
`.${this.class} .modal-buttons { margin-left: -13px !important }` : '' )
|
|
72
|
+
+ `.about-em { color: ${ this.imports.env.ui.scheme == 'dark' ? 'white' : 'green' } !important }`
|
|
73
|
+
)
|
|
74
|
+
},
|
|
75
|
+
|
|
76
|
+
observeRemoval(modal, modalType) { // to maintain stack for proper nav
|
|
77
|
+
const modalBG = modal.parentNode
|
|
78
|
+
new MutationObserver(([mutation], obs) => {
|
|
79
|
+
mutation.removedNodes.forEach(removedNode => { if (removedNode == modalBG) {
|
|
80
|
+
if (this.stack[0] == modalType) { // new modal not launched, implement nav back logic
|
|
81
|
+
this.stack.shift() // remove this modal type from stack 1st
|
|
82
|
+
const prevModalType = this.stack[0]
|
|
83
|
+
if (prevModalType) { // open it
|
|
84
|
+
this.stack.shift() // remove type from stack since re-added on open
|
|
85
|
+
this.open(prevModalType)
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
obs.disconnect()
|
|
89
|
+
}})
|
|
90
|
+
}).observe(modalBG.parentNode, { childList: true, subtree: true })
|
|
91
|
+
},
|
|
92
|
+
|
|
93
|
+
about() {
|
|
94
|
+
|
|
95
|
+
// Show modal
|
|
96
|
+
const aboutModal = this.alert(
|
|
97
|
+
`${this.imports.app.symbol} ${chrome.runtime.getManifest().name}`, // title
|
|
98
|
+
'🧠 Author: ' // msg
|
|
99
|
+
+ `<a href="${this.imports.app.author.url}">${this.imports.app.author.name}</a> `
|
|
100
|
+
+ `& <a href="${this.imports.app.urls.contributors}">contributors</a>\n`
|
|
101
|
+
+ `🏷️ Version: <span class="about-em">${this.imports.app.version}</span>\n`
|
|
102
|
+
+ '📜 Open source code: '
|
|
103
|
+
+ `<a href="${this.imports.app.urls.gitHub}" target="_blank" rel="nopener">`
|
|
104
|
+
+ this.imports.app.urls.gitHub + '</a>\n'
|
|
105
|
+
+ '⚡ Powered by: '
|
|
106
|
+
+ `<a href="${this.imports.app.urls.chatgptJS}" target="_blank" rel="noopener">chatgpt.js</a>`,
|
|
107
|
+
[ function getSupport(){}, function rateUs(){}, function moreAiExtensions(){} ], // button labels
|
|
108
|
+
'', 656 // modal width
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
// Format text
|
|
112
|
+
aboutModal.querySelector('h2').style.cssText = (
|
|
113
|
+
'text-align: center ; font-size: 51px ; line-height: 46px ; padding: 15px 0' )
|
|
114
|
+
aboutModal.querySelector('p').style.cssText = (
|
|
115
|
+
'text-align: center ; overflow-wrap: anywhere ;'
|
|
116
|
+
+ `margin: ${ this.imports.env.browser.isPortrait ? '6px 0 -16px' : '3px 0 0' }` )
|
|
117
|
+
|
|
118
|
+
// Hack buttons
|
|
119
|
+
aboutModal.querySelector('.modal-buttons').style.justifyContent = 'center'
|
|
120
|
+
aboutModal.querySelectorAll('button').forEach(btn => {
|
|
121
|
+
btn.style.cssText = 'height: 55px ; min-width: 136px ; text-align: center'
|
|
122
|
+
|
|
123
|
+
// Replace buttons w/ clones that don't dismiss modal
|
|
124
|
+
const btnClone = btn.cloneNode(true)
|
|
125
|
+
btn.parentNode.replaceChild(btnClone, btn) ; btn = btnClone
|
|
126
|
+
btn.onclick = () => this.safeWinOpen(
|
|
127
|
+
btn.textContent == 'Get Support' ? `${modals.imports.app.urls.gitHub}/issues`
|
|
128
|
+
: btn.textContent == 'Rate Us' ? `${modals.imports.app.urls.gitHub}/discussions`
|
|
129
|
+
: modals.imports.app.urls.relatedExtensions
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
// Prepend emoji
|
|
133
|
+
if (/support/i.test(btn.textContent))
|
|
134
|
+
btn.textContent = '🧠 ' + btn.textContent
|
|
135
|
+
else if (/rate/i.test(btn.textContent))
|
|
136
|
+
btn.textContent = '⭐ ' + btn.textContent
|
|
137
|
+
else if (/extensions/i.test(btn.textContent))
|
|
138
|
+
btn.textContent = '🧠 ' + btn.textContent
|
|
139
|
+
|
|
140
|
+
// Hide Dismiss button
|
|
141
|
+
else btn.style.display = 'none'
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
return aboutModal
|
|
145
|
+
},
|
|
146
|
+
|
|
147
|
+
safeWinOpen(url) { open(url, '_blank', 'noopener') } // to prevent backdoor vulnerabilities
|
|
148
|
+
};
|
|
@@ -1,37 +1,111 @@
|
|
|
1
1
|
// NOTE: This script relies on the powerful chatgpt.js library @ https://chatgpt.js.org
|
|
2
2
|
// © 2023–2024 KudoAI & contributors under the MIT license
|
|
3
|
-
// Source: https://github.com/KudoAI/chatgpt.js
|
|
4
|
-
// Latest minified release: https://cdn.jsdelivr.net/npm/@kudoai/chatgpt.js/chatgpt.min.js
|
|
5
3
|
|
|
6
4
|
(async () => {
|
|
7
5
|
|
|
8
|
-
// Import
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
//
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
6
|
+
// Import JS resources
|
|
7
|
+
for (const resource of ['components/modals.js', 'lib/chatgpt.js', 'lib/dom.js', 'lib/settings.js'])
|
|
8
|
+
await import(chrome.runtime.getURL(resource))
|
|
9
|
+
|
|
10
|
+
// Init ENV context
|
|
11
|
+
const env = { browser: { isMobile: chatgpt.browser.isMobile() }, ui: { scheme: getScheme() }}
|
|
12
|
+
env.browser.isPortrait = env.browser.isMobile && (window.innerWidth < window.innerHeight)
|
|
13
|
+
|
|
14
|
+
// Import APP data
|
|
15
|
+
const { app } = await chrome.storage.sync.get('app')
|
|
16
|
+
|
|
17
|
+
// Export DEPENDENCIES to imported resources
|
|
18
|
+
dom.imports.import({ env }) // for env.ui.scheme
|
|
19
|
+
modals.imports.import({ app, env }) // for app data + env.ui.scheme
|
|
20
|
+
|
|
21
|
+
// Add CHROME MSG listener
|
|
22
|
+
chrome.runtime.onMessage.addListener(req => { // from service-worker.js + popup/index.html
|
|
23
|
+
if (req.action == 'notify')
|
|
24
|
+
notify(...['msg', 'pos', 'notifDuration', 'shadow'].map(arg => req.options[arg]))
|
|
25
|
+
else if (req.action == 'alert')
|
|
26
|
+
modals.alert(...['title', 'msg', 'btns', 'checkbox', 'width'].map(arg => req.options[arg]))
|
|
27
|
+
else if (req.action == 'showAbout') chatgpt.isLoaded().then(() => { modals.open('about') })
|
|
28
|
+
else if (req.action == 'syncConfigToUI') syncConfigToUI(req.options)
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
// Init SETTINGS
|
|
32
|
+
await settings.load(Object.keys(settings.controls), 'skipAlert')
|
|
33
|
+
|
|
34
|
+
// Define FUNCTIONS
|
|
35
|
+
|
|
36
|
+
function notify(msg, pos = '', notifDuration = '', shadow = '') {
|
|
37
|
+
|
|
38
|
+
// Strip state word to append colored one later
|
|
39
|
+
const foundState = ['ON', 'OFF'].find(word => msg.includes(word))
|
|
40
|
+
if (foundState) msg = msg.replace(foundState, '')
|
|
41
|
+
|
|
42
|
+
// Show notification
|
|
43
|
+
chatgpt.notify(`${app.symbol} ${msg}`, pos, notifDuration, shadow || env.ui.scheme == 'dark' ? '' : 'shadow')
|
|
44
|
+
const notif = document.querySelector('.chatgpt-notif:last-child')
|
|
45
|
+
|
|
46
|
+
// Append styled state word
|
|
47
|
+
if (foundState) {
|
|
48
|
+
const styledStateSpan = dom.create.elem('span')
|
|
49
|
+
styledStateSpan.style.cssText = `color: ${
|
|
50
|
+
foundState == 'OFF' ? '#ef4848 ; text-shadow: rgba(255, 169, 225, 0.44) 2px 1px 5px'
|
|
51
|
+
: '#5cef48 ; text-shadow: rgba(255, 250, 169, 0.38) 2px 1px 5px' }`
|
|
52
|
+
styledStateSpan.append(foundState) ; notif.append(styledStateSpan)
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async function syncConfigToUI(options) { // eslint-disable-line
|
|
57
|
+
await settings.load('extensionDisabled', Object.keys(settings.controls)) // load from Chrome storage to content.js config
|
|
58
|
+
if (config.extensionDisabled) {
|
|
59
|
+
// Remove all hacks
|
|
60
|
+
} else {
|
|
61
|
+
// Add/remove hacks to reflect each potentially updated setting per settings.controls in lib/settings.mjs
|
|
62
|
+
// e.g. if you created toolbar popup toggle to hide ChatGPT footer using hiddenFooter key...
|
|
63
|
+
// ...here you would use options?.updatedKey == 'hiddenFooter' && config.hiddenFooter...
|
|
64
|
+
// ...to conditionally append/remove hidden footer style...
|
|
65
|
+
// ...(initial style creation + append if config.hiddenFooter would go in main routine)
|
|
20
66
|
}
|
|
21
|
-
|
|
22
|
-
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function getScheme() {
|
|
70
|
+
return document.documentElement.className
|
|
71
|
+
|| (window.matchMedia?.('(prefers-color-scheme: dark)')?.matches ? 'dark' : 'light')
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Run MAIN routine
|
|
75
|
+
|
|
76
|
+
chatgpt.printAllFunctions() // to console
|
|
23
77
|
|
|
24
|
-
|
|
25
|
-
chatgpt.
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
78
|
+
// CHILL a bit if your hacks depend on delayed DOM content
|
|
79
|
+
await chatgpt.isLoaded()
|
|
80
|
+
await new Promise(resolve => setTimeout(resolve, 500)); // sleep .5s
|
|
81
|
+
|
|
82
|
+
// Add STARS styles for modals
|
|
83
|
+
['black', 'white'].forEach(color => document.head.append(
|
|
84
|
+
dom.create.elem('link', { rel: 'stylesheet',
|
|
85
|
+
href: `https://assets.aiwebextensions.com/styles/rising-stars/dist/${
|
|
86
|
+
color}.min.css?v=0cde30f9ae3ce99ae998141f6e7a36de9b0cc2e7`
|
|
87
|
+
})))
|
|
88
|
+
|
|
89
|
+
if (config.extensionDisabled) return
|
|
90
|
+
|
|
91
|
+
if (!config.skipAlert) // alert to extension load
|
|
92
|
+
modals.alert('≫ ChatGPT extension loaded! 🚀', // title
|
|
93
|
+
'Success! Press Ctrl+Shift+J to view all chatgpt.js methods.', // msg
|
|
94
|
+
function getHelp() { // button
|
|
95
|
+
chrome.tabs.create({ url: `${app.urls.gitHub}/issues` }) },
|
|
96
|
+
function dontShowAgain() { // checkbox
|
|
97
|
+
settings.save('skipAlert', !config.skipAlert) }
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
// Monitor SCHEME PREF CHANGES to update modal colors + env.ui.scheme for your use
|
|
101
|
+
new MutationObserver(handleSchemePrefChange).observe( // for site scheme pref changes
|
|
102
|
+
document.documentElement, { attributes: true, attributeFilter: ['class'] })
|
|
103
|
+
window.matchMedia('(prefers-color-scheme: dark)').addEventListener( // for browser/system scheme pref changes
|
|
104
|
+
'change', () => requestAnimationFrame(handleSchemePrefChange))
|
|
105
|
+
function handleSchemePrefChange() {
|
|
106
|
+
const displayedScheme = getScheme()
|
|
107
|
+
if (env.ui.scheme != displayedScheme) { env.ui.scheme = displayedScheme ; modals.stylize() }
|
|
108
|
+
}
|
|
35
109
|
|
|
36
110
|
// Your code here...
|
|
37
111
|
// Your code here...
|
|
@@ -39,24 +113,11 @@
|
|
|
39
113
|
// Your code here...
|
|
40
114
|
// Your code here...
|
|
41
115
|
// Your code here...
|
|
116
|
+
// Your code here...
|
|
117
|
+
// Your code here...
|
|
118
|
+
// Your code here...
|
|
119
|
+
// Your code here...
|
|
120
|
+
// Your code here...
|
|
121
|
+
// Your code here...
|
|
42
122
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
function notify(msg, position = '', notifDuration = '', shadow = '') {
|
|
46
|
-
chatgpt.notify(`${ config.appSymbol } ${ msg }`, position, notifDuration,
|
|
47
|
-
shadow || chatgpt.isDarkMode() ? '' : 'shadow' ); }
|
|
48
|
-
|
|
49
|
-
function alert(title = '', msg = '', btns = '', checkbox = '', width = '') {
|
|
50
|
-
return chatgpt.alert(`${ config.appSymbol } ${ title }`, msg, btns, checkbox, width );}
|
|
51
|
-
|
|
52
|
-
// Define SYNC function
|
|
53
|
-
|
|
54
|
-
syncExtension = () => {
|
|
55
|
-
settings.load('extensionDisabled').then(() => {
|
|
56
|
-
if (config.extensionDisabled) {
|
|
57
|
-
// remove your hacks
|
|
58
|
-
} else {
|
|
59
|
-
// sync each potentially updated setting passed to settings.load()
|
|
60
|
-
}});};
|
|
61
|
-
|
|
62
|
-
})();
|
|
123
|
+
})()
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|