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
24714b77a7
@ -28,7 +28,6 @@
|
|||||||
"name": "Install dependencies",
|
"name": "Install dependencies",
|
||||||
"uses": "pnpm/action-setup@v4",
|
"uses": "pnpm/action-setup@v4",
|
||||||
"with": {
|
"with": {
|
||||||
"version": "8.12.1",
|
|
||||||
"run_install": true
|
"run_install": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -17,7 +17,6 @@
|
|||||||
"name": "Install dependencies",
|
"name": "Install dependencies",
|
||||||
"uses": "pnpm/action-setup@v4",
|
"uses": "pnpm/action-setup@v4",
|
||||||
"with": {
|
"with": {
|
||||||
"version": "8.12.1",
|
|
||||||
"run_install": true
|
"run_install": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
1
.github/workflows/build.yml
vendored
1
.github/workflows/build.yml
vendored
@ -22,7 +22,6 @@ jobs:
|
|||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
uses: pnpm/action-setup@v4
|
uses: pnpm/action-setup@v4
|
||||||
with:
|
with:
|
||||||
version: 8.12.1
|
|
||||||
run_install: true
|
run_install: true
|
||||||
- name: Type check
|
- name: Type check
|
||||||
run: pnpm run type
|
run: pnpm run type
|
||||||
|
|||||||
1
.github/workflows/pull-request-check.yml
vendored
1
.github/workflows/pull-request-check.yml
vendored
@ -11,7 +11,6 @@ jobs:
|
|||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
uses: pnpm/action-setup@v4
|
uses: pnpm/action-setup@v4
|
||||||
with:
|
with:
|
||||||
version: 8.12.1
|
|
||||||
run_install: true
|
run_install: true
|
||||||
- name: Type check
|
- name: Type check
|
||||||
run: pnpm run type
|
run: pnpm run type
|
||||||
|
|||||||
12
package.json
12
package.json
@ -51,7 +51,7 @@
|
|||||||
"postcss-loader": "^4.0.4",
|
"postcss-loader": "^4.0.4",
|
||||||
"postcss-preset-env": "^7.5.0",
|
"postcss-preset-env": "^7.5.0",
|
||||||
"prettier": "^2.8.3",
|
"prettier": "^2.8.3",
|
||||||
"sass": "^1.25.0",
|
"sass": "1.25.0",
|
||||||
"serve": "^13.0.2",
|
"serve": "^13.0.2",
|
||||||
"serve-handler": "^6.1.3",
|
"serve-handler": "^6.1.3",
|
||||||
"style-loader": "^2.0.0",
|
"style-loader": "^2.0.0",
|
||||||
@ -60,6 +60,7 @@
|
|||||||
"to-string-loader": "^1.2.0",
|
"to-string-loader": "^1.2.0",
|
||||||
"ts-node": "^10.7.0",
|
"ts-node": "^10.7.0",
|
||||||
"typescript": "^4.9.5",
|
"typescript": "^4.9.5",
|
||||||
|
"vue-eslint-parser": "^9.4.3",
|
||||||
"vue-loader": "^15.10.1",
|
"vue-loader": "^15.10.1",
|
||||||
"webpack": "^5.31.2",
|
"webpack": "^5.31.2",
|
||||||
"webpack-bundle-analyzer": "^4.5.0",
|
"webpack-bundle-analyzer": "^4.5.0",
|
||||||
@ -84,7 +85,11 @@
|
|||||||
"overrides": {
|
"overrides": {
|
||||||
"caniuse-lite": "1.0.30001668",
|
"caniuse-lite": "1.0.30001668",
|
||||||
"consolidate": "1.0.1"
|
"consolidate": "1.0.1"
|
||||||
}
|
},
|
||||||
|
"onlyBuiltDependencies": [
|
||||||
|
"@parcel/watcher",
|
||||||
|
"protobufjs"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"userscript",
|
"userscript",
|
||||||
@ -92,5 +97,6 @@
|
|||||||
"dark-theme",
|
"dark-theme",
|
||||||
"touchscreen",
|
"touchscreen",
|
||||||
"tampermonkey"
|
"tampermonkey"
|
||||||
]
|
],
|
||||||
|
"packageManager": "pnpm@10.3.0+sha512.ee592eda8815a8a293c206bb0917c4bb0ff274c50def7cbc17be05ec641fc2d1b02490ce660061356bd0d126a4d7eb2ec8830e6959fb8a447571c631d5a2442d"
|
||||||
}
|
}
|
||||||
|
|||||||
10174
pnpm-lock.yaml
generated
10174
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -10,7 +10,6 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { addComponentListener } from '@/core/settings'
|
import { addComponentListener } from '@/core/settings'
|
||||||
import { getUID } from '@/core/utils'
|
|
||||||
import { ascendingSort } from '@/core/utils/sort'
|
import { ascendingSort } from '@/core/utils/sort'
|
||||||
import { registerAndGetData } from '@/plugins/data'
|
import { registerAndGetData } from '@/plugins/data'
|
||||||
import { getBuiltInItems } from './built-in-items'
|
import { getBuiltInItems } from './built-in-items'
|
||||||
@ -28,14 +27,7 @@ const [renderedItems] = registerAndGetData(CustomNavbarRenderedItems, {
|
|||||||
items: [] as CustomNavbarItem[],
|
items: [] as CustomNavbarItem[],
|
||||||
})
|
})
|
||||||
const getItems = () => {
|
const getItems = () => {
|
||||||
const isLogin = Boolean(getUID())
|
|
||||||
const items = (initItems as CustomNavbarItemInit[])
|
const items = (initItems as CustomNavbarItemInit[])
|
||||||
.filter(it => {
|
|
||||||
if (it.loginRequired && !isLogin) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
.map(it => new CustomNavbarItem(it))
|
.map(it => new CustomNavbarItem(it))
|
||||||
.sort(ascendingSort(it => it.order))
|
.sort(ascendingSort(it => it.order))
|
||||||
renderedItems.items = items
|
renderedItems.items = items
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import { createPopper, Instance as Popper } from '@popperjs/core'
|
|||||||
import { VueModule, Executable } from '@/core/common-types'
|
import { VueModule, Executable } from '@/core/common-types'
|
||||||
import { getComponentSettings, addComponentListener } from '@/core/settings'
|
import { getComponentSettings, addComponentListener } from '@/core/settings'
|
||||||
import type { CustomNavbarOptions } from '.'
|
import type { CustomNavbarOptions } from '.'
|
||||||
|
import { getUID } from '@/core/utils'
|
||||||
|
|
||||||
export const CustomNavbarItems = 'customNavbar.items'
|
export const CustomNavbarItems = 'customNavbar.items'
|
||||||
export const CustomNavbarRenderedItems = 'customNavbar.renderedItems'
|
export const CustomNavbarRenderedItems = 'customNavbar.renderedItems'
|
||||||
@ -90,7 +91,8 @@ export class CustomNavbarItem implements Required<CustomNavbarItemInit> {
|
|||||||
},
|
},
|
||||||
true,
|
true,
|
||||||
)
|
)
|
||||||
this.hidden = CustomNavbarItem.navbarOptions.hidden.includes(this.name)
|
this.hidden =
|
||||||
|
CustomNavbarItem.navbarOptions.hidden.includes(this.name) || (!getUID() && init.loginRequired)
|
||||||
const orderMap = CustomNavbarItem.navbarOptions.order
|
const orderMap = CustomNavbarItem.navbarOptions.order
|
||||||
this.order = orderMap[this.name] || 0
|
this.order = orderMap[this.name] || 0
|
||||||
this.requestedPopup = !this.lazy
|
this.requestedPopup = !this.lazy
|
||||||
|
|||||||
@ -35,6 +35,7 @@ export const entry: ComponentEntry = async ({ metadata: { name } }) => {
|
|||||||
'https://www.bilibili.com/opus',
|
'https://www.bilibili.com/opus',
|
||||||
'https://www.bilibili.com/account/history',
|
'https://www.bilibili.com/account/history',
|
||||||
'https://www.bilibili.com/v/topic/detail',
|
'https://www.bilibili.com/v/topic/detail',
|
||||||
|
'https://www.bilibili.com/watchlater/list',
|
||||||
]
|
]
|
||||||
if (!globalFixedExclude.some(p => matchUrlPattern(p))) {
|
if (!globalFixedExclude.some(p => matchUrlPattern(p))) {
|
||||||
addComponentListener(
|
addComponentListener(
|
||||||
|
|||||||
@ -118,6 +118,7 @@ export default Vue.extend({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
const list: HTMLElement = this.$refs.navbarSortList
|
const list: HTMLElement = this.$refs.navbarSortList
|
||||||
|
if (list) {
|
||||||
const Sortable = await SortableJSLibrary
|
const Sortable = await SortableJSLibrary
|
||||||
Sortable.create(list, {
|
Sortable.create(list, {
|
||||||
delay: 100,
|
delay: 100,
|
||||||
@ -127,11 +128,8 @@ export default Vue.extend({
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
checkSequentialOrder(rendered.items)
|
checkSequentialOrder(rendered.items)
|
||||||
|
}
|
||||||
this.loaded = true
|
this.loaded = true
|
||||||
// unsafeWindow.nsTest = {
|
|
||||||
// list,
|
|
||||||
// Sortable,
|
|
||||||
// }
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
toggle() {
|
toggle() {
|
||||||
|
|||||||
@ -4,11 +4,11 @@ interface SimpleLinkConfig {
|
|||||||
name: string
|
name: string
|
||||||
displayName: string
|
displayName: string
|
||||||
href: string
|
href: string
|
||||||
|
content?: string
|
||||||
}
|
}
|
||||||
const getSimpleLinkItem = (config: SimpleLinkConfig): SimpleLinkConfig & CustomNavbarItemInit => ({
|
const getSimpleLinkItem = (config: SimpleLinkConfig): SimpleLinkConfig & CustomNavbarItemInit => ({
|
||||||
...config,
|
|
||||||
content: config.displayName,
|
content: config.displayName,
|
||||||
|
...config,
|
||||||
active: document.URL.startsWith(config.href),
|
active: document.URL.startsWith(config.href),
|
||||||
})
|
})
|
||||||
export const ranking = getSimpleLinkItem({
|
export const ranking = getSimpleLinkItem({
|
||||||
@ -18,7 +18,8 @@ export const ranking = getSimpleLinkItem({
|
|||||||
})
|
})
|
||||||
export const bangumi = getSimpleLinkItem({
|
export const bangumi = getSimpleLinkItem({
|
||||||
name: 'bangumi',
|
name: 'bangumi',
|
||||||
displayName: '番剧',
|
displayName: '番剧 (链接)',
|
||||||
|
content: '番剧',
|
||||||
href: 'https://www.bilibili.com/anime/',
|
href: 'https://www.bilibili.com/anime/',
|
||||||
})
|
})
|
||||||
export const music = getSimpleLinkItem({
|
export const music = getSimpleLinkItem({
|
||||||
|
|||||||
@ -0,0 +1,42 @@
|
|||||||
|
<template>
|
||||||
|
<div class="">{{ content }}</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts">
|
||||||
|
import {
|
||||||
|
addComponentListener,
|
||||||
|
getComponentSettings,
|
||||||
|
removeComponentListener,
|
||||||
|
} from '@/core/settings'
|
||||||
|
import type { CustomNavbarOptions } from '..'
|
||||||
|
|
||||||
|
export default Vue.extend({
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
isBangumiLinkHidden:
|
||||||
|
getComponentSettings<CustomNavbarOptions>('customNavbar').options.hidden.includes(
|
||||||
|
'bangumi',
|
||||||
|
),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
content() {
|
||||||
|
if (this.isBangumiLinkHidden) {
|
||||||
|
return '番剧'
|
||||||
|
}
|
||||||
|
return '追番追剧'
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
addComponentListener('customNavbar.hidden', this.updateBangumiLinkStatus)
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
removeComponentListener('customNavbar.hidden', this.updateBangumiLinkStatus)
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
updateBangumiLinkStatus(hiddenItems: string[]) {
|
||||||
|
const isBangumiLinkHidden = hiddenItems.includes('bangumi')
|
||||||
|
this.isBangumiLinkHidden = isBangumiLinkHidden
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
</script>
|
||||||
@ -8,8 +8,8 @@ export enum SubscriptionTypes {
|
|||||||
const uid = getUID()
|
const uid = getUID()
|
||||||
export const subscriptions: CustomNavbarItemInit = {
|
export const subscriptions: CustomNavbarItemInit = {
|
||||||
name: 'subscriptions',
|
name: 'subscriptions',
|
||||||
displayName: '番剧',
|
displayName: '番剧 (弹窗)',
|
||||||
content: '番剧',
|
content: () => import('./Content.vue').then(m => m.default),
|
||||||
|
|
||||||
href: `https://space.bilibili.com/${uid}/bangumi`,
|
href: `https://space.bilibili.com/${uid}/bangumi`,
|
||||||
touch: true,
|
touch: true,
|
||||||
|
|||||||
@ -40,7 +40,7 @@
|
|||||||
<div v-if="card.percent" class="progress" :style="{ width: card.percent * 100 + '%' }" />
|
<div v-if="card.percent" class="progress" :style="{ width: card.percent * 100 + '%' }" />
|
||||||
</a>
|
</a>
|
||||||
<a class="title" target="_blank" :href="card.href" :title="card.title">{{ card.title }}</a>
|
<a class="title" target="_blank" :href="card.href" :title="card.title">{{ card.title }}</a>
|
||||||
<div class="info">
|
<div class="info-row">
|
||||||
<a
|
<a
|
||||||
class="up"
|
class="up"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
@ -352,7 +352,7 @@ export default Vue.extend({
|
|||||||
color: var(--theme-color) !important;
|
color: var(--theme-color) !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.info {
|
.info-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: flex-end;
|
align-items: flex-end;
|
||||||
|
|||||||
@ -16,5 +16,6 @@
|
|||||||
@import "./dark-slice-16.scss";
|
@import "./dark-slice-16.scss";
|
||||||
@import "./dark-slice-17.scss";
|
@import "./dark-slice-17.scss";
|
||||||
@import "./dark-slice-18.scss";
|
@import "./dark-slice-18.scss";
|
||||||
|
@import "./dark-slice-19.scss";
|
||||||
@import "./dark-navbar.scss";
|
@import "./dark-navbar.scss";
|
||||||
@import "./dark-variables.scss";
|
@import "./dark-variables.scss";
|
||||||
|
|||||||
@ -619,7 +619,7 @@ html {
|
|||||||
&:not(.iframe) {
|
&:not(.iframe) {
|
||||||
&,
|
&,
|
||||||
body {
|
body {
|
||||||
@include background-color('2');
|
background-color: var(--bg1, #222) !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,8 @@
|
|||||||
|
@import './dark-definitions';
|
||||||
|
@import 'common';
|
||||||
|
|
||||||
|
.relation-card-info-option {
|
||||||
|
.follow-btn {
|
||||||
|
@include background-color();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,6 +1,6 @@
|
|||||||
import { postTextWithCredentials, getJsonWithCredentials } from '@/core/ajax'
|
import { postTextWithCredentials } from '@/core/ajax'
|
||||||
import { Toast } from '@/core/toast'
|
import { Toast } from '@/core/toast'
|
||||||
import { formData, getCsrf } from '@/core/utils'
|
import { getCsrf } from '@/core/utils'
|
||||||
import { registerAndGetData } from '@/plugins/data'
|
import { registerAndGetData } from '@/plugins/data'
|
||||||
|
|
||||||
export interface CheckInItem {
|
export interface CheckInItem {
|
||||||
@ -19,7 +19,7 @@ const builtInItems: CheckInItem[] = [
|
|||||||
const seedsToCoinsApi = 'https://api.live.bilibili.com/xlive/revenue/v1/wallet/silver2coin'
|
const seedsToCoinsApi = 'https://api.live.bilibili.com/xlive/revenue/v1/wallet/silver2coin'
|
||||||
const text = await postTextWithCredentials(
|
const text = await postTextWithCredentials(
|
||||||
seedsToCoinsApi,
|
seedsToCoinsApi,
|
||||||
formData({
|
new URLSearchParams({
|
||||||
csrf: getCsrf(),
|
csrf: getCsrf(),
|
||||||
csrf_token: getCsrf(),
|
csrf_token: getCsrf(),
|
||||||
}),
|
}),
|
||||||
@ -40,31 +40,5 @@ const builtInItems: CheckInItem[] = [
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: 'live-check-in',
|
|
||||||
displayName: '直播间签到',
|
|
||||||
icon: 'mdi-calendar-check',
|
|
||||||
action: async () => {
|
|
||||||
const liveCheckInApi = 'https://api.live.bilibili.com/xlive/web-ucenter/v1/sign/DoSign'
|
|
||||||
const json = (await getJsonWithCredentials(liveCheckInApi)) as {
|
|
||||||
code: number
|
|
||||||
message: string
|
|
||||||
data: {
|
|
||||||
text: string
|
|
||||||
specialText: string
|
|
||||||
allDays: number
|
|
||||||
hadSignDays: number
|
|
||||||
isBonusDay: number
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (json.code !== 0) {
|
|
||||||
Toast.info(json.message, '直播间签到', 3000)
|
|
||||||
} else {
|
|
||||||
const { text, specialText, allDays, hadSignDays } = json.data
|
|
||||||
const message = `签到成功, 获得了${text} ${specialText}\n本月进度: ${hadSignDays} / ${allDays}`
|
|
||||||
Toast.success(message, '直播间签到', 3000)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]
|
]
|
||||||
export const [checkInItems] = registerAndGetData('checkInCenter.items', builtInItems)
|
export const [checkInItems] = registerAndGetData('checkInCenter.items', builtInItems)
|
||||||
|
|||||||
@ -23,7 +23,7 @@ export const setupFeedImageExporter: ComponentEntry<Options> = async ({
|
|||||||
const imageUrls: { url: string; extension: string }[] = []
|
const imageUrls: { url: string; extension: string }[] = []
|
||||||
dqa(
|
dqa(
|
||||||
card.element,
|
card.element,
|
||||||
'.main-content .img-content, .bili-album__preview__picture__img, .bili-album .preview__picture__img, .bili-dyn-gallery__image img',
|
'.main-content .img-content, .bili-album__preview__picture__img, .bili-album .preview__picture__img, .bili-dyn-gallery__image img, .bili-album__watch__track__item img',
|
||||||
).forEach((img: HTMLImageElement | HTMLDivElement) => {
|
).forEach((img: HTMLImageElement | HTMLDivElement) => {
|
||||||
const urlData = retrieveImageUrl(img)
|
const urlData = retrieveImageUrl(img)
|
||||||
if (urlData && !imageUrls.some(({ url }) => url === urlData.url)) {
|
if (urlData && !imageUrls.some(({ url }) => url === urlData.url)) {
|
||||||
|
|||||||
7
registry/lib/components/utils/image-resolution/index.md
Normal file
7
registry/lib/components/utils/image-resolution/index.md
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
对 200% 以上的屏幕 DPI 缩放请求更高分辨率的图片, 加载时间也会相应变长一些. (也会导致某些浏览器里出现图片闪动, 因为本质上是更换了图片源)
|
||||||
|
|
||||||
|
由于 b 站在很多地方没有设置图片维持原比例, 如果计算后的图片尺寸超出原图尺寸则会产生错误的比例, 可以考虑在选项中手动降低缩放级别.
|
||||||
|
|
||||||
|
`缩放级别` 选项:
|
||||||
|
- `auto`: 根据 DPI 缩放超出 200% 的比例自动计算, 例如 250% 的缩放下会请求 1.5 倍尺寸的图片.
|
||||||
|
- `数字`: 自定义尺寸的缩放倍率.
|
||||||
@ -9,7 +9,6 @@ const options = defineOptionsMetadata({
|
|||||||
scale: {
|
scale: {
|
||||||
displayName: '缩放级别',
|
displayName: '缩放级别',
|
||||||
defaultValue: 'auto',
|
defaultValue: 'auto',
|
||||||
hidden: true,
|
|
||||||
},
|
},
|
||||||
originalImageInArticles: {
|
originalImageInArticles: {
|
||||||
displayName: '在专栏中请求原图',
|
displayName: '在专栏中请求原图',
|
||||||
@ -25,9 +24,5 @@ export const component = defineComponentMetadata({
|
|||||||
tags: [componentsTags.utils],
|
tags: [componentsTags.utils],
|
||||||
enabledByDefault: window.devicePixelRatio > 1,
|
enabledByDefault: window.devicePixelRatio > 1,
|
||||||
entry: startResolution,
|
entry: startResolution,
|
||||||
description: {
|
|
||||||
'zh-CN':
|
|
||||||
'根据屏幕 DPI 请求更高分辨率的图片, 例如 DPI 缩放 200% 则请求 2 倍的分辨率, 加载时间也会相应变长一些. (也会导致某些浏览器里出现图片闪动, 因为本质上是更换了图片源)',
|
|
||||||
},
|
|
||||||
options,
|
options,
|
||||||
})
|
})
|
||||||
|
|||||||
@ -19,6 +19,13 @@ const widthAndHeightSelectors = [
|
|||||||
]
|
]
|
||||||
const originalImageInArticlesSelectors = ['.article-detail .article-content img']
|
const originalImageInArticlesSelectors = ['.article-detail .article-content img']
|
||||||
|
|
||||||
|
const getAutoScale = () => {
|
||||||
|
if (window.devicePixelRatio <= 2) {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return window.devicePixelRatio / 2
|
||||||
|
}
|
||||||
|
|
||||||
const walk = (rootElement: Node, action: (node: HTMLElement) => void) => {
|
const walk = (rootElement: Node, action: (node: HTMLElement) => void) => {
|
||||||
const walker = document.createNodeIterator(rootElement, NodeFilter.SHOW_ELEMENT)
|
const walker = document.createNodeIterator(rootElement, NodeFilter.SHOW_ELEMENT)
|
||||||
let node = walker.nextNode()
|
let node = walker.nextNode()
|
||||||
@ -123,10 +130,11 @@ export const startResolution = styledComponentEntry<Options>(
|
|||||||
() => import('./fix.scss'),
|
() => import('./fix.scss'),
|
||||||
async ({ settings }) => {
|
async ({ settings }) => {
|
||||||
const { allMutations } = await import('@/core/observer')
|
const { allMutations } = await import('@/core/observer')
|
||||||
const dpi =
|
const scale =
|
||||||
settings.options.scale === 'auto'
|
settings.options.scale === 'auto' ? getAutoScale() : parseFloat(settings.options.scale)
|
||||||
? window.devicePixelRatio
|
if (scale === 1) {
|
||||||
: parseFloat(settings.options.scale)
|
return
|
||||||
|
}
|
||||||
const handleResolution: ImageResolutionHandler = {
|
const handleResolution: ImageResolutionHandler = {
|
||||||
getWidth: (currentWidth, element) => {
|
getWidth: (currentWidth, element) => {
|
||||||
if (
|
if (
|
||||||
@ -135,7 +143,7 @@ export const startResolution = styledComponentEntry<Options>(
|
|||||||
) {
|
) {
|
||||||
return Infinity
|
return Infinity
|
||||||
}
|
}
|
||||||
return Math.round(dpi * currentWidth)
|
return Math.round(scale * currentWidth)
|
||||||
},
|
},
|
||||||
getHeight: (currentHeight, element) => {
|
getHeight: (currentHeight, element) => {
|
||||||
if (
|
if (
|
||||||
@ -144,7 +152,7 @@ export const startResolution = styledComponentEntry<Options>(
|
|||||||
) {
|
) {
|
||||||
return Infinity
|
return Infinity
|
||||||
}
|
}
|
||||||
return Math.round(dpi * currentHeight)
|
return Math.round(scale * currentHeight)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { isTyping, matchUrlPattern } from '@/core/utils'
|
import { getActiveElement, isTyping, matchUrlPattern } from '@/core/utils'
|
||||||
import { mediaListUrls, watchlaterUrls } from '@/core/utils/urls'
|
import { mediaListUrls, watchlaterUrls } from '@/core/utils/urls'
|
||||||
import { clickElement, changeVideoTime, showTip } from './actions'
|
import { clickElement, changeVideoTime, showTip } from './actions'
|
||||||
import { shadowDomObserver } from '@/core/shadow-root'
|
import { shadowDomObserver } from '@/core/shadow-root'
|
||||||
@ -17,6 +17,7 @@ export interface KeyBindingAction {
|
|||||||
run: (context: KeyBindingActionContext) => unknown
|
run: (context: KeyBindingActionContext) => unknown
|
||||||
prevent?: boolean
|
prevent?: boolean
|
||||||
ignoreTyping?: boolean
|
ignoreTyping?: boolean
|
||||||
|
ignoreFocus?: boolean
|
||||||
}
|
}
|
||||||
export interface KeyBinding {
|
export interface KeyBinding {
|
||||||
keys: string[]
|
keys: string[]
|
||||||
@ -43,6 +44,15 @@ export const loadKeyBindings = lodash.once((bindings: KeyBinding[]) => {
|
|||||||
if (binding.action.ignoreTyping !== false && isTyping()) {
|
if (binding.action.ignoreTyping !== false && isTyping()) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 忽略其他可聚焦元素
|
||||||
|
const hasElementFocus = !([document.body, null] as (Element | null)[]).includes(
|
||||||
|
getActiveElement(),
|
||||||
|
)
|
||||||
|
if (binding.action.ignoreFocus !== false && hasElementFocus) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const key = e.key.toLowerCase()
|
const key = e.key.toLowerCase()
|
||||||
|
|
||||||
// 全景视频禁用 WASD 快捷键
|
// 全景视频禁用 WASD 快捷键
|
||||||
|
|||||||
@ -36,7 +36,8 @@ body:not(.preserve-feed-goods) .dyn-goods,
|
|||||||
.desktop-download-tip,
|
.desktop-download-tip,
|
||||||
.adcard,
|
.adcard,
|
||||||
.palette-button-adcard,
|
.palette-button-adcard,
|
||||||
.palette-button-wrap .adcard-content {
|
.palette-button-wrap .adcard-content,
|
||||||
|
.video-card-ad-small {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
.recommend-list .rec-list > :not(.video-page-card) + .video-page-card {
|
.recommend-list .rec-list > :not(.video-page-card) + .video-page-card {
|
||||||
|
|||||||
@ -1,53 +1,87 @@
|
|||||||
import { ComponentEntry } from '@/components/types'
|
import { ComponentEntry } from '@/components/types'
|
||||||
import { defineComponentMetadata } from '@/components/define'
|
import { defineComponentMetadata } from '@/components/define'
|
||||||
|
import type { RawWatchlaterItem } from '@/components/video/watchlater'
|
||||||
|
|
||||||
const entry: ComponentEntry = async ({ settings }) => {
|
const getBvidFromElement = (element: Element) => {
|
||||||
if (settings.options.page) {
|
const pic = element.querySelector('.av-pic, .bili-cover-card') as HTMLAnchorElement
|
||||||
const { select } = await import('@/core/spin-query')
|
const bvid = pic.href.match(/bvid=([^&]+)/)?.[1]
|
||||||
const { childList } = await import('@/core/observer')
|
return bvid
|
||||||
const { getWatchlaterList } = await import('@/components/video/watchlater')
|
}
|
||||||
const list = await getWatchlaterList(true)
|
|
||||||
const listBox = await select('.watch-later-list .list-box > span')
|
const redirect = (element: Element, watchlaterItem: RawWatchlaterItem) => {
|
||||||
if (!listBox) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const redirect = (item: Element, index: number) => {
|
|
||||||
try {
|
try {
|
||||||
const watchlaterItem = list[index]
|
|
||||||
const { bvid, cid, pages } = watchlaterItem
|
const { bvid, cid, pages } = watchlaterItem
|
||||||
const page = pages.find(p => p.cid === cid)?.page ?? 1
|
const page = pages.find(p => p.cid === cid)?.page ?? 1
|
||||||
const url =
|
const url =
|
||||||
page > 1
|
page > 1
|
||||||
? `https://www.bilibili.com/video/${bvid}?p=${page}`
|
? `https://www.bilibili.com/video/${bvid}?p=${page}`
|
||||||
: `https://www.bilibili.com/video/${bvid}`
|
: `https://www.bilibili.com/video/${bvid}`
|
||||||
const pic = item.querySelector('.av-pic') as HTMLAnchorElement
|
const pic = element.querySelector('.av-pic, .bili-cover-card') as HTMLAnchorElement
|
||||||
pic.target = '_blank'
|
pic.target = '_blank'
|
||||||
pic.href = url
|
pic.href = url
|
||||||
const title = item.querySelector('.av-about .t') as HTMLAnchorElement
|
const title = element.querySelector(
|
||||||
|
'.av-about .t, .bili-video-card__title a, .video-card__right .title',
|
||||||
|
) as HTMLAnchorElement
|
||||||
title.target = '_blank'
|
title.target = '_blank'
|
||||||
title.href = url
|
title.href = url
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`[watchlater redirect] error at index ${index}`, item, error)
|
console.error(`[watchlater redirect] error at ${watchlaterItem.bvid}`, element, error)
|
||||||
}
|
|
||||||
}
|
|
||||||
const runRedirect = () => {
|
|
||||||
const avItems = listBox.querySelectorAll('.av-item')
|
|
||||||
avItems.forEach(redirect)
|
|
||||||
}
|
|
||||||
childList(listBox, records => {
|
|
||||||
records.forEach(record => {
|
|
||||||
record.removedNodes.forEach(node => {
|
|
||||||
if (node instanceof HTMLElement && !node.classList.contains('itemlist-move')) {
|
|
||||||
const index = parseInt(dq(node, '.key').textContent) - 1
|
|
||||||
console.log('remove index', index)
|
|
||||||
list.splice(index, 1)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
runRedirect()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const entry: ComponentEntry = async ({ settings }) => {
|
||||||
|
if (!settings.options.page) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const { select } = await import('@/core/spin-query')
|
||||||
|
const { childListSubtree } = await import('@/core/observer')
|
||||||
|
const { getWatchlaterList } = await import('@/components/video/watchlater')
|
||||||
|
const { useScopedConsole } = await import('@/core/utils/log')
|
||||||
|
const console = useScopedConsole('稍后再看重定向')
|
||||||
|
const list: RawWatchlaterItem[] = await getWatchlaterList(true)
|
||||||
|
const listContainer = await select('.watch-later-list .list-box > span, .watchlater-list')
|
||||||
|
if (!listContainer) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const tryRedirect = (element: Element) => {
|
||||||
|
const bvid = getBvidFromElement(element)
|
||||||
|
if (bvid === undefined) {
|
||||||
|
console.warn('bvid not found for', element)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const listItem = list.find(it => it.bvid === bvid)
|
||||||
|
if (listItem === undefined) {
|
||||||
|
console.warn('bvid no match for', bvid)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
redirect(element, listItem)
|
||||||
|
}
|
||||||
|
|
||||||
|
const runRedirect = lodash.debounce(() => {
|
||||||
|
const videoCards = listContainer.querySelectorAll('.av-item, .video-card')
|
||||||
|
console.log('run redirect, length =', videoCards.length)
|
||||||
|
videoCards.forEach(card => {
|
||||||
|
tryRedirect(card)
|
||||||
|
})
|
||||||
|
}, 200)
|
||||||
|
|
||||||
|
runRedirect()
|
||||||
|
childListSubtree(listContainer, async records => {
|
||||||
|
records.forEach(r => {
|
||||||
|
const hasVideoCardChange = [...r.addedNodes].some(
|
||||||
|
node =>
|
||||||
|
node instanceof HTMLElement &&
|
||||||
|
(node.classList.contains('bili-video-card__wrap') ||
|
||||||
|
node.classList.contains('watchlater-list-container')),
|
||||||
|
)
|
||||||
|
if (hasVideoCardChange) {
|
||||||
|
runRedirect()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
export const component = defineComponentMetadata({
|
export const component = defineComponentMetadata({
|
||||||
name: 'watchlaterRedirect',
|
name: 'watchlaterRedirect',
|
||||||
displayName: '稍后再看重定向',
|
displayName: '稍后再看重定向',
|
||||||
@ -62,6 +96,9 @@ export const component = defineComponentMetadata({
|
|||||||
defaultValue: true,
|
defaultValue: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
urlInclude: ['https://www.bilibili.com/watchlater/#/list'],
|
urlInclude: [
|
||||||
|
'https://www.bilibili.com/watchlater/#/list',
|
||||||
|
'https://www.bilibili.com/watchlater/list#/list',
|
||||||
|
],
|
||||||
tags: [componentsTags.utils, componentsTags.video],
|
tags: [componentsTags.utils, componentsTags.video],
|
||||||
})
|
})
|
||||||
|
|||||||
@ -263,7 +263,7 @@ export const addMenuItem = (
|
|||||||
if (isCascader) {
|
if (isCascader) {
|
||||||
;(async () => {
|
;(async () => {
|
||||||
const cascader = await select(() => dq(morePanel, '.bili-cascader'))
|
const cascader = await select(() => dq(morePanel, '.bili-cascader'))
|
||||||
const [observer] = childList(cascader, () => {
|
childList(cascader, (_, observer) => {
|
||||||
const cascaderOptions = dq(cascader, '.bili-cascader-options')
|
const cascaderOptions = dq(cascader, '.bili-cascader-options')
|
||||||
if (cascaderOptions === null) {
|
if (cascaderOptions === null) {
|
||||||
return
|
return
|
||||||
|
|||||||
@ -49,7 +49,7 @@ addData(ListAdaptorKey, (adaptors: FeedsCardsListAdaptor[]) => {
|
|||||||
name: 'space',
|
name: 'space',
|
||||||
match: ['https://space.bilibili.com/'],
|
match: ['https://space.bilibili.com/'],
|
||||||
watchCardsList: async manager => {
|
watchCardsList: async manager => {
|
||||||
const container = (await select('.s-space')) as HTMLDivElement
|
const container = (await select('.s-space, .space-main')) as HTMLDivElement
|
||||||
if (!container) {
|
if (!container) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,9 @@
|
|||||||
@import 'common';
|
@import 'common';
|
||||||
@mixin markdown {
|
@mixin markdown {
|
||||||
line-height: normal;
|
line-height: normal;
|
||||||
|
> * {
|
||||||
|
font-size: inherit;
|
||||||
|
}
|
||||||
h1,
|
h1,
|
||||||
h2,
|
h2,
|
||||||
h3,
|
h3,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user