+import { onKeyStroke } from '@vueuse/core'
+
+import { isHomePage } from '~/utils/main'
+
+// TODO: support shortcuts like `Ctrl+Alt+T` to open in new tab, `Esc` to close
+
+const props = defineProps<{
+ url: string
+ title?: string
+}>()
+
+const emit = defineEmits<{
+ (e: 'close'): void
+}>()
+
+const show = ref(false)
+const iframeRef = ref
(null)
+const currentUrl = ref(props.url)
+const delayCloseTimer = ref(null)
+
+onMounted(async () => {
+ history.pushState({}, '', props.url)
+ show.value = true
+ await nextTick()
+ iframeRef.value?.contentWindow?.addEventListener('pushstate', updateCurrentUrl)
+ window.addEventListener('popstate', updateIframeUrl)
+})
+
+onUnmounted(() => {
+ history.pushState({}, '', 'https://www.bilibili.com')
+ iframeRef.value?.contentWindow?.removeEventListener('pushstate', updateCurrentUrl)
+ window.removeEventListener('popstate', updateIframeUrl)
+})
+
+function updateCurrentUrl() {
+ if (iframeRef.value?.contentWindow) {
+ try {
+ currentUrl.value = iframeRef.value.contentWindow.location.href
+ history.pushState({}, '', currentUrl.value)
+ }
+ catch (error) {
+ console.error('Unable to access iframe URL:', error)
+ }
+ }
+}
+
+function updateIframeUrl() {
+ if (isHomePage()) {
+ handleClose()
+ return
+ }
+
+ if (iframeRef.value?.contentWindow) {
+ iframeRef.value.contentWindow.location.replace(location.href)
+ // iframeRef.value.contentWindow.location.reload()
+ }
+}
+
+function handleClose() {
+ if (delayCloseTimer.value) {
+ clearTimeout(delayCloseTimer.value)
+ }
+ show.value = false
+ delayCloseTimer.value = setTimeout(() => {
+ emit('close')
+ }, 300)
+}
+
+function handleOpenInNewTab() {
+ window.open(props.url, '_blank')
+}
+
+onKeyStroke('Escape', (e: KeyboardEvent) => {
+ e.preventDefault()
+ handleClose()
+})
+
+// const keys = useMagicKeys()
+// const ctrlAltT = keys['Ctrl+Alt+T']
+
+// watch(() => ctrlAltT, (value) => {
+// if (value) {
+// console.log('ctrlAltT', value)
+// handleOpenInNewTab()
+// }
+// })
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/Settings/General/General.vue b/src/components/Settings/General/General.vue
index dd933fa6..61523e59 100644
--- a/src/components/Settings/General/General.vue
+++ b/src/components/Settings/General/General.vue
@@ -11,20 +11,33 @@ const { t, locale } = useI18n()
const langOptions = computed(() => {
return [
{
- value: 'en',
label: t('settings.select_language_opt.english'),
+ value: 'en',
},
{
- value: 'cmn-CN',
label: t('settings.select_language_opt.mandarin_cn'),
+ value: 'cmn-CN',
},
{
- value: 'cmn-TW',
label: t('settings.select_language_opt.mandarin_tw'),
+ value: 'cmn-TW',
},
{
- value: 'jyut',
label: t('settings.select_language_opt.jyut'),
+ value: 'jyut',
+ },
+ ]
+})
+
+const videoCardOpenModeOptions = computed(() => {
+ return [
+ {
+ label: t('settings.video_card_link_opening_behavior_opt.drawer'),
+ value: 'drawer',
+ },
+ {
+ label: t('settings.video_card_link_opening_behavior_opt.new_tab'),
+ value: 'new_tab',
},
]
})
@@ -52,10 +65,6 @@ watch(() => settings.value.language, (newValue) => {
-
-
@@ -77,6 +86,13 @@ watch(() => settings.value.language, (newValue) => {
+
+
+
diff --git a/src/components/VideoCard/VideoCard.vue b/src/components/VideoCard/VideoCard.vue
index 468ab308..91cc053b 100644
--- a/src/components/VideoCard/VideoCard.vue
+++ b/src/components/VideoCard/VideoCard.vue
@@ -3,6 +3,7 @@ import { Icon } from '@iconify/vue'
import Button from '~/components/Button.vue'
import { useApiClient } from '~/composables/api'
+import { useBewlyApp } from '~/composables/useAppProvider'
import { settings } from '~/logic'
import type { VideoPreviewResult } from '~/models/video/videoPreview'
import { calcCurrentTime, calcTimeSince, numFormatter } from '~/utils/dataFormatter'
@@ -64,9 +65,7 @@ const emit = defineEmits<{
}>()
const api = useApiClient()
-
-// Used to click and control herf attribute
-const isClick = ref(false)
+const { openIframeDrawer } = useBewlyApp()
function getCurrentVideoUrl(video: Video) {
const baseUrl = `https://www.bilibili.com/video/${video.bvid ?? `av${video.aid}`}`
@@ -75,7 +74,7 @@ function getCurrentVideoUrl(video: Video) {
}
const videoUrl = computed(() => {
- if (props.removed || !isClick.value || !props.video)
+ if (props.removed || !props.video)
return undefined
if (props.video.url)
@@ -189,14 +188,11 @@ function handelMouseLeave() {
clearTimeout(mouseLeaveTimeOut.value)
}
-function switchClickState(flag: boolean) {
- if (flag) {
- isClick.value = flag
- }
- else {
- setTimeout(() => {
- isClick.value = flag
- })
+function handleClick(event: MouseEvent) {
+ if (settings.value.videoCardLinkOpenMode === 'drawer' && videoUrl.value) {
+ event.preventDefault()
+
+ openIframeDrawer(videoUrl.value)
}
}
@@ -235,9 +231,7 @@ function handleUndo() {
:href="videoUrl" target="_blank" rel="noopener noreferrer"
@mouseenter="handleMouseEnter"
@mouseleave="handelMouseLeave"
- @mousedown="switchClickState(true)"
- @mouseup="switchClickState(false)"
- @dragend="switchClickState(false)"
+ @click="handleClick"
>
diff --git a/src/composables/useAppProvider.ts b/src/composables/useAppProvider.ts
index 6f08cabc..7470e4be 100644
--- a/src/composables/useAppProvider.ts
+++ b/src/composables/useAppProvider.ts
@@ -11,6 +11,7 @@ export interface BewlyAppProvider {
handlePageRefresh: Ref<(() => void) | undefined>
handleBackToTop: (targetScrollTop?: number) => void
haveScrollbar: () => boolean
+ openIframeDrawer: (url: string) => void
}
export function useBewlyApp(): BewlyAppProvider {
diff --git a/src/contentScripts/views/App.vue b/src/contentScripts/views/App.vue
index 1457b50c..e8ab6900 100644
--- a/src/contentScripts/views/App.vue
+++ b/src/contentScripts/views/App.vue
@@ -13,9 +13,10 @@ import { getUserID, isHomePage, scrollToTop } from '~/utils/main'
import emitter from '~/utils/mitt'
const { isDark } = useDark()
-const activatedPage = ref(settings.value.dockItemVisibilityList.find(e => e.visible === true)?.page ?? AppPage.Home)
const { locale } = useI18n()
const [showSettings, toggleSettings] = useToggle(false)
+
+const activatedPage = ref(settings.value.dockItemVisibilityList.find(e => e.visible === true)?.page ?? AppPage.Home)
const pages = {
[AppPage.Home]: defineAsyncComponent(() => import('./Home/Home.vue')),
[AppPage.Search]: defineAsyncComponent(() => import('./Search/Search.vue')),
@@ -34,6 +35,22 @@ const handleThrottledBackToTop = useThrottleFn(() => handleBackToTop(), 1000)
const topBarRef = ref()
const reachTop = ref(true)
+const iframeDrawerUrl = ref('')
+const showIframeDrawer = ref(false)
+
+const inIframe = computed((): boolean => {
+ return window.self !== window.top
+})
+
+const showBewlyPage = computed((): boolean => {
+ if (inIframe.value) {
+ return false
+ }
+ else {
+ return isHomePage() && !inIframe.value && !settings.value.useOriginalBilibiliHomepage
+ }
+})
+
watch(
() => activatedPage.value,
() => {
@@ -242,6 +259,11 @@ function handleReduceFrostedGlassBlur() {
}
}
+function openIframeDrawer(url: string) {
+ iframeDrawerUrl.value = url
+ showIframeDrawer.value = true
+}
+
/**
* Checks if the current viewport has a scrollbar.
* @returns {boolean} Returns true if the viewport has a scrollbar, false otherwise.
@@ -261,6 +283,7 @@ provide('BEWLY_APP', {
handleBackToTop,
handlePageRefresh,
handleReachBottom,
+ openIframeDrawer,
haveScrollbar,
})
@@ -274,7 +297,7 @@ provide('BEWLY_APP', {
text="$bew-text-1"
>
-
+
@@ -284,9 +307,13 @@ provide('BEWLY_APP', {
-
+
changeActivatePage(page)"
@@ -302,7 +329,7 @@ provide('BEWLY_APP', {
-
+
('BEWLY_APP', {
diff --git a/src/logic/storage.ts b/src/logic/storage.ts
index b9809305..feb5f846 100644
--- a/src/logic/storage.ts
+++ b/src/logic/storage.ts
@@ -12,7 +12,7 @@ export interface Settings {
language: string
enableGridLayoutSwitcher: boolean
enableHorizontalScrolling: boolean
- openLinkInCurrentTab: boolean
+ videoCardLinkOpenMode: 'drawer' | 'newTab'
enableVideoPreview: boolean
enableVideoCtrlBarOnVideoCard: boolean
hoverVideoCardDelayed: boolean
@@ -81,13 +81,16 @@ export const settings = useStorageLocal('settings', ref({
language: '',
enableGridLayoutSwitcher: true,
enableHorizontalScrolling: false,
- openLinkInCurrentTab: false,
+
+ disableFrostedGlass: true,
+ reduceFrostedGlassBlur: false,
+
+ blockAds: false,
+
+ videoCardLinkOpenMode: 'newTab',
enableVideoPreview: true,
enableVideoCtrlBarOnVideoCard: false,
hoverVideoCardDelayed: false,
- blockAds: false,
- disableFrostedGlass: true,
- reduceFrostedGlassBlur: false,
// Desktop & Dock
useOldTopBar: false,
diff --git a/src/manifest.ts b/src/manifest.ts
index 51f35a56..b4aa4425 100644
--- a/src/manifest.ts
+++ b/src/manifest.ts
@@ -65,6 +65,7 @@ export async function getManifest() {
css: ['./dist/contentScripts/style.css'],
run_at: 'document_start',
match_about_blank: true,
+ all_frames: true,
},
],
web_accessible_resources: [
diff --git a/src/utils/main.ts b/src/utils/main.ts
index b344c336..06458875 100644
--- a/src/utils/main.ts
+++ b/src/utils/main.ts
@@ -146,15 +146,14 @@ export function delay(ms: number) {
/**
* Check if the current page is the home page
+ * @param url the url to check
* @returns true if the current page is the home page
*/
-export function isHomePage(): boolean {
+export function isHomePage(url: string = location.href): boolean {
if (
- /https?:\/\/(?:www\.)?bilibili.com\/?(?:#\/?)?$/.test(location.href)
- // https://github.com/hakadao/BewlyBewly/issues/525 #525
- || /https?:\/\/(?:www\.)?bilibili.com\/?(?:\?.*)?$/.test(location.href)
- || /https?:\/\/(?:www\.)?bilibili.com\/index\.html$/.test(location.href)
- || /https?:\/\/(?:www\.)?bilibili.com\/\?spm_id_from=.*/.test(location.href)
+ /https?:\/\/(?:www\.)?bilibili.com\/?(?:#\/?)?$/.test(url)
+ || /https?:\/\/(?:www\.)?bilibili.com\/index\.html$/.test(url)
+ || /https?:\/\/(?:www\.)?bilibili.com\/\?spm_id_from=.*/.test(url)
) {
return true
}