From e7a8014a5012a4542d748f507fe9957ec0f0e11d Mon Sep 17 00:00:00 2001 From: PhatPhuckDave Date: Sat, 9 Aug 2025 19:37:02 +0200 Subject: [PATCH] feat(app): add waypoint functionality to map and context menu --- app.go | 12 ++++++ frontend/src/components/RegionMap.tsx | 42 ++++++++++++++++++- frontend/src/components/SystemContextMenu.tsx | 33 ++------------- frontend/wailsjs/go/main/App.d.ts | 2 + frontend/wailsjs/go/main/App.js | 4 ++ 5 files changed, 63 insertions(+), 30 deletions(-) diff --git a/app.go b/app.go index 7f65d2f..6209a38 100644 --- a/app.go +++ b/app.go @@ -110,6 +110,18 @@ func (a *App) SetDestinationForAll(systemName string, clearOthers bool, addToBeg return a.ssi.PostWaypointForAll(id, clearOthers, addToBeginning) } +// AddWaypointForAllByName resolves system name and appends as waypoint for all characters +func (a *App) AddWaypointForAllByName(systemName string, addToBeginning bool) error { + if a.ssi == nil { + return errors.New("ESI not initialised") + } + id, err := a.ssi.ResolveSystemIDByName(a.ctx, systemName) + if err != nil { + return err + } + return a.ssi.PostWaypointForAll(id, false, addToBeginning) +} + // ListCharacters returns all characters stored in the token DB func (a *App) ListCharacters() ([]CharacterInfo, error) { if a.ssi == nil || a.ssi.db == nil { diff --git a/frontend/src/components/RegionMap.tsx b/frontend/src/components/RegionMap.tsx index 1776128..7b3c4ee 100644 --- a/frontend/src/components/RegionMap.tsx +++ b/frontend/src/components/RegionMap.tsx @@ -8,6 +8,7 @@ import { loadWormholeSystems, saveWormholeSystem, deleteWormholeSystem } from '@ import { System, Position, Connection as ConnectionType } from '@/lib/types'; import { getSecurityColor } from '@/utils/securityColors'; import { Header } from './Header'; +import { ListCharacters, StartESILogin, SetDestinationForAll, AddWaypointForAllByName } from 'wailsjs/go/main/App'; interface RegionMapProps { regionName: string; @@ -67,6 +68,16 @@ export const RegionMap = ({ regionName, focusSystem, isCompact = false, isWormho const [positions, setPositions] = useState>({}); const svgRef = useRef(null); + const [viaMode, setViaMode] = useState(false); + + useEffect(() => { + const onKeyDown = (e: KeyboardEvent) => { + if (e.key === 'Escape') setViaMode(false); + }; + window.addEventListener('keydown', onKeyDown); + return () => window.removeEventListener('keydown', onKeyDown); + }, []); + const { data: rsystems, isLoading, error } = useRegionData(regionName); useEffect(() => { if (!isLoading && error == null && rsystems && rsystems.size > 0) @@ -363,6 +374,34 @@ export const RegionMap = ({ regionName, focusSystem, isCompact = false, isWormho } }; + const ensureAnyLoggedIn = async () => { + try { + const list = await ListCharacters(); + if (Array.isArray(list) && list.length > 0) return true; + await StartESILogin(); + return false; + } catch { + await StartESILogin(); + return false; + } + }; + + const onSetDestination = async (systemName: string, wantVia: boolean) => { + try { + if (!(await ensureAnyLoggedIn())) return; + if (!viaMode) { + // First selection: set destination and optionally enter via mode + await SetDestinationForAll(systemName, true, false); + if (wantVia) setViaMode(true); + } else { + // Append waypoint + await AddWaypointForAllByName(systemName, false); + } + } catch (e) { + console.error('Set destination failed:', e); + } + }; + // Close context menu when clicking outside useEffect(() => { const handleClickOutside = () => setContextMenu(null); @@ -403,7 +442,7 @@ export const RegionMap = ({ regionName, focusSystem, isCompact = false, isWormho width="100%" height="100%" viewBox={`${viewBox.x} ${viewBox.y} ${viewBox.width} ${viewBox.height}`} - className="cursor-grab active:cursor-grabbing" + className={`cursor-grab active:cursor-grabbing ${viaMode ? 'ring-2 ring-emerald-500' : ''}`} onMouseDown={handleMouseDown} onMouseMove={(e) => { if (isPanning) { @@ -506,6 +545,7 @@ export const RegionMap = ({ regionName, focusSystem, isCompact = false, isWormho onRename={(newName) => handleRenameSystem(contextMenu.system.solarSystemName, newName)} onDelete={handleDeleteSystem} onClearConnections={handleClearConnections} + onSetDestination={onSetDestination} onClose={() => setContextMenu(null)} /> )} diff --git a/frontend/src/components/SystemContextMenu.tsx b/frontend/src/components/SystemContextMenu.tsx index f988b99..7951c2c 100644 --- a/frontend/src/components/SystemContextMenu.tsx +++ b/frontend/src/components/SystemContextMenu.tsx @@ -1,7 +1,5 @@ import { useState, useRef } from 'react'; import { System } from '@/lib/types'; -import { toast } from '@/hooks/use-toast'; -import { StartESILogin, ListCharacters, SetDestinationForAll } from 'wailsjs/go/main/App'; interface SystemContextMenuProps { x: number; @@ -10,10 +8,11 @@ interface SystemContextMenuProps { onRename: (newName: string) => void; onDelete: (system: System) => void; onClearConnections: (system: System) => void; + onSetDestination: (systemName: string, viaMode: boolean) => void; onClose: () => void; } -export const SystemContextMenu = ({ x, y, system, onRename, onDelete, onClearConnections, onClose }: SystemContextMenuProps) => { +export const SystemContextMenu = ({ x, y, system, onRename, onDelete, onClearConnections, onSetDestination, onClose }: SystemContextMenuProps) => { if (!system) { return null; } @@ -29,31 +28,6 @@ export const SystemContextMenu = ({ x, y, system, onRename, onDelete, onClearCon setIsRenaming(false); }; - const ensureLoggedInAny = async () => { - try { - const list = await ListCharacters(); - if (Array.isArray(list) && list.length > 0) return true; - await StartESILogin(); - toast({ title: 'EVE Login', description: 'Please complete login in your browser, then retry.' }); - return false; - } catch { - await StartESILogin(); - toast({ title: 'EVE Login', description: 'Please complete login in your browser, then retry.' }); - return false; - } - }; - - const handleSetDestinationAll = async () => { - try { - if (!(await ensureLoggedInAny())) return; - await SetDestinationForAll(system.solarSystemName, true, false); - toast({ title: 'Destination set', description: `${system.solarSystemName}` }); - onClose(); - } catch (e: any) { - toast({ title: 'Failed to set destination', description: `${system.solarSystemName}: ${String(e)}`, variant: 'destructive' }); - } - }; - return (
diff --git a/frontend/wailsjs/go/main/App.d.ts b/frontend/wailsjs/go/main/App.d.ts index 3a3c2f0..8db8af8 100644 --- a/frontend/wailsjs/go/main/App.d.ts +++ b/frontend/wailsjs/go/main/App.d.ts @@ -2,6 +2,8 @@ // This file is automatically generated. DO NOT EDIT import {main} from '../models'; +export function AddWaypointForAllByName(arg1:string,arg2:boolean):Promise; + export function ESILoggedIn():Promise; export function ESILoginStatus():Promise; diff --git a/frontend/wailsjs/go/main/App.js b/frontend/wailsjs/go/main/App.js index 2ab77b1..e75bc1d 100644 --- a/frontend/wailsjs/go/main/App.js +++ b/frontend/wailsjs/go/main/App.js @@ -2,6 +2,10 @@ // Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL // This file is automatically generated. DO NOT EDIT +export function AddWaypointForAllByName(arg1, arg2) { + return window['go']['main']['App']['AddWaypointForAllByName'](arg1, arg2); +} + export function ESILoggedIn() { return window['go']['main']['App']['ESILoggedIn'](); }