diff --git a/frontend/react/src/constants/constants.ts b/frontend/react/src/constants/constants.ts
index 9d97ac45..a01141bb 100644
--- a/frontend/react/src/constants/constants.ts
+++ b/frontend/react/src/constants/constants.ts
@@ -259,6 +259,10 @@ export const NO_SUBSTATE = "No substate";
export enum UnitControlSubState {
NO_SUBSTATE = "No substate",
FORMATION = "Formation",
+ PROTECTION = "Protection",
+ MAP_CONTEXT_MENU = "Map context menu",
+ UNIT_CONTEXT_MENU = "Unit context menu",
+ UNIT_EXPLOSION_MENU = "Unit explosion menu"
}
export enum DrawSubState {
diff --git a/frontend/react/src/map/map.ts b/frontend/react/src/map/map.ts
index b20e14b3..5ee02085 100644
--- a/frontend/react/src/map/map.ts
+++ b/frontend/react/src/map/map.ts
@@ -19,6 +19,7 @@ import {
SpawnSubState,
DrawSubState,
JTACSubState,
+ UnitControlSubState,
} from "../constants/constants";
import { CoalitionPolygon } from "./coalitionarea/coalitionpolygon";
import { MapHiddenTypes, MapOptions } from "../types/types";
@@ -354,12 +355,12 @@ export class Map extends L.Map {
setContextActionSet(contextActionSet: ContextActionSet | null) {
this.#contextActionSet = contextActionSet;
- ContextActionSetChangedEvent.dispatch(this.#contextActionSet)
+ ContextActionSetChangedEvent.dispatch(this.#contextActionSet);
}
setContextAction(contextAction: ContextAction | null) {
this.#contextAction = contextAction;
- ContextActionChangedEvent.dispatch(this.#contextAction)
+ ContextActionChangedEvent.dispatch(this.#contextAction);
}
getCurrentControls() {
@@ -571,8 +572,10 @@ export class Map extends L.Map {
}
deselectAllCoalitionAreas() {
- CoalitionAreaSelectedEvent.dispatch(null);
- this.#coalitionAreas.forEach((coalitionArea: CoalitionPolygon | CoalitionCircle) => coalitionArea.setSelected(false));
+ if (this.getSelectedCoalitionArea() !== null) {
+ CoalitionAreaSelectedEvent.dispatch(null);
+ this.#coalitionAreas.forEach((coalitionArea: CoalitionPolygon | CoalitionCircle) => coalitionArea.setSelected(false));
+ }
}
deleteCoalitionArea(coalitionArea: CoalitionPolygon | CoalitionCircle) {
@@ -915,9 +918,6 @@ export class Map extends L.Map {
console.log(`Short press at ${pressLocation}`);
- document.dispatchEvent(new CustomEvent("hideMapContextMenu"));
- document.dispatchEvent(new CustomEvent("hideUnitContextMenu"));
-
/* Execute the short click action */
if (getApp().getState() === OlympusState.IDLE) {
/* Do nothing */
@@ -1040,7 +1040,7 @@ export class Map extends L.Map {
else document.dispatchEvent(new CustomEvent("forceboxselect", { detail: e.originalEvent }));
} else if (getApp().getState() === OlympusState.UNIT_CONTROL) {
if (e.originalEvent.button === 2) {
- document.dispatchEvent(new CustomEvent("showMapContextMenu", { detail: e })); // TODP
+ getApp().setState(OlympusState.UNIT_CONTROL, UnitControlSubState.MAP_CONTEXT_MENU);
} else {
if (e.type === "touchstart") document.dispatchEvent(new CustomEvent("forceboxselect", { detail: e }));
else document.dispatchEvent(new CustomEvent("forceboxselect", { detail: e.originalEvent }));
diff --git a/frontend/react/src/ui/contextmenus/mapcontextmenu.tsx b/frontend/react/src/ui/contextmenus/mapcontextmenu.tsx
index b5394a2a..90ebd904 100644
--- a/frontend/react/src/ui/contextmenus/mapcontextmenu.tsx
+++ b/frontend/react/src/ui/contextmenus/mapcontextmenu.tsx
@@ -1,17 +1,17 @@
import React, { useEffect, useRef, useState } from "react";
import { Unit } from "../../unit/unit";
-import { ContextActionSet } from "../../unit/contextactionset";
-import { getApp } from "../../olympusapp";
import { ContextAction } from "../../unit/contextaction";
-import { CONTEXT_ACTION_COLORS } from "../../constants/constants";
+import { CONTEXT_ACTION_COLORS, NO_SUBSTATE, OlympusState, OlympusSubState, UnitControlSubState } from "../../constants/constants";
import { OlDropdownItem } from "../components/oldropdown";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { LatLng } from "leaflet";
-import { SelectionClearedEvent } from "../../events";
+import { AppStateChangedEvent, ContextActionChangedEvent, ContextActionSetChangedEvent, SelectionClearedEvent } from "../../events";
+import { ContextActionSet } from "../../unit/contextactionset";
export function MapContextMenu(props: {}) {
- const [open, setOpen] = useState(false);
- const [contextActionsSet, setContextActionsSet] = useState(new ContextActionSet());
+ const [appState, setAppState] = useState(OlympusState.NOT_INITIALIZED);
+ const [appSubState, setAppSubState] = useState(NO_SUBSTATE as OlympusSubState);
+ const [contextActionSet, setContextActionsSet] = useState(null as ContextActionSet | null);
const [xPosition, setXPosition] = useState(0);
const [yPosition, setYPosition] = useState(0);
const [latLng, setLatLng] = useState(null as null | LatLng);
@@ -19,6 +19,16 @@ export function MapContextMenu(props: {}) {
var contentRef = useRef(null);
+ // TODO show at correct position
+
+ useEffect(() => {
+ AppStateChangedEvent.on((state, subState) => {
+ setAppState(state);
+ setAppSubState(subState);
+ });
+ ContextActionSetChangedEvent.on((contextActionSet) => setContextActionsSet(contextActionSet));
+ }, []);
+
useEffect(() => {
if (contentRef.current) {
const content = contentRef.current as HTMLDivElement;
@@ -40,69 +50,18 @@ export function MapContextMenu(props: {}) {
}
});
- useEffect(() => {
- document.addEventListener("showMapContextMenu", (ev: CustomEventInit) => {
- setOpen(true);
-
- updateData();
-
- setXPosition(ev.detail.originalEvent.clientX);
- setYPosition(ev.detail.originalEvent.clientY);
- setLatLng(ev.detail.latlng);
- setUnit(null);
- });
-
- document.addEventListener("showUnitContextMenu", (ev: CustomEventInit) => {
- setOpen(true);
-
- updateData();
-
- setXPosition(ev.detail.originalEvent.clientX);
- setYPosition(ev.detail.originalEvent.clientY);
- setLatLng(null);
- setUnit(ev.detail.sourceTarget);
- });
-
- document.addEventListener("hideMapContextMenu", (ev: CustomEventInit) => {
- setOpen(false);
- });
-
- document.addEventListener("hideUnitContextMenu", (ev: CustomEventInit) => {
- setOpen(false);
- });
-
- SelectionClearedEvent.on(() => {
- setOpen(false);
- });
- }, []);
-
- /* Update the current values of the shown data */
- function updateData() {
- var newContextActionSet = new ContextActionSet();
-
- getApp()
- .getUnitsManager()
- .getSelectedUnits()
- .filter((unit) => !unit.getHuman())
- .forEach((unit: Unit) => {
- unit.appendContextActions(newContextActionSet);
- });
-
- setContextActionsSet(newContextActionSet);
- return newContextActionSet;
- }
-
let reorderedActions: ContextAction[] = [];
CONTEXT_ACTION_COLORS.forEach((color) => {
- Object.values(contextActionsSet.getContextActions()).forEach((contextAction: ContextAction) => {
- if (color === null && contextAction.getOptions().buttonColor === undefined) reorderedActions.push(contextAction);
- else if (color === contextAction.getOptions().buttonColor) reorderedActions.push(contextAction);
- });
+ if (contextActionSet)
+ Object.values(contextActionSet.getContextActions()).forEach((contextAction: ContextAction) => {
+ if (color === null && contextAction.getOptions().buttonColor === undefined) reorderedActions.push(contextAction);
+ else if (color === contextAction.getOptions().buttonColor) reorderedActions.push(contextAction);
+ });
});
return (
<>
- {open && (
+ {appState === OlympusState.UNIT_CONTROL && appSubState === UnitControlSubState.UNIT_CONTEXT_MENU && (
<>
- {Object.values(contextActionsSet.getContextActions(latLng ? "position" : "unit")).map((contextAction) => {
- const colorString = contextAction.getOptions().buttonColor
- ? `
+ {contextActionSet &&
+ Object.values(contextActionSet.getContextActions(latLng ? "position" : "unit")).map((contextActionIt) => {
+ const colorString = contextActionIt.getOptions().buttonColor
+ ? `
border-2
- border-${contextAction.getOptions().buttonColor}-500
+ border-${contextActionIt.getOptions().buttonColor}-500
`
- : "";
+ : "";
return (
{
- if (contextAction.getOptions().executeImmediately) {
- contextAction.executeCallback(null, null);
+ if (contextActionIt.getOptions().executeImmediately) {
+ contextActionIt.executeCallback(null, null);
} else {
if (latLng !== null) {
- contextAction.executeCallback(null, latLng);
- setOpen(false);
+ contextActionIt.executeCallback(null, latLng);
} else if (unit !== null) {
- contextAction.executeCallback(unit, null);
- setOpen(false);
+ contextActionIt.executeCallback(unit, null);
}
}
+
}}
- >
-
- {contextAction.getLabel()}
-
- );
- })}
+ >
+
+
{contextActionIt.getLabel()}
+
+ );
+ })}
>
diff --git a/frontend/react/src/ui/modals/protectionprompt.tsx b/frontend/react/src/ui/modals/protectionprompt.tsx
index 83fe2986..c0ee3515 100644
--- a/frontend/react/src/ui/modals/protectionprompt.tsx
+++ b/frontend/react/src/ui/modals/protectionprompt.tsx
@@ -4,8 +4,10 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faArrowRight } from "@fortawesome/free-solid-svg-icons";
import { Unit } from "../../unit/unit";
import { FaLock } from "react-icons/fa6";
+import { getApp } from "../../olympusapp";
+import { OlympusState } from "../../constants/constants";
-export function ProtectionPrompt(props: {onContinue: () => void, onBack: () => void }) {
+export function ProtectionPrompt(props: { }) {
return (
void, onBack: () => v