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