返回 slidev
useSlideInfo.ts
根目录 / packages / client / composables / useSlideInfo.ts
1 import type { SlideInfo, SlidePatch } from '@slidev/types'
2 import type { MaybeRef, Ref } from 'vue'
3 import { useFetch } from '@vueuse/core'
4 import { computed, ref, unref } from 'vue'
5 import { getSlide } from '../logic/slides'
6
7 export interface UseSlideInfo {
8 info: Ref<SlideInfo | null>
9 update: (data: SlidePatch) => Promise<SlideInfo | void>
10 }
11
12 export function useSlideInfo(no: number): UseSlideInfo {
13 if (!__SLIDEV_HAS_SERVER__) {
14 return {
15 info: ref(getSlide(no)?.meta.slide ?? null) as Ref<SlideInfo | null>,
16 update: async () => {},
17 }
18 }
19 const url = `/__slidev/slides/${no}.json`
20 const { data: info, execute } = useFetch(url).json<SlideInfo>().get()
21
22 execute()
23
24 const update = async (data: SlidePatch) => {
25 return await fetch(
26 url,
27 {
28 method: 'POST',
29 headers: {
30 'Accept': 'application/json',
31 'Content-Type': 'application/json',
32 },
33 body: JSON.stringify(data),
34 },
35 ).then(r => r.json())
36 }
37
38 if (__DEV__) {
39 import.meta.hot?.on('slidev:update-slide', (payload) => {
40 if (payload.no === no)
41 info.value = payload.data
42 })
43 import.meta.hot?.on('slidev:update-note', (payload) => {
44 if (payload.no === no && info.value && info.value.note?.trim() !== payload.note?.trim())
45 info.value = { ...info.value, ...payload }
46 })
47 }
48
49 return {
50 info,
51 update,
52 }
53 }
54
55 const map: Record<number, UseSlideInfo> = {}
56
57 export function useDynamicSlideInfo(no: MaybeRef<number>) {
58 function get(no: number) {
59 return map[no] ??= useSlideInfo(no)
60 }
61
62 return {
63 info: computed({
64 get() {
65 return get(unref(no)).info.value
66 },
67 set(newInfo) {
68 get(unref(no)).info.value = newInfo
69 },
70 }),
71 update: async (data: SlidePatch, newId?: number) => {
72 const info = get(newId ?? unref(no))
73 const newData = await info.update(data)
74 if (newData)
75 info.info.value = newData
76 return newData
77 },
78 }
79 }
80
80 lines TYPESCRIPT