@dacsar/prview 1.0.1 → 1.1.0
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.js +170 -67
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -48727,7 +48727,49 @@ var COL = {
|
|
|
48727
48727
|
reviewee: 12,
|
|
48728
48728
|
reviewer: 12
|
|
48729
48729
|
};
|
|
48730
|
-
var
|
|
48730
|
+
var BASE_WIDTH = 7;
|
|
48731
|
+
var OPTIONAL_WIDTH = {
|
|
48732
|
+
repo: COL.repo + 1,
|
|
48733
|
+
// 18 + separator
|
|
48734
|
+
status: COL.status + 2,
|
|
48735
|
+
// 12 + separator + marginLeft
|
|
48736
|
+
diff: COL.diff + 2,
|
|
48737
|
+
elapsed: COL.elapsed + 2,
|
|
48738
|
+
author: COL.reviewee + 2,
|
|
48739
|
+
reviewer: COL.reviewer + 2
|
|
48740
|
+
};
|
|
48741
|
+
var DROP_ORDER = [
|
|
48742
|
+
"reviewer",
|
|
48743
|
+
"author",
|
|
48744
|
+
"repo",
|
|
48745
|
+
"diff",
|
|
48746
|
+
"elapsed",
|
|
48747
|
+
"status"
|
|
48748
|
+
];
|
|
48749
|
+
var MIN_TITLE_WIDTH = 20;
|
|
48750
|
+
function computeColumnLayout(columns) {
|
|
48751
|
+
const visible = new Set(
|
|
48752
|
+
Object.keys(OPTIONAL_WIDTH)
|
|
48753
|
+
);
|
|
48754
|
+
const fixed = () => {
|
|
48755
|
+
let width = BASE_WIDTH;
|
|
48756
|
+
for (const col of visible) width += OPTIONAL_WIDTH[col];
|
|
48757
|
+
return width;
|
|
48758
|
+
};
|
|
48759
|
+
for (const col of DROP_ORDER) {
|
|
48760
|
+
if (columns - fixed() >= MIN_TITLE_WIDTH) break;
|
|
48761
|
+
visible.delete(col);
|
|
48762
|
+
}
|
|
48763
|
+
return {
|
|
48764
|
+
showRepo: visible.has("repo"),
|
|
48765
|
+
showStatus: visible.has("status"),
|
|
48766
|
+
showDiff: visible.has("diff"),
|
|
48767
|
+
showElapsed: visible.has("elapsed"),
|
|
48768
|
+
showAuthor: visible.has("author"),
|
|
48769
|
+
showReviewer: visible.has("reviewer"),
|
|
48770
|
+
titleWidth: Math.max(10, columns - fixed())
|
|
48771
|
+
};
|
|
48772
|
+
}
|
|
48731
48773
|
|
|
48732
48774
|
// src/utils/format-time.ts
|
|
48733
48775
|
function formatElapsedTime(createdAt) {
|
|
@@ -48790,7 +48832,15 @@ var import_jsx_runtime3 = __toESM(require_jsx_runtime(), 1);
|
|
|
48790
48832
|
function PrRow({ pr, isSelected }) {
|
|
48791
48833
|
const { stdout } = use_stdout_default();
|
|
48792
48834
|
const columns = stdout?.columns ?? 120;
|
|
48793
|
-
const
|
|
48835
|
+
const {
|
|
48836
|
+
showRepo,
|
|
48837
|
+
showStatus,
|
|
48838
|
+
showDiff,
|
|
48839
|
+
showElapsed,
|
|
48840
|
+
showAuthor,
|
|
48841
|
+
showReviewer,
|
|
48842
|
+
titleWidth
|
|
48843
|
+
} = computeColumnLayout(columns);
|
|
48794
48844
|
const timeColor = getTimeColor(pr.createdAt);
|
|
48795
48845
|
const elapsed = formatElapsedTime(pr.createdAt);
|
|
48796
48846
|
const icon = getTimeIcon(pr.createdAt);
|
|
@@ -48805,36 +48855,48 @@ function PrRow({ pr, isSelected }) {
|
|
|
48805
48855
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Box_default, { backgroundColor: isSelected ? "#333333" : void 0, children: [
|
|
48806
48856
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { color: isSelected ? "red" : void 0, children: isSelected ? ">" : " " }),
|
|
48807
48857
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Box_default, { width: COL.icon, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { color: timeColor, wrap: "truncate", children: ` ${icon} ` }) }),
|
|
48808
|
-
|
|
48809
|
-
|
|
48810
|
-
|
|
48811
|
-
|
|
48812
|
-
|
|
48813
|
-
|
|
48858
|
+
showRepo && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
48859
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Box_default, { width: COL.repo, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Text, { dimColor: !isSelected, color: selColor, wrap: "truncate", children: [
|
|
48860
|
+
repoShort,
|
|
48861
|
+
"#",
|
|
48862
|
+
pr.number
|
|
48863
|
+
] }) }),
|
|
48864
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { dimColor: true, children: "|" })
|
|
48865
|
+
] }),
|
|
48814
48866
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Box_default, { width: titleWidth, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { bold: isSelected, color: selColor, wrap: "truncate", children: pr.title }) }),
|
|
48815
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.
|
|
48816
|
-
|
|
48817
|
-
|
|
48818
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Box_default, { width: COL.diff, marginLeft: 1, justifyContent: "flex-end", children: [
|
|
48819
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Text, { color: "green", children: [
|
|
48820
|
-
"+",
|
|
48821
|
-
pr.additions
|
|
48822
|
-
] }),
|
|
48823
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { children: " " }),
|
|
48824
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Text, { color: "red", children: [
|
|
48825
|
-
"-",
|
|
48826
|
-
pr.deletions
|
|
48827
|
-
] })
|
|
48867
|
+
showStatus && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
48868
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { dimColor: true, children: "|" }),
|
|
48869
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Box_default, { width: COL.status, marginLeft: 1, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(StatusBadge, { decision: pr.reviewDecision, isDraft: pr.isDraft }) })
|
|
48828
48870
|
] }),
|
|
48829
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.
|
|
48830
|
-
|
|
48831
|
-
|
|
48832
|
-
|
|
48833
|
-
|
|
48834
|
-
|
|
48835
|
-
|
|
48836
|
-
|
|
48837
|
-
|
|
48871
|
+
showDiff && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
48872
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { dimColor: true, children: "|" }),
|
|
48873
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Box_default, { width: COL.diff, marginLeft: 1, justifyContent: "flex-end", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Text, { wrap: "truncate", children: [
|
|
48874
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Text, { color: "green", children: [
|
|
48875
|
+
"+",
|
|
48876
|
+
pr.additions
|
|
48877
|
+
] }),
|
|
48878
|
+
" ",
|
|
48879
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Text, { color: "red", children: [
|
|
48880
|
+
"-",
|
|
48881
|
+
pr.deletions
|
|
48882
|
+
] })
|
|
48883
|
+
] }) })
|
|
48884
|
+
] }),
|
|
48885
|
+
showElapsed && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
48886
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { dimColor: true, children: "|" }),
|
|
48887
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Box_default, { width: COL.elapsed, marginLeft: 1, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { color: timeColor, wrap: "truncate", children: elapsed }) })
|
|
48888
|
+
] }),
|
|
48889
|
+
showAuthor && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
48890
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { dimColor: true, children: "|" }),
|
|
48891
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Box_default, { width: COL.reviewee, marginLeft: 1, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Text, { dimColor: true, wrap: "truncate", children: [
|
|
48892
|
+
"@",
|
|
48893
|
+
pr.author
|
|
48894
|
+
] }) })
|
|
48895
|
+
] }),
|
|
48896
|
+
showReviewer && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
48897
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { dimColor: true, children: "|" }),
|
|
48898
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Box_default, { width: COL.reviewer, marginLeft: 1, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { dimColor: true, wrap: "truncate", children: reviewerText }) })
|
|
48899
|
+
] })
|
|
48838
48900
|
] });
|
|
48839
48901
|
}
|
|
48840
48902
|
|
|
@@ -48865,6 +48927,28 @@ function PrTable({ prs, selectedIndex, maxRows }) {
|
|
|
48865
48927
|
|
|
48866
48928
|
// src/components/status-bar.tsx
|
|
48867
48929
|
var import_jsx_runtime5 = __toESM(require_jsx_runtime(), 1);
|
|
48930
|
+
var HINTS = [
|
|
48931
|
+
{ key: "Tab", label: "switch", keep: 6 },
|
|
48932
|
+
{ key: "j/k", label: "move", keep: 3 },
|
|
48933
|
+
{ key: "Enter", label: "open", keep: 2 },
|
|
48934
|
+
{ key: "y", label: "copy", keep: 4 },
|
|
48935
|
+
{ key: "/", label: "filter", keep: 5 },
|
|
48936
|
+
{ key: "r", label: "refresh", keep: 7 },
|
|
48937
|
+
{ key: "q", label: "quit", keep: 1 }
|
|
48938
|
+
];
|
|
48939
|
+
var hintWidth = (h) => h.key.length + 1 + h.label.length;
|
|
48940
|
+
function visibleHints(budget) {
|
|
48941
|
+
const byPriority = [...HINTS].sort((a, b) => a.keep - b.keep);
|
|
48942
|
+
const shown = /* @__PURE__ */ new Set();
|
|
48943
|
+
let used = 0;
|
|
48944
|
+
for (const h of byPriority) {
|
|
48945
|
+
const width = hintWidth(h) + (shown.size > 0 ? 1 : 0);
|
|
48946
|
+
if (used + width > budget) break;
|
|
48947
|
+
used += width;
|
|
48948
|
+
shown.add(h.key);
|
|
48949
|
+
}
|
|
48950
|
+
return HINTS.filter((h) => shown.has(h.key));
|
|
48951
|
+
}
|
|
48868
48952
|
function StatusBar({
|
|
48869
48953
|
isFilterActive,
|
|
48870
48954
|
filter,
|
|
@@ -48873,10 +48957,15 @@ function StatusBar({
|
|
|
48873
48957
|
reviewCount,
|
|
48874
48958
|
myCount,
|
|
48875
48959
|
isFilterMode,
|
|
48876
|
-
loading
|
|
48960
|
+
loading,
|
|
48961
|
+
copiedMessage
|
|
48877
48962
|
}) {
|
|
48963
|
+
const { stdout } = use_stdout_default();
|
|
48964
|
+
const columns = stdout?.columns ?? 80;
|
|
48878
48965
|
const isReview = activeTab === "review-requested";
|
|
48879
48966
|
const tabLabel = isReview ? `To Review (${reviewCount})` : `My PRs (${myCount})`;
|
|
48967
|
+
const reserved = 2 + tabLabel.length + (loading ? 13 : 0) + 2;
|
|
48968
|
+
const hints = visibleHints(columns - reserved);
|
|
48880
48969
|
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
48881
48970
|
Box_default,
|
|
48882
48971
|
{
|
|
@@ -48889,7 +48978,10 @@ function StatusBar({
|
|
|
48889
48978
|
paddingX: 1,
|
|
48890
48979
|
justifyContent: "space-between",
|
|
48891
48980
|
children: [
|
|
48892
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Box_default, { children:
|
|
48981
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Box_default, { children: copiedMessage ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { color: "green", children: [
|
|
48982
|
+
"\u2713 ",
|
|
48983
|
+
copiedMessage
|
|
48984
|
+
] }) : isFilterActive || filter ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
48893
48985
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "yellow", children: "/" }),
|
|
48894
48986
|
isFilterActive ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
48895
48987
|
TextInput,
|
|
@@ -48910,38 +49002,11 @@ function StatusBar({
|
|
|
48910
49002
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "gray", children: "Esc" }),
|
|
48911
49003
|
" ",
|
|
48912
49004
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { dimColor: true, children: "cancel" })
|
|
48913
|
-
] }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
48914
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.
|
|
48915
|
-
|
|
48916
|
-
|
|
48917
|
-
|
|
48918
|
-
] }),
|
|
48919
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { children: [
|
|
48920
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "white", children: "j/k" }),
|
|
48921
|
-
" ",
|
|
48922
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { dimColor: true, children: "move" })
|
|
48923
|
-
] }),
|
|
48924
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { children: [
|
|
48925
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "white", children: "Enter" }),
|
|
48926
|
-
" ",
|
|
48927
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { dimColor: true, children: "open" })
|
|
48928
|
-
] }),
|
|
48929
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { children: [
|
|
48930
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "white", children: "/" }),
|
|
48931
|
-
" ",
|
|
48932
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { dimColor: true, children: "filter" })
|
|
48933
|
-
] }),
|
|
48934
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { children: [
|
|
48935
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "white", children: "r" }),
|
|
48936
|
-
" ",
|
|
48937
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { dimColor: true, children: "refresh" })
|
|
48938
|
-
] }),
|
|
48939
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { children: [
|
|
48940
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "white", children: "q" }),
|
|
48941
|
-
" ",
|
|
48942
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { dimColor: true, children: "quit" })
|
|
48943
|
-
] })
|
|
48944
|
-
] }) })
|
|
49005
|
+
] }) : hints.map((h) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { children: [
|
|
49006
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { color: "white", children: h.key }),
|
|
49007
|
+
" ",
|
|
49008
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Text, { dimColor: true, children: h.label })
|
|
49009
|
+
] }, h.key)) })
|
|
48945
49010
|
]
|
|
48946
49011
|
}
|
|
48947
49012
|
);
|
|
@@ -49130,10 +49195,18 @@ function usePullRequests() {
|
|
|
49130
49195
|
return { reviewRequested, myPRs, loading, error, refresh: load };
|
|
49131
49196
|
}
|
|
49132
49197
|
|
|
49133
|
-
// src/utils/
|
|
49198
|
+
// src/utils/copy-to-clipboard.ts
|
|
49134
49199
|
import { execFile as execFile2 } from "node:child_process";
|
|
49200
|
+
function copyToClipboard(text) {
|
|
49201
|
+
const child = execFile2("pbcopy", () => {
|
|
49202
|
+
});
|
|
49203
|
+
child.stdin?.end(text);
|
|
49204
|
+
}
|
|
49205
|
+
|
|
49206
|
+
// src/utils/open-url.ts
|
|
49207
|
+
import { execFile as execFile3 } from "node:child_process";
|
|
49135
49208
|
function openUrl(url2) {
|
|
49136
|
-
|
|
49209
|
+
execFile3("open", [url2], () => {
|
|
49137
49210
|
});
|
|
49138
49211
|
}
|
|
49139
49212
|
|
|
@@ -49148,8 +49221,29 @@ function App2() {
|
|
|
49148
49221
|
const [selectedIndex, setSelectedIndex] = (0, import_react62.useState)(0);
|
|
49149
49222
|
const [filter, setFilter] = (0, import_react62.useState)("");
|
|
49150
49223
|
const [isFilterMode, setIsFilterMode] = (0, import_react62.useState)(false);
|
|
49224
|
+
const [copiedMessage, setCopiedMessage] = (0, import_react62.useState)("");
|
|
49225
|
+
const copiedTimer = (0, import_react62.useRef)(null);
|
|
49226
|
+
const notifyCopied = (0, import_react62.useCallback)(() => {
|
|
49227
|
+
setCopiedMessage("Copied URL to clipboard");
|
|
49228
|
+
if (copiedTimer.current) {
|
|
49229
|
+
clearTimeout(copiedTimer.current);
|
|
49230
|
+
}
|
|
49231
|
+
copiedTimer.current = setTimeout(() => setCopiedMessage(""), 2e3);
|
|
49232
|
+
}, []);
|
|
49151
49233
|
const currentPRs = activeTab === "review-requested" ? reviewRequested : myPRs;
|
|
49152
49234
|
const filteredPRs = useFilterSort(currentPRs, filter);
|
|
49235
|
+
const [, setResizeTick] = (0, import_react62.useState)(0);
|
|
49236
|
+
(0, import_react62.useEffect)(() => {
|
|
49237
|
+
if (!stdout) return;
|
|
49238
|
+
const onResize = () => {
|
|
49239
|
+
stdout.write("\x1B[2J\x1B[H");
|
|
49240
|
+
setResizeTick((n) => n + 1);
|
|
49241
|
+
};
|
|
49242
|
+
stdout.on("resize", onResize);
|
|
49243
|
+
return () => {
|
|
49244
|
+
stdout.off("resize", onResize);
|
|
49245
|
+
};
|
|
49246
|
+
}, [stdout]);
|
|
49153
49247
|
const clampIndex = (0, import_react62.useCallback)(
|
|
49154
49248
|
(index) => Math.max(0, Math.min(index, filteredPRs.length - 1)),
|
|
49155
49249
|
[filteredPRs.length]
|
|
@@ -49191,6 +49285,14 @@ function App2() {
|
|
|
49191
49285
|
}
|
|
49192
49286
|
return;
|
|
49193
49287
|
}
|
|
49288
|
+
if (input === "y") {
|
|
49289
|
+
const pr = filteredPRs[selectedIndex];
|
|
49290
|
+
if (pr) {
|
|
49291
|
+
copyToClipboard(pr.url);
|
|
49292
|
+
notifyCopied();
|
|
49293
|
+
}
|
|
49294
|
+
return;
|
|
49295
|
+
}
|
|
49194
49296
|
if (input === "/") {
|
|
49195
49297
|
setIsFilterMode(true);
|
|
49196
49298
|
return;
|
|
@@ -49241,7 +49343,8 @@ function App2() {
|
|
|
49241
49343
|
reviewCount: reviewRequested.length,
|
|
49242
49344
|
myCount: myPRs.length,
|
|
49243
49345
|
isFilterMode,
|
|
49244
|
-
loading
|
|
49346
|
+
loading,
|
|
49347
|
+
copiedMessage
|
|
49245
49348
|
}
|
|
49246
49349
|
)
|
|
49247
49350
|
] });
|