feat(app): implement character login and destination setting for multiple characters

This commit introduces several key features:

- **Multiple Character Support**: The application can now handle multiple logged-in EVE Online characters.
- **List Characters**: A new function `ListCharacters` allows retrieving a list of all authenticated characters.
- **Set Destination for All**: The `SetDestinationForAll` function enables setting a destination for all logged-in characters simultaneously.
- **UI Updates**: The frontend has been updated to display logged-in characters and to allow setting destinations for all characters.
- **Backend Refinements**: The ESI SSO logic has been improved to support refreshing tokens for multiple characters and to handle the new multi-character functionality.
- **Dependency Updates**: Dependencies have been updated to their latest versions.

chore: update go module dependencies
This commit is contained in:
2025-08-09 19:30:51 +02:00
parent 3f9d315978
commit 13da1c8340
9 changed files with 378 additions and 262 deletions

View File

@@ -11,7 +11,7 @@ import {
} from '@/components/ui/breadcrumb';
import { Button } from '@/components/ui/button';
import { toast } from '@/hooks/use-toast';
import { StartESILogin, ESILoginStatus, ESILoggedIn } from 'wailsjs/go/main/App';
import { StartESILogin, ESILoggedIn, ListCharacters } from 'wailsjs/go/main/App';
interface HeaderProps {
title: string;
@@ -21,24 +21,31 @@ interface HeaderProps {
}>;
}
interface CharacterInfo { character_id: number; character_name: string }
export const Header = ({ title, breadcrumbs = [] }: HeaderProps) => {
const navigate = useNavigate();
const [status, setStatus] = useState<string>('');
const [chars, setChars] = useState<CharacterInfo[]>([]);
const refreshState = async () => {
try {
const list = await ListCharacters();
setChars((list as any[]).map((c: any) => ({ character_id: c.character_id, character_name: c.character_name })));
} catch {}
};
useEffect(() => {
ESILoginStatus().then(setStatus).catch(() => setStatus(''));
refreshState();
}, []);
const handleLogin = async () => {
try {
await StartESILogin();
toast({ title: 'EVE Login', description: 'Complete login in your browser.' });
// Poll a few times to update status after redirect callback
for (let i = 0; i < 20; i++) {
const ok = await ESILoggedIn();
if (ok) {
const s = await ESILoginStatus();
setStatus(s);
await refreshState();
break;
}
await new Promise(r => setTimeout(r, 500));
@@ -50,7 +57,6 @@ export const Header = ({ title, breadcrumbs = [] }: HeaderProps) => {
return (
<div className="flex-shrink-0 py-4 px-4 border-b border-purple-500/20">
{/* Breadcrumb Navigation */}
{breadcrumbs.length > 0 && (
<div className="mb-3">
<Breadcrumb>
@@ -79,11 +85,18 @@ export const Header = ({ title, breadcrumbs = [] }: HeaderProps) => {
</div>
)}
{/* Title + EVE SSO */}
<div className="flex items-center justify-between">
<h1 className="text-2xl font-bold text-white">{title}</h1>
<div className="flex items-center gap-2">
<span className="text-sm text-slate-300">{status || 'EVE: not logged in'}</span>
<div className="flex items-center gap-3">
{chars.length > 0 && (
<div className="flex flex-wrap gap-2 max-w-[50vw] justify-end">
{chars.map((c) => (
<span key={c.character_id} className="px-2 py-1 rounded-full bg-purple-500/20 text-purple-200 border border-purple-400/40 text-xs whitespace-nowrap">
{c.character_name}
</span>
))}
</div>
)}
<Button size="sm" className="bg-purple-600 hover:bg-purple-700" onClick={handleLogin}>Log in</Button>
</div>
</div>