mirror of
https://github.com/the1812/Bilibili-Evolved.git
synced 2025-11-04 21:22:45 +08:00
111 lines
3.4 KiB
TypeScript
111 lines
3.4 KiB
TypeScript
import { createPopper, Instance as Popper } from '@popperjs/core'
|
|
import { VueModule, Executable } from '@/core/common-types'
|
|
import { getComponentSettings, addComponentListener } from '@/core/settings'
|
|
import type { CustomNavbarOptions } from '.'
|
|
import { getUID } from '@/core/utils'
|
|
|
|
export const CustomNavbarItems = 'customNavbar.items'
|
|
export const CustomNavbarRenderedItems = 'customNavbar.renderedItems'
|
|
/**
|
|
* 表示自定义顶栏元素的基本信息
|
|
*/
|
|
export interface CustomNavbarItemInit {
|
|
/** 名称 */
|
|
name: string
|
|
/** 显示名称 */
|
|
displayName: string
|
|
/** 内容 */
|
|
content: Executable<VueModule> | string
|
|
|
|
/** 设定CSS flex样式 (grow, shrink, basis) */
|
|
flexStyle?: string
|
|
/** 禁用状态下不响应点击, 也不显示弹窗 */
|
|
disabled?: boolean
|
|
/** 点击打开的链接 */
|
|
href?: string
|
|
/** 表示此元素是否代表当前页面, 会增加显示一个底部的边框, 并加粗文本 */
|
|
active?: boolean
|
|
/** `content`指定的内容mount之后要执行的代码 */
|
|
contentMounted?: (item: CustomNavbarItem) => Promise<void> | void
|
|
/** 点击运行的代码段 */
|
|
clickAction?: Executable
|
|
/** 获取或设置提示数字, 将显示在顶部 */
|
|
notifyCount?: number
|
|
/** 是否在触屏状态下不响应点击 */
|
|
touch?: boolean
|
|
/** 是否仅在登录后显示 */
|
|
loginRequired?: boolean
|
|
|
|
/** 弹窗内容 */
|
|
popupContent?: Executable<VueModule>
|
|
/** 设为大于0的值时, 表示预计的弹窗宽度, 将会用于边缘检测, 防止超出viewport */
|
|
boundingWidth?: number
|
|
/** 不使用默认的弹窗padding */
|
|
noPopupPadding?: boolean
|
|
/** 是否使用透明的弹窗背景 */
|
|
transparentPopup?: boolean
|
|
/** 是否懒加载弹窗 */
|
|
lazy?: boolean
|
|
}
|
|
/** 表示自定义顶栏元素 */
|
|
export class CustomNavbarItem implements Required<CustomNavbarItemInit> {
|
|
name: string
|
|
displayName: string
|
|
content: Executable<VueModule> | string
|
|
|
|
flexStyle = '0 0 auto'
|
|
disabled = false
|
|
href: string = null
|
|
active = false
|
|
clickAction: Executable = none
|
|
contentMounted: (item: CustomNavbarItem) => Promise<void> | void = none
|
|
notifyCount = 0
|
|
touch = false
|
|
loginRequired = false
|
|
|
|
popupContent: Executable<VueModule> = null
|
|
popper: Popper = null
|
|
boundingWidth = 0
|
|
noPopupPadding = false
|
|
transparentPopup = false
|
|
lazy = true
|
|
|
|
hidden = false
|
|
order = 0
|
|
requestedPopup: boolean
|
|
|
|
static navbarOptions = getComponentSettings('customNavbar').options as CustomNavbarOptions
|
|
constructor(init: CustomNavbarItemInit) {
|
|
Object.assign(this, init)
|
|
if (!this.name) {
|
|
throw new Error('Missing CustomNavbarItem name')
|
|
}
|
|
if (this.content === undefined) {
|
|
throw new Error('Missing CustomNavbarItem content')
|
|
}
|
|
|
|
addComponentListener(
|
|
'customNavbar.touch',
|
|
(value: boolean) => {
|
|
this.touch = value ? init.touch : false
|
|
},
|
|
true,
|
|
)
|
|
this.hidden =
|
|
CustomNavbarItem.navbarOptions.hidden.includes(this.name) || (!getUID() && init.loginRequired)
|
|
const orderMap = CustomNavbarItem.navbarOptions.order
|
|
this.order = orderMap[this.name] || 0
|
|
this.requestedPopup = !this.lazy
|
|
}
|
|
|
|
get element() {
|
|
return dq(`.custom-navbar-item[data-name='${this.name}']`) as HTMLElement
|
|
}
|
|
toString() {
|
|
return this.name
|
|
}
|
|
usePopper(container: HTMLElement, popup: HTMLElement) {
|
|
this.popper = createPopper(container, popup, { placement: 'bottom' })
|
|
}
|
|
}
|