diff --git a/src/components/map/Map.js b/src/components/map/Map.js
index 7a35759..05f806d 100644
--- a/src/components/map/Map.js
+++ b/src/components/map/Map.js
@@ -33,6 +33,7 @@ function Map({
onFogDraw,
onFogDrawUndo,
onFogDrawRedo,
+ onMapNoteAdd,
allowMapDrawing,
allowFogDrawing,
allowMapChange,
@@ -356,6 +357,9 @@ function Map({
active={selectedToolId === "note"}
gridSize={gridSizeNormalized}
selectedToolSettings={settings[selectedToolId]}
+ onNoteAdd={onMapNoteAdd}
+ // TODO: Sort by last modified
+ notes={mapState ? Object.values(mapState.notes) : []}
/>
);
diff --git a/src/components/map/MapNote.js b/src/components/map/MapNote.js
new file mode 100644
index 0000000..bd95179
--- /dev/null
+++ b/src/components/map/MapNote.js
@@ -0,0 +1,31 @@
+import React, { useContext } from "react";
+import { Group, Rect } from "react-konva";
+
+import MapInteractionContext from "../../contexts/MapInteractionContext";
+
+function MapNote({ note, map }) {
+ const { mapWidth, mapHeight } = useContext(MapInteractionContext);
+
+ const noteWidth = map && (mapWidth / map.grid.size.x) * note.size;
+ const noteHeight = map && (mapHeight / map.grid.size.y) * note.size;
+
+ return (
+
+
+
+ );
+}
+
+export default MapNote;
diff --git a/src/components/map/MapNotes.js b/src/components/map/MapNotes.js
index 8d3ba34..64a0463 100644
--- a/src/components/map/MapNotes.js
+++ b/src/components/map/MapNotes.js
@@ -1,21 +1,31 @@
import React, { useContext, useState, useEffect } from "react";
-import { Group, Rect } from "react-konva";
+import shortid from "shortid";
+import { Group } from "react-konva";
import MapInteractionContext from "../../contexts/MapInteractionContext";
import MapStageContext from "../../contexts/MapStageContext";
+import AuthContext from "../../contexts/AuthContext";
import { getBrushPositionForTool } from "../../helpers/drawing";
import { getRelativePointerPositionNormalized } from "../../helpers/konva";
+import MapNote from "./MapNote";
+
const defaultNoteSize = 2;
-function MapNotes({ map, selectedToolSettings, active, gridSize }) {
- const { mapWidth, mapHeight, interactionEmitter } = useContext(
- MapInteractionContext
- );
+function MapNotes({
+ map,
+ selectedToolSettings,
+ active,
+ gridSize,
+ onNoteAdd,
+ notes,
+}) {
+ const { interactionEmitter } = useContext(MapInteractionContext);
+ const { userId } = useContext(AuthContext);
const mapStageRef = useContext(MapStageContext);
const [isBrushDown, setIsBrushDown] = useState(false);
- const [brushPosition, setBrushPosition] = useState({ x: 0, y: 0 });
+ const [noteData, setNoteData] = useState(null);
useEffect(() => {
if (!active) {
@@ -36,17 +46,34 @@ function MapNotes({ map, selectedToolSettings, active, gridSize }) {
}
function handleBrushDown() {
- setBrushPosition(getBrushPosition());
+ const brushPosition = getBrushPosition();
+ setNoteData({
+ x: brushPosition.x,
+ y: brushPosition.y,
+ size: defaultNoteSize,
+ text: "",
+ id: shortid.generate(),
+ lastModified: Date.now(),
+ lastModifiedBy: userId,
+ visible: true,
+ locked: false,
+ });
setIsBrushDown(true);
}
function handleBrushMove() {
- setBrushPosition(getBrushPosition());
+ const brushPosition = getBrushPosition();
+ setNoteData((prev) => ({
+ ...prev,
+ x: brushPosition.x,
+ y: brushPosition.y,
+ }));
setIsBrushDown(true);
}
function handleBrushUp() {
- setBrushPosition({ x: 0, y: 0 });
+ onNoteAdd(noteData);
+ setNoteData(null);
setIsBrushDown(false);
}
@@ -61,25 +88,12 @@ function MapNotes({ map, selectedToolSettings, active, gridSize }) {
};
});
- const noteWidth = map && (mapWidth / map.grid.size.x) * defaultNoteSize;
- const noteHeight = map && (mapHeight / map.grid.size.y) * defaultNoteSize;
-
return (
- {isBrushDown && (
-
- )}
+ {notes.map((note) => (
+
+ ))}
+ {isBrushDown && noteData && }
);
}
diff --git a/src/database.js b/src/database.js
index 8c233fd..91cf035 100644
--- a/src/database.js
+++ b/src/database.js
@@ -268,6 +268,17 @@ function loadVersions(db) {
token.height = tokenSizes[token.id].height;
});
});
+ // v1.7.0 - Added note tool
+ db.version(16)
+ .stores({})
+ .upgrade((tx) => {
+ return tx
+ .table("states")
+ .toCollection()
+ .modify((state) => {
+ state.notes = {};
+ });
+ });
}
// Get the dexie database used in DatabaseContext
diff --git a/src/network/NetworkedMapAndTokens.js b/src/network/NetworkedMapAndTokens.js
index 0640690..98c992a 100644
--- a/src/network/NetworkedMapAndTokens.js
+++ b/src/network/NetworkedMapAndTokens.js
@@ -167,6 +167,17 @@ function NetworkedMapAndTokens({ session }) {
session.send("mapFogIndex", index);
}
+ function handleNoteAdd(note) {
+ setCurrentMapState((prevMapState) => ({
+ ...prevMapState,
+ notes: {
+ ...prevMapState.notes,
+ [note.id]: note,
+ },
+ }));
+ session.send("mapNoteAdd", note);
+ }
+
/**
* Token state
*/
@@ -395,6 +406,15 @@ function NetworkedMapAndTokens({ session }) {
fogDrawActionIndex: data,
}));
}
+ if (id === "mapNoteAdd" && currentMapState) {
+ setCurrentMapState((prevMapState) => ({
+ ...prevMapState,
+ notes: {
+ ...prevMapState.notes,
+ [data.id]: data,
+ },
+ }));
+ }
}
function handlePeerDataProgress({ id, total, count }) {
@@ -460,6 +480,7 @@ function NetworkedMapAndTokens({ session }) {
onFogDraw={handleFogDraw}
onFogDrawUndo={handleFogDrawUndo}
onFogDrawRedo={handleFogDrawRedo}
+ onMapNoteAdd={handleNoteAdd}
allowMapDrawing={canEditMapDrawing}
allowFogDrawing={canEditFogDrawing}
allowMapChange={canChangeMap}