vomebook commited on
Commit
fcf504e
ยท
1 Parent(s): f997fa4

Upload 3 files

Browse files
Files changed (2) hide show
  1. static/app.js +34 -3
  2. static/index.html +10 -3
static/app.js CHANGED
@@ -61,6 +61,8 @@ const ICONS = {
61
  database: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" width="18" height="18"><ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M21 12c0 1.66-4 3-9 3s-9-1.34-9-3"/><path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5"/></svg>',
62
  };
63
 
 
 
64
  /* โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
65
  State
66
  โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• */
@@ -82,6 +84,7 @@ const STATE = {
82
  filterFolderSelfs: [],
83
  filterMinSize: null,
84
  filterMaxSize: null,
 
85
  leftSidebarOpen: true,
86
  rightSidebarOpen: false,
87
  isMobile: false,
@@ -258,6 +261,7 @@ function cacheDOM() {
258
  DOM.filterExtList = $("#filter-ext-list");
259
  DOM.filterMinSize = $("#filter-min-size");
260
  DOM.filterMaxSize = $("#filter-max-size");
 
261
  DOM.filterMinUnit = $("#filter-min-unit");
262
  DOM.filterMaxUnit = $("#filter-max-unit");
263
  DOM.closeFiltersBtn = $("#close-filters-btn");
@@ -325,6 +329,25 @@ function highlightText(text, query) {
325
  return result;
326
  }
327
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
328
  /* โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
329
  API Client
330
  โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• */
@@ -413,6 +436,7 @@ const ROUTER = {
413
  if (STATE.filterMinSize !== null) params.set("min_size", fmtSizeUrl(STATE.filterMinSize));
414
  if (STATE.filterMaxSize !== null) params.set("max_size", fmtSizeUrl(STATE.filterMaxSize));
415
  if (!STATE.recordHistory) params.set("history", "0");
 
416
  if (DOM.sortSelect.value !== "relevance") params.set("sort", DOM.sortSelect.value);
417
  if (!STATE.searchFolders) params.set("search_folders", "false");
418
  if (STATE.exact) params.set("exact", "1");
@@ -578,6 +602,8 @@ function syncURLToState() {
578
 
579
  STATE.recordHistory = params.get("history") !== "0";
580
  if (DOM.historyToggle) DOM.historyToggle.checked = STATE.recordHistory;
 
 
581
 
582
  if (params.get("wide") === "1") {
583
  DOM.leftSidebar.classList.add("expanded-wide");
@@ -743,9 +769,9 @@ function renderResults(newItems) {
743
  </div>
744
  </div>
745
  <div class="result-actions">
746
- <button class="result-action-btn" data-action="copy" data-link="${escapeHTML(rec.Link)}">ๅคๅˆถ้“พๆŽฅ</button>
747
  <a href="/api/download?file=${encodeURIComponent(rec.File + (rec.Extension ? '.' + rec.Extension : ''))}&link=${encodeURIComponent(rec.Link)}" class="result-action-btn primary">ไธ‹่ฝฝ</a>
748
- <a href="${escapeHTML(rec.Path)}" class="result-action-btn" target="_blank">ไป“ๅบ“ๆŸฅ็œ‹</a>
749
  ${rec.HasTxt ? `<button class="result-action-btn" data-action="read" data-link="${escapeHTML(rec.Link)}" data-repo="${repoShort}">ๅœจ็บฟ้˜…่ฏป</button>` : ""}
750
  </div>`;
751
  fragment.appendChild(item);
@@ -1601,6 +1627,11 @@ async function init() {
1601
  STATE.recordHistory = DOM.historyToggle.checked;
1602
  if (!STATE.recordHistory) saveHistory([]);
1603
  });
 
 
 
 
 
1604
 
1605
  // Multi-select
1606
  if (DOM.multiSelectToggle) DOM.multiSelectToggle.addEventListener("change", updateSelectionUI);
@@ -1629,7 +1660,7 @@ async function init() {
1629
  var links = [];
1630
  for (var li = 0; li < indices.length; li++) {
1631
  var rec = STATE.results[indices[li]];
1632
- if (rec && rec.Link) links.push(rec.Link);
1633
  }
1634
  if (links.length === 0) { showToast("ๆœช้€‰ไธญไปปไฝ•ๆ–‡ไปถ"); return; }
1635
  navigator.clipboard.writeText(links.join("\n")).then(() => showToast("ๅทฒๅคๅˆถ " + links.length + " ๆก้“พๆŽฅ")).catch(() => showToast("ๅคๅˆถๅคฑ่ดฅ"));
 
61
  database: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" width="18" height="18"><ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M21 12c0 1.66-4 3-9 3s-9-1.34-9-3"/><path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5"/></svg>',
62
  };
63
 
64
+ const MIRROR_HOST = "hf-mirror.com";
65
+
66
  /* โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
67
  State
68
  โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• */
 
84
  filterFolderSelfs: [],
85
  filterMinSize: null,
86
  filterMaxSize: null,
87
+ useMirrorLinks: true,
88
  leftSidebarOpen: true,
89
  rightSidebarOpen: false,
90
  isMobile: false,
 
261
  DOM.filterExtList = $("#filter-ext-list");
262
  DOM.filterMinSize = $("#filter-min-size");
263
  DOM.filterMaxSize = $("#filter-max-size");
264
+ DOM.mirrorLinksToggle = $("#mirror-links-toggle");
265
  DOM.filterMinUnit = $("#filter-min-unit");
266
  DOM.filterMaxUnit = $("#filter-max-unit");
267
  DOM.closeFiltersBtn = $("#close-filters-btn");
 
329
  return result;
330
  }
331
 
332
+ function toMirrorURL(url) {
333
+ if (!url) return url;
334
+ try {
335
+ const parsed = new URL(url, window.location.origin);
336
+ if (parsed.hostname === "huggingface.co") parsed.hostname = MIRROR_HOST;
337
+ return parsed.toString();
338
+ } catch (e) {
339
+ return url;
340
+ }
341
+ }
342
+
343
+ function getCopyableLink(link) {
344
+ return STATE.useMirrorLinks ? toMirrorURL(link) : link;
345
+ }
346
+
347
+ function getPreviewLink(path) {
348
+ return STATE.useMirrorLinks ? toMirrorURL(path) : path;
349
+ }
350
+
351
  /* โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
352
  API Client
353
  โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• */
 
436
  if (STATE.filterMinSize !== null) params.set("min_size", fmtSizeUrl(STATE.filterMinSize));
437
  if (STATE.filterMaxSize !== null) params.set("max_size", fmtSizeUrl(STATE.filterMaxSize));
438
  if (!STATE.recordHistory) params.set("history", "0");
439
+ if (!STATE.useMirrorLinks) params.set("mirror", "0");
440
  if (DOM.sortSelect.value !== "relevance") params.set("sort", DOM.sortSelect.value);
441
  if (!STATE.searchFolders) params.set("search_folders", "false");
442
  if (STATE.exact) params.set("exact", "1");
 
602
 
603
  STATE.recordHistory = params.get("history") !== "0";
604
  if (DOM.historyToggle) DOM.historyToggle.checked = STATE.recordHistory;
605
+ STATE.useMirrorLinks = params.get("mirror") !== "0";
606
+ if (DOM.mirrorLinksToggle) DOM.mirrorLinksToggle.checked = STATE.useMirrorLinks;
607
 
608
  if (params.get("wide") === "1") {
609
  DOM.leftSidebar.classList.add("expanded-wide");
 
769
  </div>
770
  </div>
771
  <div class="result-actions">
772
+ <button class="result-action-btn" data-action="copy" data-link="${escapeHTML(getCopyableLink(rec.Link))}">ๅคๅˆถ้“พๆŽฅ</button>
773
  <a href="/api/download?file=${encodeURIComponent(rec.File + (rec.Extension ? '.' + rec.Extension : ''))}&link=${encodeURIComponent(rec.Link)}" class="result-action-btn primary">ไธ‹่ฝฝ</a>
774
+ <a href="${escapeHTML(getPreviewLink(rec.Path))}" class="result-action-btn" target="_blank">ไป“ๅบ“ๆŸฅ็œ‹</a>
775
  ${rec.HasTxt ? `<button class="result-action-btn" data-action="read" data-link="${escapeHTML(rec.Link)}" data-repo="${repoShort}">ๅœจ็บฟ้˜…่ฏป</button>` : ""}
776
  </div>`;
777
  fragment.appendChild(item);
 
1627
  STATE.recordHistory = DOM.historyToggle.checked;
1628
  if (!STATE.recordHistory) saveHistory([]);
1629
  });
1630
+ if (DOM.mirrorLinksToggle) DOM.mirrorLinksToggle.addEventListener("change", () => {
1631
+ STATE.useMirrorLinks = DOM.mirrorLinksToggle.checked;
1632
+ syncStateToURL(true);
1633
+ if (STATE.results.length > 0) renderResults();
1634
+ });
1635
 
1636
  // Multi-select
1637
  if (DOM.multiSelectToggle) DOM.multiSelectToggle.addEventListener("change", updateSelectionUI);
 
1660
  var links = [];
1661
  for (var li = 0; li < indices.length; li++) {
1662
  var rec = STATE.results[indices[li]];
1663
+ if (rec && rec.Link) links.push(getCopyableLink(rec.Link));
1664
  }
1665
  if (links.length === 0) { showToast("ๆœช้€‰ไธญไปปไฝ•ๆ–‡ไปถ"); return; }
1666
  navigator.clipboard.writeText(links.join("\n")).then(() => showToast("ๅทฒๅคๅˆถ " + links.length + " ๆก้“พๆŽฅ")).catch(() => showToast("ๅคๅˆถๅคฑ่ดฅ"));
static/index.html CHANGED
@@ -128,8 +128,8 @@
128
  </div>
129
 
130
  <div id="multi-action-bar" class="multi-action-bar" style="display:none">
131
- <button id="multi-copy-links" class="multi-action-btn">ๅคๅˆถ</button>
132
- <button id="multi-deselect" class="multi-action-btn">ๅ–ๆถˆ</button>
133
  <button id="multi-batch-download" class="multi-action-btn primary">ๆ‰น้‡ไธ‹่ฝฝ</button>
134
  <button id="multi-zip-download" class="multi-action-btn primary">ๅˆๅนถไธ‹่ฝฝ</button>
135
  <span id="multi-selected-count" class="multi-selected-count"></span>
@@ -176,6 +176,13 @@
176
  <button id="close-filters-btn" class="icon-btn-sm" aria-label="ๅ…ณ้—ญ่ฟ‡ๆปค">&times;</button>
177
  </div>
178
  <div class="sidebar-content">
 
 
 
 
 
 
 
179
  <!-- ่ฎฐๅฝ•ๆœ็ดขๅކๅฒๅผ€ๅ…ณ -->
180
  <div class="filter-section" id="history-toggle-section">
181
  <label class="toggle-row">
@@ -281,4 +288,4 @@ if ("serviceWorker" in navigator) {
281
  </script>
282
  <script src="/static/app.js"></script>
283
  </body>
284
- </html>
 
128
  </div>
129
 
130
  <div id="multi-action-bar" class="multi-action-bar" style="display:none">
131
+ <button id="multi-copy-links" class="multi-action-btn">ๅคๅˆถ้“พๆŽฅ</button>
132
+ <button id="multi-deselect" class="multi-action-btn">ๅ–ๆถˆ้€‰ๆ‹ฉ</button>
133
  <button id="multi-batch-download" class="multi-action-btn primary">ๆ‰น้‡ไธ‹่ฝฝ</button>
134
  <button id="multi-zip-download" class="multi-action-btn primary">ๅˆๅนถไธ‹่ฝฝ</button>
135
  <span id="multi-selected-count" class="multi-selected-count"></span>
 
176
  <button id="close-filters-btn" class="icon-btn-sm" aria-label="ๅ…ณ้—ญ่ฟ‡ๆปค">&times;</button>
177
  </div>
178
  <div class="sidebar-content">
179
+ <div class="filter-section" id="mirror-links-section">
180
+ <label class="toggle-row">
181
+ <span class="toggle-label">้•œๅƒ้“พๆŽฅ</span>
182
+ <input type="checkbox" id="mirror-links-toggle" checked>
183
+ <span class="toggle-switch"></span>
184
+ </label>
185
+ </div>
186
  <!-- ่ฎฐๅฝ•ๆœ็ดขๅކๅฒๅผ€ๅ…ณ -->
187
  <div class="filter-section" id="history-toggle-section">
188
  <label class="toggle-row">
 
288
  </script>
289
  <script src="/static/app.js"></script>
290
  </body>
291
+ </html>