@ogpoyraz/wtx 0.8.6 → 0.8.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/dist/cli.mjs +790 -267
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -25437,6 +25437,13 @@ function wrapText(text, width) {
|
|
|
25437
25437
|
function isTapWithoutDrag(down, up) {
|
|
25438
25438
|
return Math.abs(up.x - down.x) <= 1 && Math.abs(up.y - down.y) <= 1;
|
|
25439
25439
|
}
|
|
25440
|
+
function clampSplitRatio(totalWidth, ratio, dividerWidth = DIVIDER_WIDTH) {
|
|
25441
|
+
if (totalWidth <= MIN_PANE_COLS * 2 + dividerWidth)
|
|
25442
|
+
return 0.5;
|
|
25443
|
+
const minRatio = MIN_PANE_COLS / totalWidth;
|
|
25444
|
+
const maxRatio = (totalWidth - MIN_PANE_COLS - dividerWidth) / totalWidth;
|
|
25445
|
+
return Math.max(minRatio, Math.min(maxRatio, ratio));
|
|
25446
|
+
}
|
|
25440
25447
|
function mergeBlocks(prev, next, scope) {
|
|
25441
25448
|
if (!scope)
|
|
25442
25449
|
return sortBlocks(next);
|
|
@@ -25492,6 +25499,7 @@ function withCreatePlaceholders(blocks, creating) {
|
|
|
25492
25499
|
return { ...block, rows: sortRowsHierarchically([...block.rows, ...placeholders]) };
|
|
25493
25500
|
});
|
|
25494
25501
|
}
|
|
25502
|
+
var MIN_PANE_COLS = 20, DIVIDER_WIDTH = 3;
|
|
25495
25503
|
var init_utils = __esm(() => {
|
|
25496
25504
|
init_stack();
|
|
25497
25505
|
});
|
|
@@ -25553,10 +25561,11 @@ function useWorktrees(opts) {
|
|
|
25553
25561
|
}
|
|
25554
25562
|
}
|
|
25555
25563
|
}, [opts]);
|
|
25564
|
+
const clearWarnings = useCallback(() => setWarnings([]), []);
|
|
25556
25565
|
useEffect(() => {
|
|
25557
25566
|
refresh();
|
|
25558
25567
|
}, [refresh]);
|
|
25559
|
-
return { blocks, loading, refreshing, error: error52, warnings, lastRefreshed, pendingRepos, refresh };
|
|
25568
|
+
return { blocks, loading, refreshing, error: error52, warnings, lastRefreshed, pendingRepos, refresh, clearWarnings };
|
|
25560
25569
|
}
|
|
25561
25570
|
var init_useWorktrees = __esm(() => {
|
|
25562
25571
|
init_data();
|
|
@@ -25600,14 +25609,19 @@ import { useRef as useRef2, useCallback as useCallback2 } from "react";
|
|
|
25600
25609
|
function useTapHandler(onTap) {
|
|
25601
25610
|
const down = useRef2(null);
|
|
25602
25611
|
const onMouseDown = useCallback2((e) => {
|
|
25612
|
+
if (e.button !== 0)
|
|
25613
|
+
return;
|
|
25603
25614
|
down.current = { x: e.x, y: e.y };
|
|
25604
25615
|
}, []);
|
|
25605
25616
|
const onMouseUp = useCallback2((e) => {
|
|
25606
25617
|
const start = down.current;
|
|
25607
25618
|
down.current = null;
|
|
25619
|
+
if (e.button !== 0)
|
|
25620
|
+
return;
|
|
25608
25621
|
if (!start || !isTapWithoutDrag(start, e))
|
|
25609
25622
|
return;
|
|
25610
|
-
|
|
25623
|
+
e.stopPropagation();
|
|
25624
|
+
onTap(e);
|
|
25611
25625
|
}, [onTap]);
|
|
25612
25626
|
return { onMouseDown, onMouseUp };
|
|
25613
25627
|
}
|
|
@@ -25679,7 +25693,7 @@ async function openInBrowser(url2) {
|
|
|
25679
25693
|
|
|
25680
25694
|
// src/tui/components/WorktreeTable.tsx
|
|
25681
25695
|
import { useEffect as useEffect2, useRef as useRef3 } from "react";
|
|
25682
|
-
import { jsx, jsxs
|
|
25696
|
+
import { jsx, jsxs } from "@opentui/react/jsx-runtime";
|
|
25683
25697
|
function statusBadge(row) {
|
|
25684
25698
|
if (row.isMainCheckout)
|
|
25685
25699
|
return { text: "[main]", fg: tokens.accent };
|
|
@@ -25693,11 +25707,27 @@ function statusBadge(row) {
|
|
|
25693
25707
|
return { text: `dirty (${row.dirtyFiles.length})`, fg: tokens.warning };
|
|
25694
25708
|
return { text: "clean", fg: tokens.dim };
|
|
25695
25709
|
}
|
|
25696
|
-
function WorktreeItem({
|
|
25710
|
+
function WorktreeItem({
|
|
25711
|
+
row,
|
|
25712
|
+
isSelected,
|
|
25713
|
+
isMultiSelected,
|
|
25714
|
+
indicator,
|
|
25715
|
+
frame,
|
|
25716
|
+
id,
|
|
25717
|
+
onRowClick,
|
|
25718
|
+
onToggleSelect
|
|
25719
|
+
}) {
|
|
25697
25720
|
const prTap = useTapHandler(() => {
|
|
25698
25721
|
if (row.prUrl)
|
|
25699
25722
|
openInBrowser(row.prUrl);
|
|
25700
25723
|
});
|
|
25724
|
+
const rowTap = useTapHandler(() => {
|
|
25725
|
+
onRowClick?.();
|
|
25726
|
+
});
|
|
25727
|
+
const gutterTap = useTapHandler((e) => {
|
|
25728
|
+
e.stopPropagation();
|
|
25729
|
+
onToggleSelect?.();
|
|
25730
|
+
});
|
|
25701
25731
|
const badge = indicator ? indicator.running ? { text: `${frame} ${indicator.verb}…`, fg: tokens.accent } : { text: `◌ ${indicator.verb}`, fg: tokens.dim } : row.isPendingCreate ? { text: `${frame} creating…`, fg: tokens.accent } : statusBadge(row);
|
|
25702
25732
|
const disabled = indicator !== undefined || row.isPendingCreate === true;
|
|
25703
25733
|
const primary = isSelected ? tokens.bright : disabled ? tokens.dim : tokens.fg;
|
|
@@ -25714,98 +25744,136 @@ function WorktreeItem({ row, isSelected, isMultiSelected, indicator, frame, id }
|
|
|
25714
25744
|
ownerSegment,
|
|
25715
25745
|
baseSegment
|
|
25716
25746
|
].filter(Boolean).join(" ").trimEnd();
|
|
25747
|
+
const isClickable = !row.isPendingCreate && !indicator;
|
|
25717
25748
|
return /* @__PURE__ */ jsxs("box", {
|
|
25718
25749
|
id,
|
|
25719
25750
|
flexDirection: "column",
|
|
25720
25751
|
backgroundColor: isSelected ? tokens.selectionBg : undefined,
|
|
25721
25752
|
style: { paddingRight: 1 },
|
|
25753
|
+
...isClickable && onRowClick ? rowTap : {},
|
|
25722
25754
|
children: [
|
|
25723
|
-
/* @__PURE__ */ jsxs("
|
|
25755
|
+
/* @__PURE__ */ jsxs("box", {
|
|
25756
|
+
flexDirection: "row",
|
|
25724
25757
|
children: [
|
|
25725
|
-
/* @__PURE__ */ jsx("
|
|
25726
|
-
|
|
25727
|
-
|
|
25728
|
-
|
|
25729
|
-
|
|
25730
|
-
fg: tokens.accent,
|
|
25731
|
-
children: isMultiSelected ? "✓ " : " "
|
|
25732
|
-
}),
|
|
25733
|
-
/* @__PURE__ */ jsx("span", {
|
|
25734
|
-
fg: tokens.dim,
|
|
25735
|
-
children: hierarchyPrefix
|
|
25736
|
-
}),
|
|
25737
|
-
/* @__PURE__ */ jsx("span", {
|
|
25738
|
-
fg: primary,
|
|
25739
|
-
children: truncateBranch(row.branch)
|
|
25758
|
+
/* @__PURE__ */ jsx("text", {
|
|
25759
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
25760
|
+
fg: primary,
|
|
25761
|
+
children: isSelected ? "▸ " : " "
|
|
25762
|
+
})
|
|
25740
25763
|
}),
|
|
25741
|
-
/* @__PURE__ */ jsx("
|
|
25742
|
-
|
|
25743
|
-
|
|
25744
|
-
|
|
25745
|
-
|
|
25746
|
-
|
|
25747
|
-
|
|
25748
|
-
...row.prUrl ? prTap : {},
|
|
25749
|
-
children: [
|
|
25750
|
-
/* @__PURE__ */ jsx("span", {
|
|
25751
|
-
fg: tokens.dim,
|
|
25752
|
-
children: secondary
|
|
25764
|
+
/* @__PURE__ */ jsx("box", {
|
|
25765
|
+
width: 2,
|
|
25766
|
+
...onToggleSelect ? gutterTap : {},
|
|
25767
|
+
children: /* @__PURE__ */ jsx("text", {
|
|
25768
|
+
fg: tokens.accent,
|
|
25769
|
+
children: isMultiSelected ? "✓ " : " "
|
|
25770
|
+
})
|
|
25753
25771
|
}),
|
|
25754
|
-
|
|
25772
|
+
/* @__PURE__ */ jsxs("text", {
|
|
25755
25773
|
children: [
|
|
25756
25774
|
/* @__PURE__ */ jsx("span", {
|
|
25757
25775
|
fg: tokens.dim,
|
|
25758
|
-
children:
|
|
25776
|
+
children: hierarchyPrefix
|
|
25759
25777
|
}),
|
|
25760
25778
|
/* @__PURE__ */ jsx("span", {
|
|
25761
|
-
fg:
|
|
25762
|
-
children:
|
|
25763
|
-
}),
|
|
25764
|
-
row.prState && /* @__PURE__ */ jsx("span", {
|
|
25765
|
-
fg: tokens.dim,
|
|
25766
|
-
children: ` ${row.prState}`
|
|
25779
|
+
fg: primary,
|
|
25780
|
+
children: truncateBranch(row.branch)
|
|
25767
25781
|
}),
|
|
25768
|
-
|
|
25782
|
+
/* @__PURE__ */ jsx("span", {
|
|
25783
|
+
fg: badge.fg,
|
|
25784
|
+
children: ` ${badge.text}`
|
|
25785
|
+
})
|
|
25786
|
+
]
|
|
25787
|
+
})
|
|
25788
|
+
]
|
|
25789
|
+
}),
|
|
25790
|
+
/* @__PURE__ */ jsxs("box", {
|
|
25791
|
+
flexDirection: "row",
|
|
25792
|
+
children: [
|
|
25793
|
+
/* @__PURE__ */ jsxs("text", {
|
|
25794
|
+
children: [
|
|
25795
|
+
/* @__PURE__ */ jsx("span", {
|
|
25769
25796
|
fg: tokens.dim,
|
|
25770
|
-
children:
|
|
25797
|
+
children: secondary
|
|
25771
25798
|
}),
|
|
25772
|
-
row.
|
|
25799
|
+
row.prNumber !== null && secondary ? /* @__PURE__ */ jsx("span", {
|
|
25773
25800
|
fg: tokens.dim,
|
|
25774
|
-
children: "
|
|
25775
|
-
})
|
|
25801
|
+
children: " · "
|
|
25802
|
+
}) : null
|
|
25776
25803
|
]
|
|
25777
25804
|
}),
|
|
25778
|
-
|
|
25779
|
-
|
|
25780
|
-
children:
|
|
25805
|
+
row.prNumber !== null && /* @__PURE__ */ jsx("box", {
|
|
25806
|
+
...row.prUrl ? prTap : {},
|
|
25807
|
+
children: /* @__PURE__ */ jsxs("text", {
|
|
25808
|
+
children: [
|
|
25809
|
+
/* @__PURE__ */ jsx("span", {
|
|
25810
|
+
fg: tokens.accent,
|
|
25811
|
+
children: `#${row.prNumber}`
|
|
25812
|
+
}),
|
|
25813
|
+
row.prState && /* @__PURE__ */ jsx("span", {
|
|
25814
|
+
fg: tokens.dim,
|
|
25815
|
+
children: ` ${row.prState}`
|
|
25816
|
+
}),
|
|
25817
|
+
row.prChecks && /* @__PURE__ */ jsx("span", {
|
|
25818
|
+
fg: tokens.dim,
|
|
25819
|
+
children: ` (${row.prChecks})`
|
|
25820
|
+
}),
|
|
25821
|
+
row.prUrl && /* @__PURE__ */ jsx("span", {
|
|
25822
|
+
fg: tokens.dim,
|
|
25823
|
+
children: " ↗"
|
|
25824
|
+
})
|
|
25825
|
+
]
|
|
25826
|
+
})
|
|
25781
25827
|
}),
|
|
25782
|
-
|
|
25783
|
-
|
|
25784
|
-
|
|
25828
|
+
/* @__PURE__ */ jsxs("text", {
|
|
25829
|
+
children: [
|
|
25830
|
+
baseChangedSegment && /* @__PURE__ */ jsx("span", {
|
|
25831
|
+
fg: tokens.warning,
|
|
25832
|
+
children: baseChangedSegment
|
|
25833
|
+
}),
|
|
25834
|
+
rebaseSegment && /* @__PURE__ */ jsx("span", {
|
|
25835
|
+
fg: tokens.error,
|
|
25836
|
+
children: rebaseSegment
|
|
25837
|
+
})
|
|
25838
|
+
]
|
|
25785
25839
|
})
|
|
25786
25840
|
]
|
|
25787
25841
|
})
|
|
25788
25842
|
]
|
|
25789
25843
|
});
|
|
25790
25844
|
}
|
|
25791
|
-
function WorktreeTable({ blocks, selectedIndex, selection = new Set, frame, repoVerbs, rowVerbs }) {
|
|
25845
|
+
function WorktreeTable({ blocks, selectedIndex, selection = new Set, frame, repoVerbs, rowVerbs, onRowClick, onToggleSelect }) {
|
|
25792
25846
|
const scrollRef = useRef3(null);
|
|
25793
25847
|
useEffect2(() => {
|
|
25794
25848
|
if (scrollRef.current?.scrollChildIntoView) {
|
|
25795
25849
|
scrollRef.current.scrollChildIntoView("selected-row");
|
|
25796
25850
|
}
|
|
25797
25851
|
}, [selectedIndex]);
|
|
25798
|
-
|
|
25852
|
+
const flatIndexMap = new Map;
|
|
25853
|
+
let idx = 0;
|
|
25854
|
+
for (const b of blocks) {
|
|
25855
|
+
for (const r of b.rows) {
|
|
25856
|
+
if (!r.isPendingCreate)
|
|
25857
|
+
flatIndexMap.set(r.path, idx++);
|
|
25858
|
+
}
|
|
25859
|
+
}
|
|
25860
|
+
let headerSeen = 0;
|
|
25799
25861
|
return /* @__PURE__ */ jsx("scrollbox", {
|
|
25800
25862
|
ref: scrollRef,
|
|
25801
25863
|
id: "worktree-table",
|
|
25802
|
-
flexGrow:
|
|
25864
|
+
flexGrow: 1,
|
|
25865
|
+
width: "100%",
|
|
25803
25866
|
height: "100%",
|
|
25804
25867
|
border: true,
|
|
25805
25868
|
borderColor: tokens.border,
|
|
25869
|
+
focusedBorderColor: tokens.border,
|
|
25870
|
+
focusable: false,
|
|
25806
25871
|
title: "Worktrees",
|
|
25807
25872
|
paddingX: 1,
|
|
25808
25873
|
focused: false,
|
|
25874
|
+
onMouseScroll: (e) => {
|
|
25875
|
+
e.stopPropagation();
|
|
25876
|
+
},
|
|
25809
25877
|
children: blocks.length === 0 ? /* @__PURE__ */ jsx("text", {
|
|
25810
25878
|
fg: tokens.dim,
|
|
25811
25879
|
children: "No repositories configured."
|
|
@@ -25816,7 +25884,7 @@ function WorktreeTable({ blocks, selectedIndex, selection = new Set, frame, repo
|
|
|
25816
25884
|
style: { marginBottom: 1 },
|
|
25817
25885
|
children: [
|
|
25818
25886
|
/* @__PURE__ */ jsx("box", {
|
|
25819
|
-
style: { marginTop:
|
|
25887
|
+
style: { marginTop: headerSeen === 0 ? 0 : 1 },
|
|
25820
25888
|
children: /* @__PURE__ */ jsxs("text", {
|
|
25821
25889
|
children: [
|
|
25822
25890
|
/* @__PURE__ */ jsx("span", {
|
|
@@ -25837,18 +25905,23 @@ function WorktreeTable({ blocks, selectedIndex, selection = new Set, frame, repo
|
|
|
25837
25905
|
]
|
|
25838
25906
|
})
|
|
25839
25907
|
}),
|
|
25908
|
+
(() => {
|
|
25909
|
+
headerSeen++;
|
|
25910
|
+
return null;
|
|
25911
|
+
})(),
|
|
25840
25912
|
block.rows.map((row) => {
|
|
25841
25913
|
const navigable = !row.isPendingCreate;
|
|
25842
|
-
const
|
|
25843
|
-
|
|
25844
|
-
flatIndex++;
|
|
25914
|
+
const flatIdx = flatIndexMap.get(row.path);
|
|
25915
|
+
const isSelected = navigable && flatIdx === selectedIndex;
|
|
25845
25916
|
return /* @__PURE__ */ jsx(WorktreeItem, {
|
|
25846
25917
|
row,
|
|
25847
25918
|
isSelected,
|
|
25848
25919
|
isMultiSelected: selection.has(row.path),
|
|
25849
25920
|
indicator: rowVerbs.get(row.path),
|
|
25850
25921
|
frame,
|
|
25851
|
-
id: isSelected ? "selected-row" : undefined
|
|
25922
|
+
id: isSelected ? "selected-row" : undefined,
|
|
25923
|
+
onRowClick: navigable && flatIdx !== undefined && onRowClick ? () => onRowClick(flatIdx) : undefined,
|
|
25924
|
+
onToggleSelect: onToggleSelect ? () => onToggleSelect(row.path) : undefined
|
|
25852
25925
|
}, row.path);
|
|
25853
25926
|
})
|
|
25854
25927
|
]
|
|
@@ -25863,7 +25936,7 @@ var init_WorktreeTable = __esm(() => {
|
|
|
25863
25936
|
});
|
|
25864
25937
|
|
|
25865
25938
|
// src/tui/components/DetailPane.tsx
|
|
25866
|
-
import { jsx as jsx2, jsxs as jsxs2, Fragment
|
|
25939
|
+
import { jsx as jsx2, jsxs as jsxs2, Fragment } from "@opentui/react/jsx-runtime";
|
|
25867
25940
|
function DetailPane({ selectedRow }) {
|
|
25868
25941
|
const prTap = useTapHandler(() => {
|
|
25869
25942
|
if (selectedRow?.prUrl)
|
|
@@ -25873,9 +25946,12 @@ function DetailPane({ selectedRow }) {
|
|
|
25873
25946
|
return /* @__PURE__ */ jsx2("box", {
|
|
25874
25947
|
id: "detail-pane",
|
|
25875
25948
|
flexGrow: 1,
|
|
25949
|
+
width: "100%",
|
|
25876
25950
|
height: "100%",
|
|
25877
25951
|
border: true,
|
|
25878
25952
|
borderColor: tokens.border,
|
|
25953
|
+
focusedBorderColor: tokens.border,
|
|
25954
|
+
focusable: false,
|
|
25879
25955
|
title: "Details",
|
|
25880
25956
|
padding: 1,
|
|
25881
25957
|
justifyContent: "center",
|
|
@@ -25911,9 +25987,12 @@ function DetailPane({ selectedRow }) {
|
|
|
25911
25987
|
return /* @__PURE__ */ jsxs2("scrollbox", {
|
|
25912
25988
|
id: "detail-pane",
|
|
25913
25989
|
flexGrow: 1,
|
|
25990
|
+
width: "100%",
|
|
25914
25991
|
height: "100%",
|
|
25915
25992
|
border: true,
|
|
25916
25993
|
borderColor: tokens.border,
|
|
25994
|
+
focusedBorderColor: tokens.border,
|
|
25995
|
+
focusable: false,
|
|
25917
25996
|
title: "Details",
|
|
25918
25997
|
padding: 1,
|
|
25919
25998
|
focused: false,
|
|
@@ -26083,7 +26162,7 @@ function DetailPane({ selectedRow }) {
|
|
|
26083
26162
|
})
|
|
26084
26163
|
]
|
|
26085
26164
|
}),
|
|
26086
|
-
prNumber !== null && /* @__PURE__ */ jsxs2(
|
|
26165
|
+
prNumber !== null && /* @__PURE__ */ jsxs2(Fragment, {
|
|
26087
26166
|
children: [
|
|
26088
26167
|
/* @__PURE__ */ jsxs2("text", {
|
|
26089
26168
|
style: { marginTop: 1 },
|
|
@@ -26179,7 +26258,7 @@ function DetailPane({ selectedRow }) {
|
|
|
26179
26258
|
fg: tokens.dim,
|
|
26180
26259
|
children: "Actions:"
|
|
26181
26260
|
}),
|
|
26182
|
-
!isMainCheckout && /* @__PURE__ */ jsxs2(
|
|
26261
|
+
!isMainCheckout && /* @__PURE__ */ jsxs2(Fragment, {
|
|
26183
26262
|
children: [
|
|
26184
26263
|
/* @__PURE__ */ jsxs2("text", {
|
|
26185
26264
|
fg: tokens.dim,
|
|
@@ -26215,8 +26294,44 @@ var init_DetailPane = __esm(() => {
|
|
|
26215
26294
|
|
|
26216
26295
|
// src/tui/components/Footer.tsx
|
|
26217
26296
|
import { jsx as jsx3, jsxs as jsxs3 } from "@opentui/react/jsx-runtime";
|
|
26218
|
-
function
|
|
26219
|
-
const
|
|
26297
|
+
function HintItem({ hintKey, label, isFirst, onClick }) {
|
|
26298
|
+
const tap = useTapHandler(() => onClick?.(hintKey));
|
|
26299
|
+
return /* @__PURE__ */ jsx3("box", {
|
|
26300
|
+
flexDirection: "row",
|
|
26301
|
+
...onClick ? tap : {},
|
|
26302
|
+
children: /* @__PURE__ */ jsxs3("text", {
|
|
26303
|
+
children: [
|
|
26304
|
+
/* @__PURE__ */ jsx3("span", {
|
|
26305
|
+
fg: tokens.dim,
|
|
26306
|
+
children: isFirst ? "" : " · "
|
|
26307
|
+
}),
|
|
26308
|
+
/* @__PURE__ */ jsx3("span", {
|
|
26309
|
+
fg: tokens.dim,
|
|
26310
|
+
children: `${hintKey} ${label}`
|
|
26311
|
+
})
|
|
26312
|
+
]
|
|
26313
|
+
})
|
|
26314
|
+
});
|
|
26315
|
+
}
|
|
26316
|
+
function ErrorBadge({ count: count2, onClick }) {
|
|
26317
|
+
const tap = useTapHandler(() => onClick?.());
|
|
26318
|
+
return /* @__PURE__ */ jsx3("box", {
|
|
26319
|
+
...onClick ? tap : {},
|
|
26320
|
+
children: /* @__PURE__ */ jsxs3("text", {
|
|
26321
|
+
children: [
|
|
26322
|
+
/* @__PURE__ */ jsx3("span", {
|
|
26323
|
+
fg: tokens.error,
|
|
26324
|
+
children: `${count2} error${count2 !== 1 ? "s" : ""}`
|
|
26325
|
+
}),
|
|
26326
|
+
/* @__PURE__ */ jsx3("span", {
|
|
26327
|
+
fg: tokens.dim,
|
|
26328
|
+
children: " · e view"
|
|
26329
|
+
})
|
|
26330
|
+
]
|
|
26331
|
+
})
|
|
26332
|
+
});
|
|
26333
|
+
}
|
|
26334
|
+
function Footer({ loading, lastRefreshed, errorCount, message, busyText, spinnerFrame, filter, onHintClick, onErrorClick }) {
|
|
26220
26335
|
const frame = spinnerFrame ?? "◌";
|
|
26221
26336
|
return /* @__PURE__ */ jsxs3("box", {
|
|
26222
26337
|
id: "footer",
|
|
@@ -26232,13 +26347,20 @@ function Footer({ loading, lastRefreshed, errorCount, message, busyText, spinner
|
|
|
26232
26347
|
busyText ? /* @__PURE__ */ jsx3("text", {
|
|
26233
26348
|
fg: tokens.accent,
|
|
26234
26349
|
children: `${frame} ${busyText}`
|
|
26235
|
-
}) : /* @__PURE__ */ jsx3("
|
|
26236
|
-
|
|
26237
|
-
|
|
26350
|
+
}) : /* @__PURE__ */ jsx3("box", {
|
|
26351
|
+
flexDirection: "row",
|
|
26352
|
+
gap: 1,
|
|
26353
|
+
children: HINTS.map(([key, label], idx) => /* @__PURE__ */ jsx3(HintItem, {
|
|
26354
|
+
hintKey: key,
|
|
26355
|
+
label,
|
|
26356
|
+
isFirst: idx === 0,
|
|
26357
|
+
onClick: onHintClick
|
|
26358
|
+
}, key))
|
|
26238
26359
|
}),
|
|
26239
26360
|
/* @__PURE__ */ jsxs3("box", {
|
|
26240
26361
|
flexDirection: "row",
|
|
26241
26362
|
gap: 2,
|
|
26363
|
+
alignItems: "center",
|
|
26242
26364
|
children: [
|
|
26243
26365
|
message ? /* @__PURE__ */ jsx3("text", {
|
|
26244
26366
|
fg: tokens.warning,
|
|
@@ -26256,18 +26378,16 @@ function Footer({ loading, lastRefreshed, errorCount, message, busyText, spinner
|
|
|
26256
26378
|
")"
|
|
26257
26379
|
]
|
|
26258
26380
|
}) : null,
|
|
26259
|
-
errorCount > 0 ? /* @__PURE__ */
|
|
26260
|
-
|
|
26261
|
-
|
|
26262
|
-
fg: tokens.error,
|
|
26263
|
-
children: `${errorCount} error${errorCount !== 1 ? "s" : ""}`
|
|
26264
|
-
}),
|
|
26265
|
-
/* @__PURE__ */ jsx3("span", {
|
|
26266
|
-
fg: tokens.dim,
|
|
26267
|
-
children: " · e view"
|
|
26268
|
-
})
|
|
26269
|
-
]
|
|
26381
|
+
errorCount > 0 ? /* @__PURE__ */ jsx3(ErrorBadge, {
|
|
26382
|
+
count: errorCount,
|
|
26383
|
+
onClick: onErrorClick
|
|
26270
26384
|
}) : null,
|
|
26385
|
+
/* @__PURE__ */ jsx3(HintItem, {
|
|
26386
|
+
hintKey: "?",
|
|
26387
|
+
label: "help",
|
|
26388
|
+
isFirst: errorCount === 0,
|
|
26389
|
+
onClick: onHintClick
|
|
26390
|
+
}),
|
|
26271
26391
|
/* @__PURE__ */ jsx3("text", {
|
|
26272
26392
|
fg: tokens.dim,
|
|
26273
26393
|
children: loading ? `${frame} Refreshing…` : `Updated ${lastRefreshed}`
|
|
@@ -26280,27 +26400,83 @@ function Footer({ loading, lastRefreshed, errorCount, message, busyText, spinner
|
|
|
26280
26400
|
var HINTS;
|
|
26281
26401
|
var init_Footer = __esm(() => {
|
|
26282
26402
|
init_theme();
|
|
26403
|
+
init_use_tap();
|
|
26283
26404
|
HINTS = [
|
|
26284
|
-
["c", "config"],
|
|
26285
26405
|
["n", "create"],
|
|
26286
|
-
["
|
|
26287
|
-
["?", "help"],
|
|
26288
|
-
["H", "history"],
|
|
26289
|
-
["o", "ide"],
|
|
26290
|
-
["i", "install"],
|
|
26291
|
-
["p", "pull"],
|
|
26292
|
-
["b", "rebase"],
|
|
26293
|
-
["r", "refresh"],
|
|
26294
|
-
["d", "remove"],
|
|
26295
|
-
["m", "rename"],
|
|
26296
|
-
["s", "sync"]
|
|
26406
|
+
["d", "remove"]
|
|
26297
26407
|
];
|
|
26298
26408
|
});
|
|
26299
26409
|
|
|
26300
|
-
// src/tui/components/
|
|
26410
|
+
// src/tui/components/Divider.tsx
|
|
26411
|
+
import { useState as useState2, useRef as useRef4, useCallback as useCallback3 } from "react";
|
|
26412
|
+
import { useRenderer } from "@opentui/react";
|
|
26301
26413
|
import { jsx as jsx4 } from "@opentui/react/jsx-runtime";
|
|
26302
|
-
function
|
|
26414
|
+
function Divider({ splitRatio, totalWidth, onChange, onDraggingChange }) {
|
|
26415
|
+
const renderer = useRenderer();
|
|
26416
|
+
const [hovered, setHovered] = useState2(false);
|
|
26417
|
+
const [dragging, setDragging] = useState2(false);
|
|
26418
|
+
const startXRef = useRef4(null);
|
|
26419
|
+
const startRatioRef = useRef4(splitRatio);
|
|
26420
|
+
const handleMouseDown = useCallback3((e) => {
|
|
26421
|
+
if (e.button !== 0)
|
|
26422
|
+
return;
|
|
26423
|
+
startXRef.current = e.x;
|
|
26424
|
+
startRatioRef.current = splitRatio;
|
|
26425
|
+
setDragging(true);
|
|
26426
|
+
onDraggingChange?.(true);
|
|
26427
|
+
renderer.clearSelection();
|
|
26428
|
+
e.stopPropagation();
|
|
26429
|
+
}, [splitRatio, onDraggingChange, renderer]);
|
|
26430
|
+
const handleMouseUp = useCallback3((e) => {
|
|
26431
|
+
if (e.button !== 0)
|
|
26432
|
+
return;
|
|
26433
|
+
startXRef.current = null;
|
|
26434
|
+
setDragging(false);
|
|
26435
|
+
onDraggingChange?.(false);
|
|
26436
|
+
e.stopPropagation();
|
|
26437
|
+
}, [onDraggingChange]);
|
|
26438
|
+
const handleMouseDrag = useCallback3((e) => {
|
|
26439
|
+
if (startXRef.current === null)
|
|
26440
|
+
return;
|
|
26441
|
+
renderer.clearSelection();
|
|
26442
|
+
const dx = e.x - startXRef.current;
|
|
26443
|
+
const next = clampSplitRatio(totalWidth, startRatioRef.current + dx / totalWidth);
|
|
26444
|
+
onChange(next);
|
|
26445
|
+
e.stopPropagation();
|
|
26446
|
+
}, [totalWidth, onChange, renderer]);
|
|
26447
|
+
const dragHandlers = {
|
|
26448
|
+
onMouseDown: handleMouseDown,
|
|
26449
|
+
onMouseUp: handleMouseUp,
|
|
26450
|
+
onMouseDrag: handleMouseDrag,
|
|
26451
|
+
onMouseMove: handleMouseDrag
|
|
26452
|
+
};
|
|
26303
26453
|
return /* @__PURE__ */ jsx4("box", {
|
|
26454
|
+
width: 3,
|
|
26455
|
+
height: "100%",
|
|
26456
|
+
backgroundColor: dragging ? tokens.selectionBg : hovered ? tokens.panelBg : undefined,
|
|
26457
|
+
...dragHandlers,
|
|
26458
|
+
onMouseOver: () => setHovered(true),
|
|
26459
|
+
onMouseOut: () => setHovered(false),
|
|
26460
|
+
alignItems: "center",
|
|
26461
|
+
justifyContent: "center",
|
|
26462
|
+
children: /* @__PURE__ */ jsx4("text", {
|
|
26463
|
+
fg: dragging ? tokens.accent : hovered ? tokens.borderActive : tokens.border,
|
|
26464
|
+
...dragHandlers,
|
|
26465
|
+
onMouseOver: () => setHovered(true),
|
|
26466
|
+
onMouseOut: () => setHovered(false),
|
|
26467
|
+
children: " │ "
|
|
26468
|
+
})
|
|
26469
|
+
});
|
|
26470
|
+
}
|
|
26471
|
+
var init_Divider = __esm(() => {
|
|
26472
|
+
init_theme();
|
|
26473
|
+
init_utils();
|
|
26474
|
+
});
|
|
26475
|
+
|
|
26476
|
+
// src/tui/components/Overlay.tsx
|
|
26477
|
+
import { jsx as jsx5 } from "@opentui/react/jsx-runtime";
|
|
26478
|
+
function Overlay({ title, borderColor = tokens.border, width = 64, children }) {
|
|
26479
|
+
return /* @__PURE__ */ jsx5("box", {
|
|
26304
26480
|
id: "overlay-scrim",
|
|
26305
26481
|
position: "absolute",
|
|
26306
26482
|
width: "100%",
|
|
@@ -26312,7 +26488,7 @@ function Overlay({ title, borderColor = tokens.border, width = 64, children }) {
|
|
|
26312
26488
|
flexDirection: "row",
|
|
26313
26489
|
justifyContent: "center",
|
|
26314
26490
|
alignItems: "center",
|
|
26315
|
-
children: /* @__PURE__ */
|
|
26491
|
+
children: /* @__PURE__ */ jsx5("box", {
|
|
26316
26492
|
id: "overlay-panel",
|
|
26317
26493
|
width,
|
|
26318
26494
|
border: true,
|
|
@@ -26332,34 +26508,46 @@ var init_Overlay = __esm(() => {
|
|
|
26332
26508
|
});
|
|
26333
26509
|
|
|
26334
26510
|
// src/tui/components/HelpOverlay.tsx
|
|
26335
|
-
import { jsx as
|
|
26511
|
+
import { jsx as jsx6, jsxs as jsxs4 } from "@opentui/react/jsx-runtime";
|
|
26336
26512
|
function HelpOverlay() {
|
|
26337
26513
|
return /* @__PURE__ */ jsxs4(Overlay, {
|
|
26338
26514
|
title: "Help",
|
|
26339
26515
|
borderColor: tokens.border,
|
|
26516
|
+
width: 84,
|
|
26340
26517
|
children: [
|
|
26341
|
-
/* @__PURE__ */
|
|
26518
|
+
/* @__PURE__ */ jsx6("box", {
|
|
26342
26519
|
flexDirection: "column",
|
|
26343
|
-
style: { maxHeight:
|
|
26344
|
-
children: /* @__PURE__ */
|
|
26520
|
+
style: { maxHeight: 36 },
|
|
26521
|
+
children: /* @__PURE__ */ jsx6("scrollbox", {
|
|
26345
26522
|
flexGrow: 1,
|
|
26346
|
-
children: HELP_ENTRIES.map(([key, desc]) => /* @__PURE__ */ jsxs4("
|
|
26523
|
+
children: HELP_ENTRIES.map(([key, desc]) => /* @__PURE__ */ jsxs4("box", {
|
|
26524
|
+
flexDirection: "row",
|
|
26525
|
+
gap: 1,
|
|
26347
26526
|
children: [
|
|
26348
|
-
/* @__PURE__ */
|
|
26349
|
-
|
|
26350
|
-
|
|
26527
|
+
/* @__PURE__ */ jsx6("box", {
|
|
26528
|
+
width: 18,
|
|
26529
|
+
flexShrink: 0,
|
|
26530
|
+
children: /* @__PURE__ */ jsx6("text", {
|
|
26531
|
+
fg: tokens.accent,
|
|
26532
|
+
children: key
|
|
26533
|
+
})
|
|
26351
26534
|
}),
|
|
26352
|
-
/* @__PURE__ */
|
|
26353
|
-
|
|
26535
|
+
/* @__PURE__ */ jsx6("text", {
|
|
26536
|
+
fg: tokens.dim,
|
|
26537
|
+
children: "-"
|
|
26354
26538
|
}),
|
|
26355
|
-
/* @__PURE__ */
|
|
26356
|
-
|
|
26539
|
+
/* @__PURE__ */ jsx6("box", {
|
|
26540
|
+
flexGrow: 1,
|
|
26541
|
+
children: /* @__PURE__ */ jsx6("text", {
|
|
26542
|
+
fg: tokens.fg,
|
|
26543
|
+
children: desc
|
|
26544
|
+
})
|
|
26357
26545
|
})
|
|
26358
26546
|
]
|
|
26359
26547
|
}, key))
|
|
26360
26548
|
})
|
|
26361
26549
|
}),
|
|
26362
|
-
/* @__PURE__ */
|
|
26550
|
+
/* @__PURE__ */ jsx6("text", {
|
|
26363
26551
|
style: { marginTop: 1, fg: tokens.dim },
|
|
26364
26552
|
children: "Press any key to close"
|
|
26365
26553
|
})
|
|
@@ -26398,9 +26586,11 @@ var init_HelpOverlay = __esm(() => {
|
|
|
26398
26586
|
});
|
|
26399
26587
|
|
|
26400
26588
|
// src/tui/components/ConfirmModal.tsx
|
|
26401
|
-
import { jsx as
|
|
26402
|
-
function ConfirmModal({ title, message }) {
|
|
26403
|
-
|
|
26589
|
+
import { jsx as jsx7, jsxs as jsxs5 } from "@opentui/react/jsx-runtime";
|
|
26590
|
+
function ConfirmModal({ title, message, onConfirm, onCancel }) {
|
|
26591
|
+
const yesTap = useTapHandler(() => onConfirm?.());
|
|
26592
|
+
const noTap = useTapHandler(() => onCancel?.());
|
|
26593
|
+
return /* @__PURE__ */ jsx7(Overlay, {
|
|
26404
26594
|
title,
|
|
26405
26595
|
borderColor: tokens.warning,
|
|
26406
26596
|
children: /* @__PURE__ */ jsxs5("box", {
|
|
@@ -26408,25 +26598,42 @@ function ConfirmModal({ title, message }) {
|
|
|
26408
26598
|
justifyContent: "center",
|
|
26409
26599
|
alignItems: "center",
|
|
26410
26600
|
children: [
|
|
26411
|
-
/* @__PURE__ */
|
|
26601
|
+
/* @__PURE__ */ jsx7("text", {
|
|
26412
26602
|
children: message
|
|
26413
26603
|
}),
|
|
26414
|
-
/* @__PURE__ */ jsxs5("
|
|
26604
|
+
/* @__PURE__ */ jsxs5("box", {
|
|
26605
|
+
flexDirection: "row",
|
|
26606
|
+
gap: 2,
|
|
26415
26607
|
style: { marginTop: 2 },
|
|
26416
26608
|
children: [
|
|
26417
|
-
/* @__PURE__ */
|
|
26418
|
-
|
|
26419
|
-
children: "
|
|
26420
|
-
|
|
26421
|
-
|
|
26422
|
-
|
|
26423
|
-
|
|
26424
|
-
|
|
26425
|
-
|
|
26426
|
-
|
|
26609
|
+
/* @__PURE__ */ jsx7("box", {
|
|
26610
|
+
...onConfirm ? yesTap : {},
|
|
26611
|
+
children: /* @__PURE__ */ jsxs5("text", {
|
|
26612
|
+
children: [
|
|
26613
|
+
/* @__PURE__ */ jsx7("span", {
|
|
26614
|
+
fg: tokens.dim,
|
|
26615
|
+
children: "[y] "
|
|
26616
|
+
}),
|
|
26617
|
+
/* @__PURE__ */ jsx7("span", {
|
|
26618
|
+
fg: tokens.success,
|
|
26619
|
+
children: "Yes"
|
|
26620
|
+
})
|
|
26621
|
+
]
|
|
26622
|
+
})
|
|
26427
26623
|
}),
|
|
26428
|
-
/* @__PURE__ */
|
|
26429
|
-
|
|
26624
|
+
/* @__PURE__ */ jsx7("box", {
|
|
26625
|
+
...onCancel ? noTap : {},
|
|
26626
|
+
children: /* @__PURE__ */ jsxs5("text", {
|
|
26627
|
+
children: [
|
|
26628
|
+
/* @__PURE__ */ jsx7("span", {
|
|
26629
|
+
fg: tokens.dim,
|
|
26630
|
+
children: "[n/esc] "
|
|
26631
|
+
}),
|
|
26632
|
+
/* @__PURE__ */ jsx7("span", {
|
|
26633
|
+
children: "Cancel"
|
|
26634
|
+
})
|
|
26635
|
+
]
|
|
26636
|
+
})
|
|
26430
26637
|
})
|
|
26431
26638
|
]
|
|
26432
26639
|
})
|
|
@@ -26437,6 +26644,7 @@ function ConfirmModal({ title, message }) {
|
|
|
26437
26644
|
var init_ConfirmModal = __esm(() => {
|
|
26438
26645
|
init_Overlay();
|
|
26439
26646
|
init_theme();
|
|
26647
|
+
init_use_tap();
|
|
26440
26648
|
});
|
|
26441
26649
|
|
|
26442
26650
|
// src/tui/actions.ts
|
|
@@ -26497,20 +26705,20 @@ async function runWtxAction(args, onLine) {
|
|
|
26497
26705
|
}
|
|
26498
26706
|
|
|
26499
26707
|
// src/tui/components/ActionLogModal.tsx
|
|
26500
|
-
import { jsx as
|
|
26708
|
+
import { jsx as jsx8, jsxs as jsxs6 } from "@opentui/react/jsx-runtime";
|
|
26501
26709
|
function ActionLogModal({ title, lines, done, exitCode, remaining }) {
|
|
26502
26710
|
return /* @__PURE__ */ jsxs6(Overlay, {
|
|
26503
26711
|
title,
|
|
26504
26712
|
borderColor: tokens.border,
|
|
26505
26713
|
children: [
|
|
26506
|
-
/* @__PURE__ */
|
|
26714
|
+
/* @__PURE__ */ jsx8("box", {
|
|
26507
26715
|
flexGrow: 1,
|
|
26508
26716
|
flexDirection: "column",
|
|
26509
26717
|
style: { minHeight: 10, maxHeight: 20 },
|
|
26510
|
-
children: /* @__PURE__ */
|
|
26718
|
+
children: /* @__PURE__ */ jsx8("scrollbox", {
|
|
26511
26719
|
flexGrow: 1,
|
|
26512
26720
|
stickyScroll: true,
|
|
26513
|
-
children: lines.map((line, i2) => /* @__PURE__ */
|
|
26721
|
+
children: lines.map((line, i2) => /* @__PURE__ */ jsx8("text", {
|
|
26514
26722
|
fg: line.type === "err" ? tokens.error : tokens.fg,
|
|
26515
26723
|
children: line.text
|
|
26516
26724
|
}, i2))
|
|
@@ -26521,11 +26729,11 @@ function ActionLogModal({ title, lines, done, exitCode, remaining }) {
|
|
|
26521
26729
|
flexDirection: "row",
|
|
26522
26730
|
justifyContent: "center",
|
|
26523
26731
|
children: [
|
|
26524
|
-
!done && /* @__PURE__ */
|
|
26732
|
+
!done && /* @__PURE__ */ jsx8("text", {
|
|
26525
26733
|
fg: tokens.warning,
|
|
26526
26734
|
children: "Running..."
|
|
26527
26735
|
}),
|
|
26528
|
-
done && exitCode === 0 && /* @__PURE__ */
|
|
26736
|
+
done && exitCode === 0 && /* @__PURE__ */ jsx8("text", {
|
|
26529
26737
|
fg: tokens.success,
|
|
26530
26738
|
children: "✓ Done (exit 0)"
|
|
26531
26739
|
}),
|
|
@@ -26538,11 +26746,11 @@ function ActionLogModal({ title, lines, done, exitCode, remaining }) {
|
|
|
26538
26746
|
exitCode
|
|
26539
26747
|
]
|
|
26540
26748
|
}),
|
|
26541
|
-
remaining !== undefined && remaining > 0 && /* @__PURE__ */
|
|
26749
|
+
remaining !== undefined && remaining > 0 && /* @__PURE__ */ jsx8("span", {
|
|
26542
26750
|
fg: tokens.warning,
|
|
26543
26751
|
children: ` · ${remaining} more failure${remaining > 1 ? "s" : ""}`
|
|
26544
26752
|
}),
|
|
26545
|
-
/* @__PURE__ */
|
|
26753
|
+
/* @__PURE__ */ jsx8("span", {
|
|
26546
26754
|
fg: tokens.dim,
|
|
26547
26755
|
children: " - press any key to close"
|
|
26548
26756
|
})
|
|
@@ -26629,8 +26837,8 @@ var init_history = __esm(() => {
|
|
|
26629
26837
|
});
|
|
26630
26838
|
|
|
26631
26839
|
// src/tui/components/HistoryOverlay.tsx
|
|
26632
|
-
import { useEffect as useEffect3, useState as
|
|
26633
|
-
import { jsx as
|
|
26840
|
+
import { useEffect as useEffect3, useState as useState3 } from "react";
|
|
26841
|
+
import { jsx as jsx9, jsxs as jsxs7 } from "@opentui/react/jsx-runtime";
|
|
26634
26842
|
function formatShortTime(iso) {
|
|
26635
26843
|
const d = new Date(iso);
|
|
26636
26844
|
if (Number.isNaN(d.getTime()))
|
|
@@ -26652,7 +26860,7 @@ function HistoryEntryLine({ entry }) {
|
|
|
26652
26860
|
prefix
|
|
26653
26861
|
]
|
|
26654
26862
|
}),
|
|
26655
|
-
duration3 && /* @__PURE__ */
|
|
26863
|
+
duration3 && /* @__PURE__ */ jsx9("span", {
|
|
26656
26864
|
fg: tokens.dim,
|
|
26657
26865
|
children: duration3
|
|
26658
26866
|
})
|
|
@@ -26669,7 +26877,7 @@ function HistoryEntryLine({ entry }) {
|
|
|
26669
26877
|
prefix
|
|
26670
26878
|
]
|
|
26671
26879
|
}),
|
|
26672
|
-
duration3 && /* @__PURE__ */
|
|
26880
|
+
duration3 && /* @__PURE__ */ jsx9("span", {
|
|
26673
26881
|
fg: tokens.dim,
|
|
26674
26882
|
children: duration3
|
|
26675
26883
|
})
|
|
@@ -26678,11 +26886,11 @@ function HistoryEntryLine({ entry }) {
|
|
|
26678
26886
|
}
|
|
26679
26887
|
return /* @__PURE__ */ jsxs7("text", {
|
|
26680
26888
|
children: [
|
|
26681
|
-
/* @__PURE__ */
|
|
26889
|
+
/* @__PURE__ */ jsx9("span", {
|
|
26682
26890
|
fg: tokens.error,
|
|
26683
26891
|
children: "✗ "
|
|
26684
26892
|
}),
|
|
26685
|
-
/* @__PURE__ */
|
|
26893
|
+
/* @__PURE__ */ jsx9("span", {
|
|
26686
26894
|
children: prefix
|
|
26687
26895
|
}),
|
|
26688
26896
|
/* @__PURE__ */ jsxs7("span", {
|
|
@@ -26698,7 +26906,7 @@ function HistoryEntryLine({ entry }) {
|
|
|
26698
26906
|
});
|
|
26699
26907
|
}
|
|
26700
26908
|
function HistoryOverlay() {
|
|
26701
|
-
const [entries, setEntries] =
|
|
26909
|
+
const [entries, setEntries] = useState3([]);
|
|
26702
26910
|
useEffect3(() => {
|
|
26703
26911
|
setEntries(readRecentHistory(500));
|
|
26704
26912
|
}, []);
|
|
@@ -26707,23 +26915,23 @@ function HistoryOverlay() {
|
|
|
26707
26915
|
borderColor: tokens.border,
|
|
26708
26916
|
width: 110,
|
|
26709
26917
|
children: [
|
|
26710
|
-
/* @__PURE__ */
|
|
26918
|
+
/* @__PURE__ */ jsx9("box", {
|
|
26711
26919
|
flexGrow: 1,
|
|
26712
26920
|
flexDirection: "column",
|
|
26713
26921
|
style: { minHeight: 30, maxHeight: 46 },
|
|
26714
|
-
children: entries.length === 0 ? /* @__PURE__ */
|
|
26922
|
+
children: entries.length === 0 ? /* @__PURE__ */ jsx9("text", {
|
|
26715
26923
|
fg: tokens.dim,
|
|
26716
26924
|
children: "No actions recorded yet."
|
|
26717
|
-
}) : /* @__PURE__ */
|
|
26925
|
+
}) : /* @__PURE__ */ jsx9("scrollbox", {
|
|
26718
26926
|
flexGrow: 1,
|
|
26719
|
-
children: entries.map((entry, i2) => /* @__PURE__ */
|
|
26927
|
+
children: entries.map((entry, i2) => /* @__PURE__ */ jsx9(HistoryEntryLine, {
|
|
26720
26928
|
entry
|
|
26721
26929
|
}, i2))
|
|
26722
26930
|
})
|
|
26723
26931
|
}),
|
|
26724
|
-
/* @__PURE__ */
|
|
26932
|
+
/* @__PURE__ */ jsx9("box", {
|
|
26725
26933
|
marginTop: 1,
|
|
26726
|
-
children: /* @__PURE__ */
|
|
26934
|
+
children: /* @__PURE__ */ jsx9("text", {
|
|
26727
26935
|
fg: tokens.dim,
|
|
26728
26936
|
children: "Press any key to close · newest first"
|
|
26729
26937
|
})
|
|
@@ -26738,28 +26946,28 @@ var init_HistoryOverlay = __esm(() => {
|
|
|
26738
26946
|
});
|
|
26739
26947
|
|
|
26740
26948
|
// src/tui/components/InputModal.tsx
|
|
26741
|
-
import { useState as
|
|
26742
|
-
import { jsx as
|
|
26949
|
+
import { useState as useState4 } from "react";
|
|
26950
|
+
import { jsx as jsx10, jsxs as jsxs8 } from "@opentui/react/jsx-runtime";
|
|
26743
26951
|
function InputModal({ title, placeholder, initialValue, errorMessage: errorMessage2, onSubmit }) {
|
|
26744
|
-
const [value, setValue] =
|
|
26745
|
-
return /* @__PURE__ */
|
|
26952
|
+
const [value, setValue] = useState4(initialValue ?? "");
|
|
26953
|
+
return /* @__PURE__ */ jsx10(Overlay, {
|
|
26746
26954
|
title,
|
|
26747
26955
|
borderColor: tokens.accent,
|
|
26748
26956
|
children: /* @__PURE__ */ jsxs8("box", {
|
|
26749
26957
|
flexDirection: "column",
|
|
26750
26958
|
children: [
|
|
26751
|
-
/* @__PURE__ */
|
|
26959
|
+
/* @__PURE__ */ jsx10("input", {
|
|
26752
26960
|
focused: true,
|
|
26753
26961
|
value: initialValue ?? "",
|
|
26754
26962
|
placeholder,
|
|
26755
26963
|
onInput: (val) => setValue(val),
|
|
26756
26964
|
onSubmit: () => onSubmit(value)
|
|
26757
26965
|
}),
|
|
26758
|
-
errorMessage2 ? /* @__PURE__ */
|
|
26966
|
+
errorMessage2 ? /* @__PURE__ */ jsx10("text", {
|
|
26759
26967
|
fg: tokens.error,
|
|
26760
26968
|
style: { marginTop: 1 },
|
|
26761
26969
|
children: errorMessage2
|
|
26762
|
-
}) : /* @__PURE__ */
|
|
26970
|
+
}) : /* @__PURE__ */ jsx10("text", {
|
|
26763
26971
|
fg: tokens.dim,
|
|
26764
26972
|
style: { marginTop: 1 },
|
|
26765
26973
|
children: "Press Enter to submit, empty to cancel"
|
|
@@ -26774,11 +26982,31 @@ var init_InputModal = __esm(() => {
|
|
|
26774
26982
|
});
|
|
26775
26983
|
|
|
26776
26984
|
// src/tui/components/ChoiceModal.tsx
|
|
26777
|
-
import { useState as
|
|
26985
|
+
import { useState as useState5 } from "react";
|
|
26778
26986
|
import { useKeyboard } from "@opentui/react";
|
|
26779
|
-
import { jsx as
|
|
26987
|
+
import { jsx as jsx11, jsxs as jsxs9 } from "@opentui/react/jsx-runtime";
|
|
26988
|
+
function ChoiceOptionRow({ option, index, isSelected, onSelect }) {
|
|
26989
|
+
const tap = useTapHandler(() => onSelect(option.value));
|
|
26990
|
+
return /* @__PURE__ */ jsxs9("box", {
|
|
26991
|
+
flexDirection: "column",
|
|
26992
|
+
backgroundColor: isSelected ? tokens.selectionBg : undefined,
|
|
26993
|
+
...tap,
|
|
26994
|
+
children: [
|
|
26995
|
+
/* @__PURE__ */ jsx11("text", {
|
|
26996
|
+
children: /* @__PURE__ */ jsx11("span", {
|
|
26997
|
+
fg: isSelected ? tokens.bright : tokens.fg,
|
|
26998
|
+
children: `${index + 1}. ${option.label}`
|
|
26999
|
+
})
|
|
27000
|
+
}),
|
|
27001
|
+
option.desc && /* @__PURE__ */ jsx11("text", {
|
|
27002
|
+
fg: tokens.dim,
|
|
27003
|
+
children: ` ${option.desc}`
|
|
27004
|
+
})
|
|
27005
|
+
]
|
|
27006
|
+
});
|
|
27007
|
+
}
|
|
26780
27008
|
function ChoiceModal({ title, options, initialIndex = 0, onSubmit, onCancel }) {
|
|
26781
|
-
const [index, setIndex] =
|
|
27009
|
+
const [index, setIndex] = useState5(Math.min(Math.max(initialIndex, 0), options.length - 1));
|
|
26782
27010
|
useKeyboard((key) => {
|
|
26783
27011
|
if (key.name === "escape") {
|
|
26784
27012
|
onCancel();
|
|
@@ -26805,27 +27033,17 @@ function ChoiceModal({ title, options, initialIndex = 0, onSubmit, onCancel }) {
|
|
|
26805
27033
|
onSubmit(option.value);
|
|
26806
27034
|
}
|
|
26807
27035
|
});
|
|
26808
|
-
return /* @__PURE__ */
|
|
27036
|
+
return /* @__PURE__ */ jsx11(Overlay, {
|
|
26809
27037
|
title,
|
|
26810
27038
|
borderColor: tokens.accent,
|
|
26811
27039
|
children: /* @__PURE__ */ jsxs9("box", {
|
|
26812
27040
|
flexDirection: "column",
|
|
26813
27041
|
children: [
|
|
26814
|
-
options.map((option, i2) => /* @__PURE__ */
|
|
26815
|
-
|
|
26816
|
-
|
|
26817
|
-
|
|
26818
|
-
|
|
26819
|
-
children: /* @__PURE__ */ jsx10("span", {
|
|
26820
|
-
fg: i2 === index ? tokens.bright : tokens.fg,
|
|
26821
|
-
children: `${i2 + 1}. ${option.label}`
|
|
26822
|
-
})
|
|
26823
|
-
}),
|
|
26824
|
-
option.desc && /* @__PURE__ */ jsx10("text", {
|
|
26825
|
-
fg: tokens.dim,
|
|
26826
|
-
children: ` ${option.desc}`
|
|
26827
|
-
})
|
|
26828
|
-
]
|
|
27042
|
+
options.map((option, i2) => /* @__PURE__ */ jsx11(ChoiceOptionRow, {
|
|
27043
|
+
option,
|
|
27044
|
+
index: i2,
|
|
27045
|
+
isSelected: i2 === index,
|
|
27046
|
+
onSelect: onSubmit
|
|
26829
27047
|
}, option.value)),
|
|
26830
27048
|
/* @__PURE__ */ jsxs9("text", {
|
|
26831
27049
|
fg: tokens.dim,
|
|
@@ -26833,7 +27051,7 @@ function ChoiceModal({ title, options, initialIndex = 0, onSubmit, onCancel }) {
|
|
|
26833
27051
|
children: [
|
|
26834
27052
|
"↑/↓ to choose · Enter to confirm · 1-",
|
|
26835
27053
|
options.length,
|
|
26836
|
-
" quick pick · Esc to cancel"
|
|
27054
|
+
" quick pick · Esc to cancel · click to select"
|
|
26837
27055
|
]
|
|
26838
27056
|
})
|
|
26839
27057
|
]
|
|
@@ -26843,18 +27061,19 @@ function ChoiceModal({ title, options, initialIndex = 0, onSubmit, onCancel }) {
|
|
|
26843
27061
|
var init_ChoiceModal = __esm(() => {
|
|
26844
27062
|
init_Overlay();
|
|
26845
27063
|
init_theme();
|
|
27064
|
+
init_use_tap();
|
|
26846
27065
|
});
|
|
26847
27066
|
|
|
26848
27067
|
// src/tui/components/ConfigOverlay.tsx
|
|
26849
|
-
import { useState as
|
|
27068
|
+
import { useState as useState6, useEffect as useEffect4 } from "react";
|
|
26850
27069
|
import { useKeyboard as useKeyboard2 } from "@opentui/react";
|
|
26851
|
-
import { jsx as
|
|
27070
|
+
import { jsx as jsx12, jsxs as jsxs10, Fragment as Fragment2 } from "@opentui/react/jsx-runtime";
|
|
26852
27071
|
function ConfigOverlay({ onClose, onSaved, onError }) {
|
|
26853
|
-
const [config2, setConfig] =
|
|
26854
|
-
const [viewState, setViewState] =
|
|
26855
|
-
const [selectedIndex, setSelectedIndex] =
|
|
26856
|
-
const [windowStart, setWindowStart] =
|
|
26857
|
-
const [editState, setEditState] =
|
|
27072
|
+
const [config2, setConfig] = useState6(null);
|
|
27073
|
+
const [viewState, setViewState] = useState6({ type: "main" });
|
|
27074
|
+
const [selectedIndex, setSelectedIndex] = useState6(1);
|
|
27075
|
+
const [windowStart, setWindowStart] = useState6(0);
|
|
27076
|
+
const [editState, setEditState] = useState6({ type: "none" });
|
|
26858
27077
|
useEffect4(() => {
|
|
26859
27078
|
try {
|
|
26860
27079
|
setConfig(loadConfig());
|
|
@@ -27111,9 +27330,9 @@ function ConfigOverlay({ onClose, onSaved, onError }) {
|
|
|
27111
27330
|
hint = "Remove this repository from config";
|
|
27112
27331
|
}
|
|
27113
27332
|
}
|
|
27114
|
-
return /* @__PURE__ */ jsxs10(
|
|
27333
|
+
return /* @__PURE__ */ jsxs10(Fragment2, {
|
|
27115
27334
|
children: [
|
|
27116
|
-
/* @__PURE__ */
|
|
27335
|
+
/* @__PURE__ */ jsx12(Overlay, {
|
|
27117
27336
|
title: "Configuration",
|
|
27118
27337
|
borderColor: tokens.border,
|
|
27119
27338
|
children: /* @__PURE__ */ jsxs10("box", {
|
|
@@ -27121,7 +27340,7 @@ function ConfigOverlay({ onClose, onSaved, onError }) {
|
|
|
27121
27340
|
width: "100%",
|
|
27122
27341
|
height: 24,
|
|
27123
27342
|
children: [
|
|
27124
|
-
/* @__PURE__ */
|
|
27343
|
+
/* @__PURE__ */ jsx12("box", {
|
|
27125
27344
|
flexDirection: "column",
|
|
27126
27345
|
flexGrow: 1,
|
|
27127
27346
|
overflow: "hidden",
|
|
@@ -27129,7 +27348,7 @@ function ConfigOverlay({ onClose, onSaved, onError }) {
|
|
|
27129
27348
|
const i2 = windowStart + idx;
|
|
27130
27349
|
const isSelected = i2 === selectedIndex;
|
|
27131
27350
|
if (row.type === "header") {
|
|
27132
|
-
return /* @__PURE__ */
|
|
27351
|
+
return /* @__PURE__ */ jsx12("text", {
|
|
27133
27352
|
fg: tokens.dim,
|
|
27134
27353
|
style: { marginTop: i2 === 0 ? 0 : 1 },
|
|
27135
27354
|
children: row.label
|
|
@@ -27171,7 +27390,7 @@ function ConfigOverlay({ onClose, onSaved, onError }) {
|
|
|
27171
27390
|
labelText
|
|
27172
27391
|
]
|
|
27173
27392
|
}),
|
|
27174
|
-
valText && /* @__PURE__ */
|
|
27393
|
+
valText && /* @__PURE__ */ jsx12("text", {
|
|
27175
27394
|
fg: isSelected ? tokens.accent : tokens.dim,
|
|
27176
27395
|
bg: isSelected ? tokens.selectionBg : undefined,
|
|
27177
27396
|
flexShrink: 1,
|
|
@@ -27181,14 +27400,14 @@ function ConfigOverlay({ onClose, onSaved, onError }) {
|
|
|
27181
27400
|
}, i2);
|
|
27182
27401
|
})
|
|
27183
27402
|
}),
|
|
27184
|
-
/* @__PURE__ */
|
|
27403
|
+
/* @__PURE__ */ jsx12("box", {
|
|
27185
27404
|
flexDirection: "row",
|
|
27186
27405
|
border: true,
|
|
27187
27406
|
borderColor: tokens.border,
|
|
27188
27407
|
paddingTop: 1,
|
|
27189
27408
|
marginTop: 1,
|
|
27190
27409
|
minHeight: 3,
|
|
27191
|
-
children: /* @__PURE__ */
|
|
27410
|
+
children: /* @__PURE__ */ jsx12("text", {
|
|
27192
27411
|
fg: tokens.dim,
|
|
27193
27412
|
children: hint
|
|
27194
27413
|
})
|
|
@@ -27196,14 +27415,14 @@ function ConfigOverlay({ onClose, onSaved, onError }) {
|
|
|
27196
27415
|
]
|
|
27197
27416
|
})
|
|
27198
27417
|
}),
|
|
27199
|
-
editState.type === "input" && /* @__PURE__ */
|
|
27418
|
+
editState.type === "input" && /* @__PURE__ */ jsx12(InputModal, {
|
|
27200
27419
|
title: editState.title,
|
|
27201
27420
|
initialValue: editState.currentValue,
|
|
27202
27421
|
placeholder: "Enter value...",
|
|
27203
27422
|
errorMessage: editState.error,
|
|
27204
27423
|
onSubmit: handleInputSubmit
|
|
27205
27424
|
}),
|
|
27206
|
-
editState.type === "confirm_remove" && /* @__PURE__ */
|
|
27425
|
+
editState.type === "confirm_remove" && /* @__PURE__ */ jsx12(ConfirmModal, {
|
|
27207
27426
|
title: "Remove Repo",
|
|
27208
27427
|
message: `Remove repo ${editState.repo} from config?`
|
|
27209
27428
|
})
|
|
@@ -27220,26 +27439,29 @@ var init_ConfigOverlay = __esm(() => {
|
|
|
27220
27439
|
});
|
|
27221
27440
|
|
|
27222
27441
|
// src/tui/components/WarningsOverlay.tsx
|
|
27223
|
-
import { jsx as
|
|
27224
|
-
function WarningsOverlay({ warnings }) {
|
|
27442
|
+
import { jsx as jsx13, jsxs as jsxs11 } from "@opentui/react/jsx-runtime";
|
|
27443
|
+
function WarningsOverlay({ warnings, onAcknowledge, onClose }) {
|
|
27444
|
+
const ackTap = useTapHandler(() => onAcknowledge?.());
|
|
27445
|
+
const closeTap = useTapHandler(() => onClose?.());
|
|
27225
27446
|
return /* @__PURE__ */ jsxs11(Overlay, {
|
|
27226
27447
|
title: `Warnings (${warnings.length})`,
|
|
27227
27448
|
borderColor: tokens.warning,
|
|
27449
|
+
width: 80,
|
|
27228
27450
|
children: [
|
|
27229
|
-
/* @__PURE__ */
|
|
27451
|
+
/* @__PURE__ */ jsx13("box", {
|
|
27230
27452
|
flexDirection: "column",
|
|
27231
|
-
style: { maxHeight:
|
|
27232
|
-
children: /* @__PURE__ */
|
|
27453
|
+
style: { maxHeight: 28 },
|
|
27454
|
+
children: /* @__PURE__ */ jsx13("scrollbox", {
|
|
27233
27455
|
flexGrow: 1,
|
|
27234
27456
|
children: warnings.map((warning, i2) => /* @__PURE__ */ jsxs11("box", {
|
|
27235
27457
|
flexDirection: "column",
|
|
27236
27458
|
style: { marginBottom: 1 },
|
|
27237
27459
|
children: [
|
|
27238
|
-
/* @__PURE__ */
|
|
27460
|
+
/* @__PURE__ */ jsx13("text", {
|
|
27239
27461
|
fg: tokens.warning,
|
|
27240
27462
|
children: `⚠ ${warning.repoName}`
|
|
27241
27463
|
}),
|
|
27242
|
-
wrapText(warning.message,
|
|
27464
|
+
wrapText(warning.message, 72).map((line, j) => /* @__PURE__ */ jsx13("text", {
|
|
27243
27465
|
fg: tokens.fg,
|
|
27244
27466
|
children: ` ${line}`
|
|
27245
27467
|
}, j))
|
|
@@ -27247,9 +27469,46 @@ function WarningsOverlay({ warnings }) {
|
|
|
27247
27469
|
}, i2))
|
|
27248
27470
|
})
|
|
27249
27471
|
}),
|
|
27250
|
-
/* @__PURE__ */
|
|
27472
|
+
/* @__PURE__ */ jsxs11("box", {
|
|
27473
|
+
flexDirection: "row",
|
|
27474
|
+
gap: 3,
|
|
27475
|
+
style: { marginTop: 2 },
|
|
27476
|
+
justifyContent: "center",
|
|
27477
|
+
children: [
|
|
27478
|
+
/* @__PURE__ */ jsx13("box", {
|
|
27479
|
+
...ackTap,
|
|
27480
|
+
children: /* @__PURE__ */ jsxs11("text", {
|
|
27481
|
+
children: [
|
|
27482
|
+
/* @__PURE__ */ jsx13("span", {
|
|
27483
|
+
fg: tokens.dim,
|
|
27484
|
+
children: "[a] "
|
|
27485
|
+
}),
|
|
27486
|
+
/* @__PURE__ */ jsx13("span", {
|
|
27487
|
+
fg: tokens.success,
|
|
27488
|
+
children: "Acknowledge"
|
|
27489
|
+
})
|
|
27490
|
+
]
|
|
27491
|
+
})
|
|
27492
|
+
}),
|
|
27493
|
+
/* @__PURE__ */ jsx13("box", {
|
|
27494
|
+
...closeTap,
|
|
27495
|
+
children: /* @__PURE__ */ jsxs11("text", {
|
|
27496
|
+
children: [
|
|
27497
|
+
/* @__PURE__ */ jsx13("span", {
|
|
27498
|
+
fg: tokens.dim,
|
|
27499
|
+
children: "[esc] "
|
|
27500
|
+
}),
|
|
27501
|
+
/* @__PURE__ */ jsx13("span", {
|
|
27502
|
+
children: "Close"
|
|
27503
|
+
})
|
|
27504
|
+
]
|
|
27505
|
+
})
|
|
27506
|
+
})
|
|
27507
|
+
]
|
|
27508
|
+
}),
|
|
27509
|
+
/* @__PURE__ */ jsx13("text", {
|
|
27251
27510
|
style: { marginTop: 1, fg: tokens.dim },
|
|
27252
|
-
children: "Press
|
|
27511
|
+
children: "Press a to acknowledge and clear errors"
|
|
27253
27512
|
})
|
|
27254
27513
|
]
|
|
27255
27514
|
});
|
|
@@ -27258,12 +27517,13 @@ var init_WarningsOverlay = __esm(() => {
|
|
|
27258
27517
|
init_Overlay();
|
|
27259
27518
|
init_theme();
|
|
27260
27519
|
init_utils();
|
|
27520
|
+
init_use_tap();
|
|
27261
27521
|
});
|
|
27262
27522
|
|
|
27263
27523
|
// src/tui/hooks/useSpinnerFrame.ts
|
|
27264
|
-
import { useEffect as useEffect5, useState as
|
|
27524
|
+
import { useEffect as useEffect5, useState as useState7 } from "react";
|
|
27265
27525
|
function useSpinnerFrame(active) {
|
|
27266
|
-
const [index, setIndex] =
|
|
27526
|
+
const [index, setIndex] = useState7(0);
|
|
27267
27527
|
useEffect5(() => {
|
|
27268
27528
|
if (!active)
|
|
27269
27529
|
return;
|
|
@@ -27278,10 +27538,10 @@ var init_useSpinnerFrame = __esm(() => {
|
|
|
27278
27538
|
});
|
|
27279
27539
|
|
|
27280
27540
|
// src/tui/components/App.tsx
|
|
27281
|
-
import { useState as
|
|
27541
|
+
import { useState as useState8, useEffect as useEffect6, useMemo, useRef as useRef5, useCallback as useCallback4 } from "react";
|
|
27282
27542
|
import { existsSync as existsSync4 } from "node:fs";
|
|
27283
|
-
import { useKeyboard as useKeyboard3, useRenderer, useSelectionHandler } from "@opentui/react";
|
|
27284
|
-
import { jsx as
|
|
27543
|
+
import { useKeyboard as useKeyboard3, useRenderer as useRenderer2, useSelectionHandler, useTerminalDimensions } from "@opentui/react";
|
|
27544
|
+
import { jsx as jsx14, jsxs as jsxs12 } from "@opentui/react/jsx-runtime";
|
|
27285
27545
|
function getWorktreePathFor(repoName, branch) {
|
|
27286
27546
|
try {
|
|
27287
27547
|
const config2 = loadConfig();
|
|
@@ -27292,31 +27552,39 @@ function getWorktreePathFor(repoName, branch) {
|
|
|
27292
27552
|
}
|
|
27293
27553
|
}
|
|
27294
27554
|
function App({ opts }) {
|
|
27295
|
-
const renderer =
|
|
27296
|
-
const { blocks, loading, refreshing, error: error52, warnings, lastRefreshed, pendingRepos, refresh } = useWorktrees(opts);
|
|
27297
|
-
const [selectedIndex, setSelectedIndex] =
|
|
27298
|
-
const [modal, setModal] =
|
|
27299
|
-
const [actionMessage, setActionMessage] =
|
|
27300
|
-
const messageTimer =
|
|
27301
|
-
const [ops, setOps] =
|
|
27302
|
-
const [failedLogs, setFailedLogs] =
|
|
27303
|
-
const nextOpId =
|
|
27304
|
-
const [createModal, setCreateModal] =
|
|
27305
|
-
const [createError, setCreateError] =
|
|
27306
|
-
const [createBaseModal, setCreateBaseModal] =
|
|
27307
|
-
const [createBaseError, setCreateBaseError] =
|
|
27308
|
-
const [createDepsChoice, setCreateDepsChoice] =
|
|
27309
|
-
const [pullPrModal, setPullPrModal] =
|
|
27310
|
-
const [pullPrError, setPullPrError] =
|
|
27311
|
-
const [pullForceChoice, setPullForceChoice] =
|
|
27312
|
-
const [renameModal, setRenameModal] =
|
|
27313
|
-
const [renameError, setRenameError] =
|
|
27314
|
-
const [configOpen, setConfigOpen] =
|
|
27315
|
-
const [refreshScopes, setRefreshScopes] =
|
|
27316
|
-
const [filterText, setFilterText] =
|
|
27317
|
-
const [isFiltering, setIsFiltering] =
|
|
27318
|
-
const [selection, setSelection] =
|
|
27319
|
-
const
|
|
27555
|
+
const renderer = useRenderer2();
|
|
27556
|
+
const { blocks, loading, refreshing, error: error52, warnings, lastRefreshed, pendingRepos, refresh, clearWarnings } = useWorktrees(opts);
|
|
27557
|
+
const [selectedIndex, setSelectedIndex] = useState8(0);
|
|
27558
|
+
const [modal, setModal] = useState8({ type: "none" });
|
|
27559
|
+
const [actionMessage, setActionMessage] = useState8();
|
|
27560
|
+
const messageTimer = useRef5(null);
|
|
27561
|
+
const [ops, setOps] = useState8([]);
|
|
27562
|
+
const [failedLogs, setFailedLogs] = useState8([]);
|
|
27563
|
+
const nextOpId = useRef5(1);
|
|
27564
|
+
const [createModal, setCreateModal] = useState8(false);
|
|
27565
|
+
const [createError, setCreateError] = useState8();
|
|
27566
|
+
const [createBaseModal, setCreateBaseModal] = useState8(null);
|
|
27567
|
+
const [createBaseError, setCreateBaseError] = useState8();
|
|
27568
|
+
const [createDepsChoice, setCreateDepsChoice] = useState8(null);
|
|
27569
|
+
const [pullPrModal, setPullPrModal] = useState8(false);
|
|
27570
|
+
const [pullPrError, setPullPrError] = useState8();
|
|
27571
|
+
const [pullForceChoice, setPullForceChoice] = useState8(null);
|
|
27572
|
+
const [renameModal, setRenameModal] = useState8(false);
|
|
27573
|
+
const [renameError, setRenameError] = useState8();
|
|
27574
|
+
const [configOpen, setConfigOpen] = useState8(false);
|
|
27575
|
+
const [refreshScopes, setRefreshScopes] = useState8([]);
|
|
27576
|
+
const [filterText, setFilterText] = useState8("");
|
|
27577
|
+
const [isFiltering, setIsFiltering] = useState8(false);
|
|
27578
|
+
const [selection, setSelection] = useState8(new Set);
|
|
27579
|
+
const [splitRatio, setSplitRatio] = useState8(0.6);
|
|
27580
|
+
const [isResizing, setIsResizing] = useState8(false);
|
|
27581
|
+
const { width: termWidth } = useTerminalDimensions();
|
|
27582
|
+
const totalWidth = termWidth || renderer.width || 80;
|
|
27583
|
+
useEffect6(() => {
|
|
27584
|
+
if (termWidth)
|
|
27585
|
+
setSplitRatio((prev) => clampSplitRatio(termWidth, prev));
|
|
27586
|
+
}, [termWidth]);
|
|
27587
|
+
const doRefresh = useCallback4(async (scope) => {
|
|
27320
27588
|
const targets = scope ?? [
|
|
27321
27589
|
...new Set([...blocks.map((b) => b.repoName), ...pendingRepos])
|
|
27322
27590
|
];
|
|
@@ -27332,13 +27600,17 @@ function App({ opts }) {
|
|
|
27332
27600
|
setModal({ type: "error", message: error52 });
|
|
27333
27601
|
}
|
|
27334
27602
|
}, [error52]);
|
|
27335
|
-
const flash =
|
|
27603
|
+
const flash = useCallback4((message, ms = 3000) => {
|
|
27336
27604
|
if (messageTimer.current)
|
|
27337
27605
|
clearTimeout(messageTimer.current);
|
|
27338
27606
|
setActionMessage(message);
|
|
27339
27607
|
messageTimer.current = setTimeout(() => setActionMessage(undefined), ms);
|
|
27340
27608
|
}, []);
|
|
27341
|
-
const copySelectedText =
|
|
27609
|
+
const copySelectedText = useCallback4((warnOnEmpty) => {
|
|
27610
|
+
if (isResizing) {
|
|
27611
|
+
renderer.clearSelection();
|
|
27612
|
+
return;
|
|
27613
|
+
}
|
|
27342
27614
|
const text = renderer.getSelection()?.getSelectedText() ?? "";
|
|
27343
27615
|
if (!text) {
|
|
27344
27616
|
if (warnOnEmpty)
|
|
@@ -27346,7 +27618,7 @@ function App({ opts }) {
|
|
|
27346
27618
|
return;
|
|
27347
27619
|
}
|
|
27348
27620
|
copyTextToClipboard(renderer, text).then((ok) => flash(ok ? `Copied ${text.length} character${text.length !== 1 ? "s" : ""}` : "Copy failed"));
|
|
27349
|
-
}, [renderer, flash]);
|
|
27621
|
+
}, [renderer, flash, isResizing]);
|
|
27350
27622
|
useSelectionHandler(() => copySelectedText(false));
|
|
27351
27623
|
const busyRepos = useMemo(() => new Set(ops.flatMap((o2) => o2.repoNames)), [ops]);
|
|
27352
27624
|
const busyRowPaths = useMemo(() => new Set(ops.map((o2) => o2.rowPath).filter((p) => p !== undefined)), [ops]);
|
|
@@ -27508,6 +27780,159 @@ function App({ opts }) {
|
|
|
27508
27780
|
args.push("--force");
|
|
27509
27781
|
executeOp(op, args, [repoName]);
|
|
27510
27782
|
};
|
|
27783
|
+
const handleHintClick = useCallback4((key) => {
|
|
27784
|
+
if (key === "c") {
|
|
27785
|
+
setConfigOpen(true);
|
|
27786
|
+
return;
|
|
27787
|
+
}
|
|
27788
|
+
if (key === "?") {
|
|
27789
|
+
setModal({ type: "help" });
|
|
27790
|
+
return;
|
|
27791
|
+
}
|
|
27792
|
+
if (key === "H") {
|
|
27793
|
+
setModal({ type: "history" });
|
|
27794
|
+
return;
|
|
27795
|
+
}
|
|
27796
|
+
if (key === "r") {
|
|
27797
|
+
doRefresh();
|
|
27798
|
+
return;
|
|
27799
|
+
}
|
|
27800
|
+
if (key === "e" && warnings.length > 0) {
|
|
27801
|
+
setModal({ type: "warnings" });
|
|
27802
|
+
return;
|
|
27803
|
+
}
|
|
27804
|
+
if (key === "n") {
|
|
27805
|
+
if (!selectedRow)
|
|
27806
|
+
return;
|
|
27807
|
+
setCreateModal(true);
|
|
27808
|
+
setCreateError(undefined);
|
|
27809
|
+
return;
|
|
27810
|
+
}
|
|
27811
|
+
if (key === "m") {
|
|
27812
|
+
const target = selectedRow;
|
|
27813
|
+
if (!target || target.isMainCheckout || !target.branch || target.branch === "(detached)") {
|
|
27814
|
+
if (target?.isMainCheckout)
|
|
27815
|
+
flash("Cannot rename main checkout");
|
|
27816
|
+
else if (target && (!target.branch || target.branch === "(detached)"))
|
|
27817
|
+
flash("Cannot rename detached worktree");
|
|
27818
|
+
return;
|
|
27819
|
+
}
|
|
27820
|
+
const conflict = findConflict([target]);
|
|
27821
|
+
if (conflict) {
|
|
27822
|
+
flash(conflict);
|
|
27823
|
+
return;
|
|
27824
|
+
}
|
|
27825
|
+
setRenameModal(true);
|
|
27826
|
+
setRenameError(undefined);
|
|
27827
|
+
return;
|
|
27828
|
+
}
|
|
27829
|
+
if (key === "f") {
|
|
27830
|
+
const targets = getSelectedRows();
|
|
27831
|
+
if (targets.length > 0)
|
|
27832
|
+
startFetch(targets);
|
|
27833
|
+
return;
|
|
27834
|
+
}
|
|
27835
|
+
if (key === "o") {
|
|
27836
|
+
const targets = getSelectedRows();
|
|
27837
|
+
if (targets.length === 0)
|
|
27838
|
+
return;
|
|
27839
|
+
if (targets.length > 1) {
|
|
27840
|
+
flash("Cannot open multiple worktrees");
|
|
27841
|
+
return;
|
|
27842
|
+
}
|
|
27843
|
+
const target = targets[0];
|
|
27844
|
+
const conflict = findConflict(targets);
|
|
27845
|
+
if (conflict) {
|
|
27846
|
+
flash(conflict);
|
|
27847
|
+
return;
|
|
27848
|
+
}
|
|
27849
|
+
const op = {
|
|
27850
|
+
id: nextOpId.current++,
|
|
27851
|
+
kind: "open",
|
|
27852
|
+
repoNames: [target.repoName],
|
|
27853
|
+
rowPath: target.path,
|
|
27854
|
+
label: target.branch,
|
|
27855
|
+
title: `Open ${target.branch}`,
|
|
27856
|
+
status: "queued",
|
|
27857
|
+
lines: []
|
|
27858
|
+
};
|
|
27859
|
+
setOps((prev) => [...prev, op]);
|
|
27860
|
+
executeOp(op, ["open", target.branch, "--repo", target.repoName], null);
|
|
27861
|
+
return;
|
|
27862
|
+
}
|
|
27863
|
+
if (key === "i") {
|
|
27864
|
+
const targets = getSelectedRows();
|
|
27865
|
+
if (targets.length === 0)
|
|
27866
|
+
return;
|
|
27867
|
+
const conflict = findConflict(targets);
|
|
27868
|
+
if (conflict) {
|
|
27869
|
+
flash(conflict);
|
|
27870
|
+
return;
|
|
27871
|
+
}
|
|
27872
|
+
startBatchActions("install", targets, (r) => r.isMainCheckout ? ["deps", "--repo", r.repoName, "--install"] : ["deps", r.branch, "--repo", r.repoName, "--install"]);
|
|
27873
|
+
return;
|
|
27874
|
+
}
|
|
27875
|
+
if (key === "p") {
|
|
27876
|
+
const targets = getSelectedRows();
|
|
27877
|
+
if (targets.length === 0)
|
|
27878
|
+
return;
|
|
27879
|
+
const conflict = findConflict(targets);
|
|
27880
|
+
if (conflict) {
|
|
27881
|
+
flash(conflict);
|
|
27882
|
+
return;
|
|
27883
|
+
}
|
|
27884
|
+
startBatchActions("pull", targets, (r) => ["pull-branch", r.branch, "--repo", r.repoName]);
|
|
27885
|
+
return;
|
|
27886
|
+
}
|
|
27887
|
+
if (key === "b") {
|
|
27888
|
+
const targets = getSelectedRows();
|
|
27889
|
+
if (targets.length === 0)
|
|
27890
|
+
return;
|
|
27891
|
+
if (targets.some((r) => r.isMainCheckout)) {
|
|
27892
|
+
flash("Cannot rebase main checkout");
|
|
27893
|
+
return;
|
|
27894
|
+
}
|
|
27895
|
+
const conflict = findConflict(targets);
|
|
27896
|
+
if (conflict) {
|
|
27897
|
+
flash(conflict);
|
|
27898
|
+
return;
|
|
27899
|
+
}
|
|
27900
|
+
setModal({ type: "confirm_rebase", rows: targets });
|
|
27901
|
+
return;
|
|
27902
|
+
}
|
|
27903
|
+
if (key === "d") {
|
|
27904
|
+
const targets = getSelectedRows();
|
|
27905
|
+
if (targets.length === 0)
|
|
27906
|
+
return;
|
|
27907
|
+
if (targets.some((r) => r.isMainCheckout)) {
|
|
27908
|
+
flash("Cannot remove main checkout");
|
|
27909
|
+
return;
|
|
27910
|
+
}
|
|
27911
|
+
const conflict = findConflict(targets);
|
|
27912
|
+
if (conflict) {
|
|
27913
|
+
flash(conflict);
|
|
27914
|
+
return;
|
|
27915
|
+
}
|
|
27916
|
+
setModal({ type: "confirm_remove", rows: targets });
|
|
27917
|
+
return;
|
|
27918
|
+
}
|
|
27919
|
+
if (key === "s") {
|
|
27920
|
+
const targets = getSelectedRows();
|
|
27921
|
+
if (targets.length === 0)
|
|
27922
|
+
return;
|
|
27923
|
+
if (targets.some((r) => r.isMainCheckout)) {
|
|
27924
|
+
flash("Cannot sync main checkout");
|
|
27925
|
+
return;
|
|
27926
|
+
}
|
|
27927
|
+
const conflict = findConflict(targets);
|
|
27928
|
+
if (conflict) {
|
|
27929
|
+
flash(conflict);
|
|
27930
|
+
return;
|
|
27931
|
+
}
|
|
27932
|
+
setModal({ type: "confirm_sync", rows: targets });
|
|
27933
|
+
return;
|
|
27934
|
+
}
|
|
27935
|
+
}, [selectedRow, selection, warnings, busyRepos, busyRowPaths, doRefresh, flash, blocks]);
|
|
27511
27936
|
useKeyboard3((key) => {
|
|
27512
27937
|
if (isFiltering) {
|
|
27513
27938
|
if (key.name === "escape") {
|
|
@@ -27558,7 +27983,20 @@ function App({ opts }) {
|
|
|
27558
27983
|
return;
|
|
27559
27984
|
}
|
|
27560
27985
|
if (modal.type !== "none") {
|
|
27561
|
-
if (modal.type === "
|
|
27986
|
+
if (modal.type === "warnings") {
|
|
27987
|
+
if (key.name === "a") {
|
|
27988
|
+
clearWarnings();
|
|
27989
|
+
setModal({ type: "none" });
|
|
27990
|
+
return;
|
|
27991
|
+
}
|
|
27992
|
+
if (key.name === "escape" || key.name === "q" || key.name === "enter" || key.name === "return") {
|
|
27993
|
+
setModal({ type: "none" });
|
|
27994
|
+
return;
|
|
27995
|
+
}
|
|
27996
|
+
setModal({ type: "none" });
|
|
27997
|
+
return;
|
|
27998
|
+
}
|
|
27999
|
+
if (modal.type === "error" || modal.type === "help" || modal.type === "history") {
|
|
27562
28000
|
setModal({ type: "none" });
|
|
27563
28001
|
if (modal.type === "error" && error52) {
|
|
27564
28002
|
renderer.destroy();
|
|
@@ -27848,6 +28286,9 @@ function App({ opts }) {
|
|
|
27848
28286
|
})();
|
|
27849
28287
|
}
|
|
27850
28288
|
});
|
|
28289
|
+
const rawLeft = Math.floor(totalWidth * splitRatio);
|
|
28290
|
+
const leftCols = Math.max(20, Math.min(totalWidth - 20 - DIVIDER_WIDTH, rawLeft));
|
|
28291
|
+
const rightCols = Math.max(20, totalWidth - leftCols - DIVIDER_WIDTH);
|
|
27851
28292
|
return /* @__PURE__ */ jsxs12("box", {
|
|
27852
28293
|
flexDirection: "column",
|
|
27853
28294
|
width: "100%",
|
|
@@ -27858,16 +28299,34 @@ function App({ opts }) {
|
|
|
27858
28299
|
width: "100%",
|
|
27859
28300
|
flexGrow: 1,
|
|
27860
28301
|
children: [
|
|
27861
|
-
/* @__PURE__ */
|
|
27862
|
-
|
|
27863
|
-
|
|
27864
|
-
|
|
27865
|
-
|
|
27866
|
-
|
|
27867
|
-
|
|
28302
|
+
/* @__PURE__ */ jsx14("box", {
|
|
28303
|
+
width: leftCols,
|
|
28304
|
+
height: "100%",
|
|
28305
|
+
flexDirection: "column",
|
|
28306
|
+
children: /* @__PURE__ */ jsx14(WorktreeTable, {
|
|
28307
|
+
blocks: displayBlocks,
|
|
28308
|
+
selectedIndex,
|
|
28309
|
+
selection,
|
|
28310
|
+
frame: spinnerFrame,
|
|
28311
|
+
repoVerbs,
|
|
28312
|
+
rowVerbs,
|
|
28313
|
+
onRowClick: (idx) => setSelectedIndex(idx),
|
|
28314
|
+
onToggleSelect: (path37) => setSelection((prev) => toggleSelection(prev, path37))
|
|
28315
|
+
})
|
|
28316
|
+
}),
|
|
28317
|
+
/* @__PURE__ */ jsx14(Divider, {
|
|
28318
|
+
splitRatio,
|
|
28319
|
+
totalWidth,
|
|
28320
|
+
onChange: setSplitRatio,
|
|
28321
|
+
onDraggingChange: setIsResizing
|
|
27868
28322
|
}),
|
|
27869
|
-
/* @__PURE__ */
|
|
27870
|
-
|
|
28323
|
+
/* @__PURE__ */ jsx14("box", {
|
|
28324
|
+
width: rightCols,
|
|
28325
|
+
height: "100%",
|
|
28326
|
+
flexDirection: "column",
|
|
28327
|
+
children: /* @__PURE__ */ jsx14(DetailPane, {
|
|
28328
|
+
selectedRow
|
|
28329
|
+
})
|
|
27871
28330
|
})
|
|
27872
28331
|
]
|
|
27873
28332
|
}),
|
|
@@ -27877,35 +28336,56 @@ function App({ opts }) {
|
|
|
27877
28336
|
border: true,
|
|
27878
28337
|
borderColor: "magenta",
|
|
27879
28338
|
children: [
|
|
27880
|
-
/* @__PURE__ */
|
|
28339
|
+
/* @__PURE__ */ jsx14("text", {
|
|
27881
28340
|
children: "filter: "
|
|
27882
28341
|
}),
|
|
27883
|
-
/* @__PURE__ */
|
|
28342
|
+
/* @__PURE__ */ jsx14("input", {
|
|
27884
28343
|
focused: true,
|
|
27885
28344
|
placeholder: "Type to filter...",
|
|
27886
28345
|
onInput: (v) => setFilterText(v)
|
|
27887
28346
|
})
|
|
27888
28347
|
]
|
|
27889
28348
|
}),
|
|
27890
|
-
/* @__PURE__ */
|
|
28349
|
+
/* @__PURE__ */ jsx14(Footer, {
|
|
27891
28350
|
loading: loading || refreshing,
|
|
27892
28351
|
lastRefreshed,
|
|
27893
28352
|
errorCount: warnings.length,
|
|
27894
28353
|
message: actionMessage,
|
|
27895
28354
|
busyText: latestOp ? `${capitalize(VERBS[latestOp.kind])} ${latestOp.label}…${runningOps.length > 1 ? ` (+${runningOps.length - 1})` : ""}` : undefined,
|
|
27896
28355
|
spinnerFrame,
|
|
27897
|
-
filter: filterText ? { term: filterText, matches: flatRows.length, total: totalRows } : undefined
|
|
28356
|
+
filter: filterText ? { term: filterText, matches: flatRows.length, total: totalRows } : undefined,
|
|
28357
|
+
onHintClick: handleHintClick,
|
|
28358
|
+
onErrorClick: () => setModal({ type: "warnings" })
|
|
27898
28359
|
}),
|
|
27899
|
-
modal.type === "help" && /* @__PURE__ */
|
|
27900
|
-
modal.type === "history" && /* @__PURE__ */
|
|
27901
|
-
modal.type === "warnings" && /* @__PURE__ */
|
|
27902
|
-
warnings
|
|
28360
|
+
modal.type === "help" && /* @__PURE__ */ jsx14(HelpOverlay, {}),
|
|
28361
|
+
modal.type === "history" && /* @__PURE__ */ jsx14(HistoryOverlay, {}),
|
|
28362
|
+
modal.type === "warnings" && /* @__PURE__ */ jsx14(WarningsOverlay, {
|
|
28363
|
+
warnings,
|
|
28364
|
+
onAcknowledge: () => {
|
|
28365
|
+
clearWarnings();
|
|
28366
|
+
setModal({ type: "none" });
|
|
28367
|
+
},
|
|
28368
|
+
onClose: () => setModal({ type: "none" })
|
|
27903
28369
|
}),
|
|
27904
|
-
modal.type === "error" && /* @__PURE__ */
|
|
28370
|
+
modal.type === "error" && /* @__PURE__ */ jsx14(ConfirmModal, {
|
|
27905
28371
|
title: "Error",
|
|
27906
|
-
message: modal.message
|
|
28372
|
+
message: modal.message,
|
|
28373
|
+
onConfirm: () => {
|
|
28374
|
+
setModal({ type: "none" });
|
|
28375
|
+
if (error52) {
|
|
28376
|
+
renderer.destroy();
|
|
28377
|
+
process.exit(1);
|
|
28378
|
+
}
|
|
28379
|
+
},
|
|
28380
|
+
onCancel: () => {
|
|
28381
|
+
setModal({ type: "none" });
|
|
28382
|
+
if (error52) {
|
|
28383
|
+
renderer.destroy();
|
|
28384
|
+
process.exit(1);
|
|
28385
|
+
}
|
|
28386
|
+
}
|
|
27907
28387
|
}),
|
|
27908
|
-
modal.type === "confirm_remove" && /* @__PURE__ */
|
|
28388
|
+
modal.type === "confirm_remove" && /* @__PURE__ */ jsx14(ConfirmModal, {
|
|
27909
28389
|
title: `Remove ${modal.rows.length} Worktree(s)`,
|
|
27910
28390
|
message: (() => {
|
|
27911
28391
|
const count2 = modal.rows.length;
|
|
@@ -27920,17 +28400,41 @@ function App({ opts }) {
|
|
|
27920
28400
|
}
|
|
27921
28401
|
return lines.join(`
|
|
27922
28402
|
`);
|
|
27923
|
-
})()
|
|
28403
|
+
})(),
|
|
28404
|
+
onConfirm: () => {
|
|
28405
|
+
const rows = modal.rows;
|
|
28406
|
+
setModal({ type: "none" });
|
|
28407
|
+
startBatchActions("remove", rows, (r) => {
|
|
28408
|
+
const args = ["remove", r.branch, "--repo", r.repoName, "--yes"];
|
|
28409
|
+
const needsForce = r.dirtyFiles.length > 0 || !existsSync4(r.path);
|
|
28410
|
+
if (needsForce)
|
|
28411
|
+
args.push("--force");
|
|
28412
|
+
return args;
|
|
28413
|
+
});
|
|
28414
|
+
},
|
|
28415
|
+
onCancel: () => setModal({ type: "none" })
|
|
27924
28416
|
}),
|
|
27925
|
-
modal.type === "confirm_rebase" && /* @__PURE__ */
|
|
28417
|
+
modal.type === "confirm_rebase" && /* @__PURE__ */ jsx14(ConfirmModal, {
|
|
27926
28418
|
title: `Rebase ${modal.rows.length} Worktree(s)`,
|
|
27927
|
-
message: `Are you sure you want to fetch and rebase ${modal.rows.length === 1 ? modal.rows[0]?.branch : modal.rows.length + " worktrees"}
|
|
28419
|
+
message: `Are you sure you want to fetch and rebase ${modal.rows.length === 1 ? modal.rows[0]?.branch : modal.rows.length + " worktrees"}?`,
|
|
28420
|
+
onConfirm: () => {
|
|
28421
|
+
const rows = modal.rows;
|
|
28422
|
+
setModal({ type: "none" });
|
|
28423
|
+
startBatchActions("rebase", rows, (r) => ["rebase", r.branch, "--repo", r.repoName]);
|
|
28424
|
+
},
|
|
28425
|
+
onCancel: () => setModal({ type: "none" })
|
|
27928
28426
|
}),
|
|
27929
|
-
modal.type === "confirm_sync" && /* @__PURE__ */
|
|
28427
|
+
modal.type === "confirm_sync" && /* @__PURE__ */ jsx14(ConfirmModal, {
|
|
27930
28428
|
title: `Sync ${modal.rows.length} Worktree(s)`,
|
|
27931
|
-
message: `Are you sure you want to sync ${modal.rows.length === 1 ? modal.rows[0]?.branch : modal.rows.length + " worktrees"}
|
|
28429
|
+
message: `Are you sure you want to sync ${modal.rows.length === 1 ? modal.rows[0]?.branch : modal.rows.length + " worktrees"}?`,
|
|
28430
|
+
onConfirm: () => {
|
|
28431
|
+
const rows = modal.rows;
|
|
28432
|
+
setModal({ type: "none" });
|
|
28433
|
+
startBatchActions("sync", rows, (r) => ["sync", r.branch, "--repo", r.repoName]);
|
|
28434
|
+
},
|
|
28435
|
+
onCancel: () => setModal({ type: "none" })
|
|
27932
28436
|
}),
|
|
27933
|
-
createModal && /* @__PURE__ */
|
|
28437
|
+
createModal && /* @__PURE__ */ jsx14(InputModal, {
|
|
27934
28438
|
title: `New worktree branch in ${selectedRow?.repoName ?? ""}`,
|
|
27935
28439
|
placeholder: "Branch name (empty to cancel)",
|
|
27936
28440
|
errorMessage: createError,
|
|
@@ -27957,7 +28461,7 @@ function App({ opts }) {
|
|
|
27957
28461
|
setCreateBaseModal({ branch, repoName });
|
|
27958
28462
|
}
|
|
27959
28463
|
}),
|
|
27960
|
-
createBaseModal && /* @__PURE__ */
|
|
28464
|
+
createBaseModal && /* @__PURE__ */ jsx14(InputModal, {
|
|
27961
28465
|
title: `Base ref for ${createBaseModal.branch}`,
|
|
27962
28466
|
placeholder: "origin/main (empty for default main)",
|
|
27963
28467
|
errorMessage: createBaseError,
|
|
@@ -27973,7 +28477,7 @@ function App({ opts }) {
|
|
|
27973
28477
|
setCreateDepsChoice({ branch, repoName, base: base2 || undefined });
|
|
27974
28478
|
}
|
|
27975
28479
|
}),
|
|
27976
|
-
createDepsChoice && /* @__PURE__ */
|
|
28480
|
+
createDepsChoice && /* @__PURE__ */ jsx14(ChoiceModal, {
|
|
27977
28481
|
title: `Dependencies for ${createDepsChoice.branch}`,
|
|
27978
28482
|
options: DEPS_CHOICES,
|
|
27979
28483
|
onSubmit: (choice) => {
|
|
@@ -27983,7 +28487,7 @@ function App({ opts }) {
|
|
|
27983
28487
|
},
|
|
27984
28488
|
onCancel: () => setCreateDepsChoice(null)
|
|
27985
28489
|
}),
|
|
27986
|
-
pullPrModal && /* @__PURE__ */
|
|
28490
|
+
pullPrModal && /* @__PURE__ */ jsx14(InputModal, {
|
|
27987
28491
|
title: `Pull PR into ${selectedRow?.repoName ?? ""}`,
|
|
27988
28492
|
placeholder: "https://github.com/owner/repo/pull/123",
|
|
27989
28493
|
errorMessage: pullPrError,
|
|
@@ -28011,7 +28515,7 @@ function App({ opts }) {
|
|
|
28011
28515
|
setPullForceChoice({ link, repoName });
|
|
28012
28516
|
}
|
|
28013
28517
|
}),
|
|
28014
|
-
pullForceChoice && /* @__PURE__ */
|
|
28518
|
+
pullForceChoice && /* @__PURE__ */ jsx14(ChoiceModal, {
|
|
28015
28519
|
title: `Pull ${pullForceChoice.link.split("/").pop()}?`,
|
|
28016
28520
|
options: [
|
|
28017
28521
|
{ value: "normal", label: "Pull (skip if exists)", desc: "Fails if branch already exists" },
|
|
@@ -28024,7 +28528,7 @@ function App({ opts }) {
|
|
|
28024
28528
|
},
|
|
28025
28529
|
onCancel: () => setPullForceChoice(null)
|
|
28026
28530
|
}),
|
|
28027
|
-
renameModal && selectedRow && /* @__PURE__ */
|
|
28531
|
+
renameModal && selectedRow && /* @__PURE__ */ jsx14(InputModal, {
|
|
28028
28532
|
title: `Rename branch ${selectedRow.branch}`,
|
|
28029
28533
|
initialValue: selectedRow.branch,
|
|
28030
28534
|
placeholder: "New branch name",
|
|
@@ -28049,7 +28553,7 @@ function App({ opts }) {
|
|
|
28049
28553
|
setModal({ type: "confirm_rename", row: target, to });
|
|
28050
28554
|
}
|
|
28051
28555
|
}),
|
|
28052
|
-
modal.type === "confirm_rename" && /* @__PURE__ */
|
|
28556
|
+
modal.type === "confirm_rename" && /* @__PURE__ */ jsx14(ConfirmModal, {
|
|
28053
28557
|
title: "Rename Worktree",
|
|
28054
28558
|
message: [
|
|
28055
28559
|
`${modal.row.branch} → ${modal.to}`,
|
|
@@ -28060,14 +28564,32 @@ function App({ opts }) {
|
|
|
28060
28564
|
"Uncommitted changes and synced files move with it.",
|
|
28061
28565
|
"Proceed?"
|
|
28062
28566
|
].join(`
|
|
28063
|
-
`)
|
|
28567
|
+
`),
|
|
28568
|
+
onConfirm: () => {
|
|
28569
|
+
const { row, to } = modal;
|
|
28570
|
+
setModal({ type: "none" });
|
|
28571
|
+
const op = {
|
|
28572
|
+
id: nextOpId.current++,
|
|
28573
|
+
kind: "rename",
|
|
28574
|
+
repoNames: [row.repoName],
|
|
28575
|
+
rowPath: row.path,
|
|
28576
|
+
branch: row.branch,
|
|
28577
|
+
label: `${row.branch} → ${to}`,
|
|
28578
|
+
title: `Rename ${row.branch} → ${to}`,
|
|
28579
|
+
status: "queued",
|
|
28580
|
+
lines: []
|
|
28581
|
+
};
|
|
28582
|
+
setOps((prev) => [...prev, op]);
|
|
28583
|
+
executeOp(op, ["rename", row.branch, to, "--repo", row.repoName], [row.repoName]);
|
|
28584
|
+
},
|
|
28585
|
+
onCancel: () => setModal({ type: "none" })
|
|
28064
28586
|
}),
|
|
28065
|
-
configOpen && /* @__PURE__ */
|
|
28587
|
+
configOpen && /* @__PURE__ */ jsx14(ConfigOverlay, {
|
|
28066
28588
|
onClose: () => setConfigOpen(false),
|
|
28067
28589
|
onSaved: () => void doRefresh(),
|
|
28068
28590
|
onError: (msg) => setModal({ type: "error", message: msg })
|
|
28069
28591
|
}),
|
|
28070
|
-
failedLogs.length > 0 && /* @__PURE__ */
|
|
28592
|
+
failedLogs.length > 0 && /* @__PURE__ */ jsx14(ActionLogModal, {
|
|
28071
28593
|
title: failedLogs[0].title,
|
|
28072
28594
|
lines: failedLogs[0].lines,
|
|
28073
28595
|
done: true,
|
|
@@ -28083,6 +28605,7 @@ var init_App = __esm(() => {
|
|
|
28083
28605
|
init_WorktreeTable();
|
|
28084
28606
|
init_DetailPane();
|
|
28085
28607
|
init_Footer();
|
|
28608
|
+
init_Divider();
|
|
28086
28609
|
init_HelpOverlay();
|
|
28087
28610
|
init_ConfirmModal();
|
|
28088
28611
|
init_git();
|
|
@@ -28122,14 +28645,14 @@ __export(exports_tui, {
|
|
|
28122
28645
|
});
|
|
28123
28646
|
import { createCliRenderer, TextTableRenderable } from "@opentui/core";
|
|
28124
28647
|
import { createRoot, extend as extend2 } from "@opentui/react";
|
|
28125
|
-
import { jsx as
|
|
28648
|
+
import { jsx as jsx15 } from "@opentui/react/jsx-runtime";
|
|
28126
28649
|
async function runTerminal(opts) {
|
|
28127
28650
|
const renderer = await createCliRenderer({
|
|
28128
28651
|
exitOnCtrlC: false
|
|
28129
28652
|
});
|
|
28130
28653
|
const root = createRoot(renderer);
|
|
28131
28654
|
try {
|
|
28132
|
-
root.render(/* @__PURE__ */
|
|
28655
|
+
root.render(/* @__PURE__ */ jsx15(App, {
|
|
28133
28656
|
opts
|
|
28134
28657
|
}));
|
|
28135
28658
|
} catch (err) {
|