feat(app): add waypoint functionality to map and context menu
This commit is contained in:
12
app.go
12
app.go
@@ -110,6 +110,18 @@ func (a *App) SetDestinationForAll(systemName string, clearOthers bool, addToBeg
|
|||||||
return a.ssi.PostWaypointForAll(id, clearOthers, addToBeginning)
|
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
|
// ListCharacters returns all characters stored in the token DB
|
||||||
func (a *App) ListCharacters() ([]CharacterInfo, error) {
|
func (a *App) ListCharacters() ([]CharacterInfo, error) {
|
||||||
if a.ssi == nil || a.ssi.db == nil {
|
if a.ssi == nil || a.ssi.db == nil {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { loadWormholeSystems, saveWormholeSystem, deleteWormholeSystem } from '@
|
|||||||
import { System, Position, Connection as ConnectionType } from '@/lib/types';
|
import { System, Position, Connection as ConnectionType } from '@/lib/types';
|
||||||
import { getSecurityColor } from '@/utils/securityColors';
|
import { getSecurityColor } from '@/utils/securityColors';
|
||||||
import { Header } from './Header';
|
import { Header } from './Header';
|
||||||
|
import { ListCharacters, StartESILogin, SetDestinationForAll, AddWaypointForAllByName } from 'wailsjs/go/main/App';
|
||||||
|
|
||||||
interface RegionMapProps {
|
interface RegionMapProps {
|
||||||
regionName: string;
|
regionName: string;
|
||||||
@@ -67,6 +68,16 @@ export const RegionMap = ({ regionName, focusSystem, isCompact = false, isWormho
|
|||||||
const [positions, setPositions] = useState<Record<string, Position>>({});
|
const [positions, setPositions] = useState<Record<string, Position>>({});
|
||||||
const svgRef = useRef<SVGSVGElement>(null);
|
const svgRef = useRef<SVGSVGElement>(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);
|
const { data: rsystems, isLoading, error } = useRegionData(regionName);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isLoading && error == null && rsystems && rsystems.size > 0)
|
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
|
// Close context menu when clicking outside
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleClickOutside = () => setContextMenu(null);
|
const handleClickOutside = () => setContextMenu(null);
|
||||||
@@ -403,7 +442,7 @@ export const RegionMap = ({ regionName, focusSystem, isCompact = false, isWormho
|
|||||||
width="100%"
|
width="100%"
|
||||||
height="100%"
|
height="100%"
|
||||||
viewBox={`${viewBox.x} ${viewBox.y} ${viewBox.width} ${viewBox.height}`}
|
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}
|
onMouseDown={handleMouseDown}
|
||||||
onMouseMove={(e) => {
|
onMouseMove={(e) => {
|
||||||
if (isPanning) {
|
if (isPanning) {
|
||||||
@@ -506,6 +545,7 @@ export const RegionMap = ({ regionName, focusSystem, isCompact = false, isWormho
|
|||||||
onRename={(newName) => handleRenameSystem(contextMenu.system.solarSystemName, newName)}
|
onRename={(newName) => handleRenameSystem(contextMenu.system.solarSystemName, newName)}
|
||||||
onDelete={handleDeleteSystem}
|
onDelete={handleDeleteSystem}
|
||||||
onClearConnections={handleClearConnections}
|
onClearConnections={handleClearConnections}
|
||||||
|
onSetDestination={onSetDestination}
|
||||||
onClose={() => setContextMenu(null)}
|
onClose={() => setContextMenu(null)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
import { useState, useRef } from 'react';
|
import { useState, useRef } from 'react';
|
||||||
import { System } from '@/lib/types';
|
import { System } from '@/lib/types';
|
||||||
import { toast } from '@/hooks/use-toast';
|
|
||||||
import { StartESILogin, ListCharacters, SetDestinationForAll } from 'wailsjs/go/main/App';
|
|
||||||
|
|
||||||
interface SystemContextMenuProps {
|
interface SystemContextMenuProps {
|
||||||
x: number;
|
x: number;
|
||||||
@@ -10,10 +8,11 @@ interface SystemContextMenuProps {
|
|||||||
onRename: (newName: string) => void;
|
onRename: (newName: string) => void;
|
||||||
onDelete: (system: System) => void;
|
onDelete: (system: System) => void;
|
||||||
onClearConnections: (system: System) => void;
|
onClearConnections: (system: System) => void;
|
||||||
|
onSetDestination: (systemName: string, viaMode: boolean) => void;
|
||||||
onClose: () => 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) {
|
if (!system) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -29,31 +28,6 @@ export const SystemContextMenu = ({ x, y, system, onRename, onDelete, onClearCon
|
|||||||
setIsRenaming(false);
|
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 (
|
return (
|
||||||
<div
|
<div
|
||||||
ref={menuRef}
|
ref={menuRef}
|
||||||
@@ -111,8 +85,9 @@ export const SystemContextMenu = ({ x, y, system, onRename, onDelete, onClearCon
|
|||||||
</button>
|
</button>
|
||||||
<div className="h-px bg-slate-700 my-1" />
|
<div className="h-px bg-slate-700 my-1" />
|
||||||
<button
|
<button
|
||||||
onClick={handleSetDestinationAll}
|
onClick={(e) => { onSetDestination(system.solarSystemName, e.shiftKey); onClose(); }}
|
||||||
className="w-full px-3 py-1 text-left text-emerald-400 hover:bg-slate-700 rounded text-sm"
|
className="w-full px-3 py-1 text-left text-emerald-400 hover:bg-slate-700 rounded text-sm"
|
||||||
|
title="Shift-click to enter via mode and append waypoints"
|
||||||
>
|
>
|
||||||
Set destination
|
Set destination
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
2
frontend/wailsjs/go/main/App.d.ts
vendored
2
frontend/wailsjs/go/main/App.d.ts
vendored
@@ -2,6 +2,8 @@
|
|||||||
// This file is automatically generated. DO NOT EDIT
|
// This file is automatically generated. DO NOT EDIT
|
||||||
import {main} from '../models';
|
import {main} from '../models';
|
||||||
|
|
||||||
|
export function AddWaypointForAllByName(arg1:string,arg2:boolean):Promise<void>;
|
||||||
|
|
||||||
export function ESILoggedIn():Promise<boolean>;
|
export function ESILoggedIn():Promise<boolean>;
|
||||||
|
|
||||||
export function ESILoginStatus():Promise<string>;
|
export function ESILoginStatus():Promise<string>;
|
||||||
|
|||||||
@@ -2,6 +2,10 @@
|
|||||||
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
||||||
// This file is automatically generated. DO NOT EDIT
|
// This file is automatically generated. DO NOT EDIT
|
||||||
|
|
||||||
|
export function AddWaypointForAllByName(arg1, arg2) {
|
||||||
|
return window['go']['main']['App']['AddWaypointForAllByName'](arg1, arg2);
|
||||||
|
}
|
||||||
|
|
||||||
export function ESILoggedIn() {
|
export function ESILoggedIn() {
|
||||||
return window['go']['main']['App']['ESILoggedIn']();
|
return window['go']['main']['App']['ESILoggedIn']();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user