2021-07-19 01:28:09 -04:00
|
|
|
import Konva from "konva";
|
|
|
|
import { KonvaEventObject } from "konva/lib/Node";
|
|
|
|
import { useState } from "react";
|
2021-08-05 22:04:22 -04:00
|
|
|
import { v4 as uuid } from "uuid";
|
|
|
|
|
2021-08-05 02:24:46 -04:00
|
|
|
import Note from "../components/konva/Note";
|
2021-07-19 01:28:09 -04:00
|
|
|
import NoteDragOverlay from "../components/note/NoteDragOverlay";
|
|
|
|
import NoteMenu from "../components/note/NoteMenu";
|
|
|
|
import NoteTool from "../components/tools/NoteTool";
|
2021-08-05 22:04:22 -04:00
|
|
|
import { useBlur, useKeyboard } from "../contexts/KeyboardContext";
|
2021-08-05 00:36:57 -04:00
|
|
|
import { useUserId } from "../contexts/UserIdContext";
|
2021-08-05 22:04:22 -04:00
|
|
|
import shortcuts from "../shortcuts";
|
2021-07-20 06:17:41 -04:00
|
|
|
import {
|
|
|
|
NoteChangeEventHandler,
|
|
|
|
NoteCreateEventHander,
|
|
|
|
NoteRemoveEventHander,
|
|
|
|
} from "../types/Events";
|
2021-07-19 01:28:09 -04:00
|
|
|
import { Map, MapToolId } from "../types/Map";
|
|
|
|
import { MapState } from "../types/MapState";
|
2021-08-05 02:24:46 -04:00
|
|
|
import {
|
|
|
|
Note as NoteType,
|
|
|
|
NoteDraggingOptions,
|
|
|
|
NoteMenuOptions,
|
|
|
|
} from "../types/Note";
|
2021-07-19 01:28:09 -04:00
|
|
|
|
|
|
|
function useMapNotes(
|
|
|
|
map: Map | null,
|
|
|
|
mapState: MapState | null,
|
2021-07-20 06:17:41 -04:00
|
|
|
onNoteCreate: NoteCreateEventHander,
|
2021-07-19 01:28:09 -04:00
|
|
|
onNoteChange: NoteChangeEventHandler,
|
|
|
|
onNoteRemove: NoteRemoveEventHander,
|
2021-08-05 00:36:57 -04:00
|
|
|
selectedToolId: MapToolId
|
2021-07-19 01:28:09 -04:00
|
|
|
) {
|
2021-08-05 00:36:57 -04:00
|
|
|
const userId = useUserId();
|
|
|
|
const allowNoteEditing = !!(
|
|
|
|
map?.owner === userId || mapState?.editFlags.includes("notes")
|
|
|
|
);
|
|
|
|
|
2021-07-19 01:28:09 -04:00
|
|
|
const [isNoteMenuOpen, setIsNoteMenuOpen] = useState<boolean>(false);
|
|
|
|
const [noteMenuOptions, setNoteMenuOptions] = useState<NoteMenuOptions>();
|
|
|
|
const [noteDraggingOptions, setNoteDraggingOptions] =
|
|
|
|
useState<NoteDraggingOptions>();
|
2021-08-05 00:36:57 -04:00
|
|
|
|
2021-07-19 01:28:09 -04:00
|
|
|
function handleNoteMenuOpen(noteId: string, noteNode: Konva.Node) {
|
|
|
|
setNoteMenuOptions({ noteId, noteNode });
|
|
|
|
setIsNoteMenuOpen(true);
|
|
|
|
}
|
|
|
|
|
2021-08-05 02:24:46 -04:00
|
|
|
function handleNoteMenuClose() {
|
|
|
|
setIsNoteMenuOpen(false);
|
|
|
|
}
|
|
|
|
|
2021-07-22 02:40:33 -04:00
|
|
|
function handleNoteDragStart(_: KonvaEventObject<DragEvent>, noteId: string) {
|
2021-08-05 22:04:22 -04:00
|
|
|
if (duplicateNote) {
|
|
|
|
const note = mapState?.notes[noteId];
|
|
|
|
if (note) {
|
|
|
|
onNoteCreate([{ ...note, id: uuid() }]);
|
|
|
|
}
|
|
|
|
}
|
2021-07-22 02:40:33 -04:00
|
|
|
setNoteDraggingOptions({ dragging: true, noteId });
|
2021-07-19 01:28:09 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
function handleNoteDragEnd() {
|
|
|
|
noteDraggingOptions &&
|
|
|
|
setNoteDraggingOptions({ ...noteDraggingOptions, dragging: false });
|
|
|
|
}
|
|
|
|
|
2021-07-20 06:17:41 -04:00
|
|
|
function handleNoteRemove(noteIds: string[]) {
|
|
|
|
onNoteRemove(noteIds);
|
2021-07-19 01:28:09 -04:00
|
|
|
setNoteDraggingOptions(undefined);
|
|
|
|
}
|
|
|
|
|
2021-08-05 22:04:22 -04:00
|
|
|
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);
|
|
|
|
|
2021-07-19 01:28:09 -04:00
|
|
|
const notes = (
|
|
|
|
<NoteTool
|
|
|
|
map={map}
|
|
|
|
active={selectedToolId === "note"}
|
2021-07-20 06:17:41 -04:00
|
|
|
onNoteCreate={onNoteCreate}
|
2021-07-19 01:28:09 -04:00
|
|
|
onNoteMenuOpen={handleNoteMenuOpen}
|
2021-08-05 02:24:46 -04:00
|
|
|
>
|
|
|
|
{(mapState
|
|
|
|
? Object.values(mapState.notes).sort((a, b) =>
|
|
|
|
sortNotes(a, b, noteDraggingOptions)
|
|
|
|
)
|
|
|
|
: []
|
|
|
|
).map((note) => (
|
|
|
|
<Note
|
|
|
|
note={note}
|
|
|
|
map={map}
|
|
|
|
key={note.id}
|
|
|
|
onNoteMenuOpen={handleNoteMenuOpen}
|
|
|
|
onNoteMenuClose={handleNoteMenuClose}
|
|
|
|
draggable={
|
|
|
|
allowNoteEditing &&
|
|
|
|
(selectedToolId === "note" || selectedToolId === "move") &&
|
|
|
|
!note.locked
|
|
|
|
}
|
|
|
|
onNoteChange={onNoteChange}
|
|
|
|
onNoteDragStart={handleNoteDragStart}
|
|
|
|
onNoteDragEnd={handleNoteDragEnd}
|
|
|
|
fadeOnHover={selectedToolId === "drawing"}
|
|
|
|
selected={
|
|
|
|
!!noteMenuOptions &&
|
|
|
|
isNoteMenuOpen &&
|
|
|
|
noteMenuOptions.noteId === note.id
|
|
|
|
}
|
|
|
|
/>
|
|
|
|
))}
|
|
|
|
</NoteTool>
|
2021-07-19 01:28:09 -04:00
|
|
|
);
|
|
|
|
|
|
|
|
const noteMenu = (
|
|
|
|
<NoteMenu
|
|
|
|
isOpen={isNoteMenuOpen}
|
2021-08-05 02:24:46 -04:00
|
|
|
onRequestClose={handleNoteMenuClose}
|
2021-07-19 01:28:09 -04:00
|
|
|
onNoteChange={onNoteChange}
|
|
|
|
note={noteMenuOptions && mapState?.notes[noteMenuOptions.noteId]}
|
|
|
|
noteNode={noteMenuOptions?.noteNode}
|
|
|
|
map={map}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
|
|
|
|
const noteDragOverlay = noteDraggingOptions ? (
|
|
|
|
<NoteDragOverlay
|
2021-08-11 20:23:35 -04:00
|
|
|
draggingOptions={noteDraggingOptions}
|
2021-07-19 01:28:09 -04:00
|
|
|
onNoteRemove={handleNoteRemove}
|
|
|
|
/>
|
|
|
|
) : null;
|
|
|
|
|
|
|
|
return { notes, noteMenu, noteDragOverlay };
|
|
|
|
}
|
|
|
|
|
|
|
|
export default useMapNotes;
|
|
|
|
|
|
|
|
function sortNotes(
|
2021-08-05 02:24:46 -04:00
|
|
|
a: NoteType,
|
|
|
|
b: NoteType,
|
2021-07-19 01:28:09 -04:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|