AI_Assistant/content.js

116 lines
3.1 KiB
JavaScript

// Keep track of the current tooltip element
let currentTooltip = null
const removeTooltip = () => {
// Remove the current tooltip element, if there is one
if (currentTooltip) {
document.body.removeChild(currentTooltip)
currentTooltip = null
}
}
const addLoadingIcon = (tooltip) => {
// Create a loading element
let loadingElement = document.createElement("div")
loadingElement.classList.add("loading-ai-tooltip")
// Add a spinner animation to the loading element
let spinner = document.createElement("div")
spinner.classList.add("spinner-ai-tooltip")
loadingElement.appendChild(spinner)
// Add the loading element to the tooltip
tooltip.appendChild(loadingElement)
}
const handleRetryButtonClick = () => {
chrome.runtime.sendMessage({ retry: true })
}
const createButton = (text, callback) => {
let button = document.createElement("button")
button.innerText = text
button.onclick = callback
return button
}
const addButtons = (tooltip, apiResult) => {
let retryButton = createButton("Retry", handleRetryButtonClick)
let copyButton = createButton("Copy", () => { navigator.clipboard.writeText(apiResult) })
tooltip.appendChild(copyButton)
tooltip.appendChild(retryButton)
}
const addTooltip = (apiResult) => {
let tooltip = document.createElement("div")
tooltip.classList.add("ai-tooltip")
if (apiResult == 'loading') {
addLoadingIcon(tooltip)
} else {
tooltip.innerText = apiResult
addButtons(tooltip, apiResult)
}
document.body.appendChild(tooltip)
currentTooltip = tooltip
adjustTooltipPosition()
}
const adjustTooltipPosition = () => {
if (!currentTooltip) {
return
}
let rect = window.getSelection().getRangeAt(0).getBoundingClientRect()
currentTooltip.style.cssText = "top: " + rect.bottom + "px !important; left: " + rect.left + "px !important;"
}
const handleAPIResult = (apiResult) => {
removeTooltip()
addTooltip(apiResult)
}
const messageHandler = (message) => {
if (message.hasOwnProperty("removeTooltip")) {
removeTooltip()
} else {
console.log(message)
handleAPIResult(message.apiResult.trim())
}
}
const sendRuntimeMessage = () => {
let selectedText = window.getSelection().toString()
chrome.runtime.sendMessage({ selectedText: selectedText })
}
const debounce = (func, wait) => {
let timeout
return (...args) => {
const later = () => {
timeout = null
func(...args)
}
clearTimeout(timeout)
timeout = setTimeout(later, wait)
}
}
const handleScroll = () => {
setTimeout(adjustTooltipPosition, 300)
}
// Listen for messages from the background script
chrome.runtime.onMessage.addListener(messageHandler)
// Create a debounced version of the event listener
let debouncedSendRuntimeMessage = debounce(sendRuntimeMessage, 250)
// Add the debounced event listener
document.addEventListener("selectionchange", debouncedSendRuntimeMessage)
// Fix the position of the tooltip when the page is scrolled
window.addEventListener("wheel", handleScroll)