Skip to content

Commit

Permalink
Merge branch 'preview-features' into preview
Browse files Browse the repository at this point in the history
  • Loading branch information
the1812 committed Sep 15, 2024
2 parents 798dc23 + 2735b87 commit 45fd78f
Show file tree
Hide file tree
Showing 15 changed files with 134 additions and 43 deletions.
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"cntr",
"compositionend",
"compositionstart",
"contenteditable",
"csrf",
"ctnr",
"Danmaku",
Expand Down
39 changes: 39 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,45 @@
<!-- spell-checker: disable -->
# 更新日志

## v2.9.3-preview
主要是各种修复, 见 [v2.9.3](https://github.com/the1812/Bilibili-Evolved/releases/tag/v2.9.3).

## v2.9.3

<details>
<summary>正式版用户将获得 v2.9.1-preview ~ v2.9.2-preview 的所有改动, 点击展开查看</summary>

✨新增
- `查看封面` 可以为 aria2 输出提供直接的封面下载. (PR #4798 by [Oxygenくん](https://github.com/oxygenkun))
- 新增组件 `保存视频元数据`. (PR #4840 by [WakelessSloth56](https://github.com/WakelessSloth56))
> - 保存视频元数据为 [FFMETADATA](https://ffmpeg.org/ffmpeg-formats.html#Metadata-2) 格式
> - 使用组件 `下载视频` 时指定 `WASM` 输出方式(插件 `下载视频 - WASM 混流输出`)可选择是否直接混流入输出文件。
> - 保存视频章节为 OGM 格式 (https://github.com/the1812/Bilibili-Evolved/discussions/2069#discussioncomment-10110916)
- `简化首页` 支持隐藏轮播图. (PR #4852 by [Lime](https://github.com/Liumingxun))
- 新增组件 `添加直播间用户超链接`. (PR #4856 by [Light_Quanta](https://github.com/LightQuanta))
> 网页版直播间右上角的房间观众和大航海界面的用户列表只可查看用户名,不可进行点击。该组件为用户头像和用户名称处添加点击效果,允许通过点击直接查看用户空间。
- 插件 `下载视频 - WASM 混流输出` 支持并行下载库和音视频流. (PR #4864 by [WakelessSloth56](https://github.com/WakelessSloth56))
- `弹幕转义` 支持对正斜杠的换行 (`/n`) 进行转义. (#4865)
- `自定义顶栏` 支持直接在功能中打开布局设置. (#2666)
- `高分辨率图片` 支持处理没有指定高度的图片, 支持在专栏页面中请求原图. (#2868)
- `直播间网页全屏自适应` 样式适配较低的宽度值. (#4895)

☕开发者相关
- 外部资源接入 Subresource Integrity. (#4896)

</details>

🐛修复
- 修复 `快速收起评论` 对旧版评论区的兼容性. (#4905)
- 修复 `快捷键扩展` 的发送评论在新版评论区失效. (#4843)
- 修复 `禁用评论区搜索词` 偶现样式失效. (#4843)

☕开发者相关
- `ShadowDomObserver` 在使用前无需再调用 `observe()`.
- 增加工具方法 `getActiveElement` 检测当前页面的聚焦元素.

## v2.9.2-preview
`2024-09-08`

Expand Down
3 changes: 3 additions & 0 deletions registry/lib/components/feeds/fold-comments/fold-comment.scss
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,13 @@
}
}
.bili-comment-container {
display: flex !important;
flex-direction: column !important;
&.bili-dyn-comment .reply-list {
padding-bottom: 8px !important;
}
.fold-comment {
order: 1;
font-size: 13px;
}
.at-panel,
Expand Down
5 changes: 1 addition & 4 deletions registry/lib/components/feeds/fold-comments/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,7 @@ const entry = async () => {
}
if (feedsCardsManager.managerType === 'v2') {
const getExistingComment = () => dq(card, commentSelector) as HTMLElement
const isCommentAreaReady = () => {
const existingComment = getExistingComment()
return existingComment !== null && dq(existingComment, 'bili-comments')
}
const isCommentAreaReady = () => getExistingComment() !== null
const handler = () => {
const button = dq(card, '.bili-dyn-action.comment') as HTMLElement
button?.click()
Expand Down
10 changes: 7 additions & 3 deletions registry/lib/components/live/chat-panel-fit/chat-panel-fit.scss
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,13 @@
}
}
}
.chat-input-ctnr-new .medal-section {
min-width: 0 !important;
max-width: 0 !important;
.chat-input-ctnr-new {
.medal-section {
display: none !important;
}
.chat-input-new:not(:has(textarea.focus)) {
padding-left: 12px !important;
}
}
}
}
Expand Down
15 changes: 12 additions & 3 deletions registry/lib/components/utils/keymap/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { getComponentSettings } from '@/core/settings'
import { registerAndGetData } from '@/plugins/data'
import { Options } from '.'
import { KeyBindingAction, KeyBindingActionContext } from './bindings'
import { simulateClick } from '@/core/utils'
import { getActiveElement, simulateClick } from '@/core/utils'

export const keyboardEventToPointer = (event: KeyboardEvent): PointerEventInit => {
return {
Expand Down Expand Up @@ -239,15 +239,24 @@ export const builtInActions: Record<string, KeyBindingAction> = {
sendComment: {
displayName: '发送评论',
ignoreTyping: false,
prevent: true,
run: () => {
const { activeElement } = document
if (!activeElement || !(activeElement instanceof HTMLTextAreaElement)) {
const activeElement = getActiveElement()
if (!activeElement) {
return null
}
const isEditable =
activeElement instanceof HTMLTextAreaElement ||
activeElement.hasAttribute('contenteditable')
if (!isEditable) {
return null
}
const getShadowRoot = (node: Node) => node.getRootNode() as ShadowRoot | null
const sendButton = (() => {
const candidates = [
() => activeElement.nextElementSibling,
() => activeElement.parentElement.nextElementSibling,
() => getShadowRoot(getShadowRoot(activeElement)?.host)?.querySelector('#pub button'),
() => dq('.reply-box:focus-within .reply-box-send'),
]
const match = candidates.find(fn => fn() !== null)
Expand Down
10 changes: 8 additions & 2 deletions registry/lib/components/utils/keymap/bindings.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { isTyping, matchUrlPattern } from '@/core/utils'
import { mediaListUrls, watchlaterUrls } from '@/core/utils/urls'
import { clickElement, changeVideoTime, showTip } from './actions'
import { shadowDomObserver } from '@/core/shadow-root'

export interface KeyBindingActionContext {
binding: KeyBinding
Expand Down Expand Up @@ -29,7 +30,7 @@ export const loadKeyBindings = lodash.once((bindings: KeyBinding[]) => {
enable: true,
bindings,
}
document.body.addEventListener('keydown', (e: KeyboardEvent & { [key: string]: boolean }) => {
const keyboardHandler = (e: KeyboardEvent & { [key: string]: boolean }) => {
if (!config.enable) {
return
}
Expand Down Expand Up @@ -87,10 +88,15 @@ export const loadKeyBindings = lodash.once((bindings: KeyBinding[]) => {

const actionSuccess = !lodash.isNil(actionResult)
if (binding.action.prevent ?? actionSuccess) {
e.stopPropagation()
e.stopImmediatePropagation()
e.preventDefault()
}
})
}
document.body.addEventListener('keydown', keyboardHandler, { capture: true })
shadowDomObserver.watchShadowDom({
added: shadowDom =>
shadowDom.shadowRoot.addEventListener('keydown', keyboardHandler, { capture: true }),
})
return config
})
Expand Down
3 changes: 3 additions & 0 deletions registry/lib/components/video/download/DownloadVideo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@
<div class="download-video-config-title">使用备用下载地址:</div>
<SwitchBox v-model="useBackupUrls" />
</div>
<div class="download-video-config-description">
若默认下载地址速度缓慢, 可以尝试更换备用下载地址.
</div>
<component
:is="a.component"
v-for="a of assetsWithOptions"
Expand Down
25 changes: 19 additions & 6 deletions registry/lib/plugins/video/download/aria2-output/RpcConfig.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
<template>
<div class="rpc-config download-video-config-section">
<div>
<div>aria2下载附属资源(若支持):</div>
<SwitchBox v-model="isPluginDownloadAssets" @change="saveSettings" />
<div class="online-assets-download">
<div class="download-video-config-item">
<div class="download-video-config-title">使用 aria2 下载附属资源:</div>
<SwitchBox v-model="isPluginDownloadAssets" @change="saveAssetsSettings" />
</div>
<div class="download-video-config-description">
存在于服务器的附属资源 (例如封面) 可以一并发送到 aria2 下载.
</div>
</div>
<div v-if="isRenaming" class="profile-select">
<div class="profile-item-name">重命名 RPC 预设:</div>
Expand Down Expand Up @@ -117,11 +122,15 @@ export default Vue.extend({
}
},
methods: {
saveSettings() {
saveProfileSettings() {
options.selectedRpcProfileName = this.selectedRpcProfile.name
options.rpcProfiles = this.rpcProfiles
storedOptions.selectedRpcProfileName = options.selectedRpcProfileName
storedOptions.rpcProfiles = options.rpcProfiles
},
saveAssetsSettings() {
options.isPluginDownloadAssets = this.isPluginDownloadAssets
Object.assign(storedOptions, options)
storedOptions.isPluginDownloadAssets = options.isPluginDownloadAssets
},
async startRename() {
this.profileRename = this.selectedRpcProfile.name
Expand All @@ -143,7 +152,7 @@ export default Vue.extend({
}
this.selectedRpcProfile.name = this.profileRename
this.isRenaming = false
this.saveSettings()
this.saveProfileSettings()
},
newProfile() {
const newProfile: Aria2RpcProfile = { ...this.selectedRpcProfile }
Expand Down Expand Up @@ -206,5 +215,9 @@ export default Vue.extend({
.profile-method {
align-self: flex-start;
}
.online-assets-download {
flex-direction: column;
align-items: start;
}
}
</style>
38 changes: 20 additions & 18 deletions registry/lib/plugins/video/download/aria2-output/aria2-rpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ import { getJson, monkey, postJson } from '@/core/ajax'
import { Toast } from '@/core/toast'
import { UserAgent } from '@/core/utils/constants'
import { logError } from '@/core/utils/log'
import { DownloadVideoOutput } from '../../../../components/video/download/types'
import {
DownloadVideoAssets,
DownloadVideoOutput,
} from '../../../../components/video/download/types'
import { Aria2RpcProfile } from './rpc-profiles'

interface RpcParam {
Expand Down Expand Up @@ -138,7 +141,7 @@ export const aria2Rpc: DownloadVideoOutput = {
const { selectedRpcProfile, isPluginDownloadAssets } = instance
const { secretKey, dir, other } = selectedRpcProfile
const referer = document.URL.replace(window.location.search, '')
const ariaParamsGenerator = (url: string, title: string) => {
const getAria2Params = (url: string, title: string) => {
const singleInfoParams = []
if (secretKey) {
singleInfoParams.push(`token:${secretKey}`)
Expand All @@ -158,30 +161,29 @@ export const aria2Rpc: DownloadVideoOutput = {
}
}

// handle video params
const videoParams = infos
.map(info =>
info.titledFragments.map(fragment => {
const { url, title } = fragment
return ariaParamsGenerator(url, title)
return getAria2Params(url, title)
}),
)
.flat()

// handle assets
const assetsAriaParams = []
const extraAssetsForBrowerDownload = []
for (const { asset, instance: assetInstance } of extraOnlineAssets) {
if (isPluginDownloadAssets && 'getUrls' in asset) {
// get asset from aria2
const results = await asset.getUrls(infos, assetInstance)
assetsAriaParams.push(...results.map(({ name, url }) => ariaParamsGenerator(url, name)))
} else {
// remain asset in `extraOnlineAssets`
extraAssetsForBrowerDownload.push({ asset, instance: assetInstance })
}
}
action.extraOnlineAssets = extraAssetsForBrowerDownload
const isAriaAsset = (asset: DownloadVideoAssets) =>
isPluginDownloadAssets && asset.getUrls !== undefined
const assetsAriaParams = (
await Promise.all(
extraOnlineAssets
.filter(it => isAriaAsset(it.asset))
.map(async it => {
const { asset, instance: assetInstance } = it
const results = await asset.getUrls(infos, assetInstance)
return results.map(({ name, url }) => getAria2Params(url, name))
}),
)
).flat()
action.extraOnlineAssets = extraOnlineAssets.filter(it => !isAriaAsset(it.asset))

const totalParams = [...videoParams, ...assetsAriaParams]
const results = await sendRpc(selectedRpcProfile, totalParams)
Expand Down
2 changes: 1 addition & 1 deletion src/client/common.meta.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "2.9.2",
"version": "2.9.3",
"author": "Grant Howard, Coulomb-G",
"copyright": "[year], Grant Howard (https://github.com/the1812) & Coulomb-G (https://github.com/Coulomb-G)",
"license": "MIT",
Expand Down
1 change: 0 additions & 1 deletion src/components/utils/comment/areas/v3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ export class CommentAreaV3 extends CommentArea {

constructor(element: HTMLElement) {
super(element)
shadowDomObserver.observe()
this.shadowDomObserver = shadowDomObserver
}

Expand Down
13 changes: 10 additions & 3 deletions src/core/shadow-root/dom-observer.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { contentLoaded } from '../life-cycle'
import { childListSubtree } from '../observer'
import { deleteValue } from '../utils'
import { ShadowDomCallback, ShadowDomEntry } from './dom-entry'
Expand Down Expand Up @@ -81,6 +82,7 @@ export class ShadowDomObserver extends ShadowRootObserver {
}

forEachShadowDom(callback: ShadowDomCallback) {
this.observe()
const callCurrentAndNextLevel = (currentEntry: ShadowDomEntry) => {
callback(currentEntry)
currentEntry.children.forEach(child => {
Expand All @@ -94,6 +96,7 @@ export class ShadowDomObserver extends ShadowRootObserver {
}

watchShadowDom(callbacks: { added?: ShadowDomCallback; removed?: ShadowDomCallback }) {
this.observe()
this.forEachShadowDom(it => callbacks.added?.(it))
const addedListener = (e: CustomEvent<ShadowDomEntry>) => callbacks?.added?.(e.detail)
const removedListener = (e: CustomEvent<ShadowDomEntry>) => callbacks?.removed?.(e.detail)
Expand All @@ -109,10 +112,14 @@ export class ShadowDomObserver extends ShadowRootObserver {
if (this.observing) {
return
}
const existingRoots = ShadowRootObserver.queryAllShadowRoots()
existingRoots.forEach(root => this.addEntry(root))
;[this.rootObserver] = childListSubtree(document.body, records => this.mutationHandler(records))
this.observing = true
contentLoaded(() => {
const existingRoots = ShadowRootObserver.queryAllShadowRoots()
existingRoots.forEach(root => this.addEntry(root))
;[this.rootObserver] = childListSubtree(document.body, records =>
this.mutationHandler(records),
)
})
}

disconnect() {
Expand Down
1 change: 0 additions & 1 deletion src/core/shadow-root/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ export class ShadowRootStyles {

async addStyle(definition: ShadowRootStyleDefinition) {
const { id, style } = definition
this.observer.observe()
const entryId = `shadow-dom-style-${id !== undefined ? lodash.kebabCase(id) : getRandomId()}`
const styleSheet = new CSSStyleSheet()
await styleSheet.replace(style)
Expand Down
11 changes: 10 additions & 1 deletion src/core/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -518,9 +518,18 @@ export const playerReady = async () => {
// unsafeWindow.aid = info.aid.toString()
// return info.aid as string
// }

/** 获取当前聚焦的元素 */
export const getActiveElement = () => {
let { activeElement } = document
while (activeElement.shadowRoot !== null) {
activeElement = activeElement.shadowRoot.activeElement
}
return activeElement
}
/** 是否正在打字 */
export const isTyping = () => {
const { activeElement } = document
const activeElement = getActiveElement()
if (!activeElement) {
return false
}
Expand Down

0 comments on commit 45fd78f

Please sign in to comment.