fix: top bar covering content (#1235)

resolve #1235
This commit is contained in:
Hakadao
2025-01-02 02:13:23 +08:00
parent 1e34b8c624
commit dd50659355
9 changed files with 154 additions and 33 deletions

View File

@@ -25,17 +25,19 @@ const openMode = computed(() => {
return 'newTab'
})
// Since BewlyBewly sometimes uses an iframe to open the original Bilibili page in the current tab
// please set the target to `_top` instead of `_self`
const target = computed(() => {
if (openMode.value === 'newTab') {
return '_blank'
}
if (openMode.value === 'currentTabIfNotHomepage') {
return isHomePage() ? '_blank' : '_self'
return isHomePage() ? '_blank' : '_top'
}
if (openMode.value === 'currentTab') {
return '_self'
return '_top'
}
return '_self'
return '_top'
})
function handleClick(event: MouseEvent) {

View File

@@ -488,6 +488,7 @@ defineExpose({
>
<a
ref="logo" href="//www.bilibili.com"
target="_top"
class="group logo"
:class="{ activated: popupVisible.channels }"
style="backdrop-filter: var(--bew-filter-glass-1);"

View File

@@ -8,7 +8,7 @@ import { OVERLAY_SCROLL_BAR_SCROLL, TOP_BAR_VISIBILITY_CHANGE } from '~/constant
import { AppPage } from '~/enums/appEnums'
import { settings } from '~/logic'
import api from '~/utils/api'
import { getUserID, isHomePage } from '~/utils/main'
import { getUserID, isHomePage, isInIframe } from '~/utils/main'
import emitter from '~/utils/mitt'
import BewlyOrBiliPageSwitcher from './components/BewlyOrBiliPageSwitcher.vue'
@@ -67,6 +67,7 @@ const forceWhiteIcon = computed((): boolean => {
if (
// 首頁使用原生 bilibili 首頁時由於原版有 banner所以強制 icon 變白色用於區分背景
(isHomePage() && settings.value.useOriginalBilibiliHomepage)
|| (isInIframe() && isHomePage())
// 分區頁面由於上面有背景,所以強制 icon 變白色用於區分背景
// channel, anime, chinese anime, tv shows, movie, variety shows, mooc but not including video page
|| (
@@ -127,13 +128,15 @@ const showSearchBar = computed((): boolean => {
const isTopBarFixed = computed((): boolean => {
if (
(isHomePage() && settings.value.useOriginalBilibiliHomepage)
isHomePage()
// video page
|| /https?:\/\/(?:www.)?bilibili.com\/(?:video|list)\/.*/.test(location.href)
// anime playback & movie page
|| /https?:\/\/(?:www.)?bilibili.com\/bangumi\/play\/.*/.test(location.href)
// moment page
|| /https?:\/\/t.bilibili.com.*/.test(location.href)
// watch later page
|| /https?:\/\/(?:www\.)?bilibili\.com\/watchlater\/#\/list.*/.test(location.href)
// channel, anime, chinese anime, tv shows, movie, variety shows, mooc
|| /https?:\/\/(?:www.)?bilibili.com\/(?:v|anime|guochuang|tv|movie|variety|mooc).*/.test(location.href)
// articles page
@@ -486,6 +489,7 @@ defineExpose({
>
<a
ref="logo" href="//www.bilibili.com"
target="_top"
class="group logo"
:class="{
activated: popupVisible.channels,

View File

@@ -1,12 +1,14 @@
<script lang="ts" setup>
import { useBewlyApp } from '~/composables/useAppProvider'
import { IFRAME_PAGE_SWITCH_BEWLY, IFRAME_PAGE_SWITCH_BILI } from '~/constants/globalEvents'
import { settings } from '~/logic'
import { useMainStore } from '~/stores/mainStore'
import { isHomePage } from '~/utils/main'
// import { useSettingsStore } from '~/stores/settingsStore'
import { isInIframe } from '~/utils/main'
const { activatedPage } = useBewlyApp()
const { getDockItemByPage } = useMainStore()
// const { getDockItemConfigByPage } = useSettingsStore()
const options = readonly([
{
name: 'BewlyBewly',
@@ -20,8 +22,15 @@ const options = readonly([
},
])
const currentPage = computed(() => {
return settings.value.dockItemsConfig.find(dockItem => dockItem.page === activatedPage.value)
const showBewlyOrBiliPageSwitcher = computed(() => {
if (!isInIframe() && getDockItemByPage(activatedPage.value)?.hasBewlyPage)
return true
if (isInIframe())
return true
// const dockItemConfig = getDockItemConfigByPage(activatedPage.value)
// if (dockItemConfig?.useOriginalBiliPage && isInIframe())
// return true
return false
})
function switchPage(useOriginalBiliPage: boolean) {
@@ -29,12 +38,19 @@ function switchPage(useOriginalBiliPage: boolean) {
if (dockItem) {
dockItem.useOriginalBiliPage = useOriginalBiliPage
}
if (isInIframe()) {
if (useOriginalBiliPage)
parent.postMessage(IFRAME_PAGE_SWITCH_BILI, '*')
else
parent.postMessage(IFRAME_PAGE_SWITCH_BEWLY, '*')
}
}
</script>
<template>
<div
v-if="getDockItemByPage(activatedPage)?.hasBewlyPage && isHomePage() && !settings.useOriginalBilibiliHomepage"
v-if="showBewlyOrBiliPageSwitcher"
style="backdrop-filter: var(--bew-filter-glass-1);"
flex="~ gap-1" bg="$bew-elevated" p-1 rounded-full
h-34px
@@ -42,7 +58,7 @@ function switchPage(useOriginalBiliPage: boolean) {
<button
v-for="option in options" :key="option.name"
:class="{
active: option.useOriginalBiliPage === currentPage?.useOriginalBiliPage,
active: option.useOriginalBiliPage === isInIframe(),
}"
rounded-inherit text="$bew-text-2 hover:$bew-text-1 xs" p="x-2 lg:x-4" bg="hover:$bew-fill-2"
fw-bold duration-300

View File

@@ -3,3 +3,5 @@ export const OVERLAY_SCROLL_BAR_SCROLL = 'overlayScrollBarScroll'
export const BEWLY_MOUNTED = 'bewlyMounted'
export const DRAWER_VIDEO_ENTER_PAGE_FULL = 'drawerVideoEnterPageFull'
export const DRAWER_VIDEO_EXIT_PAGE_FULL = 'drawerVideoExitPageFull'
export const IFRAME_PAGE_SWITCH_BEWLY = 'iframePageSwitchBewly'
export const IFRAME_PAGE_SWITCH_BILI = 'iframePageSwitchBili'

View File

@@ -129,7 +129,6 @@ if (!settings.value.useOriginalBilibiliTopBar && isSupportedPages())
async function onDOMLoaded() {
let originalTopBar: HTMLElement | null = null
// DO NOT change the home page when in iframe because it will cause nested calls to the homepage
const changeHomePage = !isInIframe() && !settings.value.useOriginalBilibiliHomepage && isHomePage()
// Remove the original Bilibili homepage if in Bilibili homepage & useOriginalBilibiliHomepage is enabled
@@ -153,7 +152,7 @@ async function onDOMLoaded() {
if (isSupportedPages()) {
// Then inject the app
if (changeHomePage) {
if (isHomePage()) {
injectApp()
}
else {

View File

@@ -1,19 +1,21 @@
<script setup lang="ts">
import { useThrottleFn, useToggle } from '@vueuse/core'
import { useEventListener, useThrottleFn, useToggle } from '@vueuse/core'
import type { Ref } from 'vue'
import type { BewlyAppProvider } from '~/composables/useAppProvider'
import { useDark } from '~/composables/useDark'
import { BEWLY_MOUNTED, DRAWER_VIDEO_ENTER_PAGE_FULL, DRAWER_VIDEO_EXIT_PAGE_FULL, OVERLAY_SCROLL_BAR_SCROLL } from '~/constants/globalEvents'
import { BEWLY_MOUNTED, DRAWER_VIDEO_ENTER_PAGE_FULL, DRAWER_VIDEO_EXIT_PAGE_FULL, IFRAME_PAGE_SWITCH_BEWLY, IFRAME_PAGE_SWITCH_BILI, OVERLAY_SCROLL_BAR_SCROLL } from '~/constants/globalEvents'
import { AppPage } from '~/enums/appEnums'
import { settings } from '~/logic'
import { type DockItem, useMainStore } from '~/stores/mainStore'
import { useSettingsStore } from '~/stores/settingsStore'
import { isHomePage, isInIframe, openLinkToNewTab, queryDomUntilFound, scrollToTop } from '~/utils/main'
import emitter from '~/utils/mitt'
import { setupNecessarySettingsWatchers } from './necessarySettingsWatchers'
const mainStore = useMainStore()
const settingsStore = useSettingsStore()
const { isDark } = useDark()
const [showSettings, toggleSettings] = useToggle(false)
@@ -50,7 +52,24 @@ const iframeDrawerURL = ref<string>('')
const showIframeDrawer = ref<boolean>(false)
const iframePageRef = ref()
useEventListener(window, 'message', ({ data }) => {
switch (data) {
case IFRAME_PAGE_SWITCH_BEWLY:
{
const currentDockItemConfig = settingsStore.getDockItemConfigByPage(activatedPage.value)
if (currentDockItemConfig)
currentDockItemConfig.useOriginalBiliPage = false
}
break
case IFRAME_PAGE_SWITCH_BILI:
{
const currentDockItemConfig = settingsStore.getDockItemConfigByPage(activatedPage.value)
if (currentDockItemConfig)
currentDockItemConfig.useOriginalBiliPage = true
}
break
}
})
const iframePageURL = computed((): string => {
// If the iframe is not the BiliBili homepage or in iframe, then don't show the iframe page
if (!isHomePage(window.self.location.href) || isInIframe())
@@ -61,7 +80,6 @@ const iframePageURL = computed((): string => {
}
return ''
})
const showBewlyPage = computed((): boolean => {
if (isInIframe())
return false
@@ -73,7 +91,7 @@ const showBewlyPage = computed((): boolean => {
if (iframePageURL.value)
return false
return isHomePage() && !isInIframe() && !settings.value.useOriginalBilibiliHomepage
return isHomePage() && !settings.value.useOriginalBilibiliHomepage
})
const isFirstTimeActivatedPageChange = ref<boolean>(true)
@@ -205,6 +223,18 @@ function openIframeDrawer(url: string) {
showIframeDrawer.value = true
}
/**
* Checks if the current viewport has a scrollbar.
* @returns {boolean} Returns true if the viewport has a scrollbar, false otherwise.
*/
async function haveScrollbar() {
await nextTick()
const osInstance = scrollbarRef.value?.osInstance()
const { viewport } = osInstance.elements()
const { scrollHeight } = viewport // get scroll offset
return scrollHeight > window.innerHeight
}
// In drawer video, watch btn className changed and post message to parent
watchEffect(async (onCleanUp) => {
if (!isInIframe())
@@ -234,18 +264,6 @@ watchEffect(async (onCleanUp) => {
})
})
/**
* Checks if the current viewport has a scrollbar.
* @returns {boolean} Returns true if the viewport has a scrollbar, false otherwise.
*/
async function haveScrollbar() {
await nextTick()
const osInstance = scrollbarRef.value?.osInstance()
const { viewport } = osInstance.elements()
const { scrollHeight } = viewport // get scroll offset
return scrollHeight > window.innerHeight
}
provide<BewlyAppProvider>('BEWLY_APP', {
activatedPage,
mainAppRef,
@@ -300,7 +318,20 @@ provide<BewlyAppProvider>('BEWLY_APP', {
</div>
<!-- TopBar -->
<div v-if="!isInIframe()" m-auto max-w="$bew-page-max-width">
<div
v-if="
// When the user switches to the original Bilibili page, BewlyBewly will only show the top bar inside the iframe.
// This helps prevent the outside top bar from covering the contents.
// reference: https://github.com/BewlyBewly/BewlyBewly/issues/1235
// when on home page and not using original bilibili page, show top bar
(isHomePage() && !settingsStore.getDockItemIsUseOriginalBiliPage(activatedPage) && !isInIframe())
// when in iframe and using original bilibili page, show top bar
|| (settingsStore.getDockItemIsUseOriginalBiliPage(activatedPage) && isInIframe())
// when not on home page, show top bar
|| !isHomePage()"
m-auto max-w="$bew-page-max-width"
>
<OldTopBar
v-if="settings.useOldTopBar"
pos="top-0 left-0" z="99 hover:1001" w-full
@@ -312,12 +343,13 @@ provide<BewlyAppProvider>('BEWLY_APP', {
</div>
<div
v-if="!settings.useOriginalBilibiliHomepage"
pos="absolute top-0 left-0" w-full h-full
:style="{
height: showBewlyPage || iframePageURL ? '100dvh' : '0',
}"
>
<template v-if="!iframePageURL && showBewlyPage && activatedPage">
<template v-if="showBewlyPage">
<OverlayScrollbarsComponent ref="scrollbarRef" element="div" h-inherit defer @os-scroll="handleOsScroll">
<main m-auto max-w="$bew-page-max-width">
<div
@@ -338,7 +370,7 @@ provide<BewlyAppProvider>('BEWLY_APP', {
</main>
</OverlayScrollbarsComponent>
</template>
<IframePage v-if="iframePageURL" ref="iframePageRef" :url="iframePageURL" />
<IframePage v-else-if="iframePageURL && !isInIframe()" ref="iframePageRef" :url="iframePageURL" />
</div>
<IframeDrawer

View File

@@ -0,0 +1,23 @@
import { defineStore } from 'pinia'
import type { AppPage } from '~/enums/appEnums'
import { settings } from '~/logic'
export interface DockItemConfig {
page: AppPage
visible: boolean
openInNewTab: boolean
useOriginalBiliPage: boolean
}
export const useSettingsStore = defineStore('settings', () => {
function getDockItemConfigByPage(page: AppPage): DockItemConfig | undefined {
return settings.value.dockItemsConfig.find(e => e.page === page)
}
function getDockItemIsUseOriginalBiliPage(page: AppPage): boolean {
return settings.value.dockItemsConfig.find(e => e.page === page)?.useOriginalBiliPage || false
}
return { getDockItemConfigByPage, getDockItemIsUseOriginalBiliPage }
})

View File

@@ -0,0 +1,42 @@
import browser from 'webextension-polyfill'
import type { AppPage } from '~/enums/appEnums'
import { useSettingsStore } from '~/stores/settingsStore'
const { getDockItemConfigByPage } = useSettingsStore()
interface Message {
contentScriptQuery: string
[key: string]: any
}
export enum IFRAME_MESSAGE {
IFRAME_CHANGE_PAGE_MODE = 'iframeChangePageMode',
}
export function iframeChangePageMode(page: AppPage, useOriginalBiliPage: boolean) {
browser.runtime.sendMessage({
contentScriptQuery: IFRAME_MESSAGE.IFRAME_CHANGE_PAGE_MODE,
page,
useOriginalBiliPage,
})
}
function handleMessage(message: Message) {
if (message.contentScriptQuery === IFRAME_MESSAGE.IFRAME_CHANGE_PAGE_MODE) {
const { page, useOriginalBiliPage } = message
const dockItemConfig = getDockItemConfigByPage(page)
if (dockItemConfig) {
dockItemConfig.useOriginalBiliPage = useOriginalBiliPage
}
}
}
export function setupIframeMsgLstnrs() {
browser.runtime.onMessage.removeListener(handleConnect)
browser.runtime.onMessage.addListener(handleConnect)
}
function handleConnect() {
browser.runtime.onMessage.removeListener(handleMessage)
browser.runtime.onMessage.addListener(handleMessage)
}