mirror of
https://github.com/BewlyBewly/BewlyBewly.git
synced 2025-04-14 13:15:29 +00:00
feat(video-card): enhance video card context menu
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
import type { CSSProperties } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import { useBewlyApp } from '~/composables/useAppProvider'
|
||||
import { settings } from '~/logic'
|
||||
import { Type as ThreePointV2Type } from '~/models/video/appForYou'
|
||||
import { openLinkInBackground } from '~/utils/tab'
|
||||
|
||||
@@ -13,46 +13,69 @@ const props = defineProps<{
|
||||
video: Video
|
||||
contextMenuStyles: CSSProperties
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
(event: 'removed', selectedOpt?: { dislikeReasonId: number }): void
|
||||
(event: 'close'): void
|
||||
(event: 'reopen'): void
|
||||
}>()
|
||||
|
||||
const getVideoType = inject<() => string>('getVideoType')!
|
||||
|
||||
const videoOptions = reactive<{ id: number, name: string }[]>([
|
||||
{ id: 1, name: '不感兴趣' },
|
||||
{ id: 2, name: '不想看此UP主' },
|
||||
])
|
||||
|
||||
const { t } = useI18n()
|
||||
const showContextMenu = ref<boolean>(false)
|
||||
const showDislikeDialog = ref<boolean>(false)
|
||||
const showPipWindow = ref<boolean>(false)
|
||||
const { openIframeDrawer } = useBewlyApp()
|
||||
|
||||
enum VideoOption {
|
||||
OpenLinkInNewTab,
|
||||
OpenLinkInCurrentTab,
|
||||
// OpenInBackground,
|
||||
OpenLinkInNewWindow,
|
||||
OpenLinkInDrawer,
|
||||
// OpenInNewTab,
|
||||
OpenInBackground,
|
||||
OpenInCurrentTab,
|
||||
OpenInNewWindow,
|
||||
OpenInDrawer,
|
||||
|
||||
ViewTheOriginalCover,
|
||||
ViewThisUserChannel,
|
||||
|
||||
CopyVideoLink,
|
||||
CopyBVNumber,
|
||||
CopyAVNumber,
|
||||
}
|
||||
|
||||
const commonOptions = computed((): { command: VideoOption, name: string, icon: string, color?: string }[][] => {
|
||||
return [
|
||||
let result = [
|
||||
[
|
||||
{ command: VideoOption.OpenLinkInNewTab, name: 'Open Link in New Tab', icon: 'i-solar:square-top-down-bold-duotone' },
|
||||
{ command: VideoOption.OpenLinkInCurrentTab, name: 'Open Link in Current Tab', icon: 'i-solar:square-top-down-bold-duotone' },
|
||||
// { command: VideoOption.OpenInBackground, name: 'Open in background', icon: 'i-solar:square-top-down-bold-duotone' },
|
||||
{ command: VideoOption.OpenLinkInNewWindow, name: 'Open Link in New Window', icon: 'i-solar:maximize-square-3-bold-duotone' },
|
||||
{ command: VideoOption.OpenLinkInDrawer, name: 'Open Link in Drawer', icon: 'i-solar:archive-up-minimlistic-bold-duotone' },
|
||||
// { command: VideoOption.OpenInNewTab, name: 'Open in New Tab', icon: 'i-solar:square-top-down-bold-duotone' },
|
||||
{ command: VideoOption.OpenInBackground, name: t('video_card.operation.open_in_background'), icon: 'i-solar:square-top-down-bold-duotone' },
|
||||
{ command: VideoOption.OpenInNewWindow, name: t('video_card.operation.open_in_new_window'), icon: 'i-solar:maximize-square-3-bold-duotone' },
|
||||
{ command: VideoOption.OpenInCurrentTab, name: t('video_card.operation.open_in_current_tab'), icon: 'i-solar:square-top-down-bold-duotone' },
|
||||
{ command: VideoOption.OpenInDrawer, name: t('video_card.operation.open_in_drawer'), icon: 'i-solar:archive-up-minimlistic-bold-duotone' },
|
||||
],
|
||||
|
||||
[
|
||||
{ command: VideoOption.ViewTheOriginalCover, name: 'View the original cover', icon: 'i-solar:gallery-minimalistic-bold-duotone' },
|
||||
{ command: VideoOption.CopyVideoLink, name: t('video_card.operation.copy_video_link'), icon: 'i-solar:copy-bold-duotone' },
|
||||
{ command: VideoOption.CopyBVNumber, name: t('video_card.operation.copy_bv_number'), icon: 'i-solar:copy-bold-duotone' },
|
||||
{ command: VideoOption.CopyAVNumber, name: t('video_card.operation.copy_av_number'), icon: 'i-solar:copy-bold-duotone' },
|
||||
],
|
||||
|
||||
[
|
||||
{ command: VideoOption.ViewTheOriginalCover, name: t('video_card.operation.view_the_original_cover'), icon: 'i-solar:gallery-minimalistic-bold-duotone' },
|
||||
{ command: VideoOption.ViewThisUserChannel, name: t('video_card.operation.view_this_user_channel'), icon: 'i-solar:user-bold-duotone' },
|
||||
],
|
||||
]
|
||||
if (getVideoType() === 'bangumi') {
|
||||
result = result.map((group) => {
|
||||
return group.filter((opt) => {
|
||||
return opt.command !== VideoOption.CopyBVNumber && opt.command !== VideoOption.CopyAVNumber && opt.command !== VideoOption.ViewThisUserChannel
|
||||
})
|
||||
})
|
||||
}
|
||||
return result
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
@@ -75,36 +98,43 @@ function handleAppMoreCommand(command: ThreePointV2Type) {
|
||||
|
||||
function handleCommonCommand(command: VideoOption) {
|
||||
switch (command) {
|
||||
case VideoOption.OpenLinkInNewTab:
|
||||
case VideoOption.OpenInBackground:
|
||||
openLinkInBackground(props.video.url!)
|
||||
// // Focus back on the original tab
|
||||
// if (newTab) {
|
||||
// newTab.blur() // Remove focus from the new tab
|
||||
// window.focus() // Bring focus back to the current tab
|
||||
// }
|
||||
handleClose()
|
||||
break
|
||||
case VideoOption.OpenLinkInCurrentTab:
|
||||
case VideoOption.OpenInNewWindow:
|
||||
showPipWindow.value = true
|
||||
break
|
||||
case VideoOption.OpenInCurrentTab:
|
||||
window.open(props.video.url, '_self')
|
||||
handleClose()
|
||||
break
|
||||
// case VideoOption.OpenInBackground:
|
||||
// // Open tab in background
|
||||
// window.open(props.video.url, '_blank', 'background')
|
||||
// handleClose()
|
||||
// break
|
||||
case VideoOption.OpenLinkInNewWindow:
|
||||
showPipWindow.value = true
|
||||
break
|
||||
case VideoOption.OpenLinkInDrawer:
|
||||
case VideoOption.OpenInDrawer:
|
||||
openIframeDrawer(props.video.url || '')
|
||||
handleClose()
|
||||
break
|
||||
|
||||
case VideoOption.CopyVideoLink:
|
||||
navigator.clipboard.writeText(props.video.url!)
|
||||
handleClose()
|
||||
break
|
||||
case VideoOption.CopyBVNumber:
|
||||
navigator.clipboard.writeText(props.video.bvid!)
|
||||
handleClose()
|
||||
break
|
||||
case VideoOption.CopyAVNumber:
|
||||
navigator.clipboard.writeText(props.video.id.toString())
|
||||
handleClose()
|
||||
break
|
||||
|
||||
case VideoOption.ViewTheOriginalCover:
|
||||
window.open(props.video.cover, '_blank')
|
||||
handleClose()
|
||||
break
|
||||
case VideoOption.ViewThisUserChannel:
|
||||
window.open(`https://space.bilibili.com/${props.video.mid}`, '_blank')
|
||||
handleClose()
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,7 +176,7 @@ function handleRemoved(selectedOpt?: { dislikeReasonId: number }) {
|
||||
z-10
|
||||
>
|
||||
<ul flex="~ col gap-1">
|
||||
<template v-if="settings.recommendationMode === 'app'">
|
||||
<template v-if="getVideoType() === 'appRcmd'">
|
||||
<template v-for="option in video.threePointV2" :key="option.type">
|
||||
<li
|
||||
v-if="option.type !== ThreePointV2Type.WatchLater && option.type !== ThreePointV2Type.Feedback"
|
||||
@@ -154,12 +184,12 @@ function handleRemoved(selectedOpt?: { dislikeReasonId: number }) {
|
||||
@click="handleAppMoreCommand(option.type)"
|
||||
>
|
||||
<i class="item-icon" i-solar:confounded-circle-bold-duotone />
|
||||
<span v-if="option.type === ThreePointV2Type.Dislike">{{ $t('home.not_interested') }}</span>
|
||||
<span v-if="option.type === ThreePointV2Type.Dislike">{{ $t('video_card.operation.not_interested') }}</span>
|
||||
<span v-else>{{ option.title }}</span>
|
||||
</li>
|
||||
</template>
|
||||
</template>
|
||||
<template v-else>
|
||||
<template v-else-if="getVideoType() === 'rcmd'">
|
||||
<li
|
||||
v-for="option in videoOptions" :key="option.id"
|
||||
class="context-menu-item"
|
||||
@@ -170,9 +200,9 @@ function handleRemoved(selectedOpt?: { dislikeReasonId: number }) {
|
||||
</li>
|
||||
</template>
|
||||
|
||||
<template v-for="(optionGroup, _index) in commonOptions" :key="_index">
|
||||
<div class="divider" />
|
||||
<div v-if="getVideoType() !== 'common'" class="divider" />
|
||||
|
||||
<template v-for="(optionGroup, index) in commonOptions" :key="index">
|
||||
<li
|
||||
v-for="option in optionGroup"
|
||||
:key="option.command"
|
||||
@@ -182,6 +212,8 @@ function handleRemoved(selectedOpt?: { dislikeReasonId: number }) {
|
||||
<i class="item-icon" :class="option.icon" />
|
||||
{{ option.name }}
|
||||
</li>
|
||||
|
||||
<div v-if="index !== commonOptions.length - 1" class="divider" />
|
||||
</template>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user