vomebook commited on
Commit
76e2ea5
·
1 Parent(s): 8db8e95

Upload 2 files

Browse files
Files changed (2) hide show
  1. static/app.js +57 -1
  2. static/style.css +34 -0
static/app.js CHANGED
@@ -250,6 +250,17 @@ function saveHistory(items) {
250
  localStorage.setItem(HISTORY_KEY, JSON.stringify(items.slice(0, 20)));
251
  }
252
 
 
 
 
 
 
 
 
 
 
 
 
253
  function addHistory(query) {
254
  if (!STATE.historyEnabled || !query) return;
255
  const items = getHistory().filter((item) => item !== query);
@@ -263,7 +274,11 @@ function renderHistoryDropdown() {
263
  DOM.searchHistoryDropdown.style.display = "none";
264
  return;
265
  }
266
- DOM.searchHistoryDropdown.innerHTML = items.map((item) => `<div class="history-item" data-query="${escapeHTML(item)}"><span class="history-text">${escapeHTML(item)}</span></div>`).join("");
 
 
 
 
267
  DOM.searchHistoryDropdown.style.display = "";
268
  }
269
 
@@ -687,6 +702,17 @@ function attachEvents() {
687
  DOM.searchInput.addEventListener("focus", renderHistoryDropdown);
688
  DOM.searchInput.addEventListener("blur", () => setTimeout(() => { DOM.searchHistoryDropdown.style.display = "none"; }, 100));
689
  DOM.searchHistoryDropdown.addEventListener("click", (event) => {
 
 
 
 
 
 
 
 
 
 
 
690
  const item = event.target.closest("[data-query]");
691
  if (!item) return;
692
  DOM.searchInput.value = item.dataset.query;
@@ -694,6 +720,35 @@ function attachEvents() {
694
  syncUrl();
695
  doSearch();
696
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
697
  let timer = null;
698
  DOM.searchInput.addEventListener("input", () => {
699
  clearTimeout(timer);
@@ -701,6 +756,7 @@ function attachEvents() {
701
  STATE.query = DOM.searchInput.value.trim();
702
  STATE.page = 1;
703
  addHistory(STATE.query);
 
704
  syncUrl();
705
  doSearch();
706
  }, 250);
 
250
  localStorage.setItem(HISTORY_KEY, JSON.stringify(items.slice(0, 20)));
251
  }
252
 
253
+ function removeHistory(query) {
254
+ const items = getHistory().filter((item) => item !== query);
255
+ saveHistory(items);
256
+ renderHistoryDropdown();
257
+ }
258
+
259
+ function clearHistory() {
260
+ saveHistory([]);
261
+ renderHistoryDropdown();
262
+ }
263
+
264
  function addHistory(query) {
265
  if (!STATE.historyEnabled || !query) return;
266
  const items = getHistory().filter((item) => item !== query);
 
274
  DOM.searchHistoryDropdown.style.display = "none";
275
  return;
276
  }
277
+ DOM.searchHistoryDropdown.innerHTML = items.map((item) => `
278
+ <div class="history-item" data-query="${escapeHTML(item)}">
279
+ <span class="history-text">${escapeHTML(item)}</span>
280
+ <button type="button" class="history-del" data-del="${escapeHTML(item)}" aria-label="删除历史">×</button>
281
+ </div>`).join("") + '<div class="history-footer"><button type="button" class="history-clear-all">清空历史</button></div>';
282
  DOM.searchHistoryDropdown.style.display = "";
283
  }
284
 
 
702
  DOM.searchInput.addEventListener("focus", renderHistoryDropdown);
703
  DOM.searchInput.addEventListener("blur", () => setTimeout(() => { DOM.searchHistoryDropdown.style.display = "none"; }, 100));
704
  DOM.searchHistoryDropdown.addEventListener("click", (event) => {
705
+ const delBtn = event.target.closest(".history-del");
706
+ if (delBtn) {
707
+ event.stopPropagation();
708
+ removeHistory(delBtn.dataset.del);
709
+ return;
710
+ }
711
+ const clearBtn = event.target.closest(".history-clear-all");
712
+ if (clearBtn) {
713
+ clearHistory();
714
+ return;
715
+ }
716
  const item = event.target.closest("[data-query]");
717
  if (!item) return;
718
  DOM.searchInput.value = item.dataset.query;
 
720
  syncUrl();
721
  doSearch();
722
  });
723
+ let historyLongPressTimer = null;
724
+ const cancelHistoryLongPress = () => {
725
+ if (historyLongPressTimer) {
726
+ clearTimeout(historyLongPressTimer);
727
+ historyLongPressTimer = null;
728
+ }
729
+ };
730
+ DOM.searchHistoryDropdown.addEventListener("mousedown", (event) => {
731
+ const item = event.target.closest("[data-query]");
732
+ if (!item || event.target.closest(".history-del") || event.target.closest(".history-clear-all")) return;
733
+ cancelHistoryLongPress();
734
+ historyLongPressTimer = setTimeout(() => {
735
+ removeHistory(item.dataset.query);
736
+ historyLongPressTimer = null;
737
+ }, 600);
738
+ });
739
+ DOM.searchHistoryDropdown.addEventListener("mouseup", cancelHistoryLongPress);
740
+ DOM.searchHistoryDropdown.addEventListener("mouseleave", cancelHistoryLongPress);
741
+ DOM.searchHistoryDropdown.addEventListener("touchstart", (event) => {
742
+ const item = event.target.closest("[data-query]");
743
+ if (!item || event.target.closest(".history-del") || event.target.closest(".history-clear-all")) return;
744
+ cancelHistoryLongPress();
745
+ historyLongPressTimer = setTimeout(() => {
746
+ removeHistory(item.dataset.query);
747
+ historyLongPressTimer = null;
748
+ }, 650);
749
+ }, { passive: true });
750
+ DOM.searchHistoryDropdown.addEventListener("touchend", cancelHistoryLongPress, { passive: true });
751
+ DOM.searchHistoryDropdown.addEventListener("touchmove", cancelHistoryLongPress, { passive: true });
752
  let timer = null;
753
  DOM.searchInput.addEventListener("input", () => {
754
  clearTimeout(timer);
 
756
  STATE.query = DOM.searchInput.value.trim();
757
  STATE.page = 1;
758
  addHistory(STATE.query);
759
+ renderHistoryDropdown();
760
  syncUrl();
761
  doSearch();
762
  }, 250);
static/style.css CHANGED
@@ -307,6 +307,40 @@ ul, li {
307
  text-overflow: ellipsis;
308
  white-space: nowrap;
309
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
310
  .search-history-dropdown .history-del {
311
  flex-shrink: 0;
312
  background: none;
 
307
  text-overflow: ellipsis;
308
  white-space: nowrap;
309
  }
310
+ .search-history-dropdown .history-del {
311
+ flex-shrink: 0;
312
+ width: 22px;
313
+ height: 22px;
314
+ border-radius: 999px;
315
+ color: var(--on-surface-variant);
316
+ display: inline-flex;
317
+ align-items: center;
318
+ justify-content: center;
319
+ font-size: 14px;
320
+ opacity: 0.65;
321
+ }
322
+ .search-history-dropdown .history-del:hover,
323
+ .search-history-dropdown .history-del:focus-visible {
324
+ background: var(--surface-variant);
325
+ color: var(--primary);
326
+ opacity: 1;
327
+ }
328
+ .search-history-dropdown .history-footer {
329
+ padding: 6px 12px;
330
+ border-top: 1px solid var(--outline-variant);
331
+ display: flex;
332
+ justify-content: center;
333
+ }
334
+ .search-history-dropdown .history-clear-all {
335
+ font-size: 12px;
336
+ color: var(--primary);
337
+ padding: 4px 8px;
338
+ border-radius: 6px;
339
+ }
340
+ .search-history-dropdown .history-clear-all:hover,
341
+ .search-history-dropdown .history-clear-all:focus-visible {
342
+ background: var(--surface-variant);
343
+ }
344
  .search-history-dropdown .history-del {
345
  flex-shrink: 0;
346
  background: none;