mirror of
https://github.com/the1812/Bilibili-Evolved.git
synced 2025-11-04 21:22:45 +08:00
Merge branch 'preview-fixes' into preview-features
This commit is contained in:
commit
efdbded407
@ -28,7 +28,7 @@
|
||||
"name": "Install dependencies",
|
||||
"uses": "pnpm/action-setup@v2.2.4",
|
||||
"with": {
|
||||
"version": "8.9.0",
|
||||
"version": "8.12.1",
|
||||
"run_install": true
|
||||
}
|
||||
},
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
"name": "Install dependencies",
|
||||
"uses": "pnpm/action-setup@v2.2.4",
|
||||
"with": {
|
||||
"version": "8.9.0",
|
||||
"version": "8.12.1",
|
||||
"run_install": true
|
||||
}
|
||||
},
|
||||
|
||||
@ -144,7 +144,7 @@
|
||||
# 相关推荐
|
||||
这些脚本/插件同样能够改善您在B站的体验, 相同的功能将不会整合到 Bilibili Evolved, 但会尽可能地适配
|
||||
|
||||
## bilibili网页端添加APP首页推荐
|
||||
## bilibili 网页端添加 APP 首页推荐
|
||||
作者: [indefined](https://github.com/indefined)
|
||||
- [GitHub](https://github.com/indefined/UserScripts/tree/master/bilibiliHome)
|
||||
- [GreasyFork](https://greasyfork.org/zh-CN/scripts/368446-bilibili%E7%BD%91%E9%A1%B5%E7%AB%AF%E6%B7%BB%E5%8A%A0app%E9%A6%96%E9%A1%B5%E6%8E%A8%E8%8D%90)
|
||||
@ -161,7 +161,7 @@
|
||||
|
||||
----
|
||||
|
||||
**喜欢的话就点个⭐Star吧(°∀°)ノ**
|
||||
**喜欢的话就点个⭐Star 吧(°∀°)ノ**
|
||||
|
||||
**或者也可以考虑[捐助](https://github.com/the1812/Bilibili-Evolved/blob/preview/doc/donate.md)支持一下哦(`・ω・´)**
|
||||
|
||||
@ -182,7 +182,7 @@
|
||||
# 我写的其他一些玩意
|
||||
|
||||
## [Touhou Tagger](https://github.com/the1812/Touhou-Tagger)
|
||||
☯ 从 [THBWiki](https://thwiki.cc/) 自动填写东方Project同人音乐CD曲目信息
|
||||
☯ 从 [THBWiki](https://thwiki.cc/) 自动填写东方 Project 同人音乐 CD 曲目信息
|
||||
|
||||
## [Malware Patch](https://github.com/the1812/Malware-Patch)
|
||||
阻止中国流氓软件的管理员授权
|
||||
|
||||
@ -772,4 +772,26 @@
|
||||
|
||||
#{contains('live-info-content')} {
|
||||
background: transparent !important;
|
||||
}
|
||||
}
|
||||
|
||||
#{contains('upower-pay-container')} {
|
||||
.header {
|
||||
@include background-color('0');
|
||||
}
|
||||
#{contains('content')} {
|
||||
@include background('2');
|
||||
#{contains('tab-group')} {
|
||||
#{contains('active')} {
|
||||
@include color('f');
|
||||
}
|
||||
}
|
||||
#{contains('month-charge-grade')} {
|
||||
background: #333;
|
||||
}
|
||||
#{contains('charge-grad-container')} {
|
||||
.charge-grad-item {
|
||||
background: linear-gradient(45deg, #333, #444);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@ import { getFriendlyTitle } from '@/core/utils/title'
|
||||
import { DanmakuConverterConfig, DanmakuConverter } from '../converter/danmaku-converter'
|
||||
import { DanmakuType } from '../converter/danmaku-type'
|
||||
import { XmlDanmaku } from '../converter/xml-danmaku'
|
||||
import { playerAgent } from '@/components/video/player-agent'
|
||||
|
||||
export class JsonDanmaku {
|
||||
// static SegmentSize = 6 * 60
|
||||
@ -97,9 +98,6 @@ export const getUserDanmakuConfig = async () => {
|
||||
const playerSettingsJson = localStorage.getItem('bilibili_player_settings')
|
||||
|
||||
if (playerSettingsJson) {
|
||||
const playerSettings = JSON.parse(playerSettingsJson)
|
||||
const getConfig = <T>(prop: string, defaultValue?: T): T =>
|
||||
lodash.get(playerSettings, `setting_config.${prop}`, defaultValue)
|
||||
// 屏蔽类型
|
||||
config.blockTypes = (() => {
|
||||
const result: (DanmakuType | 'color')[] = []
|
||||
@ -111,7 +109,7 @@ export const getUserDanmakuConfig = async () => {
|
||||
}
|
||||
|
||||
for (const [type, value] of Object.entries(blockValues)) {
|
||||
if (lodash.get(playerSettings, `block.type_${type}`, true) === false) {
|
||||
if (playerAgent.getPlayerConfig<boolean>(`block.type_${type}`, true) === false) {
|
||||
result.push(...(value as (DanmakuType | 'color')[]))
|
||||
}
|
||||
}
|
||||
@ -119,13 +117,17 @@ export const getUserDanmakuConfig = async () => {
|
||||
})()
|
||||
|
||||
// 加粗
|
||||
config.bold = getConfig('bold', false)
|
||||
config.bold = playerAgent.getPlayerConfig('bold', false)
|
||||
|
||||
// 透明度
|
||||
config.alpha = lodash.clamp(1 - parseFloat(getConfig('opacity', '0.4')), 0, 1)
|
||||
config.alpha = lodash.clamp(
|
||||
1 - parseFloat(playerAgent.getPlayerConfig('opacity', '0.4')),
|
||||
0,
|
||||
1,
|
||||
)
|
||||
|
||||
// 分辨率
|
||||
const resolutionFactor = 1.4 - 0.4 * getConfig('fontsize', 1)
|
||||
const resolutionFactor = 1.4 - 0.4 * playerAgent.getPlayerConfig('fontsize', 1)
|
||||
config.resolution = {
|
||||
x: Math.round(1920 * resolutionFactor),
|
||||
y: Math.round(1080 * resolutionFactor),
|
||||
@ -133,7 +135,7 @@ export const getUserDanmakuConfig = async () => {
|
||||
|
||||
// 弹幕持续时长
|
||||
config.duration = (() => {
|
||||
const scrollDuration = 18 - 3 * getConfig('speedplus', 0)
|
||||
const scrollDuration = 18 - 3 * playerAgent.getPlayerConfig('speedplus', 0)
|
||||
return (danmaku: { type: number }) => {
|
||||
switch (danmaku.type) {
|
||||
case 4:
|
||||
@ -146,23 +148,25 @@ export const getUserDanmakuConfig = async () => {
|
||||
})()
|
||||
|
||||
// 底部间距
|
||||
const bottomMargin = getConfig('danmakuArea', 0)
|
||||
const bottomMargin = playerAgent.getPlayerConfig('danmakuArea', 0)
|
||||
config.bottomMarginPercent = bottomMargin >= 100 ? 0 : bottomMargin / 100
|
||||
// 无显示区域限制时要检查是否开启防挡字幕
|
||||
if (config.bottomMarginPercent === 0 && getConfig('preventshade', false)) {
|
||||
if (config.bottomMarginPercent === 0 && playerAgent.getPlayerConfig('preventshade', false)) {
|
||||
config.bottomMarginPercent = 0.15
|
||||
}
|
||||
|
||||
// 用户屏蔽词
|
||||
const blockSettings = lodash.get(playerSettings, 'block.list', []) as {
|
||||
/** 类型 */
|
||||
t: 'keyword' | 'regexp' | 'user'
|
||||
/** 内容 */
|
||||
v: string
|
||||
/** 是否开启 */
|
||||
s: boolean
|
||||
id: number
|
||||
}[]
|
||||
const blockSettings = playerAgent.getPlayerConfig<
|
||||
{
|
||||
/** 类型 */
|
||||
t: 'keyword' | 'regexp' | 'user'
|
||||
/** 内容 */
|
||||
v: string
|
||||
/** 是否开启 */
|
||||
s: boolean
|
||||
id: number
|
||||
}[]
|
||||
>('block.list', [])
|
||||
config.blockFilter = danmaku => {
|
||||
for (const b of blockSettings) {
|
||||
if (!b.s) {
|
||||
|
||||
@ -3,6 +3,17 @@ import { Toast } from '@/core/toast'
|
||||
import { getFriendlyTitle } from '@/core/utils/title'
|
||||
import { SubtitleConverterConfig } from '../subtitle-converter'
|
||||
|
||||
export interface SubtitleSettings {
|
||||
bilingual: boolean
|
||||
color: string
|
||||
fade: boolean
|
||||
fontsize: string
|
||||
lan: string
|
||||
opacity: number
|
||||
position: string
|
||||
scale: boolean
|
||||
shadow: string
|
||||
}
|
||||
export interface SubtitleInfo {
|
||||
id: number
|
||||
id_str: string
|
||||
@ -20,14 +31,10 @@ export const getSubtitleConfig = async (): Promise<[SubtitleConverterConfig, str
|
||||
'../subtitle-converter'
|
||||
)
|
||||
const { playerAgent } = await import('@/components/video/player-agent')
|
||||
const isBpxPlayer = dq('.bpx-player-video-wrap')
|
||||
const playerSettingsText = isBpxPlayer
|
||||
? localStorage.getItem('bpx_player_profile')
|
||||
: localStorage.getItem('bilibili_player_settings')
|
||||
if (!playerSettingsText) {
|
||||
const subtitleSettings = playerAgent.getPlayerConfig<null, SubtitleSettings>('subtitle', null)
|
||||
if (!subtitleSettings) {
|
||||
return [SubtitleConverter.defaultConfig, '']
|
||||
}
|
||||
const subtitleSettings = JSON.parse(playerSettingsText).subtitle
|
||||
const language = subtitleSettings.lan
|
||||
const title = getFriendlyTitle(true)
|
||||
const fontSizeMapping: { [key: number]: number } = {
|
||||
@ -38,11 +45,8 @@ export const getSubtitleConfig = async (): Promise<[SubtitleConverterConfig, str
|
||||
1.6: SubtitleSize.VeryLarge,
|
||||
}
|
||||
const size = fontSizeMapping[subtitleSettings.fontsize]
|
||||
const color =
|
||||
typeof subtitleSettings.color === 'number'
|
||||
? subtitleSettings.color.toString(16)
|
||||
: parseInt(subtitleSettings.color).toString(16)
|
||||
const opacity = subtitleSettings.backgroundopacity ?? subtitleSettings.opacity
|
||||
const color = parseInt(subtitleSettings.color).toString(16)
|
||||
const { opacity } = subtitleSettings
|
||||
|
||||
const positions = {
|
||||
bc: SubtitleLocation.BottomCenter,
|
||||
|
||||
@ -38,6 +38,8 @@ export abstract class PlayerAgent
|
||||
extends EventTarget
|
||||
implements EnumEventTarget<`${PlayerAgentEventTypes}`>
|
||||
{
|
||||
isBpxPlayer = true
|
||||
|
||||
abstract type: AgentType
|
||||
abstract query: PlayerQuery<ElementQuery>
|
||||
|
||||
@ -105,8 +107,12 @@ export abstract class PlayerAgent
|
||||
return null
|
||||
}
|
||||
|
||||
getPlayerConfig(target: string) {
|
||||
return lodash.get(JSON.parse(localStorage.getItem('bilibili_player_settings')), target, false)
|
||||
getPlayerConfig<DefaultValueType = unknown, ValueType = DefaultValueType>(
|
||||
target: string,
|
||||
defaultValue?: DefaultValueType,
|
||||
): ValueType | DefaultValueType {
|
||||
const storageKey = this.isBpxPlayer ? 'bpx_player_profile' : 'bilibili_player_settings'
|
||||
return lodash.get(JSON.parse(localStorage.getItem(storageKey)), target, defaultValue)
|
||||
}
|
||||
|
||||
isAutoPlay() {
|
||||
|
||||
@ -4,6 +4,7 @@ import { PlayerAgent, selectorWrap } from './base'
|
||||
import { AgentType, PlayerQuery, ElementQuery } from './types'
|
||||
|
||||
export class VideoPlayerV2Agent extends PlayerAgent {
|
||||
isBpxPlayer = false
|
||||
type: AgentType = 'video'
|
||||
query = selectorWrap({
|
||||
playerWrap: '.player-wrap',
|
||||
|
||||
@ -4,6 +4,7 @@ import { JSZipLibrary } from './runtime-library'
|
||||
import { getGeneralSettings } from './settings'
|
||||
import { formatFilename } from './utils/formatters'
|
||||
import { useScopedConsole } from './utils/log'
|
||||
import { getRandomId } from './utils'
|
||||
|
||||
/** 表示`DownloadPackage`中的一个文件 */
|
||||
export interface PackageEntry {
|
||||
@ -36,6 +37,7 @@ export class DownloadPackage {
|
||||
}
|
||||
/** 获取打包后的Blob数据 */
|
||||
async blob(): Promise<Blob | null> {
|
||||
const console = useScopedConsole('文件打包')
|
||||
if (this.entries.length === 0) {
|
||||
return null
|
||||
}
|
||||
@ -45,7 +47,20 @@ export class DownloadPackage {
|
||||
}
|
||||
const JSZip = await JSZipLibrary
|
||||
const zip = new JSZip()
|
||||
const fileExists = (name: string) => zip.filter((_, file) => file.name === name).length > 0
|
||||
this.entries.forEach(({ name, data, options }) => {
|
||||
if (fileExists(name)) {
|
||||
let tempName = name
|
||||
while (fileExists(tempName)) {
|
||||
const extensionIndex = name.lastIndexOf('.')
|
||||
tempName = `${name.substring(0, extensionIndex)}.${getRandomId(8)}${name.substring(
|
||||
extensionIndex,
|
||||
)}`
|
||||
}
|
||||
console.warn(`文件名 "${name}" 和已有文件冲突, 已临时更换为 "${tempName}"`)
|
||||
zip.file(tempName, data, options)
|
||||
return
|
||||
}
|
||||
zip.file(name, data, options)
|
||||
})
|
||||
return zip.generateAsync({ type: 'blob' })
|
||||
|
||||
Loading…
Reference in New Issue
Block a user