| import { onMounted, onUnmounted } from 'vue' |
| import { storeToRefs } from 'pinia' |
| import { useMainStore, useSlidesStore, useKeyboardStore } from '@/store' |
| import { ElementOrderCommands } from '@/types/edit' |
| import { KEYS } from '@/configs/hotkey' |
|
|
| import useSlideHandler from './useSlideHandler' |
| import useLockElement from './useLockElement' |
| import useDeleteElement from './useDeleteElement' |
| import useCombineElement from './useCombineElement' |
| import useCopyAndPasteElement from './useCopyAndPasteElement' |
| import useSelectElement from './useSelectElement' |
| import useMoveElement from './useMoveElement' |
| import useOrderElement from './useOrderElement' |
| import useHistorySnapshot from './useHistorySnapshot' |
| import useScreening from './useScreening' |
| import useScaleCanvas from './useScaleCanvas' |
|
|
| export default () => { |
| const mainStore = useMainStore() |
| const keyboardStore = useKeyboardStore() |
| const { |
| activeElementIdList, |
| disableHotkeys, |
| handleElement, |
| handleElementId, |
| editorAreaFocus, |
| thumbnailsFocus, |
| showSearchPanel, |
| } = storeToRefs(mainStore) |
| const { currentSlide } = storeToRefs(useSlidesStore()) |
| const { ctrlKeyState, shiftKeyState, spaceKeyState } = storeToRefs(keyboardStore) |
|
|
| const { |
| updateSlideIndex, |
| copySlide, |
| createSlide, |
| deleteSlide, |
| cutSlide, |
| copyAndPasteSlide, |
| selectAllSlide, |
| } = useSlideHandler() |
|
|
| const { combineElements, uncombineElements } = useCombineElement() |
| const { deleteElement } = useDeleteElement() |
| const { lockElement } = useLockElement() |
| const { copyElement, cutElement, quickCopyElement } = useCopyAndPasteElement() |
| const { selectAllElements } = useSelectElement() |
| const { moveElement } = useMoveElement() |
| const { orderElement } = useOrderElement() |
| const { redo, undo } = useHistorySnapshot() |
| const { enterScreening, enterScreeningFromStart } = useScreening() |
| const { scaleCanvas, resetCanvas } = useScaleCanvas() |
|
|
| const copy = () => { |
| if (activeElementIdList.value.length) copyElement() |
| else if (thumbnailsFocus.value) copySlide() |
| } |
|
|
| const cut = () => { |
| if (activeElementIdList.value.length) cutElement() |
| else if (thumbnailsFocus.value) cutSlide() |
| } |
|
|
| const quickCopy = () => { |
| if (activeElementIdList.value.length) quickCopyElement() |
| else if (thumbnailsFocus.value) copyAndPasteSlide() |
| } |
|
|
| const selectAll = () => { |
| if (editorAreaFocus.value) selectAllElements() |
| if (thumbnailsFocus.value) selectAllSlide() |
| } |
|
|
| const lock = () => { |
| if (!editorAreaFocus.value) return |
| lockElement() |
| } |
| const combine = () => { |
| if (!editorAreaFocus.value) return |
| combineElements() |
| } |
|
|
| const uncombine = () => { |
| if (!editorAreaFocus.value) return |
| uncombineElements() |
| } |
|
|
| const remove = () => { |
| if (activeElementIdList.value.length) deleteElement() |
| else if (thumbnailsFocus.value) deleteSlide() |
| } |
|
|
| const move = (key: string) => { |
| if (activeElementIdList.value.length) moveElement(key) |
| else if (key === KEYS.UP || key === KEYS.DOWN) updateSlideIndex(key) |
| } |
|
|
| const moveSlide = (key: string) => { |
| if (key === KEYS.PAGEUP) updateSlideIndex(KEYS.UP) |
| else if (key === KEYS.PAGEDOWN) updateSlideIndex(KEYS.DOWN) |
| } |
|
|
| const order = (command: ElementOrderCommands) => { |
| if (!handleElement.value) return |
| orderElement(handleElement.value, command) |
| } |
|
|
| const create = () => { |
| if (!thumbnailsFocus.value) return |
| createSlide() |
| } |
|
|
| const tabActiveElement = () => { |
| if (!currentSlide.value.elements.length) return |
| if (!handleElementId.value) { |
| const firstElement = currentSlide.value.elements[0] |
| mainStore.setActiveElementIdList([firstElement.id]) |
| return |
| } |
| const currentIndex = currentSlide.value.elements.findIndex(el => el.id === handleElementId.value) |
| const nextIndex = currentIndex >= currentSlide.value.elements.length - 1 ? 0 : currentIndex + 1 |
| const nextElementId = currentSlide.value.elements[nextIndex].id |
|
|
| mainStore.setActiveElementIdList([nextElementId]) |
| } |
|
|
| const keydownListener = (e: KeyboardEvent) => { |
| const { ctrlKey, shiftKey, altKey, metaKey } = e |
| const ctrlOrMetaKeyActive = ctrlKey || metaKey |
| |
| const key = e.key.toUpperCase() |
|
|
| if (ctrlOrMetaKeyActive && !ctrlKeyState.value) keyboardStore.setCtrlKeyState(true) |
| if (shiftKey && !shiftKeyState.value) keyboardStore.setShiftKeyState(true) |
| if (!disableHotkeys.value && key === KEYS.SPACE) keyboardStore.setSpaceKeyState(true) |
|
|
| |
| if (ctrlOrMetaKeyActive && key === KEYS.P) { |
| e.preventDefault() |
| mainStore.setDialogForExport('pdf') |
| return |
| } |
| if (shiftKey && key === KEYS.F5) { |
| e.preventDefault() |
| enterScreening() |
| keyboardStore.setShiftKeyState(false) |
| return |
| } |
| if (key === KEYS.F5) { |
| e.preventDefault() |
| enterScreeningFromStart() |
| return |
| } |
| if (ctrlKey && key === KEYS.F) { |
| e.preventDefault() |
| mainStore.setSearchPanelState(!showSearchPanel.value) |
| return |
| } |
| if (ctrlKey && key === KEYS.MINUS) { |
| e.preventDefault() |
| scaleCanvas('-') |
| return |
| } |
| if (ctrlKey && key === KEYS.EQUAL) { |
| e.preventDefault() |
| scaleCanvas('+') |
| return |
| } |
| if (ctrlKey && key === KEYS.DIGIT_0) { |
| e.preventDefault() |
| resetCanvas() |
| return |
| } |
| |
| if (!editorAreaFocus.value && !thumbnailsFocus.value) return |
|
|
| if (ctrlOrMetaKeyActive && key === KEYS.C) { |
| if (disableHotkeys.value) return |
| e.preventDefault() |
| copy() |
| } |
| if (ctrlOrMetaKeyActive && key === KEYS.X) { |
| if (disableHotkeys.value) return |
| e.preventDefault() |
| cut() |
| } |
| if (ctrlOrMetaKeyActive && key === KEYS.D) { |
| if (disableHotkeys.value) return |
| e.preventDefault() |
| quickCopy() |
| } |
| if (ctrlOrMetaKeyActive && key === KEYS.Z) { |
| if (disableHotkeys.value) return |
| e.preventDefault() |
| undo() |
| } |
| if (ctrlOrMetaKeyActive && key === KEYS.Y) { |
| if (disableHotkeys.value) return |
| e.preventDefault() |
| redo() |
| } |
| if (ctrlOrMetaKeyActive && key === KEYS.A) { |
| if (disableHotkeys.value) return |
| e.preventDefault() |
| selectAll() |
| } |
| if (ctrlOrMetaKeyActive && key === KEYS.L) { |
| if (disableHotkeys.value) return |
| e.preventDefault() |
| lock() |
| } |
| if (!shiftKey && ctrlOrMetaKeyActive && key === KEYS.G) { |
| if (disableHotkeys.value) return |
| e.preventDefault() |
| combine() |
| } |
| if (shiftKey && ctrlOrMetaKeyActive && key === KEYS.G) { |
| if (disableHotkeys.value) return |
| e.preventDefault() |
| uncombine() |
| } |
| if (altKey && key === KEYS.F) { |
| if (disableHotkeys.value) return |
| e.preventDefault() |
| order(ElementOrderCommands.TOP) |
| } |
| if (altKey && key === KEYS.B) { |
| if (disableHotkeys.value) return |
| e.preventDefault() |
| order(ElementOrderCommands.BOTTOM) |
| } |
| if (key === KEYS.DELETE || key === KEYS.BACKSPACE) { |
| if (disableHotkeys.value) return |
| e.preventDefault() |
| remove() |
| } |
| if (key === KEYS.UP) { |
| if (disableHotkeys.value) return |
| e.preventDefault() |
| move(KEYS.UP) |
| } |
| if (key === KEYS.DOWN) { |
| if (disableHotkeys.value) return |
| e.preventDefault() |
| move(KEYS.DOWN) |
| } |
| if (key === KEYS.LEFT) { |
| if (disableHotkeys.value) return |
| e.preventDefault() |
| move(KEYS.LEFT) |
| } |
| if (key === KEYS.RIGHT) { |
| if (disableHotkeys.value) return |
| e.preventDefault() |
| move(KEYS.RIGHT) |
| } |
| if (key === KEYS.PAGEUP) { |
| if (disableHotkeys.value) return |
| e.preventDefault() |
| moveSlide(KEYS.PAGEUP) |
| } |
| if (key === KEYS.PAGEDOWN) { |
| if (disableHotkeys.value) return |
| e.preventDefault() |
| moveSlide(KEYS.PAGEDOWN) |
| } |
| if (key === KEYS.ENTER) { |
| if (disableHotkeys.value) return |
| e.preventDefault() |
| create() |
| } |
| if (key === KEYS.TAB) { |
| if (disableHotkeys.value) return |
| e.preventDefault() |
| tabActiveElement() |
| } |
| if (editorAreaFocus.value && !shiftKey && !ctrlOrMetaKeyActive && !disableHotkeys.value) { |
| if (key === KEYS.T) { |
| mainStore.setCreatingElement({ type: 'text' }) |
| } |
| else if (key === KEYS.R) { |
| mainStore.setCreatingElement({ type: 'shape', data: { |
| viewBox: [200, 200], |
| path: 'M 0 0 L 200 0 L 200 200 L 0 200 Z', |
| }}) |
| } |
| else if (key === KEYS.O) { |
| mainStore.setCreatingElement({ type: 'shape', data: { |
| viewBox: [200, 200], |
| path: 'M 100 0 A 50 50 0 1 1 100 200 A 50 50 0 1 1 100 0 Z', |
| }}) |
| } |
| else if (key === KEYS.L) { |
| mainStore.setCreatingElement({ type: 'line', data: { |
| path: 'M 0 0 L 20 20', |
| style: 'solid', |
| points: ['', ''], |
| }}) |
| } |
| } |
| } |
| |
| const keyupListener = () => { |
| if (ctrlKeyState.value) keyboardStore.setCtrlKeyState(false) |
| if (shiftKeyState.value) keyboardStore.setShiftKeyState(false) |
| if (spaceKeyState.value) keyboardStore.setSpaceKeyState(false) |
| } |
|
|
| onMounted(() => { |
| document.addEventListener('keydown', keydownListener) |
| document.addEventListener('keyup', keyupListener) |
| window.addEventListener('blur', keyupListener) |
| }) |
| onUnmounted(() => { |
| document.removeEventListener('keydown', keydownListener) |
| document.removeEventListener('keyup', keyupListener) |
| window.removeEventListener('blur', keyupListener) |
| }) |
| } |
|
|