opencode-sesh 1.0.7 → 1.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,12 @@ All notable changes to this project are documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.0.8] - 2026-10-08
9
+
10
+ ### Fixed
11
+
12
+ - **tui:** Keep sidebar context menu clickable and dismiss preview in one press
13
+
8
14
  ## [1.0.7] - 2026-10-08
9
15
 
10
16
  ### Fixed
@@ -460,6 +466,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
460
466
  - Fixture-database regression suite, TypeScript typechecking, and ShellCheck in
461
467
  CI.
462
468
 
469
+ [1.0.8]: https://github.com/ozandogrultan/opencode-sesh/compare/v1.0.7...v1.0.8
463
470
  [1.0.7]: https://github.com/ozandogrultan/opencode-sesh/compare/v1.0.6...v1.0.7
464
471
  [1.0.6]: https://github.com/ozandogrultan/opencode-sesh/compare/v1.0.5...v1.0.6
465
472
  [1.0.5]: https://github.com/ozandogrultan/opencode-sesh/compare/v1.0.4...v1.0.5
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-sesh",
3
- "version": "1.0.7",
3
+ "version": "1.0.8",
4
4
  "description": "Browse, search, preview and resume opencode sessions from the terminal and the TUI.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -352,13 +352,21 @@ function createContextMenu(host: ContextMenuHost) {
352
352
  }
353
353
 
354
354
  const select = (index: number) => {
355
- if (state) publish({ ...state, index: Math.max(0, Math.min(state.items.length - 1, index)) })
355
+ if (!state) return
356
+ const next = Math.max(0, Math.min(state.items.length - 1, index))
357
+ // A still pointer re-fires over events; republishing an identical state
358
+ // would rebuild the keyed menu on every frame, churning renderables until
359
+ // clicks fall through to whatever is beneath.
360
+ if (next === state.index) return
361
+ publish({ ...state, index: next })
356
362
  }
357
363
 
358
364
  const move = (delta: number) => {
359
365
  if (!state) return
360
366
  const count = state.items.length
361
- publish({ ...state, index: (state.index + delta + count) % count })
367
+ const next = (state.index + delta + count) % count
368
+ if (next === state.index) return
369
+ publish({ ...state, index: next })
362
370
  }
363
371
 
364
372
  const activate = (index?: number) => {
@@ -835,7 +843,15 @@ function createTranscriptPreview(api: TuiPluginApi) {
835
843
  })
836
844
  api.ui.dialog.replace(
837
845
  () => (
838
- <box flexDirection="column" paddingLeft={4} paddingRight={4} paddingBottom={1} gap={1} backgroundColor={api.theme.current.backgroundPanel}>
846
+ <box
847
+ flexDirection="column"
848
+ paddingLeft={4}
849
+ paddingRight={4}
850
+ paddingBottom={1}
851
+ gap={1}
852
+ backgroundColor={api.theme.current.backgroundPanel}
853
+ onMouseDown={(event: { stopPropagation: () => void }) => event.stopPropagation()}
854
+ >
839
855
  <box flexDirection="row" justifyContent="space-between">
840
856
  <text attributes={TextAttributes.BOLD}>{entry.title}</text>
841
857
  <text style={{ fg: api.theme.current.textMuted }} onMouseUp={close}>esc</text>
@@ -884,7 +900,14 @@ function createTranscriptPreview(api: TuiPluginApi) {
884
900
 
885
901
  onCleanup(() => disposePreviewKeys?.())
886
902
 
887
- return { open }
903
+ // Outside presses reach the root handler; close on the first one instead of
904
+ // relying on the host backdrop. Gated on our own preview so other dialogs
905
+ // are never touched.
906
+ const closeIfOpen = () => {
907
+ if (previewID()) close()
908
+ }
909
+
910
+ return { open, closeIfOpen }
888
911
  }
889
912
 
890
913
  type TreeRow =
@@ -1313,6 +1336,7 @@ function SidebarSessions(props: { api: TuiPluginApi } & PinProps) {
1313
1336
 
1314
1337
  const onRootMouseDown = () => {
1315
1338
  menu.close()
1339
+ preview.closeIfOpen()
1316
1340
  if (insideSearchBox) {
1317
1341
  insideSearchBox = false
1318
1342
  return
@@ -1575,8 +1599,9 @@ function SidebarSessions(props: { api: TuiPluginApi } & PinProps) {
1575
1599
  <For each={tree()}>
1576
1600
  {(row) => {
1577
1601
  if (row.kind === "group") return (
1578
- <box flexDirection="row" paddingTop={1} onMouseDown={(event: { stopPropagation: () => void }) => {
1602
+ <box flexDirection="row" paddingTop={1} onMouseDown={(event: { button?: number; stopPropagation: () => void }) => {
1579
1603
  event.stopPropagation()
1604
+ if (event.button === RIGHT_BUTTON) return
1580
1605
  toggleGroup(row.dir)
1581
1606
  }}>
1582
1607
  <text flexGrow={1} flexShrink={1} wrapMode="none">
@@ -1701,6 +1726,9 @@ function SidebarSessions(props: { api: TuiPluginApi } & PinProps) {
1701
1726
  height={1}
1702
1727
  backgroundColor={view.state.index === index() ? theme().backgroundElement : RGBA.fromInts(0, 0, 0, 0)}
1703
1728
  onMouseOver={() => menu.select(index())}
1729
+ // Release activates so the press that opens a dialog cannot
1730
+ // straddle it: the release is consumed here before any dialog
1731
+ // opened by the action exists.
1704
1732
  onMouseDown={(event: { stopPropagation: () => void }) => event.stopPropagation()}
1705
1733
  onMouseUp={(event: { button?: number; stopPropagation: () => void }) => {
1706
1734
  event.stopPropagation()
@@ -1825,6 +1853,7 @@ function HomeSessions(props: { api: TuiPluginApi } & PinProps) {
1825
1853
  })
1826
1854
 
1827
1855
  const onRootMouseDown = () => {
1856
+ preview.closeIfOpen()
1828
1857
  if (insideSearchBox) {
1829
1858
  insideSearchBox = false
1830
1859
  return