mirror of
https://github.com/the1812/Bilibili-Evolved.git
synced 2025-11-04 21:22:45 +08:00
Use type Component as vue component in custom-navbar-item.ts
This commit is contained in:
parent
d24fbdd89a
commit
7ed9ced13d
@ -56,10 +56,11 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import type { ComponentPublicInstance, Ref } from 'vue'
|
||||
import type { Ref } from 'vue'
|
||||
import { defineComponent, ref } from 'vue'
|
||||
import { addComponentListener, removeComponentListener } from '@/core/settings'
|
||||
|
||||
import type { PopupContentInstance } from './custom-navbar-item'
|
||||
import { CustomNavbarItem } from './custom-navbar-item'
|
||||
import CustomNavbarLink from './CustomNavbarLink.vue'
|
||||
|
||||
@ -71,6 +72,22 @@ const isOpenInNewTab = (item: CustomNavbarItem) => {
|
||||
}
|
||||
return options.openInNewTab
|
||||
}
|
||||
function trigger(this: InstanceType<typeof ThisComponent>, initialPopup: boolean) {
|
||||
const { popup } = this
|
||||
if (!popup) {
|
||||
return
|
||||
}
|
||||
const allowRefresh =
|
||||
CustomNavbarItem.navbarOptions.refreshOnPopup &&
|
||||
popup.popupRefresh &&
|
||||
typeof popup.popupRefresh === 'function'
|
||||
if (!initialPopup && allowRefresh) {
|
||||
popup.popupRefresh()
|
||||
}
|
||||
if (popup.popupShow && typeof popup.popupShow === 'function') {
|
||||
popup.popupShow()
|
||||
}
|
||||
}
|
||||
const ThisComponent = defineComponent({
|
||||
components: {
|
||||
CustomNavbarLink,
|
||||
@ -82,7 +99,7 @@ const ThisComponent = defineComponent({
|
||||
},
|
||||
},
|
||||
setup: () => ({
|
||||
popup: ref(null) as Ref<ComponentPublicInstance | null>,
|
||||
popup: ref(null) as Ref<PopupContentInstance | null>,
|
||||
popupContainer: ref(null) as Ref<HTMLDivElement | null>,
|
||||
}),
|
||||
data() {
|
||||
@ -126,22 +143,10 @@ const ThisComponent = defineComponent({
|
||||
'iframe-container': item.iframeName,
|
||||
}
|
||||
},
|
||||
triggerPopupShow: lodash.debounce(function trigger(this: InstanceType<typeof ThisComponent>, initialPopup: boolean) {
|
||||
const { popup } = this
|
||||
if (!popup) {
|
||||
return
|
||||
}
|
||||
const allowRefresh =
|
||||
CustomNavbarItem.navbarOptions.refreshOnPopup &&
|
||||
popup.popupRefresh &&
|
||||
typeof popup.popupRefresh === 'function'
|
||||
if (!initialPopup && allowRefresh) {
|
||||
popup.popupRefresh()
|
||||
}
|
||||
if (popup.popupShow && typeof popup.popupShow === 'function') {
|
||||
popup.popupShow()
|
||||
}
|
||||
}, 300) as unknown as (initialPopup: boolean) => void,
|
||||
triggerPopupShow: lodash.debounce(trigger, 300) as unknown as (
|
||||
this: any,
|
||||
initialPopup: boolean,
|
||||
) => void,
|
||||
async requestPopup() {
|
||||
const { item } = this as {
|
||||
item: CustomNavbarItem
|
||||
|
||||
@ -1,11 +1,23 @@
|
||||
import type { Instance as Popper } from '@popperjs/core'
|
||||
import { createPopper } from '@popperjs/core'
|
||||
|
||||
import type { Executable, ImportedVueComponent } from '@/core/common-types'
|
||||
import type { Component, ComponentPublicInstance } from 'vue'
|
||||
import type { Executable } from '@/core/common-types'
|
||||
import { addComponentListener, getComponentSettings } from '@/core/settings'
|
||||
|
||||
import type { CustomNavbarOptions } from '.'
|
||||
|
||||
export interface PopupContentInstance
|
||||
extends ComponentPublicInstance<{
|
||||
container?: HTMLElement
|
||||
item?: CustomNavbarItem
|
||||
}> {
|
||||
popupRefresh?(): void
|
||||
popupShow(): void
|
||||
}
|
||||
|
||||
export type PopupContent = Component & (new () => PopupContentInstance)
|
||||
|
||||
export const CustomNavbarItems = 'customNavbar.items'
|
||||
export const CustomNavbarRenderedItems = 'customNavbar.renderedItems'
|
||||
/**
|
||||
@ -17,7 +29,7 @@ export interface CustomNavbarItemInit {
|
||||
/** 显示名称 */
|
||||
displayName: string
|
||||
/** 内容 */
|
||||
content: Executable<ImportedVueComponent> | string
|
||||
content: Component<{ item?: CustomNavbarItem }> | string
|
||||
|
||||
/** 设定CSS flex样式 (grow, shrink, basis) */
|
||||
flexStyle?: string
|
||||
@ -39,7 +51,7 @@ export interface CustomNavbarItemInit {
|
||||
loginRequired?: boolean
|
||||
|
||||
/** 弹窗内容 */
|
||||
popupContent?: Executable<ImportedVueComponent>
|
||||
popupContent?: PopupContent | undefined
|
||||
/** 设为大于0的值时, 表示预计的弹窗宽度, 将会用于边缘检测, 防止超出viewport */
|
||||
boundingWidth?: number
|
||||
/** 不使用默认的弹窗padding */
|
||||
@ -53,7 +65,7 @@ export interface CustomNavbarItemInit {
|
||||
export class CustomNavbarItem implements Required<CustomNavbarItemInit> {
|
||||
name: string
|
||||
displayName: string
|
||||
content: Executable<ImportedVueComponent> | string
|
||||
content: Component<{ item?: CustomNavbarItem }> | string
|
||||
|
||||
flexStyle = '0 0 auto'
|
||||
disabled = false
|
||||
@ -65,7 +77,7 @@ export class CustomNavbarItem implements Required<CustomNavbarItemInit> {
|
||||
touch = false
|
||||
loginRequired = false
|
||||
|
||||
popupContent: Executable<ImportedVueComponent> = null
|
||||
popupContent: PopupContent | undefined
|
||||
popper: Popper = null
|
||||
boundingWidth = 0
|
||||
noPopupPadding = false
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
import { getUID } from '@/core/utils'
|
||||
|
||||
import type { CustomNavbarItemInit } from '../custom-navbar-item'
|
||||
@ -15,5 +16,5 @@ export const favorites: CustomNavbarItemInit = {
|
||||
|
||||
boundingWidth: 380,
|
||||
noPopupPadding: true,
|
||||
popupContent: () => import('./NavbarFavorites.vue').then(m => m.default),
|
||||
popupContent: defineAsyncComponent(() => import('./NavbarFavorites.vue')),
|
||||
}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
import type { CustomNavbarItemInit } from '../custom-navbar-item'
|
||||
|
||||
export const feeds: CustomNavbarItemInit = {
|
||||
@ -20,7 +21,7 @@ export const feeds: CustomNavbarItemInit = {
|
||||
},
|
||||
loginRequired: true,
|
||||
|
||||
popupContent: () => import('./NavbarFeeds.vue').then(m => m.default),
|
||||
popupContent: defineAsyncComponent(() => import('./NavbarFeeds.vue')),
|
||||
boundingWidth: 300,
|
||||
noPopupPadding: true,
|
||||
}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
import type { CustomNavbarItemInit } from '../custom-navbar-item'
|
||||
|
||||
const href = 'https://www.bilibili.com/account/history'
|
||||
@ -13,5 +14,5 @@ export const history: CustomNavbarItemInit = {
|
||||
|
||||
boundingWidth: 400,
|
||||
noPopupPadding: true,
|
||||
popupContent: () => import('./NavbarHistory.vue').then(m => m.default),
|
||||
popupContent: defineAsyncComponent(() => import('./NavbarHistory.vue')),
|
||||
}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
import type { CustomNavbarItemInit } from '../custom-navbar-item'
|
||||
|
||||
export const home: CustomNavbarItemInit = {
|
||||
@ -9,5 +10,5 @@ export const home: CustomNavbarItemInit = {
|
||||
touch: true,
|
||||
|
||||
boundingWidth: 366,
|
||||
popupContent: () => import('./NavbarHome.vue').then(m => m.default),
|
||||
popupContent: defineAsyncComponent(() => import('./NavbarHome.vue')),
|
||||
}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
import type { CustomNavbarItemInit } from '../custom-navbar-item'
|
||||
|
||||
interface NavbarIframeConfig {
|
||||
@ -16,7 +17,7 @@ const getIframeItem = (config: NavbarIframeConfig): CustomNavbarItemInit & Navba
|
||||
|
||||
touch: true,
|
||||
|
||||
popupContent: () => import('./IframePopup.vue').then(m => m.default),
|
||||
popupContent: defineAsyncComponent(() => import('./IframePopup.vue')),
|
||||
boundingWidth: config.width,
|
||||
noPopupPadding: true,
|
||||
transparentPopup: true,
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
import type { CustomNavbarItemInit } from '../custom-navbar-item'
|
||||
|
||||
export const logo: CustomNavbarItemInit = {
|
||||
name: 'logo',
|
||||
displayName: 'Logo',
|
||||
content: () => import('./NavbarLogo.vue').then(m => m.default),
|
||||
content: defineAsyncComponent(() => import('./NavbarLogo.vue')),
|
||||
|
||||
href: 'https://www.bilibili.com/',
|
||||
}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
import type { CustomNavbarItemInit } from '../custom-navbar-item'
|
||||
|
||||
const messagesUrl = 'https://message.bilibili.com/'
|
||||
@ -11,6 +12,6 @@ export const messages: CustomNavbarItemInit = {
|
||||
loginRequired: true,
|
||||
touch: true,
|
||||
|
||||
popupContent: () => import('./NavbarMessages.vue').then(m => m.default),
|
||||
popupContent: defineAsyncComponent(() => import('./NavbarMessages.vue')),
|
||||
lazy: false,
|
||||
}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
import type { CustomNavbarItemInit } from '../custom-navbar-item'
|
||||
|
||||
const rankingUrl = 'https://www.bilibili.com/v/popular/rank/'
|
||||
@ -10,5 +11,5 @@ export const ranking: CustomNavbarItemInit = {
|
||||
active: document.URL.startsWith(rankingUrl),
|
||||
touch: true,
|
||||
|
||||
popupContent: () => import('./NavbarRanking.vue').then(m => m.default),
|
||||
popupContent: defineAsyncComponent(() => import('./NavbarRanking.vue')),
|
||||
}
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
import type { CustomNavbarItemInit } from '../custom-navbar-item'
|
||||
|
||||
export const search: CustomNavbarItemInit = {
|
||||
name: 'search',
|
||||
displayName: '搜索',
|
||||
content: () => import('./NavbarSearch.vue').then(m => m.default),
|
||||
content: defineAsyncComponent(() => import('./NavbarSearch.vue')),
|
||||
|
||||
// 禁用元素本身的 hover 效果之类的, 作为 content 的 NavbarSearch 是依然能够响应的
|
||||
disabled: true,
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
import { getUID } from '@/core/utils'
|
||||
|
||||
import type { CustomNavbarItemInit } from '../custom-navbar-item'
|
||||
@ -23,5 +24,5 @@ export const subscriptions: CustomNavbarItemInit = {
|
||||
|
||||
boundingWidth: 380,
|
||||
noPopupPadding: true,
|
||||
popupContent: () => import('./NavbarSubscriptions.vue').then(m => m.default),
|
||||
popupContent: defineAsyncComponent(() => import('./NavbarSubscriptions.vue')),
|
||||
}
|
||||
|
||||
@ -1,12 +1,13 @@
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
import type { CustomNavbarItemInit } from '../custom-navbar-item'
|
||||
|
||||
export const upload: CustomNavbarItemInit = {
|
||||
name: 'upload',
|
||||
displayName: '投稿',
|
||||
content: () => import('./NavbarUpload.vue').then(m => m.default),
|
||||
content: defineAsyncComponent(() => import('./NavbarUpload.vue')),
|
||||
|
||||
touch: true,
|
||||
href: 'https://member.bilibili.com/platform/upload/video/frame',
|
||||
|
||||
popupContent: () => import('./UploadPopup.vue').then(m => m.default),
|
||||
popupContent: defineAsyncComponent(() => import('./UploadPopup.vue')),
|
||||
}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
import { getUID } from '@/core/utils'
|
||||
|
||||
import type { CustomNavbarItemInit } from '../custom-navbar-item'
|
||||
@ -5,12 +6,12 @@ import type { CustomNavbarItemInit } from '../custom-navbar-item'
|
||||
export const userInfo: CustomNavbarItemInit = {
|
||||
name: 'userInfo',
|
||||
displayName: '个人信息',
|
||||
content: () => import('./UserFace.vue').then(m => m.default),
|
||||
content: defineAsyncComponent(() => import('./UserFace.vue')),
|
||||
|
||||
href: getUID() ? 'https://space.bilibili.com' : null,
|
||||
touch: true,
|
||||
|
||||
popupContent: () => import('./UserInfoPopup.vue').then(m => m.default),
|
||||
popupContent: defineAsyncComponent(() => import('./UserInfoPopup.vue')),
|
||||
lazy: false,
|
||||
noPopupPadding: true,
|
||||
boundingWidth: 240,
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
import type { CustomNavbarItemInit } from '../custom-navbar-item'
|
||||
|
||||
export const watchlater: CustomNavbarItemInit = {
|
||||
@ -12,5 +13,5 @@ export const watchlater: CustomNavbarItemInit = {
|
||||
|
||||
boundingWidth: 380,
|
||||
noPopupPadding: true,
|
||||
popupContent: () => import('./NavbarWatchlater.vue').then(m => m.default),
|
||||
popupContent: defineAsyncComponent(() => import('./NavbarWatchlater.vue')),
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import type { CustomNavbarOptions } from 'registry/lib/components/style/custom-navbar'
|
||||
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
import { getComponentSettings } from '@/core/settings'
|
||||
import type { PluginMetadata } from '@/plugins/plugin'
|
||||
|
||||
@ -23,7 +24,7 @@ export const plugin: PluginMetadata = {
|
||||
items.push({
|
||||
name: 'channel',
|
||||
displayName: '频道',
|
||||
content: () => import('./NavbarChannel.vue'),
|
||||
content: defineAsyncComponent(() => import('./NavbarChannel.vue')),
|
||||
clickAction: () => {
|
||||
const channelId = dq('.navbar-channel').getAttribute('data-channel-id')
|
||||
window.open(
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
import type { PluginMetadata } from '@/plugins/plugin'
|
||||
|
||||
import type { CustomNavbarItemInit } from '../../../components/style/custom-navbar/custom-navbar-item'
|
||||
@ -12,7 +13,7 @@ export const plugin: PluginMetadata = {
|
||||
items.push({
|
||||
name: 'darkMode',
|
||||
displayName: '夜间开关',
|
||||
content: () => import('./NavbarDarkMode.vue'),
|
||||
content: defineAsyncComponent(() => import('./NavbarDarkMode.vue')),
|
||||
|
||||
clickAction: () => {
|
||||
const settings = getComponentSettings('darkMode')
|
||||
|
||||
Loading…
Reference in New Issue
Block a user