Merge branch 'preview-fixes' into preview-features

This commit is contained in:
the1812 2023-07-27 23:14:06 +08:00
commit ca88f81c9b
13 changed files with 75 additions and 45 deletions

View File

@ -91,7 +91,7 @@
不兼容. 不兼容.
### [AdGuard](https://adguard.com/zh_cn/adguard-windows/overview.html) ### [AdGuard](https://adguard.com/zh_cn/adguard-windows/overview.html)
未测试. 不兼容.
## 浏览器 ## 浏览器

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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 {

View File

@ -0,0 +1 @@
启用下载字幕支持, 在视频页面中可从功能面板里下载字幕. (AI 生成的不可下载)

View File

@ -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,

View File

@ -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',
}) })
} }

View File

@ -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)
}, },
}, },
}) })

View File

@ -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() {

View File

@ -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