Format registry folder

This commit is contained in:
the1812 2022-10-12 23:27:58 +08:00
parent 8455bb3f41
commit 56d1f0b0d6
262 changed files with 3114 additions and 3539 deletions

View File

@ -25,8 +25,5 @@ export const component: ComponentMetadata = {
},
entry,
urlInclude: feedsUrls,
tags: [
componentsTags.feeds,
componentsTags.utils,
],
tags: [componentsTags.feeds, componentsTags.utils],
}

View File

@ -18,37 +18,50 @@ const entry = async () => {
addStyle()
const disableDetails = (card: FeedsCard) => {
const { element } = card
element.addEventListener('click', e => {
if (e.ctrlKey || !enabled) {
return
}
const contents = dqa(element, '.content, .bili-dyn-content [data-module="desc"] .bili-rich-text')
const target = e.target as HTMLElement
if (target.hasAttribute('click-title')) {
return
}
if ([
'bili-rich-text__action',
'bili-rich-text-topic',
'bili-rich-text-module',
'bili-rich-text-link',
].some(className => target.classList.contains(className))) {
return
}
const popups = dqa(element, '.im-popup')
if (popups.some(p => p.contains(target))) {
return
}
if (contents.some(c => c === target || c.contains(target))) {
e.stopImmediatePropagation()
}
}, { capture: true })
element.addEventListener(
'click',
e => {
if (e.ctrlKey || !enabled) {
return
}
const contents = dqa(
element,
'.content, .bili-dyn-content [data-module="desc"] .bili-rich-text',
)
const target = e.target as HTMLElement
if (target.hasAttribute('click-title')) {
return
}
if (
[
'bili-rich-text__action',
'bili-rich-text-topic',
'bili-rich-text-module',
'bili-rich-text-link',
].some(className => target.classList.contains(className))
) {
return
}
const popups = dqa(element, '.im-popup')
if (popups.some(p => p.contains(target))) {
return
}
if (contents.some(c => c === target || c.contains(target))) {
e.stopImmediatePropagation()
}
},
{ capture: true },
)
const postContent = dq(element, '.post-content, .bili-dyn-content')
if (!postContent) {
return
}
const hasCardContainer = ['.video-container', '.bangumi-container', '.media-list', '.article-container']
.some(type => dq(postContent, type))
const hasCardContainer = [
'.video-container',
'.bangumi-container',
'.media-list',
'.article-container',
].some(type => dq(postContent, type))
if (hasCardContainer) {
return
}
@ -63,7 +76,7 @@ const entry = async () => {
const details = document.createElement('div')
details.classList.add('details')
details.setAttribute('click-title', '详情')
details.innerHTML = /* html */`
details.innerHTML = /* html */ `
<i class="mdi mdi-chevron-right" click-title></i>
`
contents.insertAdjacentElement('beforeend', details)
@ -76,9 +89,7 @@ const entry = async () => {
export const component: ComponentMetadata = {
name: 'disableFeedsDetails',
displayName: '禁止跳转动态详情',
tags: [
componentsTags.feeds,
],
tags: [componentsTags.feeds],
urlInclude: feedsUrls,
description: {
'zh-CN': '禁止动态点击后跳转详情页, 方便选择其中的文字.',

View File

@ -13,14 +13,17 @@ interface LiveInfo {
}
const entry = async () => {
const { select } = await import('@/core/spin-query')
const liveList = await select('.live-up-list, .bili-dyn-live-users__body') as HTMLElement
const liveList = (await select('.live-up-list, .bili-dyn-live-users__body')) as HTMLElement
if (liveList === null) {
return
}
const pageSize = 24
const { getPages, getJsonWithCredentials } = await import('@/core/ajax')
const fullList: LiveInfo[] = await getPages({
api: page => getJsonWithCredentials(`https://api.live.bilibili.com/relation/v1/feed/feed_list?page=${page}&pagesize=${pageSize}`),
api: page =>
getJsonWithCredentials(
`https://api.live.bilibili.com/relation/v1/feed/feed_list?page=${page}&pagesize=${pageSize}`,
),
getList: json => lodash.get(json, 'data.list', []),
getTotal: json => lodash.get(json, 'data.results', 0),
})
@ -46,7 +49,10 @@ const entry = async () => {
window.open(url, '_blank')
})
}
const face = dq(clone, '.live-up-img, .bili-dyn-live-users__item__face .bili-awesome-img') as HTMLElement
const face = dq(
clone,
'.live-up-img, .bili-dyn-live-users__item__face .bili-awesome-img',
) as HTMLElement
face.style.backgroundImage = `url(${it.face})`
const title = dq(clone, '.live-name, .bili-dyn-live-users__item__title') as HTMLElement
title.innerHTML = it.title
@ -70,11 +76,6 @@ export const component: ComponentMetadata = {
'zh-CN': '在动态的`正在直播`中, 为每一个直播间加上标题, 并且能够显示超过10个的直播间.',
},
entry: styledComponentEntry(() => import('./extend-feeds-live.scss'), entry),
tags: [
componentsTags.feeds,
componentsTags.live,
],
urlInclude: [
/^https:\/\/t\.bilibili\.com\/$/,
],
tags: [componentsTags.feeds, componentsTags.live],
urlInclude: [/^https:\/\/t\.bilibili\.com\/$/],
}

View File

@ -6,12 +6,7 @@
</div>
<h2>类型</h2>
<div class="filter-types">
<FilterTypeSwitch
v-for="[name, type] of allTypes"
:key="type.id"
:name="name"
:type="type"
/>
<FilterTypeSwitch v-for="[name, type] of allTypes" :key="type.id" :name="name" :type="type" />
</div>
<h2>关键词</h2>
<div class="filter-patterns">
@ -45,10 +40,7 @@
@click="toggleBlockSide(id)"
>
<label :class="{ disabled: sideDisabled(id) }">
<span
class="name"
:class="{ disabled: sideDisabled(id) }"
>{{ type.displayName }}</span>
<span class="name" :class="{ disabled: sideDisabled(id) }">{{ type.displayName }}</span>
<VIcon :size="16" class="disabled" icon="mdi-cancel"></VIcon>
<VIcon :size="16" icon="mdi-check"></VIcon>
</label>
@ -62,11 +54,7 @@ import { FeedsCard, FeedsCardType } from '@/components/feeds/api'
import { getComponentSettings } from '@/core/settings'
import { select } from '@/core/spin-query'
import { attributes } from '@/core/observer'
import {
VIcon,
TextBox,
VButton,
} from '@/ui'
import { VIcon, TextBox, VButton } from '@/ui'
import { FeedsFilterOptions } from '.'
import { hasBlockedPattern } from './pattern'
@ -158,14 +146,9 @@ export default Vue.extend({
},
})
if (cardsManager.managerType === 'v1') {
const tab = tabBar.querySelector(
'.tab:nth-child(1) .tab-text',
) as HTMLAnchorElement
const tab = tabBar.querySelector('.tab:nth-child(1) .tab-text') as HTMLAnchorElement
attributes(tab, () => {
document.body.classList.toggle(
'by-type',
!tab.classList.contains('selected'),
)
document.body.classList.toggle('by-type', !tab.classList.contains('selected'))
})
}
if (cardsManager.managerType === 'v2') {
@ -206,9 +189,7 @@ export default Vue.extend({
updateBlockSide() {
Object.entries(sideCards).forEach(([id, type]) => {
const name = sideBlock + type.className
document.body.classList[
this.blockSideCards.includes(id) ? 'add' : 'remove'
](name)
document.body.classList[this.blockSideCards.includes(id) ? 'add' : 'remove'](name)
})
},
toggleBlockSide(id: number) {
@ -231,8 +212,8 @@ export default Vue.extend({
</script>
<style lang="scss">
@import "common";
@import "./blocker";
@import 'common';
@import './blocker';
body.enable-feeds-filter:not(.disable-feeds-filter) {
@include type-block();

View File

@ -11,9 +11,7 @@
<script lang="ts">
import { getComponentSettings } from '@/core/settings'
import {
VIcon,
} from '@/ui'
import { VIcon } from '@/ui'
const { options } = getComponentSettings('feedsFilter')
export default Vue.extend({
@ -48,9 +46,7 @@ export default Vue.extend({
},
methods: {
setFilter(disabled: boolean, updateSettings = true) {
document.body.classList[disabled ? 'add' : 'remove'](
`feeds-filter-block-${this.name}`,
)
document.body.classList[disabled ? 'add' : 'remove'](`feeds-filter-block-${this.name}`)
if (!updateSettings) {
return
}

View File

@ -57,9 +57,7 @@ export const component: ComponentMetadata = {
'zh-CN': '按照类型或者关键词过滤动态首页的内容, 也可以移除动态页的一些侧边卡片.',
},
entry,
tags: [
componentsTags.feeds,
],
tags: [componentsTags.feeds],
options,
reload: () => document.body.classList.remove('disable-feeds-filter'),
unload: () => document.body.classList.add('disable-feeds-filter'),

View File

@ -15,10 +15,7 @@ export interface BlockableCard {
export const hasBlockedPattern = (pattern: string, card: BlockableCard) => {
const upNameMatch = pattern.match(/(.+) up:([^ ]+)/)
if (upNameMatch) {
return (
testPattern(upNameMatch[1], card.text)
&& testPattern(upNameMatch[2], card.username)
)
return testPattern(upNameMatch[1], card.text) && testPattern(upNameMatch[2], card.username)
}
return testPattern(pattern, card.text)
}

View File

@ -14,11 +14,7 @@ const feedField = {
username: ['username', 'repostUsername'],
text: ['text', 'repostText'],
}
const filterableFields = [
bangumiFields,
videoField,
feedField,
]
const filterableFields = [bangumiFields, videoField, feedField]
export const feedsFilterPlugin: PluginMetadata = {
name: 'feeds.contentFilters.patterns',
displayName: '动态关键词过滤',
@ -32,18 +28,24 @@ export const feedsFilterPlugin: PluginMetadata = {
patterns: string[]
}
return items.filter(item => {
const field = filterableFields.find(it => (
const field = filterableFields.find(it =>
Object.values(it).every(fields => {
if (Array.isArray(fields)) {
return fields.some(f => f in item)
}
return fields in item
})
))
}),
)
const card = Object.fromEntries(
Object.entries(field).map(([key, value]) => {
if (Array.isArray(value)) {
return [key, value.map(v => item[v] ?? '').join('\n').trim()]
return [
key,
value
.map(v => item[v] ?? '')
.join('\n')
.trim(),
]
}
return [key, item[value].trim() as string]
}),

View File

@ -19,11 +19,7 @@ export const component: ComponentMetadata = {
description: {
'zh-CN': '强制固定动态主页的顶栏和所有侧栏.',
},
tags: [
componentsTags.feeds,
],
tags: [componentsTags.feeds],
entry,
urlInclude: [
/^https:\/\/t\.bilibili\.com\/$/,
],
urlInclude: [/^https:\/\/t\.bilibili\.com\/$/],
}

View File

@ -83,8 +83,6 @@ export const component: ComponentMetadata = {
'zh-CN': '动态里查看评论区时, 在底部添加一个`收起评论`按钮, 这样就不用再回到上面收起了.',
},
urlInclude: feedsUrlsWithoutDetail,
tags: [
componentsTags.feeds,
],
tags: [componentsTags.feeds],
entry: styledComponentEntry(() => import('./fold-comment.scss'), entry),
}

View File

@ -8,9 +8,6 @@ export const component: ComponentMetadata = {
description: {
'zh-CN': '不管内容多长, 总是完全展开动态的内容.',
},
tags: [
componentsTags.style,
componentsTags.feeds,
],
tags: [componentsTags.style, componentsTags.feeds],
urlInclude: feedsUrlsWithoutDetail,
}

View File

@ -22,11 +22,7 @@
</li>
</ul>
</VPopup>
<DefaultWidget
ref="medalButton"
icon="mdi-medal"
@click="medalOpen = !medalOpen"
>
<DefaultWidget ref="medalButton" icon="mdi-medal" @click="medalOpen = !medalOpen">
<span>更换勋章</span>
</DefaultWidget>
@ -48,11 +44,7 @@
</li>
</ul>
</VPopup>
<DefaultWidget
ref="titleButton"
icon="mdi-script-outline"
@click="titleOpen = !titleOpen"
>
<DefaultWidget ref="titleButton" icon="mdi-script-outline" @click="titleOpen = !titleOpen">
<span>更换头衔</span>
</DefaultWidget>
</div>
@ -61,13 +53,8 @@
<script lang="ts">
import { addComponentListener, getComponentSettings } from '@/core/settings'
import { descendingSort } from '@/core/utils/sort'
import {
DefaultWidget,
VPopup,
} from '@/ui'
import {
Medal, Title, Badge, getMedalList, getTitleList,
} from './badge'
import { DefaultWidget, VPopup } from '@/ui'
import { Medal, Title, Badge, getMedalList, getTitleList } from './badge'
const { options } = getComponentSettings('badgeHelper')
export default Vue.extend({
@ -85,9 +72,13 @@ export default Vue.extend({
}
},
async mounted() {
addComponentListener('badgeHelper.grayEffect', (enable: boolean) => {
this.grayEffect = enable
}, true)
addComponentListener(
'badgeHelper.grayEffect',
(enable: boolean) => {
this.grayEffect = enable
},
true,
)
const init = async () => {
const medal = this.loadMedalList()
await Title.getImageMap()
@ -142,7 +133,7 @@ export default Vue.extend({
</script>
<style lang="scss">
@import "common";
@import 'common';
.badge-popup {
top: 50%;
left: calc(100% + 8px);

View File

@ -1,4 +1,9 @@
import { getJsonWithCredentials, getPages, getTextWithCredentials, postTextWithCredentials } from '@/core/ajax'
import {
getJsonWithCredentials,
getPages,
getTextWithCredentials,
postTextWithCredentials,
} from '@/core/ajax'
import { formData, getCsrf } from '@/core/utils'
import { logError } from '@/core/utils/log'
@ -12,13 +17,16 @@ const validateJson = (json: any, errorMessage: string) => {
}
export abstract class Badge {
constructor(public isActive: boolean = false, public id: number = 0) { }
constructor(public isActive: boolean = false, public id: number = 0) {}
/** @deprecated */
static parseJson<T>(text: string, actions: {
successAction: (json: any) => T,
errorMessage: string,
errorAction: (json: any) => T
}) {
static parseJson<T>(
text: string,
actions: {
successAction: (json: any) => T
errorMessage: string
errorAction: (json: any) => T
},
) {
const json = JSON.parse(text)
if (json.code !== 0) {
logError(`${actions.errorMessage} 错误码:${json.code} ${json.message || ''}`)
@ -37,19 +45,9 @@ export class Medal extends Badge {
isLighted: boolean
constructor(json: any) {
const {
medal: {
medal_id,
level,
medal_name,
wearing_status,
is_lighted,
},
anchor_info: {
nick_name,
},
room_info: {
room_id,
},
medal: { medal_id, level, medal_name, wearing_status, is_lighted },
anchor_info: { nick_name },
room_info: { room_id },
} = json
super(wearing_status === 1, medal_id)
this.level = level
@ -59,20 +57,26 @@ export class Medal extends Badge {
this.isLighted = is_lighted
}
async activate() {
const text = await postTextWithCredentials('https://api.live.bilibili.com/xlive/web-room/v1/fansMedal/wear', formData({
medal_id: this.id,
csrf_token: getCsrf(),
csrf: getCsrf(),
}))
const text = await postTextWithCredentials(
'https://api.live.bilibili.com/xlive/web-room/v1/fansMedal/wear',
formData({
medal_id: this.id,
csrf_token: getCsrf(),
csrf: getCsrf(),
}),
)
const result = validateJson(JSON.parse(text), '佩戴勋章失败.')
this.isActive = true
return result
}
async deactivate() {
const text = await postTextWithCredentials('https://api.live.bilibili.com/xlive/web-room/v1/fansMedal/take_off', formData({
csrf_token: getCsrf(),
csrf: getCsrf(),
}))
const text = await postTextWithCredentials(
'https://api.live.bilibili.com/xlive/web-room/v1/fansMedal/take_off',
formData({
csrf_token: getCsrf(),
csrf: getCsrf(),
}),
)
const result = validateJson(JSON.parse(text), '卸下勋章失败.')
this.isActive = false
return result
@ -80,13 +84,13 @@ export class Medal extends Badge {
}
export const getMedalList = async () => {
const pages = await getPages({
api: page => getJsonWithCredentials(`https://api.live.bilibili.com/xlive/app-ucenter/v1/fansMedal/panel?page=${page}&page_size=50`),
api: page =>
getJsonWithCredentials(
`https://api.live.bilibili.com/xlive/app-ucenter/v1/fansMedal/panel?page=${page}&page_size=50`,
),
getList: json => {
validateJson(json, '无法获取勋章列表.')
return [
...lodash.get(json, 'data.list', []),
...lodash.get(json, 'data.special_list', []),
]
return [...lodash.get(json, 'data.list', []), ...lodash.get(json, 'data.special_list', [])]
},
getTotal: json => lodash.get(json, 'data.total_number', 0),
})
@ -100,9 +104,7 @@ export class Title extends Badge {
source: string
imageUrl: string
constructor(json: any) {
const {
id, cid, wear, css, name, source,
} = json
const { id, cid, wear, css, name, source } = json
super(wear, css)
this.tid = id
this.cid = cid
@ -134,7 +136,10 @@ export class Title extends Badge {
}
async activate() {
return Badge.parseJson(
await postTextWithCredentials('https://api.live.bilibili.com/i/ajaxWearTitle', `id=${this.tid}&cid=${this.cid}&csrf=${getCsrf()}&csrf_token=${getCsrf()}`),
await postTextWithCredentials(
'https://api.live.bilibili.com/i/ajaxWearTitle',
`id=${this.tid}&cid=${this.cid}&csrf=${getCsrf()}&csrf_token=${getCsrf()}`,
),
{
successAction: () => {
this.isActive = true
@ -147,8 +152,10 @@ export class Title extends Badge {
}
async deactivate() {
return Badge.parseJson(
await postTextWithCredentials('https://api.live.bilibili.com/i/ajaxCancelWearTitle',
`csrf=${getCsrf()}&csrf_token=${getCsrf()}`),
await postTextWithCredentials(
'https://api.live.bilibili.com/i/ajaxCancelWearTitle',
`csrf=${getCsrf()}&csrf_token=${getCsrf()}`,
),
{
successAction: () => {
this.isActive = false
@ -160,11 +167,15 @@ export class Title extends Badge {
)
}
}
export const getTitleList = async () => Badge.parseJson(
await getTextWithCredentials('https://api.live.bilibili.com/i/api/ajaxTitleInfo?page=1&pageSize=256&had=1'),
{
successAction: json => lodash.get(json, 'data.list', []).map((it: any) => new Title(it)) as Title[],
errorAction: () => [] as Title[],
errorMessage: '无法获取头衔列表.',
},
)
export const getTitleList = async () =>
Badge.parseJson(
await getTextWithCredentials(
'https://api.live.bilibili.com/i/api/ajaxTitleInfo?page=1&pageSize=256&had=1',
),
{
successAction: json =>
lodash.get(json, 'data.list', []).map((it: any) => new Title(it)) as Title[],
errorAction: () => [] as Title[],
errorMessage: '无法获取头衔列表.',
},
)

View File

@ -6,14 +6,13 @@ export const component = defineComponentMetadata({
name: 'badgeHelper',
displayName: '直播勋章快速更换',
description: {
'zh-CN': '在直播区中, 可从功能面板中直接切换勋章和头衔. 默认显示 256 个 (同时也是上限), 可在选项中修改.',
'zh-CN':
'在直播区中, 可从功能面板中直接切换勋章和头衔. 默认显示 256 个 (同时也是上限), 可在选项中修改.',
},
entry: () => autoMatchMedal(),
reload: none,
unload: none,
tags: [
componentsTags.live,
],
tags: [componentsTags.live],
widget: {
component: () => import('./BadgeHelper.vue').then(m => m.default),
condition: () => Boolean(getUID()),
@ -38,7 +37,5 @@ export const component = defineComponentMetadata({
defaultValue: true,
},
},
urlInclude: [
'//live.bilibili.com',
],
urlInclude: ['//live.bilibili.com'],
})

View File

@ -25,10 +25,14 @@ export default Vue.extend({
}
},
async mounted() {
const originalTextArea = await select(originalTextAreaSelector) as HTMLTextAreaElement
const sendButton = await select(sendButtonSelector) as HTMLButtonElement
const originalTextArea = (await select(originalTextAreaSelector)) as HTMLTextAreaElement
const sendButton = (await select(sendButtonSelector)) as HTMLButtonElement
if (!originalTextArea || !sendButton) {
throw new Error(`[danmakuSendBar] ref elements not found. originalTextArea = ${originalTextArea === null} sendButton = ${sendButton === null}`)
throw new Error(
`[danmakuSendBar] ref elements not found. originalTextArea = ${
originalTextArea === null
} sendButton = ${sendButton === null}`,
)
}
// console.log(originalTextArea, sendButton)
this.originalTextArea = originalTextArea
@ -37,9 +41,7 @@ export default Vue.extend({
originalTextArea.addEventListener('input', this.listenChange)
originalTextArea.addEventListener('change', this.listenChange)
if (!changeEventHook) {
const original = Object.getOwnPropertyDescriptors(
HTMLTextAreaElement.prototype,
).value
const original = Object.getOwnPropertyDescriptors(HTMLTextAreaElement.prototype).value
Object.defineProperty(originalTextArea, 'value', {
...original,
set(value: string) {

View File

@ -30,9 +30,7 @@ const entry = async () => {
export const component = defineComponentMetadata({
name: 'liveDanmakuSendbar',
displayName: '直播弹幕发送栏',
tags: [
componentsTags.live,
],
tags: [componentsTags.live],
description: {
'zh-CN': '在直播的网页全屏和全屏模式状态下, 在底部显示弹幕栏.',
},

View File

@ -1,3 +1,4 @@
export const originalTextAreaSelector = '.control-panel-ctnr .chat-input-ctnr .chat-input'
export const sendButtonSelector = '.control-panel-ctnr .chat-input-ctnr ~ .bottom-actions .bl-button--primary'
export const sendButtonSelector =
'.control-panel-ctnr .chat-input-ctnr ~ .bottom-actions .bl-button--primary'
export const leftControllerSelector = '.left-area'

View File

@ -43,7 +43,12 @@ export default Vue.extend({
return
}
const links: string[] = json.data.list.map((it: { url: string }) => it.url)
Toast.success(links.map(l => `<a class="download-link" target="_blank" href="${l}">${l}</a>`).join('\n'), '下载录像')
Toast.success(
links
.map(l => `<a class="download-link" target="_blank" href="${l}">${l}</a>`)
.join('\n'),
'下载录像',
)
} finally {
this.disabled = false
}

View File

@ -6,14 +6,10 @@ export const component = defineComponentMetadata({
description: {
'zh-CN': '在直播录像页面 `live.bilibili.com/record/` 中添加下载支持.',
},
tags: [
componentsTags.live,
],
tags: [componentsTags.live],
entry: none,
widget: {
component: () => import('./DownloadRecords.vue').then(m => m.default),
},
urlInclude: [
/^https:\/\/live\.bilibili\.com\/record\/(.+)/,
],
urlInclude: [/^https:\/\/live\.bilibili\.com\/record\/(.+)/],
})

View File

@ -46,7 +46,7 @@ let stopObservingMouseLeavePlayer: StopObservingCallback | null = null
interface FullWinToggleCallback {
(
// 标识监听到的动作是启动操作还是关闭操作
isStarted: boolean
isStarted: boolean,
): void
}
@ -75,9 +75,7 @@ function isFullWin(): boolean {
* @param callback
* @returns
*/
function observeFullWinToggle(
onToggle: FullWinToggleCallback,
): StopObservingCallback {
function observeFullWinToggle(onToggle: FullWinToggleCallback): StopObservingCallback {
/**
*
* @param {MutationRecord} mutation body
@ -113,10 +111,7 @@ function observeFullWinToggle(
}
// 将包裹按钮移动到控制条上
function moveGiftPackageToControlBar(
controlBar: Element,
giftBtn0: Element,
) {
function moveGiftPackageToControlBar(controlBar: Element, giftBtn0: Element) {
// console.debug(`[${componentName}] moving gift button to control bar...`)
const rightArea = dq(controlBar, '.right-area')
if (rightArea) {
@ -159,14 +154,9 @@ function onFullWinClose(giftBtn0: Element, originGiftBtnParent: Element) {
}
// 每当全屏模式切换时执行操作
function doOnFullWinToggle(
giftBtn0: Element,
originGiftBtnParent: Element,
): StopObservingCallback {
function doOnFullWinToggle(giftBtn0: Element, originGiftBtnParent: Element): StopObservingCallback {
return observeFullWinToggle(isStarted => {
isStarted
? onFullWinStart(giftBtn0)
: onFullWinClose(giftBtn0, originGiftBtnParent)
isStarted ? onFullWinStart(giftBtn0) : onFullWinClose(giftBtn0, originGiftBtnParent)
})
}
@ -195,7 +185,7 @@ async function reload() {
addStyle(componentStyle, componentName)
const giftBtnParent = await queryGiftBtnParent()
giftBtn = (giftBtnParent?.children[0])
giftBtn = giftBtnParent?.children[0]
if (giftBtnParent && giftBtn) {
stopObservingFullWinToggle = doOnFullWinToggle(giftBtn, giftBtnParent)

View File

@ -6,21 +6,23 @@ const liveHome = /^https:\/\/live\.bilibili\.com\/(index\.html)?$/
export const component = defineComponentMetadata({
name: 'liveHomeMute',
displayName: '直播首页静音',
tags: [
componentsTags.live,
],
tags: [componentsTags.live],
description: {
'zh-CN': '禁止直播首页的推荐直播间自动开始播放.',
},
entry: async ({ metadata }) => {
const styleID = 'hide-home-live'
addComponentListener(`${metadata.name}.hide`, (value: boolean) => {
if (value) {
addStyle('.player-area-ctnr,#player-header { display: none !important }', styleID)
} else {
removeStyle(styleID)
}
}, true)
addComponentListener(
`${metadata.name}.hide`,
(value: boolean) => {
if (value) {
addStyle('.player-area-ctnr,#player-header { display: none !important }', styleID)
} else {
removeStyle(styleID)
}
},
true,
)
},
options: {
hide: {
@ -28,9 +30,7 @@ export const component = defineComponentMetadata({
defaultValue: false,
},
},
urlInclude: [
liveHome,
],
urlInclude: [liveHome],
plugin: {
displayName: '直播首页静音 - 提前执行',
description: {

View File

@ -1,9 +1,6 @@
<template>
<a :href="href" tabindex="-1">
<DefaultWidget
name="返回原版直播间"
icon="mdi-arrow-left-circle-outline"
/>
<DefaultWidget name="返回原版直播间" icon="mdi-arrow-left-circle-outline" />
</a>
</template>
<script lang="ts">

View File

@ -4,7 +4,8 @@ import { matchUrlPattern } from '@/core/utils'
export const component = defineComponentMetadata({
name: 'originalLiveroom',
displayName: '返回原版直播间',
description: '在直播间中提供返回原版直播间的按钮, 原版直播间将无视活动皮肤, 强制使用标准的直播页面.',
description:
'在直播间中提供返回原版直播间的按钮, 原版直播间将无视活动皮肤, 强制使用标准的直播页面.',
tags: [componentsTags.live],
entry: none,
urlInclude: [

View File

@ -5,10 +5,7 @@ import { liveUrls } from '@/core/utils/urls'
export const component = defineComponentMetadata({
...toggleStyle('removeLiveWatermark', () => import('./remove-watermark.scss')),
displayName: '删除直播水印',
tags: [
componentsTags.live,
componentsTags.style,
],
tags: [componentsTags.live, componentsTags.style],
description: {
'zh-CN': '删除观看直播时角落的水印.',
},

View File

@ -5,13 +5,16 @@ const id = 'dpi-live-showgirl'
const entry = async () => {
const { addStyle } = await import('@/core/style')
if (document.getElementById(id) === null) {
addStyle(`
addStyle(
`
.haruna-ctnr,
.avatar-btn
{
transform: scale(${1 / window.devicePixelRatio}) !important;
}
`, id)
`,
id,
)
}
}
export const component = defineComponentMetadata({
@ -21,10 +24,7 @@ export const component = defineComponentMetadata({
description: {
'zh-CN': '根据屏幕 DPI 缩放直播看板娘的大小, 避免像素锯齿.',
},
tags: [
componentsTags.live,
componentsTags.style,
],
tags: [componentsTags.live, componentsTags.style],
entry,
reload: entry,
unload: () => {

View File

@ -12,9 +12,6 @@ export const component = defineComponentMetadata({
],
displayName: '自动收起直播侧栏',
description: '自动收起直播间右边偏下的侧栏. (上面有个 "关注" 的面板)',
tags: [
componentsTags.live,
componentsTags.style,
],
tags: [componentsTags.live, componentsTags.style],
urlInclude: liveUrls,
})

View File

@ -5,9 +5,13 @@ import { getNumberValidator } from '@/core/utils'
export const component = defineComponentMetadata({
name: 'autoHideSidebar',
entry: () => {
addComponentListener('autoHideSidebar.triggerWidth', (value: number) => {
document.documentElement.style.setProperty('--auto-hide-sidebar-width', `${value}px`)
}, true)
addComponentListener(
'autoHideSidebar.triggerWidth',
(value: number) => {
document.documentElement.style.setProperty('--auto-hide-sidebar-width', `${value}px`)
},
true,
)
},
displayName: '自动隐藏侧栏',
instantStyles: [
@ -26,6 +30,7 @@ export const component = defineComponentMetadata({
},
},
description: {
'zh-CN': '自动隐藏脚本的侧栏 (功能和设置图标). 设置面板停靠在右侧时不建议使用, 因为网页的滚动条会占用右边缘的触发区域.',
'zh-CN':
'自动隐藏脚本的侧栏 (功能和设置图标). 设置面板停靠在右侧时不建议使用, 因为网页的滚动条会占用右边缘的触发区域.',
},
})

View File

@ -2,11 +2,7 @@
<div class="custom-navbar" :class="styles" role="navigation">
<div class="left-pad padding"></div>
<div class="custom-navbar-items" role="list">
<NavbarItem
v-for="item of items"
:key="item.name"
:item="item"
></NavbarItem>
<NavbarItem v-for="item of items" :key="item.name" :item="item"></NavbarItem>
</div>
<div class="right-pad padding"></div>
</div>
@ -63,9 +59,13 @@ export default Vue.extend({
},
},
async mounted() {
addComponentListener('customNavbar.height', (value: number) => {
document.documentElement.style.setProperty('--navbar-height', `${value}px`)
}, true)
addComponentListener(
'customNavbar.height',
(value: number) => {
document.documentElement.style.setProperty('--navbar-height', `${value}px`)
},
true,
)
await checkTransparentFill(this)
},
methods: {
@ -214,12 +214,7 @@ body.fixed-navbar {
left: 0;
width: 100%;
height: calc(2 * var(--navbar-height));
background-image: linear-gradient(
to bottom,
#000a 0,
#0004 65%,
transparent 100%
);
background-image: linear-gradient(to bottom, #000a 0, #0004 65%, transparent 100%);
pointer-events: none;
}
}

View File

@ -111,7 +111,10 @@ export default Vue.extend({
if (!popup) {
return
}
const allowRefresh = CustomNavbarItem.navbarOptions.refreshOnPopup && popup.popupRefresh && typeof popup.popupRefresh === 'function'
const allowRefresh =
CustomNavbarItem.navbarOptions.refreshOnPopup &&
popup.popupRefresh &&
typeof popup.popupRefresh === 'function'
if (!initialPopup && allowRefresh) {
popup.popupRefresh()
}

View File

@ -1,9 +1,5 @@
<template>
<a
v-bind="$attrs"
:target="newTab ? '_blank' : null"
v-on="$listeners"
>
<a v-bind="$attrs" :target="newTab ? '_blank' : null" v-on="$listeners">
<slot />
</a>
</template>

View File

@ -4,19 +4,9 @@ import { ranking } from './ranking/ranking'
import { userInfo } from './user-info/user-info'
import { logo } from './logo/logo'
import { home } from './home/home'
import {
gamesIframe,
livesIframe,
mangaIframe,
} from './iframe/iframe'
import { gamesIframe, livesIframe, mangaIframe } from './iframe/iframe'
import { blanks } from './flexible-blank/flexible-blank'
import {
bangumi,
music,
drawing,
shop,
match,
} from './simple-links/simple-links'
import { bangumi, music, drawing, shop, match } from './simple-links/simple-links'
import { upload } from './upload/upload'
import { search } from './search/search'
import { feeds } from './feeds/feeds'

View File

@ -83,9 +83,13 @@ export class CustomNavbarItem implements Required<CustomNavbarItemInit> {
throw new Error('Missing CustomNavbarItem content')
}
addComponentListener('customNavbar.touch', (value: boolean) => {
this.touch = value ? init.touch : false
}, true)
addComponentListener(
'customNavbar.touch',
(value: boolean) => {
this.touch = value ? init.touch : false
},
true,
)
this.hidden = CustomNavbarItem.navbarOptions.hidden.includes(this.name)
const orderMap = CustomNavbarItem.navbarOptions.order
this.order = orderMap[this.name] || 0

View File

@ -1,47 +1,46 @@
import { ComponentEntry } from '@/components/types'
import { addComponentListener } from '@/core/settings'
import {
isIframe,
isNotHtml,
matchUrlPattern,
mountVueComponent,
} from '@/core/utils'
import { isIframe, isNotHtml, matchUrlPattern, mountVueComponent } from '@/core/utils'
export const entry: ComponentEntry = async ({ metadata: { name } }) => {
// const url = document.URL.replace(location.search, '')
// const isHome = url === 'https://www.bilibili.com/' || url === 'https://www.bilibili.com/index.html'
if (
isIframe()
isIframe() ||
// (getComponentSettings('bilibiliSimpleNewHomeCompatible').enabled && isHome) ||
|| isNotHtml()
isNotHtml()
) {
return
}
addComponentListener(`${name}.padding`, value => {
document.documentElement.style.setProperty('--navbar-bounds-padding', `${value}%`)
}, true)
addComponentListener(
`${name}.padding`,
value => {
document.documentElement.style.setProperty('--navbar-bounds-padding', `${value}%`)
},
true,
)
const globalFixedExclude = [
'https://space.bilibili.com',
'https://www.bilibili.com/read',
'https://www.bilibili.com/account/history',
]
if (!globalFixedExclude.some(p => matchUrlPattern(p))) {
addComponentListener(`${name}.globalFixed`, value => {
document.body.classList.toggle('fixed-navbar', value)
}, true)
addComponentListener(
`${name}.globalFixed`,
value => {
document.body.classList.toggle('fixed-navbar', value)
},
true,
)
}
const CustomNavbar = await import('./CustomNavbar.vue')
const customNavbar: Vue & {
styles: string[]
toggleStyle: (value: boolean, style: string) => void
} = mountVueComponent(CustomNavbar)
document.body.insertAdjacentElement('beforeend', customNavbar.$el);
['fill', 'shadow', 'blur'].forEach(style => {
addComponentListener(
`${name}.${style}`,
value => customNavbar.toggleStyle(value, style),
true,
)
document.body.insertAdjacentElement('beforeend', customNavbar.$el)
;['fill', 'shadow', 'blur'].forEach(style => {
addComponentListener(`${name}.${style}`, value => customNavbar.toggleStyle(value, style), true)
})
}

View File

@ -13,9 +13,7 @@
</VDropdown>
</template>
<script lang="ts">
import {
VDropdown,
} from '@/ui'
import { VDropdown } from '@/ui'
import { getUID } from '@/core/utils'
import { getJsonWithCredentials } from '@/core/ajax'
import { getComponentSettings } from '@/core/settings'
@ -51,17 +49,14 @@ export default Vue.extend({
if (json.code !== 0) {
throw new Error(`获取收藏夹列表失败: ${json.message}`)
}
this.folders = lodash.get(json, 'data.list', []).map((item: {
id: number
title: string
media_count: number
}) => (
{
id: item.id,
name: item.title,
count: item.media_count,
} as FavoritesFolder
))
this.folders = lodash.get(json, 'data.list', []).map(
(item: { id: number; title: string; media_count: number }) =>
({
id: item.id,
name: item.title,
count: item.media_count,
} as FavoritesFolder),
)
if (this.folders.length > 0 && this.folder.id === notSelectedFolder.id) {
const { lastFavoriteFolder } = navbarOptions
const folder = this.folders.find((f: FavoritesFolder) => f.id === lastFavoriteFolder)

View File

@ -39,7 +39,8 @@
target="_blank"
:href="'https://www.bilibili.com/video/' + card.bvid"
:title="card.title"
>{{ card.title }}</a>
>{{ card.title }}</a
>
<a
v-if="card.upID"
class="up"
@ -47,18 +48,10 @@
:href="'https://space.bilibili.com/' + card.upID"
:title="card.upName"
>
<DpiImage
placeholder-image
class="face"
:src="card.upFaceUrl"
:size="20"
></DpiImage>
<DpiImage placeholder-image class="face" :src="card.upFaceUrl" :size="20"></DpiImage>
<div class="name">{{ card.upName }}</div>
</a>
<div
v-else
class="description"
>
<div v-else class="description">
{{ card.description }}
</div>
</div>
@ -72,15 +65,7 @@
</div>
</template>
<script lang="ts">
import {
VLoading,
VEmpty,
VIcon,
VButton,
TextBox,
DpiImage,
ScrollTrigger,
} from '@/ui'
import { VLoading, VEmpty, VIcon, VButton, TextBox, DpiImage, ScrollTrigger } from '@/ui'
import { formatDate, formatDuration } from '@/core/utils/formatters'
import { getUID } from '@/core/utils'
import { getJsonWithCredentials } from '@/core/ajax'
@ -131,8 +116,12 @@ async function searchAllList() {
}
try {
this.loading = true
const jsonCurrent = await getJsonWithCredentials(`https://api.bilibili.com/x/v3/fav/resource/list?media_id=${this.folder.id}&pn=${this.searchPage}&ps=${MaxPageSize}&keyword=${this.search}&order=mtime&type=0&tid=0&platform=web`)
const jsonAll = await getJsonWithCredentials(`https://api.bilibili.com/x/v3/fav/resource/list?media_id=${this.folder.id}&pn=${this.searchPage}&ps=${MaxPageSize}&keyword=${this.search}&order=mtime&type=1&tid=0&platform=web`)
const jsonCurrent = await getJsonWithCredentials(
`https://api.bilibili.com/x/v3/fav/resource/list?media_id=${this.folder.id}&pn=${this.searchPage}&ps=${MaxPageSize}&keyword=${this.search}&order=mtime&type=0&tid=0&platform=web`,
)
const jsonAll = await getJsonWithCredentials(
`https://api.bilibili.com/x/v3/fav/resource/list?media_id=${this.folder.id}&pn=${this.searchPage}&ps=${MaxPageSize}&keyword=${this.search}&order=mtime&type=1&tid=0&platform=web`,
)
if (jsonCurrent.code !== 0 && jsonAll.code !== 0) {
return
}
@ -222,8 +211,7 @@ export default Vue.extend({
this.hasMoreSearchPage = true
this.searchPage = 1
this.filteredCards = (this.cards as FavoritesItemInfo[]).filter(
it => it.title.toLowerCase().includes(keyword)
|| it.upName.toLowerCase().includes(keyword),
it => it.title.toLowerCase().includes(keyword) || it.upName.toLowerCase().includes(keyword),
)
},
},
@ -238,9 +226,7 @@ export default Vue.extend({
//
return []
}
return json.data.medias
.filter(favoriteItemFilter)
.map(favoriteItemMapper)
return json.data.medias.filter(favoriteItemFilter).map(favoriteItemMapper)
},
async changeList() {
if (this.folder.id === 0) {
@ -284,8 +270,8 @@ export default Vue.extend({
})
</script>
<style lang="scss">
@import "common";
@import "../popup";
@import 'common';
@import '../popup';
.custom-navbar .favorites-list {
width: 380px;

View File

@ -1,10 +1,6 @@
<template>
<div class="navbar-feeds">
<TabControl
ref="tabControl"
:tabs="tabs"
more-link="https://t.bilibili.com/"
>
<TabControl ref="tabControl" :tabs="tabs" more-link="https://t.bilibili.com/">
<template #more-link>
所有动态
<VIcon icon="feeds" :size="18"></VIcon>
@ -13,10 +9,7 @@
</div>
</template>
<script lang="ts">
import {
TabControl,
VIcon,
} from '@/ui'
import { TabControl, VIcon } from '@/ui'
import { feedsCardTypes } from '@/components/feeds/api'
import { getNotifyCount } from '@/components/feeds/notify'
import { popperMixin } from '../mixins'
@ -61,7 +54,7 @@ export default Vue.extend({
})
</script>
<style lang="scss">
@import "../popup";
@import '../popup';
.navbar-feeds {
width: 380px;

View File

@ -3,13 +3,7 @@
<VLoading v-if="loading"></VLoading>
<VEmpty v-else-if="!loading && cards.length === 0"></VEmpty>
<transition-group name="cards" tag="div" class="live-feeds-content">
<a
v-for="c of cards"
:key="c.id"
class="live-card"
target="_blank"
:href="c.url"
>
<a v-for="c of cards" :key="c.id" class="live-card" target="_blank" :href="c.url">
<div class="face-container">
<DpiImage class="face" :size="48" :src="c.upFaceUrl"></DpiImage>
</div>
@ -22,11 +16,7 @@
</div>
</template>
<script lang="ts">
import {
VLoading,
VEmpty,
DpiImage,
} from '@/ui'
import { VLoading, VEmpty, DpiImage } from '@/ui'
import { responsiveGetPages, getJsonWithCredentials } from '@/core/ajax'
import { LiveFeedItem } from './live-feed-item'
@ -57,9 +47,10 @@ export default Vue.extend({
},
async created() {
const [responsive] = responsiveGetPages({
api: page => getJsonWithCredentials(
`https://api.live.bilibili.com/relation/v1/feed/feed_list?page=${page}&pagesize=24`,
),
api: page =>
getJsonWithCredentials(
`https://api.live.bilibili.com/relation/v1/feed/feed_list?page=${page}&pagesize=24`,
),
getList: json => lodash.get(json, 'data.list', []),
getTotal: json => lodash.get(json, 'data.results', 0),
})
@ -69,7 +60,7 @@ export default Vue.extend({
})
</script>
<style lang="scss">
@import "common";
@import 'common';
.live-feeds {
width: 100%;
@include v-center();
@ -132,7 +123,7 @@ export default Vue.extend({
color: var(--theme-color);
}
.live-name {
opacity: .75;
opacity: 0.75;
padding: 0 12px;
@include single-line();
line-height: normal;

View File

@ -2,7 +2,8 @@
*
* ()
*/
export const getBangumiFeedsMockup = async () => JSON.parse(`{
export const getBangumiFeedsMockup = async () =>
JSON.parse(`{
"code": 0,
"msg": "",
"message": "",

View File

@ -7,11 +7,7 @@ import {
import { descendingStringSort } from '@/core/utils/sort'
import { logError } from '@/core/utils/log'
import { setLatestID } from '@/components/feeds/notify'
import {
VLoading,
VEmpty,
ScrollTrigger,
} from '@/ui'
import { VLoading, VEmpty, ScrollTrigger } from '@/ui'
/**
* Vue Mixin
@ -21,7 +17,8 @@ import {
export const nextPageMixin = <MappedItem extends { id: string }, RawItem>(
type: FeedsCardType,
jsonMapper: (obj: RawItem) => MappedItem,
) => (Vue.extend({
) =>
Vue.extend({
components: {
VLoading,
VEmpty,
@ -44,7 +41,7 @@ export const nextPageMixin = <MappedItem extends { id: string }, RawItem>(
const cards = this.sortedCards as MappedItem[]
if (cards.length > 0) {
setLatestID(cards[0].id)
// console.log('setLatestID', cards[0].id)
// console.log('setLatestID', cards[0].id)
}
},
methods: {
@ -77,7 +74,8 @@ export const nextPageMixin = <MappedItem extends { id: string }, RawItem>(
this.hasMorePage = false
return
}
this.hasMorePage = lastCardID === 0 ? true : Boolean(lodash.get(json, 'data.has_more', true))
this.hasMorePage =
lastCardID === 0 ? true : Boolean(lodash.get(json, 'data.has_more', true))
} catch (error) {
logError(error)
} finally {
@ -85,4 +83,4 @@ export const nextPageMixin = <MappedItem extends { id: string }, RawItem>(
}
},
},
}))
})

View File

@ -6,10 +6,7 @@
<TextBox v-model="search" placeholder="搜索" linear></TextBox>
</div>
<div class="operations">
<div
class="operation"
@click="toggleHistoryPause"
>
<div class="operation" @click="toggleHistoryPause">
<VButton v-if="!paused" title="暂停记录历史" round>
<VIcon icon="mdi-pause" :size="14"></VIcon>
</VButton>
@ -17,11 +14,7 @@
<VIcon icon="mdi-play" :size="14"></VIcon>
</VButton>
</div>
<a
class="operation"
target="_blank"
href="https://www.bilibili.com/account/history"
>
<a class="operation" target="_blank" href="https://www.bilibili.com/account/history">
<VButton title="查看更多" round>
<VIcon icon="mdi-dots-horizontal" :size="18"></VIcon>
</VButton>
@ -29,9 +22,7 @@
</div>
</div>
<div class="header-row">
<div class="row-title">
过滤:
</div>
<div class="row-title">过滤:</div>
<div class="type-filters">
<div v-for="t of types" :key="t.name" class="type-filter">
<VButton
@ -55,11 +46,7 @@
<div class="time-group-name">
{{ g.name }}
</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">
<a class="cover-container" target="_blank" :href="h.url">
<DpiImage
@ -73,26 +60,21 @@
class="progress"
:style="{ width: h.progress * 100 + '%' }"
></div>
<div
v-if="h.progressText"
class="floating progress-number"
>{{ h.progress >= 1 ? '已看完' : h.progressText }}</div>
<div v-if="h.progressText" class="floating progress-number">
{{ h.progress >= 1 ? '已看完' : h.progressText }}
</div>
<div
v-if="h.liveStatus !== undefined"
class="floating duration live-status"
:class="{ on: h.liveStatus === 1 }"
>{{ h.liveStatus === 1 ? '直播中': '未开播' }}</div>
<div
v-if="h.durationText"
class="floating duration"
>{{ h.durationText }}</div>
>
{{ h.liveStatus === 1 ? '直播中' : '未开播' }}
</div>
<div v-if="h.durationText" class="floating duration">{{ h.durationText }}</div>
</a>
<a
class="title"
target="_blank"
:href="h.url"
:title="h.title"
>{{ h.title || h.upName + '的直播间' }}</a>
<a class="title" target="_blank" :href="h.url" :title="h.title">{{
h.title || h.upName + '的直播间'
}}</a>
<a
class="up"
target="_blank"
@ -107,11 +89,7 @@
></DpiImage>
<div class="up-name">{{ h.upName }}</div>
</a>
<div
v-if="h.timeText"
class="time"
:title="new Date(h.viewAt).toLocaleString()"
>
<div v-if="h.timeText" class="time" :title="new Date(h.viewAt).toLocaleString()">
{{ h.timeText }}
</div>
</div>
@ -130,19 +108,9 @@
import { bilibiliApi, getJsonWithCredentials, postTextWithCredentials } from '@/core/ajax'
import { formData, getCsrf } from '@/core/utils'
import { descendingSort } from '@/core/utils/sort'
import {
VButton,
VIcon,
TextBox,
VLoading,
VEmpty,
ScrollTrigger,
DpiImage,
} from '@/ui'
import { VButton, VIcon, TextBox, VLoading, VEmpty, ScrollTrigger, DpiImage } from '@/ui'
import { popperMixin } from '../mixins'
import {
types, TypeFilter, HistoryItem, getHistoryItems, group,
} from './types'
import { types, TypeFilter, HistoryItem, getHistoryItems, group } from './types'
export default Vue.extend({
components: {
@ -170,10 +138,10 @@ export default Vue.extend({
computed: {
canNextPage() {
return (
this.search === ''
&& !this.loading
&& this.hasMorePage
&& this.types.every((t: TypeFilter) => t.checked)
this.search === '' &&
!this.loading &&
this.hasMorePage &&
this.types.every((t: TypeFilter) => t.checked)
)
},
},
@ -184,10 +152,7 @@ export default Vue.extend({
},
async created() {
try {
await Promise.all([
this.nextPage(),
this.updateHistoryPauseState(),
])
await Promise.all([this.nextPage(), this.updateHistoryPauseState()])
} finally {
this.loading = false
}
@ -202,8 +167,8 @@ export default Vue.extend({
return false
}
if (
!item.title.toLowerCase().includes(this.search.toLowerCase())
&& !item.upName.toLowerCase().includes(this.search.toLowerCase())
!item.title.toLowerCase().includes(this.search.toLowerCase()) &&
!item.upName.toLowerCase().includes(this.search.toLowerCase())
) {
return false
}
@ -215,9 +180,7 @@ export default Vue.extend({
async nextPage() {
const items = await getHistoryItems(this.viewTime)
const cards: HistoryItem[] = lodash.uniqBy(
this.cards
.concat(items)
.sort(descendingSort((item: HistoryItem) => item.viewAt)),
this.cards.concat(items).sort(descendingSort((item: HistoryItem) => item.viewAt)),
item => item.id,
)
this.cards = cards
@ -228,7 +191,9 @@ export default Vue.extend({
this.hasMorePage = cards.length !== 0
},
async updateHistoryPauseState() {
const result = await bilibiliApi(getJsonWithCredentials('https://api.bilibili.com/x/v2/history/shadow'))
const result = await bilibiliApi(
getJsonWithCredentials('https://api.bilibili.com/x/v2/history/shadow'),
)
/*
result == true: 暂停
result == {}: 没暂停
@ -254,8 +219,8 @@ export default Vue.extend({
})
</script>
<style lang="scss">
@import "common";
@import "../popup";
@import 'common';
@import '../popup';
.custom-navbar-history-list {
width: 350px;

View File

@ -95,9 +95,18 @@ const formatTime = (date: Date) => {
const { yesterday } = getTimeData()
const timestamp = Number(date)
if (timestamp >= yesterday) {
return `${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`
return `${date.getHours().toString().padStart(2, '0')}:${date
.getMinutes()
.toString()
.padStart(2, '0')}`
}
return `${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')} ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`
return `${(date.getMonth() + 1).toString().padStart(2, '0')}-${date
.getDate()
.toString()
.padStart(2, '0')} ${date.getHours().toString().padStart(2, '0')}:${date
.getMinutes()
.toString()
.padStart(2, '0')}`
}
const parseHistoryItem = (item: any): HistoryItem => {
if (item.history.business === 'article') {
@ -110,7 +119,7 @@ const parseHistoryItem = (item: any): HistoryItem => {
oid, // 直播 房间号 / 专栏 cv 号
} = item.history
const progressParam = item.progress > 0 ? `t=${item.progress}` : 't=0'
const progress = item.progress === -1 ? 1 : (item.progress / item.duration)
const progress = item.progress === -1 ? 1 : item.progress / item.duration
const https = (url: string) => url.replace('http:', 'https:')
const time = new Date(item.view_at * 1000)
const cover = (() => {

View File

@ -9,10 +9,7 @@
>
<a :href="data.link" target="_blank">
<svg aria-hidden="true">
<use
:href="'#header-icon-' + data.icon"
:xlink:href="'#header-icon-' + data.icon"
/>
<use :href="'#header-icon-' + data.icon" :xlink:href="'#header-icon-' + data.icon" />
</svg>
<div class="name">{{ name }}</div>
<span class="count">
@ -26,7 +23,8 @@
class="sub-region"
:href="url"
target="_blank"
>{{ regionName }}</a>
>{{ regionName }}</a
>
</div>
</div>
</div>
@ -94,8 +92,8 @@ export default Vue.extend({
// 3. https://stackoverflow.com/a/33899301/13860169
flex-direction: row;
writing-mode: vertical-lr;
&>* {
writing-mode: horizontal-tb
& > * {
writing-mode: horizontal-tb;
}
.category-item {

View File

@ -1,10 +1,5 @@
<template>
<iframe
:src="item.src"
frameborder="0"
:width="item.width"
:height="item.height"
></iframe>
<iframe :src="item.src" frameborder="0" :width="item.width" :height="item.height"></iframe>
</template>
<script lang="ts">

View File

@ -1,4 +1,8 @@
import { defineComponentMetadata, defineOptionsMetadata, OptionsOfMetadata } from '@/components/define'
import {
defineComponentMetadata,
defineOptionsMetadata,
OptionsOfMetadata,
} from '@/components/define'
import { LaunchBarActionProvider } from '@/components/launch-bar/launch-bar-action'
import { urlInclude, urlExclude } from './urls'
import { entry } from './entry'
@ -77,10 +81,7 @@ export const component = defineComponentMetadata({
name: 'customNavbar',
displayName: '自定义顶栏',
entry,
tags: [
componentsTags.style,
componentsTags.general,
],
tags: [componentsTags.style, componentsTags.general],
options,
urlInclude,
urlExclude,
@ -110,15 +111,17 @@ export const component = defineComponentMetadata({
addData('launchBar.actions', (providers: LaunchBarActionProvider[]) => {
providers.push({
name: 'navbarSettings',
getActions: async () => [{
name: '自定义顶栏设置',
description: 'Custom Navbar Settings',
icon: 'mdi-sort',
action: async () => {
const { toggleNavbarSettings } = await import('./settings/vm')
toggleNavbarSettings()
getActions: async () => [
{
name: '自定义顶栏设置',
description: 'Custom Navbar Settings',
icon: 'mdi-sort',
action: async () => {
const { toggleNavbarSettings } = await import('./settings/vm')
toggleNavbarSettings()
},
},
}],
],
})
})
},

View File

@ -37,17 +37,12 @@ export default Vue.extend({
this.seasonLogoUrl = ''
return
}
const json = await getJson(
'https://api.bilibili.com/x/web-show/page/header?resource_id=1',
)
const json = await getJson('https://api.bilibili.com/x/web-show/page/header?resource_id=1')
if (json.code !== 0) {
this.seasonLogoUrl = ''
return
}
this.seasonLogoUrl = lodash.get(json, 'data.litpic', '').replace(
'http:',
'https:',
)
this.seasonLogoUrl = lodash.get(json, 'data.litpic', '').replace('http:', 'https:')
},
true,
)

View File

@ -7,7 +7,8 @@
:href="e.href"
:data-count="e.count || null"
@click="clearCount(e)"
>{{ e.name }}</a>
>{{ e.name }}</a
>
</div>
</div>
</template>
@ -99,9 +100,7 @@ export default Vue.extend({
return
}
const [mainJson, messageJson] = await Promise.all([
getJsonWithCredentials(
'https://api.bilibili.com/x/msgfeed/unread',
),
getJsonWithCredentials('https://api.bilibili.com/x/msgfeed/unread'),
getJsonWithCredentials(
'https://api.vc.bilibili.com/session_svr/v1/session_svr/single_unread',
),

View File

@ -1,10 +1,7 @@
<template>
<div class="ranking-popup" role="list">
<div v-for="e of entries" :key="e.name" class="ranking-entry" role="listitem">
<a
target="_blank"
:href="e.href"
>{{ e.name }}</a>
<a target="_blank" :href="e.href">{{ e.name }}</a>
</div>
</div>
</template>

View File

@ -17,7 +17,7 @@ export default Vue.extend({
// transparent mode / no fill
.launch-bar {
--color: var(--custom-navbar-foreground);
background-color: #000A;
background-color: #000a;
opacity: 0.5;
transition: opacity 0.2s ease-out;
padding: 2px 6px;

View File

@ -13,11 +13,7 @@
<script lang="ts">
import { getUID } from '@/core/utils'
import { VIcon, VButton } from '@/ui'
import {
setTriggerElement,
loadNavbarSettings,
toggleNavbarSettings,
} from './vm'
import { setTriggerElement, loadNavbarSettings, toggleNavbarSettings } from './vm'
export default Vue.extend({
components: {

View File

@ -9,9 +9,7 @@
>
<div class="navbar-settings-header">
<VIcon class="title-icon" icon="mdi-sort" :size="24"></VIcon>
<div class="title">
顶栏布局设置
</div>
<div class="title">顶栏布局设置</div>
<div class="grow"></div>
<div class="close" @click="open = false">
<VIcon icon="close" :size="18"></VIcon>
@ -19,9 +17,7 @@
</div>
<div class="navbar-settings-content">
<div class="navbar-settings-section">
<div class="navbar-settings-section-title">
边缘间距
</div>
<div class="navbar-settings-section-title">边缘间距</div>
<div class="navbar-settings-section-description">
设定两侧边缘处的间距, 单位为百分比, 100%为整个顶栏的宽度.
<br />空间不足时, 实际呈现的间距会自动缩小.
@ -32,18 +28,12 @@
@mouseout="peekPadding(false)"
>
<VSlider v-model="padding" :min="0" :max="40" :step="0.5"></VSlider>
<div class="padding-value">
{{ padding.toFixed(1) }}%
</div>
<div class="padding-value">{{ padding.toFixed(1) }}%</div>
</div>
</div>
<div class="navbar-settings-section">
<div class="navbar-settings-section-title">
元素呈现
</div>
<div
class="navbar-settings-section-description"
>
<div class="navbar-settings-section-title">元素呈现</div>
<div class="navbar-settings-section-description">
按住并拖动可以调整顺序, 点击眼睛图标可以切换隐藏/显示.
</div>
<VLoading v-if="!loaded" />
@ -67,11 +57,7 @@
<div class="toggle-visible">
<VIcon
:size="18"
:icon="
item.hidden
? 'mdi-eye-off-outline'
: 'mdi-eye-outline'
"
:icon="item.hidden ? 'mdi-eye-off-outline' : 'mdi-eye-outline'"
@click="toggleVisible(item)"
></VIcon>
</div>
@ -83,26 +69,20 @@
</template>
<script lang="ts">
import { SortableEvent } from 'sortablejs'
import {
VPopup,
VIcon,
VSlider,
VLoading,
} from '@/ui'
import { VPopup, VIcon, VSlider, VLoading } from '@/ui'
import { addComponentListener } from '@/core/settings'
import { dqa } from '@/core/utils'
import { SortableJSLibrary } from '@/core/runtime-library'
import { getData } from '@/plugins/data'
import {
CustomNavbarItem,
CustomNavbarRenderedItems,
} from '../custom-navbar-item'
import { CustomNavbarItem, CustomNavbarRenderedItems } from '../custom-navbar-item'
import { checkSequentialOrder, sortItems } from './orders'
const { navbarOptions } = CustomNavbarItem
const [rendered] = getData(CustomNavbarRenderedItems) as [{
items: CustomNavbarItem[]
}]
const [rendered] = getData(CustomNavbarRenderedItems) as [
{
items: CustomNavbarItem[]
},
]
export default Vue.extend({
components: {
VPopup,
@ -166,9 +146,9 @@ export default Vue.extend({
const container = this.$refs.navbarSortList as HTMLElement
const element = e.item
console.log(`${element.getAttribute('data-name')} ${e.oldIndex}->${e.newIndex}`)
const ordersMap = Object.fromEntries([...container.children].map((el, index) => (
[el.getAttribute('data-name') as string, index]
)))
const ordersMap = Object.fromEntries(
[...container.children].map((el, index) => [el.getAttribute('data-name') as string, index]),
)
this.rendered.items = sortItems(rendered.items, ordersMap)
},
toggleVisible(item: CustomNavbarItem) {
@ -186,7 +166,7 @@ export default Vue.extend({
})
</script>
<style lang="scss">
@import "common";
@import 'common';
.custom-navbar-settings {
@include popup();
width: 400px;

View File

@ -7,7 +7,7 @@ const regenerateOrder = (items: CustomNavbarItem[]) => {
}
item.order = index
})
const orderMap = Object.fromEntries(items.map(it => ([it.name, it.order])))
const orderMap = Object.fromEntries(items.map(it => [it.name, it.order]))
CustomNavbarItem.navbarOptions.order = orderMap
}
export const checkSequentialOrder = (items: CustomNavbarItem[]) => {

View File

@ -38,7 +38,7 @@ export default Vue.extend({
})
</script>
<style lang="scss">
@import "../popup";
@import '../popup';
.navbar-subscriptions {
width: 380px;

View File

@ -17,27 +17,18 @@
<div class="card-info">
<h1 class="title" :title="card.title">{{ card.title }}</h1>
<div class="progress-row">
<div
v-if="card.status"
class="status"
:class="'status-' + card.status"
>{{ card.statusText }}</div>
<div v-if="card.status" class="status" :class="'status-' + card.status">
{{ card.statusText }}
</div>
<div
v-if="card.progress"
class="progress"
:title="card.progress + ' | ' + card.latest"
>{{ card.progress }} | {{ card.latest }}</div>
<div
v-else
class="progress"
:title="card.latest"
>{{ card.latest }}</div>
<a
class="info"
:href="card.mediaUrl"
target="_blank"
title="详细信息"
>
{{ card.progress }} | {{ card.latest }}
</div>
<div v-else class="progress" :title="card.latest">{{ card.latest }}</div>
<a class="info" :href="card.mediaUrl" target="_blank" title="详细信息">
<VIcon icon="mdi-information-outline" :size="16"></VIcon>
</a>
</div>
@ -52,13 +43,7 @@
<script lang="ts">
import { getUID } from '@/core/utils'
import { logError } from '@/core/utils/log'
import {
DpiImage,
VLoading,
VEmpty,
VIcon,
ScrollTrigger,
} from '@/ui'
import { DpiImage, VLoading, VEmpty, VIcon, ScrollTrigger } from '@/ui'
import { getJsonWithCredentials } from '@/core/ajax'
import { SubscriptionTypes } from './subscriptions'
@ -129,22 +114,24 @@ export default Vue.extend({
logError(`加载订阅信息失败: ${json.message}`)
return
}
const cards = lodash.uniqBy(
(this.cards as any[]).concat(
(lodash.get(json, 'data.list') as any[]).map(item => ({
title: item.title,
coverUrl: item.square_cover.replace('http:', 'https:'),
latest: item.new_ep.index_show,
progress: item.progress,
id: item.season_id,
status: item.follow_status,
statusText: getStatusText(item.follow_status),
playUrl: `https://www.bilibili.com/bangumi/play/ss${item.season_id}`,
mediaUrl: `https://www.bilibili.com/bangumi/media/md${item.media_id}`,
})),
),
card => card.id,
).sort(subscriptionSorter)
const cards = lodash
.uniqBy(
(this.cards as any[]).concat(
(lodash.get(json, 'data.list') as any[]).map(item => ({
title: item.title,
coverUrl: item.square_cover.replace('http:', 'https:'),
latest: item.new_ep.index_show,
progress: item.progress,
id: item.season_id,
status: item.follow_status,
statusText: getStatusText(item.follow_status),
playUrl: `https://www.bilibili.com/bangumi/play/ss${item.season_id}`,
mediaUrl: `https://www.bilibili.com/bangumi/media/md${item.media_id}`,
})),
),
card => card.id,
)
.sort(subscriptionSorter)
this.page++
this.cards = cards
this.hasMorePage = lodash.get(json, 'data.total', 0) > this.cards.length
@ -157,7 +144,7 @@ export default Vue.extend({
</script>
<style lang="scss">
@import "common";
@import 'common';
.subscription-list {
width: 100%;

View File

@ -12,7 +12,10 @@ export const checkTransparentFill = async (vm: {
return
}
sq(
() => dqa('.animated-banner video, .banner-img img, #banner_link, .international-header .bili-banner, .bili-header__banner'),
() =>
dqa(
'.animated-banner video, .banner-img img, #banner_link, .international-header .bili-banner, .bili-header__banner',
),
banners => {
if (banners.length === 0) {
return false
@ -35,11 +38,15 @@ export const checkTransparentFill = async (vm: {
if (banner.length === 0) {
return
}
addComponentListener('customNavbar.transparent', value => {
if (!getComponentSettings('hideBanner').enabled) {
vm.toggleStyle(value, 'transparent')
}
}, true)
addComponentListener(
'customNavbar.transparent',
value => {
if (!getComponentSettings('hideBanner').enabled) {
vm.toggleStyle(value, 'transparent')
}
},
true,
)
addComponentListener('hideBanner', value => {
if (getComponentSettings('customNavbar').options.transparent) {
vm.toggleStyle(!value, 'transparent')

View File

@ -1,9 +1,7 @@
<template>
<div class="navbar-upload">
<VIcon icon="upload" :size="18"></VIcon>
<div class="navbar-upload-name">
投稿
</div>
<div class="navbar-upload-name">投稿</div>
</div>
</template>
<script lang="ts">

View File

@ -1,34 +1,21 @@
<template>
<div role="list" class="upload-popup">
<div role="listitem">
<a
target="_blank"
href="https://member.bilibili.com/platform/upload/text/apply"
>专栏投稿</a>
<a target="_blank" href="https://member.bilibili.com/platform/upload/text/apply">专栏投稿</a>
</div>
<div role="listitem">
<a
target="_blank"
href="https://member.bilibili.com/platform/upload/audio/frame"
>音频投稿</a>
<a target="_blank" href="https://member.bilibili.com/platform/upload/audio/frame">音频投稿</a>
</div>
<div role="listitem">
<a
target="_blank"
href="https://member.bilibili.com/platform/upload/sticker"
>贴纸投稿</a>
<a target="_blank" href="https://member.bilibili.com/platform/upload/sticker">贴纸投稿</a>
</div>
<div role="listitem">
<a
target="_blank"
href="https://member.bilibili.com/platform/upload/video/frame"
>视频投稿</a>
<a target="_blank" href="https://member.bilibili.com/platform/upload/video/frame">视频投稿</a>
</div>
<div role="listitem">
<a
target="_blank"
href="https://member.bilibili.com/platform/upload-manager/article"
>投稿管理</a>
<a target="_blank" href="https://member.bilibili.com/platform/upload-manager/article"
>投稿管理</a
>
</div>
<div role="listitem">
<a target="_blank" href="https://member.bilibili.com/platform/home">创作中心</a>
@ -43,7 +30,7 @@ export default Vue.extend({
})
</script>
<style lang="scss" scoped>
@import "../nav-link";
@import '../nav-link';
.upload-popup {
width: max-content;
a {

View File

@ -1,16 +1,10 @@
<template>
<div class="user-info-panel">
<div v-if="isLogin && userInfo.isLogin === true" class="logged-in">
<a
class="name"
target="_blank"
href="https://space.bilibili.com/"
>{{ userInfo.uname }}</a>
<a
class="type"
target="_blank"
href="https://account.bilibili.com/account/big"
>{{ userType }}</a>
<a class="name" target="_blank" href="https://space.bilibili.com/">{{ userInfo.uname }}</a>
<a class="type" target="_blank" href="https://account.bilibili.com/account/big">{{
userType
}}</a>
<div v-if="userInfo.vipStatus === 1 && userInfo.vipType === 2" class="privileges row">
<div
class="b-coin"
@ -43,15 +37,11 @@
:size="30"
class="level-icon plus"
/>
<VIcon
v-else
:icon="'lv' + userInfo.level_info.current_level"
class="level-icon"
/>
<VIcon v-else :icon="'lv' + userInfo.level_info.current_level" class="level-icon" />
</a>
<span
class="level-progress-label"
>{{ userInfo.level_info.current_exp }} / {{ userInfo.level_info.next_exp }}</span>
<span class="level-progress-label"
>{{ userInfo.level_info.current_exp }} / {{ userInfo.level_info.next_exp }}</span
>
</div>
<div class="level-progress separator">
<div class="level-progress-thumb" :style="levelProgressStyle"></div>
@ -77,21 +67,11 @@
<VIcon v-if="userInfo.email_verified" icon="ok" :size="18"></VIcon>
<VIcon v-else icon="cancel" :size="18"></VIcon>
</a>
<a
class="item"
target="_blank"
href="https://account.bilibili.com/site/coin"
title="硬币"
>
<a class="item" target="_blank" href="https://account.bilibili.com/site/coin" title="硬币">
<VIcon icon="coin-outline" :size="20"></VIcon>
<span>{{ userInfo.money }}</span>
</a>
<a
class="item"
target="_blank"
href="https://pay.bilibili.com/bb_balance.html"
title="B币"
>
<a class="item" target="_blank" href="https://pay.bilibili.com/bb_balance.html" title="B币">
<VIcon icon="b-coin-outline" :size="20"></VIcon>
<span>{{ userInfo.wallet.bcoin_balance }}</span>
</a>
@ -103,21 +83,24 @@
:href="'https://space.bilibili.com/' + userInfo.mid + '/fans/follow'"
target="_blank"
>
<div class="stats-number">{{ stat.following | count }}</div>关注
<div class="stats-number">{{ stat.following | count }}</div>
关注
</a>
<a
class="stats-item"
:href="'https://space.bilibili.com/' + userInfo.mid + '/fans/fans'"
target="_blank"
>
<div class="stats-number">{{ stat.follower | count }}</div>粉丝
<div class="stats-number">{{ stat.follower | count }}</div>
粉丝
</a>
<a
class="stats-item"
:href="'https://space.bilibili.com/' + userInfo.mid + '/dynamic'"
target="_blank"
>
<div class="stats-number">{{ stat.dynamic_count | count }}</div>动态
<div class="stats-number">{{ stat.dynamic_count | count }}</div>
动态
</a>
</div>
<div class="separator"></div>
@ -159,25 +142,14 @@
>
<VIcon icon="course"></VIcon>我的课程
</a>
<div
class="logout grey-button"
@click="logout()"
>
退出登录
</div>
<div class="logout grey-button" @click="logout()">退出登录</div>
</div>
<div v-if="!isLogin" class="not-logged-in">
<h1 class="welcome">
欢迎来到 bilibili
</h1>
<a
href="https://passport.bilibili.com/register/phone.html"
class="signup grey-button"
>注册</a>
<a
href="https://passport.bilibili.com/login"
class="login theme-button"
>登录</a>
<h1 class="welcome">欢迎来到 bilibili</h1>
<a href="https://passport.bilibili.com/register/phone.html" class="signup grey-button"
>注册</a
>
<a href="https://passport.bilibili.com/login" class="login theme-button">登录</a>
</div>
</div>
</template>
@ -260,30 +232,18 @@ export default Vue.extend({
async created() {
const userInfo = await getUserInfo()
this.userInfo = userInfo
const json = await getJsonWithCredentials(
'https://api.bilibili.com/x/web-interface/nav/stat',
)
const json = await getJsonWithCredentials('https://api.bilibili.com/x/web-interface/nav/stat')
this.stat = json.data || {}
if (this.isLogin && this.userInfo.vipType === 2) {
//
const privileges = await getJsonWithCredentials(
'https://api.bilibili.com/x/vip/privilege/my',
)
const privileges = await getJsonWithCredentials('https://api.bilibili.com/x/vip/privilege/my')
if (privileges.code === 0) {
const bCoin = privileges.data.list.find(
(it: { type: PrivilegeType }) => it.type === 1,
)
const bCoin = privileges.data.list.find((it: { type: PrivilegeType }) => it.type === 1)
this.privileges.bCoin.received = bCoin.state === 1
this.privileges.bCoin.expire = new Date(
bCoin.expire_time * 1000,
).toLocaleDateString()
const coupons = privileges.data.list.find(
(it: { type: PrivilegeType }) => it.type === 2,
)
this.privileges.bCoin.expire = new Date(bCoin.expire_time * 1000).toLocaleDateString()
const coupons = privileges.data.list.find((it: { type: PrivilegeType }) => it.type === 2)
this.privileges.coupons.received = coupons.state === 1
this.privileges.coupons.expire = new Date(
coupons.expire_time * 1000,
).toLocaleDateString()
this.privileges.coupons.expire = new Date(coupons.expire_time * 1000).toLocaleDateString()
}
}
},

View File

@ -4,7 +4,11 @@
<div class="search">
<TextBox v-model="search" linear placeholder="搜索"></TextBox>
</div>
<a class="operation" target="_blank" href="https://www.bilibili.com/medialist/play/watchlater">
<a
class="operation"
target="_blank"
href="https://www.bilibili.com/medialist/play/watchlater"
>
<VButton class="round-button" title="播放全部" round>
<VIcon icon="mdi-play" :size="18"></VIcon>
</VButton>
@ -17,39 +21,21 @@
</div>
<VLoading v-if="loading"></VLoading>
<VEmpty v-else-if="!loading && cards.length === 0"></VEmpty>
<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"
>
<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">
<a class="cover-container" target="_blank" :href="card.href">
<DpiImage
class="cover"
:src="card.coverUrl"
:size="{ width: 130, height: 85 }"
></DpiImage>
<div
class="floating remove"
title="移除"
@click.prevent="remove(card.aid, index)"
>
<div class="floating remove" title="移除" @click.prevent="remove(card.aid, index)">
<VIcon icon="mdi-close" :size="16"></VIcon>
</div>
<div class="floating duration">{{ card.durationText }}</div>
<div v-if="card.complete" class="floating viewed">已观看</div>
</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>
<a
class="up"
target="_blank"
@ -72,14 +58,7 @@ import {
RawWatchlaterItem,
toggleWatchlater,
} from '@/components/video/watchlater'
import {
VLoading,
VEmpty,
TextBox,
VButton,
VIcon,
DpiImage,
} from '@/ui'
import { VLoading, VEmpty, TextBox, VButton, VIcon, DpiImage } from '@/ui'
import { popperMixin } from '../mixins'
interface WatchlaterCard {
@ -191,17 +170,17 @@ export default Vue.extend({
const search = this.search.toLowerCase()
const cardsList = this.$el.querySelector('.watchlater-list-content') as HTMLElement
cardsList.scrollTo(0, 0)
this.filteredCards = (this.cards as WatchlaterCard[]).filter(card => (
card.title.toLowerCase().includes(search)
|| card.upName.toLowerCase().includes(search)
))
this.filteredCards = (this.cards as WatchlaterCard[]).filter(
card =>
card.title.toLowerCase().includes(search) || card.upName.toLowerCase().includes(search),
)
}, 100),
},
})
</script>
<style lang="scss">
@import "common";
@import "../popup";
@import 'common';
@import '../popup';
.custom-navbar .watchlater-list {
@include navbar-popup-height();

View File

@ -22,10 +22,7 @@ export const component: ComponentMetadata = {
})
},
urlExclude: darkExcludes,
tags: [
componentsTags.style,
componentsTags.general,
],
tags: [componentsTags.style, componentsTags.general],
description: {
'zh-CN': `
使 / , \`夜间模式计划时段\` 一同使用.

View File

@ -8,7 +8,10 @@ const add = async () => {
localStorage.setItem('pbp_theme_v4', 'b')
const meta = dq('meta[name="theme-color"]') as HTMLMetaElement
if (!meta) {
document.head.insertAdjacentHTML('beforeend', `<meta name="theme-color" content="${darkMetaColor}">`)
document.head.insertAdjacentHTML(
'beforeend',
`<meta name="theme-color" content="${darkMetaColor}">`,
)
} else {
meta.dataset.light = meta.content
meta.content = darkMetaColor
@ -40,10 +43,7 @@ export const component = defineComponentMetadata({
setTimeout(remove, changeDelay)
},
description: '启用夜间模式能更好地适应光线暗的环境, 并会大量应用主题颜色.',
tags: [
componentsTags.style,
componentsTags.general,
],
tags: [componentsTags.style, componentsTags.general],
instantStyles: [
{
name: 'dark-mode',

View File

@ -13,14 +13,14 @@ class ScheduleTime {
this.hour = now.getHours()
this.minute = now.getMinutes()
} else if (args.length === 1) {
const [text] = args;
[this.hour, this.minute] = text
const [text] = args
;[this.hour, this.minute] = text
.split(':')
.slice(0, 2)
.map(it => ScheduleTime.validatePart(it))
this.normalize()
} else if (args.length === 2) {
[this.hour, this.minute] = args
;[this.hour, this.minute] = args
}
}
normalize() {
@ -40,17 +40,13 @@ class ScheduleTime {
}
}
lessThan(other: ScheduleTime) {
if (this.hour < other.hour
|| (this.hour === other.hour && this.minute < other.minute)
) {
if (this.hour < other.hour || (this.hour === other.hour && this.minute < other.minute)) {
return true
}
return false
}
greaterThan(other: ScheduleTime) {
if (this.hour > other.hour
|| (this.hour === other.hour && this.minute > other.minute)
) {
if (this.hour > other.hour || (this.hour === other.hour && this.minute > other.minute)) {
return true
}
return false
@ -113,11 +109,9 @@ const checkTime = (settings: ComponentSettings) => {
export const component: ComponentMetadata = {
name: 'darkModeSchedule',
displayName: '夜间模式计划时段',
description: '设置一个使用夜间模式的时间段, 进入 / 离开此时间段时, 会自动开启 / 关闭夜间模式. 结束时间小于起始时间时将视为次日, 如 `18:00` 至 `6:00` 表示晚上 18:00 到次日 6:00. 请勿和 \`夜间模式跟随系统\` 一同使用.',
tags: [
componentsTags.style,
componentsTags.general,
],
description:
'设置一个使用夜间模式的时间段, 进入 / 离开此时间段时, 会自动开启 / 关闭夜间模式. 结束时间小于起始时间时将视为次日, 如 `18:00` 至 `6:00` 表示晚上 18:00 到次日 6:00. 请勿和 `夜间模式跟随系统` 一同使用.',
tags: [componentsTags.style, componentsTags.general],
entry: ({ settings }) => fullyLoaded(() => checkTime(settings)),
urlExclude: darkExcludes,
options: {

View File

@ -4,9 +4,7 @@ import { bangumiUrls } from '@/core/utils/urls'
export const component = defineComponentMetadata({
displayName: '隐藏番剧点评',
tags: [
componentsTags.style,
],
tags: [componentsTags.style],
...toggleStyle('hideBangumiReviews', () => import('./reviews.scss')),
urlInclude: bangumiUrls,
description: {

View File

@ -4,9 +4,7 @@ import { bangumiUrls } from '@/core/utils/urls'
export const component = defineComponentMetadata({
displayName: '隐藏番剧承包',
tags: [
componentsTags.style,
],
tags: [componentsTags.style],
...toggleStyle('hideBangumiSponsors', () => import('./sponsors.scss')),
urlInclude: bangumiUrls,
description: {

View File

@ -11,10 +11,7 @@ export const component = defineComponentMetadata({
},
],
displayName: '隐藏直播推荐',
tags: [
componentsTags.style,
componentsTags.video,
],
tags: [componentsTags.style, componentsTags.video],
description: {
'zh-CN': '隐藏视频页面右侧下方的直播推荐.',
},

View File

@ -11,12 +11,10 @@ export const component = defineComponentMetadata({
style: () => import('./related-videos.scss'),
},
],
tags: [
componentsTags.style,
componentsTags.video,
],
tags: [componentsTags.style, componentsTags.video],
description: {
'zh-CN': '隐藏番剧和视频页面右侧的推荐视频列表. 注意: 如果你想关闭 b 站的自动连播 (自动播放下一个推荐视频) 功能, 需要先取消隐藏视频推荐才能看到开关.',
'zh-CN':
'隐藏番剧和视频页面右侧的推荐视频列表. 注意: 如果你想关闭 b 站的自动连播 (自动播放下一个推荐视频) 功能, 需要先取消隐藏视频推荐才能看到开关.',
},
urlInclude: videoAndBangumiUrls,
})

View File

@ -12,9 +12,7 @@ export const component = defineComponentMetadata({
style: () => import('./top-mask.scss'),
},
],
tags: [
componentsTags.style,
],
tags: [componentsTags.style],
description: {
'zh-CN': '隐藏视频里鼠标经过时出现在右上角的覆盖层.',
},

View File

@ -4,12 +4,10 @@
</div>
</template>
<script lang="ts">
export default Vue.extend({
})
export default Vue.extend({})
</script>
<style lang="scss">
@import "common";
@import 'common';
html {
scroll-behavior: smooth;

View File

@ -2,11 +2,7 @@
<HomeRedesignBase>
<div class="fresh-home">
<div class="fresh-home-content-layout">
<FreshLayoutItem
v-for="layout of layouts"
:key="layout.name"
:item="layout"
/>
<FreshLayoutItem v-for="layout of layouts" :key="layout.name" :item="layout" />
</div>
</div>
</HomeRedesignBase>
@ -29,8 +25,8 @@ export default Vue.extend({
})
</script>
<style lang="scss">
@import "common";
@import "tabs";
@import 'common';
@import 'tabs';
.fresh-home {
padding: 16px 36px;
@ -65,7 +61,7 @@ export default Vue.extend({
@include h-center(8px);
.be-button {
.be-icon {
transition: .3s ease-out;
transition: 0.3s ease-out;
}
.be-iconfont-left-arrow {
transform: translateX(-0.5px);
@ -75,7 +71,7 @@ export default Vue.extend({
}
.mdi-refresh {
margin: 1px;
transition-duration: .5s;
transition-duration: 0.5s;
}
&:hover .mdi-refresh {
transform: rotate(1turn);
@ -91,7 +87,7 @@ export default Vue.extend({
}
.be-icon {
font-weight: normal;
transition: .3s ease-out;
transition: 0.3s ease-out;
margin-right: 6px;
}
&.rotate:hover .be-icon {

View File

@ -5,7 +5,7 @@
</div>
</template>
<style lang="scss">
@import "common";
@import 'common';
.fresh-home-sub-header {
@include h-center(6px);

View File

@ -24,12 +24,11 @@ export default Vue.extend({
.video-card {
border-radius: var(--home-card-radius) !important;
.cover-container {
border-radius:
calc(var(--home-card-radius) - 1px) calc(var(--home-card-radius) - 1px) 0 0 !important;
border-radius: calc(var(--home-card-radius) - 1px) calc(var(--home-card-radius) - 1px) 0 0 !important;
}
&,
& * {
transition: .2s ease-out;
transition: 0.2s ease-out;
}
}
}

View File

@ -8,13 +8,7 @@
<VLoading v-if="loading" />
<VEmpty v-else />
</div>
<VideoCardWrapper
v-for="video of videos"
v-else
ref="cards"
:key="video.id"
:data="video"
/>
<VideoCardWrapper v-for="video of videos" v-else ref="cards" :key="video.id" :data="video" />
</div>
</div>
</template>
@ -57,13 +51,17 @@ export default Vue.extend({
mounted() {
const container = this.$refs.content as HTMLElement
let cancel: () => void
addComponentListener('freshHome.horizontalWheelScroll', (scroll: boolean) => {
if (scroll) {
cancel = enableHorizontalScroll(container)
} else {
cancel?.()
}
}, true)
addComponentListener(
'freshHome.horizontalWheelScroll',
(scroll: boolean) => {
if (scroll) {
cancel = enableHorizontalScroll(container)
} else {
cancel?.()
}
},
true,
)
},
methods: {
async setupIntersection() {
@ -77,7 +75,9 @@ export default Vue.extend({
const container = this.$refs.content as HTMLElement
const style = getComputedStyle(container)
const containerWidth = container.clientWidth
const wrapperWidth = parseFloat(style.getPropertyValue('--card-width')) + parseFloat(style.getPropertyValue('--card-padding'))
const wrapperWidth =
parseFloat(style.getPropertyValue('--card-width')) +
parseFloat(style.getPropertyValue('--card-padding'))
const pageWidth = Math.trunc(containerWidth / wrapperWidth) * wrapperWidth
container.scrollBy(offset * pageWidth, 0)
},
@ -85,8 +85,8 @@ export default Vue.extend({
})
</script>
<style lang="scss">
@import "common";
@import "effects";
@import 'common';
@import 'effects';
.fresh-home-video-list {
--card-height: var(--home-content-height);

View File

@ -8,13 +8,15 @@ export const component = defineComponentMetadata({
name: 'freshHome',
displayName: '清爽首页',
urlInclude: homeUrls,
tags: [
componentsTags.style,
],
tags: [componentsTags.style],
entry: () => {
addComponentListener('freshHome.maxWidth', (width: number) => {
document.documentElement.style.setProperty('--home-max-width-override', `${width}px`)
}, true)
addComponentListener(
'freshHome.maxWidth',
(width: number) => {
document.documentElement.style.setProperty('--home-max-width-override', `${width}px`)
},
true,
)
contentLoaded(async () => {
const FreshHome = await import('./FreshHome.vue')
const freshHome = mountVueComponent(FreshHome)

View File

@ -1,25 +1,17 @@
<template>
<div class="fresh-home-areas">
<div class="fresh-home-header">
<div class="fresh-home-header-title">
栏目
</div>
<div class="fresh-home-header-title">栏目</div>
</div>
<div class="fresh-home-areas-content">
<a class="fresh-home-areas-content-primary" :href="primary.url" target="_blank">
<div class="fresh-home-areas-content-primary-image">
</div>
<div class="fresh-home-areas-content-primary-image"></div>
<div class="fresh-home-areas-content-primary-title">
{{ primary.title }}
</div>
</a>
<div class="fresh-home-areas-content-other">
<a
v-for="other of others"
:key="other.title"
:href="other.url"
target="_blank"
>
<a v-for="other of others" :key="other.title" :href="other.url" target="_blank">
<VButton type="transparent">
<VIcon colored :icon="other.icon" :size="22" />
{{ other.title }}
@ -76,7 +68,7 @@ export default Vue.extend({
})
</script>
<style lang="scss">
@import "common";
@import 'common';
.fresh-home-areas {
@include v-stretch();

View File

@ -1,10 +1,12 @@
<template>
<div class="fresh-home-blackboard" @mouseenter="destroyTimer" @mouseleave="createTimer">
<div class="fresh-home-header">
<div class="fresh-home-header-title">
活动
</div>
<a class="fresh-home-header-icon-button rotate" href="https://www.bilibili.com/blackboard/x/act_list/" target="_blank">
<div class="fresh-home-header-title">活动</div>
<a
class="fresh-home-header-icon-button rotate"
href="https://www.bilibili.com/blackboard/x/act_list/"
target="_blank"
>
<VButton round>
<VIcon icon="mdi-dots-horizontal" :size="20"></VIcon>
更多
@ -43,22 +45,14 @@
</a>
</div>
<div class="fresh-home-blackboard-jump-dots">
<label
v-for="(b, i) of blackboards"
:key="i"
:for="'blackboard' + i"
>
<label v-for="(b, i) of blackboards" :key="i" :for="'blackboard' + i">
<div class="fresh-home-blackboard-jump-dot"></div>
</label>
</div>
</div>
</template>
<script lang="ts">
import {
VButton,
VIcon,
DpiImage,
} from '@/ui'
import { VButton, VIcon, DpiImage } from '@/ui'
import { getBlackboards } from './api'
export default Vue.extend({
@ -98,18 +92,14 @@ export default Vue.extend({
if (!document.hasFocus() || this.$el.matches(':hover')) {
return
}
const currentIndex = parseInt(
dq(`.${radioClass}:checked`).getAttribute('data-index'),
)
const currentIndex = parseInt(dq(`.${radioClass}:checked`).getAttribute('data-index'))
let targetIndex: number
if (currentIndex === this.blackboards.length - 1) {
targetIndex = 0
} else {
targetIndex = currentIndex + 1
}
(dq(
`.${radioClass}[data-index='${targetIndex}']`,
) as HTMLInputElement).checked = true
;(dq(`.${radioClass}[data-index='${targetIndex}']`) as HTMLInputElement).checked = true
}, 5000)
},
destroyTimer() {
@ -123,7 +113,7 @@ export default Vue.extend({
})
</script>
<style lang="scss">
@import "common";
@import 'common';
$max-card-count: 16;
.fresh-home {
@ -131,7 +121,7 @@ $max-card-count: 16;
position: relative;
&,
& * {
transition: .2s ease-out;
transition: 0.2s ease-out;
}
&-cards {
display: flex;
@ -194,8 +184,8 @@ $max-card-count: 16;
width: 40px;
}
&:checked:nth-of-type(#{$i}) ~ .fresh-home-blackboard-cards .fresh-home-blackboard-card {
transform:
translateX(calc(-1 * #{$i - 1} * var(--blackboard-width-without-border))) scale(0.9);
transform: translateX(calc(-1 * #{$i - 1} * var(--blackboard-width-without-border)))
scale(0.9);
&:nth-of-type(#{$i}) {
transform: translateX(calc(-1 * #{$i - 1} * var(--blackboard-width-without-border)));
img {

View File

@ -14,11 +14,14 @@ export const getBlackboards = async (): Promise<Blackboard[]> => {
throw new Error(`获取活动卡片失败: ${message}`)
}
const list: any[] = data[locId]
return list.map(it => ({
url: it.url,
title: it.name,
// isAd: it.is_ad_loc,
isAd: it.res_id !== locId,
imageUrl: it.pic,
} as Blackboard))
return list.map(
it =>
({
url: it.url,
title: it.name,
// isAd: it.is_ad_loc,
isAd: it.res_id !== locId,
imageUrl: it.pic,
} as Blackboard),
)
}

View File

@ -1,9 +1,7 @@
<template>
<div class="fresh-home-categories">
<div class="fresh-home-header">
<div class="fresh-home-header-title">
分区
</div>
<div class="fresh-home-header-title">分区</div>
<div class="fresh-home-header-center-area">
<div class="fresh-home-header-tabs">
<div ref="tabs" class="default-tabs">
@ -105,7 +103,7 @@ export default Vue.extend({
})
</script>
<style lang="scss">
@import "common";
@import 'common';
.fresh-home-categories {
@include v-stretch();

View File

@ -2,13 +2,9 @@
<div class="fresh-home-categories-bangumi">
<div class="fresh-home-categories-bangumi-timeline">
<div class="fresh-home-categories-bangumi-timeline-header">
<SubHeader>
时间表
</SubHeader>
<SubHeader> 时间表 </SubHeader>
</div>
<BangumiTimeline
:api="timelineApi"
/>
<BangumiTimeline :api="timelineApi" />
</div>
<div class="fresh-home-categories-bangumi-rank-list">
<a
@ -16,15 +12,9 @@
:href="rankingsLink"
target="_blank"
>
<SubHeader>
排行榜
</SubHeader>
<SubHeader> 排行榜 </SubHeader>
</a>
<RankList
bangumi-mode
:parse-json="parseJson"
:api="rankingsApi"
/>
<RankList bangumi-mode :parse-json="parseJson" :api="rankingsApi" />
</div>
</div>
</template>
@ -73,22 +63,20 @@ export default Vue.extend({
parseJson(json: any) {
const items = (json.data?.list ?? []) as any[]
const cards = items
.map(
(item): RankListCard => {
const upName = item.new_ep?.index_show ?? item.title
return {
id: item.season_id,
title: item.title,
playCount: item.stat.view,
points: item.stat.follow,
upHref: item.url,
upName,
dynamic: upName,
coverUrl: item.new_ep?.cover ?? item.ss_horizontal_cover,
videoHref: item.url,
}
},
)
.map((item): RankListCard => {
const upName = item.new_ep?.index_show ?? item.title
return {
id: item.season_id,
title: item.title,
playCount: item.stat.view,
points: item.stat.follow,
upHref: item.url,
upName,
dynamic: upName,
coverUrl: item.new_ep?.cover ?? item.ss_horizontal_cover,
videoHref: item.url,
}
})
.slice(0, 10)
return applyContentFilter(cards)
},
@ -96,8 +84,8 @@ export default Vue.extend({
})
</script>
<style lang="scss">
@import "common";
@import "effects";
@import 'common';
@import 'effects';
.fresh-home-categories-bangumi {
@include h-stretch(var(--fresh-home-categories-column-gap));

View File

@ -25,19 +25,13 @@
<div class="fresh-home-categories-bangumi-timeline-date-text">
{{ dayOfWeekText(item) }}
</div>
<div
v-if="index === todayIndex"
class="fresh-home-categories-bangumi-timeline-date-today"
>
<div v-if="index === todayIndex" class="fresh-home-categories-bangumi-timeline-date-today">
TODAY
</div>
</div>
<div
ref="seasonsList"
class="
fresh-home-categories-bangumi-timeline-seasons-container
scroll-top scroll-bottom
"
class="fresh-home-categories-bangumi-timeline-seasons-container scroll-top scroll-bottom"
:class="{ 'not-empty': item.episodes.length > 0 }"
>
<div
@ -88,19 +82,13 @@
follow: season.follow,
}"
>
<div
class="fresh-home-categories-bangumi-timeline-season-time-icon"
>
<div class="fresh-home-categories-bangumi-timeline-season-time-icon">
<VIcon
:icon="
season.follow ? 'mdi-heart-outline' : 'mdi-progress-clock'
"
:icon="season.follow ? 'mdi-heart-outline' : 'mdi-progress-clock'"
:size="14"
/>
</div>
<div
class="fresh-home-categories-bangumi-timeline-season-time-text"
>
<div class="fresh-home-categories-bangumi-timeline-season-time-text">
{{ season.pub_time }}
</div>
</div>
@ -111,12 +99,7 @@
</div>
</template>
<script lang="ts">
import {
DpiImage,
VIcon,
VEmpty,
VLoading,
} from '@/ui'
import { DpiImage, VIcon, VEmpty, VLoading } from '@/ui'
import { addComponentListener } from '@/core/settings'
import { enableHorizontalScroll } from '@/core/horizontal-scroll'
import { cssVariableMixin, requestMixin } from '../../../../mixin'
@ -157,15 +140,9 @@ const timelineCssVars = (() => {
const seasonTodayWidth = 250
const timelineItemHeight = 66
const timelineTodayHeight = 96
const timelineViewportItemsHeight = (
6 * timelineItemHeight + timelineTodayHeight
)
const timelineItemGap = (
rankListHeight - timelineViewportItemsHeight
) / 6
const timelineViewportHeight = (
6 * timelineItemGap + timelineViewportItemsHeight
)
const timelineViewportItemsHeight = 6 * timelineItemHeight + timelineTodayHeight
const timelineItemGap = (rankListHeight - timelineViewportItemsHeight) / 6
const timelineViewportHeight = 6 * timelineItemGap + timelineViewportItemsHeight
return {
seasonItemWidth,
seasonTodayWidth,
@ -243,21 +220,22 @@ export default Vue.extend({
await this.$nextTick()
const list: HTMLElement[] = this.$refs.seasonsList
let cancelAll: () => void
addComponentListener('freshHome.horizontalWheelScroll', (scroll: boolean) => {
if (scroll) {
const cancel = list
.flatMap(it => [...it.children])
.map(it => enableHorizontalScroll(it as HTMLElement))
cancelAll = () => cancel.forEach(fn => fn())
} else {
cancelAll?.()
}
}, true)
const root: HTMLElement = this.$el
root.scrollTop = (
5 * timelineCssVars.timelineItemHeight
+ 5 * timelineCssVars.timelineItemGap
addComponentListener(
'freshHome.horizontalWheelScroll',
(scroll: boolean) => {
if (scroll) {
const cancel = list
.flatMap(it => [...it.children])
.map(it => enableHorizontalScroll(it as HTMLElement))
cancelAll = () => cancel.forEach(fn => fn())
} else {
cancelAll?.()
}
},
true,
)
const root: HTMLElement = this.$el
root.scrollTop = 5 * timelineCssVars.timelineItemHeight + 5 * timelineCssVars.timelineItemGap
const classPrefix = '.fresh-home-categories-bangumi-timeline'
list.forEach(seasons => {
@ -279,7 +257,10 @@ export default Vue.extend({
this.scrolled = true
return
}
const lastPublishedElement = dq(todaySeasons, `[data-season="${lastPublishedItem.season_id}"]`) as HTMLElement
const lastPublishedElement = dq(
todaySeasons,
`[data-season="${lastPublishedItem.season_id}"]`,
) as HTMLElement
if (!lastPublishedElement) {
return
}
@ -299,23 +280,14 @@ export default Vue.extend({
return season.pub_ts * 1000 <= this.now
},
dayOfWeekText(item: TimelineDay) {
return `${[
'日',
'一',
'二',
'三',
'四',
'五',
'六',
'日',
][item.day_of_week]}`
return `${['日', '一', '二', '三', '四', '五', '六', '日'][item.day_of_week]}`
},
},
})
</script>
<style lang="scss">
@import "common";
@import "effects";
@import 'common';
@import 'effects';
.fresh-home-categories-bangumi {
&-timeline {
@ -377,16 +349,13 @@ export default Vue.extend({
$icon-height: 48;
--scale-factor-x: calc(#{$icon-width} / 38);
--scale-factor-y: calc(#{$icon-height} / 36);
background-size: calc(247px * var(--scale-factor-x))
calc(663px * var(--scale-factor-y));
background-size: calc(247px * var(--scale-factor-x)) calc(663px * var(--scale-factor-y));
width: #{$icon-width}px;
height: #{$icon-height}px;
background-position-x: calc(-146px * var(--scale-factor-x));
@for $day from 1 through 7 {
&.day-of-week-#{$day} {
background-position-y: calc(
#{-36 - 72 * ($day - 1)}px * var(--scale-factor-y)
);
background-position-y: calc(#{-36 - 72 * ($day - 1)}px * var(--scale-factor-y));
}
}
body.dark & {
@ -485,8 +454,7 @@ export default Vue.extend({
&.today {
border-radius: 12px;
&.follow.published {
box-shadow: 0 0 0 2px var(--theme-color),
0 0 0 5px var(--theme-color-20);
box-shadow: 0 0 0 2px var(--theme-color), 0 0 0 5px var(--theme-color-20);
}
}
}

View File

@ -2,28 +2,19 @@
<div class="fresh-home-categories-default">
<div class="fresh-home-categories-default-video-column">
<div class="fresh-home-categories-default-video-column-item">
<SubHeader>
有新动态
</SubHeader>
<SubHeader> 有新动态 </SubHeader>
<VideoSlides :api="activeVideosApi" />
</div>
<div class="fresh-home-categories-default-video-column-item">
<SubHeader>
最新发布
</SubHeader>
<SubHeader> 最新发布 </SubHeader>
<VideoSlides :api="newVideosApi" />
</div>
</div>
<div class="fresh-home-categories-default-rank-list">
<a :href="rankingsLink" target="_blank">
<SubHeader>
排行榜
</SubHeader>
<SubHeader> 排行榜 </SubHeader>
</a>
<RankList
:parse-json="parseJson"
:api="rankingsApi"
/>
<RankList :parse-json="parseJson" :api="rankingsApi" />
</div>
</div>
</template>
@ -87,7 +78,7 @@ export default Vue.extend({
})
</script>
<style lang="scss">
@import "common";
@import 'common';
.fresh-home-categories-default {
@include h-stretch(var(--fresh-home-categories-column-gap));

View File

@ -4,11 +4,7 @@
<VLoading v-if="loading" />
<div v-if="(error || items.length === 0) && !loading" class="fresh-home-rank-list-empty">
<VEmpty />
<VButton
class="fresh-home-rank-list-refresh-button"
round
@click="reload"
>
<VButton class="fresh-home-rank-list-refresh-button" round @click="reload">
<VIcon icon="mdi-refresh" />
刷新
</VButton>
@ -25,11 +21,7 @@
>
{{ firstItem.title }}
</a>
<a
class="fresh-home-rank-list-cover"
target="_blank"
:href="firstItem.videoHref"
>
<a class="fresh-home-rank-list-cover" target="_blank" :href="firstItem.videoHref">
<DpiImage
:src="firstItem.coverUrl"
:size="{ width: ui.firstCoverWidth, height: ui.firstCoverHeight }"
@ -51,15 +43,8 @@
<div class="fresh-home-rank-list-laser" data-number="1"></div>
</div>
<div v-if="secondItem" class="fresh-home-rank-list-second-item animation">
<a
class="fresh-home-rank-list-rank-item"
target="_blank"
:href="secondItem.videoHref"
>
<div
class="fresh-home-rank-list-rank-item-title"
:title="secondItem.title"
>
<a class="fresh-home-rank-list-rank-item" target="_blank" :href="secondItem.videoHref">
<div class="fresh-home-rank-list-rank-item-title" :title="secondItem.title">
{{ secondItem.title }}
</div>
<UpInfo
@ -78,11 +63,7 @@
{{ secondItem.playCount | formatCount }}
</div>
</a>
<a
class="fresh-home-rank-list-cover"
target="_blank"
:href="secondItem.videoHref"
>
<a class="fresh-home-rank-list-cover" target="_blank" :href="secondItem.videoHref">
<DpiImage
:src="secondItem.coverUrl"
:size="{ width: ui.secondCoverWidth, height: ui.secondCoverHeight }"
@ -91,15 +72,8 @@
<div class="fresh-home-rank-list-laser" data-number="2"></div>
</div>
<div v-if="thirdItem" class="fresh-home-rank-list-third-item animation">
<a
class="fresh-home-rank-list-rank-item"
target="_blank"
:href="thirdItem.videoHref"
>
<div
class="fresh-home-rank-list-rank-item-title"
:title="thirdItem.title"
>
<a class="fresh-home-rank-list-rank-item" target="_blank" :href="thirdItem.videoHref">
<div class="fresh-home-rank-list-rank-item-title" :title="thirdItem.title">
{{ thirdItem.title }}
</div>
<UpInfo
@ -118,11 +92,7 @@
{{ secondItem.playCount | formatCount }}
</div>
</a>
<a
class="fresh-home-rank-list-cover"
target="_blank"
:href="thirdItem.videoHref"
>
<a class="fresh-home-rank-list-cover" target="_blank" :href="thirdItem.videoHref">
<DpiImage
:src="thirdItem.coverUrl"
:size="{ width: ui.thirdCoverWidth, height: ui.thirdCoverHeight }"
@ -136,13 +106,7 @@
<script lang="ts">
import UpInfo from '@/components/feeds/UpInfo.vue'
import { formatCount } from '@/core/utils/formatters'
import {
DpiImage,
VIcon,
VLoading,
VEmpty,
VButton,
} from '@/ui'
import { DpiImage, VIcon, VLoading, VEmpty, VButton } from '@/ui'
import { requestMixin, cssVariableMixin } from '../../../../mixin'
import { rankListCssVars } from './rank-list'
@ -158,10 +122,7 @@ export default Vue.extend({
filters: {
formatCount,
},
mixins: [
requestMixin(),
cssVariableMixin(rankListCssVars),
],
mixins: [requestMixin(), cssVariableMixin(rankListCssVars)],
props: {
parseJson: {
type: Function,
@ -201,7 +162,7 @@ export default Vue.extend({
})
</script>
<style lang="scss">
@import "common";
@import 'common';
.fresh-home-rank-list {
position: relative;
@ -225,7 +186,7 @@ export default Vue.extend({
& &-stats {
@include h-center(12px);
font-size: 12px;
opacity: .5;
opacity: 0.5;
margin: 0 10px;
.be-icon {
margin-right: -8px;
@ -243,7 +204,7 @@ export default Vue.extend({
&-title {
@include semi-bold();
transition: color .2s ease-out;
transition: color 0.2s ease-out;
line-height: var(--rank-item-title-height);
box-sizing: content-box;
&:hover {
@ -266,7 +227,7 @@ export default Vue.extend({
}
}
@include v-stretch();
animation: .4s var(--animation-timing) first-animation paused both;
animation: 0.4s var(--animation-timing) first-animation paused both;
position: absolute;
top: var(--padding);
left: var(--padding);
@ -317,7 +278,7 @@ export default Vue.extend({
}
}
@include v-stretch();
animation: .4s var(--animation-timing) second-animation paused both;
animation: 0.4s var(--animation-timing) second-animation paused both;
position: absolute;
top: var(--offset-second);
bottom: var(--padding);
@ -350,7 +311,7 @@ export default Vue.extend({
}
}
@include v-stretch();
animation: .4s var(--animation-timing) third-animation paused both;
animation: 0.4s var(--animation-timing) third-animation paused both;
position: absolute;
top: var(--offset-third);
right: var(--padding);
@ -379,7 +340,7 @@ export default Vue.extend({
box-shadow: none;
overflow: hidden;
transform-origin: bottom;
transition: .2s ease-out;
transition: 0.2s ease-out;
position: relative;
img {
@ -398,11 +359,7 @@ export default Vue.extend({
flex: 1;
width: 4px;
border-radius: 2px;
background-image: linear-gradient(
to bottom,
var(--theme-color) 0%,
var(--theme-color-10) 100%
);
background-image: linear-gradient(to bottom, var(--theme-color) 0%, var(--theme-color-10) 100%);
&::after {
content: attr(data-number);
@include absolute-center();
@ -436,7 +393,7 @@ export default Vue.extend({
}
.be-icon {
margin-right: 6px;
transition: .5s ease-out;
transition: 0.5s ease-out;
}
}

View File

@ -18,19 +18,12 @@
</div>
<div class="cover-placeholder-vertical"></div>
<div v-if="!loaded" class="fresh-home-video-slides-empty">
<div
class="empty-placeholder fresh-home-video-slides-main-title"
v-text="' '"
></div>
<div class="empty-placeholder fresh-home-video-slides-main-title" v-text="' '"></div>
<div class="empty-indicator">
<VLoading v-if="loading" />
<div v-if="error" class="empty-indicator-error">
<VEmpty />
<VButton
class="fresh-home-video-slides-refresh-button"
round
@click="reload"
>
<VButton class="fresh-home-video-slides-refresh-button" round @click="reload">
<VIcon icon="mdi-refresh" />
刷新
</VButton>
@ -42,11 +35,7 @@
<div class="fresh-home-video-slides-row">
<div class="cover-placeholder-horizontal"></div>
<div class="fresh-home-video-slides-main-actions">
<a
class="fresh-home-video-slides-play-button"
:href="currentUrl"
target="_blank"
>
<a class="fresh-home-video-slides-play-button" :href="currentUrl" target="_blank">
<VButton type="primary" round>
<VIcon icon="mdi-play" />
播放
@ -96,12 +85,7 @@
<div class="description-text" v-text="currentItem.description"></div>
</div>
<div class="fresh-home-video-slides-actions">
<VButton
class="fresh-home-video-slides-refresh-button"
title="刷新"
icon
@click="reload"
>
<VButton class="fresh-home-video-slides-refresh-button" title="刷新" icon @click="reload">
<VIcon icon="mdi-refresh" />
</VButton>
<VButton
@ -112,12 +96,7 @@
>
<VIcon icon="mdi-arrow-left" />
</VButton>
<VButton
class="fresh-home-video-slides-next-button"
title="下一个"
icon
@click="nextCard"
>
<VButton class="fresh-home-video-slides-next-button" title="下一个" icon @click="nextCard">
<VIcon icon="mdi-arrow-right" :size="36" />
</VButton>
</div>
@ -140,15 +119,18 @@ export default Vue.extend({
VLoading,
VEmpty,
},
mixins: [requestMixin(), cssVariableMixin({
mainCoverHeight: 185,
mainCoverWidth: 287,
otherCoverHeight: 100,
otherCoverWidth: 154,
mainPaddingX: 18,
mainPaddingY: 20,
coverPadding: 16,
})],
mixins: [
requestMixin(),
cssVariableMixin({
mainCoverHeight: 185,
mainCoverWidth: 287,
otherCoverHeight: 100,
otherCoverWidth: 154,
mainPaddingX: 18,
mainPaddingY: 20,
coverPadding: 16,
}),
],
data() {
return {
watchlaterList,
@ -224,8 +206,8 @@ export default Vue.extend({
})
</script>
<style lang="scss">
@import "common";
@import "effects";
@import 'common';
@import 'effects';
.fresh-home-video-slides {
@include card(12px);
@ -339,9 +321,7 @@ export default Vue.extend({
justify-content: space-between;
position: relative;
padding-top: var(--main-info-padding);
width: calc(
var(--main-cover-width) + var(--cover-padding) + var(--other-cover-width)
);
width: calc(var(--main-cover-width) + var(--cover-padding) + var(--other-cover-width));
}
& &-main-title {
font-size: 16px;
@ -403,9 +383,7 @@ export default Vue.extend({
}
&:nth-child(1) {
opacity: 0;
transform: translateX(
calc(0px - var(--other-cover-width) - var(--cover-padding))
);
transform: translateX(calc(0px - var(--other-cover-width) - var(--cover-padding)));
}
&:nth-child(2) {
width: var(--main-cover-width);

View File

@ -1,7 +1,4 @@
const bangumiNames = [
'番剧',
'国创',
]
const bangumiNames = ['番剧', '国创']
export const getContent = (tabName: string) => {
console.log('getContent', tabName)
if (bangumiNames.includes(tabName)) {

View File

@ -1,9 +1,7 @@
<template>
<div class="fresh-home-feeds">
<div class="fresh-home-header">
<div class="fresh-home-header-title">
动态
</div>
<div class="fresh-home-header-title">动态</div>
<div class="fresh-home-header-center-area">
<div class="fresh-home-header-tabs">
<div class="default-tabs">
@ -22,11 +20,7 @@
</div>
</div>
<div class="fresh-home-header-pagination">
<a
href="https://www.bilibili.com/video/online.html"
target="_blank"
title="在线列表"
>
<a href="https://www.bilibili.com/video/online.html" target="_blank" title="在线列表">
<VButton icon>
<VIcon icon="mdi-account-group-outline" :size="19" />
</VButton>
@ -53,11 +47,7 @@
</div>
</div>
<div class="fresh-home-feeds-content">
<VideoList
ref="videoList"
:videos="videos"
:loading="loading"
/>
<VideoList ref="videoList" :videos="videos" :loading="loading" />
</div>
</div>
</template>
@ -113,13 +103,15 @@ export default Vue.extend({
async reload() {
this.loading = true
this.videos = []
this.videos = await this.selectedTab.api().finally(() => { this.loading = false })
this.videos = await this.selectedTab.api().finally(() => {
this.loading = false
})
},
},
})
</script>
<style lang="scss">
@import "common";
@import 'common';
.fresh-home-feeds {
@include v-stretch();

View File

@ -5,11 +5,5 @@ import { categories } from './categories/categories'
import { feeds } from './feeds/feeds'
import { trending } from './trending/trending'
const builtInLayouts = [
blackboard,
trending,
feeds,
areas,
categories,
]
const builtInLayouts = [blackboard, trending, feeds, areas, categories]
export const [layouts] = registerAndGetData('homeRedesign.fresh.layouts', [...builtInLayouts])

View File

@ -17,19 +17,12 @@
</div>
</div>
<div class="fresh-home-trending-content">
<VideoList
ref="videoList"
:videos="videos"
:loading="loading"
/>
<VideoList ref="videoList" :videos="videos" :loading="loading" />
</div>
</div>
</template>
<script lang="ts">
import {
VButton,
VIcon,
} from '@/ui'
import { VButton, VIcon } from '@/ui'
import VideoList from '../../VideoList.vue'
import { freshHomeOptions } from '../../types'
import { getTrendingVideos } from '../../../trending'
@ -61,14 +54,15 @@ export default Vue.extend({
async reload() {
this.loading = true
this.videos = []
this.videos = await getTrendingVideos(freshHomeOptions.personalized)
.finally(() => { this.loading = false })
this.videos = await getTrendingVideos(freshHomeOptions.personalized).finally(() => {
this.loading = false
})
},
},
})
</script>
<style lang="scss">
@import "common";
@import 'common';
.fresh-home-trending {
@include v-stretch();

View File

@ -17,10 +17,8 @@ export const setupScrollMask = (config: ScrollMaskConfig) => {
}
const observerConfig: IntersectionObserverInit = { threshold: [1], root: container }
const [firstItem] = items
const [firstObserver] = intersectionObserve(
[firstItem],
observerConfig,
records => records.forEach(r => {
const [firstObserver] = intersectionObserve([firstItem], observerConfig, records =>
records.forEach(r => {
const isScrollTop = r.isIntersecting && r.intersectionRatio === 1
container.classList.toggle('scroll-top', isScrollTop)
}),
@ -30,10 +28,8 @@ export const setupScrollMask = (config: ScrollMaskConfig) => {
newObservers.push(firstObserver)
if (items.length > 1) {
const lastItem = items[items.length - 1]
const [lastObserver] = intersectionObserve(
[lastItem],
observerConfig,
records => records.forEach(r => {
const [lastObserver] = intersectionObserve([lastItem], observerConfig, records =>
records.forEach(r => {
const isScrollBottom = r.isIntersecting && r.intersectionRatio === 1
container.classList.toggle('scroll-bottom', isScrollBottom)
}),

View File

@ -39,13 +39,17 @@ export default Vue.extend({
},
mounted() {
const columnCountKey = '--minimal-home-column-count-override'
addComponentListener('minimalHome.columnCount', (count: number) => {
if (count > 0) {
(this.$el as HTMLElement).style.setProperty(columnCountKey, count.toString())
} else {
(this.$el as HTMLElement).style.removeProperty(columnCountKey)
}
}, true)
addComponentListener(
'minimalHome.columnCount',
(count: number) => {
if (count > 0) {
;(this.$el as HTMLElement).style.setProperty(columnCountKey, count.toString())
} else {
;(this.$el as HTMLElement).style.removeProperty(columnCountKey)
}
},
true,
)
},
})
</script>
@ -76,17 +80,13 @@ export default Vue.extend({
&-tabs {
flex-grow: 1;
min-width: calc(
var(--card-width) * var(--minimal-home-card-column) +
var(--minimal-home-grid-gap) * (var(--minimal-home-card-column) - 1) + 2 *
var(--minimal-home-grid-padding)
var(--card-width) * var(--minimal-home-card-column) + var(--minimal-home-grid-gap) *
(var(--minimal-home-card-column) - 1) + 2 * var(--minimal-home-grid-padding)
);
.minimal-home-tab {
&-cards {
display: grid;
grid-template-columns: repeat(
var(--minimal-home-card-column),
var(--card-width)
);
grid-template-columns: repeat(var(--minimal-home-card-column), var(--card-width));
gap: var(--minimal-home-grid-gap);
padding: 0 var(--minimal-home-grid-padding);
margin-bottom: 16px;

View File

@ -5,17 +5,14 @@
icon
class="minimal-home-operations-refresh"
title="刷新"
@click="backToTop(); $emit('refresh')"
@click="
backToTop()
$emit('refresh')
"
>
<VIcon icon="mdi-refresh" :size="size" />
</VButton>
<VButton
round
icon
class="minimal-home-operations-top"
title="返回顶部"
@click="backToTop"
>
<VButton round icon class="minimal-home-operations-top" title="返回顶部" @click="backToTop">
<VIcon icon="mdi-arrow-up" :size="size" />
</VButton>
</div>

View File

@ -25,13 +25,15 @@ export const component = defineComponentMetadata({
name: 'minimalHome',
displayName: '极简首页',
urlInclude: homeUrls,
tags: [
componentsTags.style,
],
tags: [componentsTags.style],
entry: () => {
addComponentListener('minimalHome.columnCount', (count: number) => {
document.documentElement.style.setProperty('--home-column-count-override', count.toString())
}, true)
addComponentListener(
'minimalHome.columnCount',
(count: number) => {
document.documentElement.style.setProperty('--home-column-count-override', count.toString())
},
true,
)
contentLoaded(async () => {
const MinimalHome = await import('./MinimalHome.vue')
const minimalHome = mountVueComponent(MinimalHome)

View File

@ -2,4 +2,5 @@ import { OptionsOfMetadata } from '@/components/define'
import { getComponentSettings } from '@/core/settings'
import type { minimalHomeOptionsMetadata } from '.'
export const minimalHomeOptions = getComponentSettings<OptionsOfMetadata<typeof minimalHomeOptionsMetadata>>('minimalHome').options
export const minimalHomeOptions =
getComponentSettings<OptionsOfMetadata<typeof minimalHomeOptionsMetadata>>('minimalHome').options

View File

@ -14,10 +14,7 @@ import { VideoCard } from '@/components/feeds/video-card'
import VideoCardComponent from '@/components/feeds/VideoCard.vue'
import { logError } from '@/core/utils/log'
import { ascendingStringSort } from '@/core/utils/sort'
import {
VEmpty,
ScrollTrigger,
} from '@/ui'
import { VEmpty, ScrollTrigger } from '@/ui'
import MinimalHomeOperations from '../MinimalHomeOperations.vue'
export default Vue.extend({
@ -46,7 +43,10 @@ export default Vue.extend({
try {
this.error = false
this.loading = true
this.cards = lodash.uniqBy([...this.cards, ...await getVideoFeeds('video', this.lastID)], it => it.id)
this.cards = lodash.uniqBy(
[...this.cards, ...(await getVideoFeeds('video', this.lastID))],
it => it.id,
)
} catch (error) {
logError(error)
this.error = true

View File

@ -13,10 +13,7 @@ import { VideoCard } from '@/components/feeds/video-card'
import VideoCardComponent from '@/components/feeds/VideoCard.vue'
import { logError } from '@/core/utils/log'
import { ascendingStringSort } from '@/core/utils/sort'
import {
VEmpty,
VLoading,
} from '@/ui'
import { VEmpty, VLoading } from '@/ui'
import { getTrendingVideos } from '../../trending'
import MinimalHomeOperations from '../MinimalHomeOperations.vue'
import { minimalHomeOptions } from '../options'

View File

@ -3,9 +3,11 @@ import { getJson } from '@/core/ajax'
/**
* API , 使 parseJson JSON , this.items
*/
export const requestMixin = (config: {
requestMethod?: (url: string) => Promise<any>
} = {}) => {
export const requestMixin = (
config: {
requestMethod?: (url: string) => Promise<any>
} = {},
) => {
const { requestMethod = getJson } = config
return Vue.extend({
props: {
@ -34,9 +36,10 @@ export const requestMixin = (config: {
try {
this.error = false
this.loading = true
this.items = this.parseJson(
await requestMethod(this.api),
).slice(0, this.itemLimit ?? Infinity)
this.items = this.parseJson(await requestMethod(this.api)).slice(
0,
this.itemLimit ?? Infinity,
)
} catch (error) {
console.error(error)
this.error = true
@ -52,19 +55,18 @@ export const requestMixin = (config: {
* UI this.ui , CSS var
* @param variables UI
*/
export const cssVariableMixin = (variables: Record<string, string | number>) => Vue.extend({
data() {
return {
ui: variables,
}
},
mounted() {
const element = this.$el as HTMLElement
Object.entries(variables).forEach(
([name, value]) => {
export const cssVariableMixin = (variables: Record<string, string | number>) =>
Vue.extend({
data() {
return {
ui: variables,
}
},
mounted() {
const element = this.$el as HTMLElement
Object.entries(variables).forEach(([name, value]) => {
const stringValue = typeof value === 'number' ? `${value}px` : value
element.style.setProperty(`--${lodash.kebabCase(name)}`, stringValue)
},
)
},
})
})
},
})

View File

@ -11,10 +11,7 @@ export const component = defineComponentMetadata({
style: () => import('./player-shadow.scss'),
},
],
tags: [
componentsTags.style,
componentsTags.video,
],
tags: [componentsTags.style, componentsTags.video],
description: {
'zh-CN': '为播放器添加主题色投影.',
},

View File

@ -4,11 +4,9 @@ export const component = defineComponentMetadata({
name: 'elegantScrollbar',
entry: none,
displayName: '使用细滚动条',
description: '使用浏览器的滚动条风格替代系统的滚动条, 不过 macOS 系统滚动条比浏览器做得好一些, 因此不建议 macOS 使用此功能.',
tags: [
componentsTags.style,
componentsTags.general,
],
description:
'使用浏览器的滚动条风格替代系统的滚动条, 不过 macOS 系统滚动条比浏览器做得好一些, 因此不建议 macOS 使用此功能.',
tags: [componentsTags.style, componentsTags.general],
instantStyles: [
{
name: 'elegant-scrollbar',

View File

@ -16,9 +16,13 @@ export const component = defineComponentMetadata({
'zh-CN': '给脚本的侧栏设置垂直偏移量, 范围为 -35% ~ 40%',
},
entry: ({ metadata }) => {
addComponentListener(`${metadata.name}.offset`, (value: number) => {
document.body.style.setProperty('--be-sidebar-offset', `${value}%`)
}, true)
addComponentListener(
`${metadata.name}.offset`,
(value: number) => {
document.body.style.setProperty('--be-sidebar-offset', `${value}%`)
},
true,
)
},
options: {
offset: {

View File

@ -5,9 +5,13 @@ export const component = defineComponentMetadata({
name,
entry: async ({ metadata }) => {
const { addComponentListener } = await import('@/core/settings')
addComponentListener(metadata.name, (value: boolean) => {
document.body.classList.toggle('simplify-comment', value)
}, true)
addComponentListener(
metadata.name,
(value: boolean) => {
document.body.classList.toggle('simplify-comment', value)
},
true,
)
},
instantStyles: [
{
@ -29,7 +33,5 @@ export const component = defineComponentMetadata({
> : 关注和等级可以通过鼠标停留在头像上, .`.trim(),
},
tags: [
componentsTags.style,
],
tags: [componentsTags.style],
})

View File

@ -75,13 +75,15 @@ const metadata: ComponentMetadata = {
() => dqa('.proxy-box > div'),
elements => elements.length > 0 || isNotHome,
)
return Object.fromEntries(categoryElements.map(it => ([
it.id.replace(/^bili_/, ''),
{
displayName: it.querySelector('header .name')?.textContent?.trim() ?? '未知分区',
defaultValue: false,
},
])))
return Object.fromEntries(
categoryElements.map(it => [
it.id.replace(/^bili_/, ''),
{
displayName: it.querySelector('header .name')?.textContent?.trim() ?? '未知分区',
defaultValue: false,
},
]),
)
}
const skipIds = ['推广']
@ -100,24 +102,25 @@ const metadata: ComponentMetadata = {
}
return null
}
const entries = headers
?.filter(element => !skipIds.includes(element.id))
.map(element => {
const container = getContainer(element) as HTMLElement
const name = element.id
if (container) {
container.dataset.area = name
return [
name,
{
displayName: name,
defaultValue: false,
},
]
}
return null
})
.filter((it): it is [string, SimplifyHomeOption] => it !== null) ?? []
const entries =
headers
?.filter(element => !skipIds.includes(element.id))
.map(element => {
const container = getContainer(element) as HTMLElement
const name = element.id
if (container) {
container.dataset.area = name
return [
name,
{
displayName: name,
defaultValue: false,
},
]
}
return null
})
.filter((it): it is [string, SimplifyHomeOption] => it !== null) ?? []
return Object.fromEntries(entries)
})()
const generatedSwitches: Record<string, unknown> = {}
@ -142,12 +145,16 @@ const metadata: ComponentMetadata = {
generatedSwitches[key] = option
})
options.simplifyOptions.switches = generatedSwitches
const generatedStyles = Object.keys(generatedOptions).map(name => `
const generatedStyles = Object.keys(generatedOptions)
.map(name =>
`
body.simplifyHome-switch-${name} .bili-layout .bili-grid[data-area="${name}"],
body.simplifyHome-switch-${name} .storey-box .proxy-box #bili_${name} {
display: none !important;
}
`.trim()).join('\n')
`.trim(),
)
.join('\n')
addStyle(generatedStyles, 'simplify-home-generated')
},
}

View File

@ -91,21 +91,19 @@ export const component = createSwitchOptions({
displayName: '房间皮肤',
},
},
})(
{
name: 'simplifyLiveroom',
displayName: '简化直播间',
entry: styledComponentEntry(() => import('./live.scss'), async () => {
})({
name: 'simplifyLiveroom',
displayName: '简化直播间',
entry: styledComponentEntry(
() => import('./live.scss'),
async () => {
const { setupSkinSimplify } = await import('./skin')
setupSkinSimplify()
}),
description: {
'zh-CN': '隐藏直播间中各种不需要的内容.',
},
tags: [
componentsTags.live,
componentsTags.style,
],
urlInclude: liveUrls,
),
description: {
'zh-CN': '隐藏直播间中各种不需要的内容.',
},
)
tags: [componentsTags.live, componentsTags.style],
urlInclude: liveUrls,
})

View File

@ -2,11 +2,15 @@ import { addComponentListener } from '@/core/settings'
import { select } from '@/core/spin-query'
export const setupSkinSimplify = async () => {
addComponentListener('simplifyLiveroom.switch-skin', async (disable: boolean) => {
const skinCss = await select('#skin-css') as HTMLStyleElement
if (!skinCss) {
return
}
skinCss.media = disable ? 'none' : 'all'
}, true)
addComponentListener(
'simplifyLiveroom.switch-skin',
async (disable: boolean) => {
const skinCss = (await select('#skin-css')) as HTMLStyleElement
if (!skinCss) {
return
}
skinCss.media = disable ? 'none' : 'all'
},
true,
)
}

Some files were not shown because too many files have changed in this diff Show More