From 4b5d09b5f3173875294fe63a13bf10a4e7725ff5 Mon Sep 17 00:00:00 2001 From: the1812 Date: Fri, 26 Apr 2024 08:31:39 +0800 Subject: [PATCH 01/21] Fix XSS vulnerability of the first suggest item --- src/components/launch-bar/search-provider.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/components/launch-bar/search-provider.ts b/src/components/launch-bar/search-provider.ts index b7085a7416..8b6cb81126 100644 --- a/src/components/launch-bar/search-provider.ts +++ b/src/components/launch-bar/search-provider.ts @@ -26,11 +26,13 @@ export const searchProvider: LaunchBarActionProvider = { content: async () => Vue.extend({ render: h => { - const content = h('div', { - domProps: { - innerHTML: /* html */ `${input}`, + const content = h( + 'div', + { + class: 'suggest-highlight', }, - }) + [input], + ) return content }, }), From 4979500d2c08fab161771a689c6f046531a537fd Mon Sep 17 00:00:00 2001 From: WakelessSloth56 Date: Fri, 26 Apr 2024 16:36:14 +0800 Subject: [PATCH 02/21] feat: wasm-output plugin supports multiple pages Co-authored-by: lainio24 --- .vscode/settings.json | 3 +- .../video/download/wasm-output/handler.ts | 64 ++++++++++++++++--- .../video/download/wasm-output/index.ts | 44 ++----------- 3 files changed, 62 insertions(+), 49 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 81dbe2a6b7..586e80f5f1 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -62,6 +62,7 @@ "linebreak", "Liveroom", "materialdesignicons", + "matroska", "medialist", "mimetype", "minmax", @@ -133,6 +134,6 @@ "*.tsx": "${capture}.ts", "tsconfig.json": "tsconfig.*.json", "package.json": "package-lock.json, yarn.lock, pnpm-lock.yaml, .*", - "index.ts": "index.*.ts, index.md, index.*.md", + "index.ts": "index.*.ts, index.md, index.*.md" } } diff --git a/registry/lib/plugins/video/download/wasm-output/handler.ts b/registry/lib/plugins/video/download/wasm-output/handler.ts index d4353e233f..bc977c3cd8 100644 --- a/registry/lib/plugins/video/download/wasm-output/handler.ts +++ b/registry/lib/plugins/video/download/wasm-output/handler.ts @@ -1,12 +1,17 @@ import { DownloadPackage } from '@/core/download' import { meta } from '@/core/meta' +import { getComponentSettings } from '@/core/settings' import { Toast } from '@/core/toast' +import { title as pluginTitle } from '.' +import type { Options } from '../../../../components/video/download' +import { DownloadVideoAction } from '../../../../components/video/download/types' import { FFmpeg } from './ffmpeg' import { getCacheOrGet, httpGet, toastProgress, toBlobUrl } from './utils' const ffmpeg = new FFmpeg() -async function load(toast: Toast) { +async function loadFFmpeg() { + const toast = Toast.info('初始化', pluginTitle) await ffmpeg.load({ workerLoadURL: toBlobUrl( await getCacheOrGet( @@ -33,24 +38,26 @@ async function load(toast: Toast) { 'application/wasm', ), }) + toast.message = '完成!' + toast.close() } -export async function run( + +async function single( name: string, - toast: Toast, videoUrl: string, audioUrl: string, isFlac: boolean, + pageIndex = 1, + totalPages = 1, ) { - if (!ffmpeg.loaded) { - await load(toast) - } + const toast = Toast.info('', `${pluginTitle} - ${pageIndex} / ${totalPages}`) ffmpeg.writeFile('video', await httpGet(videoUrl, toastProgress(toast, '正在下载视频流'))) ffmpeg.writeFile('audio', await httpGet(audioUrl, toastProgress(toast, '正在下载音频流'))) - toast.message = '混流中……' + toast.message = '混流中……' const outputExt = isFlac ? 'mkv' : 'mp4' - name = isFlac ? name.replace(/.[^/.]+$/, `.${outputExt}`) : name + name = name.replace(/.[^/.]+$/, `.${outputExt}`) await ffmpeg.exec([ '-i', 'video', @@ -59,7 +66,7 @@ export async function run( '-c:v', 'copy', '-c:a', - isFlac ? 'flac' : 'copy', + 'copy', '-f', isFlac ? 'matroska' : 'mp4', `output.${outputExt}`, @@ -71,7 +78,44 @@ export async function run( }) toast.message = '完成!' - toast.duration = 1500 + toast.duration = 1000 await DownloadPackage.single(name, outputBlob) } + +export async function run(action: DownloadVideoAction) { + if (!ffmpeg.loaded) { + await loadFFmpeg() + } + + const pages = lodash.chunk( + action.infos.flatMap(it => it.titledFragments), + 2, + ) + + const { dashAudioExtension, dashFlacAudioExtension, dashVideoExtension } = + getComponentSettings('downloadVideo').options + + for (let i = 0; i < pages.length; i++) { + const page = pages[i] + const [video, audio] = page + if ( + !( + page.length === 2 && + video.extension === dashVideoExtension && + (audio.extension === dashAudioExtension || audio.extension === dashFlacAudioExtension) + ) + ) { + throw new Error('仅支持 DASH 格式视频和音频') + } + + await single( + video.title, + video.url, + audio.url, + audio.extension === dashFlacAudioExtension, + i + 1, + pages.length, + ) + } +} diff --git a/registry/lib/plugins/video/download/wasm-output/index.ts b/registry/lib/plugins/video/download/wasm-output/index.ts index 12ad5fe00c..878bff1fe6 100644 --- a/registry/lib/plugins/video/download/wasm-output/index.ts +++ b/registry/lib/plugins/video/download/wasm-output/index.ts @@ -1,11 +1,9 @@ -import { Toast, ToastType } from '@/core/toast' +import { Toast } from '@/core/toast' import { PluginMetadata } from '@/plugins/plugin' import { DownloadVideoOutput } from '../../../../components/video/download/types' import { run } from './handler' -import { getComponentSettings } from '@/core/settings' -import type { Options } from '../../../../components/video/download' -const title = 'WASM 混流输出' +export const title = 'WASM 混流输出' const desc = '使用 WASM 在浏览器中下载并合并音视频' export const plugin: PluginMetadata = { @@ -23,40 +21,10 @@ export const plugin: PluginMetadata = { displayName: 'WASM', description: `${desc},运行过程中请勿关闭页面,初次使用或清除缓存后需要加载约 30 MB 的 WASM 文件`, runAction: async action => { - const fragments = action.infos.flatMap(it => it.titledFragments) - const { dashAudioExtension, dashFlacAudioExtension, dashVideoExtension } = - getComponentSettings('downloadVideo').options - - if ( - fragments.length > 2 || - (fragments.length === 2 && - !( - fragments[0].extension === dashVideoExtension && - (fragments[1].extension === dashAudioExtension || - fragments[1].extension === dashFlacAudioExtension) - )) - ) { - Toast.error('仅支持单个视频下载', title).duration = 1500 - } else { - const toast = Toast.info('正在加载', title) - try { - if (fragments.length === 2) { - await run( - fragments[0].title, - toast, - fragments[0].url, - fragments[1].url, - fragments[1].extension === dashFlacAudioExtension, - ) // [dash] - } else { - toast.type = ToastType.Error - toast.message = '仅支持 dash 格式视频下载' - toast.duration = 1500 - } - } catch (error) { - toast.close() - Toast.error(String(error), title) - } + try { + await run(action) + } catch (error) { + Toast.error(String(error), title) } }, }) From b4853c8f7596072179b975a26876b7084db33391 Mon Sep 17 00:00:00 2001 From: WakelessSloth56 Date: Fri, 26 Apr 2024 18:02:38 +0800 Subject: [PATCH 03/21] refactor: use action.infos directly --- .../plugins/video/download/wasm-output/handler.ts | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/registry/lib/plugins/video/download/wasm-output/handler.ts b/registry/lib/plugins/video/download/wasm-output/handler.ts index bc977c3cd8..1c48e12fd3 100644 --- a/registry/lib/plugins/video/download/wasm-output/handler.ts +++ b/registry/lib/plugins/video/download/wasm-output/handler.ts @@ -11,7 +11,7 @@ import { getCacheOrGet, httpGet, toastProgress, toBlobUrl } from './utils' const ffmpeg = new FFmpeg() async function loadFFmpeg() { - const toast = Toast.info('初始化', pluginTitle) + const toast = Toast.info('正在加载 FFmpeg', `${pluginTitle} - 初始化`) await ffmpeg.load({ workerLoadURL: toBlobUrl( await getCacheOrGet( @@ -88,20 +88,16 @@ export async function run(action: DownloadVideoAction) { await loadFFmpeg() } - const pages = lodash.chunk( - action.infos.flatMap(it => it.titledFragments), - 2, - ) - const { dashAudioExtension, dashFlacAudioExtension, dashVideoExtension } = getComponentSettings('downloadVideo').options + const pages = action.infos for (let i = 0; i < pages.length; i++) { const page = pages[i] - const [video, audio] = page + const [video, audio] = page.titledFragments if ( !( - page.length === 2 && + page.fragments.length === 2 && video.extension === dashVideoExtension && (audio.extension === dashAudioExtension || audio.extension === dashFlacAudioExtension) ) From 354c1ea7d4a8a997fb30fb35283ceb1023dd226a Mon Sep 17 00:00:00 2001 From: the1812 Date: Fri, 10 May 2024 08:51:06 +0800 Subject: [PATCH 04/21] Update description (#4734) --- registry/lib/plugins/video/download/wasm-output/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/registry/lib/plugins/video/download/wasm-output/index.ts b/registry/lib/plugins/video/download/wasm-output/index.ts index 878bff1fe6..3cde08f64c 100644 --- a/registry/lib/plugins/video/download/wasm-output/index.ts +++ b/registry/lib/plugins/video/download/wasm-output/index.ts @@ -4,7 +4,7 @@ import { DownloadVideoOutput } from '../../../../components/video/download/types import { run } from './handler' export const title = 'WASM 混流输出' -const desc = '使用 WASM 在浏览器中下载并合并音视频' +const desc = '使用 WASM 在浏览器中下载并合并音视频, 支持批量下载' export const plugin: PluginMetadata = { name: 'downloadVideo.outputs.wasm', From 0bc86f688ce4b8b09860290b2672fb20434c7db8 Mon Sep 17 00:00:00 2001 From: the1812 Date: Fri, 10 May 2024 08:51:29 +0800 Subject: [PATCH 05/21] Fix typo --- .../video/download/wasm-output/database.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/registry/lib/plugins/video/download/wasm-output/database.ts b/registry/lib/plugins/video/download/wasm-output/database.ts index 091fbee6e5..0be2ae1911 100644 --- a/registry/lib/plugins/video/download/wasm-output/database.ts +++ b/registry/lib/plugins/video/download/wasm-output/database.ts @@ -6,7 +6,7 @@ export const storeNames = { } as const async function database() { - return new Promise((reslove: (db: IDBDatabase) => void, reject) => { + return new Promise((resolve: (db: IDBDatabase) => void, reject) => { const req = unsafeWindow.indexedDB.open(DB_NAME, DB_VERSION) req.onerror = reject req.onupgradeneeded = () => { @@ -18,34 +18,34 @@ async function database() { db.createObjectStore(v) }) } - req.onsuccess = () => reslove(req.result) + req.onsuccess = () => resolve(req.result) }) } async function objectStore(name: string, mode?: IDBTransactionMode) { return database().then( db => - new Promise((reslove: (db: IDBObjectStore) => void, reject) => { + new Promise((resolve: (db: IDBObjectStore) => void, reject) => { const tr = db.transaction(name, mode) - reslove(tr.objectStore(name)) + resolve(tr.objectStore(name)) tr.onerror = reject }), ) } async function get(store: IDBObjectStore, key: IDBValidKey | IDBKeyRange) { - return new Promise((reslove: (db: any) => void, reject) => { + return new Promise((resolve: (db: any) => void, reject) => { const res = store.get(key) res.onerror = reject - res.onsuccess = () => reslove(res.result) + res.onsuccess = () => resolve(res.result) }) } async function put(store: IDBObjectStore, value: any, key?: IDBValidKey) { - return new Promise((reslove: (db: IDBValidKey) => void, reject) => { + return new Promise((resolve: (db: IDBValidKey) => void, reject) => { const res = store.put(value, key) res.onerror = reject - res.onsuccess = () => reslove(res.result) + res.onsuccess = () => resolve(res.result) }) } From 91b6a606bcba00931f8d2d59e93e0a29861a8dc7 Mon Sep 17 00:00:00 2001 From: the1812 Date: Fri, 10 May 2024 19:53:30 +0800 Subject: [PATCH 06/21] Refactor comment callback params --- src/components/utils/comment/areas/base.ts | 31 ++++++++++--------- .../utils/comment/comment-area-manager.ts | 20 +++++++----- src/components/utils/comment/types.ts | 4 +++ 3 files changed, 34 insertions(+), 21 deletions(-) diff --git a/src/components/utils/comment/areas/base.ts b/src/components/utils/comment/areas/base.ts index 3130a07bbf..d733495cb6 100644 --- a/src/components/utils/comment/areas/base.ts +++ b/src/components/utils/comment/areas/base.ts @@ -1,6 +1,6 @@ import { childListSubtree } from '@/core/observer' import type { CommentItem } from '../comment-item' -import type { CommentItemCallback } from '../types' +import type { CommentCallbackInput, CommentCallbackPair, CommentItemCallback } from '../types' import type { CommentReplyItem } from '../reply-item' import { getRandomId } from '@/core/utils' @@ -12,8 +12,7 @@ export abstract class CommentArea { items: CommentItem[] = [] /** 与之关联的 MutationObserver */ protected observer?: MutationObserver - protected itemAddedCallbacks: CommentItemCallback[] = [] - protected itemRemovedCallbacks: CommentItemCallback[] = [] + protected itemCallbacks: CommentCallbackPair[] = [] protected static replyItemClasses = ['list-item.reply-wrap', 'reply-item'] protected static replyItemSelector = CommentArea.replyItemClasses.map(c => `.${c}`).join(',') @@ -52,7 +51,7 @@ export abstract class CommentArea { this.items = elements.map(it => this.parseCommentItem(it as HTMLElement)) } this.items.forEach(item => { - this.itemAddedCallbacks.forEach(c => c(item)) + this.itemCallbacks.forEach(c => c.added?.(item)) }) ;[this.observer] = childListSubtree(this.element, records => { const observerCallId = getRandomId() @@ -77,14 +76,14 @@ export abstract class CommentArea { addedCommentElements.forEach(n => { const commentItem = this.parseCommentItem(n) this.items.push(commentItem) - this.itemAddedCallbacks.forEach(c => c(commentItem)) + this.itemCallbacks.forEach(c => c.added?.(commentItem)) }) removedCommentElements.forEach(n => { const id = this.getCommentId(n) const index = this.items.findIndex(item => item.id === id) if (index !== -1) { const [commentItem] = this.items.splice(index, 1) - this.itemRemovedCallbacks.forEach(c => c(commentItem)) + this.itemCallbacks.forEach(c => c.removed?.(commentItem)) } }) performance.mark(`observeItems subtree end ${observerCallId}`) @@ -98,14 +97,18 @@ export abstract class CommentArea { performance.measure('observeItems', 'observeItems start', 'observeItems end') } - forEachCommentItem(callbacks: { added?: CommentItemCallback; removed?: CommentItemCallback }) { - const { added, removed } = callbacks - if (added) { - this.items.forEach(item => added(item)) - this.itemAddedCallbacks.push(added) - } - if (removed) { - this.itemRemovedCallbacks.push(removed) + static resolveCallbackPair void>( + input: CommentCallbackInput, + ): CommentCallbackPair { + if (typeof input === 'function') { + return { added: input } } + return input + } + + forEachCommentItem(input: CommentCallbackInput) { + const pair = CommentArea.resolveCallbackPair(input) + this.items.forEach(item => pair.added?.(item)) + this.itemCallbacks.push(pair) } } diff --git a/src/components/utils/comment/comment-area-manager.ts b/src/components/utils/comment/comment-area-manager.ts index 2f8a32fe51..3d0d4e5ff5 100644 --- a/src/components/utils/comment/comment-area-manager.ts +++ b/src/components/utils/comment/comment-area-manager.ts @@ -1,12 +1,17 @@ import { allMutations } from '@/core/observer' import { getCommentArea } from './comment-area' -import { CommentAreaCallback, CommentItemCallback } from './types' +import { + CommentAreaCallback, + CommentCallbackInput, + CommentCallbackPair, + CommentItemCallback, +} from './types' import { CommentArea } from './areas/base' export class CommentAreaManager { /** 当前页面所有的评论区列表 */ commentAreas: CommentArea[] = [] - commentAreaCallbacks: CommentAreaCallback[] = [] + commentAreaCallbacks: CommentCallbackPair[] = [] protected static commentAreaClasses = ['bili-comment', 'bb-comment'] @@ -29,16 +34,17 @@ export class CommentAreaManager { const area = getCommentArea(node) this.commentAreas.push(area) area.observeItems() - this.commentAreaCallbacks.forEach(c => c(area)) + this.commentAreaCallbacks.forEach(c => c.added?.(area)) } } - forEachCommentArea(callback: CommentAreaCallback) { - this.commentAreas.forEach(it => callback(it)) - this.commentAreaCallbacks.push(callback) + forEachCommentArea(input: CommentCallbackInput) { + const pair = CommentArea.resolveCallbackPair(input) + this.commentAreas.forEach(it => pair.added?.(it)) + this.commentAreaCallbacks.push(pair) } - forEachCommentItem(callbacks: { added?: CommentItemCallback; removed?: CommentItemCallback }) { + forEachCommentItem(callbacks: CommentCallbackPair) { this.forEachCommentArea(area => area.forEachCommentItem(callbacks)) } } diff --git a/src/components/utils/comment/types.ts b/src/components/utils/comment/types.ts index c11dddfc53..af8d781b13 100644 --- a/src/components/utils/comment/types.ts +++ b/src/components/utils/comment/types.ts @@ -8,3 +8,7 @@ export const RepliesUpdateEventType = 'repliesUpdate' export type RepliesUpdateEventCallback = (event: CustomEvent) => void export type CommentItemCallback = (item: CommentItem) => void export type CommentAreaCallback = (area: CommentArea) => void +export type CommentCallbackPair void> = { added?: T; removed?: T } +export type CommentCallbackInput void> = + | CommentCallbackPair + | T From 690604a31bf025229c1d7c47da0ca7128ff75312 Mon Sep 17 00:00:00 2001 From: the1812 Date: Fri, 10 May 2024 20:06:50 +0800 Subject: [PATCH 07/21] Add comment area removed callbacks --- src/components/utils/comment/areas/base.ts | 7 +++++++ .../utils/comment/comment-area-manager.ts | 15 ++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/components/utils/comment/areas/base.ts b/src/components/utils/comment/areas/base.ts index d733495cb6..1535690d19 100644 --- a/src/components/utils/comment/areas/base.ts +++ b/src/components/utils/comment/areas/base.ts @@ -97,6 +97,13 @@ export abstract class CommentArea { performance.measure('observeItems', 'observeItems start', 'observeItems end') } + destroy() { + this.observer?.disconnect() + this.items.forEach(item => { + this.itemCallbacks.forEach(pair => pair.removed?.(item)) + }) + } + static resolveCallbackPair void>( input: CommentCallbackInput, ): CommentCallbackPair { diff --git a/src/components/utils/comment/comment-area-manager.ts b/src/components/utils/comment/comment-area-manager.ts index 3d0d4e5ff5..0873659fc8 100644 --- a/src/components/utils/comment/comment-area-manager.ts +++ b/src/components/utils/comment/comment-area-manager.ts @@ -1,4 +1,4 @@ -import { allMutations } from '@/core/observer' +import { allMutations, childList } from '@/core/observer' import { getCommentArea } from './comment-area' import { CommentAreaCallback, @@ -7,6 +7,7 @@ import { CommentItemCallback, } from './types' import { CommentArea } from './areas/base' +import { deleteValue } from '@/core/utils' export class CommentAreaManager { /** 当前页面所有的评论区列表 */ @@ -35,6 +36,18 @@ export class CommentAreaManager { this.commentAreas.push(area) area.observeItems() this.commentAreaCallbacks.forEach(c => c.added?.(area)) + const [observer] = childList(area.element.parentElement, records => { + records.forEach(r => { + r.removedNodes.forEach(removedNode => { + if (removedNode === area.element) { + deleteValue(this.commentAreas, a => a === area) + this.commentAreaCallbacks.forEach(c => c.removed?.(area)) + area.destroy() + observer.disconnect() + } + }) + }) + }) } } From 917b0690e92bdbe1aa1de668e136cb703152c76a Mon Sep 17 00:00:00 2001 From: the1812 Date: Fri, 10 May 2024 20:11:41 +0800 Subject: [PATCH 08/21] Add vueProps to CommentItem --- src/components/utils/comment/areas/v1.ts | 2 ++ src/components/utils/comment/areas/v2.ts | 36 ++++++++++++---------- src/components/utils/comment/reply-item.ts | 3 ++ 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/src/components/utils/comment/areas/v1.ts b/src/components/utils/comment/areas/v1.ts index 2e1861c874..60090ece72 100644 --- a/src/components/utils/comment/areas/v1.ts +++ b/src/components/utils/comment/areas/v1.ts @@ -44,6 +44,7 @@ export class CommentAreaV1 extends CommentArea { content: replyElement.querySelector('.text-con').textContent, timeText: replyElement.querySelector('.info .time, .info .time-location').textContent, likes: parseInt(replyElement.querySelector('.info .like span').textContent), + vueProps: undefined, }) } const item = new CommentItem({ @@ -55,6 +56,7 @@ export class CommentAreaV1 extends CommentArea { timeText: element.querySelector('.con .info .time, .info .time-location').textContent, likes: parseInt(element.querySelector('.con .like span').textContent), replies: [], + vueProps: undefined, }) if (dq(element, '.reply-box .view-more')) { const replyBox = dq(element, '.reply-box') as HTMLElement diff --git a/src/components/utils/comment/areas/v2.ts b/src/components/utils/comment/areas/v2.ts index 5401eaacd2..0df277f7a7 100644 --- a/src/components/utils/comment/areas/v2.ts +++ b/src/components/utils/comment/areas/v2.ts @@ -31,7 +31,7 @@ export class CommentAreaV2 extends CommentArea { } /** 获取 Vue 数据 (评论 / 回复) */ - protected getReplyFromVueData(element: HTMLElement) { + protected getReplyFromVueProps(element: HTMLElement) { const props = (element as HTMLElementWithVue)._vnode?.props return props?.reply ?? props?.subReply } @@ -39,7 +39,7 @@ export class CommentAreaV2 extends CommentArea { /** 获取回复对应的元素 */ protected getReplyItemElement(parent: HTMLElement, replyId: string) { const [replyElement] = dqa(parent, '.sub-reply-item').filter( - (it: HTMLElement) => this.getReplyFromVueData(it).rpid_str === replyId, + (it: HTMLElement) => this.getReplyFromVueProps(it).rpid_str === replyId, ) return replyElement as HTMLElement } @@ -77,15 +77,15 @@ export class CommentAreaV2 extends CommentArea { } parseCommentItem(element: HTMLElement): CommentItem { - const vueData = this.getReplyFromVueData(element) - if (!vueData) { + const vueProps = this.getReplyFromVueProps(element) + if (!vueProps) { throw new Error('Invalid comment item') } const parseReplies = () => { - if (!vueData.replies) { + if (!vueProps.replies) { return [] } - return vueData.replies.map((r: any): CommentReplyItem => { + return vueProps.replies.map((r: any): CommentReplyItem => { return new CommentReplyItem({ id: r.rpid_str, element: this.getReplyItemElement(element, r.rpid_str), @@ -94,23 +94,25 @@ export class CommentAreaV2 extends CommentArea { content: r.content.message, time: r.ctime * 1000, likes: r.like, + vueProps, }) }) } const item = new CommentItem({ - id: vueData.rpid_str, + id: vueProps.rpid_str, element, - userId: vueData.member.mid, - userName: vueData.member.uname, - content: vueData.content.message, - time: vueData.ctime * 1000, - likes: vueData.like, - pictures: vueData.content?.pictures?.map((img: any) => { + userId: vueProps.member.mid, + userName: vueProps.member.uname, + content: vueProps.content.message, + time: vueProps.ctime * 1000, + likes: vueProps.like, + pictures: vueProps.content?.pictures?.map((img: any) => { return img.img_src }), replies: parseReplies(), + vueProps, }) - if (item.replies.length < vueData.rcount) { + if (item.replies.length < vueProps.rcount) { const replyBox = dq(element, '.sub-reply-list') childList(replyBox, records => { performance.mark(`parseReplies start ${item.id}`) @@ -141,11 +143,11 @@ export class CommentAreaV2 extends CommentArea { return item } getCommentId(element: HTMLElement): string { - const vueData = this.getReplyFromVueData(element) - if (!vueData?.rpid_str) { + const vueProps = this.getReplyFromVueProps(element) + if (!vueProps?.rpid_str) { throw new Error('Invalid comment item') } - return vueData.rpid_str + return vueProps.rpid_str } static isV2Area(element: HTMLElement) { diff --git a/src/components/utils/comment/reply-item.ts b/src/components/utils/comment/reply-item.ts index 3f73f9f35d..c15bbc2411 100644 --- a/src/components/utils/comment/reply-item.ts +++ b/src/components/utils/comment/reply-item.ts @@ -16,6 +16,8 @@ export class CommentReplyItem extends EventTarget { time?: number /** 点赞数 */ likes: number + /** 对应的 Vue Props */ + vueProps: any constructor(initParams: Omit) { super() @@ -27,5 +29,6 @@ export class CommentReplyItem extends EventTarget { this.timeText = initParams.timeText this.time = initParams.time this.likes = initParams.likes + this.vueProps = initParams.vueProps } } From 1899c12f25264af30d589904d46775d4d6913531 Mon Sep 17 00:00:00 2001 From: the1812 Date: Fri, 10 May 2024 20:18:52 +0800 Subject: [PATCH 09/21] Fix getIpLocation (fix #4690) --- registry/lib/components/utils/ip-show/index.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/registry/lib/components/utils/ip-show/index.ts b/registry/lib/components/utils/ip-show/index.ts index 5cef06dff8..f8747a527f 100644 --- a/registry/lib/components/utils/ip-show/index.ts +++ b/registry/lib/components/utils/ip-show/index.ts @@ -4,9 +4,8 @@ import { defineComponentMetadata } from '@/components/define' import { CommentItem, CommentReplyItem } from '@/components/utils/comment-apis' // 新版评论区IP属地获取 -const getIpLocation = (element: HTMLElement) => { - const props = (element as any).__vueParentComponent?.props - const reply = props?.reply ?? props?.subReply +const getIpLocation = (item: CommentReplyItem) => { + const reply = item.vueProps return reply?.reply_control?.location ?? undefined } @@ -268,7 +267,7 @@ observer.observe(document.head, { childList: true }) const processItems = (items: CommentReplyItem[]) => { items.forEach(item => { - const location = getIpLocation(item.element) + const location = getIpLocation(item) if (location !== undefined) { const replyTime = item.element.querySelector('.reply-info>.reply-time') ?? From 8f701e9434595c29e64145dbd36f0a83b7a5b068 Mon Sep 17 00:00:00 2001 From: the1812 Date: Sun, 12 May 2024 13:20:48 +0800 Subject: [PATCH 10/21] Extract FocusTarget (fix #4732) --- src/components/launch-bar/LaunchBar.vue | 65 +++++++++++++---------- src/components/launch-bar/focus-target.ts | 38 +++++++++++++ 2 files changed, 75 insertions(+), 28 deletions(-) create mode 100644 src/components/launch-bar/focus-target.ts diff --git a/src/components/launch-bar/LaunchBar.vue b/src/components/launch-bar/LaunchBar.vue index 8d0a7d145c..bd0c02ff5a 100644 --- a/src/components/launch-bar/LaunchBar.vue +++ b/src/components/launch-bar/LaunchBar.vue @@ -28,9 +28,9 @@ v-for="(a, index) of actions" :key="a.key" :action="a" - @previous-item="previousItem($event, index)" - @next-item="nextItem($event, index)" - @delete-item="onDeleteItem($event, index)" + @previous-item="previousItem()" + @next-item="nextItem()" + @delete-item="onDeleteItem()" @action=" index === actions.length - 1 && onClearHistory() onAction(a) @@ -49,12 +49,12 @@ class="suggest-item disabled" > @@ -66,6 +66,7 @@ import Fuse from 'fuse.js' import { VIcon, VLoading, VEmpty } from '@/ui' import { registerAndGetData } from '@/plugins/data' import { select } from '@/core/spin-query' +import { ascendingSort } from '@/core/utils/sort' import { matchUrlPattern } from '@/core/utils' import ActionItem from './ActionItem.vue' import { @@ -75,7 +76,7 @@ import { } from './launch-bar-action' import { searchProvider, search } from './search-provider' import { historyProvider } from './history-provider' -import { ascendingSort } from '@/core/utils/sort' +import { FocusTarget } from './focus-target' const [actionProviders] = registerAndGetData(LaunchBarActionProviders, [ searchProvider, @@ -144,10 +145,12 @@ export default Vue.extend({ ActionItem, }, data() { + const focusTarget = new FocusTarget(0) return { recommended, actions: [], keyword: '', + focusTarget, noActions: false, } }, @@ -160,9 +163,15 @@ export default Vue.extend({ keyword() { this.getActions() }, + actions() { + this.focusTarget.reset(this.actions.length) + }, }, async mounted() { - this.getActions() + await this.getActions() + this.focusTarget.addEventListener('index-change', () => { + this.handleIndexUpdate() + }) if (!matchUrlPattern(/^https?:\/\/search\.bilibili\.com/)) { return } @@ -211,47 +220,47 @@ export default Vue.extend({ if (e.isComposing) { return } - this.$refs.list.querySelector('.suggest-item:last-child').focus() + this.focusTarget.previous() e.preventDefault() }, handleDown(e: KeyboardEvent) { if (e.isComposing) { return } - this.$refs.list.querySelector('.suggest-item').focus() + this.focusTarget.next() e.preventDefault() }, - previousItem(element: HTMLElement, index: number) { - if (index === 0) { - this.focus() - } else { - ;(element.previousElementSibling as HTMLElement).focus() + handleIndexUpdate() { + if (!this.focusTarget.hasFocus) { + this.focusInput() + return } + this.focusSuggestItem(this.focusTarget.index + 1) }, - nextItem(element: HTMLElement, index: number) { - const lastItemIndex = this.actions.length - 1 - if (index !== lastItemIndex) { - ;(element.nextElementSibling as HTMLElement).focus() - } else { - this.focus() - } + previousItem() { + this.focusTarget.previous() + }, + nextItem() { + this.focusTarget.next() }, search, - onDeleteItem(element: HTMLElement, index: number) { - this.previousItem(element, index) + onDeleteItem() { + this.focusTarget.previous() this.getActions() }, onClearHistory() { - this.focus() + this.focusInput() this.getActions() }, onAction() { - // this.focus() this.handleSelect() }, - focus() { + focusInput() { this.$refs.input.focus() }, + focusSuggestItem(nth: number) { + this.$refs.list.querySelector(`.suggest-item:nth-child(${nth})`)?.focus() + }, }, }) diff --git a/src/components/launch-bar/focus-target.ts b/src/components/launch-bar/focus-target.ts new file mode 100644 index 0000000000..6207ecffd9 --- /dev/null +++ b/src/components/launch-bar/focus-target.ts @@ -0,0 +1,38 @@ +export class FocusTarget extends EventTarget { + /** + * -1: Input Focus + * > -1: Item Focus + */ + private itemIndex = -1 + private itemLength = 0 + + constructor(length: number, index = -1) { + super() + this.itemLength = length + this.index = index + } + + get index() { + return this.itemIndex + } + private set index(value: number) { + this.itemIndex = lodash.clamp(value, -1, this.itemLength - 1) + this.dispatchEvent(new CustomEvent('index-change', { detail: this })) + } + get hasFocus() { + return this.itemIndex > -1 + } + + reset(length: number, index = this.index) { + this.itemLength = length + this.index = index + } + next() { + this.index += 1 + console.log(this.index) + } + previous() { + this.index -= 1 + console.log(this.index) + } +} From 57c281988bcf4d0228fc9d0f0cf78b97856b0cd0 Mon Sep 17 00:00:00 2001 From: the1812 Date: Sun, 12 May 2024 13:28:00 +0800 Subject: [PATCH 11/21] Fix widgets not cleared (fix #4731) --- src/components/settings-panel/WidgetsPanel.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/settings-panel/WidgetsPanel.vue b/src/components/settings-panel/WidgetsPanel.vue index 228671cb80..23d2e794ba 100644 --- a/src/components/settings-panel/WidgetsPanel.vue +++ b/src/components/settings-panel/WidgetsPanel.vue @@ -63,6 +63,7 @@ export default Vue.extend({ }, watch: { allWidgets() { + this.widgets = [] this.allWidgets.forEach(async (w: Widget) => { const add = await widgetFilter(w) if (add) { From 1a0f6ab5dda5ba044ddd0084746b210ee6f21d1b Mon Sep 17 00:00:00 2001 From: the1812 Date: Sun, 12 May 2024 13:30:14 +0800 Subject: [PATCH 12/21] Fix widgets panel wrap (fix #4730) --- src/components/settings-panel/WidgetsPanel.vue | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/components/settings-panel/WidgetsPanel.vue b/src/components/settings-panel/WidgetsPanel.vue index 23d2e794ba..da6c9c0783 100644 --- a/src/components/settings-panel/WidgetsPanel.vue +++ b/src/components/settings-panel/WidgetsPanel.vue @@ -94,22 +94,10 @@ export default Vue.extend({ @include v-center(); justify-content: flex-start; align-items: flex-start; - flex-wrap: wrap; padding: 16px; padding-right: 20px; - // background-color: #f8f8f8; - // border-radius: 0 8px 8px 0; - // border: 1px solid #e8e8e8; - // border-left-width: 0; - // box-sizing: content-box; - // overflow: auto; @include popup(); @include text-color(); - // @include shadow(); - // body.dark & { - // background-color: #1a1a1a; - // border-color: #333; - // } &-header { flex: 0 0 auto; @include h-center(); From c580d67617c30ab06f3dc8a57f26310ec66e321e Mon Sep 17 00:00:00 2001 From: the1812 Date: Sun, 12 May 2024 13:40:08 +0800 Subject: [PATCH 13/21] Fix keyword sync (fix #4721) --- src/components/launch-bar/LaunchBar.vue | 32 ++++++++++++------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/components/launch-bar/LaunchBar.vue b/src/components/launch-bar/LaunchBar.vue index bd0c02ff5a..b1a9050df7 100644 --- a/src/components/launch-bar/LaunchBar.vue +++ b/src/components/launch-bar/LaunchBar.vue @@ -68,6 +68,7 @@ import { registerAndGetData } from '@/plugins/data' import { select } from '@/core/spin-query' import { ascendingSort } from '@/core/utils/sort' import { matchUrlPattern } from '@/core/utils' +import { urlChange } from '@/core/observer' import ActionItem from './ActionItem.vue' import { LaunchBarActionProviders, @@ -169,30 +170,29 @@ export default Vue.extend({ }, async mounted() { await this.getActions() + if (matchUrlPattern(/^https?:\/\/search\.bilibili\.com/)) { + await this.setupSearchPageSync() + } this.focusTarget.addEventListener('index-change', () => { this.handleIndexUpdate() }) - if (!matchUrlPattern(/^https?:\/\/search\.bilibili\.com/)) { - return - } - select('#search-keyword, .search-input-el').then((input: HTMLInputElement) => { + }, + methods: { + getOnlineActions: lodash.debounce(getOnlineActions, 200), + getActions, + async setupSearchPageSync() { + const selector = '#search-keyword, .search-input-el' + const input = (await select(selector)) as HTMLInputElement if (!input) { return } this.keyword = input.value - document.addEventListener('change', e => { - if (!(e.target instanceof HTMLInputElement)) { - return - } - if (e.target.id === 'search-keyword') { - this.keyword = e.target.value - } + urlChange(url => { + const params = new URLSearchParams(url) + this.keyword = params.get('keyword') }) - }) - }, - methods: { - getOnlineActions: lodash.debounce(getOnlineActions, 200), - getActions, + await this.$nextTick() + }, handleSelect() { this.$emit('close') this.getActions() From efad15e287c682d2f49125327c8f272673b96c57 Mon Sep 17 00:00:00 2001 From: the1812 Date: Sun, 12 May 2024 13:55:34 +0800 Subject: [PATCH 14/21] Fix spm id breaking image url (fix #4719) --- .../player/screenshot/VideoScreenshot.vue | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/registry/lib/components/video/player/screenshot/VideoScreenshot.vue b/registry/lib/components/video/player/screenshot/VideoScreenshot.vue index 5e7dca5496..1215d64c62 100644 --- a/registry/lib/components/video/player/screenshot/VideoScreenshot.vue +++ b/registry/lib/components/video/player/screenshot/VideoScreenshot.vue @@ -2,7 +2,14 @@
- + @@ -40,7 +47,15 @@ export default Vue.extend({ this.$emit('discard') }, save() { - this.$refs.link.click() + const link = this.$refs.link as HTMLAnchorElement + link.addEventListener( + 'click', + e => { + e.stopPropagation() + }, + { capture: true, once: true }, + ) + link.click() this.discard() }, }, From b32d865337c88348324e56f1612c72d0bed6014a Mon Sep 17 00:00:00 2001 From: the1812 Date: Sun, 12 May 2024 14:06:03 +0800 Subject: [PATCH 15/21] Add color-scheme support (fix #4717) --- .../lib/components/style/dark-mode/index.ts | 33 ++++++++++++------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/registry/lib/components/style/dark-mode/index.ts b/registry/lib/components/style/dark-mode/index.ts index 228904a581..756b81d78f 100644 --- a/registry/lib/components/style/dark-mode/index.ts +++ b/registry/lib/components/style/dark-mode/index.ts @@ -6,27 +6,38 @@ const darkMetaColor = '#111' const add = async () => { document.body.classList.add('dark') localStorage.setItem('pbp_theme_v4', 'b') - const meta = dq('meta[name="theme-color"]') as HTMLMetaElement - if (!meta) { + + const themeColorMeta = dq('meta[name="theme-color"]') as HTMLMetaElement + if (!themeColorMeta) { document.head.insertAdjacentHTML( 'beforeend', ``, ) } else { - meta.dataset.light = meta.content - meta.content = darkMetaColor + themeColorMeta.dataset.light = themeColorMeta.content + themeColorMeta.content = darkMetaColor + } + + const colorSchemeMeta = dq('meta[name="color-scheme"]') as HTMLMetaElement + if (!colorSchemeMeta) { + document.head.insertAdjacentHTML('beforeend', ``) + } else { + colorSchemeMeta.content = 'dark' } } const remove = async () => { document.body.classList.remove('dark') - const meta = dq('meta[name="theme-color"]') as HTMLMetaElement - if (!meta) { - return - } - if (meta.dataset.light) { - meta.content = meta.dataset.light + + const themeColorMeta = dq('meta[name="theme-color"]') as HTMLMetaElement + if (themeColorMeta?.dataset.light) { + themeColorMeta.content = themeColorMeta.dataset.light } else { - meta.remove() + themeColorMeta?.remove() + } + + const colorSchemeMeta = dq('meta[name="color-scheme"]') as HTMLMetaElement + if (colorSchemeMeta) { + colorSchemeMeta.content = 'light' } } From fa1e13086662d0737101d4868e8a8a85c9391402 Mon Sep 17 00:00:00 2001 From: the1812 Date: Tue, 14 May 2024 08:54:17 +0800 Subject: [PATCH 16/21] Fix markdown styles --- registry/lib/components/video/default-location/desc.md | 10 ---------- .../lib/components/video/player/extend-speed/index.ts | 6 +++--- .../components/video/player/remember-speed/index.ts | 4 ++-- 3 files changed, 5 insertions(+), 15 deletions(-) diff --git a/registry/lib/components/video/default-location/desc.md b/registry/lib/components/video/default-location/desc.md index 8bfdc32bd1..70cfd15e3a 100644 --- a/registry/lib/components/video/default-location/desc.md +++ b/registry/lib/components/video/default-location/desc.md @@ -1,7 +1,5 @@ 打开视频/番剧时自动定位到指定位置 -
- 位置:距离页面顶部的像素距离\ 默认位置:打开视频时自动定位到此处\ 位置测试:查看、调整当前页面所在位置 @@ -9,11 +7,3 @@ 当前版本限制默认位置的最大值为 4000。\ 若有其他希望支持的页面,请提交反馈。\ 脚本不会等待评论完全加载,因此较大的默认位置将无法正确定位。 - -
- - diff --git a/registry/lib/components/video/player/extend-speed/index.ts b/registry/lib/components/video/player/extend-speed/index.ts index 025d2a7871..0ceb7dcdde 100644 --- a/registry/lib/components/video/player/extend-speed/index.ts +++ b/registry/lib/components/video/player/extend-speed/index.ts @@ -14,7 +14,7 @@ export const component = ExtendSpeedComponent.create({ > 扩展视频播放器的倍速菜单项,可用于突破原有播放倍数的上限或下限. -### 🔧 **选项** +#### 🔧 **选项** - \`隐藏滚动条\`:如果添加的倍速过多,倍速菜单将出现滚动条,在 Windows 下,若没有安装并启用「细滚动条」组件会显得比较挤,建议开启此选项隐藏滚动条. @@ -22,7 +22,7 @@ export const component = ExtendSpeedComponent.create({ - \`隐藏新增图标\`:如果认为顶部的新增倍速图标有些突兀,可以开启此选项隐藏. -### **新增倍速** +#### **新增倍速** 开启组件后,在默认情况下,播放器的倍速菜单就会新增 2.5x 和 3.0x 两个倍速选项. @@ -32,7 +32,7 @@ export const component = ExtendSpeedComponent.create({ **不推荐设置超高倍速(>3.0x)**:原生播放器内部没有针对超高倍速进行优化,可能导致音画不同步、播放卡顿、声音嘈杂/消失等一系列问题. -### **删除倍速** +#### **删除倍速** 将鼠标指针移到**自定义**的倍速菜单项上,其右侧将会显示一个移除图标,单击即可删除相应的倍速. diff --git a/registry/lib/components/video/player/remember-speed/index.ts b/registry/lib/components/video/player/remember-speed/index.ts index 6bd014be83..d2210aed9a 100644 --- a/registry/lib/components/video/player/remember-speed/index.ts +++ b/registry/lib/components/video/player/remember-speed/index.ts @@ -15,14 +15,14 @@ export const component = RememberSpeedComponent.create({ > 提高视频播放器的倍速记忆体验,可实现跨页共享倍速,也可以按视频分别记忆倍速. -### 🔧 **选项** +#### 🔧 **选项** - \`全局记忆倍速值\`:默认情况下,这是跨页共享的倍速值,如果启用「各视频分别记忆」,则作为从未独立记忆倍速视频的初始倍速值. - \`固定全局倍速值\`:默认情况下,全局倍速值将随着用户改变视频倍速而改变,打开此选项后,全局记忆倍速值不再受倍速调整的影响. - \`各视频分别记忆\`:打开此选项后,将按不同视频分别记忆倍速,对于从未被记忆过倍速的视频,将采用全局记忆倍速值,选项「固定全局倍速值」在此情况下强制生效. - \`弹出还原倍速提示\`:打开此选项后,每次成功还原倍速后都会弹出提示. -### 🌈 **温馨提示** +#### 🌈 **温馨提示** 「扩展倍速」和倍速相关的快捷键插件已分离为单独的组件或插件. From 36177ba100e0d28900b0ff6d425c9cc30a4df261 Mon Sep 17 00:00:00 2001 From: the1812 Date: Tue, 14 May 2024 09:22:02 +0800 Subject: [PATCH 17/21] Update changelog --- CHANGELOG.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a5703aa3d..72ded08c91 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,33 @@ # 更新日志 +## v2.8.11-preview +`2024-05-14` + +包含 [v2.8.11](https://github.com/the1812/Bilibili-Evolved/releases/tag/v2.8.11) 的所有更新内容. + +✨新增 +- `下载视频 - WASM 混流输出` 支持批量下载. (PR #4726 by [WakelessSloth56](https://github.com/WakelessSloth56)) +- `夜间模式` 增加 `color-scheme` meta 信息, 适配 Chrome 的 [Fluent overlay scrollbars](chrome://flags/#fluent-overlay-scrollbars). (#4717) + +## v2.8.11 +`2024-05-14` + +🐛修复 +- 修复了搜索框中的 XSS 注入问题. +- 修复 `评论区IP属地显示` 失效. (#4690) +- 在搜索框中删除搜索历史时将不再收起下拉菜单. (#4732) +- 修复功能反复开关时, 功能面板中的按钮重复出现. (#4731) +- 修复功能面板空间不足时出现折行. (#4721) +- 修复 `启用视频截图` 在番剧区失效. (#4719) + +☕开发者相关 +- Comment API 调整: + - 增加对 `CommentArea` 销毁的监测. + - `forEachCommentItem` / `forEechCommentArea` 参数统一支持 `added` 和 `removed` 回调. + - `CommentReplyItem` / `CommentItem` 增加属性 `vueProps`. + + ## v2.8.10-preview `2024-04-23` From 0cce063034cffb7ea74d698d0bbc2d08eff395ef Mon Sep 17 00:00:00 2001 From: the1812 Date: Tue, 14 May 2024 09:22:13 +0800 Subject: [PATCH 18/21] Update version number --- src/client/common.meta.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/common.meta.json b/src/client/common.meta.json index 79de1e9bc1..285af13e06 100644 --- a/src/client/common.meta.json +++ b/src/client/common.meta.json @@ -1,5 +1,5 @@ { - "version": "2.8.10", + "version": "2.8.11", "author": "Grant Howard, Coulomb-G", "copyright": "[year], Grant Howard (https://github.com/the1812) & Coulomb-G (https://github.com/Coulomb-G)", "license": "MIT", From 9d04df9a9d44a3fde4aa1c492165c7049369aea3 Mon Sep 17 00:00:00 2001 From: the1812 Date: Tue, 14 May 2024 09:27:34 +0800 Subject: [PATCH 19/21] Update donate history --- doc/donate.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/donate.md b/doc/donate.md index 66c088c933..a8e21167a6 100644 --- a/doc/donate.md +++ b/doc/donate.md @@ -29,6 +29,8 @@ https://afdian.net/@the1812?tab=sponsor | 时间 | 用户名 | 单号后4位 | 金额 | | ------------------- | --------------------- | --------- | ------- | +| 2024.05.02 16:06:40 | C*6 | 9321 | ¥100.00 | +| 2024.05.02 01:51:05 | 匿名 | 7540 | ¥5.00 | | 2024.04.08 16:02:38 | 匿名 | 2455 | ¥5.00 | | 2024.03.31 16:36:20 | N*r | 3391 | ¥5.20 | | 2024.03.27 21:25:21 | M*g | 0180 | ¥10.00 | From d1d675af27cee287df87277e56cede2709ca723c Mon Sep 17 00:00:00 2001 From: the1812 Date: Tue, 14 May 2024 09:28:54 +0800 Subject: [PATCH 20/21] Update docs --- doc/features/features.json | 6 +++--- doc/features/features.md | 20 +++++--------------- 2 files changed, 8 insertions(+), 18 deletions(-) diff --git a/doc/features/features.json b/doc/features/features.json index 57acfdfe6a..b400ddca91 100644 --- a/doc/features/features.json +++ b/doc/features/features.json @@ -699,7 +699,7 @@ "type": "component", "name": "videoDefaultLocation", "displayName": "视频页默认定位", - "description": "打开视频/番剧时自动定位到指定位置\r\n\r\n
\r\n\r\n位置:距离页面顶部的像素距离\\\r\n默认位置:打开视频时自动定位到此处\\\r\n位置测试:查看、调整当前页面所在位置\r\n\r\n当前版本限制默认位置的最大值为 4000。\\\r\n若有其他希望支持的页面,请提交反馈。\\\r\n脚本不会等待评论完全加载,因此较大的默认位置将无法正确定位。\r\n\r\n
\r\n\r\n\r\n", + "description": "打开视频/番剧时自动定位到指定位置\r\n\r\n位置:距离页面顶部的像素距离\\\r\n默认位置:打开视频时自动定位到此处\\\r\n位置测试:查看、调整当前页面所在位置\r\n\r\n当前版本限制默认位置的最大值为 4000。\\\r\n若有其他希望支持的页面,请提交反馈。\\\r\n脚本不会等待评论完全加载,因此较大的默认位置将无法正确定位。\r\n", "fullRelativePath": "../../registry/dist/components/video/default-location.js", "fullAbsolutePath": "registry/dist/components/video/default-location.js" }, @@ -779,7 +779,7 @@ "type": "component", "name": "extendVideoSpeed", "displayName": "扩展倍速", - "description": "by [@JLoeve](https://github.com/LonelySteve)\n\n\n\n> 扩展视频播放器的倍速菜单项,可用于突破原有播放倍数的上限或下限.\n\n### 🔧 **选项**\n\n- `隐藏滚动条`:如果添加的倍速过多,倍速菜单将出现滚动条,在 Windows 下,若没有安装并启用「细滚动条」组件会显得比较挤,建议开启此选项隐藏滚动条.\n\n- `隐藏移除图标`:如果认为倍速右侧的移除倍速图标有些突兀,可以开启此选项隐藏.\n\n- `隐藏新增图标`:如果认为顶部的新增倍速图标有些突兀,可以开启此选项隐藏.\n\n### **新增倍速**\n\n开启组件后,在默认情况下,播放器的倍速菜单就会新增 2.5x 和 3.0x 两个倍速选项.\n\n如果需要添加更多倍速,只需将鼠标指针移到菜单顶部的新增图标上,图标将变成一个输入框,根据需要键入新的倍速值,或通过滚轮增减数值,或直接使用推荐的数值,回车确认即可.\n\n新增倍速的范围要求在 0.0625 到 16 之间,数量则不受限制.\n\n**不推荐设置超高倍速(>3.0x)**:原生播放器内部没有针对超高倍速进行优化,可能导致音画不同步、播放卡顿、声音嘈杂/消失等一系列问题.\n\n### **删除倍速**\n\n将鼠标指针移到**自定义**的倍速菜单项上,其右侧将会显示一个移除图标,单击即可删除相应的倍速.\n\n", + "description": "by [@JLoeve](https://github.com/LonelySteve)\n\n\n\n> 扩展视频播放器的倍速菜单项,可用于突破原有播放倍数的上限或下限.\n\n#### 🔧 **选项**\n\n- `隐藏滚动条`:如果添加的倍速过多,倍速菜单将出现滚动条,在 Windows 下,若没有安装并启用「细滚动条」组件会显得比较挤,建议开启此选项隐藏滚动条.\n\n- `隐藏移除图标`:如果认为倍速右侧的移除倍速图标有些突兀,可以开启此选项隐藏.\n\n- `隐藏新增图标`:如果认为顶部的新增倍速图标有些突兀,可以开启此选项隐藏.\n\n#### **新增倍速**\n\n开启组件后,在默认情况下,播放器的倍速菜单就会新增 2.5x 和 3.0x 两个倍速选项.\n\n如果需要添加更多倍速,只需将鼠标指针移到菜单顶部的新增图标上,图标将变成一个输入框,根据需要键入新的倍速值,或通过滚轮增减数值,或直接使用推荐的数值,回车确认即可.\n\n新增倍速的范围要求在 0.0625 到 16 之间,数量则不受限制.\n\n**不推荐设置超高倍速(>3.0x)**:原生播放器内部没有针对超高倍速进行优化,可能导致音画不同步、播放卡顿、声音嘈杂/消失等一系列问题.\n\n#### **删除倍速**\n\n将鼠标指针移到**自定义**的倍速菜单项上,其右侧将会显示一个移除图标,单击即可删除相应的倍速.\n\n", "fullRelativePath": "../../registry/dist/components/video/player/extend-speed.js", "fullAbsolutePath": "registry/dist/components/video/player/extend-speed.js" }, @@ -827,7 +827,7 @@ "type": "component", "name": "rememberVideoSpeed", "displayName": "记忆倍速", - "description": "by [@JLoeve](https://github.com/LonelySteve)\n\n\n\n> 提高视频播放器的倍速记忆体验,可实现跨页共享倍速,也可以按视频分别记忆倍速.\n\n### 🔧 **选项**\n\n- `全局记忆倍速值`:默认情况下,这是跨页共享的倍速值,如果启用「各视频分别记忆」,则作为从未独立记忆倍速视频的初始倍速值.\n- `固定全局倍速值`:默认情况下,全局倍速值将随着用户改变视频倍速而改变,打开此选项后,全局记忆倍速值不再受倍速调整的影响.\n- `各视频分别记忆`:打开此选项后,将按不同视频分别记忆倍速,对于从未被记忆过倍速的视频,将采用全局记忆倍速值,选项「固定全局倍速值」在此情况下强制生效.\n- `弹出还原倍速提示`:打开此选项后,每次成功还原倍速后都会弹出提示.\n\n### 🌈 **温馨提示**\n\n「扩展倍速」和倍速相关的快捷键插件已分离为单独的组件或插件.\n\n请根据自身需要:\n\n- 前往「组件」页面安装[「扩展倍速」]((branch, ownerOverride) => `https://${host}/${ownerOverride || owner}/Bilibili-Evolved/${branch}/`registry/dist/components/video/player/extend-speed.js)组件\n- 前往「插件」页面安装[「快捷键扩展 - 视频倍速」]((branch, ownerOverride) => `https://${host}/${ownerOverride || owner}/Bilibili-Evolved/${branch}/`registry/dist/plugins/video/player/speed.js)插件.\n\n*如果想要清除当前视频的记忆状态,需要安装「快捷键扩展 - 视频倍速」插件.*\n", + "description": "by [@JLoeve](https://github.com/LonelySteve)\n\n\n\n> 提高视频播放器的倍速记忆体验,可实现跨页共享倍速,也可以按视频分别记忆倍速.\n\n#### 🔧 **选项**\n\n- `全局记忆倍速值`:默认情况下,这是跨页共享的倍速值,如果启用「各视频分别记忆」,则作为从未独立记忆倍速视频的初始倍速值.\n- `固定全局倍速值`:默认情况下,全局倍速值将随着用户改变视频倍速而改变,打开此选项后,全局记忆倍速值不再受倍速调整的影响.\n- `各视频分别记忆`:打开此选项后,将按不同视频分别记忆倍速,对于从未被记忆过倍速的视频,将采用全局记忆倍速值,选项「固定全局倍速值」在此情况下强制生效.\n- `弹出还原倍速提示`:打开此选项后,每次成功还原倍速后都会弹出提示.\n\n#### 🌈 **温馨提示**\n\n「扩展倍速」和倍速相关的快捷键插件已分离为单独的组件或插件.\n\n请根据自身需要:\n\n- 前往「组件」页面安装[「扩展倍速」]((branch, ownerOverride) => `https://${host}/${ownerOverride || owner}/Bilibili-Evolved/${branch}/`registry/dist/components/video/player/extend-speed.js)组件\n- 前往「插件」页面安装[「快捷键扩展 - 视频倍速」]((branch, ownerOverride) => `https://${host}/${ownerOverride || owner}/Bilibili-Evolved/${branch}/`registry/dist/plugins/video/player/speed.js)插件.\n\n*如果想要清除当前视频的记忆状态,需要安装「快捷键扩展 - 视频倍速」插件.*\n", "fullRelativePath": "../../registry/dist/components/video/player/remember-speed.js", "fullAbsolutePath": "registry/dist/components/video/player/remember-speed.js" }, diff --git a/doc/features/features.md b/doc/features/features.md index fc6d4b363a..ce453e906b 100644 --- a/doc/features/features.md +++ b/doc/features/features.md @@ -927,8 +927,6 @@ by [@kdxcxs](https://github.com/kdxcxs) 打开视频/番剧时自动定位到指定位置 -
- 位置:距离页面顶部的像素距离\ 默认位置:打开视频时自动定位到此处\ 位置测试:查看、调整当前页面所在位置 @@ -937,14 +935,6 @@ by [@kdxcxs](https://github.com/kdxcxs) 若有其他希望支持的页面,请提交反馈。\ 脚本不会等待评论完全加载,因此较大的默认位置将无法正确定位。 -
- - - ### [下载视频](../../registry/dist/components/video/download.js) `downloadVideo` @@ -1045,7 +1035,7 @@ by [@JLoeve](https://github.com/LonelySteve) > 扩展视频播放器的倍速菜单项,可用于突破原有播放倍数的上限或下限. -### 🔧 **选项** +#### 🔧 **选项** - `隐藏滚动条`:如果添加的倍速过多,倍速菜单将出现滚动条,在 Windows 下,若没有安装并启用「细滚动条」组件会显得比较挤,建议开启此选项隐藏滚动条. @@ -1053,7 +1043,7 @@ by [@JLoeve](https://github.com/LonelySteve) - `隐藏新增图标`:如果认为顶部的新增倍速图标有些突兀,可以开启此选项隐藏. -### **新增倍速** +#### **新增倍速** 开启组件后,在默认情况下,播放器的倍速菜单就会新增 2.5x 和 3.0x 两个倍速选项. @@ -1063,7 +1053,7 @@ by [@JLoeve](https://github.com/LonelySteve) **不推荐设置超高倍速(>3.0x)**:原生播放器内部没有针对超高倍速进行优化,可能导致音画不同步、播放卡顿、声音嘈杂/消失等一系列问题. -### **删除倍速** +#### **删除倍速** 将鼠标指针移到**自定义**的倍速菜单项上,其右侧将会显示一个移除图标,单击即可删除相应的倍速. @@ -1133,14 +1123,14 @@ by [@JLoeve](https://github.com/LonelySteve) > 提高视频播放器的倍速记忆体验,可实现跨页共享倍速,也可以按视频分别记忆倍速. -### 🔧 **选项** +#### 🔧 **选项** - `全局记忆倍速值`:默认情况下,这是跨页共享的倍速值,如果启用「各视频分别记忆」,则作为从未独立记忆倍速视频的初始倍速值. - `固定全局倍速值`:默认情况下,全局倍速值将随着用户改变视频倍速而改变,打开此选项后,全局记忆倍速值不再受倍速调整的影响. - `各视频分别记忆`:打开此选项后,将按不同视频分别记忆倍速,对于从未被记忆过倍速的视频,将采用全局记忆倍速值,选项「固定全局倍速值」在此情况下强制生效. - `弹出还原倍速提示`:打开此选项后,每次成功还原倍速后都会弹出提示. -### 🌈 **温馨提示** +#### 🌈 **温馨提示** 「扩展倍速」和倍速相关的快捷键插件已分离为单独的组件或插件. From 4e00907bf6930594d7b38268b958e633fc64ea56 Mon Sep 17 00:00:00 2001 From: the1812 Date: Tue, 14 May 2024 09:30:52 +0800 Subject: [PATCH 21/21] Update docs --- doc/features/features.json | 2 +- doc/features/features.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/features/features.json b/doc/features/features.json index c29e173aab..781f178c5e 100644 --- a/doc/features/features.json +++ b/doc/features/features.json @@ -1116,7 +1116,7 @@ "type": "plugin", "name": "downloadVideo.outputs.wasm", "displayName": "下载视频 - WASM 混流输出", - "description": "by [@WakelessSloth56](https://github.com/WakelessSloth56)\n\n使用 WASM 在浏览器中下载并合并音视频", + "description": "by [@WakelessSloth56](https://github.com/WakelessSloth56)\n\n使用 WASM 在浏览器中下载并合并音视频, 支持批量下载", "fullRelativePath": "../../registry/dist/plugins/video/download/wasm-output.js", "fullAbsolutePath": "registry/dist/plugins/video/download/wasm-output.js" }, diff --git a/doc/features/features.md b/doc/features/features.md index 0c22ad4f01..810fc1d516 100644 --- a/doc/features/features.md +++ b/doc/features/features.md @@ -1495,7 +1495,7 @@ by [@diannaojiang](https://github.com/diannaojiang) by [@WakelessSloth56](https://github.com/WakelessSloth56) -使用 WASM 在浏览器中下载并合并音视频 +使用 WASM 在浏览器中下载并合并音视频, 支持批量下载 ### [快捷键扩展 - 视频倍速](../../registry/dist/plugins/video/player/speed.js) `speed.keymap`