@slidev/client 0.49.9 → 0.49.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/builtin/ShikiMagicMove.vue +7 -3
- package/composables/useDrawings.ts +4 -4
- package/composables/useWakeLock.ts +13 -0
- package/constants.ts +1 -0
- package/internals/ClicksSlider.vue +13 -6
- package/internals/NoteDisplay.vue +16 -10
- package/internals/NoteEditable.vue +4 -0
- package/internals/SelectList.vue +3 -3
- package/internals/Settings.vue +18 -3
- package/package.json +3 -3
- package/pages/notes.vue +12 -1
- package/pages/overview.vue +14 -3
- package/pages/play.vue +3 -0
- package/pages/presenter.vue +3 -0
- package/setup/root.ts +2 -0
- package/state/drawings.ts +6 -2
- package/state/index.ts +1 -0
- package/state/shared.ts +5 -0
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
import { ShikiMagicMovePrecompiled } from 'shiki-magic-move/vue'
|
|
3
3
|
import type { KeyedTokensInfo } from 'shiki-magic-move/types'
|
|
4
4
|
import type { PropType } from 'vue'
|
|
5
|
-
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
|
|
5
|
+
import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
|
|
6
6
|
import lz from 'lz-string'
|
|
7
|
+
import { sleep } from '@antfu/utils'
|
|
7
8
|
import { useSlideContext } from '../context'
|
|
8
9
|
import { makeId, updateCodeHighlightRange } from '../logic/utils'
|
|
9
10
|
import { useNav } from '../composables/useNav'
|
|
@@ -72,9 +73,12 @@ onMounted(() => {
|
|
|
72
73
|
}
|
|
73
74
|
currentClickSum += current.length || 1
|
|
74
75
|
}
|
|
75
|
-
stepIndex.value = step
|
|
76
76
|
|
|
77
|
-
|
|
77
|
+
nextTick(async () => {
|
|
78
|
+
stepIndex.value = step
|
|
79
|
+
|
|
80
|
+
await sleep(0)
|
|
81
|
+
|
|
78
82
|
const pre = container.value?.querySelector('.shiki') as HTMLElement
|
|
79
83
|
if (!pre)
|
|
80
84
|
return
|
|
@@ -2,7 +2,7 @@ import { computed, markRaw, nextTick, reactive, ref, watch } from 'vue'
|
|
|
2
2
|
import type { Brush, Options as DrauuOptions, DrawingMode } from 'drauu'
|
|
3
3
|
import { createDrauu } from 'drauu'
|
|
4
4
|
import { createSharedComposable, toReactive, useLocalStorage } from '@vueuse/core'
|
|
5
|
-
import { drawingState,
|
|
5
|
+
import { drawingState, onPatchDrawingState, patchDrawingState } from '../state/drawings'
|
|
6
6
|
import { configs } from '../env'
|
|
7
7
|
import { isInputting } from '../state'
|
|
8
8
|
import { useNav } from './useNav'
|
|
@@ -67,7 +67,7 @@ export const useDrawings = createSharedComposable(() => {
|
|
|
67
67
|
function clearDrauu() {
|
|
68
68
|
drauu.clear()
|
|
69
69
|
if (syncUp.value)
|
|
70
|
-
|
|
70
|
+
patchDrawingState(currentSlideNo.value, '')
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
function updateState() {
|
|
@@ -93,11 +93,11 @@ export const useDrawings = createSharedComposable(() => {
|
|
|
93
93
|
const dump = drauu.dump()
|
|
94
94
|
const key = currentSlideNo.value
|
|
95
95
|
if ((drawingState[key] || '') !== dump && syncUp.value)
|
|
96
|
-
|
|
96
|
+
patchDrawingState(key, drauu.dump())
|
|
97
97
|
}
|
|
98
98
|
})
|
|
99
99
|
|
|
100
|
-
|
|
100
|
+
onPatchDrawingState((state) => {
|
|
101
101
|
disableDump = true
|
|
102
102
|
if (state[currentSlideNo.value] != null)
|
|
103
103
|
drauu.load(state[currentSlideNo.value] || '')
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { useWakeLock as useVueUseWakeLock } from '@vueuse/core'
|
|
2
|
+
import { watchEffect } from 'vue'
|
|
3
|
+
import { wakeLockEnabled } from '../state'
|
|
4
|
+
|
|
5
|
+
export function useWakeLock() {
|
|
6
|
+
const { request, release } = useVueUseWakeLock()
|
|
7
|
+
|
|
8
|
+
watchEffect((onCleanup) => {
|
|
9
|
+
if (wakeLockEnabled.value)
|
|
10
|
+
request('screen')
|
|
11
|
+
onCleanup(release)
|
|
12
|
+
})
|
|
13
|
+
}
|
package/constants.ts
CHANGED
|
@@ -4,9 +4,13 @@ import { clamp, range } from '@antfu/utils'
|
|
|
4
4
|
import { computed } from 'vue'
|
|
5
5
|
import { CLICKS_MAX } from '../constants'
|
|
6
6
|
|
|
7
|
-
const props = defineProps<{
|
|
7
|
+
const props = withDefaults(defineProps<{
|
|
8
8
|
clicksContext: ClicksContext
|
|
9
|
-
|
|
9
|
+
readonly?: boolean
|
|
10
|
+
active?: boolean
|
|
11
|
+
}>(), {
|
|
12
|
+
active: true,
|
|
13
|
+
})
|
|
10
14
|
|
|
11
15
|
const total = computed(() => props.clicksContext.total)
|
|
12
16
|
const start = computed(() => clamp(0, props.clicksContext.clicksStart, total.value))
|
|
@@ -24,6 +28,8 @@ const current = computed({
|
|
|
24
28
|
const clicksRange = computed(() => range(start.value, total.value + 1))
|
|
25
29
|
|
|
26
30
|
function onMousedown() {
|
|
31
|
+
if (props.readonly)
|
|
32
|
+
return
|
|
27
33
|
if (current.value < 0 || current.value > total.value)
|
|
28
34
|
current.value = 0
|
|
29
35
|
}
|
|
@@ -38,7 +44,7 @@ function onMousedown() {
|
|
|
38
44
|
<div class="flex gap-0.5 items-center min-w-16 font-mono mr1">
|
|
39
45
|
<carbon:cursor-1 text-sm op50 />
|
|
40
46
|
<div flex-auto />
|
|
41
|
-
<template v-if="current >= 0 && current !== CLICKS_MAX">
|
|
47
|
+
<template v-if="current >= 0 && current !== CLICKS_MAX && active">
|
|
42
48
|
<span text-primary>{{ current }}</span>
|
|
43
49
|
<span op25>/</span>
|
|
44
50
|
</template>
|
|
@@ -46,7 +52,6 @@ function onMousedown() {
|
|
|
46
52
|
</div>
|
|
47
53
|
<div
|
|
48
54
|
relative flex-auto h5 font-mono flex="~"
|
|
49
|
-
@dblclick="current = clicksContext.total"
|
|
50
55
|
>
|
|
51
56
|
<div
|
|
52
57
|
v-for="i of clicksRange" :key="i"
|
|
@@ -71,8 +76,10 @@ function onMousedown() {
|
|
|
71
76
|
</div>
|
|
72
77
|
<input
|
|
73
78
|
v-model="current"
|
|
74
|
-
class="range"
|
|
75
|
-
type="range" :min="start" :max="total" :step="1"
|
|
79
|
+
class="range"
|
|
80
|
+
type="range" :min="start" :max="total" :step="1"
|
|
81
|
+
absolute inset-0 z-10 op0
|
|
82
|
+
:class="readonly ? 'pointer-events-none' : ''"
|
|
76
83
|
:style="{ '--thumb-width': `${1 / (length + 1) * 100}%` }"
|
|
77
84
|
@mousedown="onMousedown"
|
|
78
85
|
@focus="event => (event.currentTarget as HTMLElement)?.blur()"
|
|
@@ -3,14 +3,20 @@ import { computed, nextTick, onMounted, ref, watch } from 'vue'
|
|
|
3
3
|
import type { ClicksContext } from '@slidev/types'
|
|
4
4
|
import { CLICKS_MAX } from '../constants'
|
|
5
5
|
|
|
6
|
-
const props =
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
6
|
+
const props = withDefaults(
|
|
7
|
+
defineProps<{
|
|
8
|
+
class?: string | string[]
|
|
9
|
+
noteHtml?: string
|
|
10
|
+
note?: string
|
|
11
|
+
highlight?: boolean
|
|
12
|
+
placeholder?: string
|
|
13
|
+
clicksContext?: ClicksContext
|
|
14
|
+
autoScroll?: boolean
|
|
15
|
+
}>(),
|
|
16
|
+
{
|
|
17
|
+
highlight: true,
|
|
18
|
+
},
|
|
19
|
+
)
|
|
14
20
|
|
|
15
21
|
const emit = defineEmits<{
|
|
16
22
|
(type: 'markerDblclick', e: MouseEvent, clicks: number): void
|
|
@@ -30,7 +36,7 @@ function highlightNote() {
|
|
|
30
36
|
const markers = Array.from(noteDisplay.value.querySelectorAll(`.${CLASS_MARKER}`)) as HTMLElement[]
|
|
31
37
|
|
|
32
38
|
const current = +(props.clicksContext?.current ?? CLICKS_MAX)
|
|
33
|
-
const disabled = current < 0 || current >= CLICKS_MAX
|
|
39
|
+
const disabled = current < 0 || current >= CLICKS_MAX || !props.highlight
|
|
34
40
|
|
|
35
41
|
const nodeToIgnores = new Set<Element>()
|
|
36
42
|
function ignoreParent(node: Element) {
|
|
@@ -114,7 +120,7 @@ function highlightNote() {
|
|
|
114
120
|
}
|
|
115
121
|
|
|
116
122
|
watch(
|
|
117
|
-
() => [props.noteHtml, props.clicksContext?.current],
|
|
123
|
+
() => [props.noteHtml, props.clicksContext?.current, props.highlight],
|
|
118
124
|
() => {
|
|
119
125
|
nextTick(() => {
|
|
120
126
|
highlightNote()
|
|
@@ -26,6 +26,9 @@ const props = defineProps({
|
|
|
26
26
|
clicksContext: {
|
|
27
27
|
type: Object as PropType<ClicksContext>,
|
|
28
28
|
},
|
|
29
|
+
highlight: {
|
|
30
|
+
default: true,
|
|
31
|
+
},
|
|
29
32
|
autoHeight: {
|
|
30
33
|
default: false,
|
|
31
34
|
},
|
|
@@ -112,6 +115,7 @@ watch(
|
|
|
112
115
|
:note-html="info?.noteHTML"
|
|
113
116
|
:clicks-context="clicksContext"
|
|
114
117
|
:auto-scroll="!autoHeight"
|
|
118
|
+
:highlight="props.highlight"
|
|
115
119
|
@marker-click="(e, clicks) => emit('markerClick', e, clicks)"
|
|
116
120
|
@marker-dblclick="(e, clicks) => emit('markerDblclick', e, clicks)"
|
|
117
121
|
/>
|
package/internals/SelectList.vue
CHANGED
|
@@ -5,7 +5,7 @@ import type { SelectionItem } from './types'
|
|
|
5
5
|
|
|
6
6
|
const props = defineProps({
|
|
7
7
|
modelValue: {
|
|
8
|
-
type: [Object, String, Number] as PropType<any>,
|
|
8
|
+
type: [Object, String, Number, Boolean] as PropType<any>,
|
|
9
9
|
},
|
|
10
10
|
title: {
|
|
11
11
|
type: String,
|
|
@@ -43,7 +43,7 @@ const value = useVModel(props, 'modelValue', emit, { passive: true })
|
|
|
43
43
|
|
|
44
44
|
<style lang="postcss" scoped>
|
|
45
45
|
.select-list {
|
|
46
|
-
@apply
|
|
46
|
+
@apply my-2;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
.item {
|
|
@@ -55,6 +55,6 @@ const value = useVModel(props, 'modelValue', emit, { passive: true })
|
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
.title {
|
|
58
|
-
@apply text-xs uppercase opacity-50 tracking-widest px-7 py-1;
|
|
58
|
+
@apply text-xs uppercase opacity-50 tracking-widest px-7 py-1 select-none text-nowrap;
|
|
59
59
|
}
|
|
60
60
|
</style>
|
package/internals/Settings.vue
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import {
|
|
2
|
+
import { useWakeLock } from '@vueuse/core'
|
|
3
|
+
import { slideScale, wakeLockEnabled } from '../state'
|
|
3
4
|
import SelectList from './SelectList.vue'
|
|
4
5
|
import type { SelectionItem } from './types'
|
|
5
6
|
|
|
6
|
-
const
|
|
7
|
+
const scaleItems: SelectionItem<number>[] = [
|
|
7
8
|
{
|
|
8
9
|
display: 'Fit',
|
|
9
10
|
value: 0,
|
|
@@ -13,10 +14,24 @@ const items: SelectionItem<number>[] = [
|
|
|
13
14
|
value: 1,
|
|
14
15
|
},
|
|
15
16
|
]
|
|
17
|
+
|
|
18
|
+
const { isSupported } = useWakeLock()
|
|
19
|
+
|
|
20
|
+
const wakeLockItems: SelectionItem<boolean>[] = [
|
|
21
|
+
{
|
|
22
|
+
display: 'Enabled',
|
|
23
|
+
value: true,
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
display: 'Disabled',
|
|
27
|
+
value: false,
|
|
28
|
+
},
|
|
29
|
+
]
|
|
16
30
|
</script>
|
|
17
31
|
|
|
18
32
|
<template>
|
|
19
33
|
<div class="text-sm select-none">
|
|
20
|
-
<SelectList v-model="slideScale" title="Scale" :items="
|
|
34
|
+
<SelectList v-model="slideScale" title="Scale" :items="scaleItems" />
|
|
35
|
+
<SelectList v-if="__SLIDEV_FEATURE_WAKE_LOCK__ && isSupported" v-model="wakeLockEnabled" title="Wake lock" :items="wakeLockItems" />
|
|
21
36
|
</div>
|
|
22
37
|
</template>
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@slidev/client",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.49.
|
|
4
|
+
"version": "0.49.11",
|
|
5
5
|
"description": "Presentation slides for developers",
|
|
6
6
|
"author": "antfu <anthonyfu117@hotmail.com>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -59,8 +59,8 @@
|
|
|
59
59
|
"vue": "^3.4.27",
|
|
60
60
|
"vue-router": "^4.3.2",
|
|
61
61
|
"yaml": "^2.4.2",
|
|
62
|
-
"@slidev/parser": "0.49.
|
|
63
|
-
"@slidev/types": "0.49.
|
|
62
|
+
"@slidev/parser": "0.49.11",
|
|
63
|
+
"@slidev/types": "0.49.11"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
66
66
|
"vite": "^5.2.12"
|
package/pages/notes.vue
CHANGED
|
@@ -8,7 +8,9 @@ import { fullscreen } from '../state'
|
|
|
8
8
|
|
|
9
9
|
import NoteDisplay from '../internals/NoteDisplay.vue'
|
|
10
10
|
import IconButton from '../internals/IconButton.vue'
|
|
11
|
+
import ClicksSlider from '../internals/ClicksSlider.vue'
|
|
11
12
|
import { useNav } from '../composables/useNav'
|
|
13
|
+
import { createClicksContextBase } from '../composables/useClicks'
|
|
12
14
|
|
|
13
15
|
useHead({ title: `Notes - ${slidesTitle}` })
|
|
14
16
|
|
|
@@ -32,6 +34,12 @@ function increaseFontSize() {
|
|
|
32
34
|
function decreaseFontSize() {
|
|
33
35
|
fontSize.value = fontSize.value - 1
|
|
34
36
|
}
|
|
37
|
+
|
|
38
|
+
const clicksContext = computed(() => {
|
|
39
|
+
const clicks = sharedState.lastUpdate?.type === 'viewer' ? sharedState.viewerClicks : sharedState.clicks
|
|
40
|
+
const total = sharedState.lastUpdate?.type === 'viewer' ? sharedState.viewerClicksTotal : sharedState.clicksTotal
|
|
41
|
+
return createClicksContextBase(ref(clicks), undefined, total)
|
|
42
|
+
})
|
|
35
43
|
</script>
|
|
36
44
|
|
|
37
45
|
<template>
|
|
@@ -49,10 +57,13 @@ function decreaseFontSize() {
|
|
|
49
57
|
:note="currentRoute?.meta.slide.note"
|
|
50
58
|
:note-html="currentRoute?.meta.slide.noteHTML"
|
|
51
59
|
:placeholder="`No notes for Slide ${pageNo}.`"
|
|
52
|
-
:clicks-context="
|
|
60
|
+
:clicks-context="clicksContext"
|
|
53
61
|
:auto-scroll="true"
|
|
54
62
|
/>
|
|
55
63
|
</div>
|
|
64
|
+
<div class="flex-none border-t border-main" px3 py2>
|
|
65
|
+
<ClicksSlider :clicks-context="clicksContext" readonly />
|
|
66
|
+
</div>
|
|
56
67
|
<div class="flex-none border-t border-main">
|
|
57
68
|
<div class="flex gap-1 items-center px-6 py-3">
|
|
58
69
|
<IconButton :title="isFullscreen ? 'Close fullscreen' : 'Enter fullscreen'" @click="toggleFullscreen">
|
package/pages/overview.vue
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { computed, nextTick, onMounted, reactive, ref } from 'vue'
|
|
2
|
+
import { computed, nextTick, onMounted, reactive, ref, shallowRef } from 'vue'
|
|
3
3
|
import { useHead } from '@unhead/vue'
|
|
4
4
|
import type { ClicksContext, SlideRoute } from '@slidev/types'
|
|
5
5
|
import { pathPrefix, slidesTitle } from '../env'
|
|
@@ -28,6 +28,7 @@ const wordCounts = computed(() => slides.value.map(route => wordCount(route.meta
|
|
|
28
28
|
const totalWords = computed(() => wordCounts.value.reduce((a, b) => a + b, 0))
|
|
29
29
|
const totalClicks = computed(() => slides.value.map(route => getSlideClicks(route)).reduce((a, b) => a + b, 0))
|
|
30
30
|
|
|
31
|
+
const activeSlide = shallowRef<SlideRoute>()
|
|
31
32
|
const clicksContextMap = new WeakMap<SlideRoute, ClicksContext>()
|
|
32
33
|
function getClicksContext(route: SlideRoute) {
|
|
33
34
|
// We create a local clicks context to calculate the total clicks of the slide
|
|
@@ -40,8 +41,15 @@ function getSlideClicks(route: SlideRoute) {
|
|
|
40
41
|
return route.meta?.clicks || getClicksContext(route)?.total
|
|
41
42
|
}
|
|
42
43
|
|
|
44
|
+
function toggleRoute(route: SlideRoute) {
|
|
45
|
+
if (activeSlide.value === route)
|
|
46
|
+
activeSlide.value = undefined
|
|
47
|
+
else
|
|
48
|
+
activeSlide.value = route
|
|
49
|
+
}
|
|
50
|
+
|
|
43
51
|
function wordCount(str: string) {
|
|
44
|
-
return str.match(/[\w
|
|
52
|
+
return str.match(/[\w`'\-]+/g)?.length || 0
|
|
45
53
|
}
|
|
46
54
|
|
|
47
55
|
function isElementInViewport(el: HTMLElement) {
|
|
@@ -185,9 +193,11 @@ onMounted(() => {
|
|
|
185
193
|
</div>
|
|
186
194
|
<ClicksSlider
|
|
187
195
|
v-if="getSlideClicks(route)"
|
|
196
|
+
:active="activeSlide === route"
|
|
188
197
|
:clicks-context="getClicksContext(route)"
|
|
189
198
|
class="w-full mt-2"
|
|
190
|
-
@dblclick="
|
|
199
|
+
@dblclick="toggleRoute(route)"
|
|
200
|
+
@click="activeSlide = route"
|
|
191
201
|
/>
|
|
192
202
|
</div>
|
|
193
203
|
<div class="py3 mt-0.5 mr--8 ml--4 op0 transition group-hover:op100">
|
|
@@ -204,6 +214,7 @@ onMounted(() => {
|
|
|
204
214
|
:no="route.no"
|
|
205
215
|
class="max-w-250 w-250 text-lg rounded p3"
|
|
206
216
|
:auto-height="true"
|
|
217
|
+
:highlight="activeSlide === route"
|
|
207
218
|
:editing="edittingNote === route.no"
|
|
208
219
|
:clicks-context="getClicksContext(route)"
|
|
209
220
|
@dblclick="edittingNote !== route.no ? edittingNote = route.no : null"
|
package/pages/play.vue
CHANGED
|
@@ -10,6 +10,7 @@ import SlidesShow from '../internals/SlidesShow.vue'
|
|
|
10
10
|
import PrintStyle from '../internals/PrintStyle.vue'
|
|
11
11
|
import { onContextMenu } from '../logic/contextMenu'
|
|
12
12
|
import { useNav } from '../composables/useNav'
|
|
13
|
+
import { useWakeLock } from '../composables/useWakeLock'
|
|
13
14
|
import { useDrawings } from '../composables/useDrawings'
|
|
14
15
|
import PresenterMouse from '../internals/PresenterMouse.vue'
|
|
15
16
|
|
|
@@ -32,6 +33,8 @@ function onClick(e: MouseEvent) {
|
|
|
32
33
|
|
|
33
34
|
useSwipeControls(root)
|
|
34
35
|
registerShortcuts()
|
|
36
|
+
if (__SLIDEV_FEATURE_WAKE_LOCK__)
|
|
37
|
+
useWakeLock()
|
|
35
38
|
|
|
36
39
|
const persistNav = computed(() => isScreenVertical.value || showEditor.value)
|
|
37
40
|
|
package/pages/presenter.vue
CHANGED
|
@@ -24,11 +24,14 @@ import ClicksSlider from '../internals/ClicksSlider.vue'
|
|
|
24
24
|
import ContextMenu from '../internals/ContextMenu.vue'
|
|
25
25
|
import { useNav } from '../composables/useNav'
|
|
26
26
|
import { useDrawings } from '../composables/useDrawings'
|
|
27
|
+
import { useWakeLock } from '../composables/useWakeLock'
|
|
27
28
|
|
|
28
29
|
const main = ref<HTMLDivElement>()
|
|
29
30
|
|
|
30
31
|
registerShortcuts()
|
|
31
32
|
useSwipeControls(main)
|
|
33
|
+
if (__SLIDEV_FEATURE_WAKE_LOCK__)
|
|
34
|
+
useWakeLock()
|
|
32
35
|
|
|
33
36
|
const {
|
|
34
37
|
clicksContext,
|
package/setup/root.ts
CHANGED
|
@@ -67,10 +67,12 @@ export default function setupRoot() {
|
|
|
67
67
|
if (isPresenter.value) {
|
|
68
68
|
patch('page', +currentSlideNo.value)
|
|
69
69
|
patch('clicks', clicksContext.value.current)
|
|
70
|
+
patch('clicksTotal', clicksContext.value.total)
|
|
70
71
|
}
|
|
71
72
|
else {
|
|
72
73
|
patch('viewerPage', +currentSlideNo.value)
|
|
73
74
|
patch('viewerClicks', clicksContext.value.current)
|
|
75
|
+
patch('viewerClicksTotal', clicksContext.value.total)
|
|
74
76
|
}
|
|
75
77
|
|
|
76
78
|
patch('lastUpdate', {
|
package/state/drawings.ts
CHANGED
|
@@ -3,5 +3,9 @@ import { createSyncState } from './syncState'
|
|
|
3
3
|
|
|
4
4
|
export type DrawingsState = Record<number, string | undefined>
|
|
5
5
|
|
|
6
|
-
const {
|
|
7
|
-
|
|
6
|
+
export const {
|
|
7
|
+
init: initDrawingState,
|
|
8
|
+
onPatch: onPatchDrawingState,
|
|
9
|
+
patch: patchDrawingState,
|
|
10
|
+
state: drawingState,
|
|
11
|
+
} = createSyncState<DrawingsState>(serverDrawingState, serverDrawingState, __SLIDEV_FEATURE_DRAWINGS_PERSIST__)
|
package/state/index.ts
CHANGED
|
@@ -25,6 +25,7 @@ export const isOnFocus = computed(() => ['BUTTON', 'A'].includes(activeElement.v
|
|
|
25
25
|
export const currentCamera = useLocalStorage<string>('slidev-camera', 'default', { listenToStorageChanges: false })
|
|
26
26
|
export const currentMic = useLocalStorage<string>('slidev-mic', 'default', { listenToStorageChanges: false })
|
|
27
27
|
export const slideScale = useLocalStorage<number>('slidev-scale', 0)
|
|
28
|
+
export const wakeLockEnabled = useLocalStorage('slidev-wake-lock', true)
|
|
28
29
|
|
|
29
30
|
export const showPresenterCursor = useLocalStorage('slidev-presenter-cursor', true, { listenToStorageChanges: false })
|
|
30
31
|
export const showEditor = useLocalStorage('slidev-show-editor', false, { listenToStorageChanges: false })
|
package/state/shared.ts
CHANGED
|
@@ -4,6 +4,8 @@ import { createSyncState } from './syncState'
|
|
|
4
4
|
export interface SharedState {
|
|
5
5
|
page: number
|
|
6
6
|
clicks: number
|
|
7
|
+
clicksTotal: number
|
|
8
|
+
|
|
7
9
|
cursor?: {
|
|
8
10
|
x: number
|
|
9
11
|
y: number
|
|
@@ -11,6 +13,7 @@ export interface SharedState {
|
|
|
11
13
|
|
|
12
14
|
viewerPage: number
|
|
13
15
|
viewerClicks: number
|
|
16
|
+
viewerClicksTotal: number
|
|
14
17
|
|
|
15
18
|
lastUpdate?: {
|
|
16
19
|
id: string
|
|
@@ -22,8 +25,10 @@ export interface SharedState {
|
|
|
22
25
|
const { init, onPatch, patch, state } = createSyncState<SharedState>(serverState, {
|
|
23
26
|
page: 1,
|
|
24
27
|
clicks: 0,
|
|
28
|
+
clicksTotal: 0,
|
|
25
29
|
viewerPage: 1,
|
|
26
30
|
viewerClicks: 0,
|
|
31
|
+
viewerClicksTotal: 0,
|
|
27
32
|
})
|
|
28
33
|
|
|
29
34
|
export {
|