From 854524a03cf3aa6d0b4d6cf6dbecd9d25b26abae Mon Sep 17 00:00:00 2001 From: Dmitry Popov Date: Sun, 23 Mar 2025 21:51:26 +0100 Subject: [PATCH 1/5] feat(Core): added support for jumpgates connection type --- .../ContextMenuConnection.tsx | 16 +++++------ .../SolarSystemEdge/SolarSystemEdge.tsx | 16 +++++------ .../hooks/Mapper/components/map/constants.ts | 3 ++- .../components/Connections/Connections.tsx | 21 +++++++-------- assets/js/hooks/Mapper/types/connection.ts | 1 + .../map/server/map_server_connections_impl.ex | 27 +++++++++++++++++-- 6 files changed, 54 insertions(+), 30 deletions(-) diff --git a/assets/js/hooks/Mapper/components/map/components/ContextMenuConnection/ContextMenuConnection.tsx b/assets/js/hooks/Mapper/components/map/components/ContextMenuConnection/ContextMenuConnection.tsx index b1ddbcf4..d3794267 100644 --- a/assets/js/hooks/Mapper/components/map/components/ContextMenuConnection/ContextMenuConnection.tsx +++ b/assets/js/hooks/Mapper/components/map/components/ContextMenuConnection/ContextMenuConnection.tsx @@ -1,10 +1,3 @@ -import React, { RefObject, useMemo } from 'react'; -import { ContextMenu } from 'primereact/contextmenu'; -import { PrimeIcons } from 'primereact/api'; -import { MenuItem } from 'primereact/menuitem'; -import { ConnectionType, MassState, ShipSizeStatus, SolarSystemConnection, TimeStatus } from '@/hooks/Mapper/types'; -import clsx from 'clsx'; -import classes from './ContextMenuConnection.module.scss'; import { MASS_STATE_NAMES, MASS_STATE_NAMES_ORDER, @@ -13,7 +6,14 @@ import { SHIP_SIZES_NAMES_SHORT, SHIP_SIZES_SIZE, } from '@/hooks/Mapper/components/map/constants.ts'; +import { ConnectionType, MassState, ShipSizeStatus, SolarSystemConnection, TimeStatus } from '@/hooks/Mapper/types'; +import clsx from 'clsx'; +import { PrimeIcons } from 'primereact/api'; +import { ContextMenu } from 'primereact/contextmenu'; +import { MenuItem } from 'primereact/menuitem'; +import React, { RefObject, useMemo } from 'react'; import { Edge } from 'reactflow'; +import classes from './ContextMenuConnection.module.scss'; export interface ContextMenuConnectionProps { contextMenuRef: RefObject; @@ -42,7 +42,7 @@ export const ContextMenuConnection: React.FC = ({ } const isFrigateSize = edge.data?.ship_size_type === ShipSizeStatus.small; - const isWormhole = edge.data?.type !== ConnectionType.gate; + const isWormhole = edge.data?.type === ConnectionType.wormhole; return [ ...(isWormhole 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 431349a2..d7868210 100644 --- a/assets/js/hooks/Mapper/components/map/components/SolarSystemEdge/SolarSystemEdge.tsx +++ b/assets/js/hooks/Mapper/components/map/components/SolarSystemEdge/SolarSystemEdge.tsx @@ -1,14 +1,14 @@ import { useCallback, useMemo, useState } from 'react'; -import classes from './SolarSystemEdge.module.scss'; -import { EdgeLabelRenderer, EdgeProps, getBezierPath, getSmoothStepPath, Position, useStore } from 'reactflow'; -import { getEdgeParams } from '@/hooks/Mapper/components/map/utils.ts'; -import clsx from 'clsx'; -import { ConnectionType, 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'; import { SHIP_SIZES_DESCRIPTION, SHIP_SIZES_NAMES_SHORT } from '@/hooks/Mapper/components/map/constants.ts'; +import { getEdgeParams } from '@/hooks/Mapper/components/map/utils.ts'; +import { WdTooltipWrapper } from '@/hooks/Mapper/components/ui-kit/WdTooltipWrapper'; +import { ConnectionType, MassState, ShipSizeStatus, SolarSystemConnection, TimeStatus } from '@/hooks/Mapper/types'; +import clsx from 'clsx'; +import { PrimeIcons } from 'primereact/api'; +import { EdgeLabelRenderer, EdgeProps, getBezierPath, getSmoothStepPath, Position, useStore } from 'reactflow'; +import classes from './SolarSystemEdge.module.scss'; const MAP_TRANSLATES: Record = { [Position.Top]: 'translate(-48%, 0%)', @@ -42,7 +42,7 @@ export const SHIP_SIZES_COLORS = { 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 isWormhole = data?.type !== ConnectionType.gate; + const isWormhole = data?.type === ConnectionType.wormhole; const { data: { isThickConnections }, diff --git a/assets/js/hooks/Mapper/components/map/constants.ts b/assets/js/hooks/Mapper/components/map/constants.ts index 626d5cfb..0450014a 100644 --- a/assets/js/hooks/Mapper/components/map/constants.ts +++ b/assets/js/hooks/Mapper/components/map/constants.ts @@ -716,11 +716,12 @@ export const STATUS_CLASSES: Record = { [STATUSES.dangerous]: 'eve-system-status-dangerous', }; -export const TYPE_NAMES_ORDER = [ConnectionType.wormhole, ConnectionType.gate]; +export const TYPE_NAMES_ORDER = [ConnectionType.wormhole, ConnectionType.gate, ConnectionType.jumpgate]; export const TYPE_NAMES = { [ConnectionType.wormhole]: 'Wormhole', [ConnectionType.gate]: 'Gate', + [ConnectionType.jumpgate]: 'Jumpgate', }; export const MASS_STATE_NAMES_ORDER = [MassState.verge, MassState.half, MassState.normal]; diff --git a/assets/js/hooks/Mapper/components/mapRootContent/components/Connections/Connections.tsx b/assets/js/hooks/Mapper/components/mapRootContent/components/Connections/Connections.tsx index 51e5543b..d88d6b24 100644 --- a/assets/js/hooks/Mapper/components/mapRootContent/components/Connections/Connections.tsx +++ b/assets/js/hooks/Mapper/components/mapRootContent/components/Connections/Connections.tsx @@ -1,22 +1,21 @@ -import classes from './Connections.module.scss'; -import { Sidebar } from 'primereact/sidebar'; -import { useEffect, useMemo, useState, useCallback } from 'react'; import { useMapRootState } from '@/hooks/Mapper/mapRootProvider'; -import { VirtualScroller, VirtualScrollerTemplateOptions } from 'primereact/virtualscroller'; -import clsx from 'clsx'; import { - ConnectionType, - ConnectionOutput, ConnectionInfoOutput, + ConnectionOutput, + ConnectionType, OutCommand, Passage, SolarSystemConnection, } from '@/hooks/Mapper/types'; +import clsx from 'clsx'; +import { Sidebar } from 'primereact/sidebar'; +import { VirtualScroller, VirtualScrollerTemplateOptions } from 'primereact/virtualscroller'; +import { useCallback, useEffect, useMemo, useState } from 'react'; +import classes from './Connections.module.scss'; -import { PassageCard } from './PassageCard'; -import { InfoDrawer, SystemView } from '@/hooks/Mapper/components/ui-kit'; +import { InfoDrawer, SystemView, TimeAgo } from '@/hooks/Mapper/components/ui-kit'; import { kgToTons } from '@/hooks/Mapper/utils/kgToTons.ts'; -import { TimeAgo } from '@/hooks/Mapper/components/ui-kit'; +import { PassageCard } from './PassageCard'; const sortByDate = (a: string, b: string) => new Date(a).getTime() - new Date(b).getTime(); @@ -78,7 +77,7 @@ export const Connections = ({ selectedConnection, onHide }: OnTheMapProps) => { }, [connections, selectedConnection]); const isWormhole = useMemo(() => { - return cnInfo?.type !== ConnectionType.gate; + return cnInfo?.type === ConnectionType.wormhole; }, [cnInfo]); const [passages, setPassages] = useState([]); diff --git a/assets/js/hooks/Mapper/types/connection.ts b/assets/js/hooks/Mapper/types/connection.ts index 30c8b2a1..7d71871d 100644 --- a/assets/js/hooks/Mapper/types/connection.ts +++ b/assets/js/hooks/Mapper/types/connection.ts @@ -1,6 +1,7 @@ export enum ConnectionType { wormhole, gate, + jumpgate, } export enum MassState { diff --git a/lib/wanderer_app/map/server/map_server_connections_impl.ex b/lib/wanderer_app/map/server/map_server_connections_impl.ex index cd20acfc..9da59e11 100644 --- a/lib/wanderer_app/map/server/map_server_connections_impl.ex +++ b/lib/wanderer_app/map/server/map_server_connections_impl.ex @@ -69,6 +69,7 @@ defmodule WandererApp.Map.Server.ConnectionsImpl do @connection_time_status_eol 1 @connection_type_wormhole 0 @connection_type_stargate 1 + @connection_type_jumpgate 2 def get_connection_auto_expire_hours(), do: WandererApp.Env.map_connection_auto_expire_hours() @@ -144,6 +145,28 @@ defmodule WandererApp.Map.Server.ConnectionsImpl do state end + def update_connection_type( + %{map_id: map_id} = state, + %{ + solar_system_source_id: solar_system_source_id, + solar_system_target_id: solar_system_target_id, + character_id: character_id + } = _connection_info, + type + ) do + # :ok = + # maybe_add_connection( + # map_id, + # %{solar_system_id: solar_system_target_id}, + # %{ + # solar_system_id: solar_system_source_id + # }, + # character_id + # ) + + state + end + def get_connection_info( %{map_id: map_id} = _state, %{ @@ -236,7 +259,7 @@ defmodule WandererApp.Map.Server.ConnectionsImpl do } -> connection_start_time = get_start_time(map_id, connection_id) - type != @connection_type_stargate && + type == @connection_type_wormhole && DateTime.diff(DateTime.utc_now(), connection_start_time, :hour) >= connection_auto_eol_hours && is_connection_valid( @@ -292,7 +315,7 @@ defmodule WandererApp.Map.Server.ConnectionsImpl do ) not is_connection_exist || - (type != @connection_type_stargate && is_connection_valid && + (type == @connection_type_wormhole && is_connection_valid && DateTime.diff(DateTime.utc_now(), connection_mark_eol_time, :hour) >= connection_auto_expire_hours - connection_auto_eol_hours + +connection_eol_expire_timeout_hours) From 616e82c497ff4b9a376b2136d9ce05778ab57527 Mon Sep 17 00:00:00 2001 From: DanSylvest Date: Thu, 18 Sep 2025 11:52:16 +0300 Subject: [PATCH 2/5] fix(Map): Add support for Bridge. Made all tooltips left and right paddings. --- .../ContextMenuConnection.module.scss | 4 + .../ContextMenuConnection.tsx | 169 +++++++++++------- .../components/KillsCounter/KillsCounter.tsx | 3 +- .../components/LocalCounter/LocalCounter.tsx | 8 +- .../SolarSystemEdge.module.scss | 7 + .../SolarSystemEdge/SolarSystemEdge.tsx | 28 ++- .../UnsplashedSignature.tsx | 1 + .../hooks/Mapper/components/map/constants.ts | 4 +- .../components/map/helpers/isKnownSpace.ts | 9 + .../components/map/hooks/useMapHandlers.ts | 160 +++++++++-------- .../map/styles/eve-common-variables.scss | 1 + .../components/ui-kit/WdTooltip/WdTooltip.tsx | 12 +- .../WdTooltipWrapper/WdTooltipWrapper.tsx | 16 +- assets/js/hooks/Mapper/types/connection.ts | 2 +- 14 files changed, 270 insertions(+), 154 deletions(-) diff --git a/assets/js/hooks/Mapper/components/map/components/ContextMenuConnection/ContextMenuConnection.module.scss b/assets/js/hooks/Mapper/components/map/components/ContextMenuConnection/ContextMenuConnection.module.scss index d61984d1..0e20cc10 100644 --- a/assets/js/hooks/Mapper/components/map/components/ContextMenuConnection/ContextMenuConnection.module.scss +++ b/assets/js/hooks/Mapper/components/map/components/ContextMenuConnection/ContextMenuConnection.module.scss @@ -8,6 +8,10 @@ background-image: linear-gradient(207deg, transparent, var(--conn-frigate)); } +.ConnectionBridge { + background-image: linear-gradient(207deg, transparent, var(--conn-bridge)); +} + .ConnectionSave { background-image: linear-gradient(207deg, transparent, var(--conn-save)); } diff --git a/assets/js/hooks/Mapper/components/map/components/ContextMenuConnection/ContextMenuConnection.tsx b/assets/js/hooks/Mapper/components/map/components/ContextMenuConnection/ContextMenuConnection.tsx index d3794267..b603087e 100644 --- a/assets/js/hooks/Mapper/components/map/components/ContextMenuConnection/ContextMenuConnection.tsx +++ b/assets/js/hooks/Mapper/components/map/components/ContextMenuConnection/ContextMenuConnection.tsx @@ -14,6 +14,8 @@ import { MenuItem } from 'primereact/menuitem'; import React, { RefObject, useMemo } from 'react'; import { Edge } from 'reactflow'; import classes from './ContextMenuConnection.module.scss'; +import { getSystemStaticInfo } from '@/hooks/Mapper/mapRootProvider/hooks/useLoadSystemStatic.ts'; +import { isNullsecSpace } from '@/hooks/Mapper/components/map/helpers/isKnownSpace.ts'; export interface ContextMenuConnectionProps { contextMenuRef: RefObject; @@ -21,6 +23,7 @@ export interface ContextMenuConnectionProps { onChangeTimeState(): void; onChangeMassState(state: MassState): void; onChangeShipSizeStatus(state: ShipSizeStatus): void; + onChangeType(type: ConnectionType): void; onToggleMassSave(isLocked: boolean): void; onHide(): void; edge?: Edge; @@ -32,6 +35,7 @@ export const ContextMenuConnection: React.FC = ({ onChangeTimeState, onChangeMassState, onChangeShipSizeStatus, + onChangeType, onToggleMassSave, onHide, edge, @@ -41,84 +45,127 @@ export const ContextMenuConnection: React.FC = ({ return []; } + const sourceInfo = getSystemStaticInfo(edge.data?.source); + const targetInfo = getSystemStaticInfo(edge.data?.target); + + const bothNullsec = + sourceInfo && targetInfo && isNullsecSpace(sourceInfo.system_class) && isNullsecSpace(targetInfo.system_class); + const isFrigateSize = edge.data?.ship_size_type === ShipSizeStatus.small; - const isWormhole = edge.data?.type === ConnectionType.wormhole; + + if (edge.data?.type === ConnectionType.bridge) { + return [ + { + label: `Set as Wormhole`, + icon: 'pi hero-arrow-uturn-left', + command: () => onChangeType(ConnectionType.wormhole), + }, + { + label: 'Disconnect', + icon: PrimeIcons.TRASH, + command: onDeleteConnection, + }, + ]; + } + + if (edge.data?.type === ConnectionType.gate) { + return [ + { + label: 'Disconnect', + icon: PrimeIcons.TRASH, + command: onDeleteConnection, + }, + ]; + } return [ - ...(isWormhole + { + label: `EOL`, + className: clsx({ + [classes.ConnectionTimeEOL]: edge.data?.time_status === TimeStatus.eol, + }), + icon: PrimeIcons.CLOCK, + command: onChangeTimeState, + }, + { + label: `Frigate`, + className: clsx({ + [classes.ConnectionFrigate]: isFrigateSize, + }), + icon: PrimeIcons.CLOUD, + command: () => + onChangeShipSizeStatus( + edge.data?.ship_size_type === ShipSizeStatus.small ? ShipSizeStatus.large : ShipSizeStatus.small, + ), + }, + { + label: `Save mass`, + className: clsx({ + [classes.ConnectionSave]: edge.data?.locked, + }), + icon: PrimeIcons.LOCK, + command: () => onToggleMassSave(!edge.data?.locked), + }, + ...(!isFrigateSize ? [ { - label: `EOL`, - className: clsx({ - [classes.ConnectionTimeEOL]: edge.data?.time_status === TimeStatus.eol, - }), - icon: PrimeIcons.CLOCK, - command: onChangeTimeState, - }, - { - label: `Frigate`, - className: clsx({ - [classes.ConnectionFrigate]: isFrigateSize, - }), - icon: PrimeIcons.CLOUD, - command: () => - onChangeShipSizeStatus( - edge.data?.ship_size_type === ShipSizeStatus.small ? ShipSizeStatus.large : ShipSizeStatus.small, - ), - }, - { - label: `Save mass`, - className: clsx({ - [classes.ConnectionSave]: edge.data?.locked, - }), - icon: PrimeIcons.LOCK, - command: () => onToggleMassSave(!edge.data?.locked), - }, - ...(!isFrigateSize - ? [ - { - label: `Mass status`, - icon: PrimeIcons.CHART_PIE, - items: MASS_STATE_NAMES_ORDER.map(x => ({ - label: MASS_STATE_NAMES[x], - className: clsx({ - [classes.SelectedItem]: edge.data?.mass_status === x, - }), - command: () => onChangeMassState(x), - })), - }, - ] - : []), - - { - label: `Ship Size`, - icon: PrimeIcons.CLOUD, - items: SHIP_SIZES_NAMES_ORDER.map(x => ({ - label: ( -
-
{SHIP_SIZES_NAMES_SHORT[x]}
-
{SHIP_SIZES_NAMES[x]}
-
-
- {SHIP_SIZES_SIZE[x]} t. -
-
- ) as unknown as string, // TODO my lovely kostyl + label: `Mass status`, + icon: PrimeIcons.CHART_PIE, + items: MASS_STATE_NAMES_ORDER.map(x => ({ + label: MASS_STATE_NAMES[x], className: clsx({ - [classes.SelectedItem]: edge.data?.ship_size_type === x, + [classes.SelectedItem]: edge.data?.mass_status === x, }), - command: () => onChangeShipSizeStatus(x), + command: () => onChangeMassState(x), })), }, ] : []), + + { + label: `Ship Size`, + icon: PrimeIcons.CLOUD, + items: SHIP_SIZES_NAMES_ORDER.map(x => ({ + label: ( +
+
{SHIP_SIZES_NAMES_SHORT[x]}
+
{SHIP_SIZES_NAMES[x]}
+
+
+ {SHIP_SIZES_SIZE[x]} t. +
+
+ ) as unknown as string, // TODO my lovely kostyl + className: clsx({ + [classes.SelectedItem]: edge.data?.ship_size_type === x, + }), + command: () => onChangeShipSizeStatus(x), + })), + }, + ...(bothNullsec + ? [ + { + label: `Set as Bridge`, + icon: 'pi hero-forward', + command: () => onChangeType(ConnectionType.bridge), + }, + ] + : []), { label: 'Disconnect', icon: PrimeIcons.TRASH, command: onDeleteConnection, }, ]; - }, [edge, onChangeTimeState, onDeleteConnection, onChangeShipSizeStatus, onToggleMassSave, onChangeMassState]); + }, [ + edge, + onChangeTimeState, + onDeleteConnection, + onChangeType, + onChangeShipSizeStatus, + onToggleMassSave, + onChangeMassState, + ]); return ( <> diff --git a/assets/js/hooks/Mapper/components/map/components/KillsCounter/KillsCounter.tsx b/assets/js/hooks/Mapper/components/map/components/KillsCounter/KillsCounter.tsx index 347a301d..6fcb7ec4 100644 --- a/assets/js/hooks/Mapper/components/map/components/KillsCounter/KillsCounter.tsx +++ b/assets/js/hooks/Mapper/components/map/components/KillsCounter/KillsCounter.tsx @@ -56,7 +56,8 @@ export const KillsCounter = ({ className={className} tooltipClassName="!px-0" size={size} - interactive={true} + interactive + smallPaddings > {children} diff --git a/assets/js/hooks/Mapper/components/map/components/LocalCounter/LocalCounter.tsx b/assets/js/hooks/Mapper/components/map/components/LocalCounter/LocalCounter.tsx index ad02c909..3298731c 100644 --- a/assets/js/hooks/Mapper/components/map/components/LocalCounter/LocalCounter.tsx +++ b/assets/js/hooks/Mapper/components/map/components/LocalCounter/LocalCounter.tsx @@ -46,7 +46,13 @@ export const LocalCounter = ({ localCounterCharacters, hasUserCharacters, showIc [classes.Pathfinder]: theme === AvailableThemes.pathfinder, })} > - +
= { [Position.Top]: 'translate(-48%, 0%)', @@ -43,6 +44,8 @@ export const SolarSystemEdge = ({ id, source, target, markerEnd, style, data }: const sourceNode = useStore(useCallback(store => store.nodeInternals.get(source), [source])); const targetNode = useStore(useCallback(store => store.nodeInternals.get(target), [target])); const isWormhole = data?.type === ConnectionType.wormhole; + const isGate = data?.type === ConnectionType.gate; + const isBridge = data?.type === ConnectionType.bridge; const { data: { isThickConnections }, @@ -55,9 +58,7 @@ export const SolarSystemEdge = ({ id, source, target, markerEnd, style, data }: const offset = isThickConnections ? MAP_OFFSETS_TICK[targetPos] : MAP_OFFSETS[targetPos]; - const method = isWormhole ? getBezierPath : getBezierPath; - - const [edgePath, labelX, labelY] = method({ + const [edgePath, labelX, labelY] = getBezierPath({ sourceX: sx - offset.x, sourceY: sy - offset.y, sourcePosition: sourcePos, @@ -67,7 +68,7 @@ export const SolarSystemEdge = ({ id, source, target, markerEnd, style, data }: }); return [edgePath, labelX, labelY, sx, sy, tx, ty, sourcePos, targetPos]; - }, [isThickConnections, sourceNode, targetNode, isWormhole]); + }, [isThickConnections, sourceNode, targetNode]); if (!sourceNode || !targetNode || !data) { return null; @@ -81,7 +82,8 @@ export const SolarSystemEdge = ({ id, source, target, markerEnd, style, data }: [classes.Tick]: isThickConnections, [classes.TimeCrit]: isWormhole && data.time_status === TimeStatus.eol, [classes.Hovered]: hovered, - [classes.Gate]: !isWormhole, + [classes.Gate]: isGate, + [classes.Bridge]: isBridge, })} d={path} markerEnd={markerEnd} @@ -95,7 +97,8 @@ export const SolarSystemEdge = ({ id, source, target, markerEnd, style, data }: [classes.MassVerge]: isWormhole && data.mass_status === MassState.verge, [classes.MassHalf]: isWormhole && data.mass_status === MassState.half, [classes.Frigate]: isWormhole && data.ship_size_type === ShipSizeStatus.small, - [classes.Gate]: !isWormhole, + [classes.Gate]: isGate, + [classes.Bridge]: isBridge, })} d={path} markerEnd={markerEnd} @@ -147,6 +150,19 @@ export const SolarSystemEdge = ({ id, source, target, markerEnd, style, data }: )} + {isBridge && ( + + B + + )} + {isWormhole && data.ship_size_type !== ShipSizeStatus.large && (
} + smallPaddings >
diff --git a/assets/js/hooks/Mapper/components/map/constants.ts b/assets/js/hooks/Mapper/components/map/constants.ts index 0cf92405..a0198da2 100644 --- a/assets/js/hooks/Mapper/components/map/constants.ts +++ b/assets/js/hooks/Mapper/components/map/constants.ts @@ -716,12 +716,12 @@ export const STATUS_CLASSES: Record = { [STATUSES.dangerous]: 'eve-system-status-dangerous', }; -export const TYPE_NAMES_ORDER = [ConnectionType.wormhole, ConnectionType.gate, ConnectionType.jumpgate]; +export const TYPE_NAMES_ORDER = [ConnectionType.wormhole, ConnectionType.gate, ConnectionType.bridge]; export const TYPE_NAMES = { [ConnectionType.wormhole]: 'Wormhole', [ConnectionType.gate]: 'Gate', - [ConnectionType.jumpgate]: 'Jumpgate', + [ConnectionType.bridge]: 'Jumpgate', }; export const MASS_STATE_NAMES_ORDER = [MassState.verge, MassState.half, MassState.normal]; diff --git a/assets/js/hooks/Mapper/components/map/helpers/isKnownSpace.ts b/assets/js/hooks/Mapper/components/map/helpers/isKnownSpace.ts index 7fa0b10c..4b4dc6fa 100644 --- a/assets/js/hooks/Mapper/components/map/helpers/isKnownSpace.ts +++ b/assets/js/hooks/Mapper/components/map/helpers/isKnownSpace.ts @@ -15,3 +15,12 @@ export const isKnownSpace = (wormholeClassID: number) => { export const isPossibleSpace = (spaces: number[], wormholeClassID: number) => { return spaces.includes(wormholeClassID); }; + +export const isNullsecSpace = (wormholeClassID: number) => { + switch (wormholeClassID) { + case SOLAR_SYSTEM_CLASS_IDS.ns: + return true; + } + + return false; +}; diff --git a/assets/js/hooks/Mapper/components/map/hooks/useMapHandlers.ts b/assets/js/hooks/Mapper/components/map/hooks/useMapHandlers.ts index bd0068c3..11f594cf 100644 --- a/assets/js/hooks/Mapper/components/map/hooks/useMapHandlers.ts +++ b/assets/js/hooks/Mapper/components/map/hooks/useMapHandlers.ts @@ -49,87 +49,91 @@ export const useMapHandlers = (ref: ForwardedRef, onSelectionChange const { charactersUpdated, presentCharacters, characterAdded, characterRemoved, characterUpdated } = useCommandsCharacters(); - useImperativeHandle(ref, () => { - return { - command(type, data) { - switch (type) { - case Commands.init: - 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: - setTimeout(() => removeConnections(data as CommandRemoveConnections), 100); - break; - case Commands.charactersUpdated: - charactersUpdated(data as CommandCharactersUpdated); - break; - case Commands.characterAdded: - characterAdded(data as CommandCharacterAdded); - break; - case Commands.characterRemoved: - characterRemoved(data as CommandCharacterRemoved); - break; - case Commands.characterUpdated: - characterUpdated(data as CommandCharacterUpdated); - break; - case Commands.presentCharacters: - presentCharacters(data as CommandPresentCharacters); - break; - case Commands.updateConnection: - updateConnection(data as CommandUpdateConnection); - break; - case Commands.mapUpdated: - mapUpdated(data as CommandMapUpdated); - break; - case Commands.killsUpdated: - killsUpdated(data as CommandKillsUpdated); - break; + useImperativeHandle( + ref, + () => { + return { + command(type, data) { + switch (type) { + case Commands.init: + 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: + setTimeout(() => removeConnections(data as CommandRemoveConnections), 100); + break; + case Commands.charactersUpdated: + charactersUpdated(data as CommandCharactersUpdated); + break; + case Commands.characterAdded: + characterAdded(data as CommandCharacterAdded); + break; + case Commands.characterRemoved: + characterRemoved(data as CommandCharacterRemoved); + break; + case Commands.characterUpdated: + characterUpdated(data as CommandCharacterUpdated); + break; + case Commands.presentCharacters: + presentCharacters(data as CommandPresentCharacters); + break; + case Commands.updateConnection: + updateConnection(data as CommandUpdateConnection); + break; + case Commands.mapUpdated: + mapUpdated(data as CommandMapUpdated); + break; + case Commands.killsUpdated: + killsUpdated(data as CommandKillsUpdated); + break; - case Commands.centerSystem: - setTimeout(() => { - const systemId = `${data}`; - centerSystem(systemId as CommandSelectSystem); - }, 100); - break; + case Commands.centerSystem: + setTimeout(() => { + const systemId = `${data}`; + centerSystem(systemId as CommandSelectSystem); + }, 100); + break; - case Commands.selectSystem: - selectSystems({ systems: [data as string], delay: 500 }); - break; + case Commands.selectSystem: + selectSystems({ systems: [data as string], delay: 500 }); + break; - case Commands.selectSystems: - selectSystems(data as CommandSelectSystems); - break; + case Commands.selectSystems: + selectSystems(data as CommandSelectSystems); + break; - case Commands.pingAdded: - case Commands.pingCancelled: - case Commands.routes: - case Commands.signaturesUpdated: - case Commands.linkSignatureToSystem: - case Commands.detailedKillsUpdated: - case Commands.characterActivityData: - case Commands.trackingCharactersData: - case Commands.updateActivity: - case Commands.updateTracking: - case Commands.userSettingsUpdated: - // do nothing - break; + case Commands.pingAdded: + case Commands.pingCancelled: + case Commands.routes: + case Commands.signaturesUpdated: + case Commands.linkSignatureToSystem: + case Commands.detailedKillsUpdated: + case Commands.characterActivityData: + case Commands.trackingCharactersData: + case Commands.updateActivity: + case Commands.updateTracking: + case Commands.userSettingsUpdated: + // do nothing + break; - default: - console.warn(`Map handlers: Unknown command: ${type}`, data); - break; - } - }, - }; - }, []); + default: + console.warn(`Map handlers: Unknown command: ${type}`, data); + break; + } + }, + }; + }, + [], + ); }; diff --git a/assets/js/hooks/Mapper/components/map/styles/eve-common-variables.scss b/assets/js/hooks/Mapper/components/map/styles/eve-common-variables.scss index 2af93c92..45025904 100644 --- a/assets/js/hooks/Mapper/components/map/styles/eve-common-variables.scss +++ b/assets/js/hooks/Mapper/components/map/styles/eve-common-variables.scss @@ -118,6 +118,7 @@ $homeDark30: color.adjust($homeBase, $lightness: -30%); --conn-time-eol: #7452c3e3; --conn-frigate: #325d88; + --conn-bridge: rgba(135, 185, 93, 0.85); --conn-save: rgba(155, 102, 45, 0.85); --selected-item-bg: rgba(98, 98, 98, 0.33); } diff --git a/assets/js/hooks/Mapper/components/ui-kit/WdTooltip/WdTooltip.tsx b/assets/js/hooks/Mapper/components/ui-kit/WdTooltip/WdTooltip.tsx index 459e3b7e..34d3996c 100644 --- a/assets/js/hooks/Mapper/components/ui-kit/WdTooltip/WdTooltip.tsx +++ b/assets/js/hooks/Mapper/components/ui-kit/WdTooltip/WdTooltip.tsx @@ -18,6 +18,7 @@ export interface TooltipProps extends Omit, content: (() => React.ReactNode) | React.ReactNode; targetSelector?: string; interactive?: boolean; + smallPaddings?: boolean; } export interface OffsetPosition { @@ -47,6 +48,7 @@ export const WdTooltip = forwardRef( position: tPosition = TooltipPosition.default, offset = 5, interactive = false, + smallPaddings = false, className, ...restProps }: TooltipProps, @@ -264,10 +266,14 @@ export const WdTooltip = forwardRef( ref={tooltipRef} className={clsx( classes.tooltip, - interactive ? 'pointer-events-auto' : 'pointer-events-none', - 'absolute px-1 py-1', + 'absolute px-2 py-1', 'border rounded-sm border-green-300 border-opacity-10 bg-stone-900 bg-opacity-90', - pos == null && 'invisible', + { + 'pointer-events-auto': interactive, + 'pointer-events-none': !interactive, + invisible: pos == null, + '!px-1': smallPaddings, + }, className, )} style={{ diff --git a/assets/js/hooks/Mapper/components/ui-kit/WdTooltipWrapper/WdTooltipWrapper.tsx b/assets/js/hooks/Mapper/components/ui-kit/WdTooltipWrapper/WdTooltipWrapper.tsx index fdf7da9e..ce5d80ce 100644 --- a/assets/js/hooks/Mapper/components/ui-kit/WdTooltipWrapper/WdTooltipWrapper.tsx +++ b/assets/js/hooks/Mapper/components/ui-kit/WdTooltipWrapper/WdTooltipWrapper.tsx @@ -8,13 +8,26 @@ export type WdTooltipWrapperProps = { content?: (() => ReactNode) | ReactNode; size?: TooltipSize; interactive?: boolean; + smallPaddings?: boolean; tooltipClassName?: string; } & Omit, 'content' | 'size'> & Omit; export const WdTooltipWrapper = forwardRef( ( - { className, children, content, offset, position, targetSelector, interactive, size, tooltipClassName, ...props }, + { + className, + children, + content, + offset, + position, + targetSelector, + interactive, + smallPaddings, + size, + tooltipClassName, + ...props + }, forwardedRef, ) => { const suffix = useMemo(() => Math.random().toString(36).slice(2, 7), []); @@ -31,6 +44,7 @@ export const WdTooltipWrapper = forwardRef diff --git a/assets/js/hooks/Mapper/types/connection.ts b/assets/js/hooks/Mapper/types/connection.ts index 7d71871d..a8235756 100644 --- a/assets/js/hooks/Mapper/types/connection.ts +++ b/assets/js/hooks/Mapper/types/connection.ts @@ -1,7 +1,7 @@ export enum ConnectionType { wormhole, gate, - jumpgate, + bridge, } export enum MassState { From f601bb8751c5a8471320959e87e60d0ba777b625 Mon Sep 17 00:00:00 2001 From: Dmitry Popov Date: Tue, 23 Sep 2025 17:48:59 +0200 Subject: [PATCH 3/5] Merge branch 'main' into jumpgates --- lib/wanderer_app/api/map_connection.ex | 1 + .../map/server/map_server_connections_impl.ex | 12 +----------- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/lib/wanderer_app/api/map_connection.ex b/lib/wanderer_app/api/map_connection.ex index 2d3a1254..7bae103e 100644 --- a/lib/wanderer_app/api/map_connection.ex +++ b/lib/wanderer_app/api/map_connection.ex @@ -168,6 +168,7 @@ defmodule WandererApp.Api.MapConnection do # where 0 - Wormhole # where 1 - Gate + # where 2 - Bridge attribute :type, :integer do default(0) diff --git a/lib/wanderer_app/map/server/map_server_connections_impl.ex b/lib/wanderer_app/map/server/map_server_connections_impl.ex index cfb4c468..c6d11b8d 100644 --- a/lib/wanderer_app/map/server/map_server_connections_impl.ex +++ b/lib/wanderer_app/map/server/map_server_connections_impl.ex @@ -72,7 +72,7 @@ defmodule WandererApp.Map.Server.ConnectionsImpl do @connection_time_status_eol 1 @connection_type_wormhole 0 @connection_type_stargate 1 - @connection_type_jumpgate 2 + @connection_type_bridge 2 @medium_ship_size 1 def get_connection_auto_expire_hours(), do: WandererApp.Env.map_connection_auto_expire_hours() @@ -156,16 +156,6 @@ defmodule WandererApp.Map.Server.ConnectionsImpl do } = _connection_info, type ) do - # :ok = - # maybe_add_connection( - # map_id, - # %{solar_system_id: solar_system_target_id}, - # %{ - # solar_system_id: solar_system_source_id - # }, - # character_id - # ) - state end From cedf5761f8dcbe1375c622634eef68ad38277211 Mon Sep 17 00:00:00 2001 From: Dmitry Popov Date: Tue, 23 Sep 2025 17:51:45 +0200 Subject: [PATCH 4/5] Merge branch 'main' into jumpgates --- .../live/access_lists/access_lists_live.html.heex | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/wanderer_app_web/live/access_lists/access_lists_live.html.heex b/lib/wanderer_app_web/live/access_lists/access_lists_live.html.heex index 654aba33..fe736092 100644 --- a/lib/wanderer_app_web/live/access_lists/access_lists_live.html.heex +++ b/lib/wanderer_app_web/live/access_lists/access_lists_live.html.heex @@ -34,7 +34,11 @@ - <.link :if={@allow_acl_creation} class="btn mt-2 w-full btn-neutral rounded-none" patch={~p"/access-lists/new"}> + <.link + :if={@allow_acl_creation} + class="btn mt-2 w-full btn-neutral rounded-none" + patch={~p"/access-lists/new"} + > <.icon name="hero-plus-solid" class="w-6 h-6" />

New Access List

@@ -142,10 +146,10 @@ placeholder="Select an owner" options={Enum.map(@characters, fn character -> {character.label, character.id} end)} /> - +
- +
From efa2e5205445af1e1040e941a163bb10cf48769d Mon Sep 17 00:00:00 2001 From: Dmitry Popov Date: Tue, 23 Sep 2025 18:18:32 +0200 Subject: [PATCH 5/5] Merge branch 'main' into jumpgates --- .../controllers/blog_html/index.html.heex | 80 +++++++++++++++---- .../2025/05-07-systems-connections-api.md | 4 +- 2 files changed, 66 insertions(+), 18 deletions(-) diff --git a/lib/wanderer_app_web/controllers/blog_html/index.html.heex b/lib/wanderer_app_web/controllers/blog_html/index.html.heex index 4bea3386..e93c476f 100644 --- a/lib/wanderer_app_web/controllers/blog_html/index.html.heex +++ b/lib/wanderer_app_web/controllers/blog_html/index.html.heex @@ -1,4 +1,4 @@ -
+
@@ -26,23 +26,71 @@
-