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
ca88f81c9b
@ -91,7 +91,7 @@
|
|||||||
不兼容.
|
不兼容.
|
||||||
|
|
||||||
### [AdGuard](https://adguard.com/zh_cn/adguard-windows/overview.html)
|
### [AdGuard](https://adguard.com/zh_cn/adguard-windows/overview.html)
|
||||||
未测试.
|
不兼容.
|
||||||
|
|
||||||
## 浏览器
|
## 浏览器
|
||||||
|
|
||||||
|
|||||||
@ -54,3 +54,23 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.new-silver-wallet {
|
||||||
|
background-color: var(--Ga1_u) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.new-list-box * .num > span {
|
||||||
|
color: var(--text3) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.click-root > .content-box {
|
||||||
|
color: #000 !important;
|
||||||
|
> .text {
|
||||||
|
color: #000 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.new-list-box * .static-bg-root {
|
||||||
|
--static-bg-color: #ffecf1 !important;
|
||||||
|
--static-bg-border-color: #ff6699 !important;
|
||||||
|
}
|
||||||
|
|||||||
@ -22,7 +22,7 @@
|
|||||||
<transition-group v-else name="cards" tag="div" class="cards">
|
<transition-group v-else name="cards" tag="div" class="cards">
|
||||||
<div v-for="card of filteredCards" :key="card.id" class="favorite-card">
|
<div v-for="card of filteredCards" :key="card.id" class="favorite-card">
|
||||||
<a
|
<a
|
||||||
class="cover-container"
|
class="favorites-cover-container"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
:href="'https://www.bilibili.com/video/' + card.bvid"
|
:href="'https://www.bilibili.com/video/' + card.bvid"
|
||||||
>
|
>
|
||||||
@ -376,7 +376,7 @@ export default Vue.extend({
|
|||||||
&:hover .cover {
|
&:hover .cover {
|
||||||
transform: scale(1.05);
|
transform: scale(1.05);
|
||||||
}
|
}
|
||||||
.cover-container {
|
.favorites-cover-container {
|
||||||
grid-area: cover;
|
grid-area: cover;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
border-radius: 8px 0 0 8px;
|
border-radius: 8px 0 0 8px;
|
||||||
|
|||||||
@ -48,7 +48,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<transition-group name="time-group" tag="div" class="time-group-items">
|
<transition-group name="time-group" tag="div" class="time-group-items">
|
||||||
<div v-for="h of g.items" :key="h.id" class="time-group-item">
|
<div v-for="h of g.items" :key="h.id" class="time-group-item">
|
||||||
<a class="cover-container" target="_blank" :href="h.url">
|
<a class="history-cover-container" target="_blank" :href="h.url">
|
||||||
<DpiImage
|
<DpiImage
|
||||||
class="cover"
|
class="cover"
|
||||||
:src="h.cover"
|
:src="h.cover"
|
||||||
@ -381,7 +381,7 @@ export default Vue.extend({
|
|||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.cover-container {
|
.history-cover-container {
|
||||||
$height: 55px;
|
$height: 55px;
|
||||||
$padding: 2px;
|
$padding: 2px;
|
||||||
grid-area: cover;
|
grid-area: cover;
|
||||||
|
|||||||
@ -11,7 +11,7 @@
|
|||||||
:href="card.playUrl"
|
:href="card.playUrl"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
>
|
>
|
||||||
<div class="cover-container">
|
<div class="subscriptions-cover-container">
|
||||||
<DpiImage class="cover" :src="card.coverUrl" :size="64"></DpiImage>
|
<DpiImage class="cover" :src="card.coverUrl" :size="64"></DpiImage>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-info">
|
<div class="card-info">
|
||||||
@ -186,7 +186,7 @@ export default Vue.extend({
|
|||||||
background-color: #2d2d2d;
|
background-color: #2d2d2d;
|
||||||
color: #eee;
|
color: #eee;
|
||||||
}
|
}
|
||||||
.cover-container {
|
.subscriptions-cover-container {
|
||||||
height: 64px;
|
height: 64px;
|
||||||
width: 64px;
|
width: 64px;
|
||||||
border-radius: $radius 0 0 $radius;
|
border-radius: $radius 0 0 $radius;
|
||||||
|
|||||||
@ -24,7 +24,7 @@
|
|||||||
<VEmpty v-else-if="!loading && cards.length === 0"></VEmpty>
|
<VEmpty v-else-if="!loading && cards.length === 0"></VEmpty>
|
||||||
<transition-group v-else name="cards" tag="div" class="watchlater-list-content">
|
<transition-group v-else name="cards" tag="div" class="watchlater-list-content">
|
||||||
<div v-for="(card, index) of filteredCards" :key="card.aid" class="watchlater-card">
|
<div v-for="(card, index) of filteredCards" :key="card.aid" class="watchlater-card">
|
||||||
<a class="cover-container" target="_blank" :href="card.href">
|
<a class="watchlater-cover-container" target="_blank" :href="card.href">
|
||||||
<DpiImage
|
<DpiImage
|
||||||
class="cover"
|
class="cover"
|
||||||
:src="card.coverUrl"
|
:src="card.coverUrl"
|
||||||
@ -285,7 +285,7 @@ export default Vue.extend({
|
|||||||
&:hover .cover {
|
&:hover .cover {
|
||||||
transform: scale(1.05);
|
transform: scale(1.05);
|
||||||
}
|
}
|
||||||
.cover-container {
|
.watchlater-cover-container {
|
||||||
grid-area: cover;
|
grid-area: cover;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
border-radius: 8px 0 0 8px;
|
border-radius: 8px 0 0 8px;
|
||||||
|
|||||||
@ -3,7 +3,8 @@
|
|||||||
.bilibili-player-ending-panel-box-videos,
|
.bilibili-player-ending-panel-box-videos,
|
||||||
.r-con .rcmd-list,
|
.r-con .rcmd-list,
|
||||||
.playlist-container .recommend-list-container,
|
.playlist-container .recommend-list-container,
|
||||||
.bpx-player-ending-related {
|
.bpx-player-ending-related,
|
||||||
|
.plp-r [class*="recommend_wrap"] {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
.bilibili-player-ending-panel-box-functions .bilibili-player-upinfo-spans {
|
.bilibili-player-ending-panel-box-functions .bilibili-player-upinfo-spans {
|
||||||
|
|||||||
1
registry/lib/components/video/subtitle/download/index.md
Normal file
1
registry/lib/components/video/subtitle/download/index.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
启用下载字幕支持, 在视频页面中可从功能面板里下载字幕. (AI 生成的不可下载)
|
||||||
@ -9,9 +9,6 @@ import { getBlobByType, SubtitleDownloadType } from './utils'
|
|||||||
export const component = defineComponentMetadata({
|
export const component = defineComponentMetadata({
|
||||||
name: 'downloadSubtitle',
|
name: 'downloadSubtitle',
|
||||||
displayName: '下载字幕',
|
displayName: '下载字幕',
|
||||||
description: {
|
|
||||||
'zh-CN': '启用下载字幕支持, 在视频页面中可从功能面板里下载字幕.',
|
|
||||||
},
|
|
||||||
tags: [componentsTags.video],
|
tags: [componentsTags.video],
|
||||||
entry: none,
|
entry: none,
|
||||||
urlInclude: videoAndBangumiUrls,
|
urlInclude: videoAndBangumiUrls,
|
||||||
|
|||||||
@ -1,8 +1,19 @@
|
|||||||
import { getJson } from '@/core/ajax'
|
import { bilibiliApi, getJson, getJsonWithCredentials } from '@/core/ajax'
|
||||||
import { Toast } from '@/core/toast'
|
import { Toast } from '@/core/toast'
|
||||||
import { getFriendlyTitle } from '@/core/utils/title'
|
import { getFriendlyTitle } from '@/core/utils/title'
|
||||||
import { SubtitleConverterConfig } from '../subtitle-converter'
|
import { SubtitleConverterConfig } from '../subtitle-converter'
|
||||||
|
|
||||||
|
export interface SubtitleInfo {
|
||||||
|
id: number
|
||||||
|
id_str: string
|
||||||
|
lan: string
|
||||||
|
lan_doc: string
|
||||||
|
is_lock: boolean
|
||||||
|
subtitle_url: string
|
||||||
|
type: number
|
||||||
|
ai_type: number
|
||||||
|
ai_status: number
|
||||||
|
}
|
||||||
export type SubtitleDownloadType = 'json' | 'ass'
|
export type SubtitleDownloadType = 'json' | 'ass'
|
||||||
export const getSubtitleConfig = async (): Promise<[SubtitleConverterConfig, string]> => {
|
export const getSubtitleConfig = async (): Promise<[SubtitleConverterConfig, string]> => {
|
||||||
const { SubtitleConverter, SubtitleSize, SubtitleLocation } = await import(
|
const { SubtitleConverter, SubtitleSize, SubtitleLocation } = await import(
|
||||||
@ -64,11 +75,10 @@ export const getSubtitleConfig = async (): Promise<[SubtitleConverterConfig, str
|
|||||||
return [config, language]
|
return [config, language]
|
||||||
}
|
}
|
||||||
export const getSubtitleList = async (aid: string, cid: string | number) => {
|
export const getSubtitleList = async (aid: string, cid: string | number) => {
|
||||||
const { VideoInfo } = await import('@/components/video/video-info')
|
const data = await bilibiliApi(
|
||||||
const info = new VideoInfo(aid)
|
getJsonWithCredentials(`https://api.bilibili.com/x/player/wbi/v2?aid=${aid}&cid=${cid}`),
|
||||||
info.cid = typeof cid === 'string' ? parseInt(cid) : cid
|
)
|
||||||
await info.fetchInfo()
|
return lodash.get(data, 'subtitle.subtitles', []) as SubtitleInfo[]
|
||||||
return info.subtitles
|
|
||||||
}
|
}
|
||||||
export const getBlobByType = async (
|
export const getBlobByType = async (
|
||||||
type: SubtitleDownloadType,
|
type: SubtitleDownloadType,
|
||||||
@ -88,8 +98,8 @@ export const getBlobByType = async (
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
const [config, language] = await getSubtitleConfig()
|
const [config, language] = await getSubtitleConfig()
|
||||||
const subtitle = subtitles.find(s => s.languageCode === language) || subtitles[0]
|
const subtitle = subtitles.find(s => s.lan === language) || subtitles[0]
|
||||||
const json = await getJson(subtitle.url)
|
const json = await getJson(subtitle.subtitle_url)
|
||||||
const rawData = json.body
|
const rawData = json.body
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'ass': {
|
case 'ass': {
|
||||||
@ -102,7 +112,7 @@ export const getBlobByType = async (
|
|||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
case 'json': {
|
case 'json': {
|
||||||
return new Blob([JSON.stringify(rawData)], {
|
return new Blob([JSON.stringify(rawData, undefined, 2)], {
|
||||||
type: 'text/json',
|
type: 'text/json',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,8 +7,8 @@
|
|||||||
@click.self="performAction($event)"
|
@click.self="performAction($event)"
|
||||||
@keydown.enter.prevent.stop="performAction($event)"
|
@keydown.enter.prevent.stop="performAction($event)"
|
||||||
@keydown.shift.delete.prevent.stop="performDelete($event)"
|
@keydown.shift.delete.prevent.stop="performDelete($event)"
|
||||||
@keydown.up.prevent.stop="$emit('previous-item', $event)"
|
@keydown.up.prevent.stop="$emit('previous-item', $event.currentTarget)"
|
||||||
@keydown.down.prevent.stop="$emit('next-item', $event)"
|
@keydown.down.prevent.stop="$emit('next-item', $event.currentTarget)"
|
||||||
>
|
>
|
||||||
<div class="suggest-item-content">
|
<div class="suggest-item-content">
|
||||||
<div v-if="action.icon" class="suggest-item-icon" @click="performAction($event)">
|
<div v-if="action.icon" class="suggest-item-icon" @click="performAction($event)">
|
||||||
@ -54,15 +54,17 @@ export default Vue.extend({
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async performAction(event: KeyboardEvent | MouseEvent) {
|
async performAction(event: KeyboardEvent | MouseEvent) {
|
||||||
|
const { currentTarget } = event
|
||||||
await this.action.action()
|
await this.action.action()
|
||||||
this.$emit('action', event)
|
this.$emit('action', currentTarget)
|
||||||
},
|
},
|
||||||
async performDelete(event: KeyboardEvent | MouseEvent) {
|
async performDelete(event: KeyboardEvent | MouseEvent) {
|
||||||
|
const { currentTarget } = event
|
||||||
if (!this.action.deleteAction) {
|
if (!this.action.deleteAction) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
await this.action.deleteAction()
|
await this.action.deleteAction()
|
||||||
this.$emit('delete-item', event)
|
this.$emit('delete-item', currentTarget)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@ -221,24 +221,24 @@ export default Vue.extend({
|
|||||||
this.$refs.list.querySelector('.suggest-item').focus()
|
this.$refs.list.querySelector('.suggest-item').focus()
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
},
|
},
|
||||||
previousItem(e: KeyboardEvent, index: number) {
|
previousItem(element: HTMLElement, index: number) {
|
||||||
if (index === 0) {
|
if (index === 0) {
|
||||||
this.focus()
|
this.focus()
|
||||||
} else {
|
} else {
|
||||||
;((e.currentTarget as HTMLElement).previousElementSibling as HTMLElement).focus()
|
;(element.previousElementSibling as HTMLElement).focus()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
nextItem(e: KeyboardEvent, index: number) {
|
nextItem(element: HTMLElement, index: number) {
|
||||||
const lastItemIndex = this.actions.length - 1
|
const lastItemIndex = this.actions.length - 1
|
||||||
if (index !== lastItemIndex) {
|
if (index !== lastItemIndex) {
|
||||||
;((e.currentTarget as HTMLElement).nextElementSibling as HTMLElement).focus()
|
;(element.nextElementSibling as HTMLElement).focus()
|
||||||
} else {
|
} else {
|
||||||
this.focus()
|
this.focus()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
search,
|
search,
|
||||||
onDeleteItem(e: Event, index: number) {
|
onDeleteItem(element: HTMLElement, index: number) {
|
||||||
this.previousItem(e, index)
|
this.previousItem(element, index)
|
||||||
this.getActions()
|
this.getActions()
|
||||||
},
|
},
|
||||||
onClearHistory() {
|
onClearHistory() {
|
||||||
|
|||||||
@ -21,12 +21,6 @@ export class VideoInfo {
|
|||||||
title: string
|
title: string
|
||||||
pageNumber: number
|
pageNumber: number
|
||||||
}[]
|
}[]
|
||||||
subtitles: {
|
|
||||||
id: number
|
|
||||||
languageCode: string
|
|
||||||
language: string
|
|
||||||
url: string
|
|
||||||
}[]
|
|
||||||
|
|
||||||
constructor(id: string, bvid = false) {
|
constructor(id: string, bvid = false) {
|
||||||
if (bvid) {
|
if (bvid) {
|
||||||
@ -70,15 +64,20 @@ export class VideoInfo {
|
|||||||
title: it.part,
|
title: it.part,
|
||||||
pageNumber: it.page,
|
pageNumber: it.page,
|
||||||
}))
|
}))
|
||||||
this.subtitles =
|
|
||||||
data.subtitle?.list?.map((it: any) => ({
|
|
||||||
id: it.id,
|
|
||||||
languageCode: it.lan,
|
|
||||||
language: it.lan_doc,
|
|
||||||
url: it.subtitle_url.replace('http:', 'https:'),
|
|
||||||
})) ?? []
|
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @deprecated */
|
||||||
|
// eslint-disable-next-line class-methods-use-this
|
||||||
|
get subtitles(): {
|
||||||
|
id: number
|
||||||
|
languageCode: string
|
||||||
|
language: string
|
||||||
|
url: string
|
||||||
|
}[] {
|
||||||
|
console.warn('VideoInfo.subtitles is deprecated')
|
||||||
|
return []
|
||||||
|
}
|
||||||
}
|
}
|
||||||
export class BangumiInfo {
|
export class BangumiInfo {
|
||||||
ep: number
|
ep: number
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user