From 3b86fab35a089133d115d7be4db64712e69d931a Mon Sep 17 00:00:00 2001 From: undefined Date: Wed, 9 Jul 2025 02:13:47 +0800 Subject: [PATCH] ui: use clipboard instead of html5 api --- .../ui-default/pages/problem_main.page.tsx | 44 +++++++++++++------ 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/packages/ui-default/pages/problem_main.page.tsx b/packages/ui-default/pages/problem_main.page.tsx index 3440841ea..fe30acfce 100644 --- a/packages/ui-default/pages/problem_main.page.tsx +++ b/packages/ui-default/pages/problem_main.page.tsx @@ -1,4 +1,5 @@ import parser, { SearchParserResult } from '@hydrooj/utils/lib/search'; +import Clipboard from 'clipboard'; import $ from 'jquery'; import _ from 'lodash'; import React from 'react'; @@ -288,6 +289,9 @@ function processElement(ele) { function ProblemSelectionDisplay(props) { // eslint-disable-line const [pids, setPids] = React.useState([]); const [dialogOpen, setDialogOpen] = React.useState(false); + const [copyIdRef, setCopyIdRef] = React.useState(null); + const [copyPidRef, setCopyPidRef] = React.useState(null); + const problemSelectAutoCompleteRef = React.useRef(null); React.useEffect(() => { props.onClear?.(() => { @@ -319,18 +323,30 @@ function ProblemSelectionDisplay(props) { // eslint-disable-line (window as any).__getPids = () => pids; (window as any).__setPids = (newIds: string[]) => setPids(newIds); }, [pids]); - - const problemSelectAutoCompleteRef = React.useRef(null); - const copyIds = React.useCallback(async () => { - await navigator.clipboard.writeText(pids.join(',')); - Notification.success(i18n('Problem ids copied to clipboard!')); - problemSelectAutoCompleteRef.current.getSelectedItems(); - }, [pids]); - const copyPids = React.useCallback(async () => { - const items = problemSelectAutoCompleteRef.current.getSelectedItems(); - await navigator.clipboard.writeText(items.map((i) => i.pid || i.docId).join(',')); - Notification.success(i18n('Problem ids copied to clipboard!')); - }, [pids]); + React.useEffect(() => { + if (!copyIdRef) return; + const clip = new Clipboard(copyIdRef, { + text: () => problemSelectAutoCompleteRef.current.getSelectedItems().map((i) => i.docId).join(','), + }); + clip.on('success', () => { + Notification.success(i18n('Problem ids copied to clipboard!')); + }); + clip.on('error', () => { + Notification.error(i18n('Copy failed :(')); + }); + }, [copyIdRef]); + React.useEffect(() => { + if (!copyPidRef) return; + const clip = new Clipboard(copyPidRef, { + text: () => problemSelectAutoCompleteRef.current.getSelectedItems().map((i) => i.pid || i.docId).join(','), + }); + clip.on('success', () => { + Notification.success(i18n('Problem ids copied to clipboard!')); + }); + clip.on('error', () => { + Notification.error(i18n('Copy failed :(')); + }); + }, [copyPidRef]); const updateCheckboxSelection = React.useCallback(() => { for (const i of $('[data-checkbox-group="problem"]:checked')) { @@ -380,8 +396,8 @@ function ProblemSelectionDisplay(props) { // eslint-disable-line
- {' '} - {' '} + {' '} + {' '} {' '}