返回 slidev
storage.ts
根目录 / packages / client / state / storage.ts
1 import type { DragElementState } from '../composables/useDragElements'
2 import { breakpointsTailwind, isClient, useActiveElement, useBreakpoints, useFullscreen, useLocalStorage, useMagicKeys, useToggle, useWindowSize } from '@vueuse/core'
3 import { computed, reactive, ref, shallowRef } from 'vue'
4 import { slideAspect } from '../env'
5
6 export const showRecordingDialog = ref(false)
7 export const showInfoDialog = ref(false)
8 export const showGotoDialog = ref(false)
9 export const showOverview = ref(false)
10
11 /**
12 * Skip slides transition when triggered by HMR.
13 * Will reset automatically after user navigations
14 */
15 export const hmrSkipTransition = ref(false)
16 export const disableTransition = ref(false)
17
18 export const shortcutsEnabled = ref(true)
19
20 // Use a locking mechanism to support multiple simultaneous locks
21 // and avoid race conditions. Race conditions may occur, for example,
22 // when locking shortcuts on editor focus and moving from one editor
23 // to another, as blur events can be triggered after focus.
24 const shortcutsLocks = reactive(new Set<symbol>())
25
26 export const shortcutsLocked = computed(() => shortcutsLocks.size > 0)
27
28 export function lockShortcuts() {
29 const lock = Symbol('shortcuts lock')
30 shortcutsLocks.add(lock)
31 return () => {
32 shortcutsLocks.delete(lock)
33 }
34 }
35
36 export const breakpoints = useBreakpoints({
37 xs: 460,
38 ...breakpointsTailwind,
39 })
40 export const windowSize = useWindowSize()
41 export const magicKeys = useMagicKeys()
42 export const isScreenVertical = computed(() => windowSize.height.value - windowSize.width.value / slideAspect.value > 120)
43 export const fullscreen = useFullscreen(isClient ? document.body : null)
44
45 export const activeElement = useActiveElement()
46 export const isInputting = computed(() => ['INPUT', 'TEXTAREA'].includes(activeElement.value?.tagName || ''))
47 export const isOnFocus = computed(() => ['BUTTON', 'A'].includes(activeElement.value?.tagName || ''))
48
49 export const currentCamera = useLocalStorage<string>('slidev-camera', 'default', { listenToStorageChanges: false })
50 export const currentMic = useLocalStorage<string>('slidev-mic', 'default', { listenToStorageChanges: false })
51 export const slideScale = useLocalStorage<number>('slidev-scale', 0)
52 export const wakeLockEnabled = useLocalStorage('slidev-wake-lock', true)
53 export const hideCursorIdle = useLocalStorage('slidev-hide-cursor-idle', true)
54 export const skipExportPdfTip = useLocalStorage('slidev-skip-export-pdf-tip', false)
55 export const captureDelay = useLocalStorage('slidev-export-capture-delay', 400, { listenToStorageChanges: false })
56
57 export const showPresenterCursor = useLocalStorage('slidev-presenter-cursor', true, { listenToStorageChanges: false })
58
59 export const cursorStyle = useLocalStorage<'cursor' | 'laser'>('slidev-cursor-style', 'cursor', { listenToStorageChanges: false })
60
61 export function togglePresenterCursor() {
62 showPresenterCursor.value = !showPresenterCursor.value
63 }
64
65 export const showEditor = useLocalStorage('slidev-show-editor', false, { listenToStorageChanges: false })
66 export const isEditorVertical = useLocalStorage('slidev-editor-vertical', false, { listenToStorageChanges: false })
67 export const editorWidth = useLocalStorage('slidev-editor-width', isClient ? window.innerWidth * 0.4 : 318, { listenToStorageChanges: false })
68 export const editorHeight = useLocalStorage('slidev-editor-height', isClient ? window.innerHeight * 0.4 : 300, { listenToStorageChanges: false })
69
70 export const activeDragElement = shallowRef<DragElementState | null>(null)
71
72 export const presenterNotesFontSize = useLocalStorage('slidev-presenter-font-size', 1, { listenToStorageChanges: false })
73 export const presenterLayout = useLocalStorage('slidev-presenter-layout', 1, { listenToStorageChanges: false })
74
75 export const viewerCssFilterDefaults = {
76 invert: false,
77 contrast: 1,
78 brightness: 1,
79 hueRotate: 0,
80 saturate: 1,
81 sepia: 0,
82 }
83 export const viewerCssFilter = useLocalStorage(
84 'slidev-viewer-css-filter',
85 viewerCssFilterDefaults,
86 { listenToStorageChanges: false, mergeDefaults: true, deep: true },
87 )
88 export const hasViewerCssFilter = computed(() => {
89 return (Object.keys(viewerCssFilterDefaults) as (keyof typeof viewerCssFilterDefaults)[])
90 .some(k => viewerCssFilter.value[k] !== viewerCssFilterDefaults[k])
91 })
92
93 export function togglePresenterLayout() {
94 presenterLayout.value = presenterLayout.value + 1
95 if (presenterLayout.value > 3)
96 presenterLayout.value = 1
97 }
98
99 export function increasePresenterFontSize() {
100 presenterNotesFontSize.value = Math.min(2, presenterNotesFontSize.value + 0.1)
101 }
102
103 export function decreasePresenterFontSize() {
104 presenterNotesFontSize.value = Math.max(0.5, presenterNotesFontSize.value - 0.1)
105 }
106
107 export const toggleOverview = useToggle(showOverview)
108
109 export const syncDirections = useLocalStorage(
110 'slidev-sync-directions',
111 {
112 viewerSend: true,
113 viewerReceive: true,
114 presenterSend: true,
115 presenterReceive: true,
116 },
117 {
118 listenToStorageChanges: false,
119 mergeDefaults: true,
120 },
121 )
122
122 lines TYPESCRIPT