From 594a25ace1027a11bab8826eef8e604246403d29 Mon Sep 17 00:00:00 2001 From: undefined Date: Tue, 14 Oct 2025 08:15:09 +0800 Subject: [PATCH] ui: make sure objective problem navigation only render once --- .../ui-default/pages/problem_detail.page.tsx | 57 +++++++++++-------- 1 file changed, 34 insertions(+), 23 deletions(-) diff --git a/packages/ui-default/pages/problem_detail.page.tsx b/packages/ui-default/pages/problem_detail.page.tsx index 94b502608..6c32dc599 100644 --- a/packages/ui-default/pages/problem_detail.page.tsx +++ b/packages/ui-default/pages/problem_detail.page.tsx @@ -239,15 +239,6 @@ const page = new NamedPage(['problem_detail', 'contest_detail_problem', 'homewor if (UiContext.tdoc?._id && UiContext.tdoc.rule !== 'homework') cacheKey += `@${UiContext.tdoc._id}`; let setUpdate; - function ProblemNavigation() { - [, setUpdate] = React.useState(0); - return
- {pids.map((i) => - {i} - )} -
; - } - const db = await openDB; async function saveAns() { await db.put('solutions', { @@ -256,9 +247,36 @@ const page = new NamedPage(['problem_detail', 'contest_detail_problem', 'homewor }); } async function clearAns() { + if (!(await confirm(i18n('All changes will be lost. Are you sure to clear all answers?')))) return; await db.delete('solutions', `${cacheKey}#objective`); window.location.reload(); } + + function ProblemNavigation() { + [, setUpdate] = React.useState(0); + const update = React.useCallback(() => { setUpdate?.((v) => v + 1); }, []); + React.useEffect(() => { + $(document).on('click', update); + $(document).on('input', update); + return () => { + $(document).off('click', update); + $(document).off('input', update); + }; + }, [update]); + return <> +
+ {pids.map((i) => + {i} + )} +
+
  • + +
  • + ; + } + async function loadAns() { const saved = await db.get('solutions', `${cacheKey}#objective`); if (typeof saved?.value !== 'string') return; @@ -279,7 +297,7 @@ const page = new NamedPage(['problem_detail', 'contest_detail_problem', 'homewor if (cnt) { await loadAns(); - $('.problem-content .typo').append(document.getElementsByClassName('nav__item--round').length + $('.problem-content .typo').append(!document.getElementsByClassName('nav__item--round').length ? `` : ``); $('.objective-input[type!=checkbox]').on('input', (e: JQuery.TriggeredEvent) => { @@ -310,23 +328,16 @@ const page = new NamedPage(['problem_detail', 'contest_detail_problem', 'homewor Notification.error(err.message); }); }); - $('.section--problem-sidebar ol.menu').prepend(tpl(
  • - - {i18n('Clear answers')} - -
  • )); - $(document).on('click', '#clearAnswers', async () => { - if (await confirm(i18n('All changes will be lost. Are you sure to clear all answers?'))) await clearAns(); - }); } - const ele = document.createElement('div'); - $('.section--problem-sidebar ol.menu').prepend(ele); - createRoot(ele).render(); + if (!document.getElementById('problem-navigation')) { + const ele = document.createElement('div'); + ele.id = 'problem-navigation'; + $('.section--problem-sidebar ol.menu').prepend(ele); + createRoot(document.getElementById('problem-navigation')).render(); + } $('.non-scratchpad--hide').hide(); $('.scratchpad--hide').hide(); $('.outer-loader-container').hide(); - $(document).on('click', () => { setUpdate?.((v) => v + 1); }); - $(document).on('input', () => { setUpdate?.((v) => v + 1); }); } $(document).on('click', '[name="problem-sidebar__open-scratchpad"]', (ev) => {