Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions packages/app/src/context/global-sync/event-reducer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ describe("applyDirectoryEvent", () => {
expect(store.sessionTotal).toBe(2)
})

test("cleans session caches when archived", () => {
test("removes an archived session from the list but keeps its caches for open tabs", () => {
const message = userMessage("msg_1", "ses_1")
const [store, setStore] = createStore(
baseState({
Expand All @@ -235,13 +235,13 @@ describe("applyDirectoryEvent", () => {

expect(store.session.map((x) => x.id)).toEqual(["ses_2"])
expect(store.sessionTotal).toBe(1)
expect(store.message.ses_1).toBeUndefined()
expect(store.part[message.id]).toBeUndefined()
expect(store.session_diff.ses_1).toBeUndefined()
expect(store.todo.ses_1).toBeUndefined()
expect(store.permission.ses_1).toBeUndefined()
expect(store.question.ses_1).toBeUndefined()
expect(store.session_status.ses_1).toBeUndefined()
expect(store.message.ses_1).toHaveLength(1)
expect(store.part[message.id]).toHaveLength(1)
expect(store.session_diff.ses_1).toHaveLength(0)
expect(store.todo.ses_1).toHaveLength(0)
expect(store.permission.ses_1).toHaveLength(0)
expect(store.question.ses_1).toHaveLength(0)
expect(store.session_status.ses_1).toEqual({ type: "busy" })
})

test("ignores an archived session absent from a passive directory store", () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/app/src/context/global-sync/event-reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ export function applyDirectoryEvent(input: {
draft.splice(result.index, 1)
}),
)
cleanupSessionCaches(input.setStore, info.id, input.setSessionTodo)
// Caches survive archiving so open tabs keep rendering the session.
if (info.parentID) break
input.setStore("sessionTotal", (value) => Math.max(0, value - 1))
break
Expand Down
1 change: 0 additions & 1 deletion packages/app/src/context/server-session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1002,7 +1002,6 @@ export function createServerSession(
case "session.updated": {
const info = (event.properties as { info: Session }).info
remember(info)
if (info.time.archived) evict([info.id])
return
}
case "session.deleted": {
Expand Down
27 changes: 9 additions & 18 deletions packages/app/src/pages/home-session-archive.test.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,24 @@
import { expect, test } from "bun:test"
import { SESSION_TABS_REMOVED_EVENT, readSessionTabsRemovedDetail } from "@/components/titlebar-session-events"
import { SESSION_TABS_REMOVED_EVENT } from "@/components/titlebar-session-events"
import { archiveHomeSession } from "./home-session-archive"
import type { ServerConnection } from "@/context/server"

const remote = "remote" as ServerConnection.Key
test("archiving a Home session updates the list without touching open tabs", async () => {
let tabsRemovedEvent = false
window.addEventListener(SESSION_TABS_REMOVED_EVENT, () => {
tabsRemovedEvent = true
})

test("archiving a Home session removes its open titlebar tab", async () => {
let detail: ReturnType<typeof readSessionTabsRemovedDetail>
let removed = false
window.addEventListener(
SESSION_TABS_REMOVED_EVENT,
(event) => {
detail = readSessionTabsRemovedDetail(event)
},
{ once: true },
)

await archiveHomeSession({
server: remote,
session: { id: "ses_1", directory: "/workspace" },
sessionID: "ses_1",
archive: async () => undefined,
remove: () => {
removed = true
},
})

expect(removed).toBe(true)
expect(detail).toEqual({ server: remote, directory: "/workspace", sessionIDs: ["ses_1"] })
expect(tabsRemovedEvent).toBe(false)
})

test("reports archive failures without removing the session", async () => {
Expand All @@ -35,8 +27,7 @@ test("reports archive failures without removing the session", async () => {
let removed = false

await archiveHomeSession({
server: remote,
session: { id: "ses_1", directory: "/workspace" },
sessionID: "ses_1",
archive: async () => Promise.reject(failure),
remove: () => {
removed = true
Expand Down
18 changes: 2 additions & 16 deletions packages/app/src/pages/home-session-archive.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,13 @@
import { notifySessionTabsRemoved } from "@/components/titlebar-session-events"
import type { ServerConnection } from "@/context/server"

type HomeSession = {
id: string
directory: string
}

export async function archiveHomeSession(input: {
server: ServerConnection.Key
session: HomeSession
sessionID: string
archive: (sessionID: string) => Promise<unknown>
remove: () => void
onError?: (error: unknown) => void
}) {
await input
.archive(input.session.id)
.archive(input.sessionID)
.then(() => {
input.remove()
notifySessionTabsRemoved({
server: input.server,
directory: input.session.directory,
sessionIDs: [input.session.id],
})
})
.catch((error) => input.onError?.(error))
}
3 changes: 1 addition & 2 deletions packages/app/src/pages/home/home-sessions-controller.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -211,8 +211,7 @@ export function createHomeSessionsController(home: HomeController) {
const [, setStore] = ctx.sync.child(session.directory)
if ((await ctx.sdk.protocol) !== "v1") return
await archiveHomeSession({
server: ServerConnection.key(conn),
session,
sessionID: session.id,
archive: (sessionID) =>
ctx.sdk.client.session.update({
sessionID,
Expand Down
9 changes: 1 addition & 8 deletions packages/app/src/pages/session/session-archive.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { useNavigate } from "@solidjs/router"
import { produce } from "solid-js/store"
import { notifySessionTabsRemoved } from "@/components/titlebar-session-events"
import { useLanguage } from "@/context/language"
import { useSDK } from "@/context/sdk"
import { useSync } from "@/context/sync"
Expand Down Expand Up @@ -37,15 +36,12 @@ export function useSessionArchive() {
navigate(`/${params.dir}/session`)
}

// Archive is a data operation only — open tabs keep rendering the session. Only deletion navigates.
const archive = async (sessionID: string) => {
const session = sync().session.get(sessionID)
if (!session) return
if ((await sdk().protocol) !== "v1") return

const sessions = sync().data.session ?? []
const index = sessions.findIndex((s) => s.id === sessionID)
const nextSession = index === -1 ? undefined : (sessions[index + 1] ?? sessions[index - 1])

await sdk()
.client.session.update({ sessionID, directory: sdk().directory, time: { archived: Date.now() } })
.then(() => {
Expand All @@ -55,9 +51,6 @@ export function useSessionArchive() {
if (index !== -1) draft.session.splice(index, 1)
}),
)
sync().session.evict(sessionID)
navigateAfterRemoval(sessionID, session.parentID, nextSession?.id)
notifySessionTabsRemoved({ directory: sdk().directory, sessionIDs: [sessionID] })
})
.catch((err) => {
showToast({
Expand Down
Loading