mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
More work on responsive design for small screens
This commit is contained in:
6
frontend/react/.vscode/extensions.json
vendored
Normal file
6
frontend/react/.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"esbenp.prettier-vscode",
|
||||
"dbaeumer.vscode-eslint"
|
||||
]
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { LatLng, LatLngBounds } from "leaflet";
|
||||
import { Context } from "../types/types";
|
||||
import { Context, MapOptions } from "../types/types";
|
||||
|
||||
export const DEFAULT_CONTEXT: Context = "default context";
|
||||
|
||||
@@ -292,7 +292,8 @@ export const MAP_OPTIONS_DEFAULTS = {
|
||||
showUnitsEngagementRings: true,
|
||||
showUnitsAcquisitionRings: true,
|
||||
fillSelectedRing: false,
|
||||
};
|
||||
showMinimap: false
|
||||
} as MapOptions;
|
||||
|
||||
export const MAP_HIDDEN_TYPES_DEFAULTS = {
|
||||
human: false,
|
||||
|
||||
@@ -31,3 +31,8 @@
|
||||
.z-ui-4 {
|
||||
z-index: 2004;
|
||||
}
|
||||
|
||||
.z-ui-5 {
|
||||
z-index: 2005;
|
||||
}
|
||||
|
||||
|
||||
@@ -123,6 +123,7 @@ export class Map extends L.Map {
|
||||
#cameraZoomRatio: number = 1.0;
|
||||
|
||||
#contextAction: null | ContextAction = null;
|
||||
#theatre: string = "";
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -157,17 +158,6 @@ export class Map extends L.Map {
|
||||
this.#miniMapPolyline = new L.Polyline([], { color: "#202831" });
|
||||
this.#miniMapPolyline.addTo(this.#miniMapLayerGroup);
|
||||
|
||||
/* Scale */
|
||||
//@ts-ignore TODO more hacking because the module is provided as a pure javascript module only
|
||||
//L.control.scalenautic({ position: "topright", maxWidth: 300, nautic: true, metric: true, imperial: false }).addTo(this);
|
||||
|
||||
/* Map source dropdown */
|
||||
//this.#mapSourceDropdown = new Dropdown("map-type", (layerName: string) => this.setLayer(layerName));
|
||||
//this.#mapSourceDropdown.setOptions(this.getLayers(), null);
|
||||
//
|
||||
///* Visibility options dropdown */
|
||||
//this.#mapVisibilityOptionsDropdown = new Dropdown("map-visibility-options", (value: string) => { });
|
||||
|
||||
/* Init the state machine */
|
||||
this.#state = IDLE;
|
||||
|
||||
@@ -235,6 +225,8 @@ export class Map extends L.Map {
|
||||
this.#broadcastPosition();
|
||||
}, 500); // DCS does not always apply the altitude correctly at the first set when changing map type
|
||||
}
|
||||
|
||||
this.updateMinimap();
|
||||
});
|
||||
|
||||
document.addEventListener("configLoaded", () => {
|
||||
@@ -567,29 +559,16 @@ export class Map extends L.Map {
|
||||
}
|
||||
|
||||
setTheatre(theatre: string) {
|
||||
this.#theatre = theatre;
|
||||
|
||||
var bounds = new L.LatLngBounds([-90, -180], [90, 180]);
|
||||
var miniMapZoom = 5;
|
||||
if (theatre in mapBounds) {
|
||||
bounds = mapBounds[theatre as keyof typeof mapBounds].bounds;
|
||||
miniMapZoom = mapBounds[theatre as keyof typeof mapBounds].zoom;
|
||||
}
|
||||
|
||||
this.setView(bounds.getCenter(), 8);
|
||||
|
||||
if (this.#miniMap) this.#miniMap.remove();
|
||||
|
||||
//@ts-ignore // Needed because some of the inputs are wrong in the original module interface
|
||||
this.#miniMap = new ClickableMiniMap(this.#miniMapLayerGroup, {
|
||||
position: "topright",
|
||||
width: 192 * 1.5,
|
||||
height: 108 * 1.5,
|
||||
zoomLevelFixed: miniMapZoom,
|
||||
centerFixed: bounds.getCenter(),
|
||||
}).addTo(this);
|
||||
this.#miniMap.disableInteractivity();
|
||||
this.#miniMap.getMap().on("click", (e: any) => {
|
||||
if (this.#miniMap) this.setView(e.latlng);
|
||||
});
|
||||
this.updateMinimap();
|
||||
|
||||
const boundaries = this.#getMinimapBoundaries();
|
||||
this.#miniMapPolyline.setLatLngs(
|
||||
@@ -599,6 +578,33 @@ export class Map extends L.Map {
|
||||
this.setLayerName(this.#layerName);
|
||||
}
|
||||
|
||||
updateMinimap() {
|
||||
if (this.#miniMap) this.#miniMap.remove();
|
||||
|
||||
if (this.#options.showMinimap) {
|
||||
var bounds = new L.LatLngBounds([-90, -180], [90, 180]);
|
||||
var miniMapZoom = 5;
|
||||
if (this.#theatre in mapBounds) {
|
||||
bounds = mapBounds[this.#theatre as keyof typeof mapBounds].bounds;
|
||||
miniMapZoom = mapBounds[this.#theatre as keyof typeof mapBounds].zoom;
|
||||
}
|
||||
|
||||
this.#miniMap = new ClickableMiniMap(this.#miniMapLayerGroup, {
|
||||
position: "topright",
|
||||
width: 192 * 1.5,
|
||||
height: 108 * 1.5,
|
||||
//@ts-ignore Needed because some of the inputs are wrong in the original module interface
|
||||
zoomLevelFixed: miniMapZoom,
|
||||
//@ts-ignore Needed because some of the inputs are wrong in the original module interface
|
||||
centerFixed: bounds.getCenter(),
|
||||
}).addTo(this);
|
||||
this.#miniMap.disableInteractivity();
|
||||
this.#miniMap.getMap().on("click", (e: any) => {
|
||||
if (this.#miniMap) this.setView(e.latlng);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
getMiniMapLayerGroup() {
|
||||
return this.#miniMapLayerGroup;
|
||||
}
|
||||
@@ -1092,13 +1098,11 @@ export class Map extends L.Map {
|
||||
|
||||
#showDestinationCursors() {
|
||||
const singleCursor = !this.#shiftKey;
|
||||
const selectedUnitsCount = getApp()
|
||||
.getUnitsManager()
|
||||
.getSelectedUnits({
|
||||
excludeHumans: true,
|
||||
excludeProtected: true,
|
||||
onlyOnePerGroup: true,
|
||||
}).length;
|
||||
const selectedUnitsCount = getApp().getUnitsManager().getSelectedUnits({
|
||||
excludeHumans: true,
|
||||
excludeProtected: true,
|
||||
onlyOnePerGroup: true,
|
||||
}).length;
|
||||
if (singleCursor) {
|
||||
this.#hideDestinationCursors();
|
||||
} else if (!singleCursor) {
|
||||
@@ -1126,13 +1130,11 @@ export class Map extends L.Map {
|
||||
}
|
||||
|
||||
#updateDestinationCursors() {
|
||||
const selectedUnitsCount = getApp()
|
||||
.getUnitsManager()
|
||||
.getSelectedUnits({
|
||||
excludeHumans: true,
|
||||
excludeProtected: true,
|
||||
onlyOnePerGroup: true,
|
||||
}).length;
|
||||
const selectedUnitsCount = getApp().getUnitsManager().getSelectedUnits({
|
||||
excludeHumans: true,
|
||||
excludeProtected: true,
|
||||
onlyOnePerGroup: true,
|
||||
}).length;
|
||||
if (selectedUnitsCount > 1) {
|
||||
const groupLatLng =
|
||||
this.#computeDestinationRotation &&
|
||||
|
||||
@@ -19,6 +19,7 @@ export type MapOptions = {
|
||||
showUnitsEngagementRings: boolean;
|
||||
showUnitsAcquisitionRings: boolean;
|
||||
fillSelectedRing: boolean;
|
||||
showMinimap: boolean;
|
||||
};
|
||||
|
||||
export type MapHiddenTypes = {
|
||||
|
||||
@@ -106,10 +106,7 @@ export function OlDropdown(props: {
|
||||
type="button"
|
||||
>
|
||||
{props.leftIcon && (
|
||||
<FontAwesomeIcon
|
||||
icon={props.leftIcon}
|
||||
className={`mr-3`}
|
||||
/>
|
||||
<FontAwesomeIcon icon={props.leftIcon} className={`mr-3`} />
|
||||
)}
|
||||
<span className="overflow-hidden text-ellipsis text-nowrap">
|
||||
{props.label}
|
||||
@@ -138,7 +135,7 @@ export function OlDropdown(props: {
|
||||
ref={contentRef}
|
||||
data-open={open}
|
||||
className={`
|
||||
absolute z-ui-2 w-full divide-y divide-gray-100 overflow-y-scroll
|
||||
absolute z-ui-4 w-full divide-y divide-gray-100 overflow-y-scroll
|
||||
rounded-lg bg-white p-2 shadow
|
||||
dark:bg-gray-700
|
||||
data-[open='false']:hidden
|
||||
|
||||
@@ -38,7 +38,7 @@ export function LoginModal(props: {
|
||||
<Modal
|
||||
className={`
|
||||
inline-flex h-[75%] max-h-[530px] w-[80%] max-w-[1100px] overflow-y-auto
|
||||
scroll-smooth bg-white
|
||||
scroll-smooth bg-white z-ui-5
|
||||
dark:bg-olympus-800
|
||||
max-md:h-full max-md:max-h-full max-md:w-full max-md:rounded-none
|
||||
max-md:border-none
|
||||
@@ -111,9 +111,7 @@ export function LoginModal(props: {
|
||||
></img>
|
||||
</span>
|
||||
<div
|
||||
className={`
|
||||
flex flex-col items-start gap-1
|
||||
`}
|
||||
className={`flex flex-col items-start gap-1`}
|
||||
>
|
||||
<h1
|
||||
className={`
|
||||
@@ -143,10 +141,7 @@ export function LoginModal(props: {
|
||||
{props.commandMode === null ? (
|
||||
<>
|
||||
<div
|
||||
className={`
|
||||
flex flex-col items-start
|
||||
gap-2
|
||||
`}
|
||||
className={`flex flex-col items-start gap-2`}
|
||||
>
|
||||
<label
|
||||
className={`
|
||||
@@ -157,7 +152,7 @@ export function LoginModal(props: {
|
||||
Password{" "}
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
type="password"
|
||||
onChange={(ev) =>
|
||||
setPassword(ev.currentTarget.value)
|
||||
}
|
||||
|
||||
@@ -14,10 +14,11 @@ export function Menu(props: {
|
||||
<div
|
||||
data-open={props.open}
|
||||
className={`
|
||||
absolute left-16 top-[62px] w-[430px] z-ui-0 h-screen overflow-y-auto
|
||||
bg-gray-200 backdrop-blur-lg backdrop-grayscale transition-transform
|
||||
absolute left-16 right-0 top-[60px] bg-gray-200 backdrop-grayscale
|
||||
z-ui-3 h-screen overflow-y-auto backdrop-blur-lg transition-transform
|
||||
dark:bg-olympus-800/90
|
||||
data-[open='false']:-translate-x-full
|
||||
sm:w-[400px]
|
||||
`}
|
||||
tabIndex={-1}
|
||||
>
|
||||
|
||||
39
frontend/react/src/ui/panels/mapstatepanel.tsx
Normal file
39
frontend/react/src/ui/panels/mapstatepanel.tsx
Normal file
@@ -0,0 +1,39 @@
|
||||
import React, { useState } from "react";
|
||||
import { FaHandPointer } from "react-icons/fa6";
|
||||
import { IDLE, SPAWN_UNIT } from "../../constants/constants";
|
||||
|
||||
export function MapStatePanel(props: {}) {
|
||||
const [mapState, setMapState] = useState(IDLE);
|
||||
|
||||
document.addEventListener("mapStateChanged", (ev) => {
|
||||
setMapState((ev as CustomEvent).detail);
|
||||
});
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`
|
||||
absolute bottom-6 right-[10px] w-[288px] z-ui-5 flex items-center
|
||||
justify-between rounded-lg bg-gray-200 p-3 text-sm backdrop-blur-lg
|
||||
backdrop-grayscale
|
||||
dark:bg-olympus-800/90 dark:text-gray-200
|
||||
`}
|
||||
>
|
||||
<div className={`flex w-full items-center gap-2 font-semibold`}>
|
||||
{mapState === IDLE && "IDLE"}
|
||||
{mapState === SPAWN_UNIT && (
|
||||
<div className={`flex w-full items-center`}>
|
||||
<FaHandPointer className="mr-2 text-sm text-white" />
|
||||
<div
|
||||
className={`
|
||||
w-full animate-pulse border-l-[1px] px-2 text-center
|
||||
dark:text-white
|
||||
`}
|
||||
>
|
||||
Click on the map to spawn
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { zeroAppend } from "../../other/utils";
|
||||
import { DateAndTime } from "../../interfaces";
|
||||
import { getApp } from "../../olympusapp";
|
||||
import { FaChevronDown, FaChevronUp } from "react-icons/fa6";
|
||||
|
||||
export function MiniMapPanel(props: {}) {
|
||||
var [frameRate, setFrameRate] = useState(0);
|
||||
@@ -14,14 +16,16 @@ export function MiniMapPanel(props: {}) {
|
||||
var [connected, setConnected] = useState(false);
|
||||
var [paused, setPaused] = useState(false);
|
||||
var [showMissionTime, setShowMissionTime] = useState(false);
|
||||
var [showMinimap, setShowMinimap] = useState(false);
|
||||
|
||||
document.addEventListener("serverStatusUpdated", (ev) => {
|
||||
setFrameRate(ev.detail.frameRate);
|
||||
setLoad(ev.detail.load);
|
||||
setElapsedTime(ev.detail.elapsedTime);
|
||||
setMissionTime(ev.detail.missionTime);
|
||||
setConnected(ev.detail.connected);
|
||||
setPaused(ev.detail.paused);
|
||||
const detail = (ev as CustomEvent).detail;
|
||||
setFrameRate(detail.frameRate);
|
||||
setLoad(detail.load);
|
||||
setElapsedTime(detail.elapsedTime);
|
||||
setMissionTime(detail.missionTime);
|
||||
setConnected(detail.connected);
|
||||
setPaused(detail.paused);
|
||||
});
|
||||
|
||||
// A bit of a hack to set the rounded borders to the minimap
|
||||
@@ -32,6 +36,10 @@ export function MiniMapPanel(props: {}) {
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener("mapOptionsChanged", (event) => {
|
||||
setShowMinimap(getApp().getMap().getOptions().showMinimap);
|
||||
});
|
||||
|
||||
// Compute the time string depending on mission or elapsed time
|
||||
let hours = 0;
|
||||
let minutes = 0;
|
||||
@@ -63,62 +71,57 @@ export function MiniMapPanel(props: {}) {
|
||||
<div
|
||||
onClick={() => setShowMissionTime(!showMissionTime)}
|
||||
className={`
|
||||
absolute right-[10px] top-[233px] w-[288px] z-ui-0 flex items-center
|
||||
justify-between rounded-b-lg bg-gray-200 p-3 text-sm backdrop-blur-lg
|
||||
backdrop-grayscale
|
||||
absolute right-[10px]
|
||||
${showMinimap ? `top-[232px]` : `top-[70px]`}
|
||||
w-[288px] z-ui-0 flex items-center justify-between
|
||||
${showMinimap ? `rounded-b-lg` : `rounded-lg`}
|
||||
bg-gray-200 p-3 text-sm backdrop-blur-lg backdrop-grayscale
|
||||
dark:bg-olympus-800/90 dark:text-gray-200
|
||||
`}
|
||||
>
|
||||
{!connected ? (
|
||||
<div
|
||||
className={`
|
||||
flex animate-pulse items-center gap-2 font-semibold
|
||||
`}
|
||||
>
|
||||
<div
|
||||
className={`relative h-4 w-4 rounded-full bg-[#F05252]`}
|
||||
></div>
|
||||
<div className={`flex animate-pulse items-center gap-2 font-semibold`}>
|
||||
<div className={`relative h-4 w-4 rounded-full bg-[#F05252]`}></div>
|
||||
Server disconnected
|
||||
</div>
|
||||
) : paused ? (
|
||||
<div
|
||||
className={`
|
||||
flex animate-pulse items-center gap-2 font-semibold
|
||||
`}
|
||||
>
|
||||
<div
|
||||
className={`relative h-4 w-4 rounded-full bg-[#FF9900]`}
|
||||
></div>
|
||||
<div className={`flex animate-pulse items-center gap-2 font-semibold`}>
|
||||
<div className={`relative h-4 w-4 rounded-full bg-[#FF9900]`}></div>
|
||||
Server paused
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<div className="font-semibold">
|
||||
FPS:{" "}
|
||||
<span
|
||||
style={{ color: frameRateColor }}
|
||||
className={`font-semibold`}
|
||||
>
|
||||
<span style={{ color: frameRateColor }} className={`font-semibold`}>
|
||||
{frameRate}
|
||||
</span>{" "}
|
||||
</div>
|
||||
<div className="font-semibold">
|
||||
Load:{" "}
|
||||
<span
|
||||
style={{ color: loadColor }}
|
||||
className={`font-semibold`}
|
||||
>
|
||||
<span style={{ color: loadColor }} className={`font-semibold`}>
|
||||
{load}
|
||||
</span>{" "}
|
||||
</div>
|
||||
<div className="font-semibold">
|
||||
{showMissionTime ? "MT" : "ET"}: {timeString}{" "}
|
||||
</div>
|
||||
<div
|
||||
className={`relative h-4 w-4 rounded-full bg-[#8BFF63]`}
|
||||
></div>
|
||||
<div className={`relative h-4 w-4 rounded-full bg-[#8BFF63]`}></div>
|
||||
</>
|
||||
)}
|
||||
{showMinimap ? (
|
||||
<FaChevronUp
|
||||
onClick={() => {
|
||||
getApp().getMap().setOption("showMinimap", false);
|
||||
}}
|
||||
></FaChevronUp>
|
||||
) : (
|
||||
<FaChevronDown
|
||||
onClick={() => {
|
||||
getApp().getMap().setOption("showMinimap", true);
|
||||
}}
|
||||
></FaChevronDown>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -196,6 +196,33 @@ export function Options(props: {
|
||||
G
|
||||
</kbd>
|
||||
</div>
|
||||
<div
|
||||
className={`
|
||||
group flex flex-row rounded-md justify-content cursor-pointer gap-4
|
||||
p-2
|
||||
dark:hover:bg-olympus-400
|
||||
`}
|
||||
onClick={() => {
|
||||
getApp()
|
||||
.getMap()
|
||||
.setOption("showMinimap", !props.options.showMinimap);
|
||||
}}
|
||||
>
|
||||
<OlCheckbox
|
||||
checked={props.options.showMinimap}
|
||||
onChange={() => {}}
|
||||
></OlCheckbox>
|
||||
<span>Show minimap</span>
|
||||
<kbd
|
||||
className={`
|
||||
ml-auto rounded-lg border border-gray-200 bg-gray-100 px-2 py-1.5
|
||||
text-xs font-semibold text-gray-800
|
||||
dark:border-gray-500 dark:bg-gray-600 dark:text-gray-100
|
||||
`}
|
||||
>
|
||||
?
|
||||
</kbd>
|
||||
</div>
|
||||
|
||||
{/*
|
||||
<hr className="w-auto m-2 my-1 bg-gray-700 border-[1px] dark:border-olympus-500"></hr>
|
||||
|
||||
@@ -21,16 +21,20 @@ export function SideBar() {
|
||||
{(events) => (
|
||||
<nav
|
||||
className={`
|
||||
flex flex-col z-ui-1 h-full bg-gray-300
|
||||
flex flex-col z-ui-4 h-full bg-gray-300
|
||||
dark:bg-olympus-900
|
||||
`}
|
||||
>
|
||||
<div className={`
|
||||
w-16 flex-1 flex-wrap items-center justify-center p-4
|
||||
`}>
|
||||
<div className={`
|
||||
<div
|
||||
className={`
|
||||
w-16 flex-1 flex-wrap items-center justify-center p-4
|
||||
`}
|
||||
>
|
||||
<div
|
||||
className={`
|
||||
flex flex-col items-center justify-center gap-2.5
|
||||
`}>
|
||||
`}
|
||||
>
|
||||
<OlStateButton
|
||||
onClick={events.toggleMainMenuVisible}
|
||||
checked={appState.mainMenuVisible}
|
||||
@@ -64,9 +68,11 @@ export function SideBar() {
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex w-16 flex-wrap content-end justify-center p-4">
|
||||
<div className={`
|
||||
<div
|
||||
className={`
|
||||
flex flex-col items-center justify-center gap-2.5
|
||||
`}>
|
||||
`}
|
||||
>
|
||||
<OlStateButton
|
||||
onClick={() =>
|
||||
window.open("https://github.com/Pax1601/DCSOlympus/wiki")
|
||||
|
||||
@@ -35,8 +35,9 @@ import {
|
||||
import { Coalition } from "../../types/types";
|
||||
import { ftToM, knotsToMs, mToFt, msToKnots } from "../../other/utils";
|
||||
|
||||
export function UnitControlMenu() {
|
||||
var [open, setOpen] = useState(false);
|
||||
export function UnitControlMenu(props: {
|
||||
open: boolean
|
||||
}) {
|
||||
var [selectedUnits, setSelectedUnits] = useState([] as Unit[]);
|
||||
|
||||
var [selectedUnitsData, setSelectedUnitsData] = useState({
|
||||
@@ -94,7 +95,6 @@ export function UnitControlMenu() {
|
||||
|
||||
/* When a unit is selected, open the menu */
|
||||
document.addEventListener("unitsSelection", (ev: CustomEventInit) => {
|
||||
setOpen(true);
|
||||
setSelectedUnits(ev.detail as Unit[]);
|
||||
|
||||
updateData();
|
||||
@@ -108,7 +108,6 @@ export function UnitControlMenu() {
|
||||
|
||||
/* When all units are deselected clean the view */
|
||||
document.addEventListener("clearSelection", () => {
|
||||
setOpen(false);
|
||||
setSelectedUnits([]);
|
||||
});
|
||||
|
||||
@@ -185,7 +184,7 @@ export function UnitControlMenu() {
|
||||
getApp()?.getUnitsManager()?.getSelectedUnitsCategories() ?? [];
|
||||
|
||||
return (
|
||||
<Menu open={open} title="Units selected (x)" onClose={() => {}}>
|
||||
<Menu open={props.open} title="Units selected (x)" onClose={() => {}}>
|
||||
{/* Units list */}
|
||||
<div
|
||||
className={`
|
||||
@@ -240,9 +239,11 @@ export function UnitControlMenu() {
|
||||
return ["Aircraft", "Helicopter"].includes(category);
|
||||
}) && (
|
||||
<div>
|
||||
<div className={`
|
||||
flex flex-row content-center items-center justify-between
|
||||
`}>
|
||||
<div
|
||||
className={`
|
||||
flex flex-row content-center items-center justify-between
|
||||
`}
|
||||
>
|
||||
<div className="flex flex-col">
|
||||
<span
|
||||
className={`
|
||||
@@ -313,9 +314,11 @@ export function UnitControlMenu() {
|
||||
}
|
||||
{/* Airspeed selector */}
|
||||
<div>
|
||||
<div className={`
|
||||
flex flex-row content-center items-center justify-between
|
||||
`}>
|
||||
<div
|
||||
className={`
|
||||
flex flex-row content-center items-center justify-between
|
||||
`}
|
||||
>
|
||||
<div className="flex flex-col">
|
||||
<span
|
||||
className={`
|
||||
@@ -417,9 +420,7 @@ export function UnitControlMenu() {
|
||||
}) && (
|
||||
<>
|
||||
{" "}
|
||||
<div
|
||||
className={`flex flex-col gap-2`}
|
||||
>
|
||||
<div className={`flex flex-col gap-2`}>
|
||||
<span
|
||||
className={`
|
||||
font-normal
|
||||
@@ -573,9 +574,7 @@ export function UnitControlMenu() {
|
||||
}) && (
|
||||
<>
|
||||
{" "}
|
||||
<div
|
||||
className={`flex flex-col gap-2`}
|
||||
>
|
||||
<div className={`flex flex-col gap-2`}>
|
||||
<span
|
||||
className={`
|
||||
font-normal
|
||||
|
||||
@@ -40,7 +40,7 @@ export function UnitMouseControlBar(props: {}) {
|
||||
|
||||
/* Deselect the context action when exiting state */
|
||||
document.addEventListener("mapStateChanged", (ev) => {
|
||||
setOpen(ev.detail === CONTEXT_ACTION);
|
||||
setOpen((ev as CustomEvent).detail === CONTEXT_ACTION);
|
||||
});
|
||||
|
||||
/* Update the current values of the shown data */
|
||||
@@ -65,8 +65,8 @@ export function UnitMouseControlBar(props: {}) {
|
||||
<>
|
||||
<div
|
||||
className={`
|
||||
absolute left-[50%] top-20 flex translate-x-[-50%] gap-2
|
||||
rounded-md bg-gray-200 p-2 z-ui-2
|
||||
absolute left-[50%] top-16 flex translate-x-[calc(-50%+2rem)]
|
||||
gap-2 rounded-md bg-gray-200 p-2 z-ui-2
|
||||
dark:bg-olympus-900
|
||||
`}
|
||||
>
|
||||
@@ -84,11 +84,9 @@ export function UnitMouseControlBar(props: {}) {
|
||||
} else {
|
||||
if (activeContextAction != contextAction) {
|
||||
setActiveContextAction(contextAction);
|
||||
getApp()
|
||||
.getMap()
|
||||
.setState(CONTEXT_ACTION, {
|
||||
contextAction: contextAction,
|
||||
});
|
||||
getApp().getMap().setState(CONTEXT_ACTION, {
|
||||
contextAction: contextAction,
|
||||
});
|
||||
} else {
|
||||
setActiveContextAction(null);
|
||||
getApp()
|
||||
@@ -105,16 +103,21 @@ export function UnitMouseControlBar(props: {}) {
|
||||
{activeContextAction && (
|
||||
<div
|
||||
className={`
|
||||
absolute left-[50%] top-36 flex translate-x-[-50%] items-center
|
||||
gap-2 rounded-md bg-gray-200 p-4 z-ui-1
|
||||
absolute left-[50%] top-32 flex translate-x-[calc(-50%+2rem)]
|
||||
items-center gap-2 rounded-md bg-gray-200 p-4 z-ui-1
|
||||
min-w-[300px]
|
||||
dark:bg-olympus-800
|
||||
`}
|
||||
>
|
||||
<FaInfoCircle className="mr-2 text-sm text-blue-500" />
|
||||
<FaInfoCircle className={`
|
||||
mr-2 hidden min-w-8 text-sm text-blue-500
|
||||
md:block
|
||||
`} />
|
||||
<div
|
||||
className={`
|
||||
border-l-[1px] px-5
|
||||
px-2
|
||||
dark:text-gray-400
|
||||
md:border-l-[1px] md:px-5
|
||||
`}
|
||||
>
|
||||
{activeContextAction.getDescription()}
|
||||
|
||||
@@ -24,6 +24,7 @@ import { LoginModal } from "./modals/login";
|
||||
import { sha256 } from "js-sha256";
|
||||
import { MiniMapPanel } from "./panels/minimappanel";
|
||||
import { UnitMouseControlBar } from "./panels/unitmousecontrolbar";
|
||||
import { MapStatePanel } from "./panels/mapstatepanel";
|
||||
|
||||
export type OlympusState = {
|
||||
mainMenuVisible: boolean;
|
||||
@@ -188,9 +189,11 @@ export function UI() {
|
||||
<div className="flex h-full">
|
||||
{loginModalVisible && (
|
||||
<>
|
||||
<div className={`
|
||||
fixed left-0 top-0 h-full w-full z-ui-3 bg-[#111111]/95
|
||||
`}></div>
|
||||
<div
|
||||
className={`
|
||||
fixed left-0 top-0 h-full w-full z-ui-5 bg-[#111111]/95
|
||||
`}
|
||||
></div>
|
||||
<LoginModal
|
||||
onLogin={(password) => {
|
||||
checkPassword(password);
|
||||
@@ -222,9 +225,10 @@ export function UI() {
|
||||
options={mapOptions}
|
||||
/>
|
||||
<MiniMapPanel />
|
||||
<UnitControlMenu />
|
||||
<UnitControlMenu open={unitControlMenuVisible} />
|
||||
<div id="map-container" className="h-full w-screen" />
|
||||
<UnitMouseControlBar />
|
||||
<MapStatePanel />
|
||||
</div>
|
||||
</div>
|
||||
</EventsProvider>
|
||||
|
||||
@@ -377,7 +377,6 @@ export abstract class Unit extends CustomMarker {
|
||||
/* Leaflet events listeners */
|
||||
this.on("click", (e) => this.#onClick(e));
|
||||
this.on("dblclick", (e) => this.#onDoubleClick(e));
|
||||
this.on("contextmenu", (e) => this.#onContextMenu(e));
|
||||
this.on("mouseover", () => {
|
||||
if (this.belongsToCommandedCoalition()) {
|
||||
this.setHighlighted(true);
|
||||
@@ -1558,24 +1557,6 @@ export abstract class Unit extends CustomMarker {
|
||||
});
|
||||
}
|
||||
|
||||
#onContextMenu(e: any) {
|
||||
var contextActionSet = new ContextActionSet();
|
||||
|
||||
var units = getApp().getUnitsManager().getSelectedUnits();
|
||||
if (!units.includes(this)) units.push(this);
|
||||
|
||||
units.forEach((unit: Unit) => {
|
||||
unit.appendContextActions(contextActionSet);
|
||||
});
|
||||
|
||||
if (Object.keys(contextActionSet.getContextActions()).length > 0) {
|
||||
getApp()
|
||||
.getMap()
|
||||
.showUnitContextMenu(e.originalEvent.x, e.originalEvent.y, e.latlng);
|
||||
//getApp().getMap().getUnitContextMenu().setContextActions(contextActionSet);
|
||||
}
|
||||
}
|
||||
|
||||
#updateMarker() {
|
||||
this.updateVisibility();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user