From e2ea04145a35fd675bdc556b64e2f727b2d9fffd Mon Sep 17 00:00:00 2001 From: _Kerman Date: Wed, 24 Apr 2024 14:26:02 +0800 Subject: [PATCH 1/4] refactor: DOM structure --- packages/client/composables/useNav.ts | 19 +++-- packages/client/constants.ts | 1 - packages/client/env.ts | 2 + packages/client/internals/Controls.vue | 10 +++ packages/client/internals/DrawingControls.vue | 2 +- packages/client/internals/DrawingLayer.vue | 2 +- packages/client/internals/DrawingPreview.vue | 2 +- packages/client/internals/NavControls.vue | 2 +- packages/client/internals/NoteDisplay.vue | 2 +- packages/client/internals/QuickOverview.vue | 8 +- packages/client/internals/Settings.vue | 2 +- packages/client/internals/SlideContainer.vue | 74 +++++++------------ packages/client/internals/SlideWrapper.vue | 48 +++++------- packages/client/internals/SlidesShow.vue | 9 ++- packages/client/pages/entry.vue | 42 +++++------ packages/client/pages/notes.vue | 19 ++--- packages/client/pages/overview.vue | 15 +--- packages/client/pages/play.vue | 28 ++----- packages/client/pages/presenter.vue | 34 +++------ packages/client/setup/root.ts | 10 +-- packages/client/styles/index.css | 4 + packages/types/src/types.ts | 4 +- test/_tutils.ts | 4 - 23 files changed, 143 insertions(+), 200 deletions(-) diff --git a/packages/client/composables/useNav.ts b/packages/client/composables/useNav.ts index 0460069c65..86e2de5da3 100644 --- a/packages/client/composables/useNav.ts +++ b/packages/client/composables/useNav.ts @@ -55,7 +55,7 @@ export interface SlidevContextNav { /** Go to previous slide */ prevSlide: (lastClicks?: boolean) => Promise /** Go to slide */ - go: (page: number | string, clicks?: number) => Promise + go: (page: number | string, clicks?: number, force?: boolean) => Promise /** Go to the first slide */ goFirst: () => Promise /** Go to the last slide */ @@ -181,14 +181,14 @@ export function useNavBase( return go(total.value) } - async function go(page: number | string, clicks: number = 0) { + async function go(page: number | string, clicks: number = 0, force = false) { skipTransition.value = false const pageChanged = currentSlideNo.value !== page const clicksChanged = clicks !== queryClicks.value const meta = getSlide(page)?.meta const clicksStart = meta?.slide?.frontmatter.clicksStart ?? 0 clicks = clamp(clicks, clicksStart, meta?.__clicksContext?.total ?? CLICKS_MAX) - if (pageChanged || clicksChanged) { + if (force || pageChanged || clicksChanged) { await router?.push({ path: getSlidePath(page, isPresenter.value), query: { @@ -379,9 +379,16 @@ export const useNav = createSharedComposable((): SlidevContextNavFull => { watch( [nav.total, state.currentRoute], async () => { - if (state.hasPrimarySlide.value && !getSlide(state.currentRoute.value.params.no as string)) { - // The current slide may has been removed. Redirect to the last slide. - await nav.goLast() + const no = state.currentRoute.value.params.no as string + if (state.hasPrimarySlide.value && !getSlide(no)) { + if (no && no !== 'index.html') { + // The current slide may has been removed. Redirect to the last slide. + await nav.go(nav.total.value, 0, true) + } + else { + // Redirect to the first slide + await nav.go(1, 0, true) + } } }, { flush: 'pre', immediate: true }, diff --git a/packages/client/constants.ts b/packages/client/constants.ts index 0284c72506..3acfacc867 100644 --- a/packages/client/constants.ts +++ b/packages/client/constants.ts @@ -11,7 +11,6 @@ export const injectionSlideScale = '$$slidev-slide-scale' as unknown as Injectio export const injectionSlidevContext = '$$slidev-context' as unknown as InjectionKey> export const injectionRoute = '$$slidev-route' as unknown as InjectionKey export const injectionRenderContext = '$$slidev-render-context' as unknown as InjectionKey> -export const injectionActive = '$$slidev-active' as unknown as InjectionKey> export const injectionFrontmatter = '$$slidev-fontmatter' as unknown as InjectionKey> export const injectionSlideZoom = '$$slidev-slide-zoom' as unknown as InjectionKey> diff --git a/packages/client/env.ts b/packages/client/env.ts index fc9de7674b..59dad897df 100644 --- a/packages/client/env.ts +++ b/packages/client/env.ts @@ -16,3 +16,5 @@ export const slideHeight = computed(() => Math.ceil(slideWidth.value / slideAspe export const themeVars = computed(() => { return objectMap(configs.themeConfig || {}, (k, v) => [`--slidev-theme-${k}`, v]) }) + +export const slidesTitle = configs.titleTemplate.replace('%s', configs.title || 'Slidev') diff --git a/packages/client/internals/Controls.vue b/packages/client/internals/Controls.vue index 8c0e716ece..f914fa504b 100644 --- a/packages/client/internals/Controls.vue +++ b/packages/client/internals/Controls.vue @@ -2,11 +2,18 @@ import { shallowRef } from 'vue' import { showInfoDialog, showOverview, showRecordingDialog } from '../state' import { configs } from '../env' +import { useNav } from '../composables/useNav' import QuickOverview from './QuickOverview.vue' import InfoDialog from './InfoDialog.vue' import Goto from './Goto.vue' import ContextMenu from './ContextMenu.vue' +const { isEmbedded } = useNav() +const drawingEnabled = __SLIDEV_FEATURE_DRAWINGS__ && !configs.drawings.presenterOnly && !isEmbedded.value +const DrawingControls = shallowRef() +if (drawingEnabled) + import('../internals/DrawingControls.vue').then(v => DrawingControls.value = v.default) + const WebCamera = shallowRef() const RecordingDialog = shallowRef() if (__SLIDEV_FEATURE_RECORD__) { @@ -16,6 +23,9 @@ if (__SLIDEV_FEATURE_RECORD__) { ../composables/drawings + diff --git a/packages/client/internals/DrawingPreview.vue b/packages/client/internals/DrawingPreview.vue index 36612c7a9e..c21fe541d0 100644 --- a/packages/client/internals/DrawingPreview.vue +++ b/packages/client/internals/DrawingPreview.vue @@ -12,4 +12,4 @@ const { drawingState } = useDrawings() class="w-full h-full absolute top-0 pointer-events-none" v-html="drawingState[page]" /> -../composables/drawings + diff --git a/packages/client/internals/NavControls.vue b/packages/client/internals/NavControls.vue index d531eb6651..b3e7b5c0d8 100644 --- a/packages/client/internals/NavControls.vue +++ b/packages/client/internals/NavControls.vue @@ -179,4 +179,4 @@ if (__SLIDEV_FEATURE_DRAWINGS__) -../composables/drawings + diff --git a/packages/client/internals/NoteDisplay.vue b/packages/client/internals/NoteDisplay.vue index 51627293ea..0f0baf20f0 100644 --- a/packages/client/internals/NoteDisplay.vue +++ b/packages/client/internals/NoteDisplay.vue @@ -17,7 +17,7 @@ const emit = defineEmits<{ (type: 'markerClick', e: MouseEvent, clicks: number): void }>() -const withClicks = computed(() => props.clicksContext?.current != null && props.noteHtml?.includes('slidev-note-click-mark')) +const withClicks = computed(() => props.clicksContext != null && props.noteHtml?.includes('slidev-note-click-mark')) const noteDisplay = ref(null) const CLASS_FADE = 'slidev-note-fade' diff --git a/packages/client/internals/QuickOverview.vue b/packages/client/internals/QuickOverview.vue index fad425ebaf..a74d41d1f9 100644 --- a/packages/client/internals/QuickOverview.vue +++ b/packages/client/internals/QuickOverview.vue @@ -4,7 +4,6 @@ import { computed, ref, watchEffect } from 'vue' import { breakpoints, showOverview, windowSize } from '../state' import { currentOverviewPage, overviewRowCount } from '../logic/overview' import { createFixedClicks } from '../composables/useClicks' -import { getSlideClass } from '../utils' import { CLICKS_MAX } from '../constants' import { useNav } from '../composables/useNav' import SlideContainer from './SlideContainer.vue' @@ -119,7 +118,7 @@ setTimeout(() => {
{ class="pointer-events-none" > @@ -168,7 +164,7 @@ setTimeout(() => {
-
+
diff --git a/packages/client/internals/Settings.vue b/packages/client/internals/Settings.vue index 7eb72d88a2..f2640eb7ec 100644 --- a/packages/client/internals/Settings.vue +++ b/packages/client/internals/Settings.vue @@ -16,7 +16,7 @@ const items: SelectionItem[] = [ diff --git a/packages/client/internals/SlideContainer.vue b/packages/client/internals/SlideContainer.vue index 9ee65faf6c..435bd17561 100644 --- a/packages/client/internals/SlideContainer.vue +++ b/packages/client/internals/SlideContainer.vue @@ -1,9 +1,10 @@ - diff --git a/packages/client/internals/SlideWrapper.vue b/packages/client/internals/SlideWrapper.vue index 047566cdcb..6b9c5dc8e0 100644 --- a/packages/client/internals/SlideWrapper.vue +++ b/packages/client/internals/SlideWrapper.vue @@ -1,10 +1,11 @@ @@ -85,7 +78,6 @@ const SlideComponent = defineAsyncComponent({ .slidev-page { position: absolute; - width: 100%; - height: 100%; + inset: 0; } diff --git a/packages/client/internals/SlidesShow.vue b/packages/client/internals/SlidesShow.vue index 4cc6fb4819..7e9c5f6850 100644 --- a/packages/client/internals/SlidesShow.vue +++ b/packages/client/internals/SlidesShow.vue @@ -8,7 +8,6 @@ import { createFixedClicks } from '../composables/useClicks' import { activeDragElement } from '../state' import { CLICKS_MAX } from '../constants' import SlideWrapper from './SlideWrapper.vue' -import PresenterMouse from './PresenterMouse.vue' import DragControl from './DragControl.vue' import GlobalTop from '#slidev/global-components/top' @@ -22,11 +21,11 @@ const { currentSlideRoute, currentTransition, getPrimaryClicks, - isPresenter, nextRoute, slides, isPrintMode, isPrintWithClicks, + clicksDirection, } = useNav() // preload next route @@ -64,10 +63,13 @@ function onAfterLeave() { v-bind="skipTransition ? {} : currentTransition" id="slideshow" tag="div" + :class="{ + 'slidev-nav-go-forward': clicksDirection > 0, + 'slidev-nav-go-backward': clicksDirection < 0, + }" @after-leave="onAfterLeave" > - diff --git a/packages/client/pages/notes.vue b/packages/client/pages/notes.vue index 90f83b4f89..7849f1943c 100644 --- a/packages/client/pages/notes.vue +++ b/packages/client/pages/notes.vue @@ -2,7 +2,7 @@ import { useHead } from '@unhead/vue' import { computed, ref, watch } from 'vue' import { useLocalStorage } from '@vueuse/core' -import { configs } from '../env' +import { slidesTitle } from '../env' import { sharedState } from '../state/shared' import { fullscreen } from '../state' @@ -10,10 +10,7 @@ import NoteDisplay from '../internals/NoteDisplay.vue' import IconButton from '../internals/IconButton.vue' import { useNav } from '../composables/useNav' -const slideTitle = configs.titleTemplate.replace('%s', configs.title || 'Slidev') -useHead({ - title: `Notes - ${slideTitle}`, -}) +useHead({ title: `Notes - ${slidesTitle}` }) const { slides, total } = useNav() const { isFullscreen, toggle: toggleFullscreen } = fullscreen @@ -39,20 +36,20 @@ function decreaseFontSize() {