2021-07-17 12:48:04 +10:00
|
|
|
import { useState, useEffect, useRef } from "react";
|
2020-11-03 17:15:39 +11:00
|
|
|
import shortid from "shortid";
|
|
|
|
|
import { Group } from "react-konva";
|
2021-07-17 12:48:04 +10:00
|
|
|
import Konva from "konva";
|
2020-11-03 16:21:39 +11:00
|
|
|
|
2021-03-12 11:02:58 +11:00
|
|
|
import { useInteractionEmitter } from "../../contexts/MapInteractionContext";
|
2021-02-06 13:32:38 +11:00
|
|
|
import { useMapStage } from "../../contexts/MapStageContext";
|
2021-06-24 16:14:20 +10:00
|
|
|
import { useUserId } from "../../contexts/UserIdContext";
|
2020-11-03 16:21:39 +11:00
|
|
|
|
2021-02-09 14:13:08 +11:00
|
|
|
import Vector2 from "../../helpers/Vector2";
|
|
|
|
|
import { getRelativePointerPosition } from "../../helpers/konva";
|
|
|
|
|
|
|
|
|
|
import useGridSnapping from "../../hooks/useGridSnapping";
|
2020-11-03 16:21:39 +11:00
|
|
|
|
2021-07-19 15:28:09 +10:00
|
|
|
import Note from "../konva/Note";
|
2020-11-03 17:15:39 +11:00
|
|
|
|
2021-07-17 12:48:04 +10:00
|
|
|
import { Map } from "../../types/Map";
|
|
|
|
|
import { Note as NoteType } from "../../types/Note";
|
|
|
|
|
import {
|
2021-07-20 20:17:41 +10:00
|
|
|
NoteCreateEventHander,
|
2021-07-17 12:48:04 +10:00
|
|
|
NoteChangeEventHandler,
|
|
|
|
|
NoteDragEventHandler,
|
|
|
|
|
NoteMenuOpenEventHandler,
|
|
|
|
|
} from "../../types/Events";
|
|
|
|
|
|
2020-11-03 16:21:39 +11:00
|
|
|
const defaultNoteSize = 2;
|
|
|
|
|
|
2021-07-17 12:48:04 +10:00
|
|
|
type MapNoteProps = {
|
2021-07-17 17:25:41 +10:00
|
|
|
map: Map | null;
|
2021-07-17 12:48:04 +10:00
|
|
|
active: boolean;
|
2021-07-20 20:17:41 +10:00
|
|
|
onNoteCreate: NoteCreateEventHander;
|
2021-07-17 12:48:04 +10:00
|
|
|
onNoteChange: NoteChangeEventHandler;
|
|
|
|
|
notes: NoteType[];
|
|
|
|
|
onNoteMenuOpen: NoteMenuOpenEventHandler;
|
|
|
|
|
draggable: boolean;
|
|
|
|
|
onNoteDragStart: NoteDragEventHandler;
|
|
|
|
|
onNoteDragEnd: NoteDragEventHandler;
|
|
|
|
|
fadeOnHover: boolean;
|
|
|
|
|
};
|
|
|
|
|
|
2021-07-19 15:28:09 +10:00
|
|
|
function NoteTool({
|
2020-11-03 17:15:39 +11:00
|
|
|
map,
|
|
|
|
|
active,
|
2021-07-20 20:17:41 +10:00
|
|
|
onNoteCreate,
|
2020-11-04 15:03:34 +11:00
|
|
|
onNoteChange,
|
2020-11-03 17:15:39 +11:00
|
|
|
notes,
|
2020-11-04 15:03:34 +11:00
|
|
|
onNoteMenuOpen,
|
2020-11-05 12:28:28 +11:00
|
|
|
draggable,
|
2020-11-05 14:41:33 +11:00
|
|
|
onNoteDragStart,
|
|
|
|
|
onNoteDragEnd,
|
2021-01-28 16:26:28 +11:00
|
|
|
fadeOnHover,
|
2021-07-17 12:48:04 +10:00
|
|
|
}: MapNoteProps) {
|
2021-03-12 11:02:58 +11:00
|
|
|
const interactionEmitter = useInteractionEmitter();
|
2021-06-24 16:14:20 +10:00
|
|
|
const userId = useUserId();
|
2021-02-06 13:32:38 +11:00
|
|
|
const mapStageRef = useMapStage();
|
2020-11-03 16:21:39 +11:00
|
|
|
const [isBrushDown, setIsBrushDown] = useState(false);
|
2021-07-17 12:48:04 +10:00
|
|
|
const [noteData, setNoteData] = useState<NoteType | null>(null);
|
2020-11-03 16:21:39 +11:00
|
|
|
|
2021-07-17 12:48:04 +10:00
|
|
|
const creatingNoteRef = useRef<Konva.Group>(null);
|
2020-11-04 15:03:34 +11:00
|
|
|
|
2021-02-09 14:13:08 +11:00
|
|
|
const snapPositionToGrid = useGridSnapping();
|
|
|
|
|
|
2020-11-03 16:21:39 +11:00
|
|
|
useEffect(() => {
|
|
|
|
|
if (!active) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const mapStage = mapStageRef.current;
|
|
|
|
|
|
2021-02-09 14:13:08 +11:00
|
|
|
function getBrushPosition() {
|
2021-07-17 12:48:04 +10:00
|
|
|
if (!mapStage) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2021-02-09 14:13:08 +11:00
|
|
|
const mapImage = mapStage.findOne("#mapImage");
|
|
|
|
|
let position = getRelativePointerPosition(mapImage);
|
2021-07-17 12:48:04 +10:00
|
|
|
if (!position) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2021-07-17 17:25:41 +10:00
|
|
|
if (map?.snapToGrid) {
|
2021-02-09 14:13:08 +11:00
|
|
|
position = snapPositionToGrid(position);
|
|
|
|
|
}
|
|
|
|
|
return Vector2.divide(position, {
|
|
|
|
|
x: mapImage.width(),
|
|
|
|
|
y: mapImage.height(),
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-22 15:00:31 +11:00
|
|
|
function handleBrushDown() {
|
2021-02-09 14:13:08 +11:00
|
|
|
const brushPosition = getBrushPosition();
|
2021-07-17 12:48:04 +10:00
|
|
|
if (!brushPosition || !userId) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2020-11-05 12:28:28 +11:00
|
|
|
setNoteData({
|
|
|
|
|
x: brushPosition.x,
|
|
|
|
|
y: brushPosition.y,
|
|
|
|
|
size: defaultNoteSize,
|
|
|
|
|
text: "",
|
|
|
|
|
id: shortid.generate(),
|
|
|
|
|
lastModified: Date.now(),
|
|
|
|
|
lastModifiedBy: userId,
|
|
|
|
|
visible: true,
|
|
|
|
|
locked: false,
|
|
|
|
|
color: "yellow",
|
2021-01-25 10:03:20 +11:00
|
|
|
textOnly: false,
|
2020-11-05 12:28:28 +11:00
|
|
|
});
|
|
|
|
|
setIsBrushDown(true);
|
2020-11-03 16:21:39 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function handleBrushMove() {
|
2020-11-27 12:23:57 +11:00
|
|
|
if (noteData) {
|
2021-02-09 14:13:08 +11:00
|
|
|
const brushPosition = getBrushPosition();
|
2021-07-17 12:48:04 +10:00
|
|
|
if (!brushPosition) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
setNoteData((prev) => {
|
|
|
|
|
if (!prev) {
|
|
|
|
|
return prev;
|
|
|
|
|
}
|
|
|
|
|
return {
|
|
|
|
|
...prev,
|
|
|
|
|
x: brushPosition.x,
|
|
|
|
|
y: brushPosition.y,
|
|
|
|
|
};
|
|
|
|
|
});
|
2020-11-27 12:23:57 +11:00
|
|
|
setIsBrushDown(true);
|
|
|
|
|
}
|
2020-11-03 16:21:39 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function handleBrushUp() {
|
2021-07-17 12:48:04 +10:00
|
|
|
if (noteData && creatingNoteRef.current) {
|
2021-07-20 20:17:41 +10:00
|
|
|
onNoteCreate([noteData]);
|
2020-11-04 15:03:34 +11:00
|
|
|
onNoteMenuOpen(noteData.id, creatingNoteRef.current);
|
|
|
|
|
}
|
2020-11-03 17:15:39 +11:00
|
|
|
setNoteData(null);
|
2020-11-03 16:21:39 +11:00
|
|
|
setIsBrushDown(false);
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-17 12:48:04 +10:00
|
|
|
interactionEmitter?.on("dragStart", handleBrushDown);
|
|
|
|
|
interactionEmitter?.on("drag", handleBrushMove);
|
|
|
|
|
interactionEmitter?.on("dragEnd", handleBrushUp);
|
2020-11-03 16:21:39 +11:00
|
|
|
|
|
|
|
|
return () => {
|
2021-07-17 12:48:04 +10:00
|
|
|
interactionEmitter?.off("dragStart", handleBrushDown);
|
|
|
|
|
interactionEmitter?.off("drag", handleBrushMove);
|
|
|
|
|
interactionEmitter?.off("dragEnd", handleBrushUp);
|
2020-11-03 16:21:39 +11:00
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return (
|
2021-07-21 18:56:18 +10:00
|
|
|
<Group id="notes">
|
2020-11-03 17:15:39 +11:00
|
|
|
{notes.map((note) => (
|
2020-11-05 14:41:33 +11:00
|
|
|
<Note
|
2020-11-04 15:03:34 +11:00
|
|
|
note={note}
|
|
|
|
|
map={map}
|
|
|
|
|
key={note.id}
|
|
|
|
|
onNoteMenuOpen={onNoteMenuOpen}
|
2020-11-05 15:30:22 +11:00
|
|
|
draggable={draggable && !note.locked}
|
2020-11-04 15:03:34 +11:00
|
|
|
onNoteChange={onNoteChange}
|
2020-11-05 14:41:33 +11:00
|
|
|
onNoteDragStart={onNoteDragStart}
|
|
|
|
|
onNoteDragEnd={onNoteDragEnd}
|
2021-01-28 16:26:28 +11:00
|
|
|
fadeOnHover={fadeOnHover}
|
2020-11-04 15:03:34 +11:00
|
|
|
/>
|
2020-11-03 17:15:39 +11:00
|
|
|
))}
|
2020-11-04 15:03:34 +11:00
|
|
|
<Group ref={creatingNoteRef}>
|
2021-07-17 12:48:04 +10:00
|
|
|
{isBrushDown && noteData && <Note note={noteData} map={map} />}
|
2020-11-04 15:03:34 +11:00
|
|
|
</Group>
|
2020-11-03 16:21:39 +11:00
|
|
|
</Group>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-19 15:28:09 +10:00
|
|
|
export default NoteTool;
|