| 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 |