Просмотр исходного кода

fix(tui): keep session switching pinned-only (#27775)

Shoubhit Dash 3 месяцев назад
Родитель
Сommit
f99339e525

+ 9 - 33
packages/opencode/src/cli/cmd/tui/app.tsx

@@ -76,8 +76,6 @@ const appBindingCommands = [
   "command.palette.show",
   "session.list",
   "session.new",
-  "session.cycle_recent",
-  "session.cycle_recent_reverse",
   "session.quick_switch.1",
   "session.quick_switch.2",
   "session.quick_switch.3",
@@ -482,35 +480,15 @@ function App(props: { onSnapshot?: () => Promise<string[]> }) {
         },
       },
       ...(Flag.OPENCODE_EXPERIMENTAL_SESSION_SWITCHING
-        ? [
-            {
-              name: "session.cycle_recent",
-              title: "Cycle to previous recent session",
-              category: "Session",
-              hidden: true,
-              run: () => {
-                local.session.cycleRecent(1)
-              },
+        ? Array.from({ length: 9 }, (_, i) => ({
+            name: `session.quick_switch.${i + 1}`,
+            title: `Switch to session in quick slot ${i + 1}`,
+            category: "Session",
+            hidden: true,
+            run: () => {
+              local.session.quickSwitch(i + 1)
             },
-            {
-              name: "session.cycle_recent_reverse",
-              title: "Cycle to next recent session",
-              category: "Session",
-              hidden: true,
-              run: () => {
-                local.session.cycleRecent(-1)
-              },
-            },
-            ...Array.from({ length: 9 }, (_, i) => ({
-              name: `session.quick_switch.${i + 1}`,
-              title: `Switch to session in quick slot ${i + 1}`,
-              category: "Session",
-              hidden: true,
-              run: () => {
-                local.session.quickSwitch(i + 1)
-              },
-            })),
-          ]
+          }))
         : []),
       {
         name: "model.list",
@@ -830,9 +808,7 @@ function App(props: { onSnapshot?: () => Promise<string[]> }) {
       "app",
       Flag.OPENCODE_EXPERIMENTAL_SESSION_SWITCHING
         ? appBindingCommands
-        : appBindingCommands.filter(
-            (c) => !c.startsWith("session.cycle_recent") && !c.startsWith("session.quick_switch"),
-          ),
+        : appBindingCommands.filter((c) => !c.startsWith("session.quick_switch")),
     ),
   }))
 

+ 1 - 25
packages/opencode/src/cli/cmd/tui/component/dialog-session-list.tsx

@@ -130,8 +130,6 @@ export function DialogSessionList() {
 
   const [browseOrder] = createSignal<string[]>(orderByRecency(sync.data.session))
 
-  const RECENT_LIMIT = 5
-
   const options = createMemo(() => {
     const enabled = Flag.OPENCODE_EXPERIMENTAL_SESSION_SWITCHING
     const today = new Date().toDateString()
@@ -144,18 +142,12 @@ export function DialogSessionList() {
     const searchResult = searchResults()
     const displayOrder = searchResult ? orderByRecency(searchResult) : browseOrder()
 
-    const dismissed = enabled ? new Set(local.session.dismissedRecent()) : new Set<string>()
     const pinned = enabled ? local.session.pinned().filter((id) => sessionMap.has(id)) : []
     const pinnedSet = new Set(pinned)
     const slotByID = enabled
       ? new Map<string, number>(local.session.slots().map((id, i) => [id, i + 1]))
       : new Map<string, number>()
 
-    const recent = enabled
-      ? displayOrder.filter((id) => !pinnedSet.has(id) && !dismissed.has(id)).slice(0, RECENT_LIMIT)
-      : []
-    const recentSet = new Set(recent)
-
     function buildOption(id: string, category: string) {
       const x = sessionMap.get(id)
       if (!x) return undefined
@@ -198,7 +190,7 @@ export function DialogSessionList() {
     }
 
     const remaining = displayOrder
-      .filter((id) => !pinnedSet.has(id) && !recentSet.has(id))
+      .filter((id) => !pinnedSet.has(id))
       .map((id) => {
         const x = sessionMap.get(id)
         if (!x) return undefined
@@ -209,7 +201,6 @@ export function DialogSessionList() {
 
     return [
       ...pinned.map((id) => buildOption(id, "Pinned")).filter((x) => x !== undefined),
-      ...recent.map((id) => buildOption(id, "Recent")).filter((x) => x !== undefined),
       ...remaining,
     ]
   })
@@ -245,21 +236,6 @@ export function DialogSessionList() {
                   local.session.togglePin(option.value)
                 },
               },
-              {
-                command: "session.toggle.recent",
-                title: "toggle recent",
-                onTrigger: (option: { value: string }) => {
-                  if (local.session.isPinned(option.value)) {
-                    toast.show({
-                      variant: "info",
-                      message: "Unpin the session first to toggle it in Recent",
-                      duration: 3000,
-                    })
-                    return
-                  }
-                  local.session.toggleRecent(option.value)
-                },
-              },
             ]
           : []),
         {

+ 0 - 6
packages/opencode/src/cli/cmd/tui/config/keybind.ts

@@ -87,9 +87,6 @@ export const Definitions = {
   session_child_cycle_reverse: keybind("left", "Go to previous child session"),
   session_parent: keybind("up", "Go to parent session"),
   session_pin_toggle: keybind("ctrl+f", "Pin or unpin session in the session list"),
-  session_toggle_recent: keybind("ctrl+h", "Show or hide session in the Recent group"),
-  session_cycle_recent: keybind("<leader>]", "Cycle to the previous recent session"),
-  session_cycle_recent_reverse: keybind("<leader>[", "Cycle to the next recent session"),
   session_quick_switch_1: keybind("<leader>1", "Switch to session in quick slot 1"),
   session_quick_switch_2: keybind("<leader>2", "Switch to session in quick slot 2"),
   session_quick_switch_3: keybind("<leader>3", "Switch to session in quick slot 3"),
@@ -273,9 +270,6 @@ export const CommandMap = {
   session_child_cycle_reverse: "session.child.previous",
   session_parent: "session.parent",
   session_pin_toggle: "session.pin.toggle",
-  session_toggle_recent: "session.toggle.recent",
-  session_cycle_recent: "session.cycle_recent",
-  session_cycle_recent_reverse: "session.cycle_recent_reverse",
   session_quick_switch_1: "session.quick_switch.1",
   session_quick_switch_2: "session.quick_switch.2",
   session_quick_switch_3: "session.quick_switch.3",

+ 3 - 101
packages/opencode/src/cli/cmd/tui/context/local.tsx

@@ -1,6 +1,6 @@
 import { createStore } from "solid-js/store"
 import { createSimpleContext } from "./helper"
-import { batch, createEffect, createMemo, on } from "solid-js"
+import { batch, createEffect, createMemo } from "solid-js"
 import { useSync } from "@tui/context/sync"
 import { useTheme } from "@tui/context/theme"
 import { useRoute } from "@tui/context/route"
@@ -8,7 +8,6 @@ import { useEvent } from "@tui/context/event"
 import { uniqueBy } from "remeda"
 import path from "path"
 import { Global } from "@opencode-ai/core/global"
-import { Flag } from "@opencode-ai/core/flag/flag"
 import { iife } from "@/util/iife"
 import { useToast } from "../ui/toast"
 import { useArgs } from "./args"
@@ -387,13 +386,9 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
       const [sessionStore, setSessionStore] = createStore<{
         ready: boolean
         pinned: string[]
-        dismissedRecent: string[]
-        recentOrder: string[]
       }>({
         ready: false,
         pinned: [],
-        dismissedRecent: [],
-        recentOrder: [],
       })
 
       const filePath = path.join(Global.Path.state, "session.json")
@@ -409,16 +404,12 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
         state.pending = false
         void Filesystem.writeJson(filePath, {
           pinned: sessionStore.pinned,
-          dismissedRecent: sessionStore.dismissedRecent,
-          recentOrder: sessionStore.recentOrder,
         })
       }
 
       Filesystem.readJson(filePath)
         .then((x: any) => {
           if (Array.isArray(x.pinned)) setSessionStore("pinned", x.pinned)
-          if (Array.isArray(x.dismissedRecent)) setSessionStore("dismissedRecent", x.dismissedRecent)
-          if (Array.isArray(x.recentOrder)) setSessionStore("recentOrder", x.recentOrder)
         })
         .catch(() => {})
         .finally(() => {
@@ -428,19 +419,10 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
 
       const route = useRoute()
       const event = useEvent()
-      let cycling = false
 
       const slots = createMemo(() => {
-        const rootSessions = sync.data.session.filter((x) => x.parentID === undefined)
-        const existing = new Set(rootSessions.map((x) => x.id))
-        const dismissed = new Set(sessionStore.dismissedRecent)
-        const pins = sessionStore.pinned.filter((id) => existing.has(id))
-        const pinnedSet = new Set(pins)
-        const recent = rootSessions
-          .filter((x) => !pinnedSet.has(x.id) && !dismissed.has(x.id))
-          .toSorted((a, b) => b.time.updated - a.time.updated)
-          .map((x) => x.id)
-        return [...pins, ...recent].slice(0, 9)
+        const existing = new Set(sync.data.session.filter((x) => x.parentID === undefined).map((x) => x.id))
+        return sessionStore.pinned.filter((id) => existing.has(id)).slice(0, 9)
       })
 
       function prune(sessionID: string) {
@@ -451,18 +433,6 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
               sessionStore.pinned.filter((x) => x !== sessionID),
             )
           }
-          if (sessionStore.dismissedRecent.includes(sessionID)) {
-            setSessionStore(
-              "dismissedRecent",
-              sessionStore.dismissedRecent.filter((x) => x !== sessionID),
-            )
-          }
-          if (sessionStore.recentOrder.includes(sessionID)) {
-            setSessionStore(
-              "recentOrder",
-              sessionStore.recentOrder.filter((x) => x !== sessionID),
-            )
-          }
           save()
         })
       }
@@ -471,25 +441,6 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
         prune(evt.properties.info.id)
       })
 
-      if (Flag.OPENCODE_EXPERIMENTAL_SESSION_SWITCHING) {
-        createEffect(
-          on(
-            () => (sessionStore.ready && route.data.type === "session" ? route.data.sessionID : undefined),
-            (sessionID) => {
-              if (!sessionID) return
-              if (cycling) {
-                cycling = false
-                return
-              }
-              const filtered = sessionStore.recentOrder.filter((x) => x !== sessionID)
-              const next = [sessionID, ...filtered].slice(0, 20)
-              setSessionStore("recentOrder", next)
-              save()
-            },
-          ),
-        )
-      }
-
       return {
         get ready() {
           return sessionStore.ready
@@ -497,19 +448,10 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
         pinned() {
           return sessionStore.pinned
         },
-        dismissedRecent() {
-          return sessionStore.dismissedRecent
-        },
-        recentOrder() {
-          return sessionStore.recentOrder
-        },
         slots,
         isPinned(sessionID: string) {
           return sessionStore.pinned.includes(sessionID)
         },
-        isDismissed(sessionID: string) {
-          return sessionStore.dismissedRecent.includes(sessionID)
-        },
         togglePin(sessionID: string) {
           batch(() => {
             const exists = sessionStore.pinned.includes(sessionID)
@@ -520,52 +462,12 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({
             save()
           })
         },
-        toggleRecent(sessionID: string) {
-          batch(() => {
-            const exists = sessionStore.dismissedRecent.includes(sessionID)
-            const next = exists
-              ? sessionStore.dismissedRecent.filter((x) => x !== sessionID)
-              : [sessionID, ...sessionStore.dismissedRecent]
-            setSessionStore("dismissedRecent", next)
-            save()
-          })
-        },
         quickSwitch(slot: number) {
           const target = slots()[slot - 1]
           if (!target) return
           if (route.data.type === "session" && route.data.sessionID === target) return
           route.navigate({ type: "session", sessionID: target })
         },
-        cycleRecent(direction: 1 | -1) {
-          if (route.data.type !== "session") {
-            toast.show({
-              variant: "info",
-              message: "Open a session first to cycle between recent sessions",
-              duration: 3000,
-            })
-            return
-          }
-          const current = route.data.sessionID
-          const order = sessionStore.recentOrder.filter((id) =>
-            sync.data.session.some((s) => s.id === id && s.parentID === undefined),
-          )
-          if (order.length < 2) {
-            toast.show({
-              variant: "info",
-              message: "No other recent sessions to cycle to",
-              duration: 3000,
-            })
-            return
-          }
-          const index = order.indexOf(current)
-          if (index === -1) return
-          const next = index + direction
-          if (next < 0 || next >= order.length) return
-          const target = order[next]
-          if (!target || target === current) return
-          cycling = true
-          route.navigate({ type: "session", sessionID: target })
-        },
       }
     })
 

+ 1 - 13
packages/opencode/src/cli/cmd/tui/feature-plugins/home/tips-view.tsx

@@ -29,8 +29,6 @@ type Shortcuts = {
   messagesToggleConceal: TipShortcut
   modelCycleRecent: TipShortcut
   modelList: TipShortcut
-  sessionCycleRecent: TipShortcut
-  sessionCycleRecentReverse: TipShortcut
   sessionExport: TipShortcut
   sessionInterrupt: TipShortcut
   sessionList: TipShortcut
@@ -41,7 +39,6 @@ type Shortcuts = {
   sessionQuickSwitch9: TipShortcut
   sessionSidebarToggle: TipShortcut
   sessionTimeline: TipShortcut
-  sessionToggleRecent: TipShortcut
   statusView: TipShortcut
   terminalSuspend: TipShortcut
   themeList: TipShortcut
@@ -121,8 +118,6 @@ export function Tips(props: { api: TuiPluginApi; connected?: boolean }) {
     messagesToggleConceal: configShortcut(props.api, "session.toggle.conceal"),
     modelCycleRecent: useCommandShortcut("model.cycle_recent"),
     modelList: useCommandShortcut("model.list"),
-    sessionCycleRecent: useCommandShortcut("session.cycle_recent"),
-    sessionCycleRecentReverse: useCommandShortcut("session.cycle_recent_reverse"),
     sessionExport: configShortcut(props.api, "session.export"),
     sessionInterrupt: configShortcut(props.api, "session.interrupt"),
     sessionList: useCommandShortcut("session.list"),
@@ -133,7 +128,6 @@ export function Tips(props: { api: TuiPluginApi; connected?: boolean }) {
     sessionQuickSwitch9: useCommandShortcut("session.quick_switch.9"),
     sessionSidebarToggle: configShortcut(props.api, "session.sidebar.toggle"),
     sessionTimeline: configShortcut(props.api, "session.timeline"),
-    sessionToggleRecent: configShortcut(props.api, "session.toggle.recent"),
     statusView: useCommandShortcut("opencode.status"),
     terminalSuspend: useCommandShortcut("terminal.suspend"),
     themeList: useCommandShortcut("theme.switch"),
@@ -183,14 +177,8 @@ const TIPS: Tip[] = [
           press(shortcuts.sessionPinToggle(), "in the session list to pin a session so it stays at the top"),
         (shortcuts) =>
           shortcuts.sessionQuickSwitch1() && shortcuts.sessionQuickSwitch9()
-            ? `Pinned and recent sessions are bound to ${shortcutText(shortcuts.sessionQuickSwitch1())} through ${shortcutText(shortcuts.sessionQuickSwitch9())} for one-press switching`
+            ? `Pinned sessions are bound to ${shortcutText(shortcuts.sessionQuickSwitch1())} through ${shortcutText(shortcuts.sessionQuickSwitch9())} for one-press switching`
             : undefined,
-        (shortcuts) =>
-          shortcuts.sessionCycleRecent() && shortcuts.sessionCycleRecentReverse()
-            ? `Press ${shortcutText(shortcuts.sessionCycleRecent())} / ${shortcutText(shortcuts.sessionCycleRecentReverse())} to cycle through recently visited sessions`
-            : undefined,
-        (shortcuts) =>
-          press(shortcuts.sessionToggleRecent(), "in the session list to show or hide a session in the Recent group"),
       ] satisfies Tip[])
     : []),
   "Run {highlight}/compact{/highlight} to summarize long sessions near context limits",