import Konva from "konva"; import { Group } from "react-konva"; import { KonvaEventObject } from "konva/lib/Node"; import { useState } from "react"; import { v4 as uuid } from "uuid"; import Note from "../components/konva/Note"; import NoteDragOverlay from "../components/note/NoteDragOverlay"; import NoteMenu from "../components/note/NoteMenu"; import NoteTool from "../components/tools/NoteTool"; import { useBlur, useKeyboard } from "../contexts/KeyboardContext"; import { useUserId } from "../contexts/UserIdContext"; import shortcuts from "../shortcuts"; import { NoteChangeEventHandler, NoteCreateEventHander, NoteRemoveEventHander, } from "../types/Events"; import { Map, MapToolId } from "../types/Map"; import { MapState } from "../types/MapState"; import { Note as NoteType, NoteDraggingOptions, NoteMenuOptions, } from "../types/Note"; function useMapNotes( map: Map | null, mapState: MapState | null, onNoteCreate: NoteCreateEventHander, onNoteChange: NoteChangeEventHandler, onNoteRemove: NoteRemoveEventHander, selectedToolId: MapToolId ) { const userId = useUserId(); const allowNoteEditing = !!( map?.owner === userId || mapState?.editFlags.includes("notes") ); const [isNoteMenuOpen, setIsNoteMenuOpen] = useState(false); const [noteMenuOptions, setNoteMenuOptions] = useState(); const [noteDraggingOptions, setNoteDraggingOptions] = useState(); function handleNoteMenuOpen( noteId: string, noteNode: Konva.Node, focus: boolean ) { setNoteMenuOptions({ noteId, noteNode, focus }); setIsNoteMenuOpen(true); } function handleNoteMenuClose() { setIsNoteMenuOpen(false); } function handleNoteDragStart(_: KonvaEventObject, noteId: string) { if (duplicateNote) { const note = mapState?.notes[noteId]; if (note) { onNoteCreate([{ ...note, id: uuid() }]); } } setNoteDraggingOptions({ dragging: true, noteId }); } function handleNoteDragEnd() { noteDraggingOptions && setNoteDraggingOptions({ ...noteDraggingOptions, dragging: false }); } function handleNoteRemove(noteIds: string[]) { onNoteRemove(noteIds); setNoteDraggingOptions(undefined); } const [duplicateNote, setDuplicateNote] = useState(false); function handleKeyDown(event: KeyboardEvent) { if (shortcuts.duplicate(event)) { setDuplicateNote(true); } } function handleKeyUp(event: KeyboardEvent) { if (shortcuts.duplicate(event)) { setDuplicateNote(false); } } function handleBlur() { setDuplicateNote(false); } useKeyboard(handleKeyDown, handleKeyUp); useBlur(handleBlur); const notes = ( {(mapState ? Object.values(mapState.notes).sort((a, b) => sortNotes(a, b, noteDraggingOptions) ) : [] ).map((note) => ( ))} ); const noteMenu = ( ); const noteDragOverlay = noteDraggingOptions ? ( ) : null; return { notes, noteMenu, noteDragOverlay }; } export default useMapNotes; function sortNotes( a: NoteType, b: NoteType, noteDraggingOptions?: NoteDraggingOptions ) { if ( noteDraggingOptions && noteDraggingOptions.dragging && noteDraggingOptions.noteId === a.id ) { // If dragging token `a` move above return 1; } else if ( noteDraggingOptions && noteDraggingOptions.dragging && noteDraggingOptions.noteId === b.id ) { // If dragging token `b` move above return -1; } else { // Else sort so last modified is on top return a.lastModified - b.lastModified; } }