+
An error occurred
{props.message}
- Please Check the console for more details. (Ctrl+Shift+J)
+ You can check the console for more details. (Ctrl+Shift+J)
)
}
diff --git a/src/components/footer.tsx b/src/components/footer.tsx
index c2d6f3e..0ca20a9 100644
--- a/src/components/footer.tsx
+++ b/src/components/footer.tsx
@@ -6,10 +6,10 @@ function Footer() {
return (
)
}
diff --git a/src/components/toolbar.tsx b/src/components/toolbar.tsx
index 0d7335e..e556b49 100644
--- a/src/components/toolbar.tsx
+++ b/src/components/toolbar.tsx
@@ -10,6 +10,11 @@ import Dropdown from './dropdown'
import { getTranslation, localizationKeys, setLocaleLanguage } from 'src/util/localization'
import Footer from './footer'
+type DropdownItem = {
+ target: {
+ value: string
+ }
+}
const numResultsOptions = Array.from({ length: 10 }, (_, i) => i + 1).map((num) => ({
value: num,
@@ -21,11 +26,10 @@ numResultsOptions.push({
label: 'Max results'
})
-function Toolbar(
- props: {
- textarea: HTMLTextAreaElement | null,
- }
-) {
+interface ToolbarProps {
+ textarea: HTMLTextAreaElement | null
+}
+const Toolbar = ({ textarea }: ToolbarProps) => {
const [webAccess, setWebAccess] = useState(false)
const [numResults, setNumResults] = useState(3)
const [timePeriod, setTimePeriod] = useState('')
@@ -56,18 +60,15 @@ function Toolbar(
Browser.runtime.onMessage.addListener(handleMessage)
- return function cleanup() {
- Browser.runtime.onMessage.removeListener(handleMessage)
- }
+ return () => Browser.runtime.onMessage.removeListener(handleMessage)
}, [])
useEffect(() => {
updateUserConfig({ webAccess })
updateTextAreaPlaceholder(webAccess)
- props.textarea?.focus()
+ textarea?.focus()
}, [webAccess])
-
const handlePromptClick = () => updatePrompts()
const updatePrompts = () => {
@@ -77,28 +78,28 @@ function Toolbar(
}
const updateTextAreaPlaceholder = (show: boolean) => {
- props.textarea?.setAttribute('placeholder', show ? getTranslation(localizationKeys.UI.textareaPlaceholder) : '')
+ textarea?.setAttribute('placeholder', show ? getTranslation(localizationKeys.UI.textareaPlaceholder) : '')
}
const handleWebAccessToggle = () => setWebAccess((prev) => !prev)
- const handleNumResultsChange = (e: { target: { value: string } }) => {
+ const handleNumResultsChange = (e: DropdownItem) => {
const value = parseInt(e.target.value, 10)
setNumResults(value)
updateUserConfig({ numWebResults: value })
}
- const handleTimePeriodChange = (e: { target: { value: string } }) => {
+ const handleTimePeriodChange = (e: DropdownItem) => {
setTimePeriod(e.target.value)
updateUserConfig({ timePeriod: e.target.value })
}
- const handleRegionChange = (e: { target: { value: string } }) => {
+ const handleRegionChange = (e: DropdownItem) => {
setRegion(e.target.value)
updateUserConfig({ region: e.target.value })
}
- const handlePromptChange = (e: { target: { value: string } }) => {
+ const handlePromptChange = (e: DropdownItem) => {
const uuid = e.target.value
@@ -159,7 +160,7 @@ function Toolbar(
value={promptUUID}
onChange={handlePromptChange}
options={
- prompts.map((prompt) => ({ value: prompt.uuid, label: prompt.name })).concat({ value: 'wcg-new-prompt', label: `+ ${getTranslation(localizationKeys.buttons.newPrompt)}` })
+ prompts.map((prompt) => ({ value: prompt.uuid ?? 'undefin', label: prompt.name })).concat({ value: 'wcg-new-prompt', label: `+ ${getTranslation(localizationKeys.buttons.newPrompt)}` })
}
onClick={handlePromptClick}
/>
diff --git a/src/content-scripts/api.ts b/src/content-scripts/api.ts
index 161257f..5cb8563 100644
--- a/src/content-scripts/api.ts
+++ b/src/content-scripts/api.ts
@@ -35,22 +35,23 @@ export async function getWebpageTitleAndText(url: string, html_str = ''): Promis
}
}
html = await response.text()
-
}
const doc = parseHTML(html).document
const parsed = new Readability(doc).parse()
- if (!parsed) {
- return { title: "Could not parse the page.", body: "", url }
+ if (!parsed || !parsed.textContent) {
+ return { title: "Could not parse the page.", body: "Could not parse the page.", url }
}
-
- let text = cleanText(parsed.textContent)
+ console.log("text", parsed.textContent);
+ let text = cleanText(parsed.textContent)
+
const userConfig = await getUserConfig()
- if (userConfig.trimLongText) {
- text = text.slice(0, 14500)
+ if (userConfig.trimLongText && text.length > 14400) {
+ text = text.slice(0, 14400)
+ text += "\n\n[Text has been trimmed to 14,500 characters. You can disable this on WebChatGPT's options page.]"
}
return { title: parsed.title, body: text, url }
}
diff --git a/src/content-scripts/ddg_search.ts b/src/content-scripts/ddg_search.ts
index 5412bab..dc61868 100644
--- a/src/content-scripts/ddg_search.ts
+++ b/src/content-scripts/ddg_search.ts
@@ -52,7 +52,7 @@ export async function getHtml({ query, timerange, region }: SearchRequest): Prom
}
function htmlToSearchResults(html: string, numResults: number): SearchResult[] {
- console.log("htmlToSearchResults", numResults)
+ // console.log("htmlToSearchResults", numResults)
const $ = cheerio.load(html)
const results: SearchResult[] = []
@@ -72,8 +72,8 @@ function htmlToSearchResults(html: string, numResults: number): SearchResult[] {
// Extract web search results
const upperBound = zeroClickLink.length > 0 ? numResults - 1 : numResults
- const webLinks = $(`table:nth-of-type(${numTables}) .result-link`).slice(0, upperBound)
- const webSnippets = $(`table:nth-of-type(${numTables}) .result-snippet`).slice(0, upperBound)
+ const webLinks = $(`table:nth-of-type(${numTables}) tr:not(.result-sponsored) .result-link`).slice(0, upperBound)
+ const webSnippets = $(`table:nth-of-type(${numTables}) tr:not(.result-sponsored) .result-snippet`).slice(0, upperBound)
webLinks.each((i, element) => {
const link = $(element)
const snippet = $(webSnippets[i]).text().trim()
diff --git a/src/content-scripts/mainUI.tsx b/src/content-scripts/mainUI.tsx
index 6490209..9b9750a 100644
--- a/src/content-scripts/mainUI.tsx
+++ b/src/content-scripts/mainUI.tsx
@@ -13,9 +13,9 @@ import { apiExtractText } from './api'
let isProcessing = false
-let btnSubmit: HTMLButtonElement
-let textarea: HTMLTextAreaElement
-let footer: HTMLDivElement
+let btnSubmit: HTMLButtonElement | null | undefined
+let textarea: HTMLTextAreaElement | null
+let chatGptFooter: HTMLDivElement | null
function renderSlashCommandsMenu() {
@@ -24,7 +24,7 @@ function renderSlashCommandsMenu() {
if (div) div.remove()
div = document.createElement('wcg-slash-commands-menu')
- const textareaParentParent = textarea.parentElement?.parentElement
+ const textareaParentParent = textarea?.parentElement?.parentElement
textareaParentParent?.insertBefore(div, textareaParentParent.firstChild)
render(
, div)
@@ -58,6 +58,8 @@ async function processQuery(query: string, userConfig: UserConfig) {
async function handleSubmit(query: string) {
+ if (!textarea) return
+
const userConfig = await getUserConfig()
if (!userConfig.webAccess) {
@@ -81,6 +83,9 @@ async function handleSubmit(query: string) {
}
async function onSubmit(event: MouseEvent | KeyboardEvent) {
+
+ if (!textarea) return
+
const isKeyEvent = event instanceof KeyboardEvent
if (isKeyEvent && event.shiftKey && event.key === 'Enter') return
@@ -88,14 +93,17 @@ async function onSubmit(event: MouseEvent | KeyboardEvent) {
if (isKeyEvent && event.key === 'Enter' && event.isComposing) return
if (!isProcessing && (event.type === "click" || (isKeyEvent && event.key === 'Enter'))) {
- const query = textarea.value.trim()
+ const query = textarea?.value.trim()
- if (query === "") return
+ // if query is empty or undefined, return
+ if (!query) return
textarea.value = ""
const isPartialCommand = slashCommands.some(command => command.name.startsWith(query) && query.length <= command.name.length)
- if (isPartialCommand) return
+ if (isPartialCommand) {
+ return
+ }
isProcessing = true
await handleSubmit(query)
@@ -104,14 +112,14 @@ async function onSubmit(event: MouseEvent | KeyboardEvent) {
}
function pressEnter() {
- textarea.focus()
+ textarea?.focus()
const enterEvent = new KeyboardEvent('keydown', {
bubbles: true,
cancelable: true,
key: 'Enter',
code: 'Enter'
})
- textarea.dispatchEvent(enterEvent)
+ textarea?.dispatchEvent(enterEvent)
}
function showErrorMessage(error: Error) {
@@ -124,59 +132,93 @@ function showErrorMessage(error: Error) {
async function updateUI() {
- if (getWebChatGPTToolbar()) return
+ formChild = document.querySelector('form')?.children[0] as HTMLElement
+ textarea = getTextArea()
+ // console.info("UpdateUI textarea: ", textarea)
+
+ const toolbar = getWebChatGPTToolbar()
+ if (!textarea) {
+ toolbar?.remove()
+ return
+ }
+
+ if (toolbar) return
+
+ console.info("WebChatGPT: Updating UI")
btnSubmit = getSubmitButton()
- textarea = getTextArea()
- footer = getFooter()
+ btnSubmit?.addEventListener("click", onSubmit)
- if (textarea && btnSubmit) {
+ textarea?.addEventListener("keydown", onSubmit)
- textarea.addEventListener("keydown", onSubmit)
- btnSubmit.addEventListener("click", onSubmit)
+ await renderToolbar()
- const textareaParentParent = textarea.parentElement?.parentElement
- if (textareaParentParent && textareaParentParent.parentElement) {
- textareaParentParent.style.flexDirection = 'column'
- textareaParentParent.parentElement.style.flexDirection = 'column'
- textareaParentParent.parentElement.style.gap = '0px'
- textareaParentParent.parentElement.style.marginBottom = '0.5em'
- }
+ renderSlashCommandsMenu()
- try {
- const { shadowRootDiv, shadowRoot } = await createShadowRoot('content-scripts/mainUI.css')
- shadowRootDiv.classList.add('wcg-toolbar')
- textareaParentParent?.appendChild(shadowRootDiv)
- render(
, shadowRoot)
- } catch (e) {
- if (e instanceof Error) {
- showErrorMessage(Error(`Error loading WebChatGPT toolbar: ${e.message}. Please reload the page (F5).`));
- console.error(e)
- }
- }
- // textarea.parentElement.style.flexDirection = 'row'
+ // textarea.parentElement.style.flexDirection = 'row'
- renderSlashCommandsMenu()
+ chatGptFooter = getFooter()
+ if (chatGptFooter) {
+ const lastChild = chatGptFooter.lastElementChild as HTMLElement
+ if (lastChild) lastChild.style.padding = '0 0 0.5em 0'
}
+}
- if (footer) {
- const lastChild = footer.lastElementChild as HTMLElement
- if (lastChild)
- lastChild.style.padding = '0 0 0.5em 0'
+async function renderToolbar() {
+
+ try {
+ const textareaParentParent = textarea?.parentElement?.parentElement
+ // const textareaParentParent = formChild
+ // if (textareaParentParent && textareaParentParent.parentElement) {
+ // textareaParentParent.style.flexDirection = 'column'
+ // textareaParentParent.parentElement.style.flexDirection = 'column'
+ // textareaParentParent.parentElement.style.gap = '0px'
+ // textareaParentParent.parentElement.style.marginBottom = '0.5em'
+ // }
+
+ const { shadowRootDiv, shadowRoot } = await createShadowRoot('content-scripts/mainUI.css')
+ shadowRootDiv.classList.add('wcg-toolbar')
+ textareaParentParent?.appendChild(shadowRootDiv)
+ render(
, shadowRoot)
+
+ } catch (e) {
+ if (e instanceof Error) {
+ showErrorMessage(Error(`Error loading WebChatGPT toolbar: ${e.message}. Please reload the page (F5).`))
+ }
}
}
-const rootEl = getRootElement()
-window.onload = function () {
- updateUI()
+const form = document.querySelector('form')
+const formParent = form?.parentElement
+const rootEl = getRootElement()
+let formChild = document.querySelector('form')?.children[0] as HTMLElement
+const mutationObserver = new MutationObserver(() => {
try {
- new MutationObserver(() => {
- updateUI()
- }).observe(rootEl, { childList: true })
+ updateUI()
} catch (e) {
if (e instanceof Error) {
showErrorMessage(e)
}
}
+})
+
+window.onload = function () {
+ updateUI()
+
+ if (formChild) {
+ mutationObserver.observe(formChild, { childList: true })
+ }
+
+ if (rootEl) {
+ mutationObserver.observe(rootEl, { childList: true })
+ }
+
+ if (formParent) {
+ mutationObserver.observe(formParent, { childList: true })
+ }
+}
+
+window.onunload = function () {
+ mutationObserver.disconnect()
}
diff --git a/src/manifest.json b/src/manifest.json
index ca03c92..fa2f1f4 100644
--- a/src/manifest.json
+++ b/src/manifest.json
@@ -3,7 +3,7 @@
"name": "__MSG_appName__",
"description": "__MSG_appDesc__",
"default_locale": "en",
- "version": "3.2.5",
+ "version": "3.2.6",
"icons": {
"16": "icons/icon16.png",
"48": "icons/icon48.png",
diff --git a/src/manifest.v2.json b/src/manifest.v2.json
index 6171e35..9c2efa6 100644
--- a/src/manifest.v2.json
+++ b/src/manifest.v2.json
@@ -3,7 +3,7 @@
"name": "__MSG_appName__",
"description": "__MSG_appDesc__",
"default_locale": "en",
- "version": "3.2.5",
+ "version": "3.2.6",
"icons": {
"16": "icons/icon16.png",
"48": "icons/icon48.png",