Update
This commit is contained in:
@@ -10,6 +10,7 @@ import { getSecurityColor } from '@/utils/securityColors';
|
||||
import { Header } from './Header';
|
||||
import { ListCharacters, StartESILogin, SetDestinationForAll, AddWaypointForAllByName, PostRouteForAllByNames } from 'wailsjs/go/main/App';
|
||||
import { toast } from '@/hooks/use-toast';
|
||||
import { getSystemsRegions } from '@/utils/systemApi';
|
||||
|
||||
interface RegionMapProps {
|
||||
regionName: string;
|
||||
@@ -73,6 +74,8 @@ export const RegionMap = ({ regionName, focusSystem, isCompact = false, isWormho
|
||||
const [viaDest, setViaDest] = useState<string | null>(null);
|
||||
const [viaQueue, setViaQueue] = useState<string[]>([]);
|
||||
|
||||
const [offRegionLinks, setOffRegionLinks] = useState<Array<{ from: string; to: string; toRegion: string }>>([]);
|
||||
|
||||
useEffect(() => {
|
||||
const onKeyDown = async (e: KeyboardEvent) => {
|
||||
if (e.key === 'Escape' && viaMode) {
|
||||
@@ -109,6 +112,41 @@ export const RegionMap = ({ regionName, focusSystem, isCompact = false, isWormho
|
||||
setConnections(connections);
|
||||
}, [systems]);
|
||||
|
||||
// Compute off-region links lazily using PB only for missing nodes
|
||||
useEffect(() => {
|
||||
const computeOffRegion = async () => {
|
||||
if (!systems || systems.size === 0) {
|
||||
setOffRegionLinks([]);
|
||||
return;
|
||||
}
|
||||
const out: Array<{ from: string; to: string; toRegion: string }> = [];
|
||||
const toLookup: Set<string> = new Set();
|
||||
for (const [fromName, sys] of systems.entries()) {
|
||||
const neighbors = (sys.connectedSystems || '').split(',').map(s => s.trim()).filter(Boolean);
|
||||
for (const n of neighbors) {
|
||||
if (!systems.has(n)) {
|
||||
toLookup.add(n);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (toLookup.size === 0) { setOffRegionLinks([]); return; }
|
||||
const regionMap = await getSystemsRegions(Array.from(toLookup));
|
||||
for (const [fromName, sys] of systems.entries()) {
|
||||
const neighbors = (sys.connectedSystems || '').split(',').map(s => s.trim()).filter(Boolean);
|
||||
for (const n of neighbors) {
|
||||
if (!systems.has(n)) {
|
||||
const toRegion = regionMap[n];
|
||||
if (toRegion && toRegion !== regionName) {
|
||||
out.push({ from: fromName, to: n, toRegion });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
setOffRegionLinks(out);
|
||||
};
|
||||
computeOffRegion();
|
||||
}, [systems, regionName]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isWormholeRegion) {
|
||||
loadWormholeSystems().then(wormholeSystems => {
|
||||
@@ -470,6 +508,9 @@ export const RegionMap = ({ regionName, focusSystem, isCompact = false, isWormho
|
||||
<feMergeNode in="SourceGraphic" />
|
||||
</feMerge>
|
||||
</filter>
|
||||
<marker id="arrowhead" markerWidth="6" markerHeight="6" refX="5" refY="3" orient="auto" markerUnits="strokeWidth">
|
||||
<path d="M0,0 L0,6 L6,3 z" fill="#ffd166" />
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
{/* Render all connections */}
|
||||
@@ -512,6 +553,22 @@ export const RegionMap = ({ regionName, focusSystem, isCompact = false, isWormho
|
||||
/>
|
||||
))}
|
||||
|
||||
{/* Off-region link indicators (clickable arrows) */}
|
||||
{offRegionLinks.map((link, idx) => {
|
||||
const pos = positions[link.from];
|
||||
if (!pos) return null;
|
||||
const offsetX = 10;
|
||||
const offsetY = -14;
|
||||
return (
|
||||
<g key={`off-${idx}`} transform={`translate(${pos.x + offsetX}, ${pos.y + offsetY})`}>
|
||||
<rect x={-10} y={-12} width={20} height={14} rx={3} fill="#1f2937" stroke="#ffd166" strokeWidth={1} opacity={0.9} />
|
||||
<path d="M-6,-5 L6,-5" stroke="#ffd166" strokeWidth={2} markerEnd="url(#arrowhead)" />
|
||||
<text x={0} y={6} textAnchor="middle" fontSize="7" fill="#ffd166">{link.toRegion}</text>
|
||||
<rect x={-10} y={-12} width={20} height={20} fill="transparent" onClick={(e) => { e.stopPropagation(); navigate(`/regions/${encodeURIComponent(link.toRegion)}/${encodeURIComponent(link.to)}`); }} />
|
||||
</g>
|
||||
);
|
||||
})}
|
||||
|
||||
{/* Highlight focused system */}
|
||||
{focusSystem && positions[focusSystem] && (
|
||||
<circle
|
||||
|
@@ -4,3 +4,40 @@ export const getSystemId = async (systemName: string): Promise<string> => {
|
||||
const system = await pb.collection('regionview').getFirstListItem(`sysname='${systemName}'`);
|
||||
return system.id;
|
||||
};
|
||||
|
||||
const regionCache: Map<string, string> = new Map();
|
||||
|
||||
export const getSystemRegion = async (systemName: string): Promise<string> => {
|
||||
const key = systemName;
|
||||
const cached = regionCache.get(key);
|
||||
if (cached) return cached;
|
||||
const rec = await pb.collection('regionview').getFirstListItem(`sysname='${systemName}'`);
|
||||
regionCache.set(key, rec.sysregion);
|
||||
return rec.sysregion as string;
|
||||
};
|
||||
|
||||
export const getSystemsRegions = async (systemNames: string[]): Promise<Record<string, string>> => {
|
||||
const result: Record<string, string> = {};
|
||||
const pending: string[] = [];
|
||||
for (const name of systemNames) {
|
||||
const cached = regionCache.get(name);
|
||||
if (cached) {
|
||||
result[name] = cached;
|
||||
} else {
|
||||
pending.push(name);
|
||||
}
|
||||
}
|
||||
if (pending.length === 0) return result;
|
||||
// Fetch uncached in parallel
|
||||
const fetched = await Promise.all(
|
||||
pending.map(async (name) => {
|
||||
const rec = await pb.collection('regionview').getFirstListItem(`sysname='${name}'`);
|
||||
regionCache.set(name, rec.sysregion);
|
||||
return { name, region: rec.sysregion as string };
|
||||
})
|
||||
);
|
||||
for (const { name, region } of fetched) {
|
||||
result[name] = region;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
Reference in New Issue
Block a user