Skip to content

Commit

Permalink
fix: stabilize menu injection
Browse files Browse the repository at this point in the history
  • Loading branch information
pionxzh committed Dec 21, 2022
1 parent ca633f6 commit 224a51f
Show file tree
Hide file tree
Showing 5 changed files with 168 additions and 124 deletions.
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,15 @@
},
"devDependencies": {
"@pionxzh/eslint-config-ts": "^0.1.1",
"@types/node": "^18.11.10",
"@types/node": "^18.11.17",
"cpy-cli": "^4.2.0",
"eslint": "^8.29.0",
"eslint": "^8.30.0",
"husky": "^8.0.2",
"lint-staged": "^13.1.0",
"rimraf": "^3.0.2",
"sass": "^1.56.1",
"sass": "^1.57.0",
"turbo": "^1.6.3",
"typescript": "^4.9.3"
"typescript": "^4.9.4"
},
"lint-staged": {
"*.{js,jsx,ts,tsx}": "pnpm exec eslint"
Expand Down
3 changes: 2 additions & 1 deletion packages/userscript/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
},
"dependencies": {
"html2canvas": "^1.4.1",
"vite-plugin-monkey": "^2.7.3"
"sentinel-js": "^0.0.5",
"vite-plugin-monkey": "^2.10.0"
},
"devDependencies": {
"vite": "^3.1.4"
Expand Down
56 changes: 44 additions & 12 deletions packages/userscript/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import html2canvas from 'html2canvas'
import sentinel from 'sentinel-js'
import { chatGPTAvatarSVG, fileCode, iconCamera, iconCopy } from './icons'
import { copyToClipboard, downloadFile, downloadUrl, escapeHtml, getBase64FromImg, onloadSafe, sleep, timestamp } from './utils'
import templateHtml from './template.html?raw'
Expand All @@ -24,18 +25,13 @@ main()

function main() {
onloadSafe(() => {
const firstMenuItem = document.querySelector('nav > a')
const container = firstMenuItem?.parentElement
if (!firstMenuItem || !container) {
console.error('Failed to locate the menu container element.')
// alert('Failed to locate the menu container element. Please report this issue to the developer.')
const nav = document.querySelector('nav')
if (!nav) {
console.error('Failed to locate the nav element. Please report this issue to the developer.')
// alert('Failed to locate the nav element. Please report this issue to the developer.')
return
}

const divider = document.createElement('div')
divider.className = 'border-b border-white/20'
divider.style.marginBottom = '0.5rem'

const copyHtml = `${iconCopy}Copy Text`
const copiedHtml = `${iconCopy}Copied`
const onCopyText = (e: MouseEvent) => {
Expand All @@ -52,16 +48,52 @@ function main() {
}, 3000)
}

const divider = createDivider()
const textExport = createMenuItem(iconCopy, 'Copy Text', onCopyText)
const pngExport = createMenuItem(iconCamera, 'Screenshot', exportToPng)
const htmlExport = createMenuItem(fileCode, 'Export WebPage', exportToHtml)
firstMenuItem.after(divider, textExport, pngExport, htmlExport)
const container = createMenuContainer()
container.append(textExport, pngExport, htmlExport, divider)
})
}

function createMenuContainer() {
const container = document.createElement('div')
container.id = 'exporter-menu'
container.className = 'pt-1'

const chatList = document.querySelector('nav > div')
if (chatList) {
chatList.after(container)
sentinel.on('nav > div.overflow-y-auto', (el) => {
const nav = document.querySelector('nav')!
if (container.parentElement !== nav) {
el.after(container)
}
})
}
else {
const nav = document.querySelector('nav')!
nav.append(container)
sentinel.on('nav', (el) => {
if (container.parentElement !== nav) {
el.append(container)
}
})
}

return container
}

function createDivider() {
const divider = document.createElement('div')
divider.className = 'border-b border-white/20'
return divider
}

function createMenuItem(icon: string, title: string, onClick: (e: MouseEvent) => void) {
const firstMenuItem = document.querySelector('nav > a')!
const menuItem = firstMenuItem.cloneNode(true) as HTMLAnchorElement
const menuItem = document.createElement('a')
menuItem.className = 'flex py-3 px-3 items-center gap-3 rounded-md hover:bg-gray-500/10 transition-colors duration-200 text-white cursor-pointer text-sm mb-2 flex-shrink-0 border border-white/20'
menuItem.removeAttribute('href')
menuItem.innerHTML = `${icon}${title}`
menuItem.addEventListener('click', onClick)
Expand Down
5 changes: 5 additions & 0 deletions packages/userscript/src/sentinel-js.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
declare module 'sentinel-js' {
export function on<T = HTMLElement>(cssSelectors: string | string[], callback: (el: T) => void): void
export function off<T = HTMLElement>(event: string | string[], callback: (el: T) => void): void
export function reset(): void
}
Loading

1 comment on commit 224a51f

@Notarin
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Such an awesome commit, I was just about to make an issue for this, but clearly you were one step ahead of me.

Please sign in to comment.