mirror of
https://github.com/the1812/Bilibili-Evolved.git
synced 2025-11-04 21:22:45 +08:00
245 lines
7.1 KiB
TypeScript
245 lines
7.1 KiB
TypeScript
import {
|
|
TestPattern,
|
|
Executable,
|
|
VueModule,
|
|
I18nDescription,
|
|
} from '@/core/common-types'
|
|
import { ComponentSettings } from '@/core/settings'
|
|
import { CoreApis } from '@/core/core-apis'
|
|
import { PluginMinimalData } from '@/plugins/plugin'
|
|
import { Range } from '@/ui/range'
|
|
import { Widget } from '@/components/widget'
|
|
import { LanguagePack } from './i18n/types'
|
|
|
|
export type Author = {
|
|
name: string
|
|
link: string
|
|
}
|
|
|
|
export interface FeatureBase {
|
|
// TODO: 可在编译时转换 Markdown 以提高运行时性能
|
|
/** 描述 (支持 markdown), 可以设置为对象提供多语言的描述 (`key: 语言代码`) */
|
|
description?: I18nDescription
|
|
/** 作者信息 */
|
|
author?: Author | Author[]
|
|
/** 编译时的 commit hash, 由 Babel 注入, 不需要手动填写 */
|
|
commitHash?: string
|
|
/** 编译时的 core version, 由 Babel 注入, 不需要手动填写 */
|
|
coreVersion?: string
|
|
}
|
|
|
|
type Optional<Target, Props extends keyof Target> = {
|
|
[P in Props]?: Target[P]
|
|
} & Omit<Target, Props>
|
|
|
|
/** 组件标签 */
|
|
export interface ComponentTag {
|
|
/** 标签的名称 */
|
|
name: string
|
|
/** 标签的显示名称 */
|
|
displayName: string
|
|
/** 标签的颜色 */
|
|
color: string
|
|
/** 标签对应图标(传入`<VIcon>`的`icon`中) */
|
|
icon: string
|
|
/** 设置面板中的呈现顺序 */
|
|
order: number
|
|
}
|
|
|
|
type ComponentOptionValidator<T> = (value: T, oldValue: T) => T | undefined | null
|
|
|
|
// TODO: 参考 discussion #3041。当不兼容代码替换完成后将 any 改为 unknown
|
|
export type UnknownOptions = Record<string, any>
|
|
|
|
export type EmptyOptions = Record<string, never>
|
|
|
|
/** 单个选项的信息 */
|
|
export interface OptionMetadata<V = unknown> {
|
|
/** 默认值 */
|
|
defaultValue: V
|
|
/** 显示名称 */
|
|
displayName?: string
|
|
/** 如果希望这个选项显示为一个下拉框, 可以用相应的 `enum` 提供下拉框的选值, 或者也可以传入 `string[]` */
|
|
dropdownEnum?: unknown
|
|
/** 是否不显示在设置面板中(不自动生成选项UI) */
|
|
hidden?: boolean
|
|
/** 设为 `true` 时, 将用颜色选取器替代文本框 */
|
|
color?: boolean
|
|
/** 设置范围, 可以显示为一个滑动条 */
|
|
slider?: {
|
|
min?: number
|
|
max?: number
|
|
step?: number
|
|
}
|
|
/** `number`, `string`或`Range`类型的选项, 可以添加验证函数来阻止非法输入 */
|
|
validator?: ComponentOptionValidator<Range<string>> |
|
|
ComponentOptionValidator<string> | ComponentOptionValidator<number>
|
|
}
|
|
|
|
/** 多个选项的信息 */
|
|
export type OptionsMetadata<O extends UnknownOptions = UnknownOptions> = {
|
|
[OptionName in keyof O]: OptionMetadata<O[OptionName]>
|
|
}
|
|
|
|
// TODO: 参考 discussion #3041。当不兼容代码替换完成后删除
|
|
export type ComponentOptions = OptionsMetadata
|
|
|
|
/** 组件标签 */
|
|
export const componentsTags = {
|
|
/** 视频 */
|
|
video: {
|
|
name: 'video',
|
|
displayName: '视频',
|
|
color: '#2196F3',
|
|
icon: 'mdi-play-circle-outline',
|
|
order: 1,
|
|
} as ComponentTag,
|
|
/** 样式 */
|
|
style: {
|
|
name: 'style',
|
|
displayName: '样式',
|
|
color: '#8BC34A',
|
|
icon: 'mdi-palette-outline',
|
|
order: 2,
|
|
} as ComponentTag,
|
|
/** 动态 */
|
|
feeds: {
|
|
name: 'feeds',
|
|
displayName: '动态',
|
|
color: '#00ACC1',
|
|
// 用了MDI里尖角的风车图标, 因为懒得再调视觉大小了
|
|
icon: 'mdi-pinwheel-outline',
|
|
order: 3,
|
|
} as ComponentTag,
|
|
/** 直播 */
|
|
live: {
|
|
name: 'live',
|
|
displayName: '直播',
|
|
color: '#26A69A',
|
|
icon: 'mdi-video-wireless-outline',
|
|
order: 4,
|
|
} as ComponentTag,
|
|
/** 工具 */
|
|
utils: {
|
|
name: 'utils',
|
|
displayName: '工具',
|
|
color: '#A36FFD',
|
|
icon: 'mdi-rocket-launch-outline',
|
|
order: 5,
|
|
} as ComponentTag,
|
|
/** 触摸 */
|
|
touch: {
|
|
name: 'touch',
|
|
displayName: '触摸',
|
|
color: '#78909C',
|
|
icon: 'mdi-gesture-tap-button',
|
|
order: 6,
|
|
} as ComponentTag,
|
|
/** 实验性 */
|
|
experimental: {
|
|
name: 'experimental',
|
|
displayName: '实验',
|
|
color: '#FF5722',
|
|
icon: 'mdi-flask-outline',
|
|
order: 7,
|
|
} as ComponentTag,
|
|
/** 通用 */
|
|
general: {
|
|
name: 'general',
|
|
displayName: '通用',
|
|
color: '#888',
|
|
icon: 'mdi-progress-wrench',
|
|
order: 8,
|
|
} as ComponentTag,
|
|
}
|
|
|
|
/**
|
|
* 从 OptionalOptionsMetadata 中获取 Options 信息。
|
|
* 当其为 undefined 时,返回类型 EmptyOptions。
|
|
*/
|
|
export type OptionsFromOptionalMeta<M extends OptionalOptionsMetadata> = (
|
|
M extends undefined | Record<string, never> ? EmptyOptions :
|
|
M extends OptionsMetadata<infer O> ? O : never
|
|
)
|
|
|
|
/** 组件入口函数的参数 */
|
|
export interface ComponentEntryContext<
|
|
Om extends OptionalOptionsMetadata = OptionalOptionsMetadata
|
|
> {
|
|
/** 当前组件的设置 */
|
|
settings: ComponentSettings<OptionsFromOptionalMeta<Om>>
|
|
/** 当前组件的信息 */
|
|
metadata: ComponentMetadata<Om>
|
|
/** 核心 API */
|
|
coreApis: CoreApis
|
|
}
|
|
|
|
/** 组件入口函数 */
|
|
export type ComponentEntry<
|
|
Om extends OptionalOptionsMetadata = OptionalOptionsMetadata,
|
|
T = unknown
|
|
> = (
|
|
context: ComponentEntryContext<Om>
|
|
) => T | Promise<T>
|
|
|
|
/** 带有函数/复杂对象的组件信息 */
|
|
export interface FunctionalMetadata<
|
|
Om extends OptionalOptionsMetadata = OptionalOptionsMetadata
|
|
> {
|
|
/** 主入口, 重新开启时不会再运行 */
|
|
entry: ComponentEntry<Om>
|
|
/** 导出小组件 */
|
|
widget?: Omit<Widget, 'name'>
|
|
/** 首屏样式, 会尽快注入 (before DCL) */
|
|
instantStyles?: {
|
|
/** 样式ID */
|
|
name: string
|
|
/** 样式内容, 可以是一个导入样式的函数 */
|
|
style: string | (() => Promise<{ default: string }>)
|
|
/** 设为`true`则注入到`document.body`末尾, 否则注入到`document.head`末尾 */
|
|
important?: boolean
|
|
}[]
|
|
/** 重新开启时执行 */
|
|
reload?: Executable
|
|
/** 关闭时执行 */
|
|
unload?: Executable
|
|
/** 插件化数据定义 */
|
|
plugin?: Optional<PluginMinimalData, 'name'>
|
|
/** 额外想要展示在设置里的选项 UI */
|
|
extraOptions?: () => Promise<VueModule>
|
|
/** 设置匹配的URL, 不匹配则不运行此组件 */
|
|
urlInclude?: TestPattern
|
|
/** 设置不匹配的URL, 不匹配则不运行此组件, 优先级高于`urlInclude` */
|
|
urlExclude?: TestPattern
|
|
}
|
|
|
|
/** ComponentMetadata 的类型参数,用于表达其可选参数 options 的类型 */
|
|
export type OptionalOptionsMetadata<O extends UnknownOptions = UnknownOptions> = (
|
|
OptionsMetadata<O> | undefined
|
|
)
|
|
|
|
/** 组件基本信息 */
|
|
export interface ComponentMetadata<
|
|
Om extends OptionalOptionsMetadata = OptionalOptionsMetadata
|
|
> extends FeatureBase, FunctionalMetadata<Om> {
|
|
/** 组件名称 */
|
|
name: string
|
|
/** 显示名称 */
|
|
displayName: string
|
|
/** 标签 */
|
|
tags: ComponentTag[]
|
|
/** 是否默认开启, 省略时为 true */
|
|
enabledByDefault?: boolean
|
|
/** 是否可更改, 不可更改时启用状态固定为 `enabledByDefault` 的值 */
|
|
configurable?: boolean
|
|
/** 是否在设置界面中隐藏 (代码仍可操作) */
|
|
hidden?: boolean
|
|
/** 组件子选项 */
|
|
options?: Om
|
|
/** i18n 数据 */
|
|
i18n?: Record<string, LanguagePack>
|
|
}
|
|
|
|
/** 用户组件的非函数基本信息, 用于直接保存为 JSON */
|
|
export type UserComponentMetadata = Omit<ComponentMetadata, keyof FunctionalMetadata>
|