diff --git a/CHANGELOG.md b/CHANGELOG.md index b3a6f2a..2f78772 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # CHANGELOG +## 4.0.11 + +- 新增:播放页 展开视频合集第二行标题 +- 更新:评论过滤 开关设定对全站通用 +- 修复:评论过滤 排除自己的评论和@自己的评论 + ## 4.0.10 - 新增:评论区过滤 过滤@其他用户的无回复评论 diff --git a/src/modules/filters/index.ts b/src/modules/filters/index.ts index 273ca92..7216bb2 100644 --- a/src/modules/filters/index.ts +++ b/src/modules/filters/index.ts @@ -14,20 +14,15 @@ import { } from '../../utils/pageType' import { BiliCleanerStorage } from '../../utils/storage' import { - commentFilterDynamicEntry, - commentFilterDynamicGroups, - commentFilterDynamicHandler, -} from './variety/comment/pages/dynamic' + commentFilterCommonEntry, + commentFilterCommonGroups, + commentFilterCommonHandler, +} from './variety/comment/pages/common' import { - commentFilterSpaceEntry, - commentFilterSpaceGroups, - commentFilterSpaceHandler, -} from './variety/comment/pages/space' -import { - commentFilterVideoEntry, - commentFilterVideoGroups, - commentFilterVideoHandler, -} from './variety/comment/pages/video' + commentFilterLegacyEntry, + commentFilterLegacyGroups, + commentFilterLegacyHandler, +} from './variety/comment/pages/legacy' import { dynamicFilterDynamicEntry, dynamicFilterDynamicGroups, @@ -96,21 +91,15 @@ export const videoFilters: Filter[] = [ /** 评论过滤器 */ export const commentFilters: Filter[] = [ { - name: '视频页/番剧页 视频评论过滤', - groups: commentFilterVideoGroups, - entry: commentFilterVideoEntry, - checkFn: () => isPageVideo() || isPageBangumi() || isPagePlaylist(), - }, - { - name: '动态页 动态评论过滤', - groups: commentFilterDynamicGroups, - entry: commentFilterDynamicEntry, - checkFn: () => isPageDynamic(), + name: '视频页/番剧页/动态页 视频评论过滤', + groups: commentFilterCommonGroups, + entry: commentFilterCommonEntry, + checkFn: () => isPageVideo() || isPageBangumi() || isPagePlaylist() || isPageDynamic(), }, { name: '空间页 动态评论过滤', - groups: commentFilterSpaceGroups, - entry: commentFilterSpaceEntry, + groups: commentFilterLegacyGroups, + entry: commentFilterLegacyEntry, checkFn: () => isPageSpace(), }, ] @@ -181,7 +170,6 @@ export const filterContextMenuHandlers = [ videoFilterPopularHandler, videoFilterHomepageHandler, dynamicFilterDynamicHandler, - commentFilterVideoHandler, - commentFilterDynamicHandler, - commentFilterSpaceHandler, + commentFilterCommonHandler, + commentFilterLegacyHandler, ] diff --git a/src/modules/filters/variety/comment/pages/video.ts b/src/modules/filters/variety/comment/pages/common.ts similarity index 88% rename from src/modules/filters/variety/comment/pages/video.ts rename to src/modules/filters/variety/comment/pages/common.ts index cb7c518..7060fd0 100644 --- a/src/modules/filters/variety/comment/pages/video.ts +++ b/src/modules/filters/variety/comment/pages/common.ts @@ -9,7 +9,7 @@ import { } from '../../../../../types/filter' import fetchHook from '../../../../../utils/fetch' import { debugFilter as debug, error } from '../../../../../utils/logger' -import { isPageBangumi, isPagePlaylist, isPageVideo } from '../../../../../utils/pageType' +import { isPageBangumi, isPageDynamic, isPagePlaylist, isPageVideo } from '../../../../../utils/pageType' import ShadowInstance from '../../../../../utils/shadow' import { BiliCleanerStorage } from '../../../../../utils/storage' import { orderedUniq, showEle } from '../../../../../utils/tool' @@ -26,7 +26,13 @@ import { CommentLevelFilter, CommentUsernameFilter, } from '../subFilters/black' -import { CommentIsLinkFilter, CommentIsNoteFilter, CommentIsPinFilter, CommentIsUpFilter } from '../subFilters/white' +import { + CommentIsLinkFilter, + CommentIsMeFilter, + CommentIsNoteFilter, + CommentIsPinFilter, + CommentIsUpFilter, +} from '../subFilters/white' const GM_KEYS = { black: { @@ -145,6 +151,20 @@ const selectorFns = { } return false }, + // 自己发布 or @自己 的评论 + isMe: (comment: HTMLElement): SelectorResult => { + const me = (comment as any).__user?.uname + if (!me) { + return false + } + if ( + (comment as any).__data?.member?.uname === me || + (comment as any).__data?.content?.message?.includes(`@${me}`) + ) { + return true + } + return false + }, }, sub: { username: (comment: HTMLElement): SelectorResult => { @@ -165,6 +185,14 @@ const selectorFns = { .replace('@', '') .trim() }, + callUserNoReply: (comment: HTMLElement): SelectorResult => { + return (comment as any).__data?.content?.message + ?.trim() + ?.replace(/^回复\s?@[^@\s]+\s?:/, '') + ?.match(/@[^@\s]+/)?.[0] + .replace('@', '') + .trim() + }, callUserOnly: (comment: HTMLElement): SelectorResult => { return ( (comment as any).__data?.content?.message @@ -174,6 +202,15 @@ const selectorFns = { .trim() === '' ) }, + callUserOnlyNoReply: (comment: HTMLElement): SelectorResult => { + return ( + (comment as any).__data?.content?.message + ?.trim() + ?.replace(/^回复\s?@[^@\s]+\s?:/, '') + ?.replace(/@[^@\s]+/g, ' ') + .trim() === '' + ) + }, level: (comment: HTMLElement): SelectorResult => { return (comment as any).__data?.member?.level_info?.current_level }, @@ -193,6 +230,23 @@ const selectorFns = { } return false }, + // 自己发布 or @自己 的评论 + isMe: (comment: HTMLElement): SelectorResult => { + const me = (comment as any).__user?.uname + if (!me) { + return false + } + if ( + (comment as any).__data?.member?.uname === me || + (comment as any).__data?.content?.message + ?.trim() + ?.replace(/^回复\s?@[^@\s]+\s?:/, '') + .includes(`@${me}`) + ) { + return true + } + return false + }, }, } @@ -200,7 +254,7 @@ const selectorFns = { let isRootWhite = false let isSubWhite = false -class CommentFilterVideo implements IMainFilter { +class CommentFilterCommon implements IMainFilter { target: HTMLElement | undefined // 黑名单 @@ -218,6 +272,7 @@ class CommentFilterVideo implements IMainFilter { commentIsPinFilter = new CommentIsPinFilter() commentIsNoteFilter = new CommentIsNoteFilter() commentIsLinkFilter = new CommentIsLinkFilter() + commentIsMeFilter = new CommentIsMeFilter() init() { // 黑名单 @@ -271,7 +326,7 @@ class CommentFilterVideo implements IMainFilter { rootComments.forEach((v) => { debug( [ - `CommentFilterVideo rootComments`, + `CommentFilterCommon rootComments`, `username: ${selectorFns.root.username(v)}`, `content: ${selectorFns.root.content(v)}`, `callUser: ${selectorFns.root.callUser(v)}`, @@ -283,6 +338,7 @@ class CommentFilterVideo implements IMainFilter { `isPin: ${selectorFns.root.isPin(v)}`, `isNote: ${selectorFns.root.isNote(v)}`, `isLink: ${selectorFns.root.isLink(v)}`, + `isMe: ${selectorFns.root.isMe(v)}`, ].join('\n'), ) }) @@ -312,11 +368,12 @@ class CommentFilterVideo implements IMainFilter { this.commentIsPinFilter.isEnable && whitePairs.push([this.commentIsPinFilter, selectorFns.root.isPin]) this.commentIsNoteFilter.isEnable && whitePairs.push([this.commentIsNoteFilter, selectorFns.root.isNote]) this.commentIsLinkFilter.isEnable && whitePairs.push([this.commentIsLinkFilter, selectorFns.root.isLink]) + this.commentIsMeFilter.isEnable && whitePairs.push([this.commentIsMeFilter, selectorFns.root.isMe]) const rootBlackCnt = await coreCheck(rootComments, true, blackPairs, whitePairs) const time = (performance.now() - timer).toFixed(1) debug( - `CommentFilterVideo hide ${rootBlackCnt} in ${rootComments.length} root comments, mode=${mode}, time=${time}`, + `CommentFilterCommon hide ${rootBlackCnt} in ${rootComments.length} root comments, mode=${mode}, time=${time}`, ) } @@ -336,7 +393,9 @@ class CommentFilterVideo implements IMainFilter { this.commentBotFilter.isEnable || this.commentCallBotFilter.isEnable || this.commentCallUserFilter.isEnable || - this.commentCallUserOnlyFilter.isEnable + this.commentCallUserNoReplyFilter.isEnable || + this.commentCallUserOnlyFilter.isEnable || + this.commentCallUserOnlyNoReplyFilter.isEnable ) ) { revertAll = true @@ -359,14 +418,17 @@ class CommentFilterVideo implements IMainFilter { subComments.forEach((v) => { debug( [ - `CommentFilterVideo subComments`, + `CommentFilterCommon subComments`, `username: ${selectorFns.sub.username(v)}`, `content: ${selectorFns.sub.content(v)}`, `callUser: ${selectorFns.sub.callUser(v)}`, + `callUserNoReply: ${selectorFns.sub.callUserNoReply(v)}`, `callUserOnly: ${selectorFns.sub.callUserOnly(v)}`, + `callUserOnlyNoReply: ${selectorFns.sub.callUserOnlyNoReply(v)}`, `level: ${selectorFns.sub.level(v)}`, `isUp: ${selectorFns.sub.isUp(v)}`, `isLink: ${selectorFns.sub.isLink(v)}`, + `isMe: ${selectorFns.sub.isMe(v)}`, ].join('\n'), ) }) @@ -384,17 +446,22 @@ class CommentFilterVideo implements IMainFilter { this.commentBotFilter.isEnable && blackPairs.push([this.commentBotFilter, selectorFns.sub.username]) this.commentCallBotFilter.isEnable && blackPairs.push([this.commentCallBotFilter, selectorFns.sub.callUser]) this.commentCallUserFilter.isEnable && blackPairs.push([this.commentCallUserFilter, selectorFns.sub.callUser]) + this.commentCallUserNoReplyFilter.isEnable && + blackPairs.push([this.commentCallUserNoReplyFilter, selectorFns.sub.callUserNoReply]) this.commentCallUserOnlyFilter.isEnable && blackPairs.push([this.commentCallUserOnlyFilter, selectorFns.sub.callUserOnly]) + this.commentCallUserOnlyNoReplyFilter.isEnable && + blackPairs.push([this.commentCallUserOnlyNoReplyFilter, selectorFns.sub.callUserOnlyNoReply]) const whitePairs: SubFilterPair[] = [] this.commentIsUpFilter.isEnable && whitePairs.push([this.commentIsUpFilter, selectorFns.sub.isUp]) this.commentIsLinkFilter.isEnable && whitePairs.push([this.commentIsLinkFilter, selectorFns.sub.isLink]) + this.commentIsMeFilter.isEnable && whitePairs.push([this.commentIsMeFilter, selectorFns.sub.isMe]) const subBlackCnt = await coreCheck(subComments, false, blackPairs, whitePairs) const time = (performance.now() - timer).toFixed(1) debug( - `CommentFilterVideo hide ${subBlackCnt} in ${subComments.length} sub comments, mode=${mode}, time=${time}`, + `CommentFilterCommon hide ${subBlackCnt} in ${subComments.length} sub comments, mode=${mode}, time=${time}`, ) } @@ -402,12 +469,12 @@ class CommentFilterVideo implements IMainFilter { this.checkRoot(mode) .then() .catch((err) => { - error(`CommentFilterVideo checkRoot mode=${mode} error`, err) + error(`CommentFilterCommon checkRoot mode=${mode} error`, err) }) this.checkSub(mode) .then() .catch((err) => { - error(`CommentFilterVideo checkSub mode=${mode} error`, err) + error(`CommentFilterCommon checkSub mode=${mode} error`, err) }) } @@ -442,14 +509,15 @@ class CommentFilterVideo implements IMainFilter { //================================================================================================== -const mainFilter = new CommentFilterVideo() +const mainFilter = new CommentFilterCommon() -export const commentFilterVideoEntry = async () => { +export const commentFilterCommonEntry = async () => { mainFilter.init() + mainFilter.commentIsMeFilter.enable() mainFilter.observe() } -export const commentFilterVideoGroups: Group[] = [ +export const commentFilterCommonGroups: Group[] = [ { name: '评论用户过滤', items: [ @@ -772,8 +840,8 @@ export const commentFilterVideoGroups: Group[] = [ ] // 右键菜单handler -export const commentFilterVideoHandler: ContextMenuTargetHandler = (target: HTMLElement): FilterContextMenu[] => { - if (!(isPageVideo() || isPagePlaylist() || isPageBangumi())) { +export const commentFilterCommonHandler: ContextMenuTargetHandler = (target: HTMLElement): FilterContextMenu[] => { + if (!(isPageVideo() || isPagePlaylist() || isPageBangumi() || isPageDynamic())) { return [] } @@ -795,7 +863,7 @@ export const commentFilterVideoHandler: ContextMenuTargetHandler = (target: HTML arr.unshift(username) BiliCleanerStorage.set(GM_KEYS.black.username.valueKey, orderedUniq(arr)) } catch (err) { - error(`commentFilterVideoHandler add username ${username} failed`, err) + error(`commentFilterCommonHandler add username ${username} failed`, err) } }, }) diff --git a/src/modules/filters/variety/comment/pages/dynamic.ts b/src/modules/filters/variety/comment/pages/dynamic.ts deleted file mode 100644 index 94c0b92..0000000 --- a/src/modules/filters/variety/comment/pages/dynamic.ts +++ /dev/null @@ -1,797 +0,0 @@ -import settings from '../../../../../settings' -import { Group } from '../../../../../types/collection' -import { - ContextMenuTargetHandler, - FilterContextMenu, - IMainFilter, - SelectorResult, - SubFilterPair, -} from '../../../../../types/filter' -import fetchHook from '../../../../../utils/fetch' -import { debugFilter as debug, error } from '../../../../../utils/logger' -import { isPageDynamic } from '../../../../../utils/pageType' -import ShadowInstance from '../../../../../utils/shadow' -import { BiliCleanerStorage } from '../../../../../utils/storage' -import { orderedUniq, showEle } from '../../../../../utils/tool' -import { coreCheck } from '../../../core/core' -import { bots } from '../extra/bots' -import { - CommentBotFilter, - CommentCallBotFilter, - CommentCallUserFilter, - CommentCallUserNoReplyFilter, - CommentCallUserOnlyFilter, - CommentCallUserOnlyNoReplyFilter, - CommentContentFilter, - CommentLevelFilter, - CommentUsernameFilter, -} from '../subFilters/black' -import { CommentIsLinkFilter, CommentIsNoteFilter, CommentIsPinFilter, CommentIsUpFilter } from '../subFilters/white' - -const GM_KEYS = { - black: { - username: { - statusKey: 'dynamic-comment-username-filter-status', - valueKey: 'global-comment-username-filter-value', - }, - content: { - statusKey: 'dynamic-comment-content-filter-status', - valueKey: 'global-comment-content-filter-value', - }, - level: { - statusKey: 'dynamic-comment-level-filter-status', - valueKey: 'global-comment-level-filter-value', - }, - bot: { - statusKey: 'dynamic-comment-bot-filter-status', - }, - callBot: { - statusKey: 'dynamic-comment-call-bot-filter-status', - }, - callUser: { - statusKey: 'dynamic-comment-call-user-filter-status', - }, - callUserNoReply: { - statusKey: 'dynamic-comment-call-user-noreply-filter-status', - }, - callUserOnly: { - statusKey: 'dynamic-comment-call-user-only-filter-status', - }, - callUserOnlyNoReply: { - statusKey: 'dynamic-comment-call-user-only-noreply-filter-status', - }, - isAD: { - statusKey: 'dynamic-comment-ad-filter-status', - }, - }, - white: { - root: { - statusKey: 'dynamic-comment-root-whitelist-status', - }, - sub: { - statusKey: 'dynamic-comment-sub-whitelist-status', - }, - isUp: { - statusKey: 'dynamic-comment-uploader-whitelist-status', - }, - isPin: { - statusKey: 'dynamic-comment-pinned-whitelist-status', - }, - isNote: { - statusKey: 'dynamic-comment-note-whitelist-status', - }, - isLink: { - statusKey: 'dynamic-comment-link-whitelist-status', - }, - }, -} - -// 一二级评论信息提取 -const selectorFns = { - root: { - username: (comment: HTMLElement): SelectorResult => { - return (comment as any).__data?.member?.uname?.trim() - }, - content: (comment: HTMLElement): SelectorResult => { - return (comment as any).__data?.content?.message?.replace(/@[^@\s]+/g, ' ').trim() - }, - callUser: (comment: HTMLElement): SelectorResult => { - return (comment as any).__data?.content?.members[0]?.uname - }, - callUserNoReply: (comment: HTMLElement): SelectorResult => { - if ((comment as any).__data?.rcount !== 0) { - return undefined - } - return (comment as any).__data?.content?.members[0]?.uname - }, - callUserOnly: (comment: HTMLElement): SelectorResult => { - return (comment as any).__data?.content?.message?.replace(/@[^@\s]+/g, ' ').trim() === '' - }, - callUserOnlyNoReply: (comment: HTMLElement): SelectorResult => { - if ((comment as any).__data?.rcount !== 0) { - return undefined - } - return (comment as any).__data?.content?.message?.replace(/@[^@\s]+/g, ' ').trim() === '' - }, - level: (comment: HTMLElement): SelectorResult => { - return (comment as any).__data?.member?.level_info?.current_level - }, - isUp: (comment: HTMLElement): SelectorResult => { - const mid = (comment as any).__data?.mid - const upMid = (comment as any).__upMid - return typeof mid === 'number' && mid === upMid - }, - isPin: (comment: HTMLElement): SelectorResult => { - return !!(comment as any).__data?.reply_control?.is_up_top - }, - isNote: (comment: HTMLElement): SelectorResult => { - return !!(comment as any).__data?.reply_control?.is_note_v2 - }, - isLink: (comment: HTMLElement): SelectorResult => { - const jump_url = (comment as any).__data?.content?.jump_url - if (jump_url) { - for (const k of Object.keys(jump_url)) { - if (!jump_url[k]?.pc_url?.includes('search.bilibili.com')) { - return true - } - } - } - return false - }, - }, - sub: { - username: (comment: HTMLElement): SelectorResult => { - return (comment as any).__data?.member?.uname?.trim() - }, - content: (comment: HTMLElement): SelectorResult => { - return (comment as any).__data?.content?.message - ?.trim() - ?.replace(/^回复\s?@[^@\s]+\s?:/, '') - ?.replace(/@[^@\s]+/g, ' ') - .trim() - }, - callUser: (comment: HTMLElement): SelectorResult => { - return (comment as any).__data?.content?.message - ?.trim() - ?.replace(/^回复\s?@[^@\s]+\s?:/, '') - ?.match(/@[^@\s]+/)?.[0] - .replace('@', '') - .trim() - }, - callUserOnly: (comment: HTMLElement): SelectorResult => { - return ( - (comment as any).__data?.content?.message - ?.trim() - ?.replace(/^回复\s?@[^@\s]+\s?:/, '') - ?.replace(/@[^@\s]+/g, ' ') - .trim() === '' - ) - }, - level: (comment: HTMLElement): SelectorResult => { - return (comment as any).__data?.member?.level_info?.current_level - }, - isUp: (comment: HTMLElement): SelectorResult => { - const mid = (comment as any).__data?.mid - const upMid = (comment as any).__upMid - return typeof mid === 'number' && mid === upMid - }, - isLink: (comment: HTMLElement): SelectorResult => { - const urls = (comment as any).__data?.content?.jump_url - if (urls) { - for (const k of Object.keys(urls)) { - if (!urls[k]?.pc_url?.includes('search.bilibili.com')) { - return true - } - } - } - return false - }, - }, -} -// 一二级评论是否检测 -let isRootWhite = false -let isSubWhite = false - -class CommentFilterDynamic implements IMainFilter { - target: HTMLElement | undefined - - // 黑名单 - commentUsernameFilter = new CommentUsernameFilter() - commentContentFilter = new CommentContentFilter() - commentLevelFilter = new CommentLevelFilter() - commentBotFilter = new CommentBotFilter() - commentCallBotFilter = new CommentCallBotFilter() - commentCallUserFilter = new CommentCallUserFilter() - commentCallUserNoReplyFilter = new CommentCallUserNoReplyFilter() - commentCallUserOnlyFilter = new CommentCallUserOnlyFilter() - commentCallUserOnlyNoReplyFilter = new CommentCallUserOnlyNoReplyFilter() - // 白名单 - commentIsUpFilter = new CommentIsUpFilter() - commentIsPinFilter = new CommentIsPinFilter() - commentIsNoteFilter = new CommentIsNoteFilter() - commentIsLinkFilter = new CommentIsLinkFilter() - - init() { - // 黑名单 - this.commentUsernameFilter.setParam(BiliCleanerStorage.get(GM_KEYS.black.username.valueKey, [])) - this.commentContentFilter.setParam(BiliCleanerStorage.get(GM_KEYS.black.content.valueKey, [])) - this.commentLevelFilter.setParam(BiliCleanerStorage.get(GM_KEYS.black.level.valueKey, 0)) - this.commentBotFilter.setParam(bots) - this.commentCallBotFilter.setParam(bots) - this.commentCallUserFilter.setParam([`/./`]) - this.commentCallUserNoReplyFilter.setParam([`/./`]) - } - - /** - * 检测一级评论 - * @param mode full全量,incr增量 - * @returns - */ - async checkRoot(mode?: 'full' | 'incr') { - const timer = performance.now() - let revertAll = false - if ( - !( - this.commentUsernameFilter.isEnable || - this.commentContentFilter.isEnable || - this.commentLevelFilter.isEnable || - this.commentBotFilter.isEnable || - this.commentCallBotFilter.isEnable || - this.commentCallUserFilter.isEnable || - this.commentCallUserNoReplyFilter.isEnable || - this.commentCallUserOnlyFilter.isEnable || - this.commentCallUserOnlyNoReplyFilter.isEnable - ) - ) { - revertAll = true - } - - let rootComments: HTMLElement[] = [] - if (ShadowInstance.shadowStore.has('BILI-COMMENT-THREAD-RENDERER')) { - rootComments = Array.from(ShadowInstance.shadowStore.get('BILI-COMMENT-THREAD-RENDERER')!).map( - (v) => v.host as HTMLElement, - ) - if (mode === 'incr') { - rootComments = rootComments.filter((v) => !v.hasAttribute(settings.filterSign)) - } - } - if (!rootComments.length) { - return - } - - if (settings.enableDebugFilter) { - rootComments.forEach((v) => { - debug( - [ - `CommentFilterDynamic rootComments`, - `username: ${selectorFns.root.username(v)}`, - `content: ${selectorFns.root.content(v)}`, - `callUser: ${selectorFns.root.callUser(v)}`, - `callUserNoReply: ${selectorFns.root.callUserNoReply(v)}`, - `callUserOnly: ${selectorFns.root.callUserOnly(v)}`, - `callUserOnlyNoReply: ${selectorFns.root.callUserOnlyNoReply(v)}`, - `level: ${selectorFns.root.level(v)}`, - `isUp: ${selectorFns.root.isUp(v)}`, - `isPin: ${selectorFns.root.isPin(v)}`, - `isNote: ${selectorFns.root.isNote(v)}`, - `isLink: ${selectorFns.root.isLink(v)}`, - ].join('\n'), - ) - }) - } - - if (isRootWhite || revertAll) { - rootComments.forEach((el) => showEle(el)) - return - } - - const blackPairs: SubFilterPair[] = [] - this.commentUsernameFilter.isEnable && blackPairs.push([this.commentUsernameFilter, selectorFns.root.username]) - this.commentContentFilter.isEnable && blackPairs.push([this.commentContentFilter, selectorFns.root.content]) - this.commentLevelFilter.isEnable && blackPairs.push([this.commentLevelFilter, selectorFns.root.level]) - this.commentBotFilter.isEnable && blackPairs.push([this.commentBotFilter, selectorFns.root.username]) - this.commentCallBotFilter.isEnable && blackPairs.push([this.commentCallBotFilter, selectorFns.root.callUser]) - this.commentCallUserFilter.isEnable && blackPairs.push([this.commentCallUserFilter, selectorFns.root.callUser]) - this.commentCallUserNoReplyFilter.isEnable && - blackPairs.push([this.commentCallUserNoReplyFilter, selectorFns.root.callUserNoReply]) - this.commentCallUserOnlyFilter.isEnable && - blackPairs.push([this.commentCallUserOnlyFilter, selectorFns.root.callUserOnly]) - this.commentCallUserOnlyNoReplyFilter.isEnable && - blackPairs.push([this.commentCallUserOnlyNoReplyFilter, selectorFns.root.callUserOnlyNoReply]) - - const whitePairs: SubFilterPair[] = [] - this.commentIsUpFilter.isEnable && whitePairs.push([this.commentIsUpFilter, selectorFns.root.isUp]) - this.commentIsPinFilter.isEnable && whitePairs.push([this.commentIsPinFilter, selectorFns.root.isPin]) - this.commentIsNoteFilter.isEnable && whitePairs.push([this.commentIsNoteFilter, selectorFns.root.isNote]) - this.commentIsLinkFilter.isEnable && whitePairs.push([this.commentIsLinkFilter, selectorFns.root.isLink]) - - const rootBlackCnt = await coreCheck(rootComments, true, blackPairs, whitePairs) - const time = (performance.now() - timer).toFixed(1) - debug( - `CommentFilterDynamic hide ${rootBlackCnt} in ${rootComments.length} root comments, mode=${mode}, time=${time}`, - ) - } - - /** - * 检测二级评论 - * @param mode full全量,incr增量 - * @returns - */ - async checkSub(mode?: 'full' | 'incr') { - const timer = performance.now() - let revertAll = false - if ( - !( - this.commentUsernameFilter.isEnable || - this.commentContentFilter.isEnable || - this.commentLevelFilter.isEnable || - this.commentBotFilter.isEnable || - this.commentCallBotFilter.isEnable || - this.commentCallUserFilter.isEnable || - this.commentCallUserOnlyFilter.isEnable - ) - ) { - revertAll = true - } - - let subComments: HTMLElement[] = [] - if (ShadowInstance.shadowStore.has('BILI-COMMENT-REPLY-RENDERER')) { - subComments = Array.from(ShadowInstance.shadowStore.get('BILI-COMMENT-REPLY-RENDERER')!).map( - (v) => v.host as HTMLElement, - ) - if (mode === 'incr') { - subComments = subComments.filter((v) => !v.hasAttribute(settings.filterSign)) - } - } - if (!subComments.length) { - return - } - - if (settings.enableDebugFilter) { - subComments.forEach((v) => { - debug( - [ - `CommentFilterDynamic subComments`, - `username: ${selectorFns.sub.username(v)}`, - `content: ${selectorFns.sub.content(v)}`, - `callUser: ${selectorFns.sub.callUser(v)}`, - `callUserOnly: ${selectorFns.sub.callUserOnly(v)}`, - `level: ${selectorFns.sub.level(v)}`, - `isUp: ${selectorFns.sub.isUp(v)}`, - `isLink: ${selectorFns.sub.isLink(v)}`, - ].join('\n'), - ) - }) - } - - if (isSubWhite || revertAll) { - subComments.forEach((el) => showEle(el)) - return - } - - const blackPairs: SubFilterPair[] = [] - this.commentUsernameFilter.isEnable && blackPairs.push([this.commentUsernameFilter, selectorFns.sub.username]) - this.commentContentFilter.isEnable && blackPairs.push([this.commentContentFilter, selectorFns.sub.content]) - this.commentLevelFilter.isEnable && blackPairs.push([this.commentLevelFilter, selectorFns.sub.level]) - this.commentBotFilter.isEnable && blackPairs.push([this.commentBotFilter, selectorFns.sub.username]) - this.commentCallBotFilter.isEnable && blackPairs.push([this.commentCallBotFilter, selectorFns.sub.callUser]) - this.commentCallUserFilter.isEnable && blackPairs.push([this.commentCallUserFilter, selectorFns.sub.callUser]) - this.commentCallUserOnlyFilter.isEnable && - blackPairs.push([this.commentCallUserOnlyFilter, selectorFns.sub.callUserOnly]) - - const whitePairs: SubFilterPair[] = [] - this.commentIsUpFilter.isEnable && whitePairs.push([this.commentIsUpFilter, selectorFns.sub.isUp]) - this.commentIsLinkFilter.isEnable && whitePairs.push([this.commentIsLinkFilter, selectorFns.sub.isLink]) - - const subBlackCnt = await coreCheck(subComments, false, blackPairs, whitePairs) - const time = (performance.now() - timer).toFixed(1) - debug( - `CommentFilterDynamic hide ${subBlackCnt} in ${subComments.length} sub comments, mode=${mode}, time=${time}`, - ) - } - - check(mode?: 'full' | 'incr') { - this.checkRoot(mode) - .then() - .catch((err) => { - error('checkRoot failed', err) - }) - this.checkSub(mode) - .then() - .catch((err) => { - error('checkSub failed', err) - }) - } - - /** - * 监听一级/二级评论container - * 使用同一Observer监视所有二级评论上级节点,所有变化只触发一次回调 - */ - observe() { - ShadowInstance.addShadowObserver( - 'BILI-COMMENTS', - new MutationObserver(() => { - this.checkRoot('incr').then().catch() - }), - { - subtree: true, - childList: true, - }, - ) - - ShadowInstance.addShadowObserver( - 'BILI-COMMENT-REPLIES-RENDERER', - new MutationObserver(() => { - this.checkSub('full').then().catch() - }), - { - subtree: true, - childList: true, - }, - ) - } -} - -//================================================================================================== - -const mainFilter = new CommentFilterDynamic() - -export const commentFilterDynamicEntry = async () => { - mainFilter.init() - mainFilter.observe() -} - -export const commentFilterDynamicGroups: Group[] = [ - { - name: '评论用户过滤', - items: [ - { - type: 'switch', - id: GM_KEYS.black.username.statusKey, - name: '启用 评论用户过滤 (右键单击用户名)', - noStyle: true, - enableFn: () => { - mainFilter.commentUsernameFilter.enable() - mainFilter.check('full') - }, - disableFn: () => { - mainFilter.commentUsernameFilter.disable() - mainFilter.check('full') - }, - }, - { - type: 'editor', - id: GM_KEYS.black.username.valueKey, - name: '编辑 评论用户黑名单', - description: ['本黑名单与UP主黑名单互不影响', '右键屏蔽的用户会出现在首行'], - editorTitle: '评论区 用户黑名单', - editorDescription: ['每行一个用户名,保存时自动去重'], - saveFn: async () => { - mainFilter.commentUsernameFilter.setParam( - BiliCleanerStorage.get(GM_KEYS.black.username.valueKey, []), - ) - mainFilter.check('full') - }, - }, - ], - }, - { - name: '评论内容过滤', - items: [ - { - type: 'switch', - id: GM_KEYS.black.content.statusKey, - name: '启用 评论关键词过滤', - noStyle: true, - enableFn: () => { - mainFilter.commentContentFilter.enable() - mainFilter.check('full') - }, - disableFn: () => { - mainFilter.commentContentFilter.disable() - mainFilter.check('full') - }, - }, - { - type: 'editor', - id: GM_KEYS.black.content.valueKey, - name: '编辑 评论关键词黑名单', - editorTitle: '评论关键词 黑名单', - editorDescription: [ - '每行一个关键词或正则,不区分大小写', - '请勿使用过于激进的关键词或正则', - '正则默认 iu 模式,无需 flag,语法:/abc|\\d+/', - ], - saveFn: async () => { - mainFilter.commentContentFilter.setParam(BiliCleanerStorage.get(GM_KEYS.black.content.valueKey, [])) - mainFilter.check('full') - }, - }, - ], - }, - { - name: '按类型过滤', - items: [ - { - type: 'switch', - id: GM_KEYS.black.callBot.statusKey, - name: '过滤 召唤AI的评论', - noStyle: true, - enableFn: () => { - mainFilter.commentCallBotFilter.enable() - mainFilter.check('full') - }, - disableFn: () => { - mainFilter.commentCallBotFilter.disable() - mainFilter.check('full') - }, - }, - { - type: 'switch', - id: GM_KEYS.black.bot.statusKey, - name: '过滤 AI发布的评论', - noStyle: true, - enableFn: () => { - mainFilter.commentBotFilter.enable() - mainFilter.check('full') - }, - disableFn: () => { - mainFilter.commentBotFilter.disable() - mainFilter.check('full') - }, - }, - { - type: 'switch', - id: GM_KEYS.black.isAD.statusKey, - name: '过滤 带货评论 (实验功能)', - noStyle: true, - enableFn: () => { - fetchHook.addPostFn( - async ( - input: RequestInfo | URL, - init: RequestInit | undefined, - resp?: Response, - ): Promise => { - if (!resp) { - return - } - if ( - typeof input === 'string' && - init?.method?.toUpperCase() === 'GET' && - input.includes('api.bilibili.com/x/v2/reply/wbi/main') - ) { - try { - const respData = await resp.clone().json() - const msg = respData?.data?.top?.upper?.content?.message - if (msg && /b23\.tv\/mall-|领券|gaoneng\.bilibili\.com/.test(msg)) { - respData.data.top = null - respData.data.top_replies = null - return new Response(JSON.stringify(respData), { - status: resp.status, - statusText: resp.statusText, - headers: resp.headers, - }) - } - } catch { - return resp - } - return resp - } - }, - ) - }, - }, - { - type: 'switch', - id: GM_KEYS.black.callUserOnly.statusKey, - name: '过滤 只含 @其他用户 的全部评论', - noStyle: true, - enableFn: () => { - mainFilter.commentCallUserOnlyFilter.enable() - mainFilter.check('full') - }, - disableFn: () => { - mainFilter.commentCallUserOnlyFilter.disable() - mainFilter.check('full') - }, - }, - { - type: 'switch', - id: GM_KEYS.black.callUserOnlyNoReply.statusKey, - name: '过滤 只含 @其他用户 的无回复评论', - noStyle: true, - enableFn: () => { - mainFilter.commentCallUserOnlyNoReplyFilter.enable() - mainFilter.check('full') - }, - disableFn: () => { - mainFilter.commentCallUserOnlyNoReplyFilter.disable() - mainFilter.check('full') - }, - }, - { - type: 'switch', - id: GM_KEYS.black.callUser.statusKey, - name: '过滤 包含 @其他用户 的全部评论', - noStyle: true, - enableFn: () => { - mainFilter.commentCallUserFilter.enable() - mainFilter.check('full') - }, - disableFn: () => { - mainFilter.commentCallUserFilter.disable() - mainFilter.check('full') - }, - }, - { - type: 'switch', - id: GM_KEYS.black.callUserNoReply.statusKey, - name: '过滤 包含 @其他用户 的无回复评论', - noStyle: true, - enableFn: () => { - mainFilter.commentCallUserNoReplyFilter.enable() - mainFilter.check('full') - }, - disableFn: () => { - mainFilter.commentCallUserNoReplyFilter.disable() - mainFilter.check('full') - }, - }, - ], - }, - { - name: '等级过滤', - items: [ - { - type: 'switch', - id: GM_KEYS.black.level.statusKey, - name: '启用 用户等级过滤', - noStyle: true, - enableFn: () => { - mainFilter.commentLevelFilter.enable() - mainFilter.check('full') - }, - disableFn: () => { - mainFilter.commentLevelFilter.disable() - mainFilter.check('full') - }, - }, - { - type: 'number', - id: GM_KEYS.black.level.valueKey, - name: '设定最低等级 (0~6)', - minValue: 0, - maxValue: 6, - step: 1, - defaultValue: 0, - disableValue: 0, - fn: (value: number) => { - mainFilter.commentLevelFilter.setParam(value) - mainFilter.check('full') - }, - }, - ], - }, - { - name: '白名单 免过滤', - items: [ - { - type: 'switch', - id: GM_KEYS.white.root.statusKey, - name: '一级评论(主评论) 免过滤', - noStyle: true, - enableFn: () => { - isRootWhite = true - mainFilter.check('full') - }, - disableFn: () => { - isRootWhite = false - mainFilter.check('full') - }, - }, - { - type: 'switch', - id: GM_KEYS.white.sub.statusKey, - name: '二级评论(回复) 免过滤', - noStyle: true, - enableFn: () => { - isSubWhite = true - mainFilter.check('full') - }, - disableFn: () => { - isSubWhite = false - mainFilter.check('full') - }, - }, - { - type: 'switch', - id: GM_KEYS.white.isUp.statusKey, - name: 'UP主的评论 免过滤', - noStyle: true, - enableFn: () => { - mainFilter.commentIsUpFilter.enable() - mainFilter.check('full') - }, - disableFn: () => { - mainFilter.commentIsUpFilter.disable() - mainFilter.check('full') - }, - }, - { - type: 'switch', - id: GM_KEYS.white.isPin.statusKey, - name: '置顶评论 免过滤', - noStyle: true, - enableFn: () => { - mainFilter.commentIsPinFilter.enable() - mainFilter.check('full') - }, - disableFn: () => { - mainFilter.commentIsPinFilter.disable() - mainFilter.check('full') - }, - }, - { - type: 'switch', - id: GM_KEYS.white.isNote.statusKey, - name: '笔记/图片评论 免过滤', - noStyle: true, - enableFn: () => { - mainFilter.commentIsNoteFilter.enable() - mainFilter.check('full') - }, - disableFn: () => { - mainFilter.commentIsNoteFilter.disable() - mainFilter.check('full') - }, - }, - { - type: 'switch', - id: GM_KEYS.white.isLink.statusKey, - name: '含超链接的评论 免过滤', - noStyle: true, - enableFn: () => { - mainFilter.commentIsLinkFilter.enable() - mainFilter.check('full') - }, - disableFn: () => { - mainFilter.commentIsLinkFilter.disable() - mainFilter.check('full') - }, - }, - ], - }, -] - -// 右键菜单handler -export const commentFilterDynamicHandler: ContextMenuTargetHandler = (target: HTMLElement): FilterContextMenu[] => { - if (!isPageDynamic()) { - return [] - } - - const menus: FilterContextMenu[] = [] - if ( - target.parentElement?.id === 'user-name' || - target.classList.contains('user-name') || - target.classList.contains('sub-user-name') - ) { - const username = target.textContent?.trim() - if (username && mainFilter.commentUsernameFilter.isEnable) { - menus.push({ - name: `屏蔽用户:${username}`, - fn: async () => { - try { - mainFilter.commentUsernameFilter.addParam(username) - mainFilter.check('full') - const arr: string[] = BiliCleanerStorage.get(GM_KEYS.black.username.valueKey, []) - arr.unshift(username) - BiliCleanerStorage.set(GM_KEYS.black.username.valueKey, orderedUniq(arr)) - } catch (err) { - error(`commentFilterDynamicHandler add username ${username} failed`, err) - } - }, - }) - } - } - return menus -} diff --git a/src/modules/filters/variety/comment/pages/space.ts b/src/modules/filters/variety/comment/pages/legacy.ts similarity index 93% rename from src/modules/filters/variety/comment/pages/space.ts rename to src/modules/filters/variety/comment/pages/legacy.ts index 95c5c6a..7b48ef4 100644 --- a/src/modules/filters/variety/comment/pages/space.ts +++ b/src/modules/filters/variety/comment/pages/legacy.ts @@ -28,51 +28,51 @@ import { CommentIsLinkFilter, CommentIsNoteFilter, CommentIsPinFilter, CommentIs const GM_KEYS = { black: { username: { - statusKey: 'dynamic-comment-username-filter-status', + statusKey: 'video-comment-username-filter-status', valueKey: 'global-comment-username-filter-value', }, content: { - statusKey: 'dynamic-comment-content-filter-status', + statusKey: 'video-comment-content-filter-status', valueKey: 'global-comment-content-filter-value', }, level: { - statusKey: 'dynamic-comment-level-filter-status', + statusKey: 'video-comment-level-filter-status', valueKey: 'global-comment-level-filter-value', }, bot: { - statusKey: 'dynamic-comment-bot-filter-status', + statusKey: 'video-comment-bot-filter-status', }, callBot: { - statusKey: 'dynamic-comment-call-bot-filter-status', + statusKey: 'video-comment-call-bot-filter-status', }, callUser: { - statusKey: 'dynamic-comment-call-user-filter-status', + statusKey: 'video-comment-call-user-filter-status', }, callUserOnly: { - statusKey: 'dynamic-comment-call-user-only-filter-status', + statusKey: 'video-comment-call-user-only-filter-status', }, isAD: { - statusKey: 'dynamic-comment-ad-filter-status', + statusKey: 'video-comment-ad-filter-status', }, }, white: { root: { - statusKey: 'dynamic-comment-root-whitelist-status', + statusKey: 'video-comment-root-whitelist-status', }, sub: { - statusKey: 'dynamic-comment-sub-whitelist-status', + statusKey: 'video-comment-sub-whitelist-status', }, isUp: { - statusKey: 'dynamic-comment-uploader-whitelist-status', + statusKey: 'video-comment-uploader-whitelist-status', }, isPin: { - statusKey: 'dynamic-comment-pinned-whitelist-status', + statusKey: 'video-comment-pinned-whitelist-status', }, isNote: { - statusKey: 'dynamic-comment-note-whitelist-status', + statusKey: 'video-comment-note-whitelist-status', }, isLink: { - statusKey: 'dynamic-comment-link-whitelist-status', + statusKey: 'video-comment-link-whitelist-status', }, }, } @@ -170,7 +170,7 @@ const selectorFns = { let isRootWhite = false let isSubWhite = false -class CommentFilterSpace implements IMainFilter { +class CommentFilterLegacy implements IMainFilter { target: HTMLElement | undefined // 黑名单 @@ -231,7 +231,7 @@ class CommentFilterSpace implements IMainFilter { rootComments.forEach((v) => { debug( [ - `CommentFilterSpace rootComments`, + `CommentFilterLegacy rootComments`, `username: ${selectorFns.root.username(v)}`, `content: ${selectorFns.root.content(v)}`, `callUser: ${selectorFns.root.callUser(v)}`, @@ -247,7 +247,7 @@ class CommentFilterSpace implements IMainFilter { subComments.forEach((v) => { debug( [ - `CommentFilterSpace subComments`, + `CommentFilterLegacy subComments`, `username: ${selectorFns.sub.username(v)}`, `content: ${selectorFns.sub.content(v)}`, `callUser: ${selectorFns.sub.callUser(v)}`, @@ -320,7 +320,7 @@ class CommentFilterSpace implements IMainFilter { const time = (performance.now() - timer).toFixed(1) debug( - `CommentFilterSpace hide ${rootBlackCnt} in ${rootComments.length} root, ${subBlackCnt} in ${subComments.length} sub, mode=${mode}, time=${time}`, + `CommentFilterLegacy hide ${rootBlackCnt} in ${rootComments.length} root, ${subBlackCnt} in ${subComments.length} sub, mode=${mode}, time=${time}`, ) } @@ -328,7 +328,7 @@ class CommentFilterSpace implements IMainFilter { this.check('full') .then() .catch((err) => { - error('CommentFilterSpace check full error', err) + error('CommentFilterLegacy check full error', err) }) } @@ -336,7 +336,7 @@ class CommentFilterSpace implements IMainFilter { this.check('incr') .then() .catch((err) => { - error('CommentFilterSpace check incr error', err) + error('CommentFilterLegacy check incr error', err) }) } @@ -345,7 +345,7 @@ class CommentFilterSpace implements IMainFilter { return node.id === 'app' }).then((ele) => { if (ele) { - debug('CommentFilterSpace target appear') + debug('CommentFilterLegacy target appear') this.target = ele this.checkFull() const commentObserver = new MutationObserver(() => { @@ -358,14 +358,14 @@ class CommentFilterSpace implements IMainFilter { } //================================================================================================== -const mainFilter = new CommentFilterSpace() +const mainFilter = new CommentFilterLegacy() -export const commentFilterSpaceEntry = async () => { +export const commentFilterLegacyEntry = async () => { mainFilter.init() mainFilter.observe() } -export const commentFilterSpaceGroups: Group[] = [ +export const commentFilterLegacyGroups: Group[] = [ { name: '评论用户过滤', items: [ @@ -660,7 +660,7 @@ export const commentFilterSpaceGroups: Group[] = [ ] // 右键菜单handler -export const commentFilterSpaceHandler: ContextMenuTargetHandler = (target: HTMLElement): FilterContextMenu[] => { +export const commentFilterLegacyHandler: ContextMenuTargetHandler = (target: HTMLElement): FilterContextMenu[] => { if (!isPageSpace()) { return [] } @@ -683,7 +683,7 @@ export const commentFilterSpaceHandler: ContextMenuTargetHandler = (target: HTML arr.unshift(username) BiliCleanerStorage.set(GM_KEYS.black.username.valueKey, orderedUniq(arr)) } catch (err) { - error(`commentFilterSpaceHandler add username ${username} failed`, err) + error(`commentFilterLegacyHandler add username ${username} failed`, err) } }, }) diff --git a/src/modules/filters/variety/comment/subFilters/white.ts b/src/modules/filters/variety/comment/subFilters/white.ts index 90d6741..8df9521 100644 --- a/src/modules/filters/variety/comment/subFilters/white.ts +++ b/src/modules/filters/variety/comment/subFilters/white.ts @@ -7,3 +7,5 @@ export class CommentIsPinFilter extends BooleanFilter {} export class CommentIsNoteFilter extends BooleanFilter {} export class CommentIsLinkFilter extends BooleanFilter {} + +export class CommentIsMeFilter extends BooleanFilter {} diff --git a/src/modules/rules/video/groups/right.scss b/src/modules/rules/video/groups/right.scss index 761102d..b78c940 100644 --- a/src/modules/rules/video/groups/right.scss +++ b/src/modules/rules/video/groups/right.scss @@ -89,7 +89,43 @@ html[video-page-hide-right-container-reco-list-next-play] { } } -// 优化 视频合集列表高度 +// 恢复 分P视频 编号 +html[video-page-hide-right-container-multi-page-add-counter] { + .video-pod__list.multip.list { + counter-reset: section-counter; + + .video-pod__item { + &::before { + counter-increment: section-counter; + content: 'P' counter(section-counter); + font-size: 15px; + margin-right: 10px; + transition: color 0.2s; + } + &.active::before, + &:hover::before { + color: var(--brand_blue); + } + } + } +} + +// 展开 视频合集 第二行标题 +html[video-page-right-container-section-unfold-title] { + .video-pod.video-pod .section .video-pod__item { + .title { + height: fit-content !important; + } + .title-txt { + -webkit-line-clamp: 2 !important; + line-height: 21px !important; + margin-top: 4px !important; + margin-bottom: 4px !important; + } + } +} + +// 优化 视频合集 列表高度 html[video-page-hide-right-container-section-height] { .video-sections-content-list, .video-pod__body { @@ -162,27 +198,6 @@ html[video-page-hide-right-container-section-subscribe] { } } -// 恢复 分P视频 编号 -html[video-page-hide-right-container-multi-page-add-counter] { - .video-pod__list.multip.list { - counter-reset: section-counter; - - .video-pod__item { - &::before { - counter-increment: section-counter; - content: 'P' counter(section-counter); - font-size: 15px; - margin-right: 10px; - transition: color 0.2s; - } - &.active::before, - &:hover::before { - color: var(--brand_blue); - } - } - } -} - // 相关视频 视频信息置底 html[video-page-right-container-set-info-bottom] { :is(.video-page-card-small, .video-page-operator-card-small) .card-box .info { diff --git a/src/modules/rules/video/groups/right.ts b/src/modules/rules/video/groups/right.ts index 304c782..fa44363 100644 --- a/src/modules/rules/video/groups/right.ts +++ b/src/modules/rules/video/groups/right.ts @@ -39,15 +39,26 @@ export const videoRightItems: Item[] = [ }, { type: 'switch', - id: 'video-page-hide-right-container-section-next-btn', - name: '隐藏 视频合集 自动连播开关', + id: 'video-page-hide-right-container-multi-page-add-counter', + name: '恢复 分P视频 编号', + defaultEnable: true, + }, + { + type: 'switch', + id: 'video-page-right-container-section-unfold-title', + name: '展开 视频合集 第二行标题', }, { type: 'switch', id: 'video-page-hide-right-container-section-height', - name: '优化 视频合集列表高度', + name: '优化 视频合集 列表高度', defaultEnable: true, }, + { + type: 'switch', + id: 'video-page-hide-right-container-section-next-btn', + name: '隐藏 视频合集 自动连播开关', + }, { type: 'switch', id: 'video-page-hide-right-container-section-play-num', @@ -64,12 +75,6 @@ export const videoRightItems: Item[] = [ id: 'video-page-hide-right-container-section-subscribe', name: '隐藏 视频合集 订阅合集', }, - { - type: 'switch', - id: 'video-page-hide-right-container-multi-page-add-counter', - name: '恢复 分P视频 编号', - defaultEnable: true, - }, { type: 'switch', id: 'video-page-right-container-set-info-bottom', diff --git a/src/views/CommentFilterPanelView.vue b/src/views/CommentFilterPanelView.vue index 6ec2df0..3d0b052 100644 --- a/src/views/CommentFilterPanelView.vue +++ b/src/views/CommentFilterPanelView.vue @@ -1,7 +1,7 @@