feat(Map): Follow Character on Map and auto select their current system

fixes #34
This commit is contained in:
Dmitry Popov
2024-10-11 12:11:33 +04:00
parent 912cad42ac
commit 2f672ae970
28 changed files with 517 additions and 74 deletions

View File

@@ -11,7 +11,7 @@ const Characters = ({ data }: { data: CharacterTypeRaw[] }) => {
const handleSelect = useCallback(
(character: CharacterTypeRaw) => {
mapRef.current?.command(Commands.selectSystem, character?.location?.solar_system_id?.toString());
mapRef.current?.command(Commands.centerSystem, character?.location?.solar_system_id?.toString());
},
[mapRef],
);

View File

@@ -48,19 +48,19 @@ export const useContextMenuSystemInfoHandlers = ({ hubs, outCommand, mapRef }: U
}, []);
const onAddSystem = useCallback(() => {
const { system, outCommand, mapRef } = ref.current;
if (!system) {
const { system: solarSystemId, outCommand, mapRef } = ref.current;
if (!solarSystemId) {
return;
}
outCommand({
type: OutCommand.addSystem,
data: {
system_id: system,
system_id: solarSystemId,
},
});
setTimeout(() => {
mapRef.current?.command(Commands.selectSystem, system);
mapRef.current?.command(Commands.centerSystem, solarSystemId);
setSystem(undefined);
}, 200);
}, []);

View File

@@ -5,5 +5,6 @@ export * from './useMapRemoveSystems';
export * from './useCommandsCharacters';
export * from './useCommandsConnections';
export * from './useCommandsConnections';
export * from './useCenterSystem';
export * from './useSelectSystem';
export * from './useMapCommands';

View File

@@ -0,0 +1,18 @@
import { useReactFlow } from 'reactflow';
import { useCallback } from 'react';
import { CommandCenterSystem } from '@/hooks/Mapper/types';
export const useCenterSystem = () => {
const rf = useReactFlow();
return useCallback((systemId: CommandCenterSystem) => {
if (!rf) {
return;
}
const systemNode = rf.getNodes().find(x => x.data.id === systemId);
if (!systemNode) {
return;
}
rf.setCenter(systemNode.position.x, systemNode.position.y, { duration: 1000 });
}, []);
};

View File

@@ -1,21 +1,21 @@
import { useReactFlow } from 'reactflow';
import { useCallback, useRef } from 'react';
import { useCallback } from 'react';
import { CommandSelectSystem } from '@/hooks/Mapper/types';
export const useSelectSystem = () => {
const rf = useReactFlow();
const ref = useRef({ rf });
ref.current = { rf };
return useCallback((systemId: CommandSelectSystem) => {
if (!ref.current?.rf) {
if (!rf) {
return;
}
const systemNode = ref.current.rf.getNodes().find(x => x.data.id === systemId);
if (!systemNode) {
return;
}
ref.current.rf.setCenter(systemNode.position.x, systemNode.position.y, { duration: 1000 });
rf.setNodes(nds =>
nds.map(node => {
return {
...node,
selected: node.id === systemId,
};
}),
);
}, []);
};

View File

@@ -1,4 +1,4 @@
import { ForwardedRef, useImperativeHandle } from 'react';
import { ForwardedRef, useImperativeHandle, useRef } from 'react';
import {
CommandAddConnections,
CommandAddSystems,
@@ -26,6 +26,7 @@ import {
useMapInit,
useMapRemoveSystems,
useMapUpdateSystems,
useCenterSystem,
useSelectSystem,
} from './api';
import { OnMapSelectionChange } from '@/hooks/Mapper/components/map/map.types.ts';
@@ -35,8 +36,12 @@ export const useMapHandlers = (ref: ForwardedRef<MapHandlers>, onSelectionChange
const mapAddSystems = useMapAddSystems();
const mapUpdateSystems = useMapUpdateSystems();
const removeSystems = useMapRemoveSystems(onSelectionChange);
const centerSystem = useCenterSystem();
const selectSystem = useSelectSystem();
const selectRef = useRef({ onSelectionChange });
selectRef.current = { onSelectionChange };
const { addConnections, removeConnections, updateConnection } = useCommandsConnections();
const { mapUpdated, killsUpdated } = useMapCommands();
const { charactersUpdated, presentCharacters, characterAdded, characterRemoved, characterUpdated } =
@@ -91,8 +96,22 @@ export const useMapHandlers = (ref: ForwardedRef<MapHandlers>, onSelectionChange
killsUpdated(data as CommandKillsUpdated);
break;
case Commands.centerSystem:
setTimeout(() => {
const systemId = `${data}`;
centerSystem(systemId as CommandSelectSystem);
}, 100);
break;
case Commands.selectSystem:
selectSystem(data as CommandSelectSystem);
setTimeout(() => {
const systemId = `${data}`;
selectRef.current.onSelectionChange({
systems: [systemId],
connections: [],
});
selectSystem(systemId as CommandSelectSystem);
}, 100);
break;
case Commands.routes:

View File

@@ -91,7 +91,7 @@ export const RoutesList = ({ data, onContextMenu }: RoutesListProps) => {
const { mapRef } = useMapRootState();
const handleClick = useCallback(
(systemId: number) => mapRef.current?.command(Commands.selectSystem, systemId.toString()),
(systemId: number) => mapRef.current?.command(Commands.centerSystem, systemId.toString()),
[mapRef],
);

View File

@@ -6,6 +6,7 @@ import { useMapRootState } from '@/hooks/Mapper/mapRootProvider';
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';
export interface MapRootContentProps {}
@@ -19,6 +20,8 @@ export const MapRootContent = ({}: MapRootContentProps) => {
const handleShowOnTheMap = useCallback(() => setShowOnTheMap(true), []);
useSkipContextMenu();
return (
<Layout map={<MapWrapper refn={mapRef} />}>
{!isShowMenu ? (

View File

@@ -22,6 +22,13 @@ export const RightBar = ({ onShowOnTheMap }: RightBarProps) => {
});
}, [outCommand]);
const handleOpenUserSettings = useCallback(() => {
outCommand({
type: OutCommand.openUserSettings,
data: null,
});
}, [outCommand]);
const toggleMinimap = useCallback(() => {
setInterfaceSettings(x => ({
...x,
@@ -63,6 +70,16 @@ export const RightBar = ({ onShowOnTheMap }: RightBarProps) => {
</button>
</WdTooltipWrapper>
<WdTooltipWrapper content="User settings" position={TooltipPosition.left}>
<button
className="btn bg-transparent text-gray-400 hover:text-white border-transparent hover:bg-transparent py-2 h-auto min-h-auto"
type="button"
onClick={handleOpenUserSettings}
>
<i className="pi pi-cog text-lg"></i>
</button>
</WdTooltipWrapper>
<WdTooltipWrapper content="Show on the map" position={TooltipPosition.left}>
<button
className="btn bg-transparent text-gray-400 hover:text-white border-transparent hover:bg-transparent py-2 h-auto min-h-auto"
@@ -87,9 +104,9 @@ export const RightBar = ({ onShowOnTheMap }: RightBarProps) => {
onClick={toggleKSpace}
>
{interfaceSettings.isShowKSpace ? (
<i className="pi pi-star-fill text-lg"></i>
<i className="pi pi-heart-fill text-lg"></i>
) : (
<i className="pi pi-star text-lg"></i>
<i className="pi pi-heart text-lg"></i>
)}
</button>
</WdTooltipWrapper>

View File

@@ -37,7 +37,7 @@ export const CharacterCard = ({
const { mapRef } = useMapRootState();
const handleSelect = useCallback(() => {
mapRef.current?.command(Commands.selectSystem, char?.location?.solar_system_id?.toString());
mapRef.current?.command(Commands.centerSystem, char?.location?.solar_system_id?.toString());
}, [mapRef, char]);
return (