mirror of
https://github.com/anomalyco/opencode.git
synced 2026-11-13 19:46:16 +03:00
fix(app): never hide every server from Home (#60454)
Co-authored-by: Brendonovich <14191578+Brendonovich@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
Unverified
parent
c9ba395ecf
commit
f71cee9804
@@ -61,6 +61,19 @@ test("a working Home session keeps its project avatar and shows its activity rin
|
||||
expect(box!.x).toBeGreaterThan(title!.x + title!.width)
|
||||
})
|
||||
|
||||
test("Home lists projects and sessions when stored state hides every server", async ({ page }) => {
|
||||
await mockStressTimeline(page)
|
||||
await seed(page, { usedProjects: { local: [fixture.project.id] } })
|
||||
// A second seed merges into the server entry the first one wrote.
|
||||
await seed(page, { storage: { "opencode.global.dat:server": { hidden: { [fixture.serverKey]: true } } } })
|
||||
await page.goto("/")
|
||||
|
||||
await expect(
|
||||
page.locator('[data-component="home-project-row"]').filter({ hasText: fixture.project.name }),
|
||||
).toBeVisible()
|
||||
await expect(row(page, fixture.expected.targetTitle)).toBeVisible()
|
||||
})
|
||||
|
||||
test("the session context menu renames, exports, and deletes a Home session", async ({ page }) => {
|
||||
await openHome(page)
|
||||
const target = row(page, fixture.expected.targetTitle)
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
import { expect, test } from "bun:test"
|
||||
import { canRemoveServer, createServerProjects, resolveServerList, ServerConnection, serverLabel } from "./registry"
|
||||
import {
|
||||
canRemoveServer,
|
||||
createServerProjects,
|
||||
resolveServerList,
|
||||
resolveVisibleServers,
|
||||
ServerConnection,
|
||||
serverLabel,
|
||||
} from "./registry"
|
||||
import { Schema } from "effect"
|
||||
import { ServerState } from "./persistence"
|
||||
import { createStore } from "solid-js/store"
|
||||
@@ -99,6 +106,21 @@ test("keeps exact persisted server identities and prevents removing provided ser
|
||||
expect(canRemoveServer({ key, stored, provided: [{ type: "http", http: { url: key } }] })).toBe(false)
|
||||
})
|
||||
|
||||
test("hidden servers are left out, but never every server: the built-in one, otherwise the first, stays shown", () => {
|
||||
const sidecar: ServerConnection.Sidecar = { type: "sidecar", variant: "base", http: { url: "http://127.0.0.1:4096" } }
|
||||
const remote: ServerConnection.Http = { type: "http", http: { url: "https://apollo.example.test" } }
|
||||
const other: ServerConnection.Http = { type: "http", http: { url: "https://zeus.example.test" } }
|
||||
|
||||
const hide = (...servers: ServerConnection.Any[]) =>
|
||||
Object.fromEntries(servers.map((server) => [ServerConnection.key(server), true]))
|
||||
|
||||
expect(resolveVisibleServers({ servers: [sidecar, remote], hidden: {} })).toEqual([sidecar, remote])
|
||||
expect(resolveVisibleServers({ servers: [sidecar, remote], hidden: hide(sidecar) })).toEqual([remote])
|
||||
expect(resolveVisibleServers({ servers: [remote, sidecar], hidden: hide(remote, sidecar) })).toEqual([sidecar])
|
||||
expect(resolveVisibleServers({ servers: [remote, other], hidden: hide(remote, other) })).toEqual([remote])
|
||||
expect(resolveVisibleServers({ servers: [], hidden: hide(remote) })).toEqual([])
|
||||
})
|
||||
|
||||
/** The server props a project store follows, which the test changes. */
|
||||
type ProjectScopeProps = { server: ServerConnection.Key; canonicalLocalServer?: ServerConnection.Key }
|
||||
|
||||
|
||||
@@ -133,6 +133,21 @@ export function canRemoveServer(input: {
|
||||
return input.stored.some((server) => server.http.url === input.key)
|
||||
}
|
||||
|
||||
/**
|
||||
* The servers Home lists. Home needs at least one, so when every server is flagged hidden (stored by an older
|
||||
* build, or edited by hand) the built-in server, otherwise the first, is shown anyway.
|
||||
*/
|
||||
export function resolveVisibleServers(input: {
|
||||
servers: Array<ServerConnection.Any>
|
||||
hidden: StoredState["hidden"]
|
||||
}): Array<ServerConnection.Any> {
|
||||
const visible = input.servers.filter((conn) => !input.hidden[ServerConnection.key(conn)])
|
||||
|
||||
if (visible.length > 0 || input.servers.length === 0) return visible
|
||||
|
||||
return [input.servers.find(ServerConnection.builtin) ?? input.servers[0]]
|
||||
}
|
||||
|
||||
export namespace ServerConnection {
|
||||
type Base = { displayName?: string; label?: string }
|
||||
|
||||
@@ -229,7 +244,16 @@ export const { use: useServers, provider: ServersProvider } = createSimpleContex
|
||||
return resolveServerList({ stored: store.list, props: props.servers })
|
||||
})
|
||||
|
||||
const visibleServers = createMemo(() => allServers().filter((conn) => !store.hidden[ServerConnection.key(conn)]))
|
||||
const visibleServers = createMemo(() => resolveVisibleServers({ servers: allServers(), hidden: store.hidden }))
|
||||
|
||||
// Clears the hidden flag of any server shown despite it, so the stored flags say what Home shows.
|
||||
function unhideShown(servers: Array<ServerConnection.Any>) {
|
||||
for (const conn of resolveVisibleServers({ servers, hidden: store.hidden })) {
|
||||
const key = ServerConnection.key(conn)
|
||||
|
||||
if (store.hidden[key]) setStore("hidden", key, false)
|
||||
}
|
||||
}
|
||||
|
||||
function add(input: ServerConnection.Http) {
|
||||
const url_ = normalizeServerUrl(input.http.url)
|
||||
@@ -254,9 +278,18 @@ export const { use: useServers, provider: ServersProvider } = createSimpleContex
|
||||
const list = store.list.filter((x) => x.http.url !== key)
|
||||
batch(() => {
|
||||
setStore("list", list)
|
||||
// Removing the only shown server must not leave the rest all hidden.
|
||||
unhideShown(resolveServerList({ stored: list, props: props.servers }))
|
||||
})
|
||||
}
|
||||
|
||||
function setHidden(key: ServerConnection.Key, hidden: boolean) {
|
||||
// Home always lists at least one server, so hiding the only shown one does nothing.
|
||||
if (hidden && visibleServers().every((conn) => ServerConnection.key(conn) === key)) return
|
||||
|
||||
setStore("hidden", key, hidden)
|
||||
}
|
||||
|
||||
function canRemove(key: ServerConnection.Key) {
|
||||
return canRemoveServer({ key, provided: props.servers, stored: store.list })
|
||||
}
|
||||
@@ -300,11 +333,9 @@ export const { use: useServers, provider: ServersProvider } = createSimpleContex
|
||||
// state wait on this, but the provider must not block first render on storage.
|
||||
hydrated,
|
||||
isHidden(key: ServerConnection.Key) {
|
||||
return store.hidden[key] ?? false
|
||||
},
|
||||
setHidden(key: ServerConnection.Key, hidden: boolean) {
|
||||
setStore("hidden", key, hidden)
|
||||
return !!store.hidden[key] && !visibleServers().some((conn) => ServerConnection.key(conn) === key)
|
||||
},
|
||||
setHidden,
|
||||
add,
|
||||
remove,
|
||||
canRemove,
|
||||
|
||||
Reference in New Issue
Block a user