Skip to content

Commit

Permalink
Merge pull request #152 from qunash/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
qunash authored Apr 20, 2023
2 parents 31566a8 + 0386255 commit efc097e
Show file tree
Hide file tree
Showing 12 changed files with 124 additions and 79 deletions.
3 changes: 2 additions & 1 deletion .hintrc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"development"
],
"hints": {
"axe/forms": "off"
"axe/forms": "off",
"no-inline-styles": "off"
}
}
Binary file not shown.
Binary file not shown.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"private": true,
"name": "webchatgpt",
"version": "3.2.5",
"version": "3.2.6",
"license": "MIT",
"scripts": {
"build-dev": "node build.mjs",
Expand Down
4 changes: 2 additions & 2 deletions src/components/errorMessage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ function ErrorMessage(props: { message: string }): h.JSX.Element | null {

return (
// <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">
<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">
<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">
<b>An error occurred</b><br />
{props.message}<br /><br />
Please Check the console for more details. (Ctrl+Shift+J)
You can check the console for more details. (Ctrl+Shift+J)
</div>
)
}
Expand Down
4 changes: 2 additions & 2 deletions src/components/footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ function Footer() {

return (
<div className="wcg-text-center wcg-text-xs wcg-text-gray-400">
<a href='https://github.com/qunash/chatgpt-advanced' target='_blank' className='underline wcg-text-gray-400 wcg-underline' rel="noreferrer">
<a href='https://github.com/qunash/chatgpt-advanced' target='_blank' className='underline wcg-text-gray-400 wcg-underline' rel="noreferrer noopener">
WebChatGPT extension v.{extension_version}
</a>.
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>.
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>.
</div>
)
}
Expand Down
33 changes: 17 additions & 16 deletions src/components/toolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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('')
Expand Down Expand Up @@ -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 = () => {
Expand All @@ -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

Expand Down Expand Up @@ -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}
/>
Expand Down
15 changes: 8 additions & 7 deletions src/content-scripts/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
}
Expand Down
6 changes: 3 additions & 3 deletions src/content-scripts/ddg_search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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[] = []

Expand All @@ -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()
Expand Down
132 changes: 87 additions & 45 deletions src/content-scripts/mainUI.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -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(<SlashCommandsMenu textarea={textarea} />, div)
Expand Down Expand Up @@ -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) {
Expand All @@ -81,21 +83,27 @@ 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

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)
Expand All @@ -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) {
Expand All @@ -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(<Toolbar textarea={textarea} />, 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(<Toolbar textarea={textarea} />, 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()
}
Loading

0 comments on commit efc097e

Please sign in to comment.