mirror of
https://github.com/BewlyBewly/BewlyBewly.git
synced 2025-04-14 13:15:29 +00:00
feat(settings): touch screen optimization
This commit is contained in:
@@ -86,6 +86,9 @@ settings:
|
||||
mandarin_cn: 官话 - 简体中文
|
||||
mandarin_tw: 官話 - 正體中文
|
||||
jyut: 廣東話
|
||||
touch_screen_optimization: 触屏体验改进
|
||||
touch_screen_optimization_desc: >
|
||||
启用后,如顶栏,你可能需要点击项目以查看更多信息,而不是鼠标直接悬停查看。(旧版顶栏不支持此功能)
|
||||
chk_box:
|
||||
show: 显示
|
||||
hidden: 隐藏
|
||||
|
||||
@@ -86,6 +86,9 @@ settings:
|
||||
mandarin_cn: 官话 - 简体中文
|
||||
mandarin_tw: 官話 - 正體中文
|
||||
jyut: 廣東話
|
||||
touch_screen_optimization: 觸控螢幕體驗改進
|
||||
touch_screen_optimization_desc: >
|
||||
啟用後,如頂欄,你可能需要點選項目才能看到更多資訊,而不是滑鼠移過去就會顯示。(舊版頂欄不支援此功能)
|
||||
chk_box:
|
||||
show: 顯示
|
||||
hidden: 隱藏
|
||||
|
||||
@@ -86,6 +86,9 @@ settings:
|
||||
mandarin_cn: Mandarin - Simplified Chinese
|
||||
mandarin_tw: Mandarin - Traditional Chinese
|
||||
jyut: Cantonese
|
||||
touch_screen_optimization: Touch screen optimization
|
||||
touch_screen_optimization_desc: >
|
||||
After this setting is turned on, like the top bar, you must click on items to view more information instead of hovering over them. (This feature is not supported by the old top bar.)
|
||||
chk_box:
|
||||
show: Show
|
||||
hidden: Hidden
|
||||
|
||||
@@ -86,6 +86,9 @@ settings:
|
||||
mandarin_cn: 官话 - 简体中文
|
||||
mandarin_tw: 官話 - 正體中文
|
||||
jyut: 廣東話
|
||||
touch_screen_optimization: 觸控螢幕體驗改進
|
||||
touch_screen_optimization_desc: >
|
||||
呢個設定開咗之後,好似頂部欄噉,撳咗啲嘢先至可以睇到更多嘅資料,而唔係淨係靠游標懸停就睇到。(舊版頂部欄唔支援呢個功能)
|
||||
chk_box:
|
||||
show: 擺出嚟
|
||||
hidden: 收埋
|
||||
|
||||
@@ -58,6 +58,10 @@ watch(() => settings.value.language, (newValue) => {
|
||||
/>
|
||||
</SettingsItem>
|
||||
|
||||
<SettingsItem :title="$t('settings.touch_screen_optimization')" :desc="$t('settings.touch_screen_optimization_desc')">
|
||||
<Radio v-model="settings.touchScreenOptimization" />
|
||||
</SettingsItem>
|
||||
|
||||
<SettingsItem :title="$t('settings.enable_grid_layout_switcher')">
|
||||
<Radio v-model="settings.enableGridLayoutSwitcher" />
|
||||
</SettingsItem>
|
||||
|
||||
@@ -126,7 +126,7 @@ function setCurrentTitle() {
|
||||
flex justify-between items-center
|
||||
>
|
||||
<aside
|
||||
class="group"
|
||||
:class="{ group: !settings.touchScreenOptimization }"
|
||||
shrink-0 p="x-4" pos="absolute left--84px" z-2
|
||||
>
|
||||
<ul
|
||||
@@ -134,8 +134,8 @@ function setCurrentTitle() {
|
||||
--un-shadow: var(--bew-shadow-4), var(--bew-shadow-edge-glow-2);
|
||||
backdrop-filter: var(--bew-filter-glass-2);
|
||||
"
|
||||
flex="~ gap-2 col" rounded="30px hover:25px" p-2 shadow
|
||||
bg="$bew-content-alt hover:$bew-elevated dark:$bew-elevated dark-hover:$bew-elevated"
|
||||
flex="~ gap-2 col" rounded="30px group-hover:25px" p-2 shadow
|
||||
bg="$bew-content-alt group-hover:$bew-elevated dark:$bew-elevated dark-group-hover:$bew-elevated"
|
||||
scale="group-hover:105" duration-300 overflow-hidden antialiased transform-gpu
|
||||
border="1 $bew-border-color"
|
||||
>
|
||||
@@ -143,7 +143,7 @@ function setCurrentTitle() {
|
||||
<a
|
||||
cursor-pointer w="40px group-hover:180px" h-40px
|
||||
rounded-30px flex items-center overflow-x-hidden
|
||||
duration-300 bg="hover:$bew-fill-2"
|
||||
duration-300 bg="group-hover:$bew-fill-2"
|
||||
:class="{ 'menu-item-activated': menuItem.value === activatedMenuItem }"
|
||||
@click="changeMenuItem(menuItem.value)"
|
||||
>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { useMouseInElement } from '@vueuse/core'
|
||||
import { onClickOutside, useMouseInElement } from '@vueuse/core'
|
||||
import type { Ref, UnwrapNestedRefs } from 'vue'
|
||||
|
||||
import { useApiClient } from '~/composables/api'
|
||||
@@ -128,8 +128,8 @@ function closeAllTopBarPopup(exceptionKey?: keyof typeof popupVisible) {
|
||||
|
||||
const rightSideInactive = computed(() => {
|
||||
let isInactive = false
|
||||
Object.entries(popupVisible).forEach(([key, value]) => {
|
||||
if (value && key !== 'userPanel') {
|
||||
Object.entries(popupVisible).forEach(([_key, value]) => {
|
||||
if (value) {
|
||||
isInactive = true
|
||||
}
|
||||
})
|
||||
@@ -137,104 +137,63 @@ const rightSideInactive = computed(() => {
|
||||
})
|
||||
|
||||
// Channels
|
||||
const channels = useDelayedHover({
|
||||
beforeEnter: () => closeAllTopBarPopup('channels'),
|
||||
enter: () => {
|
||||
popupVisible.channels = true
|
||||
},
|
||||
leave: () => {
|
||||
popupVisible.channels = false
|
||||
},
|
||||
})
|
||||
|
||||
const channels = setupTopBarItemHoverEvent('channels')
|
||||
// Avatar
|
||||
const avatar = useDelayedHover({
|
||||
beforeEnter: () => closeAllTopBarPopup('userPanel'),
|
||||
enter: () => {
|
||||
popupVisible.userPanel = true
|
||||
},
|
||||
beforeLeave: () => {
|
||||
popupVisible.userPanel = false
|
||||
},
|
||||
leave: () => {
|
||||
popupVisible.userPanel = false
|
||||
},
|
||||
})
|
||||
|
||||
const avatar = setupTopBarItemHoverEvent('userPanel')
|
||||
// Notifications
|
||||
const notifications = useDelayedHover({
|
||||
beforeEnter: () => closeAllTopBarPopup('notifications'),
|
||||
enter: () => {
|
||||
popupVisible.notifications = true
|
||||
},
|
||||
leave: () => {
|
||||
popupVisible.notifications = false
|
||||
},
|
||||
})
|
||||
|
||||
const notifications = setupTopBarItemHoverEvent('notifications')
|
||||
// Moments
|
||||
const moments = useDelayedHover({
|
||||
beforeEnter: () => closeAllTopBarPopup('moments'),
|
||||
enter: () => {
|
||||
popupVisible.moments = true
|
||||
momentsPopRef.value && momentsPopRef.value.checkIfHasNewMomentsThenUpdateMoments()
|
||||
},
|
||||
leave: () => {
|
||||
popupVisible.moments = false
|
||||
},
|
||||
})
|
||||
|
||||
const moments = setupTopBarItemHoverEvent('moments')
|
||||
// Favorites
|
||||
const favorites = useDelayedHover({
|
||||
beforeEnter: () => closeAllTopBarPopup('favorites'),
|
||||
enter: () => {
|
||||
popupVisible.favorites = true
|
||||
},
|
||||
leave: () => {
|
||||
popupVisible.favorites = false
|
||||
},
|
||||
})
|
||||
|
||||
const favorites = setupTopBarItemHoverEvent('favorites')
|
||||
// History
|
||||
const history = useDelayedHover({
|
||||
beforeEnter: () => closeAllTopBarPopup('history'),
|
||||
enter: () => {
|
||||
popupVisible.history = true
|
||||
},
|
||||
leave: () => {
|
||||
popupVisible.history = false
|
||||
},
|
||||
})
|
||||
|
||||
const history = setupTopBarItemHoverEvent('history')
|
||||
// Watch Later
|
||||
const watchLater = useDelayedHover({
|
||||
beforeEnter: () => closeAllTopBarPopup('watchLater'),
|
||||
enter: () => {
|
||||
popupVisible.watchLater = true
|
||||
},
|
||||
leave: () => {
|
||||
popupVisible.watchLater = false
|
||||
},
|
||||
})
|
||||
|
||||
const watchLater = setupTopBarItemHoverEvent('watchLater')
|
||||
// Upload
|
||||
const upload = useDelayedHover({
|
||||
beforeEnter: () => closeAllTopBarPopup('upload'),
|
||||
enter: () => {
|
||||
popupVisible.upload = true
|
||||
},
|
||||
leave: () => {
|
||||
popupVisible.upload = false
|
||||
},
|
||||
})
|
||||
|
||||
const upload = setupTopBarItemHoverEvent('upload')
|
||||
// More
|
||||
const more = useDelayedHover({
|
||||
beforeEnter: () => closeAllTopBarPopup(),
|
||||
enter: () => {
|
||||
popupVisible.more = true
|
||||
},
|
||||
leave: () => popupVisible.more = false,
|
||||
const more = setupTopBarItemHoverEvent('more')
|
||||
|
||||
const topBarItemElements = {
|
||||
channels,
|
||||
userPanel: avatar,
|
||||
notifications,
|
||||
moments,
|
||||
favorites,
|
||||
history,
|
||||
watchLater,
|
||||
upload,
|
||||
}
|
||||
|
||||
function setupTopBarItemHoverEvent(key: keyof typeof popupVisible) {
|
||||
return useDelayedHover({
|
||||
beforeEnter: () => closeAllTopBarPopup(key),
|
||||
enter: () => {
|
||||
popupVisible[key] = true
|
||||
},
|
||||
leave: () => {
|
||||
popupVisible[key] = false
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const currentClickedTopBarItem = ref<keyof typeof popupVisible | null>(null)
|
||||
|
||||
function handleClickTopBarItem(event: MouseEvent, key: keyof typeof popupVisible) {
|
||||
if (settings.value.touchScreenOptimization) {
|
||||
event.preventDefault()
|
||||
closeAllTopBarPopup(key)
|
||||
popupVisible[key] = !popupVisible[key]
|
||||
currentClickedTopBarItem.value = key
|
||||
}
|
||||
}
|
||||
|
||||
Object.entries(topBarItemElements).forEach(([key, val]) => {
|
||||
onClickOutside(val, () => {
|
||||
if (currentClickedTopBarItem.value === key)
|
||||
popupVisible[key as keyof typeof popupVisible] = false
|
||||
})
|
||||
})
|
||||
|
||||
// #endregion
|
||||
@@ -493,6 +452,7 @@ defineExpose({
|
||||
bg="$bew-elevated hover:$bew-theme-color dark-hover:white"
|
||||
shadow="[var(--bew-shadow-edge-glow-1),var(--bew-shadow-2)]"
|
||||
w-46px h-46px transform-gpu
|
||||
@click="event => handleClickTopBarItem(event, 'channels')"
|
||||
>
|
||||
|
||||
<svg
|
||||
@@ -580,6 +540,7 @@ defineExpose({
|
||||
ref="moments"
|
||||
class="right-side-item"
|
||||
:class="{ active: popupVisible.moments }"
|
||||
@click="event => handleClickTopBarItem(event, 'moments')"
|
||||
>
|
||||
<template v-if="newMomentsCount > 0">
|
||||
<div
|
||||
@@ -601,7 +562,12 @@ defineExpose({
|
||||
</ALink>
|
||||
|
||||
<Transition name="slide-in">
|
||||
<MomentsPop v-show="popupVisible.moments" ref="momentsPopRef" class="bew-popover" />
|
||||
<MomentsPop
|
||||
v-show="popupVisible.moments"
|
||||
ref="momentsPopRef"
|
||||
class="bew-popover"
|
||||
@click.stop="() => {}"
|
||||
/>
|
||||
</Transition>
|
||||
</div>
|
||||
|
||||
@@ -610,6 +576,7 @@ defineExpose({
|
||||
ref="favorites"
|
||||
class="right-side-item"
|
||||
:class="{ active: popupVisible.favorites }"
|
||||
@click="event => handleClickTopBarItem(event, 'favorites')"
|
||||
>
|
||||
<ALink
|
||||
:href="`https://space.bilibili.com/${mid}/favlist`"
|
||||
@@ -624,6 +591,7 @@ defineExpose({
|
||||
v-if="popupVisible.favorites"
|
||||
ref="favoritesPopRef"
|
||||
class="bew-popover"
|
||||
@click.stop="() => {}"
|
||||
/>
|
||||
</KeepAlive>
|
||||
</Transition>
|
||||
@@ -634,6 +602,7 @@ defineExpose({
|
||||
ref="history"
|
||||
class="right-side-item"
|
||||
:class="{ active: popupVisible.history }"
|
||||
@click="event => handleClickTopBarItem(event, 'history')"
|
||||
>
|
||||
<ALink
|
||||
href="https://www.bilibili.com/account/history"
|
||||
@@ -644,7 +613,11 @@ defineExpose({
|
||||
</ALink>
|
||||
|
||||
<Transition name="slide-in">
|
||||
<HistoryPop v-if="popupVisible.history" class="bew-popover" />
|
||||
<HistoryPop
|
||||
v-if="popupVisible.history"
|
||||
class="bew-popover"
|
||||
@click.stop="() => {}"
|
||||
/>
|
||||
</Transition>
|
||||
</div>
|
||||
|
||||
@@ -653,6 +626,7 @@ defineExpose({
|
||||
ref="watchLater"
|
||||
class="right-side-item"
|
||||
:class="{ active: popupVisible.watchLater }"
|
||||
@click="event => handleClickTopBarItem(event, 'watchLater')"
|
||||
>
|
||||
<ALink
|
||||
href="https://www.bilibili.com/watchlater/#/list"
|
||||
@@ -665,6 +639,7 @@ defineExpose({
|
||||
<WatchLaterPop
|
||||
v-if="popupVisible.watchLater"
|
||||
class="bew-popover"
|
||||
@click.stop="() => {}"
|
||||
/>
|
||||
</Transition>
|
||||
</div>
|
||||
@@ -686,13 +661,18 @@ defineExpose({
|
||||
ref="more"
|
||||
class="right-side-item lg:!hidden flex"
|
||||
:class="{ active: popupVisible.more }"
|
||||
@click="event => handleClickTopBarItem(event, 'more')"
|
||||
>
|
||||
<a title="More">
|
||||
<div i-mingcute:menu-line />
|
||||
</a>
|
||||
|
||||
<Transition name="slide-in">
|
||||
<MorePop v-show="popupVisible.more" class="bew-popover" />
|
||||
<MorePop
|
||||
v-show="popupVisible.more"
|
||||
class="bew-popover"
|
||||
@click.stop="() => {}"
|
||||
/>
|
||||
</Transition>
|
||||
</div>
|
||||
|
||||
@@ -708,6 +688,7 @@ defineExpose({
|
||||
ref="upload"
|
||||
class="right-side-item"
|
||||
:class="{ active: popupVisible.upload }"
|
||||
@click="event => handleClickTopBarItem(event, 'upload')"
|
||||
>
|
||||
<a
|
||||
href="https://member.bilibili.com/platform/upload/video/frame"
|
||||
@@ -721,6 +702,7 @@ defineExpose({
|
||||
<UploadPop
|
||||
v-if="popupVisible.upload"
|
||||
class="bew-popover"
|
||||
@click.stop="() => {}"
|
||||
/>
|
||||
</Transition>
|
||||
</div>
|
||||
@@ -730,6 +712,7 @@ defineExpose({
|
||||
ref="notifications"
|
||||
class="right-side-item"
|
||||
:class="{ active: popupVisible.notifications }"
|
||||
@click="event => handleClickTopBarItem(event, 'notifications')"
|
||||
>
|
||||
<template v-if="unReadMessageCount > 0">
|
||||
<div
|
||||
@@ -755,6 +738,7 @@ defineExpose({
|
||||
<NotificationsPop
|
||||
v-if="popupVisible.notifications"
|
||||
class="bew-popover"
|
||||
@click.stop="() => {}"
|
||||
/>
|
||||
</Transition>
|
||||
</div>
|
||||
@@ -767,6 +751,7 @@ defineExpose({
|
||||
ref="avatar"
|
||||
:class="{ hover: popupVisible.userPanel }"
|
||||
class="avatar right-side-item"
|
||||
@click="event => handleClickTopBarItem(event, 'userPanel')"
|
||||
>
|
||||
<ALink
|
||||
ref="avatarImg"
|
||||
@@ -807,6 +792,7 @@ defineExpose({
|
||||
:user-info="userInfo"
|
||||
after:h="!0"
|
||||
pos="!left-auto !right-0" transform="!translate-x-0"
|
||||
@click.stop="() => {}"
|
||||
/>
|
||||
</Transition>
|
||||
</div>
|
||||
|
||||
@@ -3,10 +3,11 @@ import DOMPurify from 'dompurify'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import { useApiClient } from '~/composables/api'
|
||||
import { settings } from '~/logic'
|
||||
import { revokeAccessKey } from '~/utils/authProvider'
|
||||
import { numFormatter } from '~/utils/dataFormatter'
|
||||
import { LV0_ICON, LV1_ICON, LV2_ICON, LV3_ICON, LV4_ICON, LV5_ICON, LV6_ICON, LV6_LIGHTNING_ICON } from '~/utils/lvIcons'
|
||||
import { getCSRF, getUserID } from '~/utils/main'
|
||||
import { getCSRF, getUserID, isHomePage } from '~/utils/main'
|
||||
|
||||
import type { UserInfo, UserStat } from '../types'
|
||||
import ALink from './ALink.vue'
|
||||
@@ -111,6 +112,21 @@ function getLvIcon(level: number, isSigma: boolean = false): string {
|
||||
}
|
||||
return levelIcons[level] || ''
|
||||
}
|
||||
|
||||
function handleClickChannel() {
|
||||
if (settings.value.topBarLinkOpenMode === 'newTab') {
|
||||
window.open(`https://space.bilibili.com/${mid.value}`, '_blank')
|
||||
}
|
||||
else if (settings.value.topBarLinkOpenMode === 'currentTabIfNotHomepage') {
|
||||
if (isHomePage())
|
||||
window.open(`https://space.bilibili.com/${mid.value}`, '_blank')
|
||||
else
|
||||
window.open(`https://space.bilibili.com/${mid.value}`, '_self')
|
||||
}
|
||||
else {
|
||||
window.open(`https://space.bilibili.com/${mid.value}`, '_self')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -121,9 +137,17 @@ function getLvIcon(level: number, isSigma: boolean = false): string {
|
||||
shadow="[var(--bew-shadow-3),var(--bew-shadow-edge-glow-1)]"
|
||||
>
|
||||
<div
|
||||
text="xl" font-medium
|
||||
text="xl" font-medium flex="~ items-center gap-2"
|
||||
>
|
||||
{{ userInfo.uname ? userInfo.uname : '-' }}
|
||||
<Button
|
||||
v-if="settings.touchScreenOptimization"
|
||||
type="secondary" strong @click="handleClickChannel"
|
||||
>
|
||||
{{ userInfo.uname ? userInfo.uname : '-' }}
|
||||
</Button>
|
||||
<span v-else>
|
||||
{{ userInfo.uname ? userInfo.uname : '-' }}
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
text="xs $bew-text-2"
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
import { settings } from '~/logic'
|
||||
|
||||
// DISABLED WHEN IN TOUCHSCREEN OPTIMIZATION IS ENABLED IN SETTINGS
|
||||
export function useDelayedHover({ enterDelay = 250, leaveDelay = 310, beforeEnter, enter, beforeLeave, leave }:
|
||||
{ enterDelay?: number, leaveDelay?: number, beforeEnter?: Function, enter: Function, beforeLeave?: Function, leave: Function }) {
|
||||
const el = ref<HTMLElement>()
|
||||
@@ -40,8 +43,10 @@ export function useDelayedHover({ enterDelay = 250, leaveDelay = 310, beforeEnte
|
||||
|
||||
watch(el, (el, _, onCleanup) => {
|
||||
if (el) {
|
||||
el.addEventListener('mouseenter', handleMouseEnter)
|
||||
el.addEventListener('mouseleave', handleMouseLeave)
|
||||
if (!settings.value.touchScreenOptimization) {
|
||||
el.addEventListener('mouseenter', handleMouseEnter)
|
||||
el.addEventListener('mouseleave', handleMouseLeave)
|
||||
}
|
||||
}
|
||||
|
||||
onCleanup(() => {
|
||||
@@ -52,5 +57,16 @@ export function useDelayedHover({ enterDelay = 250, leaveDelay = 310, beforeEnte
|
||||
})
|
||||
}, { flush: 'post' })
|
||||
|
||||
watch(() => settings.value.touchScreenOptimization, (newValue) => {
|
||||
if (newValue) {
|
||||
el.value?.removeEventListener('mouseenter', handleMouseEnter)
|
||||
el.value?.removeEventListener('mouseleave', handleMouseLeave)
|
||||
}
|
||||
else {
|
||||
el.value?.addEventListener('mouseenter', handleMouseEnter)
|
||||
el.value?.addEventListener('mouseleave', handleMouseLeave)
|
||||
}
|
||||
}, { immediate: true })
|
||||
|
||||
return el
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ export const accessKey = useStorageLocal('accessKey', '')
|
||||
|
||||
export interface Settings {
|
||||
language: string
|
||||
touchScreenOptimization: boolean
|
||||
enableGridLayoutSwitcher: boolean
|
||||
enableHorizontalScrolling: boolean
|
||||
|
||||
@@ -83,6 +84,7 @@ export interface Settings {
|
||||
}
|
||||
export const settings = useStorageLocal('settings', ref<Settings>({
|
||||
language: '',
|
||||
touchScreenOptimization: false,
|
||||
enableGridLayoutSwitcher: true,
|
||||
enableHorizontalScrolling: false,
|
||||
|
||||
|
||||
Reference in New Issue
Block a user