mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-07-13 00:11:37 +08:00
fix: 修复主题定制器移动端滚动高度
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import type { CSSProperties } from 'vue'
|
||||||
import {
|
import {
|
||||||
themeCustomizerPrimaryColors,
|
themeCustomizerPrimaryColors,
|
||||||
useThemeCustomizer,
|
useThemeCustomizer,
|
||||||
@@ -44,12 +45,26 @@ const { t } = useI18n()
|
|||||||
const { global: globalTheme } = useTheme()
|
const { global: globalTheme } = useTheme()
|
||||||
const display = useDisplay()
|
const display = useDisplay()
|
||||||
const defaultPrimaryColor = themeCustomizerPrimaryColors[0].value
|
const defaultPrimaryColor = themeCustomizerPrimaryColors[0].value
|
||||||
|
const customizerViewportHeight = ref('100dvh')
|
||||||
|
|
||||||
const drawer = computed({
|
const drawer = computed({
|
||||||
get: () => props.modelValue,
|
get: () => props.modelValue,
|
||||||
set: value => emit('update:modelValue', value),
|
set: value => emit('update:modelValue', value),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
function getVisibleViewportHeight() {
|
||||||
|
if (typeof window === 'undefined') return '100dvh'
|
||||||
|
|
||||||
|
const height = window.visualViewport?.height || window.innerHeight || document.documentElement.clientHeight
|
||||||
|
|
||||||
|
return height > 0 ? `${Math.round(height)}px` : '100dvh'
|
||||||
|
}
|
||||||
|
|
||||||
|
// iOS 小屏的可见视口会随地址栏和独立模式 safe area 变化,面板高度需要跟随真实可见高度。
|
||||||
|
function syncCustomizerViewportHeight() {
|
||||||
|
customizerViewportHeight.value = getVisibleViewportHeight()
|
||||||
|
}
|
||||||
|
|
||||||
// 将主题定制器打开状态同步到根节点,供全局悬浮按钮避让右侧面板。
|
// 将主题定制器打开状态同步到根节点,供全局悬浮按钮避让右侧面板。
|
||||||
function syncThemeCustomizerOpenState(isOpen: boolean) {
|
function syncThemeCustomizerOpenState(isOpen: boolean) {
|
||||||
if (typeof document === 'undefined') return
|
if (typeof document === 'undefined') return
|
||||||
@@ -71,10 +86,38 @@ function clearThemeCustomizerOpenState() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
watch(drawer, syncThemeCustomizerOpenState, { immediate: true })
|
watch(drawer, syncThemeCustomizerOpenState, { immediate: true })
|
||||||
|
watch(drawer, isOpen => {
|
||||||
|
if (isOpen) nextTick(syncCustomizerViewportHeight)
|
||||||
|
})
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
syncCustomizerViewportHeight()
|
||||||
|
window.addEventListener('resize', syncCustomizerViewportHeight)
|
||||||
|
window.addEventListener('orientationchange', syncCustomizerViewportHeight)
|
||||||
|
window.visualViewport?.addEventListener('resize', syncCustomizerViewportHeight)
|
||||||
|
window.visualViewport?.addEventListener('scroll', syncCustomizerViewportHeight)
|
||||||
|
})
|
||||||
|
|
||||||
onScopeDispose(clearThemeCustomizerOpenState)
|
onScopeDispose(clearThemeCustomizerOpenState)
|
||||||
|
onScopeDispose(() => {
|
||||||
|
if (typeof window === 'undefined') return
|
||||||
|
|
||||||
|
window.removeEventListener('resize', syncCustomizerViewportHeight)
|
||||||
|
window.removeEventListener('orientationchange', syncCustomizerViewportHeight)
|
||||||
|
window.visualViewport?.removeEventListener('resize', syncCustomizerViewportHeight)
|
||||||
|
window.visualViewport?.removeEventListener('scroll', syncCustomizerViewportHeight)
|
||||||
|
})
|
||||||
|
|
||||||
const customizerContainer = computed(() => (appMode.value ? VDialog : VNavigationDrawer))
|
const customizerContainer = computed(() => (appMode.value ? VDialog : VNavigationDrawer))
|
||||||
|
|
||||||
|
const customizerContainerStyle = computed<CSSProperties>(() => {
|
||||||
|
if (!appMode.value) return {}
|
||||||
|
|
||||||
|
return {
|
||||||
|
'--theme-customizer-viewport-height': customizerViewportHeight.value,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
const customizerContainerProps = computed(() => {
|
const customizerContainerProps = computed(() => {
|
||||||
if (appMode.value && display.mdAndDown.value) {
|
if (appMode.value && display.mdAndDown.value) {
|
||||||
return {
|
return {
|
||||||
@@ -201,7 +244,12 @@ async function handleResetSettings() {
|
|||||||
/>
|
/>
|
||||||
</Transition>
|
</Transition>
|
||||||
|
|
||||||
<component :is="customizerContainer" v-model="drawer" v-bind="customizerContainerProps">
|
<component
|
||||||
|
:is="customizerContainer"
|
||||||
|
v-model="drawer"
|
||||||
|
v-bind="customizerContainerProps"
|
||||||
|
:style="customizerContainerStyle"
|
||||||
|
>
|
||||||
<div class="theme-customizer-panel" :class="{ 'theme-customizer-panel--dialog': appMode }">
|
<div class="theme-customizer-panel" :class="{ 'theme-customizer-panel--dialog': appMode }">
|
||||||
<div class="theme-customizer-header py-5 px-4">
|
<div class="theme-customizer-header py-5 px-4">
|
||||||
<div>
|
<div>
|
||||||
@@ -398,9 +446,18 @@ async function handleResetSettings() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.theme-customizer-dialog-overlay {
|
.theme-customizer-dialog-overlay {
|
||||||
|
--theme-customizer-viewport-height: 100dvh;
|
||||||
|
|
||||||
z-index: 12000 !important;
|
z-index: 12000 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.theme-customizer-dialog-overlay > .v-overlay__content {
|
||||||
|
overflow: hidden;
|
||||||
|
block-size: var(--theme-customizer-viewport-height);
|
||||||
|
margin-block: 0 !important;
|
||||||
|
max-block-size: var(--theme-customizer-viewport-height);
|
||||||
|
}
|
||||||
|
|
||||||
.theme-customizer-panel {
|
.theme-customizer-panel {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -414,11 +471,13 @@ async function handleResetSettings() {
|
|||||||
border: 1px solid rgba(var(--v-theme-on-surface), 0.08);
|
border: 1px solid rgba(var(--v-theme-on-surface), 0.08);
|
||||||
border-radius: 16px;
|
border-radius: 16px;
|
||||||
background: rgb(var(--v-theme-surface));
|
background: rgb(var(--v-theme-surface));
|
||||||
block-size: 100dvh;
|
block-size: var(--theme-customizer-viewport-height, 100dvh);
|
||||||
|
max-block-size: var(--theme-customizer-viewport-height, 100dvh);
|
||||||
}
|
}
|
||||||
|
|
||||||
.theme-customizer-panel--dialog .theme-customizer-body {
|
.theme-customizer-panel--dialog .theme-customizer-body {
|
||||||
block-size: calc(100dvh - 80px - env(safe-area-inset-bottom) - env(safe-area-inset-top));
|
block-size: auto;
|
||||||
|
padding-block-end: env(safe-area-inset-bottom);
|
||||||
}
|
}
|
||||||
|
|
||||||
.theme-customizer-drawer.v-theme--transparent,
|
.theme-customizer-drawer.v-theme--transparent,
|
||||||
|
|||||||
Reference in New Issue
Block a user