Skip to content

YouTube 頻道過濾器

Choose a tag to compare

@hubig21 hubig21 released this 10 Apr 06:46
· 28 commits to main since this release
81e29b6

YouTube 頻道過濾器 — 更新記錄

v1.0.1(2026-04-10)

🐛 修正

1. 語言過濾偵測大幅改善(含泰文修正)

問題:v1.0.0 的語言偵測函式(detectLang)僅支援 5 種語言(日、韓、中、俄、阿拉伯),導致泰文(th)等語言的 BCP-47 自訂代碼完全無效——即使正確輸入代碼,過濾也不會生效。

修正:重寫 detectLang(),擴充至 20+ 種語言的 Unicode 字元集偵測:

新增語言 BCP-47
🇹🇭 泰文 th
🇮🇳 印地文 hi
🇧🇩 孟加拉文 bn
🇲🇲 緬甸文 my
🇱🇰 僧伽羅文 si
🇮🇳 泰盧固文 te
🇮🇳 泰米爾文 ta
🇮🇳 旁遮普文 pa
🇬🇪 喬治亞文 ka
🇦🇲 亞美尼亞文 hy
🇪🇹 阿姆哈拉文 am
🇮🇱 希伯來文 he
🇩🇪 德文 de
🇫🇷 法文 fr
🇪🇸 西班牙文 es
🇮🇹 義大利文 it
🇧🇷 葡萄牙文 pt
🇵🇱 波蘭文 pl
🇨🇿 捷克/斯洛伐克文 cs
🇳🇴 北歐文 no

同時修正語言比對邏輯:改用精確比對(lang === code),避免 es(西班牙文)誤命中 est(愛沙尼亞文)等邊界情況。


2. 頁面重整(Reload)後版面缺失

問題:YouTube 是 SPA,在特定操作後會清空並重建整個 DOM。腳本的 root 變數仍指向已移除的舊元素,因程式碼有 if (root) return 判斷,導致面板不重建,重整後按鈕與介面完全消失。

修正(三處):

  1. Panel.build() 加入 document.body.contains(root) 存在性檢查,若已脫離 DOM 則自動重置重建
  2. FAB.injectHeaderBtn() 重試前先重置 headerBtn,確保頂欄按鈕可重新注入
  3. Obs.watchNav() 回呼加入 Panel.build(),確保任何頁面切換後面板正常恢復

3. 說明頁新增捐款連結

在「ℹ️ 說明」Tab 軟體資訊下方,新增「☕ 支持開發者」區塊:

本專案採用自願訂閱模式。如果您認為這個工具有價值,並且每月能輕鬆捐贈幾枚金幣,歡迎支持我持續維護與開發。您的支持是最大的動力!

捐款連結:Liberapay

注意:Liberapay 的 JavaScript widget 會被 YouTube CSP 封鎖,改用純連結,功能相同且完全相容。


4. 首頁快捷按鈕重複顯示兩排

問題:Observer 的 selector 同時選取了 ytd-rich-item-renderer(外層容器)和 yt-lockup-view-model(內層子元素)——兩者對應同一張影片卡片,導致 injectCards 對同一卡片注入兩次快捷按鈕列。

ytd-rich-item-renderer      ← 被選到(外層)
  └── yt-lockup-view-model  ← 被選到(內層,同一張卡)

修正:injectCards 遇到 yt-lockup-view-model 時,先用 closest() 向上查找父層容器:

  • 若父層已有 data-ytf-qa 標記(外層已處理)→ 跳過
  • 若無父層(側邊推薦的獨立卡片)→ 正常注入

首頁卡片由 ytd-rich-item-renderer 處理,側邊推薦由 yt-lockup-view-model 處理,不再重複。


v1.0.0(2026-04-09)

首次正式發布。詳見完整功能列表。


YouTube Channel Filter — Changelog

v1.0.1 (2026-04-10)

🐛 Bug Fixes

1. Language Filter Detection — Major Improvement (including Thai)

Problem: The detectLang() function in v1.0.0 only supported 5 languages (Japanese, Korean, Chinese, Russian, Arabic). Custom BCP-47 codes like th (Thai) had no effect — even when correctly entered, no videos would be filtered.

Fix: Rewrote detectLang() to detect 20+ languages via Unicode character blocks:

Language BCP-47
🇹🇭 Thai th
🇮🇳 Hindi hi
🇧🇩 Bengali bn
🇲🇲 Burmese my
🇱🇰 Sinhala si
🇮🇳 Telugu te
🇮🇳 Tamil ta
🇮🇳 Punjabi pa
🇬🇪 Georgian ka
🇦🇲 Armenian hy
🇪🇹 Amharic am
🇮🇱 Hebrew he
🇩🇪 German de
🇫🇷 French fr
🇪🇸 Spanish es
🇮🇹 Italian it
🇧🇷 Portuguese pt
🇵🇱 Polish pl
🇨🇿 Czech / Slovak cs
🇳🇴 Nordic no

Also fixed language matching to use exact comparison (lang === code), preventing false positives such as es (Spanish) incorrectly matching est (Estonian).


2. Panel Missing After Page Reload

Problem: YouTube is a Single Page Application that occasionally clears and rebuilds the entire DOM. The script's root variable continued pointing to the old detached element. Because of an early-return guard (if (root) return), the panel would never rebuild — the management panel and top bar button disappeared after a reload.

Fix: Three coordinated changes:

  1. Panel.build() — Added document.body.contains(root) check; auto-resets and rebuilds if the panel has been detached from the DOM.
  2. FAB.injectHeaderBtn() — Resets headerBtn to null before retrying injection so the top bar button can be re-injected after DOM reconstruction.
  3. Obs.watchNav() callback — Now explicitly calls Panel.build() after every SPA navigation event.

3. Donate Link Added to About Tab

A new "☕ Support the Developer" section has been added below the software info card in the ℹ️ About tab:

This project runs on a voluntary subscription model. If you find this tool valuable and can comfortably spare a few coins each month, please consider supporting my work. Your support means everything!

Donate via Liberapay

Note: Liberapay's JavaScript widget is blocked by YouTube's Content Security Policy. A plain hyperlink is used instead — same destination, fully CSP-compatible.


4. Quick Action Buttons Appearing Twice on Homepage

Problem: The Observer selector included both ytd-rich-item-renderer (outer container) and yt-lockup-view-model (inner child element) — both pointing to the same video card. As a result, injectCards injected the quick action button bar twice into the same card.

ytd-rich-item-renderer      ← matched (outer)
  └── yt-lockup-view-model  ← matched (inner, same card)

Fix: When injectCards encounters a yt-lockup-view-model, it first uses closest() to check for an already-processed parent container:

  • If a parent already has the data-ytf-qa marker (outer layer handled it) → skip
  • If no such parent exists (standalone sidebar card) → inject normally

Homepage cards are now handled exclusively by ytd-rich-item-renderer; sidebar recommendations are handled by yt-lockup-view-model. No more duplicates.


v1.0.0 (2026-04-09)

Initial public release. See full feature list in the main description.