0
0
mirror of https://github.com/go-gitea/gitea.git synced 2026-05-11 20:05:38 +02:00

Address Copilot review on attachSearchBox

- hide() also cancels the pending debounced search so a fetch scheduled
  before blur/Escape/outside-click does not fire afterwards and re-show
  the dropdown on a field the user has already left
- use urlQueryEscape for the {query} substitution to keep escaping
  symmetric with the Go backend (matches Go's url.QueryEscape: space → +,
  strict RFC 3986 for !'()*); both decoders still accept %20

Co-Authored-By: Claude (Opus 4.7) <noreply@anthropic.com>
This commit is contained in:
silverwind 2026-04-27 02:08:02 +02:00
parent 6b7c386452
commit 73d7f6867a
No known key found for this signature in database
GPG Key ID: 2E62B41C93869443

View File

@ -1,6 +1,7 @@
import {debounce} from 'throttle-debounce';
import {GET} from './fetch.ts';
import {html, htmlRaw} from '../utils/html.ts';
import {urlQueryEscape} from '../utils/url.ts';
export type SearchResult = {
title: string;
@ -34,8 +35,10 @@ export function attachSearchBox<T = unknown>(container: HTMLElement, url: string
}
const itemResults = new Map<HTMLElement, SearchResult>();
let fetchController: AbortController | null = null;
let search: ReturnType<typeof debounce<(query: string) => Promise<void>>> | null = null;
const hide = () => {
search?.cancel();
fetchController?.abort();
resultsEl.style.display = 'none';
resultsEl.replaceChildren();
@ -59,12 +62,12 @@ export function attachSearchBox<T = unknown>(container: HTMLElement, url: string
hide();
};
const search = debounce(200, async (query: string) => {
search = debounce(200, async (query: string) => {
fetchController?.abort();
if (query.length < minCharacters) return hide();
const ctrl = (fetchController = new AbortController());
try {
const response = await GET(url.replaceAll('{query}', encodeURIComponent(query)), {signal: ctrl.signal});
const response = await GET(url.replaceAll('{query}', urlQueryEscape(query)), {signal: ctrl.signal});
if (!response.ok) return hide();
const results = parse(await response.json(), query);
// hide() ran (signal aborted) or a newer keystroke landed before the response did