feat(web/ui): unify session opening and add repo card in project list

- Add openSession utility with tab deduplication/focus
- Use openSession in navbar live sessions, use-instance-actions, and project tool links
- Pass onAddRepository to ProjectListItem and add dashed 'Add Repository' card
- Style add-repo card in projects.css
This commit is contained in:
Developer
2026-06-16 21:31:38 +00:00
parent d5119f29f6
commit bf698b3ff2
6 changed files with 82 additions and 67 deletions
+5 -18
View File
@@ -2,6 +2,7 @@ import { Link, NavLink, Outlet, useLocation } from "react-router-dom";
import type { Session } from "../api/sessions";
import { useTheme } from "../hooks/use-theme";
import { openSession } from "../utils/open-session";
import { useAuth } from "../state/auth";
import { useSessions } from "../state/sessions";
import { useMobileViewport } from "../hooks/use-mobile-viewport";
@@ -33,19 +34,6 @@ const NAV_ITEMS: {
const SessionItem = ({ session }: { session: Session }) => {
const isRunning = session.status === "running";
// Determine the link target:
// - Web tools open their tunnel URL
// - Terminal tools open the terminal page
// - Everything else falls back to the project page
const hasTerminal = session.tool_type_interfaces.includes("terminal");
const hasWeb = session.tool_type_interfaces.includes("web");
const href =
session.url && hasWeb
? session.url
: hasTerminal
? `/instances/${session.id}/terminal`
: `/projects/${session.project_id}`;
const contextName = session.workspace_name || session.repository_name;
const tooltipParts = [
session.display_name,
@@ -56,10 +44,9 @@ const SessionItem = ({ session }: { session: Session }) => {
tooltipParts.push(`(${session.status})`);
return (
<a
href={href}
target={`session-${session.id}`}
rel="noreferrer"
<button
type="button"
onClick={() => openSession(session)}
className="nav-item session-item"
title={tooltipParts.join(" · ")}
>
@@ -76,7 +63,7 @@ const SessionItem = ({ session }: { session: Session }) => {
{session.tool_type_name} · {session.project_name}
</span>
</span>
</a>
</button>
);
};