mirror of
https://github.com/BewlyBewly/BewlyBewly.git
synced 2025-04-14 13:15:29 +00:00
Co-authored-by: Hakadao <a578457889743@gmail.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { onKeyStroke, useEventListener } from '@vueuse/core'
|
||||
|
||||
import { DRAWER_VIDEO_ENTER_PAGE_FULL, DRAWER_VIDEO_EXIT_PAGE_FULL } from '~/constants/globalEvents'
|
||||
import { isHomePage } from '~/utils/main'
|
||||
|
||||
// TODO: support shortcuts like `Ctrl+Alt+T` to open in new tab, `Esc` to close
|
||||
@@ -15,9 +16,13 @@ const emit = defineEmits<{
|
||||
}>()
|
||||
|
||||
const show = ref(false)
|
||||
const headerShow = ref(false)
|
||||
const iframeRef = ref<HTMLIFrameElement | null>(null)
|
||||
const currentUrl = ref<string>(props.url)
|
||||
const delayCloseTimer = ref<NodeJS.Timeout | null>(null)
|
||||
const inIframe = computed((): boolean => {
|
||||
return window.self !== window.top
|
||||
})
|
||||
|
||||
useEventListener(window, 'popstate', updateIframeUrl)
|
||||
nextTick(() => {
|
||||
@@ -27,6 +32,7 @@ nextTick(() => {
|
||||
onMounted(async () => {
|
||||
history.pushState(null, '', props.url)
|
||||
show.value = true
|
||||
headerShow.value = true
|
||||
await nextTick()
|
||||
iframeRef.value?.focus()
|
||||
})
|
||||
@@ -69,6 +75,7 @@ async function handleClose() {
|
||||
}
|
||||
await releaseIframeResources()
|
||||
show.value = false
|
||||
headerShow.value = false
|
||||
delayCloseTimer.value = setTimeout(() => {
|
||||
emit('close')
|
||||
}, 300)
|
||||
@@ -95,10 +102,13 @@ function handleOpenInNewTab() {
|
||||
|
||||
const isEscPressed = ref<boolean>(false)
|
||||
const escPressedTimer = ref<NodeJS.Timeout | null>(null)
|
||||
const disableEscPress = ref<boolean>(false)
|
||||
|
||||
nextTick(() => {
|
||||
onKeyStroke('Escape', (e: KeyboardEvent) => {
|
||||
e.preventDefault()
|
||||
if (disableEscPress.value)
|
||||
return
|
||||
if (isEscPressed.value) {
|
||||
handleClose()
|
||||
}
|
||||
@@ -114,6 +124,24 @@ nextTick(() => {
|
||||
}, { target: iframeRef.value?.contentWindow })
|
||||
})
|
||||
|
||||
watchEffect(() => {
|
||||
if (inIframe.value)
|
||||
return null
|
||||
|
||||
useEventListener(window, 'message', ({ data }) => {
|
||||
switch (data) {
|
||||
case DRAWER_VIDEO_ENTER_PAGE_FULL:
|
||||
headerShow.value = false
|
||||
disableEscPress.value = true
|
||||
break
|
||||
case DRAWER_VIDEO_EXIT_PAGE_FULL:
|
||||
headerShow.value = true
|
||||
disableEscPress.value = false
|
||||
break
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
// const keys = useMagicKeys()
|
||||
// const ctrlAltT = keys['Ctrl+Alt+T']
|
||||
|
||||
@@ -140,7 +168,7 @@ nextTick(() => {
|
||||
|
||||
<Transition name="fade">
|
||||
<div
|
||||
v-if="show"
|
||||
v-if="headerShow"
|
||||
pos="relative top-0" flex="~ items-center justify-end gap-2"
|
||||
max-w="$bew-page-max-width" w-full h="$bew-top-bar-height"
|
||||
m-auto px-4
|
||||
@@ -195,15 +223,18 @@ nextTick(() => {
|
||||
<Transition name="drawer">
|
||||
<div
|
||||
v-if="show"
|
||||
pos="absolute top-$bew-top-bar-height left-0" of-hidden bg="$bew-bg"
|
||||
:pos="`absolute ${headerShow ? 'top-$bew-top-bar-height' : 'top-0'} left-0`" of-hidden bg="$bew-bg"
|
||||
rounded="t-$bew-radius" w-full h-full
|
||||
>
|
||||
<iframe
|
||||
ref="iframeRef"
|
||||
:src="currentUrl"
|
||||
:style="{
|
||||
bottom: headerShow ? `var(--bew-top-bar-height)` : '0',
|
||||
}"
|
||||
frameborder="0"
|
||||
pointer-events-auto
|
||||
pos="absolute bottom-$bew-top-bar-height left-0"
|
||||
pos="absolute left-0"
|
||||
w-full h-full
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
export const TOP_BAR_VISIBILITY_CHANGE = 'topBarVisibilityChange'
|
||||
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'
|
||||
|
||||
@@ -4,10 +4,10 @@ import type { Ref } from 'vue'
|
||||
|
||||
import type { BewlyAppProvider } from '~/composables/useAppProvider'
|
||||
import { useDark } from '~/composables/useDark'
|
||||
import { BEWLY_MOUNTED, OVERLAY_SCROLL_BAR_SCROLL } from '~/constants/globalEvents'
|
||||
import { BEWLY_MOUNTED, DRAWER_VIDEO_ENTER_PAGE_FULL, DRAWER_VIDEO_EXIT_PAGE_FULL, OVERLAY_SCROLL_BAR_SCROLL } from '~/constants/globalEvents'
|
||||
import { AppPage } from '~/enums/appEnums'
|
||||
import { settings } from '~/logic'
|
||||
import { isHomePage, scrollToTop } from '~/utils/main'
|
||||
import { isHomePage, queryDomUntilFound, scrollToTop } from '~/utils/main'
|
||||
import emitter from '~/utils/mitt'
|
||||
|
||||
import { setupNecessarySettingsWatchers } from './necessarySettingsWatchers'
|
||||
@@ -127,6 +127,35 @@ function openIframeDrawer(url: string) {
|
||||
showIframeDrawer.value = true
|
||||
}
|
||||
|
||||
// In drawer video, watch btn className changed and post message to parent
|
||||
watchEffect(async (onCleanUp) => {
|
||||
if (!inIframe.value)
|
||||
return null
|
||||
|
||||
const observer = new MutationObserver(([{ target: el }]) => {
|
||||
if (!(el instanceof HTMLElement))
|
||||
return null
|
||||
if (el.classList.contains('bpx-state-entered')) {
|
||||
parent.postMessage(DRAWER_VIDEO_ENTER_PAGE_FULL)
|
||||
}
|
||||
else {
|
||||
parent.postMessage(DRAWER_VIDEO_EXIT_PAGE_FULL)
|
||||
}
|
||||
})
|
||||
|
||||
const abort = new AbortController()
|
||||
queryDomUntilFound('.bpx-player-ctrl-btn.bpx-player-ctrl-web', 500, abort).then((openVideo2WebFullBtn) => {
|
||||
if (!openVideo2WebFullBtn)
|
||||
return
|
||||
observer.observe(openVideo2WebFullBtn, { attributes: true })
|
||||
})
|
||||
|
||||
onCleanUp(() => {
|
||||
observer.disconnect()
|
||||
abort.abort()
|
||||
})
|
||||
})
|
||||
|
||||
/**
|
||||
* Checks if the current viewport has a scrollbar.
|
||||
* @returns {boolean} Returns true if the viewport has a scrollbar, false otherwise.
|
||||
|
||||
@@ -255,3 +255,22 @@ export function compareVersions(version1: string, version2: string): number {
|
||||
|
||||
return 0 // Versions are equal
|
||||
}
|
||||
|
||||
export function queryDomUntilFound(selector: string, timeout = 500, abort?: AbortController): Promise<HTMLElement | null> {
|
||||
return new Promise((resolve) => {
|
||||
const interval = setInterval(() => {
|
||||
const element = document.querySelector(selector)
|
||||
if (element) {
|
||||
clearInterval(interval)
|
||||
resolve(element as HTMLElement)
|
||||
}
|
||||
}, timeout)
|
||||
|
||||
if (abort) {
|
||||
abort.signal.addEventListener('abort', () => {
|
||||
clearInterval(interval)
|
||||
resolve(null)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user