diff --git a/assets/js/hooks/Mapper/MapRoot.tsx b/assets/js/hooks/Mapper/MapRoot.tsx index a45d593a..509b3717 100644 --- a/assets/js/hooks/Mapper/MapRoot.tsx +++ b/assets/js/hooks/Mapper/MapRoot.tsx @@ -15,11 +15,10 @@ const ErrorFallback = () => { }; export default function MapRoot({ hooks }) { - const mapRef = useRef(null); const providerRef = useRef(null); const hooksRef = useRef(hooks); - const mapperHandlerRefs = useRef([mapRef, providerRef]); + const mapperHandlerRefs = useRef([providerRef]); const { handleCommand, handleMapEvent, handleMapEvents } = useMapperHandlers(mapperHandlerRefs.current, hooksRef); @@ -41,7 +40,7 @@ export default function MapRoot({ hooks }) { return ( - + diff --git a/assets/js/hooks/Mapper/components/characters/Characters.tsx b/assets/js/hooks/Mapper/components/characters/Characters.tsx index 3b611ffb..313ae523 100644 --- a/assets/js/hooks/Mapper/components/characters/Characters.tsx +++ b/assets/js/hooks/Mapper/components/characters/Characters.tsx @@ -1,20 +1,19 @@ import { useCallback } from 'react'; import clsx from 'clsx'; import { useAutoAnimate } from '@formkit/auto-animate/react'; -import { useMapRootState } from '@/hooks/Mapper/mapRootProvider'; import { Commands } from '@/hooks/Mapper/types/mapHandlers.ts'; import { CharacterTypeRaw } from '@/hooks/Mapper/types'; +import { emitMapEvent } from '@/hooks/Mapper/events'; const Characters = ({ data }: { data: CharacterTypeRaw[] }) => { const [parent] = useAutoAnimate(); - const { mapRef } = useMapRootState(); - const handleSelect = useCallback( - (character: CharacterTypeRaw) => { - mapRef.current?.command(Commands.centerSystem, character?.location?.solar_system_id?.toString()); - }, - [mapRef], - ); + const handleSelect = useCallback((character: CharacterTypeRaw) => { + emitMapEvent({ + name: Commands.centerSystem, + data: character?.location?.solar_system_id?.toString(), + }); + }, []); const items = data.map(character => (
  • ; } -export const useContextMenuSystemInfoHandlers = ({ hubs, outCommand, mapRef }: UseContextMenuSystemHandlersProps) => { +export const useContextMenuSystemInfoHandlers = ({ hubs, outCommand }: UseContextMenuSystemHandlersProps) => { const contextMenuRef = useRef(null); const [system, setSystem] = useState(); const routeRef = useRef<(SolarSystemStaticInfoRaw | undefined)[]>([]); - const ref = useRef({ hubs, system, outCommand, mapRef }); - ref.current = { hubs, system, outCommand, mapRef }; + const ref = useRef({ hubs, system, outCommand }); + ref.current = { hubs, system, outCommand }; const open = useCallback( (ev: React.SyntheticEvent, systemId: string, route: (SolarSystemStaticInfoRaw | undefined)[]) => { @@ -48,7 +48,7 @@ export const useContextMenuSystemInfoHandlers = ({ hubs, outCommand, mapRef }: U }, []); const onAddSystem = useCallback(() => { - const { system: solarSystemId, outCommand, mapRef } = ref.current; + const { system: solarSystemId, outCommand } = ref.current; if (!solarSystemId) { return; } @@ -60,7 +60,11 @@ export const useContextMenuSystemInfoHandlers = ({ hubs, outCommand, mapRef }: U }, }); setTimeout(() => { - mapRef.current?.command(Commands.centerSystem, solarSystemId); + emitMapEvent({ + name: Commands.centerSystem, + data: solarSystemId, + }); + setSystem(undefined); }, 200); }, []); diff --git a/assets/js/hooks/Mapper/components/map/Map.tsx b/assets/js/hooks/Mapper/components/map/Map.tsx index 55ab02df..e6065b31 100644 --- a/assets/js/hooks/Mapper/components/map/Map.tsx +++ b/assets/js/hooks/Mapper/components/map/Map.tsx @@ -1,10 +1,11 @@ -import { ForwardedRef, forwardRef, MouseEvent, useCallback, useEffect, useRef } from 'react'; +import { ForwardedRef, forwardRef, MouseEvent, useCallback, useEffect } from 'react'; import ReactFlow, { Background, ConnectionMode, Edge, MiniMap, Node, + NodeChange, NodeDragHandler, OnConnect, OnMoveEnd, @@ -13,7 +14,6 @@ import ReactFlow, { SelectionMode, useEdgesState, useNodesState, - NodeChange, useReactFlow, } from 'reactflow'; import 'reactflow/dist/style.css'; @@ -21,7 +21,6 @@ import classes from './Map.module.scss'; import './styles/neon-theme.scss'; import './styles/eve-common.scss'; import { MapProvider, useMapState } from './MapProvider'; -import { useMapRootState } from '@/hooks/Mapper/mapRootProvider'; import { useMapHandlers, useUpdateNodes } from './hooks'; import { MapHandlers, OutCommand, OutCommandHandler } from '@/hooks/Mapper/types/mapHandlers.ts'; import { @@ -37,7 +36,6 @@ import { SESSION_KEY } from '@/hooks/Mapper/constants.ts'; import { SolarSystemConnection, SolarSystemRawType } from '@/hooks/Mapper/types'; import { ctxManager } from '@/hooks/Mapper/utils/contextManager.ts'; import { NodeSelectionMouseHandler } from '@/hooks/Mapper/components/contexts/types.ts'; -import { useDeleteSystems } from '@/hooks/Mapper/components/contexts/hooks'; const DEFAULT_VIEW_PORT = { zoom: 1, x: 0, y: 0 }; @@ -93,12 +91,14 @@ interface MapCompProps { refn: ForwardedRef; onCommand: OutCommandHandler; onSelectionChange: OnMapSelectionChange; + onManualDelete(systems: string[]): void; onConnectionInfoClick?(e: SolarSystemConnection): void; onSelectionContextMenu?: NodeSelectionMouseHandler; minimapClasses?: string; isShowMinimap?: boolean; onSystemContextMenu: (event: MouseEvent, systemId: string) => void; showKSpaceBG?: boolean; + isThickConnections?: boolean; } const MapComp = ({ @@ -109,8 +109,10 @@ const MapComp = ({ onSystemContextMenu, onConnectionInfoClick, onSelectionContextMenu, + onManualDelete, isShowMinimap, showKSpaceBG, + isThickConnections, }: MapCompProps) => { const { getNode } = useReactFlow(); const [nodes, , onNodesChange] = useNodesState(initialNodes); @@ -121,14 +123,6 @@ const MapComp = ({ const { handleRootContext, ...rootCtxProps } = useContextMenuRootHandlers(); const { handleConnectionContext, ...connectionCtxProps } = useContextMenuConnectionHandlers(); const { update } = useMapState(); - const { - data: { systems }, - } = useMapRootState(); - - const { deleteSystems } = useDeleteSystems(); - - const systemsRef = useRef({ systems }); - systemsRef.current = { systems }; const onConnect: OnConnect = useCallback( params => { @@ -186,35 +180,41 @@ const MapComp = ({ const handleNodesChange = useCallback( (changes: NodeChange[]) => { const systemsIdsToRemove: string[] = []; + const nextChanges = changes.reduce((acc, change) => { - if (change.type === 'remove') { - const node = getNode(change.id); - const { systems = [] } = systemsRef.current; - if (node?.data?.id && !systems.map(s => s.id).includes(node?.data?.id)) { - return [...acc, change]; - } else if (!node?.data?.locked) { - systemsIdsToRemove.push(node?.data?.id); - } + if (change.type !== 'remove') { + return [...acc, change]; + } + + const node = getNode(change.id); + if (!node) { + return [...acc, change]; + } + + if (node.data.locked) { return acc; } + + systemsIdsToRemove.push(node.data.id); return [...acc, change]; }, [] as NodeChange[]); - if (systemsIdsToRemove.length) { - deleteSystems(systemsIdsToRemove); + if (systemsIdsToRemove.length > 0) { + onManualDelete(systemsIdsToRemove); } onNodesChange(nextChanges); }, - [deleteSystems, getNode, onNodesChange], + [getNode, onManualDelete, onNodesChange], ); useEffect(() => { update(x => ({ ...x, showKSpaceBG: showKSpaceBG, + isThickConnections: isThickConnections, })); - }, [showKSpaceBG, update]); + }, [showKSpaceBG, isThickConnections, update]); return ( <> @@ -238,6 +238,7 @@ const MapComp = ({ onConnectStart={() => update({ isConnecting: true })} onConnectEnd={() => update({ isConnecting: false })} onNodeMouseEnter={(_, node) => update({ hoverNodeId: node.id })} + // onKeyUp= onNodeMouseLeave={() => update({ hoverNodeId: null })} onEdgeClick={(_, t) => { onConnectionInfoClick?.(t.data); diff --git a/assets/js/hooks/Mapper/components/map/MapProvider.tsx b/assets/js/hooks/Mapper/components/map/MapProvider.tsx index 7b963f42..a80dfa29 100644 --- a/assets/js/hooks/Mapper/components/map/MapProvider.tsx +++ b/assets/js/hooks/Mapper/components/map/MapProvider.tsx @@ -8,6 +8,7 @@ export type MapData = MapUnionTypes & { hoverNodeId: string | null; visibleNodes: Set; showKSpaceBG: boolean; + isThickConnections: boolean; }; interface MapProviderProps { @@ -17,6 +18,7 @@ interface MapProviderProps { const INITIAL_DATA: MapData = { wormholesData: {}, + wormholes: [], effects: {}, characters: [], userCharacters: [], @@ -29,6 +31,7 @@ const INITIAL_DATA: MapData = { hoverNodeId: null, visibleNodes: new Set(), showKSpaceBG: false, + isThickConnections: false, }; export interface MapContextProps { diff --git a/assets/js/hooks/Mapper/components/map/components/SolarSystemEdge/SolarSystemEdge.module.scss b/assets/js/hooks/Mapper/components/map/components/SolarSystemEdge/SolarSystemEdge.module.scss index 91127c4e..036d03e2 100644 --- a/assets/js/hooks/Mapper/components/map/components/SolarSystemEdge/SolarSystemEdge.module.scss +++ b/assets/js/hooks/Mapper/components/map/components/SolarSystemEdge/SolarSystemEdge.module.scss @@ -21,7 +21,7 @@ } &.Frigate { - stroke: #4e62c9; + stroke: #d4f0ff; } &.Hovered { @@ -37,9 +37,16 @@ } &.Frigate { - stroke: #41acd7; + stroke: #d4f0ff; } + } + &.Tick { + stroke-width: 3px; + + &.Hovered { + stroke-width: 3px; + } } } @@ -61,6 +68,14 @@ stroke: #ef7dce; } } + + &.Tick { + stroke-width: 5px; + + &.TimeCrit { + stroke-width: 6px; + } + } } .ClickPath { @@ -93,5 +108,14 @@ width: 5px; height: 5px; z-index: 1001; + + &.Tick { + width: 7px; + height: 7px; + + &.Right { + margin-left: 0px; + } + } } diff --git a/assets/js/hooks/Mapper/components/map/components/SolarSystemEdge/SolarSystemEdge.tsx b/assets/js/hooks/Mapper/components/map/components/SolarSystemEdge/SolarSystemEdge.tsx index aabd2111..df63636d 100644 --- a/assets/js/hooks/Mapper/components/map/components/SolarSystemEdge/SolarSystemEdge.tsx +++ b/assets/js/hooks/Mapper/components/map/components/SolarSystemEdge/SolarSystemEdge.tsx @@ -7,33 +7,54 @@ import clsx from 'clsx'; import { MassState, ShipSizeStatus, SolarSystemConnection, TimeStatus } from '@/hooks/Mapper/types'; import { PrimeIcons } from 'primereact/api'; import { WdTooltipWrapper } from '@/hooks/Mapper/components/ui-kit/WdTooltipWrapper'; +import { useMapState } from '@/hooks/Mapper/components/map/MapProvider.tsx'; const MAP_TRANSLATES: Record = { - [Position.Top]: 'translate(-50%, 0%)', + [Position.Top]: 'translate(-48%, 0%)', [Position.Bottom]: 'translate(-50%, -100%)', [Position.Left]: 'translate(0%, -50%)', [Position.Right]: 'translate(-100%, -50%)', }; +const MAP_OFFSETS_TICK: Record = { + [Position.Top]: { x: 0, y: 3 }, + [Position.Bottom]: { x: 0, y: -3 }, + [Position.Left]: { x: 3, y: 0 }, + [Position.Right]: { x: -3, y: 0 }, +}; + +const MAP_OFFSETS: Record = { + [Position.Top]: { x: 0, y: 0 }, + [Position.Bottom]: { x: 0, y: 0 }, + [Position.Left]: { x: 0, y: 0 }, + [Position.Right]: { x: 0, y: 0 }, +}; + export const SolarSystemEdge = ({ id, source, target, markerEnd, style, data }: EdgeProps) => { const sourceNode = useStore(useCallback(store => store.nodeInternals.get(source), [source])); const targetNode = useStore(useCallback(store => store.nodeInternals.get(target), [target])); + const { + data: { isThickConnections }, + } = useMapState(); + const [hovered, setHovered] = useState(false); const [path, labelX, labelY, sx, sy, tx, ty, sourcePos, targetPos] = useMemo(() => { const { sx, sy, tx, ty, sourcePos, targetPos } = getEdgeParams(sourceNode, targetNode); + const offset = isThickConnections ? MAP_OFFSETS_TICK[targetPos] : MAP_OFFSETS[targetPos]; + const [edgePath, labelX, labelY] = getBezierPath({ - sourceX: sx, - sourceY: sy, + sourceX: sx - offset.x, + sourceY: sy - offset.y, sourcePosition: sourcePos, targetPosition: targetPos, - targetX: tx, - targetY: ty, + targetX: tx + offset.x, + targetY: ty + offset.y, }); return [edgePath, labelX, labelY, sx, sy, tx, ty, sourcePos, targetPos]; - }, [sourceNode, targetNode]); + }, [isThickConnections, sourceNode, targetNode]); if (!sourceNode || !targetNode || !data) { return null; @@ -44,6 +65,7 @@ export const SolarSystemEdge = ({ id, source, target, markerEnd, style, data }:
    diff --git a/assets/js/hooks/Mapper/components/map/components/SolarSystemNode/SolarSystemNode.module.scss b/assets/js/hooks/Mapper/components/map/components/SolarSystemNode/SolarSystemNode.module.scss index cc73ec94..133779f5 100644 --- a/assets/js/hooks/Mapper/components/map/components/SolarSystemNode/SolarSystemNode.module.scss +++ b/assets/js/hooks/Mapper/components/map/components/SolarSystemNode/SolarSystemNode.module.scss @@ -212,6 +212,14 @@ $tooltip-bg: #202020; // Темный фон для подсказок color: #ffb01d; } + /* Firefox kostyl */ + @-moz-document url-prefix() { + .classSystemName { + font-family: inherit !important; + font-weight: bold; + } + } + .classSystemName { //font-weight: bold; } @@ -262,6 +270,13 @@ $tooltip-bg: #202020; // Темный фон для подсказок & > * { line-height: 10px; } + + /* Firefox kostyl */ + @-moz-document url-prefix() { + position: relative; + top: -1px; + } + } .Handlers { @@ -299,4 +314,25 @@ $tooltip-bg: #202020; // Темный фон для подсказок &.HandleLeft { left: -2px; } + + &.Tick { + width: 7px; + height: 7px; + + &.HandleTop { + top: -3px; + } + + &.HandleRight { + right: -3px; + } + + &.HandleBottom { + bottom: -3px; + } + + &.HandleLeft { + left: -3px; + } + } } diff --git a/assets/js/hooks/Mapper/components/map/components/SolarSystemNode/SolarSystemNode.tsx b/assets/js/hooks/Mapper/components/map/components/SolarSystemNode/SolarSystemNode.tsx index 7335a575..ea617dd5 100644 --- a/assets/js/hooks/Mapper/components/map/components/SolarSystemNode/SolarSystemNode.tsx +++ b/assets/js/hooks/Mapper/components/map/components/SolarSystemNode/SolarSystemNode.tsx @@ -79,6 +79,7 @@ export const SolarSystemNode = memo(({ data, selected }: WrapNodeProps { const rf = useReactFlow(); - const ref = useRef({ onSelectionChange }); - ref.current = { onSelectionChange }; + const ref = useRef({ onSelectionChange, rf }); + ref.current = { onSelectionChange, rf }; - return useCallback( - (systems: CommandRemoveSystems) => { - rf.deleteElements({ nodes: systems.map(x => ({ id: `${x}` })) }); + return useCallback((systems: CommandRemoveSystems) => { + ref.current.rf.deleteElements({ nodes: systems.map(x => ({ id: `${x}` })) }); - const newSelection = rf - .getNodes() - .filter(x => !systems.includes(parseInt(x.id))) - .filter(x => x.selected) - .map(x => x.id); + const newSelection = ref.current.rf + .getNodes() + .filter(x => !systems.includes(parseInt(x.id))) + .filter(x => x.selected) + .map(x => x.id); - ref.current.onSelectionChange({ - systems: newSelection, - connections: [], - }); - }, - [rf], - ); + ref.current.onSelectionChange({ + systems: newSelection, + connections: [], + }); + }, []); }; diff --git a/assets/js/hooks/Mapper/components/map/hooks/useMapHandlers.ts b/assets/js/hooks/Mapper/components/map/hooks/useMapHandlers.ts index 64e35e57..6bc6dce0 100644 --- a/assets/js/hooks/Mapper/components/map/hooks/useMapHandlers.ts +++ b/assets/js/hooks/Mapper/components/map/hooks/useMapHandlers.ts @@ -19,8 +19,6 @@ import { MapHandlers, } from '@/hooks/Mapper/types/mapHandlers.ts'; -import { useMapEventListener } from '@/hooks/Mapper/events'; - import { useCommandsCharacters, useCommandsConnections, @@ -60,13 +58,16 @@ export const useMapHandlers = (ref: ForwardedRef, onSelectionChange mapInit(data as CommandInit); break; case Commands.addSystems: + setTimeout(() => mapAddSystems(data as CommandAddSystems), 100); break; case Commands.updateSystems: mapUpdateSystems(data as CommandUpdateSystems); break; case Commands.removeSystems: + setTimeout(() => removeSystems(data as CommandRemoveSystems), 100); break; case Commands.addConnections: + setTimeout(() => addConnections(data as CommandAddConnections), 100); break; case Commands.removeConnections: removeConnections(data as CommandRemoveConnections); @@ -131,20 +132,4 @@ export const useMapHandlers = (ref: ForwardedRef, onSelectionChange }, [], ); - - useMapEventListener(event => { - switch (event.name) { - case Commands.addConnections: - addConnections(event.data as CommandAddConnections); - break; - case Commands.addSystems: - mapAddSystems(event.data as CommandAddSystems); - break; - case Commands.removeSystems: - removeSystems(event.data as CommandRemoveSystems); - break; - default: - break; - } - }); }; diff --git a/assets/js/hooks/Mapper/components/mapInterface/widgets/RoutesWidget/RoutesList/RoutesList.tsx b/assets/js/hooks/Mapper/components/mapInterface/widgets/RoutesWidget/RoutesList/RoutesList.tsx index 3c948b87..7081f49a 100644 --- a/assets/js/hooks/Mapper/components/mapInterface/widgets/RoutesWidget/RoutesList/RoutesList.tsx +++ b/assets/js/hooks/Mapper/components/mapInterface/widgets/RoutesWidget/RoutesList/RoutesList.tsx @@ -5,7 +5,7 @@ import { SystemViewStandalone, WdTooltip, WdTooltipHandlers } from '@/hooks/Mapp import { getBackgroundClass, getShapeClass } from '@/hooks/Mapper/components/map/helpers'; import { MouseEvent, useCallback, useRef, useState } from 'react'; import { Commands } from '@/hooks/Mapper/types'; -import { useMapRootState } from '@/hooks/Mapper/mapRootProvider'; +import { emitMapEvent } from '@/hooks/Mapper/events'; export type RouteSystemProps = { destination: number; @@ -88,11 +88,10 @@ export interface RoutesListProps { export const RoutesList = ({ data, onContextMenu }: RoutesListProps) => { const [selected, setSelected] = useState(null); - const { mapRef } = useMapRootState(); const handleClick = useCallback( - (systemId: number) => mapRef.current?.command(Commands.centerSystem, systemId.toString()), - [mapRef], + (systemId: number) => emitMapEvent({ name: Commands.centerSystem, data: systemId?.toString() }), + [], ); if (!data.has_connection) { diff --git a/assets/js/hooks/Mapper/components/mapInterface/widgets/RoutesWidget/RoutesWidget.tsx b/assets/js/hooks/Mapper/components/mapInterface/widgets/RoutesWidget/RoutesWidget.tsx index 7559e10d..ebb91045 100644 --- a/assets/js/hooks/Mapper/components/mapInterface/widgets/RoutesWidget/RoutesWidget.tsx +++ b/assets/js/hooks/Mapper/components/mapInterface/widgets/RoutesWidget/RoutesWidget.tsx @@ -30,7 +30,6 @@ const sortByDist = (a: Route, b: Route) => { export const RoutesWidgetContent = () => { const { data: { selectedSystems, hubs = [], systems, routes }, - mapRef, outCommand, } = useMapRootState(); @@ -42,7 +41,6 @@ export const RoutesWidgetContent = () => { const { open, ...systemCtxProps } = useContextMenuSystemInfoHandlers({ outCommand, hubs, - mapRef, }); const preparedHubs = useMemo(() => { diff --git a/assets/js/hooks/Mapper/components/mapRootContent/MapRootContent.tsx b/assets/js/hooks/Mapper/components/mapRootContent/MapRootContent.tsx index 6773e726..e2b70ff7 100644 --- a/assets/js/hooks/Mapper/components/mapRootContent/MapRootContent.tsx +++ b/assets/js/hooks/Mapper/components/mapRootContent/MapRootContent.tsx @@ -7,13 +7,13 @@ import { useCallback, useState } from 'react'; import { OnTheMap, RightBar } from '@/hooks/Mapper/components/mapRootContent/components'; import { MapContextMenu } from '@/hooks/Mapper/components/mapRootContent/components/MapContextMenu/MapContextMenu.tsx'; import { useSkipContextMenu } from '@/hooks/Mapper/hooks/useSkipContextMenu'; -import { MapSettings } from "@/hooks/Mapper/components/mapRootContent/components/MapSettings"; +import { MapSettings } from '@/hooks/Mapper/components/mapRootContent/components/MapSettings'; export interface MapRootContentProps {} // eslint-disable-next-line no-empty-pattern export const MapRootContent = ({}: MapRootContentProps) => { - const { mapRef, interfaceSettings } = useMapRootState(); + const { interfaceSettings } = useMapRootState(); const { isShowMenu } = interfaceSettings; const [showOnTheMap, setShowOnTheMap] = useState(false); @@ -26,7 +26,7 @@ export const MapRootContent = ({}: MapRootContentProps) => { useSkipContextMenu(); return ( - }> + }> {!isShowMenu ? (
    diff --git a/assets/js/hooks/Mapper/components/mapRootContent/components/MapSettings/MapSettings.tsx b/assets/js/hooks/Mapper/components/mapRootContent/components/MapSettings/MapSettings.tsx index 072ea635..8ca3b20c 100644 --- a/assets/js/hooks/Mapper/components/mapRootContent/components/MapSettings/MapSettings.tsx +++ b/assets/js/hooks/Mapper/components/mapRootContent/components/MapSettings/MapSettings.tsx @@ -61,6 +61,7 @@ const CONNECTIONS_CHECKBOXES_PROPS: CheckboxesList = [ const UI_CHECKBOXES_PROPS: CheckboxesList = [ { prop: InterfaceStoredSettingsProps.isShowMenu, label: 'Enable compact map menu bar' }, + { prop: InterfaceStoredSettingsProps.isThickConnections, label: 'Tick connections' }, ]; export const MapSettings = ({ show, onHide }: MapSettingsProps) => { diff --git a/assets/js/hooks/Mapper/components/mapWrapper/MapWrapper.tsx b/assets/js/hooks/Mapper/components/mapWrapper/MapWrapper.tsx index ac02d057..a6ba6316 100644 --- a/assets/js/hooks/Mapper/components/mapWrapper/MapWrapper.tsx +++ b/assets/js/hooks/Mapper/components/mapWrapper/MapWrapper.tsx @@ -1,14 +1,14 @@ import { Map } from '@/hooks/Mapper/components/map/Map.tsx'; -import { ForwardedRef, useCallback, useRef, useState } from 'react'; -import { MapHandlers, OutCommand, OutCommandHandler, SolarSystemConnection } from '@/hooks/Mapper/types'; +import { useCallback, useRef, useState } from 'react'; +import { OutCommand, OutCommandHandler, SolarSystemConnection } from '@/hooks/Mapper/types'; import { MapRootData, useMapRootState } from '@/hooks/Mapper/mapRootProvider'; import { OnMapSelectionChange } from '@/hooks/Mapper/components/map/map.types.ts'; import isEqual from 'lodash.isequal'; import { ContextMenuSystem, useContextMenuSystemHandlers } from '@/hooks/Mapper/components/contexts'; import { SystemCustomLabelDialog, - SystemSettingsDialog, SystemLinkSignatureDialog, + SystemSettingsDialog, } from '@/hooks/Mapper/components/mapInterface/components'; import classes from './MapWrapper.module.scss'; import { Connections } from '@/hooks/Mapper/components/mapRootContent/components/Connections'; @@ -20,25 +20,45 @@ import { Commands } from '@/hooks/Mapper/types/mapHandlers.ts'; import { useMapEventListener } from '@/hooks/Mapper/events'; import { STORED_INTERFACE_DEFAULT_VALUES } from '@/hooks/Mapper/mapRootProvider/MapRootProvider'; - -interface MapWrapperProps { - refn: ForwardedRef; -} +import { useDeleteSystems } from '@/hooks/Mapper/components/contexts/hooks'; +import { useCommonMapEventProcessor } from '@/hooks/Mapper/components/mapWrapper/hooks/useCommonMapEventProcessor.ts'; // TODO: INFO - this component needs for abstract work with Map instance -export const MapWrapper = ({ refn }: MapWrapperProps) => { +export const MapWrapper = () => { const { update, outCommand, data: { selectedConnections, selectedSystems, hubs, systems }, - interfaceSettings: { isShowMenu, isShowMinimap = STORED_INTERFACE_DEFAULT_VALUES.isShowMinimap, isShowKSpace }, + interfaceSettings: { + isShowMenu, + isShowMinimap = STORED_INTERFACE_DEFAULT_VALUES.isShowMinimap, + isShowKSpace, + isThickConnections, + }, } = useMapRootState(); + const { deleteSystems } = useDeleteSystems(); + const { mapRef, runCommand } = useCommonMapEventProcessor(); const { open, ...systemContextProps } = useContextMenuSystemHandlers({ systems, hubs, outCommand }); const { handleSystemMultipleContext, ...systemMultipleCtxProps } = useContextMenuSystemMultipleHandlers(); - const ref = useRef({ selectedConnections, selectedSystems, systemContextProps, systems }); - ref.current = { selectedConnections, selectedSystems, systemContextProps, systems }; + const [openSettings, setOpenSettings] = useState(null); + const [openLinkSignatures, setOpenLinkSignatures] = useState(null); + const [openCustomLabel, setOpenCustomLabel] = useState(null); + const [selectedConnection, setSelectedConnection] = useState(null); + + const ref = useRef({ selectedConnections, selectedSystems, systemContextProps, systems, deleteSystems }); + ref.current = { selectedConnections, selectedSystems, systemContextProps, systems, deleteSystems }; + + useMapEventListener(event => { + switch (event.name) { + case Commands.linkSignatureToSystem: + setOpenLinkSignatures(event.data); + return true; + } + + runCommand(event); + }); const onSelectionChange: OnMapSelectionChange = useCallback( ({ systems, connections }) => { @@ -59,9 +79,6 @@ export const MapWrapper = ({ refn }: MapWrapperProps) => { [update], ); - const [openSettings, setOpenSettings] = useState(null); - const [openLinkSignatures, setOpenLinkSignatures] = useState(null); - const [openCustomLabel, setOpenCustomLabel] = useState(null); const handleCommand: OutCommandHandler = useCallback( event => { switch (event.type) { @@ -95,22 +112,19 @@ export const MapWrapper = ({ refn }: MapWrapperProps) => { [open], ); - const [selectedConnection, setSelectedConnection] = useState(null); - const handleConnectionDbClick = useCallback((e: SolarSystemConnection) => setSelectedConnection(e), []); - useMapEventListener(event => { - switch (event.name) { - case Commands.linkSignatureToSystem: - setOpenLinkSignatures(event.data); - return true; + const handleManualDelete = useCallback((toDelete: string[]) => { + const restDel = toDelete.filter(x => ref.current.systems.some(y => y.id === x)); + if (restDel.length > 0) { + ref.current.deleteSystems(restDel); } - }); + }, []); return ( <> { minimapClasses={!isShowMenu ? classes.MiniMap : undefined} isShowMinimap={isShowMinimap} showKSpaceBG={isShowKSpace} + onManualDelete={handleManualDelete} + isThickConnections={isThickConnections} /> {openSettings != null && ( diff --git a/assets/js/hooks/Mapper/components/mapWrapper/hooks/useCommonMapEventProcessor.ts b/assets/js/hooks/Mapper/components/mapWrapper/hooks/useCommonMapEventProcessor.ts new file mode 100644 index 00000000..7c8d9967 --- /dev/null +++ b/assets/js/hooks/Mapper/components/mapWrapper/hooks/useCommonMapEventProcessor.ts @@ -0,0 +1,38 @@ +import { MutableRefObject, useCallback, useEffect, useRef } from 'react'; +import { Command, Commands, MapHandlers } from '@/hooks/Mapper/types'; +import { MapEvent } from '@/hooks/Mapper/events'; +import { useMapRootState } from '@/hooks/Mapper/mapRootProvider'; + +export const useCommonMapEventProcessor = () => { + const mapRef = useRef() as MutableRefObject; + const { + data: { systems }, + } = useMapRootState(); + + const refQueue = useRef[]>([]); + + // const ref = useRef({}) + + const runCommand = useCallback(({ name, data }: MapEvent) => { + switch (name) { + case Commands.addSystems: + case Commands.removeSystems: + // case Commands.addConnections: + refQueue.current.push({ name, data }); + return; + } + + // @ts-ignore hz why here type error + mapRef.current?.command(name, data); + }, []); + + useEffect(() => { + refQueue.current.forEach(x => mapRef.current?.command(x.name, x.data)); + refQueue.current = []; + }, [systems]); + + return { + mapRef, + runCommand, + }; +}; diff --git a/assets/js/hooks/Mapper/components/ui-kit/CharacterCard/CharacterCard.tsx b/assets/js/hooks/Mapper/components/ui-kit/CharacterCard/CharacterCard.tsx index d47950d6..86c4a0a4 100644 --- a/assets/js/hooks/Mapper/components/ui-kit/CharacterCard/CharacterCard.tsx +++ b/assets/js/hooks/Mapper/components/ui-kit/CharacterCard/CharacterCard.tsx @@ -4,7 +4,7 @@ import classes from './CharacterCard.module.scss'; import { SystemView } from '@/hooks/Mapper/components/ui-kit/SystemView'; import { CharacterTypeRaw, WithIsOwnCharacter } from '@/hooks/Mapper/types'; import { Commands } from '@/hooks/Mapper/types/mapHandlers.ts'; -import { useMapRootState } from '@/hooks/Mapper/mapRootProvider'; +import { emitMapEvent } from '@/hooks/Mapper/events'; type CharacterCardProps = { compact?: boolean; @@ -34,11 +34,12 @@ export const CharacterCard = ({ useSystemsCache, ...char }: CharacterCardProps) => { - const { mapRef } = useMapRootState(); - const handleSelect = useCallback(() => { - mapRef.current?.command(Commands.centerSystem, char?.location?.solar_system_id?.toString()); - }, [mapRef, char]); + emitMapEvent({ + name: Commands.centerSystem, + data: char?.location?.solar_system_id?.toString(), + }); + }, [char]); return (
    diff --git a/assets/js/hooks/Mapper/mapRootProvider/MapRootProvider.tsx b/assets/js/hooks/Mapper/mapRootProvider/MapRootProvider.tsx index 5dab427b..1d6df42d 100644 --- a/assets/js/hooks/Mapper/mapRootProvider/MapRootProvider.tsx +++ b/assets/js/hooks/Mapper/mapRootProvider/MapRootProvider.tsx @@ -31,24 +31,26 @@ export enum InterfaceStoredSettingsProps { isShowMenu = 'isShowMenu', isShowMinimap = 'isShowMinimap', isShowKSpace = 'isShowKSpace', + isThickConnections = 'isThickConnections', } export type InterfaceStoredSettings = { isShowMenu: boolean; isShowMinimap: boolean; isShowKSpace: boolean; + isThickConnections: boolean; }; export const STORED_INTERFACE_DEFAULT_VALUES: InterfaceStoredSettings = { isShowMenu: false, isShowMinimap: true, isShowKSpace: false, + isThickConnections: false, }; export interface MapRootContextProps { update: ContextStoreDataUpdate; data: MapRootData; - mapRef: RefObject; outCommand: OutCommandHandler; interfaceSettings: InterfaceStoredSettings; setInterfaceSettings: Dispatch>; @@ -57,7 +59,6 @@ export interface MapRootContextProps { const MapRootContext = createContext({ update: () => {}, data: { ...INITIAL_DATA }, - mapRef: { current: null }, // @ts-ignore outCommand: async () => void 0, interfaceSettings: STORED_INTERFACE_DEFAULT_VALUES, @@ -67,7 +68,6 @@ const MapRootContext = createContext({ type MapRootProviderProps = { // eslint-disable-next-line @typescript-eslint/no-explicit-any fwdRef: ForwardedRef; - mapRef: RefObject; outCommand: OutCommandHandler; } & WithChildren; @@ -78,7 +78,7 @@ const MapRootHandlers = forwardRef(({ children }: WithChildren, fwdRef: Forwarde }); // eslint-disable-next-line react/display-name -export const MapRootProvider = ({ children, fwdRef, mapRef, outCommand }: MapRootProviderProps) => { +export const MapRootProvider = ({ children, fwdRef, outCommand }: MapRootProviderProps) => { const { update, ref } = useContextStore({ ...INITIAL_DATA }); const [interfaceSettings, setInterfaceSettings] = useLocalStorageState( @@ -94,7 +94,6 @@ export const MapRootProvider = ({ children, fwdRef, mapRef, outCommand }: MapRoo update, data: ref, outCommand: outCommand, - mapRef: mapRef, setInterfaceSettings, interfaceSettings, }} diff --git a/assets/js/hooks/Mapper/mapRootProvider/hooks/useMapRootHandlers.ts b/assets/js/hooks/Mapper/mapRootProvider/hooks/useMapRootHandlers.ts index 36cb5827..ce70369f 100644 --- a/assets/js/hooks/Mapper/mapRootProvider/hooks/useMapRootHandlers.ts +++ b/assets/js/hooks/Mapper/mapRootProvider/hooks/useMapRootHandlers.ts @@ -44,87 +44,79 @@ export const useMapRootHandlers = (ref: ForwardedRef) => { return { command(type, data) { switch (type) { - case Commands.init: + case Commands.init: // USED mapInit(data as CommandInit); break; - case Commands.addSystems: + case Commands.addSystems: // USED addSystems(data as CommandAddSystems); - setTimeout(() => { - emitMapEvent({ name: Commands.addSystems, data }); - }, 100); break; - case Commands.updateSystems: + case Commands.updateSystems: // USED updateSystems(data as CommandUpdateSystems); break; - case Commands.removeSystems: + case Commands.removeSystems: // USED removeSystems(data as CommandRemoveSystems); - setTimeout(() => { - emitMapEvent({ name: Commands.removeSystems, data }); - }, 100); - break; - case Commands.addConnections: + case Commands.addConnections: // USED addConnections(data as CommandAddConnections); - setTimeout(() => { - emitMapEvent({ name: Commands.addConnections, data }); - }, 100); break; - case Commands.removeConnections: + case Commands.removeConnections: // USED removeConnections(data as CommandRemoveConnections); break; - case Commands.updateConnection: + case Commands.updateConnection: // USED updateConnection(data as CommandUpdateConnection); break; - case Commands.charactersUpdated: + case Commands.charactersUpdated: // USED charactersUpdated(data as CommandCharactersUpdated); break; - case Commands.characterAdded: + case Commands.characterAdded: // USED characterAdded(data as CommandCharacterAdded); break; - case Commands.characterRemoved: + case Commands.characterRemoved: // USED characterRemoved(data as CommandCharacterRemoved); break; - case Commands.characterUpdated: + case Commands.characterUpdated: // USED characterUpdated(data as CommandCharacterUpdated); break; - case Commands.presentCharacters: + case Commands.presentCharacters: // USED presentCharacters(data as CommandPresentCharacters); break; - case Commands.mapUpdated: + case Commands.mapUpdated: // USED mapUpdated(data as CommandMapUpdated); break; case Commands.routes: mapRoutes(data as CommandRoutes); break; - case Commands.centerSystem: + case Commands.centerSystem: // USED // do nothing here break; - case Commands.selectSystem: + case Commands.selectSystem: // USED // do nothing here break; - case Commands.linkSignatureToSystem: - // TODO command data type lost - // @ts-ignore - emitMapEvent({ name: Commands.linkSignatureToSystem, data }); - break; + // case Commands.linkSignatureToSystem: + // // TODO command data type lost + // // @ts-ignore + // emitMapEvent({ name: Commands.linkSignatureToSystem, data }); + // break; case Commands.killsUpdated: // do nothing here break; - case Commands.signaturesUpdated: - // TODO command data type lost - // @ts-ignore - emitMapEvent({ name: Commands.signaturesUpdated, data }); - break; + // case Commands.signaturesUpdated: + // // TODO command data type lost + // // @ts-ignore + // emitMapEvent({ name: Commands.signaturesUpdated, data }); + // break; default: console.warn(`JOipP Interface handlers: Unknown command: ${type}`, data); break; } + + emitMapEvent({ name: type, data }); }, }; }, diff --git a/assets/package.json b/assets/package.json index 575b0786..4612d636 100644 --- a/assets/package.json +++ b/assets/package.json @@ -33,7 +33,7 @@ "react-grid-layout": "^1.3.4", "react-hook-form": "^7.53.1", "react-usestateref": "^1.0.9", - "reactflow": "^11.10.4", + "reactflow": "^11.11.4", "rxjs": "^7.8.1", "tailwindcss": "^3.3.6", "topbar": "^3.0.0", diff --git a/assets/yarn.lock b/assets/yarn.lock index f0c77bae..d6b15927 100644 --- a/assets/yarn.lock +++ b/assets/yarn.lock @@ -3280,9 +3280,9 @@ react@18.2.0: dependencies: loose-envify "^1.1.0" -reactflow@^11.10.4: +reactflow@^11.11.4: version "11.11.4" - resolved "https://registry.npmjs.org/reactflow/-/reactflow-11.11.4.tgz" + resolved "https://registry.yarnpkg.com/reactflow/-/reactflow-11.11.4.tgz#e3593e313420542caed81aecbd73fb9bc6576653" integrity sha512-70FOtJkUWH3BAOsN+LU9lCrKoKbtOPnz2uq0CV2PLdNSwxTXOhCbsZr50GmZ+Rtw3jx8Uv7/vBFtCGixLfd4Og== dependencies: "@reactflow/background" "11.3.14"