Download frontend/src/hooks/useSlideHandler.ts from CatPtain/web_ppt: direct link, hf CLI and curl.
- Browser
- Download file 6.16 kB
-
https://huggingface.co/spaces/CatPtain/web_ppt/resolve/main/frontend/src/hooks/useSlideHandler.ts
- Command line
-
hf download hf://spaces/CatPtain/web_ppt/frontend/src/hooks/useSlideHandler.ts
-
curl -L -o useSlideHandler.ts https://huggingface.co/spaces/CatPtain/web_ppt/resolve/main/frontend/src/hooks/useSlideHandler.ts
6.16 kB
| import { computed } from 'vue' | |
| import { storeToRefs } from 'pinia' | |
| import { nanoid } from 'nanoid' | |
| import { useMainStore, useSlidesStore } from '@/store' | |
| import type { Slide } from '@/types/slides' | |
| import { copyText, readClipboard } from '@/utils/clipboard' | |
| import { encrypt } from '@/utils/crypto' | |
| import { createElementIdMap } from '@/utils/element' | |
| import { KEYS } from '@/configs/hotkey' | |
| import message from '@/utils/message' | |
| import usePasteTextClipboardData from '@/hooks/usePasteTextClipboardData' | |
| import useHistorySnapshot from '@/hooks/useHistorySnapshot' | |
| import useAddSlidesOrElements from '@/hooks/useAddSlidesOrElements' | |
| export default () => { | |
| const mainStore = useMainStore() | |
| const slidesStore = useSlidesStore() | |
| const { selectedSlidesIndex: _selectedSlidesIndex, activeElementIdList } = storeToRefs(mainStore) | |
| const { currentSlide, slides, theme, slideIndex } = storeToRefs(slidesStore) | |
| const selectedSlidesIndex = computed(() => [..._selectedSlidesIndex.value, slideIndex.value]) | |
| const selectedSlides = computed(() => slides.value.filter((item, index) => selectedSlidesIndex.value.includes(index))) | |
| const selectedSlidesId = computed(() => selectedSlides.value.map(item => item.id)) | |
| const { pasteTextClipboardData } = usePasteTextClipboardData() | |
| const { addSlidesFromData } = useAddSlidesOrElements() | |
| const { addHistorySnapshot } = useHistorySnapshot() | |
| // 重置幻灯片 | |
| const resetSlides = () => { | |
| const emptySlide: Slide = { | |
| id: nanoid(10), | |
| elements: [], | |
| background: { | |
| type: 'solid', | |
| color: theme.value.backgroundColor, | |
| }, | |
| } | |
| slidesStore.updateSlideIndex(0) | |
| mainStore.setActiveElementIdList([]) | |
| slidesStore.setSlides([emptySlide]) | |
| } | |
| /** | |
| * 移动页面焦点 | |
| * @param command 移动页面焦点命令:上移、下移 | |
| */ | |
| const updateSlideIndex = (command: string) => { | |
| if (command === KEYS.UP && slideIndex.value > 0) { | |
| if (activeElementIdList.value.length) mainStore.setActiveElementIdList([]) | |
| slidesStore.updateSlideIndex(slideIndex.value - 1) | |
| } | |
| else if (command === KEYS.DOWN && slideIndex.value < slides.value.length - 1) { | |
| if (activeElementIdList.value.length) mainStore.setActiveElementIdList([]) | |
| slidesStore.updateSlideIndex(slideIndex.value + 1) | |
| } | |
| } | |
| // 将当前页面数据加密后复制到剪贴板 | |
| const copySlide = () => { | |
| const text = encrypt(JSON.stringify({ | |
| type: 'slides', | |
| data: selectedSlides.value, | |
| })) | |
| copyText(text).then(() => { | |
| mainStore.setThumbnailsFocus(true) | |
| }) | |
| } | |
| // 尝试将剪贴板页面数据解密后添加到下一页(粘贴) | |
| const pasteSlide = () => { | |
| readClipboard().then(text => { | |
| pasteTextClipboardData(text, { onlySlide: true }) | |
| }).catch(err => message.warning(err)) | |
| } | |
| // 创建一页空白页并添加到下一页 | |
| const createSlide = () => { | |
| const emptySlide: Slide = { | |
| id: nanoid(10), | |
| elements: [], | |
| background: { | |
| type: 'solid', | |
| color: theme.value.backgroundColor, | |
| }, | |
| } | |
| mainStore.setActiveElementIdList([]) | |
| slidesStore.addSlide(emptySlide) | |
| addHistorySnapshot() | |
| } | |
| // 根据模板创建新页面 | |
| const createSlideByTemplate = (slide: Slide) => { | |
| const { groupIdMap, elIdMap } = createElementIdMap(slide.elements) | |
| for (const element of slide.elements) { | |
| element.id = elIdMap[element.id] | |
| if (element.groupId) element.groupId = groupIdMap[element.groupId] | |
| } | |
| const newSlide = { | |
| ...slide, | |
| id: nanoid(10), | |
| } | |
| mainStore.setActiveElementIdList([]) | |
| slidesStore.addSlide(newSlide) | |
| addHistorySnapshot() | |
| } | |
| // 将当前页复制一份到下一页 | |
| const copyAndPasteSlide = () => { | |
| const slide = JSON.parse(JSON.stringify(currentSlide.value)) | |
| addSlidesFromData([slide]) | |
| } | |
| // 删除当前页,若将删除全部页面,则执行重置幻灯片操作 | |
| const deleteSlide = (targetSlidesId = selectedSlidesId.value) => { | |
| if (slides.value.length === targetSlidesId.length) resetSlides() | |
| else slidesStore.deleteSlide(targetSlidesId) | |
| mainStore.updateSelectedSlidesIndex([]) | |
| addHistorySnapshot() | |
| } | |
| // 将当前页复制后删除(剪切) | |
| // 由于复制操作会导致多选状态消失,所以需要提前将需要删除的页面ID进行缓存 | |
| const cutSlide = () => { | |
| const targetSlidesId = [...selectedSlidesId.value] | |
| copySlide() | |
| deleteSlide(targetSlidesId) | |
| } | |
| // 选中全部幻灯片 | |
| const selectAllSlide = () => { | |
| const newSelectedSlidesIndex = Array.from(Array(slides.value.length), (item, index) => index) | |
| mainStore.setActiveElementIdList([]) | |
| mainStore.updateSelectedSlidesIndex(newSelectedSlidesIndex) | |
| } | |
| // 拖拽调整幻灯片顺序同步数据 | |
| const sortSlides = (newIndex: number, oldIndex: number) => { | |
| if (oldIndex === newIndex) return | |
| const _slides: Slide[] = JSON.parse(JSON.stringify(slides.value)) | |
| const movingSlide = _slides[oldIndex] | |
| const movingSlideSection = movingSlide.sectionTag | |
| if (movingSlideSection) { | |
| const movingSlideSectionNext = _slides[oldIndex + 1] | |
| delete movingSlide.sectionTag | |
| if (movingSlideSectionNext && !movingSlideSectionNext.sectionTag) { | |
| movingSlideSectionNext.sectionTag = movingSlideSection | |
| } | |
| } | |
| if (newIndex === 0) { | |
| const firstSection = _slides[0].sectionTag | |
| if (firstSection) { | |
| delete _slides[0].sectionTag | |
| movingSlide.sectionTag = firstSection | |
| } | |
| } | |
| const _slide = _slides[oldIndex] | |
| _slides.splice(oldIndex, 1) | |
| _slides.splice(newIndex, 0, _slide) | |
| slidesStore.setSlides(_slides) | |
| slidesStore.updateSlideIndex(newIndex) | |
| } | |
| const isEmptySlide = computed(() => { | |
| if (slides.value.length > 1) return false | |
| if (slides.value[0].elements.length > 0) return false | |
| return true | |
| }) | |
| return { | |
| resetSlides, | |
| updateSlideIndex, | |
| copySlide, | |
| pasteSlide, | |
| createSlide, | |
| createSlideByTemplate, | |
| copyAndPasteSlide, | |
| deleteSlide, | |
| cutSlide, | |
| selectAllSlide, | |
| sortSlides, | |
| isEmptySlide, | |
| } | |
| } |