Skip to content

Commit efc097e

Browse files
authored
Merge pull request #152 from qunash/dev
Dev
2 parents 31566a8 + 0386255 commit efc097e

File tree

12 files changed

+124
-79
lines changed

12 files changed

+124
-79
lines changed

.hintrc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"development"
44
],
55
"hints": {
6-
"axe/forms": "off"
6+
"axe/forms": "off",
7+
"no-inline-styles": "off"
78
}
89
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"private": true,
33
"name": "webchatgpt",
4-
"version": "3.2.5",
4+
"version": "3.2.6",
55
"license": "MIT",
66
"scripts": {
77
"build-dev": "node build.mjs",

src/components/errorMessage.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ function ErrorMessage(props: { message: string }): h.JSX.Element | null {
1717

1818
return (
1919
// <div className="absolute wcg-bottom-0 wcg-right-1 dark:wcg-text-white wcg-bg-red-500 wcg-p-4 wcg-rounded-lg wcg-mb-4 wcg-mr-4 wcg-text-sm">
20-
<div role="alert" className="absolute bottom-0 right-1 dark:text-white bg-red-500 p-4 rounded-lg mb-4 mr-4 text-sm">
20+
<div role="alert" className="absolute bottom-0 right-1 dark:text-white bg-red-500 p-4 rounded-lg mb-4 mr-4 text-sm max-w-sm">
2121
<b>An error occurred</b><br />
2222
{props.message}<br /><br />
23-
Please Check the console for more details. (Ctrl+Shift+J)
23+
You can check the console for more details. (Ctrl+Shift+J)
2424
</div>
2525
)
2626
}

src/components/footer.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ function Footer() {
66

77
return (
88
<div className="wcg-text-center wcg-text-xs wcg-text-gray-400">
9-
<a href='https://github.com/qunash/chatgpt-advanced' target='_blank' className='underline wcg-text-gray-400 wcg-underline' rel="noreferrer">
9+
<a href='https://github.com/qunash/chatgpt-advanced' target='_blank' className='underline wcg-text-gray-400 wcg-underline' rel="noreferrer noopener">
1010
WebChatGPT extension v.{extension_version}
1111
</a>.
12-
If you like the extension, please consider <a href='https://www.buymeacoffee.com/anzorq?utm_source=webchatgpt&utm_medium=toolbar' target='_blank' className='wcg-text-gray-400 wcg-underline' rel="noreferrer">supporting me</a>.
12+
If you like the extension, please consider <a href='https://www.buymeacoffee.com/anzorq?utm_source=webchatgpt&utm_medium=toolbar' target='_blank' className='wcg-text-gray-400 wcg-underline' rel="noreferrer noopener">supporting me</a>.
1313
</div>
1414
)
1515
}

src/components/toolbar.tsx

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ import Dropdown from './dropdown'
1010
import { getTranslation, localizationKeys, setLocaleLanguage } from 'src/util/localization'
1111
import Footer from './footer'
1212

13+
type DropdownItem = {
14+
target: {
15+
value: string
16+
}
17+
}
1318

1419
const numResultsOptions = Array.from({ length: 10 }, (_, i) => i + 1).map((num) => ({
1520
value: num,
@@ -21,11 +26,10 @@ numResultsOptions.push({
2126
label: 'Max results'
2227
})
2328

24-
function Toolbar(
25-
props: {
26-
textarea: HTMLTextAreaElement | null,
27-
}
28-
) {
29+
interface ToolbarProps {
30+
textarea: HTMLTextAreaElement | null
31+
}
32+
const Toolbar = ({ textarea }: ToolbarProps) => {
2933
const [webAccess, setWebAccess] = useState(false)
3034
const [numResults, setNumResults] = useState(3)
3135
const [timePeriod, setTimePeriod] = useState('')
@@ -56,18 +60,15 @@ function Toolbar(
5660

5761
Browser.runtime.onMessage.addListener(handleMessage)
5862

59-
return function cleanup() {
60-
Browser.runtime.onMessage.removeListener(handleMessage)
61-
}
63+
return () => Browser.runtime.onMessage.removeListener(handleMessage)
6264
}, [])
6365

6466
useEffect(() => {
6567
updateUserConfig({ webAccess })
6668
updateTextAreaPlaceholder(webAccess)
67-
props.textarea?.focus()
69+
textarea?.focus()
6870
}, [webAccess])
6971

70-
7172
const handlePromptClick = () => updatePrompts()
7273

7374
const updatePrompts = () => {
@@ -77,28 +78,28 @@ function Toolbar(
7778
}
7879

7980
const updateTextAreaPlaceholder = (show: boolean) => {
80-
props.textarea?.setAttribute('placeholder', show ? getTranslation(localizationKeys.UI.textareaPlaceholder) : '')
81+
textarea?.setAttribute('placeholder', show ? getTranslation(localizationKeys.UI.textareaPlaceholder) : '')
8182
}
8283

8384
const handleWebAccessToggle = () => setWebAccess((prev) => !prev)
8485

85-
const handleNumResultsChange = (e: { target: { value: string } }) => {
86+
const handleNumResultsChange = (e: DropdownItem) => {
8687
const value = parseInt(e.target.value, 10)
8788
setNumResults(value)
8889
updateUserConfig({ numWebResults: value })
8990
}
9091

91-
const handleTimePeriodChange = (e: { target: { value: string } }) => {
92+
const handleTimePeriodChange = (e: DropdownItem) => {
9293
setTimePeriod(e.target.value)
9394
updateUserConfig({ timePeriod: e.target.value })
9495
}
9596

96-
const handleRegionChange = (e: { target: { value: string } }) => {
97+
const handleRegionChange = (e: DropdownItem) => {
9798
setRegion(e.target.value)
9899
updateUserConfig({ region: e.target.value })
99100
}
100101

101-
const handlePromptChange = (e: { target: { value: string } }) => {
102+
const handlePromptChange = (e: DropdownItem) => {
102103

103104
const uuid = e.target.value
104105

@@ -159,7 +160,7 @@ function Toolbar(
159160
value={promptUUID}
160161
onChange={handlePromptChange}
161162
options={
162-
prompts.map((prompt) => ({ value: prompt.uuid, label: prompt.name })).concat({ value: 'wcg-new-prompt', label: `+ ${getTranslation(localizationKeys.buttons.newPrompt)}` })
163+
prompts.map((prompt) => ({ value: prompt.uuid ?? 'undefin', label: prompt.name })).concat({ value: 'wcg-new-prompt', label: `+ ${getTranslation(localizationKeys.buttons.newPrompt)}` })
163164
}
164165
onClick={handlePromptClick}
165166
/>

src/content-scripts/api.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,22 +35,23 @@ export async function getWebpageTitleAndText(url: string, html_str = ''): Promis
3535
}
3636
}
3737
html = await response.text()
38-
3938
}
4039

4140

4241
const doc = parseHTML(html).document
4342
const parsed = new Readability(doc).parse()
4443

45-
if (!parsed) {
46-
return { title: "Could not parse the page.", body: "", url }
44+
if (!parsed || !parsed.textContent) {
45+
return { title: "Could not parse the page.", body: "Could not parse the page.", url }
4746
}
48-
49-
let text = cleanText(parsed.textContent)
5047

48+
console.log("text", parsed.textContent);
49+
let text = cleanText(parsed.textContent)
50+
5151
const userConfig = await getUserConfig()
52-
if (userConfig.trimLongText) {
53-
text = text.slice(0, 14500)
52+
if (userConfig.trimLongText && text.length > 14400) {
53+
text = text.slice(0, 14400)
54+
text += "\n\n[Text has been trimmed to 14,500 characters. You can disable this on WebChatGPT's options page.]"
5455
}
5556
return { title: parsed.title, body: text, url }
5657
}

src/content-scripts/ddg_search.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ export async function getHtml({ query, timerange, region }: SearchRequest): Prom
5252
}
5353

5454
function htmlToSearchResults(html: string, numResults: number): SearchResult[] {
55-
console.log("htmlToSearchResults", numResults)
55+
// console.log("htmlToSearchResults", numResults)
5656
const $ = cheerio.load(html)
5757
const results: SearchResult[] = []
5858

@@ -72,8 +72,8 @@ function htmlToSearchResults(html: string, numResults: number): SearchResult[] {
7272

7373
// Extract web search results
7474
const upperBound = zeroClickLink.length > 0 ? numResults - 1 : numResults
75-
const webLinks = $(`table:nth-of-type(${numTables}) .result-link`).slice(0, upperBound)
76-
const webSnippets = $(`table:nth-of-type(${numTables}) .result-snippet`).slice(0, upperBound)
75+
const webLinks = $(`table:nth-of-type(${numTables}) tr:not(.result-sponsored) .result-link`).slice(0, upperBound)
76+
const webSnippets = $(`table:nth-of-type(${numTables}) tr:not(.result-sponsored) .result-snippet`).slice(0, upperBound)
7777
webLinks.each((i, element) => {
7878
const link = $(element)
7979
const snippet = $(webSnippets[i]).text().trim()

src/content-scripts/mainUI.tsx

Lines changed: 87 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ import { apiExtractText } from './api'
1313

1414
let isProcessing = false
1515

16-
let btnSubmit: HTMLButtonElement
17-
let textarea: HTMLTextAreaElement
18-
let footer: HTMLDivElement
16+
let btnSubmit: HTMLButtonElement | null | undefined
17+
let textarea: HTMLTextAreaElement | null
18+
let chatGptFooter: HTMLDivElement | null
1919

2020

2121
function renderSlashCommandsMenu() {
@@ -24,7 +24,7 @@ function renderSlashCommandsMenu() {
2424
if (div) div.remove()
2525

2626
div = document.createElement('wcg-slash-commands-menu')
27-
const textareaParentParent = textarea.parentElement?.parentElement
27+
const textareaParentParent = textarea?.parentElement?.parentElement
2828

2929
textareaParentParent?.insertBefore(div, textareaParentParent.firstChild)
3030
render(<SlashCommandsMenu textarea={textarea} />, div)
@@ -58,6 +58,8 @@ async function processQuery(query: string, userConfig: UserConfig) {
5858

5959
async function handleSubmit(query: string) {
6060

61+
if (!textarea) return
62+
6163
const userConfig = await getUserConfig()
6264

6365
if (!userConfig.webAccess) {
@@ -81,21 +83,27 @@ async function handleSubmit(query: string) {
8183
}
8284

8385
async function onSubmit(event: MouseEvent | KeyboardEvent) {
86+
87+
if (!textarea) return
88+
8489
const isKeyEvent = event instanceof KeyboardEvent
8590

8691
if (isKeyEvent && event.shiftKey && event.key === 'Enter') return
8792

8893
if (isKeyEvent && event.key === 'Enter' && event.isComposing) return
8994

9095
if (!isProcessing && (event.type === "click" || (isKeyEvent && event.key === 'Enter'))) {
91-
const query = textarea.value.trim()
96+
const query = textarea?.value.trim()
9297

93-
if (query === "") return
98+
// if query is empty or undefined, return
99+
if (!query) return
94100

95101
textarea.value = ""
96102

97103
const isPartialCommand = slashCommands.some(command => command.name.startsWith(query) && query.length <= command.name.length)
98-
if (isPartialCommand) return
104+
if (isPartialCommand) {
105+
return
106+
}
99107

100108
isProcessing = true
101109
await handleSubmit(query)
@@ -104,14 +112,14 @@ async function onSubmit(event: MouseEvent | KeyboardEvent) {
104112
}
105113

106114
function pressEnter() {
107-
textarea.focus()
115+
textarea?.focus()
108116
const enterEvent = new KeyboardEvent('keydown', {
109117
bubbles: true,
110118
cancelable: true,
111119
key: 'Enter',
112120
code: 'Enter'
113121
})
114-
textarea.dispatchEvent(enterEvent)
122+
textarea?.dispatchEvent(enterEvent)
115123
}
116124

117125
function showErrorMessage(error: Error) {
@@ -124,59 +132,93 @@ function showErrorMessage(error: Error) {
124132

125133
async function updateUI() {
126134

127-
if (getWebChatGPTToolbar()) return
135+
formChild = document.querySelector('form')?.children[0] as HTMLElement
136+
textarea = getTextArea()
137+
// console.info("UpdateUI textarea: ", textarea)
138+
139+
const toolbar = getWebChatGPTToolbar()
140+
if (!textarea) {
141+
toolbar?.remove()
142+
return
143+
}
144+
145+
if (toolbar) return
146+
147+
console.info("WebChatGPT: Updating UI")
128148

129149
btnSubmit = getSubmitButton()
130-
textarea = getTextArea()
131-
footer = getFooter()
150+
btnSubmit?.addEventListener("click", onSubmit)
132151

133-
if (textarea && btnSubmit) {
152+
textarea?.addEventListener("keydown", onSubmit)
134153

135-
textarea.addEventListener("keydown", onSubmit)
136-
btnSubmit.addEventListener("click", onSubmit)
154+
await renderToolbar()
137155

138-
const textareaParentParent = textarea.parentElement?.parentElement
139-
if (textareaParentParent && textareaParentParent.parentElement) {
140-
textareaParentParent.style.flexDirection = 'column'
141-
textareaParentParent.parentElement.style.flexDirection = 'column'
142-
textareaParentParent.parentElement.style.gap = '0px'
143-
textareaParentParent.parentElement.style.marginBottom = '0.5em'
144-
}
156+
renderSlashCommandsMenu()
145157

146-
try {
147-
const { shadowRootDiv, shadowRoot } = await createShadowRoot('content-scripts/mainUI.css')
148-
shadowRootDiv.classList.add('wcg-toolbar')
149-
textareaParentParent?.appendChild(shadowRootDiv)
150-
render(<Toolbar textarea={textarea} />, shadowRoot)
151-
} catch (e) {
152-
if (e instanceof Error) {
153-
showErrorMessage(Error(`Error loading WebChatGPT toolbar: ${e.message}. Please reload the page (F5).`));
154-
console.error(e)
155-
}
156-
}
157-
// textarea.parentElement.style.flexDirection = 'row'
158+
// textarea.parentElement.style.flexDirection = 'row'
158159

159-
renderSlashCommandsMenu()
160+
chatGptFooter = getFooter()
161+
if (chatGptFooter) {
162+
const lastChild = chatGptFooter.lastElementChild as HTMLElement
163+
if (lastChild) lastChild.style.padding = '0 0 0.5em 0'
160164
}
165+
}
161166

162-
if (footer) {
163-
const lastChild = footer.lastElementChild as HTMLElement
164-
if (lastChild)
165-
lastChild.style.padding = '0 0 0.5em 0'
167+
async function renderToolbar() {
168+
169+
try {
170+
const textareaParentParent = textarea?.parentElement?.parentElement
171+
// const textareaParentParent = formChild
172+
// if (textareaParentParent && textareaParentParent.parentElement) {
173+
// textareaParentParent.style.flexDirection = 'column'
174+
// textareaParentParent.parentElement.style.flexDirection = 'column'
175+
// textareaParentParent.parentElement.style.gap = '0px'
176+
// textareaParentParent.parentElement.style.marginBottom = '0.5em'
177+
// }
178+
179+
const { shadowRootDiv, shadowRoot } = await createShadowRoot('content-scripts/mainUI.css')
180+
shadowRootDiv.classList.add('wcg-toolbar')
181+
textareaParentParent?.appendChild(shadowRootDiv)
182+
render(<Toolbar textarea={textarea} />, shadowRoot)
183+
184+
} catch (e) {
185+
if (e instanceof Error) {
186+
showErrorMessage(Error(`Error loading WebChatGPT toolbar: ${e.message}. Please reload the page (F5).`))
187+
}
166188
}
167189
}
168190

169-
const rootEl = getRootElement()
170-
window.onload = function () {
171-
updateUI()
191+
const form = document.querySelector('form')
192+
const formParent = form?.parentElement
172193

194+
const rootEl = getRootElement()
195+
let formChild = document.querySelector('form')?.children[0] as HTMLElement
196+
const mutationObserver = new MutationObserver(() => {
173197
try {
174-
new MutationObserver(() => {
175-
updateUI()
176-
}).observe(rootEl, { childList: true })
198+
updateUI()
177199
} catch (e) {
178200
if (e instanceof Error) {
179201
showErrorMessage(e)
180202
}
181203
}
204+
})
205+
206+
window.onload = function () {
207+
updateUI()
208+
209+
if (formChild) {
210+
mutationObserver.observe(formChild, { childList: true })
211+
}
212+
213+
if (rootEl) {
214+
mutationObserver.observe(rootEl, { childList: true })
215+
}
216+
217+
if (formParent) {
218+
mutationObserver.observe(formParent, { childList: true })
219+
}
220+
}
221+
222+
window.onunload = function () {
223+
mutationObserver.disconnect()
182224
}

0 commit comments

Comments
 (0)