mirror of
https://mirror.skon.top/github.com/langgenius/dify.git
synced 2026-04-30 17:50:29 +08:00
fix(web): restore "Copied" feedback state on copy buttons (#35513)
This commit is contained in:
@@ -40,11 +40,11 @@ describe('CopyFeedback', () => {
|
||||
expect(mockCopy).toHaveBeenCalledWith('test content')
|
||||
})
|
||||
|
||||
it('calls reset on mouse leave', () => {
|
||||
it('does not reset on mouse leave (relies on hook timeout)', () => {
|
||||
render(<CopyFeedback content="test content" />)
|
||||
const button = screen.getByRole('button')
|
||||
fireEvent.mouseLeave(button.firstChild as Element)
|
||||
expect(mockReset).toHaveBeenCalledTimes(1)
|
||||
expect(mockReset).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -88,11 +88,11 @@ describe('CopyFeedbackNew', () => {
|
||||
expect(mockCopy).toHaveBeenCalledWith('test content')
|
||||
})
|
||||
|
||||
it('calls reset on mouse leave', () => {
|
||||
it('does not reset on mouse leave (relies on hook timeout)', () => {
|
||||
const { container } = render(<CopyFeedbackNew content="test content" />)
|
||||
const clickableArea = container.querySelector('.cursor-pointer')!.firstChild as HTMLElement
|
||||
fireEvent.mouseLeave(clickableArea)
|
||||
expect(mockReset).toHaveBeenCalledTimes(1)
|
||||
expect(mockReset).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -19,7 +19,10 @@ const prefixEmbedded = 'overview.appInfo.embedded'
|
||||
|
||||
const CopyFeedback = ({ content }: Props) => {
|
||||
const { t } = useTranslation()
|
||||
const { copied, copy, reset } = useClipboard()
|
||||
// Rely on useClipboard's own timer to flip `copied` back to false so the
|
||||
// "Copied" tooltip stays visible long enough to be read, matching the
|
||||
// KeyValueItem pattern. Do NOT reset on mouse leave.
|
||||
const { copied, copy } = useClipboard({ timeout: 2000 })
|
||||
|
||||
const tooltipText = copied
|
||||
? t(`${prefixEmbedded}.copied`, { ns: 'appOverview' })
|
||||
@@ -36,10 +39,7 @@ const CopyFeedback = ({ content }: Props) => {
|
||||
popupContent={safeText}
|
||||
>
|
||||
<ActionButton>
|
||||
<div
|
||||
onClick={handleCopy}
|
||||
onMouseLeave={reset}
|
||||
>
|
||||
<div onClick={handleCopy}>
|
||||
{copied && <RiClipboardFill className="h-4 w-4" />}
|
||||
{!copied && <RiClipboardLine className="h-4 w-4" />}
|
||||
</div>
|
||||
@@ -52,7 +52,7 @@ export default CopyFeedback
|
||||
|
||||
export const CopyFeedbackNew = ({ content, className }: Pick<Props, 'className' | 'content'>) => {
|
||||
const { t } = useTranslation()
|
||||
const { copied, copy, reset } = useClipboard()
|
||||
const { copied, copy } = useClipboard({ timeout: 2000 })
|
||||
|
||||
const tooltipText = copied
|
||||
? t(`${prefixEmbedded}.copied`, { ns: 'appOverview' })
|
||||
@@ -73,7 +73,6 @@ export const CopyFeedbackNew = ({ content, className }: Pick<Props, 'className'
|
||||
>
|
||||
<div
|
||||
onClick={handleCopy}
|
||||
onMouseLeave={reset}
|
||||
className={`h-full w-full ${copyStyle.copyIcon} ${copied ? copyStyle.copied : ''}`}
|
||||
>
|
||||
</div>
|
||||
|
||||
@@ -43,12 +43,14 @@ export function useClipboard({
|
||||
const copy = useCallback(async (valueToCopy: string) => {
|
||||
try {
|
||||
await writeTextToClipboard(valueToCopy)
|
||||
handleCopyResult(true)
|
||||
}
|
||||
catch (e) {
|
||||
if (usePromptAsFallback) {
|
||||
try {
|
||||
// eslint-disable-next-line no-alert -- prompt as fallback in case of copy error
|
||||
window.prompt(promptFallbackText, valueToCopy)
|
||||
handleCopyResult(true)
|
||||
}
|
||||
catch (e2) {
|
||||
handleCopyError(e2 as Error)
|
||||
|
||||
Reference in New Issue
Block a user