mirror of
https://github.com/pionxzh/chatgpt-exporter.git
synced 2026-09-21 13:37:42 -05:00
feat: remove copy button in chat in favor of the built-in copy button
This commit is contained in:
@@ -5,7 +5,6 @@ import { fetchConversation, processConversation } from './api'
|
||||
import { KEY_FILENAME_FORMAT, LEGACY_KEY_FILENAME_FORMAT } from './constants'
|
||||
import { getChatIdFromUrl, getConversationChoice } from './page'
|
||||
import { Menu } from './ui/Menu'
|
||||
import { SecondaryToolbar } from './ui/SecondaryToolbar'
|
||||
import { onloadSafe } from './utils/utils'
|
||||
|
||||
import './i18n'
|
||||
@@ -74,20 +73,6 @@ function main() {
|
||||
}
|
||||
})
|
||||
|
||||
/** Insert copy button to the next of feedback buttons */
|
||||
sentinel.on('main .flex.justify-between', (node) => {
|
||||
if (!node.querySelector('button')) return
|
||||
// ignore codeblock
|
||||
if (node.closest('pre')) return
|
||||
|
||||
const secondaryToolbar = document.createElement('div')
|
||||
secondaryToolbar.className = 'w-full secondary-toolbar'
|
||||
const threads = Array.from(document.querySelectorAll('main .group'))
|
||||
const index = threads.indexOf(node.closest('.group')!)
|
||||
render(<SecondaryToolbar index={index} />, secondaryToolbar)
|
||||
node.append(secondaryToolbar)
|
||||
})
|
||||
|
||||
/** Insert timestamp to the bottom right of each message */
|
||||
let chatId = ''
|
||||
sentinel.on('main .group', async () => {
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
.invisible + .secondary-toolbar {
|
||||
display: none;
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
import { useState } from 'preact/hooks'
|
||||
import { exportToTextFromIndex } from '../exporter/text'
|
||||
import { IconCheck, IconCopy, IconLoading } from './Icons'
|
||||
|
||||
import './SecondaryToolbar.css'
|
||||
|
||||
const TIMEOUT = 2500
|
||||
|
||||
export const SecondaryToolbar = ({ index }: { index: number }) => {
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [succeed, setSucceed] = useState(false)
|
||||
|
||||
const handleClick = async () => {
|
||||
try {
|
||||
setLoading(true)
|
||||
const result = await exportToTextFromIndex(index)
|
||||
if (result) {
|
||||
setSucceed(true)
|
||||
setTimeout(() => setSucceed(false), TIMEOUT)
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex w-full ml-4 mt-2 absolute lg:translate-x-full lg:right-0 lg:pl-2 lg:mt-0 lg:top-8">
|
||||
{ loading
|
||||
? <IconLoading className="w-6 h-6 text-gray-500 dark:text-gray-400" style={{ padding: 5 }} />
|
||||
: succeed
|
||||
? <IconCheck className="w-6 h-6 text-gray-500 dark:text-gray-400" style={{ padding: 3 }} />
|
||||
: (
|
||||
<button
|
||||
onClick={handleClick}
|
||||
className="p-1 rounded-md hover:bg-gray-100 hover:text-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-gray-200"
|
||||
>
|
||||
<IconCopy className="w-4 h-4 text-gray-400 dark:text-gray-400" />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user