Merge branch 'refactoring' of https://github.com/Pax1601/DCSOlympus into refactoring

This commit is contained in:
Davide Passoni
2024-11-07 10:05:32 +01:00
6 changed files with 184 additions and 207 deletions

View File

@@ -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 && (
<>
<div
ref={contentRef}
@@ -113,13 +72,14 @@ export function MapContextMenu(props: {}) {
flex w-full flex-col gap-2 overflow-x-auto no-scrollbar p-2
`}
>
{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 (
<OlDropdownItem
className={`
@@ -127,24 +87,23 @@ export function MapContextMenu(props: {}) {
${colorString}
`}
onClick={() => {
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);
}
}
}}
>
<FontAwesomeIcon className="my-auto" icon={contextAction.getIcon()} />
<div>{contextAction.getLabel()}</div>
</OlDropdownItem>
);
})}
>
<FontAwesomeIcon className="my-auto" icon={contextActionIt.getIcon()} />
<div>{contextActionIt.getLabel()}</div>
</OlDropdownItem>
);
})}
</div>
</div>
</>

View File

@@ -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 (
<Modal
className={`
@@ -56,7 +58,7 @@ export function ProtectionPrompt(props: {onContinue: () => void, onBack: () => v
<div className="flex">
<button
type="button"
onClick={() => {props.onContinue()}}
onClick={() => getApp().getUnitsManager().executeProtectionCallback()}
className={`
mb-2 me-2 ml-auto flex content-center items-center gap-2
rounded-sm bg-blue-700 px-5 py-2.5 text-sm font-medium text-white
@@ -70,7 +72,7 @@ export function ProtectionPrompt(props: {onContinue: () => void, onBack: () => v
</button>
<button
type="button"
onClick={props.onBack}
onClick={() => getApp().setState(OlympusState.UNIT_CONTROL)}
className={`
mb-2 me-2 flex content-center items-center gap-2 rounded-sm
border-[1px] bg-blue-700 px-5 py-2.5 text-sm font-medium

View File

@@ -34,10 +34,7 @@ import { Unit } from "../unit/unit";
import { ProtectionPrompt } from "./modals/protectionprompt";
import { UnitExplosionMenu } from "./panels/unitexplosionmenu";
import { JTACMenu } from "./panels/jtacmenu";
import {
AppStateChangedEvent,
MapOptionsChangedEvent
} from "../events";
import { AppStateChangedEvent, MapOptionsChangedEvent } from "../events";
export type OlympusUIState = {
mainMenuVisible: boolean;
@@ -64,9 +61,6 @@ export function UI() {
const [formationLeader, setFormationLeader] = useState(null as null | Unit);
const [formationWingmen, setFormationWingmen] = useState(null as null | Unit[]);
const [protectionPromptVisible, setProtectionPromptVisible] = useState(false);
const [protectionCallback, setProtectionCallback] = useState(null as any);
const [protectionUnits, setProtectionUnits] = useState([] as Unit[]);
const [unitExplosionUnits, setUnitExplosionUnits] = useState([] as Unit[]);
@@ -76,14 +70,6 @@ export function UI() {
setAppSubState(subState);
});
MapOptionsChangedEvent.on((mapOptions) => setMapOptions({ ...mapOptions }));
document.addEventListener("showProtectionPrompt", (ev: CustomEventInit) => {
setProtectionPromptVisible(true);
setProtectionCallback(() => {
return ev.detail.callback;
});
setProtectionUnits(ev.detail.units);
});
}, []);
function checkPassword(password: string) {
@@ -127,9 +113,9 @@ export function UI() {
<div className="flex h-full w-full flex-row-reverse">
{appState === OlympusState.LOGIN && (
<>
<div
className={`fixed left-0 top-0 z-30 h-full w-full bg-[#111111]/95`}
></div>
<div className={`
fixed left-0 top-0 z-30 h-full w-full bg-[#111111]/95
`}></div>
<LoginModal
onLogin={(password) => {
checkPassword(password);
@@ -146,27 +132,18 @@ export function UI() {
/>
</>
)}
{protectionPromptVisible && (
{appState === OlympusState.UNIT_CONTROL && appSubState == UnitControlSubState.PROTECTION && (
<>
<div
className={`fixed left-0 top-0 z-30 h-full w-full bg-[#111111]/95`}
></div>
<ProtectionPrompt
onContinue={(units) => {
protectionCallback(units);
setProtectionPromptVisible(false);
}}
onBack={() => {
setProtectionPromptVisible(false);
}}
units={protectionUnits}
/>
<div className={`
fixed left-0 top-0 z-30 h-full w-full bg-[#111111]/95
`}></div>
<ProtectionPrompt />
</>
)}
<div id="map-container" className="z-0 h-full w-screen" />
<MainMenu open={appState === OlympusState.MAIN_MENU} onClose={() => getApp().setState(OlympusState.IDLE)} />
<SpawnMenu open={appState === OlympusState.SPAWN} onClose={() => getApp().setState(OlympusState.IDLE)} />
<OptionsMenu open={appState === OlympusState.OPTIONS} onClose={() => getApp().setState(OlympusState.IDLE)} options={mapOptions} /* TODO remove *//>
<OptionsMenu open={appState === OlympusState.OPTIONS} onClose={() => getApp().setState(OlympusState.IDLE)} options={mapOptions} /* TODO remove */ />
<UnitControlMenu
open={appState === OlympusState.UNIT_CONTROL && appSubState !== UnitControlSubState.FORMATION}