1. Toggle Switch + 說明文字

開關控制項,用於布林設定選項,支援說明文字和 Badge 標籤

啟用時只搜尋 AVSOX / FC2,適合無碼作品
僅影響桌面版
<div class="settings-form-group">
  <label class="settings-label">
    <input type="checkbox" class="toggle toggle-primary">
    <span class="label-text">無碼模式</span>
  </label>
  <small class="settings-hint">啟用時只搜尋 AVSOX / FC2,適合無碼作品</small>
</div>

2. Select 下拉選單

下拉選擇器,用於單選或雙選組合(如排序 + 順序)

<div class="settings-form-row">
  <label class="row-label">主題模式</label>
  <select class="select select-bordered select-sm">
    <option value="light">淺色模式 (Light)</option>
    <option value="dim">深色模式 (Dim)</option>
  </select>
</div>

3. Number Input + 單位後綴

數字輸入框,右側顯示單位(字元、MB 等)

字元
字元
MB
0 = 不過濾
<div class="settings-form-row">
  <label class="row-label">標題長度限制</label>
  <div class="input-group-inline">
    <input type="number" class="input input-bordered input-sm" value="80">
    <span class="input-suffix">字元</span>
  </div>
</div>

4. Text Input + 說明文字

文字輸入框,支援說明文字和按鈕組合(如選擇資料夾)

範例:C:\Users\<你的使用者名稱>\下載
例如: C:\Program Files\DAUM\PotPlayer\PotPlayerMini64.exe
<div class="settings-form-row">
  <label class="row-label">輸出目錄</label>
  <div style="flex: 1; display: flex; gap: 8px;">
    <input type="text" class="input input-bordered input-sm" value="output" style="flex: 1;">
    <button class="btn btn-outline btn-sm" type="button">
      <i class="bi bi-folder"></i>
    </button>
  </div>
</div>

5. 收合區塊(Collapsible Section)

進階設定區域的收合/展開控制,卡片式觸發器 + Alpine.js 互動

Expanded State

字元
字元

Collapsed State

<div x-data="{ expanded: false }">
  <button class="collapsible-trigger" type="button" @click="expanded = !expanded" :aria-expanded="expanded.toString()">
    <span class="collapsible-title">
      <i class="bi bi-gear"></i> 進階刮削設定
    </span>
    <span class="btn-icon-collapse" aria-hidden="true">
      <i class="bi bi-chevron-down" :class="{ 'rotate-180': expanded }"></i>
    </span>
  </button>
  <div x-show="expanded" x-transition class="collapsible-content">
    <!-- 進階設定內容 -->
  </div>
</div>

6. 變數插入 Dropdown

檔案命名格式的變數插入控制項,展示變數列表 + description + example

Single Variable Dropdown (檔案命名格式)

番號 片商 {title}
番號 標題 女優 所有女優 片商 發售日 年份

Multi-Layer Folder Structure (3 層連動)

/
番號
內層
番號 標題 女優 片商 年份
預覽: SSNI-618/[SSNI-618][SOD] 絕對領域.mp4
連動規則: 內層有值才能啟用中層,中層有值才能啟用外層(由內向外逐層啟用)
<!-- 格式預覽 -->
<div class="format-preview">
  <span class="tag-badge">番號</span>
  <span class="tag-badge">片商</span> {title}
</div>

<!-- 單一變數插入 -->
<div class="variable-input-group">
  <input type="text" class="input input-bordered input-sm">
  <div class="variable-dropdown">
    <button class="btn-variable" type="button">
      <i class="bi bi-braces"></i> 變數
    </button>
    <div class="variable-menu">
      <span class="variable-badge">番號</span>
      <span class="variable-badge">標題</span>
      <span class="variable-badge">女優</span>
      <span class="variable-badge">片商</span>
    </div>
  </div>
</div>

7. API Key 警告 Alert

用於 Gemini API Key 輸入框下方的安全提示,強調敏感資料風險

Google AI Studio 可免費申請
安全提示:
  • API Key 將以明文存儲在 config.json
  • 請勿將 config.json 分享給他人
  • 如需撤銷,請前往 Google AI Studio 重新生成
<div class="alert alert-warning api-key-alert">
  <i class="bi bi-exclamation-triangle-fill"></i>
  <div class="alert-content">
    <strong>安全提示:</strong>
    <ul class="alert-list">
      <li>API Key 將以明文存儲在 config.json</li>
      <li>請勿將 config.json 分享給他人</li>
      <li>如需撤銷,請前往 <a href="..." target="_blank" class="alert-link">Google AI Studio</a> 重新生成</li>
    </ul>
  </div>
</div>

8. 版本 + 檢查更新

版本資訊顯示 + 檢查更新按鈕(含 default / loading / completed 三態)

v0.3.0
手動檢查 GitHub 是否有新版本
<!-- Default 狀態 -->
<button class="btn btn-outline btn-sm" type="button">
  <i class="bi bi-cloud-download"></i> 檢查更新
</button>

<!-- Loading 狀態 -->
<button class="btn btn-outline btn-sm" type="button" disabled>
  <span class="loading loading-spinner loading-sm"></span> 檢查中...
</button>

<!-- Completed 狀態 - 有更新 -->
<div class="badge badge-success gap-2">
  <i class="bi bi-download"></i>
  <a href="..." target="_blank">新版本 v0.3.1 可用</a>
</div>

<!-- Completed 狀態 - 已最新 -->
<span style="color: var(--text-muted);">
  <i class="bi bi-check-circle"></i> 已是最新版本
</span>

<!-- Completed 狀態 - 錯誤 -->
<span style="color: var(--color-error);">
  <i class="bi bi-exclamation-circle"></i> 網路錯誤
</span>

9. 儲存按鈕(Primary CTA)

Settings 表單的主要行動按鈕,位於表單最下方右對齊


<div class="save-btn-wrapper">
  <button type="submit" class="btn btn-primary save-btn">
    <i class="bi bi-save"></i> 儲存設定
  </button>
</div>

11. Font Size Control

Settings header 右上角的 5 段字型大小快速切換器(xs / sm / md / lg / xl)。 按鈕文字統一顯示「A」,但各自套用對應的 font-size,視覺上呈現從小到大的漸變。 active 狀態套用 .active class,顯示 accent 背景色。

目前選擇:
<div class="font-size-control">
  <template x-for="s in [{k:'xs',l:'A'},{k:'sm',l:'A'},{k:'md',l:'A'},{k:'lg',l:'A'},{k:'xl',l:'A'}]">
    <button type="button"
            class="font-size-btn"
            :class="{ active: fontSize === s.k }"
            :style="'font-size:' + {xs:'0.7rem',sm:'0.8rem',md:'0.9rem',lg:'1.05rem',xl:'1.2rem'}[s.k]"
            @click="fontSize = s.k"
            x-text="s.l">
    </button>
  </template>
</div>

12. User Tag Editor

來源:search.html 詳情面板的標籤編輯器。 分為系統 tag(.tag-badge,唯讀)和用戶 tag(.tag-badge.user-tag,可刪除)。 點「+」顯示輸入框,輸入後按 ✓ 或 Enter 新增;點 × 刪除 user tag;Escape 取消。

<!-- 系統 tag(唯讀)-->
<span class="badge tag-badge" x-text="tag"></span>

<!-- 用戶 tag(可刪除)-->
<span class="badge tag-badge user-tag">
  <span x-text="tag"></span>
  <span class="tag-remove" @click="removeUserTag(tag)">&times;</span>
</span>

<!-- 新增按鈕 -->
<button x-show="!addingTag" @click="showAddTagInput()"
        class="btn btn-sm tag-add-btn">+</button>

<!-- 新增輸入框 -->
<span x-show="addingTag" class="tag-input-wrapper">
  <input type="text" x-model="newTagValue"
         @keydown.enter="confirmAddTag()" @keydown.escape="cancelAddTag()"
         class="tag-input" placeholder="輸入標籤">
  <button @click="confirmAddTag()" class="btn btn-sm tag-confirm">✓</button>
  <button @click="cancelAddTag()" class="btn btn-sm tag-cancel">✕</button>
</span>

13. Source Pill(跨頁共用元件)

掃描來源膠囊 — 來源排序開關 / Parts Bin 可加入態。元件已從 settings.css 抽至 components/source-pill.css 並去 #settings-components scope, 故 Settings / Search / Showcase 皆可直接渲染。 本卡刻意不包 id="settings-components" — 仍正確著色即證明已 unscoped。 Parts Bin 三態:可加入(staged, available=true):+ icon、無刪除線、cursor pointer; 不可達(available=false):灰 dashed + 灰 slash + 右上 amber dot; active(promoted):由 Settings Active Row 管理(非 Parts Bin)。

JavBus
DMM
FC2
JavLibrary BETA
MetaTube
StagedProvider
UnreachableProvider
<!-- unscoped:不需 id="settings-components" 包裹 -->
<!-- 啟用 / 停用 -->
<div class="source-pill" data-enabled="true">
  <i class="bi bi-slash-circle slash-icn"></i>
  <span class="pill-name">JavBus</span>
</div>

<!-- 無碼(success accent)-->
<div class="source-pill source-pill--uncensored" data-enabled="true">...</div>

<!-- manual-only(BETA badge)-->
<div class="source-pill source-pill--manual-only" data-enabled="false">
  <span class="pill-name">JavLibrary</span>
  <span class="source-pill-badge">BETA</span>
</div>

<!-- metatube(m 角標)-->
<span class="source-pill-mt-badge">m</span>

<!-- parts-bin 可加入(staged,available=true:+ icon、無刪除線、pointer)-->
<div class="source-pill is-partsbin" data-enabled="false" data-available="true">
  <i class="bi bi-plus-circle plus-icn" aria-hidden="true"></i>
  <i class="bi bi-slash-circle slash-icn" aria-hidden="true"></i>
  <span class="pill-name">StagedProvider</span>
</div>

<!-- parts-bin 不可達(available=false:灰 dashed + slash + 右上 amber dot)-->
<div class="source-pill is-partsbin" data-enabled="false" data-available="false">
  <i class="bi bi-plus-circle plus-icn" aria-hidden="true"></i>
  <i class="bi bi-slash-circle slash-icn" aria-hidden="true"></i>
  <span class="pill-name">UnreachableProvider</span>
</div>

14. Long-press 進階入口(700ms 長壓 pattern)

700ms 長壓開進階重刮 / 搜尋彈窗。共用 mixin shared/long-press.jslongPressState), 三處共用同一份 wiring:Search 送出鈕(長壓 → 進階搜尋)、 Showcase grid 缺卡 enrich-btnShowcase lightbox 🔍(長壓 → 進階重刮)。 短按走原本 tap 行為(搜尋 / enrich),長壓 700ms 達標後 fire callback 開彈窗, longPressClickGuard 吞掉長壓後的同一次 click(避免連帶送出 / 連帶 enrich,US8)。 刻意無長壓進度環、無提示氣泡 / 視覺 affordance(長壓為進階快捷,不對一般用戶強調)。 六事件 wiring 一律傳 $eventlongPressEnd($event) / longPressCancel($event) 在 touchend / touchcancel 設 synthetic-mouse 抑制窗,longPressStart(..., $event) 讓抑制窗內 UA 補發的 synthetic mousedown early-return(不清長壓旗標),否則長壓開彈窗會被補發的 click 連帶觸發底層 tap(雙觸發,Codex PR#47 P2)。

短按 = tap 行為;長壓 700ms = 進階入口
<!-- main.js:import + mergeState(descriptor-preserving,禁 spread)-->
import { longPressState } from '@/shared/long-press.js';
mergeState(..., longPressState());

<!-- template wiring(六事件 + click guard;全部傳 $event:touch synthetic-mouse 抑制契約)-->
<button
    @mousedown="longPressStart(() => openRescrape(video,'enrich'), () => rescrapeEnabled(), $event)"
    @mouseup="longPressEnd($event)"
    @mouseleave="longPressCancel($event)"
    @touchstart.passive="longPressStart(cb, enabledFn, $event)"
    @touchend="longPressEnd($event)"
    @touchcancel="longPressCancel($event)"
    @click="longPressClickGuard($event) || tapHandler()">...</button>

15. Segmented 控件(全開 | 無碼模式)

搜尋來源卡 batchbar 左側的藥丸型分段控件,取代原有的 track+thumb toggle。 左段「全開」(#sourcesAllOpenToggle)啟用所有 builtin 來源至 cap; 右段「無碼模式」(#sourcesUncensoredToggle)關閉所有有碼來源。 CSS scope:#settings-components .settings-sources-segmented(pill 白名單 §1 第 7 條)。 .is-on 態玻璃高亮(backdrop-filter + shadow-2)。prefers-reduced-motion 停 transition。

態一:全開段亮(allBuiltinEnabled && !uncensoredMode)
態二:無碼段亮(uncensoredMode)
<!-- 父層需有 id="settings-components"(CSS scope guard)-->
<div class="settings-sources-segmented">
  <button id="sourcesAllOpenToggle"
          :class="{ 'is-on': allBuiltinEnabled && !uncensoredMode }"
          :aria-pressed="(allBuiltinEnabled && !uncensoredMode) ? 'true' : 'false'"
          @click="if (uncensoredMode && enabledCount >= 10) { _flashCapAlert(); } else { enableAllToCap(); }">
    全開
  </button>
  <button id="sourcesUncensoredToggle"
          :class="{ 'is-on': uncensoredMode }"
          :aria-pressed="uncensoredMode ? 'true' : 'false'"
          @click="uncensoredMode = true">
    無碼模式
  </button>
</div>

16. metatube 連線狀態 banner(已連線態)

掃描來源卡 metatube 區「已連線」狀態列(.settings-mt-connect-status,僅 metatubeConnected 分支渲染; 未連線是 connect form 非 banner)。綠 ✓ + 伺服器 URL + 編輯/中斷/重測 mini 鈕,下接 tier-hint。 CSS scope:#settings-componentsdim 校準(69 T3):近黑底吃光 8% success tint → 提 tint 16% + solid 邊 + 3px 左色條, 綠態明確可辨。切 dim 對照即 P9/P10 驗證點。

已連線 metatube,30+ provider 可用於進階重刮與搜尋。

17. 進階重刮彈窗 — 來源 picker(step-1)

🔄 長壓開的進階重刮彈窗 step-1「挑來源」視圖(_rescrape_modal.html)。 重用 .source-pill--action(點擊式非拖曳):auto pill + builtin(有碼/無碼)+ metatube pill(m 角標); 找不到番號就地顯示 .rescrape-inline-error(不換頁)。 dim 校準(69 T2/T4):膠囊有碼/無碼一眼可辨(P1)、inline-error warning 提 tint + solid 邊(P20)。 切 dim 對照即 P1/P20 驗證點。