opencode-sesh 1.0.0 → 1.0.1
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/AGENTS.md +4 -4
- package/CHANGELOG.md +7 -0
- package/README.md +2 -2
- package/package.json +1 -1
- package/tui-plugins/sesh-panel/tui.tsx +54 -36
package/AGENTS.md
CHANGED
|
@@ -122,7 +122,7 @@ Resume happens in place (`exec` after `cd` to the session's cwd).
|
|
|
122
122
|
action must come **before** `reload`/`reload-sync`: placed after, fzf silently
|
|
123
123
|
publishes an empty list (verified on 0.74.3).
|
|
124
124
|
- Destructive actions confirm. `sesh-delete.sh` prompts on a TTY and refuses
|
|
125
|
-
without `--yes` when stdin is not one; the TUI arms on the first
|
|
125
|
+
without `--yes` when stdin is not one; the TUI arms on the first Option-D and
|
|
126
126
|
commits on the second (or `y`).
|
|
127
127
|
- The installer prefers the local opencode version for `@opencode-ai/*` and
|
|
128
128
|
merges (never clobbers) the config `package.json`; opencode runs `bun install`
|
|
@@ -144,7 +144,7 @@ Resume happens in place (`exec` after `cd` to the session's cwd).
|
|
|
144
144
|
Row markers alone signal session state: a running agent animates a loading
|
|
145
145
|
spinner marker, the open session shows its own ●, and every other idle row
|
|
146
146
|
stays neutral (polled every 15 s); Option-P previews
|
|
147
|
-
a row and
|
|
147
|
+
a row and option+d deletes one (armed, then confirmed). The section lists every
|
|
148
148
|
session without a row cap and flex-grows to fill the sidebar, with overflow
|
|
149
149
|
scrolling inside; the picker remains the place for transcript search.
|
|
150
150
|
Sessions waiting on the user (unanswered questions, stuck runs) pin a
|
|
@@ -153,7 +153,7 @@ Resume happens in place (`exec` after `cd` to the session's cwd).
|
|
|
153
153
|
- **Picker:** a custom dialog (not `DialogSelect`) grouped by
|
|
154
154
|
project/directory, recency-ordered, resume via
|
|
155
155
|
`api.route.navigate("session", …)`. `option+o` and the command palette open it;
|
|
156
|
-
|
|
156
|
+
Option-D arms and then confirms a delete through `api.client.session.delete` and
|
|
157
157
|
removes the row only after the server confirms; Ctrl-F forks through
|
|
158
158
|
`api.client.session.fork`; Ctrl-G scopes the list to the selected session's
|
|
159
159
|
project.
|
|
@@ -207,7 +207,7 @@ Resume happens in place (`exec` after `cd` to the session's cwd).
|
|
|
207
207
|
same row. The section lists every session with no row cap
|
|
208
208
|
(`tests/tui.mjs` asserts the cap stays out); overflow scrolls inside the
|
|
209
209
|
stretched section.
|
|
210
|
-
- **Delete in the TUI is two-step.** The first `
|
|
210
|
+
- **Delete in the TUI is two-step.** The first `option+d` arms `pendingDelete`,
|
|
211
211
|
the second (or `y`, or Enter in the picker footer) commits the armed row
|
|
212
212
|
wherever the pointer or cursor is, and `n`/Esc (or a five-second timeout)
|
|
213
213
|
cancels. Moving the pointer must never disarm: edge-hover flicker ate the
|
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.1] - 2026-10-08
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- **tui:** Bind delete to option+d, readable selected rows, keep scroll on delete
|
|
13
|
+
|
|
8
14
|
## [1.0.0] - 2026-10-07
|
|
9
15
|
|
|
10
16
|
### Breaking changes
|
|
@@ -418,6 +424,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
418
424
|
- Fixture-database regression suite, TypeScript typechecking, and ShellCheck in
|
|
419
425
|
CI.
|
|
420
426
|
|
|
427
|
+
[1.0.1]: https://github.com/ozandogrultan/opencode-sesh/compare/v1.0.0...v1.0.1
|
|
421
428
|
[1.0.0]: https://github.com/ozandogrultan/opencode-sesh/compare/v0.14.1...v1.0.0
|
|
422
429
|
[0.14.1]: https://github.com/ozandogrultan/opencode-sesh/compare/v0.14.0...v0.14.1
|
|
423
430
|
[0.14.0]: https://github.com/ozandogrultan/opencode-sesh/compare/v0.13.0...v0.14.0
|
package/README.md
CHANGED
|
@@ -176,7 +176,7 @@ non-interactive `sesh-delete.sh` refuses unless given `--yes`.
|
|
|
176
176
|
| `↑`/`↓`, `PgUp`/`PgDn`, `Home`/`End` | Move the selection |
|
|
177
177
|
| Option-P | Toggle the transcript preview |
|
|
178
178
|
| Enter | Open the selected session |
|
|
179
|
-
|
|
|
179
|
+
| Option-D | Delete the selected session (asks to confirm) |
|
|
180
180
|
| Ctrl-F | Fork the selected session |
|
|
181
181
|
| Ctrl-G | Toggle scope: the selected session's project, or every project |
|
|
182
182
|
| Option-W / Option-S | Show only sessions needing input / pinned sessions |
|
|
@@ -197,7 +197,7 @@ workspace at its directory; outside cmux it shows a toast instead.
|
|
|
197
197
|
Click the sidebar's `search…` box to filter recent sessions in place; click
|
|
198
198
|
elsewhere or press Esc to leave search. Click the **Sessions** heading to drive
|
|
199
199
|
the list from the keyboard instead of the mouse (`↑`/`↓` to move, Enter to open,
|
|
200
|
-
Option-P to preview, Ctrl-S/Ctrl-D to pin,
|
|
200
|
+
Option-P to preview, Ctrl-S/Ctrl-D to pin, Option-D to delete, Esc to leave). Pinned
|
|
201
201
|
directories rise first, while sessions within each directory are ordered by
|
|
202
202
|
last update, newest first. The section lists every session and scrolls to fill
|
|
203
203
|
the sidebar, so click **▾ hide** to collapse it when you need the room.
|
package/package.json
CHANGED
|
@@ -1149,6 +1149,8 @@ function SidebarSessions(props: { api: TuiPluginApi } & PinProps) {
|
|
|
1149
1149
|
return true
|
|
1150
1150
|
}
|
|
1151
1151
|
|
|
1152
|
+
let sidebarScroll: { scrollTop: number } | undefined
|
|
1153
|
+
|
|
1152
1154
|
const deleteEntry = async (entry: Entry) => {
|
|
1153
1155
|
cancelDelete()
|
|
1154
1156
|
if (deleting()) return
|
|
@@ -1165,8 +1167,14 @@ function SidebarSessions(props: { api: TuiPluginApi } & PinProps) {
|
|
|
1165
1167
|
props.api.ui.toast({ message: "Session was not deleted", variant: "error" })
|
|
1166
1168
|
return
|
|
1167
1169
|
}
|
|
1170
|
+
const scrollTop = sidebarScroll?.scrollTop ?? 0
|
|
1168
1171
|
setEntries(remaining)
|
|
1169
1172
|
setHovered(undefined)
|
|
1173
|
+
const restore = () => {
|
|
1174
|
+
if (sidebarScroll) sidebarScroll.scrollTop = scrollTop
|
|
1175
|
+
}
|
|
1176
|
+
queueMicrotask(restore)
|
|
1177
|
+
setTimeout(restore, 0)
|
|
1170
1178
|
props.api.ui.toast({ message: `Deleted "${truncate(entry.title, 40)}"`, variant: "info" })
|
|
1171
1179
|
if (currentID() === entry.id) props.api.route.navigate("home")
|
|
1172
1180
|
} catch {
|
|
@@ -1240,7 +1248,7 @@ function SidebarSessions(props: { api: TuiPluginApi } & PinProps) {
|
|
|
1240
1248
|
},
|
|
1241
1249
|
},
|
|
1242
1250
|
{
|
|
1243
|
-
key: "
|
|
1251
|
+
key: "alt+d",
|
|
1244
1252
|
desc: "Confirm delete",
|
|
1245
1253
|
preventDefault: true,
|
|
1246
1254
|
cmd: () => {
|
|
@@ -1317,7 +1325,7 @@ function SidebarSessions(props: { api: TuiPluginApi } & PinProps) {
|
|
|
1317
1325
|
cmd: () => openSidebarPreview(entry),
|
|
1318
1326
|
},
|
|
1319
1327
|
{
|
|
1320
|
-
key: "
|
|
1328
|
+
key: "alt+d",
|
|
1321
1329
|
desc: "Delete session",
|
|
1322
1330
|
preventDefault: true,
|
|
1323
1331
|
cmd: () => {
|
|
@@ -1364,7 +1372,7 @@ function SidebarSessions(props: { api: TuiPluginApi } & PinProps) {
|
|
|
1364
1372
|
},
|
|
1365
1373
|
},
|
|
1366
1374
|
{
|
|
1367
|
-
key: "
|
|
1375
|
+
key: "alt+d",
|
|
1368
1376
|
desc: "Delete session",
|
|
1369
1377
|
preventDefault: true,
|
|
1370
1378
|
cmd: () => {
|
|
@@ -1463,7 +1471,7 @@ function SidebarSessions(props: { api: TuiPluginApi } & PinProps) {
|
|
|
1463
1471
|
when={entries().length > 0}
|
|
1464
1472
|
fallback={
|
|
1465
1473
|
<text style={{ fg: theme().textMuted }}>
|
|
1466
|
-
{loadFailed() ? "Session list unavailable · will retry" : "No sessions yet ·
|
|
1474
|
+
{loadFailed() ? "Session list unavailable · will retry" : "No sessions yet · option+o to browse"}
|
|
1467
1475
|
</text>
|
|
1468
1476
|
}
|
|
1469
1477
|
>
|
|
@@ -1495,6 +1503,7 @@ function SidebarSessions(props: { api: TuiPluginApi } & PinProps) {
|
|
|
1495
1503
|
</Show>
|
|
1496
1504
|
</box>
|
|
1497
1505
|
<scrollbox
|
|
1506
|
+
ref={(node: { scrollTop: number }) => (sidebarScroll = node)}
|
|
1498
1507
|
flexGrow={1}
|
|
1499
1508
|
flexShrink={1}
|
|
1500
1509
|
verticalScrollbarOptions={{ visible: false }}
|
|
@@ -1567,7 +1576,7 @@ function SidebarSessions(props: { api: TuiPluginApi } & PinProps) {
|
|
|
1567
1576
|
matchColor={theme().warning}
|
|
1568
1577
|
/>
|
|
1569
1578
|
<text flexShrink={0} style={{ fg: isPendingDelete(row.entry.id) ? theme().error : theme().textMuted }}>
|
|
1570
|
-
{isPendingDelete(row.entry.id) ? "
|
|
1579
|
+
{isPendingDelete(row.entry.id) ? "option+d again" : ago(row.entry.updated)}
|
|
1571
1580
|
</text>
|
|
1572
1581
|
</box>
|
|
1573
1582
|
)
|
|
@@ -1575,14 +1584,14 @@ function SidebarSessions(props: { api: TuiPluginApi } & PinProps) {
|
|
|
1575
1584
|
</For>
|
|
1576
1585
|
</scrollbox>
|
|
1577
1586
|
<Show when={remaining() > 0}>
|
|
1578
|
-
<text style={{ fg: theme().textMuted }}>{`… ${remaining()} more ·
|
|
1587
|
+
<text style={{ fg: theme().textMuted }}>{`… ${remaining()} more · option+o for all`}</text>
|
|
1579
1588
|
</Show>
|
|
1580
1589
|
<Show when={query().trim() && filteredEntries().length === 0}>
|
|
1581
|
-
<text style={{ fg: theme().textMuted }}>No title or directory matches ·
|
|
1590
|
+
<text style={{ fg: theme().textMuted }}>No title or directory matches · option+o to search transcripts</text>
|
|
1582
1591
|
</Show>
|
|
1583
1592
|
<Show when={navActive()}>
|
|
1584
1593
|
<box paddingTop={1}>
|
|
1585
|
-
<text style={{ fg: theme().textMuted }}>↑↓ move · enter open ·
|
|
1594
|
+
<text style={{ fg: theme().textMuted }}>↑↓ move · enter open · option+p preview · ctrl+s/d pin · option+d delete · esc done</text>
|
|
1586
1595
|
</box>
|
|
1587
1596
|
</Show>
|
|
1588
1597
|
</Show>
|
|
@@ -1734,7 +1743,7 @@ function HomeSessions(props: { api: TuiPluginApi } & PinProps) {
|
|
|
1734
1743
|
priority: 25,
|
|
1735
1744
|
bindings: [
|
|
1736
1745
|
{ key: "y", desc: "Confirm delete", preventDefault: true, cmd: () => { confirmArmed() } },
|
|
1737
|
-
{ key: "
|
|
1746
|
+
{ key: "alt+d", desc: "Confirm delete", preventDefault: true, cmd: () => { confirmArmed() } },
|
|
1738
1747
|
{ key: "enter", desc: "Confirm delete", preventDefault: true, cmd: () => { confirmArmed() } },
|
|
1739
1748
|
{ key: "n", desc: "Cancel delete", preventDefault: true, cmd: cancelDelete },
|
|
1740
1749
|
{ key: "escape", desc: "Cancel delete", preventDefault: true, cmd: cancelDelete },
|
|
@@ -1790,7 +1799,7 @@ function HomeSessions(props: { api: TuiPluginApi } & PinProps) {
|
|
|
1790
1799
|
cmd: () => preview.open(entry),
|
|
1791
1800
|
},
|
|
1792
1801
|
{
|
|
1793
|
-
key: "
|
|
1802
|
+
key: "alt+d",
|
|
1794
1803
|
desc: "Delete session",
|
|
1795
1804
|
preventDefault: true,
|
|
1796
1805
|
cmd: () => {
|
|
@@ -1851,7 +1860,7 @@ function HomeSessions(props: { api: TuiPluginApi } & PinProps) {
|
|
|
1851
1860
|
<box flexDirection="row" gap={1}>
|
|
1852
1861
|
<text style={{ fg: theme().textMuted }}>Recent sessions</text>
|
|
1853
1862
|
<text style={{ fg: theme().textMuted }}>
|
|
1854
|
-
{loadFailed() ? "· list unavailable, will retry" : "· none yet,
|
|
1863
|
+
{loadFailed() ? "· list unavailable, will retry" : "· none yet, option+o to browse"}
|
|
1855
1864
|
</text>
|
|
1856
1865
|
</box>
|
|
1857
1866
|
}
|
|
@@ -1859,7 +1868,7 @@ function HomeSessions(props: { api: TuiPluginApi } & PinProps) {
|
|
|
1859
1868
|
<box flexDirection="row" justifyContent="space-between" gap={2}>
|
|
1860
1869
|
<box flexDirection="row" gap={1}>
|
|
1861
1870
|
<text style={{ fg: theme().textMuted }}>Recent sessions</text>
|
|
1862
|
-
<text style={{ fg: theme().textMuted }}>·
|
|
1871
|
+
<text style={{ fg: theme().textMuted }}>· option+o for all</text>
|
|
1863
1872
|
</box>
|
|
1864
1873
|
<box
|
|
1865
1874
|
flexDirection="row"
|
|
@@ -1916,14 +1925,14 @@ function HomeSessions(props: { api: TuiPluginApi } & PinProps) {
|
|
|
1916
1925
|
/>
|
|
1917
1926
|
<text flexShrink={0} style={{ fg: pendingDelete() === entry.id ? theme().error : theme().textMuted }}>
|
|
1918
1927
|
{pendingDelete() === entry.id
|
|
1919
|
-
? "
|
|
1928
|
+
? "option+d again"
|
|
1920
1929
|
: `${props.pins().directories.includes(entry.dir) ? "★ " : ""}${prettyDir(entry.dir, home)} · ${ago(entry.updated)}`}
|
|
1921
1930
|
</text>
|
|
1922
1931
|
</box>
|
|
1923
1932
|
)}
|
|
1924
1933
|
</For>
|
|
1925
1934
|
<Show when={visible().length === 0}>
|
|
1926
|
-
<text style={{ fg: theme().textMuted }}>No title or directory matches ·
|
|
1935
|
+
<text style={{ fg: theme().textMuted }}>No title or directory matches · option+o to search transcripts</text>
|
|
1927
1936
|
</Show>
|
|
1928
1937
|
</Show>
|
|
1929
1938
|
</box>
|
|
@@ -2104,7 +2113,7 @@ const tui: TuiPlugin = async (api) => {
|
|
|
2104
2113
|
// lets it size to content, so a taller picker drifts downward. Pin the
|
|
2105
2114
|
// content height and offset it up by the same amount to keep it centred.
|
|
2106
2115
|
const dialogWidth = Math.min(116, api.renderer.width - 2)
|
|
2107
|
-
const CHROME_ROWS =
|
|
2116
|
+
const CHROME_ROWS = 13
|
|
2108
2117
|
const listHeight = () => Math.max(6, Math.floor(termHeight * 0.75) - CHROME_ROWS)
|
|
2109
2118
|
const dialogHeight = () => listHeight() + CHROME_ROWS
|
|
2110
2119
|
const dialogOffset = () => Math.min(0, Math.floor(termHeight / 4 - dialogHeight() / 2 - 1))
|
|
@@ -2115,6 +2124,7 @@ const tui: TuiPlugin = async (api) => {
|
|
|
2115
2124
|
))
|
|
2116
2125
|
|
|
2117
2126
|
let previousSelection: Entry[] = []
|
|
2127
|
+
let deletedAt: number | undefined
|
|
2118
2128
|
createEffect(() => {
|
|
2119
2129
|
const rows = selectableEntries()
|
|
2120
2130
|
const position = rows.findIndex((entry) => entry.id === previousSelection[cursor()]?.id)
|
|
@@ -2122,12 +2132,17 @@ const tui: TuiPlugin = async (api) => {
|
|
|
2122
2132
|
rows.some((entry, index) => entry.id !== previousSelection[index]?.id))) {
|
|
2123
2133
|
// A search/filter/collapse changed the tree: reveal the retained row or
|
|
2124
2134
|
// start at the first result rather than leaving a stale window open.
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2135
|
+
if (deletedAt !== undefined) {
|
|
2136
|
+
setCursor(Math.max(0, Math.min(deletedAt, rows.length - 1)))
|
|
2137
|
+
deletedAt = undefined
|
|
2138
|
+
} else {
|
|
2139
|
+
const next = position >= 0 ? position : 0
|
|
2140
|
+
setCursor(next)
|
|
2141
|
+
const id = rows[next]?.id
|
|
2142
|
+
setViewportStart(position < 0 || next === 0 ? 0 : Math.max(0, pickerRows().findIndex(
|
|
2143
|
+
(row) => row.kind === "item" && row.entry.id === id,
|
|
2144
|
+
)))
|
|
2145
|
+
}
|
|
2131
2146
|
} else if (cursor() >= rows.length) setCursor(Math.max(0, rows.length - 1))
|
|
2132
2147
|
previousSelection = rows
|
|
2133
2148
|
})
|
|
@@ -2260,6 +2275,8 @@ const tui: TuiPlugin = async (api) => {
|
|
|
2260
2275
|
api.ui.toast({ message: "Session was not deleted", variant: "error" })
|
|
2261
2276
|
return
|
|
2262
2277
|
}
|
|
2278
|
+
deletedAt = selectableEntries().findIndex((item) => item.id === entry.id)
|
|
2279
|
+
if (deletedAt < 0) deletedAt = undefined
|
|
2263
2280
|
setAllEntries(remaining)
|
|
2264
2281
|
api.ui.toast({ message: `Deleted "${truncate(entry.title, 40)}"`, variant: "info" })
|
|
2265
2282
|
if (currentSessionID() === entry.id) api.route.navigate("home")
|
|
@@ -2285,7 +2302,7 @@ const tui: TuiPlugin = async (api) => {
|
|
|
2285
2302
|
},
|
|
2286
2303
|
},
|
|
2287
2304
|
{
|
|
2288
|
-
key: "
|
|
2305
|
+
key: "alt+d",
|
|
2289
2306
|
desc: "Confirm delete",
|
|
2290
2307
|
preventDefault: true,
|
|
2291
2308
|
cmd: () => {
|
|
@@ -2367,7 +2384,7 @@ const tui: TuiPlugin = async (api) => {
|
|
|
2367
2384
|
if (entry) onTogglePin("directories", entry.dir)
|
|
2368
2385
|
} },
|
|
2369
2386
|
{
|
|
2370
|
-
key: "
|
|
2387
|
+
key: "alt+d",
|
|
2371
2388
|
desc: "Delete session",
|
|
2372
2389
|
preventDefault: true,
|
|
2373
2390
|
cmd: () => {
|
|
@@ -2422,6 +2439,7 @@ const tui: TuiPlugin = async (api) => {
|
|
|
2422
2439
|
flexDirection="column"
|
|
2423
2440
|
height={dialogHeight()}
|
|
2424
2441
|
marginTop={dialogOffset()}
|
|
2442
|
+
paddingTop={1}
|
|
2425
2443
|
paddingBottom={1}
|
|
2426
2444
|
gap={1}
|
|
2427
2445
|
backgroundColor={api.theme.current.backgroundPanel}
|
|
@@ -2534,7 +2552,7 @@ const tui: TuiPlugin = async (api) => {
|
|
|
2534
2552
|
paddingRight={4}
|
|
2535
2553
|
backgroundColor={
|
|
2536
2554
|
row.entry.id === selectableEntries()[cursor()]?.id
|
|
2537
|
-
? api.theme.current.
|
|
2555
|
+
? api.theme.current.backgroundElement
|
|
2538
2556
|
: RGBA.fromInts(0, 0, 0, 0)
|
|
2539
2557
|
}
|
|
2540
2558
|
onMouseMove={() => {
|
|
@@ -2549,7 +2567,7 @@ const tui: TuiPlugin = async (api) => {
|
|
|
2549
2567
|
>
|
|
2550
2568
|
<box flexDirection="row" gap={1}>
|
|
2551
2569
|
<text flexShrink={0} style={{ fg: row.entry.id === selectableEntries()[cursor()]?.id
|
|
2552
|
-
? api.theme.current.
|
|
2570
|
+
? api.theme.current.text : api.theme.current.textMuted }}>
|
|
2553
2571
|
{row.last ? "└" : "├"}
|
|
2554
2572
|
</text>
|
|
2555
2573
|
<Show when={row.entry.id === currentSessionID()}>
|
|
@@ -2558,7 +2576,7 @@ const tui: TuiPlugin = async (api) => {
|
|
|
2558
2576
|
style={{
|
|
2559
2577
|
fg:
|
|
2560
2578
|
row.entry.id === selectableEntries()[cursor()]?.id
|
|
2561
|
-
? api.theme.current.
|
|
2579
|
+
? api.theme.current.text
|
|
2562
2580
|
: api.theme.current.primary,
|
|
2563
2581
|
}}
|
|
2564
2582
|
>
|
|
@@ -2571,12 +2589,12 @@ const tui: TuiPlugin = async (api) => {
|
|
|
2571
2589
|
bold={row.entry.id === selectableEntries()[cursor()]?.id}
|
|
2572
2590
|
color={
|
|
2573
2591
|
row.entry.id === selectableEntries()[cursor()]?.id
|
|
2574
|
-
? api.theme.current.
|
|
2592
|
+
? api.theme.current.text
|
|
2575
2593
|
: api.theme.current.text
|
|
2576
2594
|
}
|
|
2577
2595
|
matchColor={
|
|
2578
2596
|
row.entry.id === selectableEntries()[cursor()]?.id
|
|
2579
|
-
? api.theme.current.
|
|
2597
|
+
? api.theme.current.text
|
|
2580
2598
|
: api.theme.current.warning
|
|
2581
2599
|
}
|
|
2582
2600
|
/>
|
|
@@ -2587,7 +2605,7 @@ const tui: TuiPlugin = async (api) => {
|
|
|
2587
2605
|
pendingDelete()?.id === row.entry.id
|
|
2588
2606
|
? api.theme.current.error
|
|
2589
2607
|
: row.entry.id === selectableEntries()[cursor()]?.id
|
|
2590
|
-
? api.theme.current.
|
|
2608
|
+
? api.theme.current.text
|
|
2591
2609
|
: api.theme.current.textMuted,
|
|
2592
2610
|
}}
|
|
2593
2611
|
>
|
|
@@ -2608,7 +2626,7 @@ const tui: TuiPlugin = async (api) => {
|
|
|
2608
2626
|
<Highlighted
|
|
2609
2627
|
text={match()}
|
|
2610
2628
|
query={query()}
|
|
2611
|
-
color={row.entry.id === selectableEntries()[cursor()]?.id ? api.theme.current.
|
|
2629
|
+
color={row.entry.id === selectableEntries()[cursor()]?.id ? api.theme.current.text : api.theme.current.textMuted}
|
|
2612
2630
|
matchColor={api.theme.current.warning}
|
|
2613
2631
|
/>
|
|
2614
2632
|
</box>
|
|
@@ -2646,10 +2664,10 @@ const tui: TuiPlugin = async (api) => {
|
|
|
2646
2664
|
>
|
|
2647
2665
|
{pendingDelete()
|
|
2648
2666
|
? `Delete "${truncate(pendingDelete()!.title, 40)}"? y confirm · n cancel`
|
|
2649
|
-
: "↑↓ move · enter open · ctrl+g project ·
|
|
2667
|
+
: "↑↓ move · enter open · ctrl+g project · option+w input · option+s pinned · option+p preview"}
|
|
2650
2668
|
</text>
|
|
2651
2669
|
<Show when={!pendingDelete()}>
|
|
2652
|
-
<text style={{ fg: api.theme.current.textMuted }}>ctrl+s/d pin ·
|
|
2670
|
+
<text style={{ fg: api.theme.current.textMuted }}>ctrl+s/d pin · option+d delete · ctrl+f fork · esc close</text>
|
|
2653
2671
|
</Show>
|
|
2654
2672
|
</box>
|
|
2655
2673
|
<Show when={showPreview()}>
|
|
@@ -2903,7 +2921,7 @@ ORDER BY lifetime_cost DESC`).all() ?? []) as {
|
|
|
2903
2921
|
paddingRight={1}
|
|
2904
2922
|
backgroundColor={
|
|
2905
2923
|
index() === cursor()
|
|
2906
|
-
? api.theme.current.
|
|
2924
|
+
? api.theme.current.backgroundElement
|
|
2907
2925
|
: RGBA.fromInts(0, 0, 0, 0)
|
|
2908
2926
|
}
|
|
2909
2927
|
onMouseDown={() => {
|
|
@@ -2918,7 +2936,7 @@ ORDER BY lifetime_cost DESC`).all() ?? []) as {
|
|
|
2918
2936
|
style={{
|
|
2919
2937
|
fg:
|
|
2920
2938
|
index() === cursor()
|
|
2921
|
-
? api.theme.current.
|
|
2939
|
+
? api.theme.current.text
|
|
2922
2940
|
: api.theme.current.text,
|
|
2923
2941
|
}}
|
|
2924
2942
|
>
|
|
@@ -2929,7 +2947,7 @@ ORDER BY lifetime_cost DESC`).all() ?? []) as {
|
|
|
2929
2947
|
style={{
|
|
2930
2948
|
fg:
|
|
2931
2949
|
index() === cursor()
|
|
2932
|
-
? api.theme.current.
|
|
2950
|
+
? api.theme.current.text
|
|
2933
2951
|
: api.theme.current.warning,
|
|
2934
2952
|
}}
|
|
2935
2953
|
>
|
|
@@ -2940,7 +2958,7 @@ ORDER BY lifetime_cost DESC`).all() ?? []) as {
|
|
|
2940
2958
|
style={{
|
|
2941
2959
|
fg:
|
|
2942
2960
|
index() === cursor()
|
|
2943
|
-
? api.theme.current.
|
|
2961
|
+
? api.theme.current.text
|
|
2944
2962
|
: api.theme.current.textMuted,
|
|
2945
2963
|
}}
|
|
2946
2964
|
>
|