Compare commits

...
Author SHA1 Message Date
Brendonovich d0172c3cab fix(app): show SSH auth prompt only when required 2026-09-18 00:28:30 +00:00
3 changed files with 25 additions and 11 deletions
@@ -1,5 +1,18 @@
import { expect, story } from "../../storybook/playwright/story"
story("home connection progress stays in the server row", async ({ mount, page }) => {
const component = await mount("app-dialog-ssh--home-connecting")
await component.getByRole("button", { name: "Projects" }).click()
await expect(page.getByRole("status", { name: "Connecting over SSH…" })).toBeVisible()
await expect(page.locator('[data-action="home-server-authenticate"]')).toHaveCount(0)
})
story("home authentication action appears when required", async ({ mount, page }) => {
const component = await mount("app-dialog-ssh--authentication-required")
await component.getByRole("button", { name: "Projects" }).click()
await expect(page.getByRole("button", { name: "Authenticate", exact: true })).toBeVisible()
})
story("settings menu reconnect retains its prompt handler across server updates", async ({ mount, page }) => {
const component = await mount("app-dialog-ssh--settings-reconnect")
await component.getByRole("button", { name: "More options" }).click()
+2 -8
View File
@@ -11,7 +11,6 @@ import { ProjectAvatar } from "@opencode/ui/project-avatar"
import { Icon } from "@opencode/ui/icon"
import { IconButton } from "@opencode/ui/icon-button"
import { Button } from "@opencode/ui/button"
import { Spinner } from "@opencode/ui/spinner"
import { Menu } from "@opencode/ui/menu"
import { Tooltip } from "@opencode/ui/tooltip"
import { getProjectAvatarVariant, type HomeProjectSelection, type LocalProject } from "@/shell/state/layout"
@@ -256,7 +255,7 @@ function HomeProjectsPanel(props: HomeProjectsViewProps) {
collapsed={collapsed()}
health={props.serverHealth(item)}
/>
<Show when={authentication() || connecting()}>
<Show when={authentication()}>
<div class="mx-3 h-px bg-v2-border-border-base" />
<div class="px-1.5 py-1">
<Button
@@ -264,14 +263,9 @@ function HomeProjectsPanel(props: HomeProjectsViewProps) {
class="w-full"
size="small"
variant="neutral"
disabled={connecting()}
aria-busy={!!connecting()}
onClick={() => props.onAuthenticateServer?.(item)}
>
<Show when={connecting()}>
<Spinner class="size-3.5" />
</Show>
{props.language.t(connecting() ? "ssh.stage.connecting" : "ssh.action.authenticate")}
{props.language.t("ssh.action.authenticate")}
</Button>
</div>
</Show>
@@ -14,6 +14,7 @@ import { SshConnectionPanel } from "./connection-panel"
import { SshServerSettings } from "./settings"
function Fixture(props: {
home?: boolean
session?: boolean
settings?: boolean
incompatible?: boolean
@@ -25,10 +26,15 @@ function Fixture(props: {
const state: { item?: SshItem; before?: SshItem; step: number; timer?: ReturnType<typeof setTimeout> } = {
step: 0,
item:
props.initial === "required"
props.initial === "required" || props.home
? {
config: { id: "story", target: "ssh linuxbook", name: "" },
stage: props.session || props.settings ? "disconnected" : "authentication",
stage:
props.session || props.settings
? "disconnected"
: props.initial === "connecting"
? "connecting"
: "authentication",
saved: true,
detail: "",
}
@@ -141,7 +147,7 @@ function Fixture(props: {
<AuthenticationSettings />
) : props.session ? (
<AuthenticationSession />
) : props.initial === "required" ? (
) : props.initial === "required" || props.home ? (
<AuthenticationHome />
) : (
<Open initial={props.initial} />
@@ -277,6 +283,7 @@ function Open(props: { initial?: string }) {
export default { title: "App/Dialogs/SSH", id: "app-dialog-ssh" }
export const AuthenticationRequired = { render: () => <Fixture initial="required" /> }
export const HomeConnecting = { render: () => <Fixture home initial="connecting" /> }
export const SettingsReconnect = { render: () => <Fixture initial="required" settings connectionDelay={200} /> }
export const IncompatibleHost = { render: () => <Fixture incompatible /> }
export const IncompatibleSession = { render: () => <Fixture initial="required" session incompatible /> }